Eclipse SUMO - Simulation of Urban MObility
ODMatrix.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2006-2020 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
21 // An O/D (origin/destination) matrix
22 /****************************************************************************/
23 #include <config.h>
24 
25 #include <iostream>
26 #include <algorithm>
27 #include <list>
28 #include <iterator>
31 #include <utils/common/StdDefs.h>
33 #include <utils/common/ToString.h>
38 #include <utils/common/SUMOTime.h>
42 #include <utils/xml/XMLSubSys.h>
43 #include <router/RORoute.h>
44 #include "ODAmitranHandler.h"
45 #include "ODMatrix.h"
46 
47 
48 // ===========================================================================
49 // method definitions
50 // ===========================================================================
52  : myDistricts(dc), myNumLoaded(0), myNumWritten(0), myNumDiscarded(0), myBegin(-1), myEnd(-1) {}
53 
54 
56  for (ODCell* const cell : myContainer) {
57  for (RORoute* const r : cell->pathsVector) {
58  delete r;
59  }
60  delete cell;
61  }
62  myContainer.clear();
63 }
64 
65 
66 bool
67 ODMatrix::add(double vehicleNumber, SUMOTime begin,
68  SUMOTime end, const std::string& origin, const std::string& destination,
69  const std::string& vehicleType, const bool originIsEdge, const bool destinationIsEdge) {
70  myNumLoaded += vehicleNumber;
71  if (!originIsEdge && !destinationIsEdge && myDistricts.get(origin) == nullptr && myDistricts.get(destination) == nullptr) {
72  WRITE_WARNING("Missing origin '" + origin + "' and destination '" + destination + "' (" + toString(vehicleNumber) + " vehicles).");
73  myNumDiscarded += vehicleNumber;
74  myMissingDistricts.insert(origin);
75  myMissingDistricts.insert(destination);
76  return false;
77  } else if (!originIsEdge && myDistricts.get(origin) == 0 && vehicleNumber > 0) {
78  WRITE_ERROR("Missing origin '" + origin + "' (" + toString(vehicleNumber) + " vehicles).");
79  myNumDiscarded += vehicleNumber;
80  myMissingDistricts.insert(origin);
81  return false;
82  } else if (!destinationIsEdge && myDistricts.get(destination) == 0 && vehicleNumber > 0) {
83  WRITE_ERROR("Missing destination '" + destination + "' (" + toString(vehicleNumber) + " vehicles).");
84  myNumDiscarded += vehicleNumber;
85  myMissingDistricts.insert(destination);
86  return false;
87  }
88  if (!originIsEdge && myDistricts.get(origin)->sourceNumber() == 0) {
89  WRITE_ERROR("District '" + origin + "' has no source.");
90  myNumDiscarded += vehicleNumber;
91  return false;
92  } else if (!destinationIsEdge && myDistricts.get(destination)->sinkNumber() == 0) {
93  WRITE_ERROR("District '" + destination + "' has no sink.");
94  myNumDiscarded += vehicleNumber;
95  return false;
96  }
97  ODCell* cell = new ODCell();
98  cell->begin = begin;
99  cell->end = end;
100  cell->origin = origin;
101  cell->destination = destination;
102  cell->vehicleType = vehicleType;
103  cell->vehicleNumber = vehicleNumber;
104  cell->originIsEdge = originIsEdge;
105  cell->destinationIsEdge = destinationIsEdge;
106  myContainer.push_back(cell);
107  return true;
108 }
109 
110 
111 bool
112 ODMatrix::add(const std::string& id, const SUMOTime depart,
113  const std::string& fromTaz, const std::string& toTaz,
114  const std::string& vehicleType, const bool originIsEdge, const bool destinationIsEdge) {
115  if (myMissingDistricts.count(fromTaz) > 0 || myMissingDistricts.count(toTaz) > 0) {
116  myNumLoaded += 1.;
117  myNumDiscarded += 1.;
118  return false;
119  }
120  // we start looking from the end because there is a high probability that the input is sorted by time
121  std::vector<ODCell*>& odList = myShortCut[std::make_pair(fromTaz, toTaz)];
122  ODCell* cell = nullptr;
123  for (std::vector<ODCell*>::const_reverse_iterator c = odList.rbegin(); c != odList.rend(); ++c) {
124  if ((*c)->begin <= depart && (*c)->end > depart && (*c)->vehicleType == vehicleType) {
125  cell = *c;
126  break;
127  }
128  }
129  if (cell == nullptr) {
130  const SUMOTime interval = string2time(OptionsCont::getOptions().getString("aggregation-interval"));
131  const int intervalIdx = (int)(depart / interval);
132  if (add(1., intervalIdx * interval, (intervalIdx + 1) * interval, fromTaz, toTaz, vehicleType, originIsEdge, destinationIsEdge)) {
133  cell = myContainer.back();
134  odList.push_back(cell);
135  } else {
136  return false;
137  }
138  } else {
139  myNumLoaded += 1.;
140  cell->vehicleNumber += 1.;
141  }
142  cell->departures[depart].push_back(id);
143  return true;
144 }
145 
146 
147 double
149  int& vehName, std::vector<ODVehicle>& into,
150  const bool uniform, const bool differSourceSink,
151  const std::string& prefix) {
152  int vehicles2insert = (int) cell->vehicleNumber;
153  // compute whether the fraction forces an additional vehicle insertion
154  if (RandHelper::rand() < cell->vehicleNumber - (double)vehicles2insert) {
155  vehicles2insert++;
156  }
157  if (vehicles2insert == 0) {
158  return cell->vehicleNumber;
159  }
160 
161  const double offset = (double)(cell->end - cell->begin) / (double) vehicles2insert / (double) 2.;
162  for (int i = 0; i < vehicles2insert; ++i) {
163  ODVehicle veh;
164  veh.id = prefix + toString(vehName++);
165 
166  if (uniform) {
167  veh.depart = (SUMOTime)(offset + cell->begin + ((double)(cell->end - cell->begin) * (double) i / (double) vehicles2insert));
168  } else {
169  veh.depart = (SUMOTime)RandHelper::rand(cell->begin, cell->end);
170  }
171  const bool canDiffer = myDistricts.get(cell->origin)->sourceNumber() > 1 || myDistricts.get(cell->destination)->sinkNumber() > 1;
172  do {
175  } while (canDiffer && differSourceSink && (veh.to == veh.from));
176  if (!canDiffer && differSourceSink && (veh.to == veh.from)) {
177  WRITE_WARNING("Cannot find different source and sink edge for origin '" + cell->origin + "' and destination '" + cell->destination + "'.");
178  }
179  veh.cell = cell;
180  into.push_back(veh);
181  }
182  return cell->vehicleNumber - vehicles2insert;
183 }
184 
185 
186 void
187 ODMatrix::writeDefaultAttrs(OutputDevice& dev, const bool noVtype,
188  const ODCell* const cell) {
189  const OptionsCont& oc = OptionsCont::getOptions();
190  if (!noVtype && cell->vehicleType != "") {
192  }
194  if (oc.isSet("departlane") && oc.getString("departlane") != "default") {
195  dev.writeAttr(SUMO_ATTR_DEPARTLANE, oc.getString("departlane"));
196  }
197  if (oc.isSet("departpos")) {
198  dev.writeAttr(SUMO_ATTR_DEPARTPOS, oc.getString("departpos"));
199  }
200  if (oc.isSet("departspeed") && oc.getString("departspeed") != "default") {
201  dev.writeAttr(SUMO_ATTR_DEPARTSPEED, oc.getString("departspeed"));
202  }
203  if (oc.isSet("arrivallane")) {
204  dev.writeAttr(SUMO_ATTR_ARRIVALLANE, oc.getString("arrivallane"));
205  }
206  if (oc.isSet("arrivalpos")) {
207  dev.writeAttr(SUMO_ATTR_ARRIVALPOS, oc.getString("arrivalpos"));
208  }
209  if (oc.isSet("arrivalspeed")) {
210  dev.writeAttr(SUMO_ATTR_ARRIVALSPEED, oc.getString("arrivalspeed"));
211  }
212 }
213 
214 
215 void
217  OutputDevice& dev, const bool uniform,
218  const bool differSourceSink, const bool noVtype,
219  const std::string& prefix, const bool stepLog,
220  bool pedestrians, bool persontrips,
221  const std::string& modes) {
222  if (myContainer.size() == 0) {
223  return;
224  }
225  std::map<std::pair<std::string, std::string>, double> fractionLeft;
226  int vehName = 0;
227  sortByBeginTime();
228  // recheck begin time
229  begin = MAX2(begin, myContainer.front()->begin);
230  std::vector<ODCell*>::iterator next = myContainer.begin();
231  std::vector<ODVehicle> vehicles;
232  SUMOTime lastOut = -DELTA_T;
233  // go through the time steps
234  for (SUMOTime t = begin; t < end;) {
235  if (stepLog && t - lastOut >= DELTA_T) {
236  std::cout << "Parsing time " + time2string(t) << '\r';
237  lastOut = t;
238  }
239  // recheck whether a new cell got valid
240  bool changed = false;
241  while (next != myContainer.end() && (*next)->begin <= t && (*next)->end > t) {
242  std::pair<std::string, std::string> odID = std::make_pair((*next)->origin, (*next)->destination);
243  // check whether the current cell must be extended by the last fraction
244  if (fractionLeft.find(odID) != fractionLeft.end()) {
245  (*next)->vehicleNumber += fractionLeft[odID];
246  fractionLeft[odID] = 0;
247  }
248  // get the new departures (into tmp)
249  const int oldSize = (int)vehicles.size();
250  const double fraction = computeDeparts(*next, vehName, vehicles, uniform, differSourceSink, prefix);
251  if (oldSize != (int)vehicles.size()) {
252  changed = true;
253  }
254  if (fraction != 0) {
255  fractionLeft[odID] = fraction;
256  }
257  ++next;
258  }
259  if (changed) {
260  sort(vehicles.begin(), vehicles.end(), descending_departure_comperator());
261  }
262 
263  const OptionsCont& oc = OptionsCont::getOptions();
264  std::string personDepartPos = oc.isSet("departpos") ? oc.getString("departpos") : "random";
265  std::string personArrivalPos = oc.isSet("arrivalpos") ? oc.getString("arrivalpos") : "random";
266  for (std::vector<ODVehicle>::reverse_iterator i = vehicles.rbegin(); i != vehicles.rend() && (*i).depart == t; ++i) {
267  if (t >= begin) {
268  myNumWritten++;
269  if (pedestrians) {
271  dev.writeAttr(SUMO_ATTR_DEPARTPOS, personDepartPos);
272  dev.openTag(SUMO_TAG_WALK);
273  dev.writeAttr(SUMO_ATTR_FROM, (*i).from).writeAttr(SUMO_ATTR_TO, (*i).to);
274  dev.writeAttr(SUMO_ATTR_FROM_TAZ, (*i).cell->origin).writeAttr(SUMO_ATTR_TO_TAZ, (*i).cell->destination);
275  dev.writeAttr(SUMO_ATTR_ARRIVALPOS, personArrivalPos);
276  dev.closeTag();
277  dev.closeTag();
278  } else if (persontrips) {
280  dev.writeAttr(SUMO_ATTR_DEPARTPOS, personDepartPos);
282  dev.writeAttr(SUMO_ATTR_FROM, (*i).from).writeAttr(SUMO_ATTR_TO, (*i).to);
283  dev.writeAttr(SUMO_ATTR_FROM_TAZ, (*i).cell->origin).writeAttr(SUMO_ATTR_TO_TAZ, (*i).cell->destination);
284  dev.writeAttr(SUMO_ATTR_ARRIVALPOS, personArrivalPos);
285  if (modes != "") {
286  dev.writeAttr(SUMO_ATTR_MODES, modes);
287  }
288  dev.closeTag();
289  dev.closeTag();
290  } else {
292  dev.writeAttr(SUMO_ATTR_FROM, (*i).from).writeAttr(SUMO_ATTR_TO, (*i).to);
293  writeDefaultAttrs(dev, noVtype, i->cell);
294  dev.closeTag();
295  }
296  }
297  }
298  while (vehicles.size() != 0 && vehicles.back().depart == t) {
299  vehicles.pop_back();
300  }
301  if (!vehicles.empty()) {
302  t = vehicles.back().depart;
303  }
304  if (next != myContainer.end() && (t > (*next)->begin || vehicles.empty())) {
305  t = (*next)->begin;
306  }
307  if (next == myContainer.end() && vehicles.empty()) {
308  break;
309  }
310  }
311 }
312 
313 
314 void
315 ODMatrix::writeFlows(const SUMOTime begin, const SUMOTime end,
316  OutputDevice& dev, bool noVtype,
317  const std::string& prefix,
318  bool asProbability, bool pedestrians, bool persontrips,
319  const std::string& modes) {
320  if (myContainer.size() == 0) {
321  return;
322  }
323  int flowName = 0;
324  sortByBeginTime();
325  // recheck begin time
326  for (std::vector<ODCell*>::const_iterator i = myContainer.begin(); i != myContainer.end(); ++i) {
327  const ODCell* const c = *i;
328  if (c->end > begin && c->begin < end) {
329  const double probability = asProbability ? float(c->vehicleNumber) / STEPS2TIME(c->end - c->begin) : 1;
330  if (probability <= 0) {
331  continue;
332  }
333  //Person flows
334  if (pedestrians) {
335  dev.openTag(SUMO_TAG_PERSONFLOW).writeAttr(SUMO_ATTR_ID, prefix + toString(flowName++));
337  if (!asProbability) {
339  } else {
340  if (probability > 1) {
341  WRITE_WARNING("Flow density of " + toString(probability) + " vehicles per second, cannot be represented with a simple probability. Falling back to even spacing.");
343  } else {
344  dev.setPrecision(6);
345  dev.writeAttr(SUMO_ATTR_PROB, probability);
346  dev.setPrecision();
347  }
348  }
349  dev.openTag(SUMO_TAG_WALK);
351  dev.writeAttr(SUMO_ATTR_ARRIVALPOS, "random");
352  dev.closeTag();
353  dev.closeTag();
354  } else if (persontrips) {
355  dev.openTag(SUMO_TAG_PERSONFLOW).writeAttr(SUMO_ATTR_ID, prefix + toString(flowName++));
357  if (!asProbability) {
359  } else {
360  if (probability > 1) {
361  WRITE_WARNING("Flow density of " + toString(probability) + " vehicles per second, cannot be represented with a simple probability. Falling back to even spacing.");
363  } else {
364  dev.setPrecision(6);
365  dev.writeAttr(SUMO_ATTR_PROB, probability);
366  dev.setPrecision();
367  }
368  }
371  dev.writeAttr(SUMO_ATTR_ARRIVALPOS, "random");
372  if (modes != "") {
373  dev.writeAttr(SUMO_ATTR_MODES, modes);
374  }
375  dev.closeTag();
376  dev.closeTag();
377  } else {
378  // Normal flow output
379  dev.openTag(SUMO_TAG_FLOW).writeAttr(SUMO_ATTR_ID, prefix + toString(flowName++));
382 
383  if (!asProbability) {
385  } else {
386  if (probability > 1) {
387  WRITE_WARNING("Flow density of " + toString(probability) + " vehicles per second, cannot be represented with a simple probability. Falling back to even spacing.");
389  } else {
390  dev.setPrecision(6);
391  dev.writeAttr(SUMO_ATTR_PROB, probability);
392  dev.setPrecision();
393  }
394  }
395  writeDefaultAttrs(dev, noVtype, *i);
396  dev.closeTag();
397  }
398  }
399  }
400 }
401 
402 
403 std::string
405  while (lr.good() && lr.hasMore()) {
406  const std::string line = lr.readLine();
407  if (line[0] != '*') {
408  return StringUtils::prune(line);
409  }
410  }
411  throw ProcessError("End of file while reading " + lr.getFileName() + ".");
412 }
413 
414 
415 SUMOTime
416 ODMatrix::parseSingleTime(const std::string& time) {
417  if (time.find('.') == std::string::npos) {
418  throw OutOfBoundsException();
419  }
420  std::string hours = time.substr(0, time.find('.'));
421  std::string minutes = time.substr(time.find('.') + 1);
422  return TIME2STEPS(StringUtils::toInt(hours) * 3600 + StringUtils::toInt(minutes) * 60);
423 }
424 
425 
426 std::pair<SUMOTime, SUMOTime>
428  std::string line = getNextNonCommentLine(lr);
429  try {
431  myBegin = parseSingleTime(st.next());
432  myEnd = parseSingleTime(st.next());
433  if (myBegin >= myEnd) {
434  throw ProcessError("Matrix begin time " + time2string(myBegin) + " is larger than end time " + time2string(myEnd) + ".");
435  }
436  return std::make_pair(myBegin, myEnd);
437  } catch (OutOfBoundsException&) {
438  throw ProcessError("Broken period definition '" + line + "'.");
439  } catch (NumberFormatException&) {
440  throw ProcessError("Broken period definition '" + line + "'.");
441  }
442 }
443 
444 
445 double
446 ODMatrix::readFactor(LineReader& lr, double scale) {
447  std::string line = getNextNonCommentLine(lr);
448  double factor = -1;
449  try {
450  factor = StringUtils::toDouble(line) * scale;
451  } catch (NumberFormatException&) {
452  throw ProcessError("Broken factor: '" + line + "'.");
453  }
454  return factor;
455 }
456 
457 void
458 ODMatrix::readV(LineReader& lr, double scale,
459  std::string vehType, bool matrixHasVehType) {
460  PROGRESS_BEGIN_MESSAGE("Reading matrix '" + lr.getFileName() + "' stored as VMR");
461  // parse first defs
462  std::string line;
463  if (matrixHasVehType) {
464  line = getNextNonCommentLine(lr);
465  if (vehType == "") {
466  vehType = StringUtils::prune(line);
467  }
468  }
469 
470  // parse time
471  std::pair<SUMOTime, SUMOTime> times = readTime(lr);
472  SUMOTime begin = times.first;
473  SUMOTime end = times.second;
474 
475  // factor
476  double factor = readFactor(lr, scale);
477 
478  // districts
479  line = getNextNonCommentLine(lr);
480  const int numDistricts = StringUtils::toInt(StringUtils::prune(line));
481  // parse district names (normally ints)
482  std::vector<std::string> names;
483  while ((int)names.size() != numDistricts && lr.hasMore()) {
484  line = getNextNonCommentLine(lr);
486  while (st2.hasNext()) {
487  names.push_back(st2.next());
488  }
489  }
490  if (!lr.hasMore()) {
491  throw ProcessError("Missing line with " + toString(numDistricts) + " district names.");
492  }
493 
494  // parse the cells
495  for (std::vector<std::string>::iterator si = names.begin(); si != names.end(); ++si) {
496  std::vector<std::string>::iterator di = names.begin();
497  do {
498  try {
499  line = getNextNonCommentLine(lr);
500  } catch (ProcessError&) {
501  throw ProcessError("Missing line for district " + (*si) + ".");
502  }
503  if (line.length() == 0) {
504  continue;
505  }
506  try {
508  while (st2.hasNext()) {
509  assert(di != names.end());
510  double vehNumber = StringUtils::toDouble(st2.next()) * factor;
511  if (vehNumber != 0) {
512  add(vehNumber, begin, end, *si, *di, vehType);
513  }
514  if (di == names.end()) {
515  throw ProcessError("More entries than districts found.");
516  }
517  ++di;
518  }
519  } catch (NumberFormatException&) {
520  throw ProcessError("Not numeric vehicle number in line '" + line + "'.");
521  }
522  if (!lr.hasMore()) {
523  break;
524  }
525  } while (di != names.end());
526  }
528 }
529 
530 
531 void
532 ODMatrix::readO(LineReader& lr, double scale,
533  std::string vehType, bool matrixHasVehType) {
534  PROGRESS_BEGIN_MESSAGE("Reading matrix '" + lr.getFileName() + "' stored as OR");
535  // parse first defs
536  std::string line;
537  if (matrixHasVehType) {
538  line = getNextNonCommentLine(lr);
539  int type = StringUtils::toInt(StringUtils::prune(line));
540  if (vehType == "") {
541  vehType = toString(type);
542  }
543  }
544 
545  // parse time
546  std::pair<SUMOTime, SUMOTime> times = readTime(lr);
547  SUMOTime begin = times.first;
548  SUMOTime end = times.second;
549 
550  // factor
551  double factor = readFactor(lr, scale);
552 
553  // parse the cells
554  while (lr.hasMore()) {
555  line = getNextNonCommentLine(lr);
556  if (line.length() == 0) {
557  continue;
558  }
560  if (st2.size() == 0) {
561  continue;
562  }
563  try {
564  std::string sourceD = st2.next();
565  std::string destD = st2.next();
566  double vehNumber = StringUtils::toDouble(st2.next()) * factor;
567  if (vehNumber != 0) {
568  add(vehNumber, begin, end, sourceD, destD, vehType);
569  }
570  } catch (OutOfBoundsException&) {
571  throw ProcessError("Missing at least one information in line '" + line + "'.");
572  } catch (NumberFormatException&) {
573  throw ProcessError("Not numeric vehicle number in line '" + line + "'.");
574  }
575  }
577 }
578 
579 
580 
581 double
583  return myNumLoaded;
584 }
585 
586 
587 double
589  return myNumWritten;
590 }
591 
592 
593 double
595  return myNumDiscarded;
596 }
597 
598 
599 void
600 ODMatrix::applyCurve(const Distribution_Points& ps, ODCell* cell, std::vector<ODCell*>& newCells) {
601  const std::vector<double>& times = ps.getVals();
602  for (int i = 0; i < (int)times.size() - 1; ++i) {
603  ODCell* ncell = new ODCell();
604  ncell->begin = TIME2STEPS(times[i]);
605  ncell->end = TIME2STEPS(times[i + 1]);
606  ncell->origin = cell->origin;
607  ncell->destination = cell->destination;
608  ncell->vehicleType = cell->vehicleType;
609  ncell->vehicleNumber = cell->vehicleNumber * ps.getProbs()[i] / ps.getOverallProb();
610  newCells.push_back(ncell);
611  }
612 }
613 
614 
615 void
617  std::vector<ODCell*> oldCells = myContainer;
618  myContainer.clear();
619  for (std::vector<ODCell*>::iterator i = oldCells.begin(); i != oldCells.end(); ++i) {
620  std::vector<ODCell*> newCells;
621  applyCurve(ps, *i, newCells);
622  copy(newCells.begin(), newCells.end(), back_inserter(myContainer));
623  delete *i;
624  }
625 }
626 
627 
628 void
630  std::vector<std::string> files = oc.getStringVector("od-matrix-files");
631  for (std::vector<std::string>::iterator i = files.begin(); i != files.end(); ++i) {
632  LineReader lr(*i);
633  if (!lr.good()) {
634  throw ProcessError("Could not open '" + (*i) + "'.");
635  }
636  std::string type = lr.readLine();
637  // get the type only
638  if (type.find(';') != std::string::npos) {
639  type = type.substr(0, type.find(';'));
640  }
641  // parse type-dependant
642  if (type.length() > 1 && type[1] == 'V') {
643  // process ptv's 'V'-matrices
644  if (type.find('N') != std::string::npos) {
645  throw ProcessError("'" + *i + "' does not contain the needed information about the time described.");
646  }
647  readV(lr, oc.getFloat("scale"), oc.getString("vtype"), type.find('M') != std::string::npos);
648  } else if (type.length() > 1 && type[1] == 'O') {
649  // process ptv's 'O'-matrices
650  if (type.find('N') != std::string::npos) {
651  throw ProcessError("'" + *i + "' does not contain the needed information about the time described.");
652  }
653  readO(lr, oc.getFloat("scale"), oc.getString("vtype"), type.find('M') != std::string::npos);
654  } else {
655  throw ProcessError("'" + *i + "' uses an unknown matrix type '" + type + "'.");
656  }
657  }
658  std::vector<std::string> amitranFiles = oc.getStringVector("od-amitran-files");
659  for (std::vector<std::string>::iterator i = amitranFiles.begin(); i != amitranFiles.end(); ++i) {
660  if (!FileHelpers::isReadable(*i)) {
661  throw ProcessError("Could not access matrix file '" + *i + "' to load.");
662  }
663  PROGRESS_BEGIN_MESSAGE("Loading matrix in Amitran format from '" + *i + "'");
664  ODAmitranHandler handler(*this, *i);
665  if (!XMLSubSys::runParser(handler, *i)) {
667  } else {
669  }
670  }
671 }
672 
673 
674 void
676  std::vector<std::string> routeFiles = oc.getStringVector("route-files");
677  for (std::vector<std::string>::iterator i = routeFiles.begin(); i != routeFiles.end(); ++i) {
678  if (!FileHelpers::isReadable(*i)) {
679  throw ProcessError("Could not access route file '" + *i + "' to load.");
680  }
681  PROGRESS_BEGIN_MESSAGE("Loading routes and trips from '" + *i + "'");
682  if (!XMLSubSys::runParser(handler, *i)) {
684  } else {
686  }
687  }
688 }
689 
690 
692 ODMatrix::parseTimeLine(const std::vector<std::string>& def, bool timelineDayInHours) {
693  Distribution_Points result("N/A");
694  if (timelineDayInHours) {
695  if (def.size() != 24) {
696  throw ProcessError("Assuming 24 entries for a day timeline, but got " + toString(def.size()) + ".");
697  }
698  for (int chour = 0; chour < 24; ++chour) {
699  result.add(chour * 3600., StringUtils::toDouble(def[chour]));
700  }
701  result.add(24 * 3600., 0.); // dummy value to finish the last interval
702  } else {
703  for (int i = 0; i < (int)def.size(); i++) {
704  StringTokenizer st2(def[i], ":");
705  if (st2.size() != 2) {
706  throw ProcessError("Broken time line definition: missing a value in '" + def[i] + "'.");
707  }
708  const double time = StringUtils::toDouble(st2.next());
709  result.add(time, StringUtils::toDouble(st2.next()));
710  }
711  }
712  return result;
713 }
714 
715 
716 void
718  std::sort(myContainer.begin(), myContainer.end(), cell_by_begin_comparator());
719 }
720 
721 
722 /****************************************************************************/
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:284
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:276
#define PROGRESS_DONE_MESSAGE()
Definition: MsgHandler.h:280
#define PROGRESS_FAILED_MESSAGE()
Definition: MsgHandler.h:283
#define PROGRESS_BEGIN_MESSAGE(msg)
Definition: MsgHandler.h:279
SUMOTime DELTA_T
Definition: SUMOTime.cpp:37
std::string time2string(SUMOTime t)
convert SUMOTime to string
Definition: SUMOTime.cpp:68
SUMOTime string2time(const std::string &r)
convert string to SUMOTime
Definition: SUMOTime.cpp:45
#define STEPS2TIME(x)
Definition: SUMOTime.h:53
#define TIME2STEPS(x)
Definition: SUMOTime.h:55
long long int SUMOTime
Definition: SUMOTime.h:31
@ SUMO_TAG_WALK
@ SUMO_TAG_FLOW
a flow definitio nusing a from-to edges instead of a route (used by router)
@ SUMO_TAG_PERSON
@ SUMO_TAG_PERSONTRIP
@ SUMO_TAG_PERSONFLOW
@ SUMO_TAG_TRIP
a single trip definition (used by router)
@ SUMO_ATTR_NUMBER
@ SUMO_ATTR_ARRIVALSPEED
@ SUMO_ATTR_ARRIVALLANE
@ SUMO_ATTR_DEPART
@ SUMO_ATTR_ARRIVALPOS
@ SUMO_ATTR_BEGIN
weights: time range begin
@ SUMO_ATTR_MODES
@ SUMO_ATTR_DEPARTPOS
@ SUMO_ATTR_TO_TAZ
@ SUMO_ATTR_DEPARTSPEED
@ SUMO_ATTR_TO
@ SUMO_ATTR_FROM
@ SUMO_ATTR_END
weights: time range end
@ SUMO_ATTR_FROM_TAZ
@ SUMO_ATTR_DEPARTLANE
@ SUMO_ATTR_PROB
@ SUMO_ATTR_TYPE
@ SUMO_ATTR_ID
T MAX2(T a, T b)
Definition: StdDefs.h:79
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:44
static bool isReadable(std::string path)
Checks whether the given file is readable.
Definition: FileHelpers.cpp:48
Retrieves a file linewise and reports the lines to a handler.
Definition: LineReader.h:48
bool good() const
Returns the information whether the stream is readable.
Definition: LineReader.cpp:229
bool readLine(LineHandler &lh)
Reads a single (the next) line from the file and reports it to the given LineHandler.
Definition: LineReader.cpp:67
bool hasMore() const
Returns whether another line may be read (the file was not read completely)
Definition: LineReader.cpp:51
std::string getFileName() const
Returns the name of the used file.
Definition: LineReader.cpp:173
T get(const std::string &id) const
Retrieves an item.
An XML-Handler for districts.
A container for districts.
std::string getRandomSourceFromDistrict(const std::string &name) const
Returns the id of a random source from the named district.
std::string getRandomSinkFromDistrict(const std::string &name) const
Returns the id of a random sink from the named district.
int sourceNumber() const
Returns the number of sources.
Definition: ODDistrict.cpp:75
int sinkNumber() const
Returns the number of sinks.
Definition: ODDistrict.cpp:69
Used for sorting the cells by the begin time they describe.
Definition: ODMatrix.h:381
Used for sorting vehicles by their departure (latest first)
Definition: ODMatrix.h:417
SUMOTime myEnd
Definition: ODMatrix.h:375
double getNumLoaded() const
Returns the number of loaded vehicles.
Definition: ODMatrix.cpp:582
void readV(LineReader &lr, double scale, std::string vehType, bool matrixHasVehType)
read a VISUM-matrix with the V Format
Definition: ODMatrix.cpp:458
bool add(double vehicleNumber, SUMOTime begin, SUMOTime end, const std::string &origin, const std::string &destination, const std::string &vehicleType, const bool originIsEdge=false, const bool destinationIsEdge=false)
Builds a single cell from the given values, verifying them.
Definition: ODMatrix.cpp:67
void sortByBeginTime()
Definition: ODMatrix.cpp:717
double readFactor(LineReader &lr, double scale)
Definition: ODMatrix.cpp:446
ODMatrix(const ODDistrictCont &dc)
Constructor.
Definition: ODMatrix.cpp:51
double computeDeparts(ODCell *cell, int &vehName, std::vector< ODVehicle > &into, const bool uniform, const bool differSourceSink, const std::string &prefix)
Computes the vehicle departs stored in the given cell and saves them in "into".
Definition: ODMatrix.cpp:148
SUMOTime myBegin
parsed time bounds
Definition: ODMatrix.h:375
~ODMatrix()
Destructor.
Definition: ODMatrix.cpp:55
SUMOTime parseSingleTime(const std::string &time)
Definition: ODMatrix.cpp:416
void writeFlows(const SUMOTime begin, const SUMOTime end, OutputDevice &dev, const bool noVtype, const std::string &prefix, bool asProbability=false, bool pedestrians=false, bool persontrips=false, const std::string &modes="")
Writes the flows stored in the matrix.
Definition: ODMatrix.cpp:315
void applyCurve(const Distribution_Points &ps)
Splits the stored cells dividing them on the given time line.
Definition: ODMatrix.cpp:616
std::map< const std::pair< const std::string, const std::string >, std::vector< ODCell * > > myShortCut
The loaded cells indexed by origin and destination.
Definition: ODMatrix.h:357
std::pair< SUMOTime, SUMOTime > readTime(LineReader &lr)
Definition: ODMatrix.cpp:427
void readO(LineReader &lr, double scale, std::string vehType, bool matrixHasVehType)
read a VISUM-matrix with the O Format
Definition: ODMatrix.cpp:532
std::set< std::string > myMissingDistricts
The missing districts already warned about.
Definition: ODMatrix.h:363
void write(SUMOTime begin, const SUMOTime end, OutputDevice &dev, const bool uniform, const bool differSourceSink, const bool noVtype, const std::string &prefix, const bool stepLog, bool pedestrians, bool persontrips, const std::string &modes)
Writes the vehicles stored in the matrix assigning the sources and sinks.
Definition: ODMatrix.cpp:216
const ODDistrictCont & myDistricts
The districts to retrieve sources/sinks from.
Definition: ODMatrix.h:360
Distribution_Points parseTimeLine(const std::vector< std::string > &def, bool timelineDayInHours)
split the given timeline
Definition: ODMatrix.cpp:692
void writeDefaultAttrs(OutputDevice &dev, const bool noVtype, const ODCell *const cell)
Helper function for flow and trip output writing the depart and arrival attributes.
Definition: ODMatrix.cpp:187
double myNumLoaded
Number of loaded vehicles.
Definition: ODMatrix.h:366
double myNumWritten
Number of written vehicles.
Definition: ODMatrix.h:369
void loadMatrix(OptionsCont &oc)
read a matrix in one of several formats
Definition: ODMatrix.cpp:629
void loadRoutes(OptionsCont &oc, SUMOSAXHandler &handler)
read SUMO routes
Definition: ODMatrix.cpp:675
double getNumWritten() const
Returns the number of written vehicles.
Definition: ODMatrix.cpp:588
std::vector< ODCell * > myContainer
The loaded cells.
Definition: ODMatrix.h:354
double myNumDiscarded
Number of discarded vehicles.
Definition: ODMatrix.h:372
double getNumDiscarded() const
Returns the number of discarded vehicles.
Definition: ODMatrix.cpp:594
std::string getNextNonCommentLine(LineReader &lr)
Definition: ODMatrix.cpp:404
A storage for options typed value containers)
Definition: OptionsCont.h:89
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
const StringVector & getStringVector(const std::string &name) const
Returns the list of string-value of the named option (only for Option_StringVector)
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:60
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:239
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
void setPrecision(int precision=gPrecision)
Sets the precison or resets it to default.
A complete router's route.
Definition: RORoute.h:52
static double rand(std::mt19937 *rng=nullptr)
Returns a random real number in [0, 1)
Definition: RandHelper.h:51
double getOverallProb() const
Return the sum of the probabilites assigned to the members.
const std::vector< double > & getProbs() const
Returns the probabilities assigned to the members of the distribution.
const std::vector< T > & getVals() const
Returns the members of the distribution.
bool add(T val, double prob, bool checkDuplicates=true)
Adds a value with an assigned probability to the distribution.
SAX-handler base for SUMO-files.
int size() const
returns the number of existing substrings
static const int WHITECHARS
identifier for splitting the given string at all whitespace characters
bool hasNext()
returns the information whether further substrings exist
std::string next()
returns the next substring when it exists. Otherwise the behaviour is undefined
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter
static std::string prune(const std::string &str)
Removes trailing and leading whitechars.
Definition: StringUtils.cpp:47
static int toInt(const std::string &sData)
converts a string into the integer value described by it by calling the char-type converter,...
static bool runParser(GenericSAXHandler &handler, const std::string &file, const bool isNet=false, const bool isRoute=false)
Runs the given handler on the given file; returns if everything's ok.
Definition: XMLSubSys.cpp:148
A single O/D-matrix cell.
Definition: ODCell.h:48
std::string destination
Name of the destination district.
Definition: ODCell.h:62
std::map< SUMOTime, std::vector< std::string > > departures
mapping of departure times to departing vehicles, if already fixed
Definition: ODCell.h:71
std::string vehicleType
Name of the vehicle type.
Definition: ODCell.h:65
std::string origin
Name of the origin district.
Definition: ODCell.h:59
double vehicleNumber
The number of vehicles.
Definition: ODCell.h:50
bool originIsEdge
the origin "district" is an edge id
Definition: ODCell.h:74
SUMOTime end
The end time this cell describes.
Definition: ODCell.h:56
SUMOTime begin
The begin time this cell describes.
Definition: ODCell.h:53
bool destinationIsEdge
the destination "district" is an edge id
Definition: ODCell.h:77
An internal representation of a single vehicle.
Definition: ODMatrix.h:265
SUMOTime depart
The departure time of the vehicle.
Definition: ODMatrix.h:269
std::string from
The edge the vehicles shall start at.
Definition: ODMatrix.h:273
ODCell * cell
The cell of the ODMatrix which generated the vehicle.
Definition: ODMatrix.h:271
std::string to
The edge the vehicles shall end at.
Definition: ODMatrix.h:275
std::string id
The id of the vehicle.
Definition: ODMatrix.h:267