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-2022 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, const std::pair<SUMOTime, SUMOTime>& beginEnd,
68  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 = beginEnd.first;
99  cell->end = beginEnd.second;
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  if (myBegin == -1 || cell->begin < myBegin) {
108  myBegin = cell->begin;
109  }
110  if (cell->end > myEnd) {
111  myEnd = cell->end;
112  }
113  return true;
114 }
115 
116 
117 bool
118 ODMatrix::add(const std::string& id, const SUMOTime depart,
119  const std::string& fromTaz, const std::string& toTaz,
120  const std::string& vehicleType, const bool originIsEdge, const bool destinationIsEdge) {
121  if (myMissingDistricts.count(fromTaz) > 0 || myMissingDistricts.count(toTaz) > 0) {
122  myNumLoaded += 1.;
123  myNumDiscarded += 1.;
124  return false;
125  }
126  // we start looking from the end because there is a high probability that the input is sorted by time
127  std::vector<ODCell*>& odList = myShortCut[std::make_pair(fromTaz, toTaz)];
128  ODCell* cell = nullptr;
129  for (std::vector<ODCell*>::const_reverse_iterator c = odList.rbegin(); c != odList.rend(); ++c) {
130  if ((*c)->begin <= depart && (*c)->end > depart && (*c)->vehicleType == vehicleType) {
131  cell = *c;
132  break;
133  }
134  }
135  if (cell == nullptr) {
136  const SUMOTime interval = string2time(OptionsCont::getOptions().getString("aggregation-interval"));
137  const int intervalIdx = (int)(depart / interval);
138  if (add(1., std::make_pair(intervalIdx * interval, (intervalIdx + 1) * interval),
139  fromTaz, toTaz, vehicleType, originIsEdge, destinationIsEdge)) {
140  cell = myContainer.back();
141  odList.push_back(cell);
142  } else {
143  return false;
144  }
145  } else {
146  myNumLoaded += 1.;
147  cell->vehicleNumber += 1.;
148  }
149  cell->departures[depart].push_back(id);
150  return true;
151 }
152 
153 
154 double
156  int& vehName, std::vector<ODVehicle>& into,
157  const bool uniform, const bool differSourceSink,
158  const std::string& prefix) {
159  int vehicles2insert = (int) cell->vehicleNumber;
160  // compute whether the fraction forces an additional vehicle insertion
161  if (RandHelper::rand() < cell->vehicleNumber - (double)vehicles2insert) {
162  vehicles2insert++;
163  }
164  if (vehicles2insert == 0) {
165  return cell->vehicleNumber;
166  }
167 
168  const double offset = (double)(cell->end - cell->begin) / (double) vehicles2insert / (double) 2.;
169  for (int i = 0; i < vehicles2insert; ++i) {
170  ODVehicle veh;
171  veh.id = prefix + toString(vehName++);
172 
173  if (uniform) {
174  veh.depart = (SUMOTime)(offset + cell->begin + ((double)(cell->end - cell->begin) * (double) i / (double) vehicles2insert));
175  } else {
176  veh.depart = (SUMOTime)RandHelper::rand(cell->begin, cell->end);
177  }
178  const bool canDiffer = myDistricts.get(cell->origin)->sourceNumber() > 1 || myDistricts.get(cell->destination)->sinkNumber() > 1;
179  do {
182  } while (canDiffer && differSourceSink && (veh.to == veh.from));
183  if (!canDiffer && differSourceSink && (veh.to == veh.from)) {
184  WRITE_WARNING("Cannot find different source and sink edge for origin '" + cell->origin + "' and destination '" + cell->destination + "'.");
185  }
186  veh.cell = cell;
187  into.push_back(veh);
188  }
189  return cell->vehicleNumber - vehicles2insert;
190 }
191 
192 
193 void
194 ODMatrix::writeDefaultAttrs(OutputDevice& dev, const bool noVtype,
195  const ODCell* const cell) {
196  const OptionsCont& oc = OptionsCont::getOptions();
197  if (!noVtype && cell->vehicleType != "") {
199  }
201  if (oc.isSet("departlane") && oc.getString("departlane") != "default") {
202  dev.writeAttr(SUMO_ATTR_DEPARTLANE, oc.getString("departlane"));
203  }
204  if (oc.isSet("departpos")) {
205  dev.writeAttr(SUMO_ATTR_DEPARTPOS, oc.getString("departpos"));
206  }
207  if (oc.isSet("departspeed") && oc.getString("departspeed") != "default") {
208  dev.writeAttr(SUMO_ATTR_DEPARTSPEED, oc.getString("departspeed"));
209  }
210  if (oc.isSet("arrivallane")) {
211  dev.writeAttr(SUMO_ATTR_ARRIVALLANE, oc.getString("arrivallane"));
212  }
213  if (oc.isSet("arrivalpos")) {
214  dev.writeAttr(SUMO_ATTR_ARRIVALPOS, oc.getString("arrivalpos"));
215  }
216  if (oc.isSet("arrivalspeed")) {
217  dev.writeAttr(SUMO_ATTR_ARRIVALSPEED, oc.getString("arrivalspeed"));
218  }
219 }
220 
221 
222 void
224  OutputDevice& dev, const bool uniform,
225  const bool differSourceSink, const bool noVtype,
226  const std::string& prefix, const bool stepLog,
227  bool pedestrians, bool persontrips,
228  const std::string& modes) {
229  if (myContainer.size() == 0) {
230  return;
231  }
232  std::map<std::pair<std::string, std::string>, double> fractionLeft;
233  int vehName = 0;
234  sortByBeginTime();
235  // recheck begin time
236  begin = MAX2(begin, myContainer.front()->begin);
237  std::vector<ODCell*>::iterator next = myContainer.begin();
238  std::vector<ODVehicle> vehicles;
239  SUMOTime lastOut = -DELTA_T;
240 
241  const OptionsCont& oc = OptionsCont::getOptions();
242  std::string personDepartPos = oc.isSet("departpos") ? oc.getString("departpos") : "random";
243  std::string personArrivalPos = oc.isSet("arrivalpos") ? oc.getString("arrivalpos") : "random";
244  SumoXMLAttr fromAttr = oc.getBool("junctions") ? SUMO_ATTR_FROMJUNCTION : SUMO_ATTR_FROM;
245  SumoXMLAttr toAttr = oc.getBool("junctions") ? SUMO_ATTR_TOJUNCTION : SUMO_ATTR_TO;
246 
247  // go through the time steps
248  for (SUMOTime t = begin; t < end;) {
249  if (stepLog && t - lastOut >= DELTA_T) {
250  std::cout << "Parsing time " + time2string(t) << '\r';
251  lastOut = t;
252  }
253  // recheck whether a new cell got valid
254  bool changed = false;
255  while (next != myContainer.end() && (*next)->begin <= t && (*next)->end > t) {
256  std::pair<std::string, std::string> odID = std::make_pair((*next)->origin, (*next)->destination);
257  // check whether the current cell must be extended by the last fraction
258  if (fractionLeft.find(odID) != fractionLeft.end()) {
259  (*next)->vehicleNumber += fractionLeft[odID];
260  fractionLeft[odID] = 0;
261  }
262  // get the new departures (into tmp)
263  const int oldSize = (int)vehicles.size();
264  const double fraction = computeDeparts(*next, vehName, vehicles, uniform, differSourceSink, prefix);
265  if (oldSize != (int)vehicles.size()) {
266  changed = true;
267  }
268  if (fraction != 0) {
269  fractionLeft[odID] = fraction;
270  }
271  ++next;
272  }
273  if (changed) {
274  sort(vehicles.begin(), vehicles.end(), descending_departure_comperator());
275  }
276 
277  for (std::vector<ODVehicle>::reverse_iterator i = vehicles.rbegin(); i != vehicles.rend() && (*i).depart == t; ++i) {
278  if (t >= begin) {
279  myNumWritten++;
280  if (pedestrians) {
282  dev.writeAttr(SUMO_ATTR_DEPARTPOS, personDepartPos);
283  dev.openTag(SUMO_TAG_WALK);
284  dev.writeAttr(fromAttr, (*i).from);
285  dev.writeAttr(toAttr, (*i).to);
286  dev.writeAttr(SUMO_ATTR_FROM_TAZ, (*i).cell->origin).writeAttr(SUMO_ATTR_TO_TAZ, (*i).cell->destination);
287  dev.writeAttr(SUMO_ATTR_ARRIVALPOS, personArrivalPos);
288  dev.closeTag();
289  dev.closeTag();
290  } else if (persontrips) {
292  dev.writeAttr(SUMO_ATTR_DEPARTPOS, personDepartPos);
294  dev.writeAttr(fromAttr, (*i).from);
295  dev.writeAttr(toAttr, (*i).to);
296  dev.writeAttr(SUMO_ATTR_FROM_TAZ, (*i).cell->origin).writeAttr(SUMO_ATTR_TO_TAZ, (*i).cell->destination);
297  dev.writeAttr(SUMO_ATTR_ARRIVALPOS, personArrivalPos);
298  if (modes != "") {
299  dev.writeAttr(SUMO_ATTR_MODES, modes);
300  }
301  dev.closeTag();
302  dev.closeTag();
303  } else {
305  dev.writeAttr(fromAttr, (*i).from);
306  dev.writeAttr(toAttr, (*i).to);
307  writeDefaultAttrs(dev, noVtype, i->cell);
308  dev.closeTag();
309  }
310  }
311  }
312  while (vehicles.size() != 0 && vehicles.back().depart == t) {
313  vehicles.pop_back();
314  }
315  if (!vehicles.empty()) {
316  t = vehicles.back().depart;
317  }
318  if (next != myContainer.end() && (t > (*next)->begin || vehicles.empty())) {
319  t = (*next)->begin;
320  }
321  if (next == myContainer.end() && vehicles.empty()) {
322  break;
323  }
324  }
325 }
326 
327 
328 void
329 ODMatrix::writeFlows(const SUMOTime begin, const SUMOTime end,
330  OutputDevice& dev, bool noVtype,
331  const std::string& prefix,
332  bool asProbability, bool pedestrians, bool persontrips,
333  const std::string& modes) {
334  if (myContainer.size() == 0) {
335  return;
336  }
337  int flowName = 0;
338  sortByBeginTime();
339  // recheck begin time
340  for (std::vector<ODCell*>::const_iterator i = myContainer.begin(); i != myContainer.end(); ++i) {
341  const ODCell* const c = *i;
342  if (c->end > begin && c->begin < end) {
343  const double probability = asProbability ? float(c->vehicleNumber) / STEPS2TIME(c->end - c->begin) : 1;
344  if (probability <= 0) {
345  continue;
346  }
347  //Person flows
348  if (pedestrians) {
349  dev.openTag(SUMO_TAG_PERSONFLOW).writeAttr(SUMO_ATTR_ID, prefix + toString(flowName++));
351  if (!asProbability) {
353  } else {
354  if (probability > 1) {
355  WRITE_WARNING("Flow density of " + toString(probability) + " vehicles per second, cannot be represented with a simple probability. Falling back to even spacing.");
357  } else {
358  dev.setPrecision(6);
359  dev.writeAttr(SUMO_ATTR_PROB, probability);
360  dev.setPrecision();
361  }
362  }
363  dev.openTag(SUMO_TAG_WALK);
365  dev.writeAttr(SUMO_ATTR_ARRIVALPOS, "random");
366  dev.closeTag();
367  dev.closeTag();
368  } else if (persontrips) {
369  dev.openTag(SUMO_TAG_PERSONFLOW).writeAttr(SUMO_ATTR_ID, prefix + toString(flowName++));
371  if (!asProbability) {
373  } else {
374  if (probability > 1) {
375  WRITE_WARNING("Flow density of " + toString(probability) + " vehicles per second, cannot be represented with a simple probability. Falling back to even spacing.");
377  } else {
378  dev.setPrecision(6);
379  dev.writeAttr(SUMO_ATTR_PROB, probability);
380  dev.setPrecision();
381  }
382  }
385  dev.writeAttr(SUMO_ATTR_ARRIVALPOS, "random");
386  if (modes != "") {
387  dev.writeAttr(SUMO_ATTR_MODES, modes);
388  }
389  dev.closeTag();
390  dev.closeTag();
391  } else {
392  // Normal flow output
393  dev.openTag(SUMO_TAG_FLOW).writeAttr(SUMO_ATTR_ID, prefix + toString(flowName++));
396 
397  if (!asProbability) {
399  } else {
400  if (probability > 1) {
401  WRITE_WARNING("Flow density of " + toString(probability) + " vehicles per second, cannot be represented with a simple probability. Falling back to even spacing.");
403  } else {
404  dev.setPrecision(6);
405  dev.writeAttr(SUMO_ATTR_PROB, probability);
406  dev.setPrecision();
407  }
408  }
409  writeDefaultAttrs(dev, noVtype, *i);
410  dev.closeTag();
411  }
412  }
413  }
414 }
415 
416 
417 std::string
419  while (lr.good() && lr.hasMore()) {
420  const std::string line = lr.readLine();
421  if (line[0] != '*') {
422  return StringUtils::prune(line);
423  }
424  }
425  throw ProcessError("End of file while reading " + lr.getFileName() + ".");
426 }
427 
428 
429 SUMOTime
430 ODMatrix::parseSingleTime(const std::string& time) {
431  if (time.find('.') == std::string::npos) {
432  throw NumberFormatException("no separator");
433  }
434  const std::string hours = time.substr(0, time.find('.'));
435  const std::string minutes = time.substr(time.find('.') + 1);
436  return TIME2STEPS(StringUtils::toInt(hours) * 3600 + StringUtils::toInt(minutes) * 60);
437 }
438 
439 
440 std::pair<SUMOTime, SUMOTime>
442  std::string line = getNextNonCommentLine(lr);
443  try {
445  const SUMOTime begin = parseSingleTime(st.next());
446  const SUMOTime end = parseSingleTime(st.next());
447  if (begin >= end) {
448  throw ProcessError("Matrix begin time " + time2string(begin) + " is larger than end time " + time2string(end) + ".");
449  }
450  return std::make_pair(begin, end);
451  } catch (OutOfBoundsException&) {
452  throw ProcessError("Broken period definition '" + line + "'.");
453  } catch (NumberFormatException& e) {
454  throw ProcessError("Broken period definition '" + line + "' (" + e.what() + ").");
455  }
456 }
457 
458 
459 double
460 ODMatrix::readFactor(LineReader& lr, double scale) {
461  std::string line = getNextNonCommentLine(lr);
462  double factor = -1;
463  try {
464  factor = StringUtils::toDouble(line) * scale;
465  } catch (NumberFormatException&) {
466  throw ProcessError("Broken factor: '" + line + "'.");
467  }
468  return factor;
469 }
470 
471 void
472 ODMatrix::readV(LineReader& lr, double scale,
473  std::string vehType, bool matrixHasVehType) {
474  PROGRESS_BEGIN_MESSAGE("Reading matrix '" + lr.getFileName() + "' stored as VMR");
475  // parse first defs
476  std::string line;
477  if (matrixHasVehType) {
478  line = getNextNonCommentLine(lr);
479  if (vehType == "") {
480  vehType = StringUtils::prune(line);
481  }
482  }
483 
484  const std::pair<SUMOTime, SUMOTime> beginEnd = readTime(lr);
485  const double factor = readFactor(lr, scale);
486 
487  // districts
488  line = getNextNonCommentLine(lr);
489  const int numDistricts = StringUtils::toInt(StringUtils::prune(line));
490  // parse district names (normally ints)
491  std::vector<std::string> names;
492  while ((int)names.size() != numDistricts && lr.hasMore()) {
493  line = getNextNonCommentLine(lr);
495  while (st2.hasNext()) {
496  names.push_back(st2.next());
497  }
498  }
499  if (!lr.hasMore()) {
500  throw ProcessError("Missing line with " + toString(numDistricts) + " district names.");
501  }
502 
503  // parse the cells
504  for (std::vector<std::string>::iterator si = names.begin(); si != names.end(); ++si) {
505  std::vector<std::string>::iterator di = names.begin();
506  do {
507  try {
508  line = getNextNonCommentLine(lr);
509  } catch (ProcessError&) {
510  throw ProcessError("Missing line for district " + (*si) + ".");
511  }
512  if (line.length() == 0) {
513  continue;
514  }
515  try {
517  while (st2.hasNext()) {
518  assert(di != names.end());
519  double vehNumber = StringUtils::toDouble(st2.next()) * factor;
520  if (vehNumber != 0) {
521  add(vehNumber, beginEnd, *si, *di, vehType);
522  }
523  if (di == names.end()) {
524  throw ProcessError("More entries than districts found.");
525  }
526  ++di;
527  }
528  } catch (NumberFormatException&) {
529  throw ProcessError("Not numeric vehicle number in line '" + line + "'.");
530  }
531  if (!lr.hasMore()) {
532  break;
533  }
534  } while (di != names.end());
535  }
537 }
538 
539 
540 void
541 ODMatrix::readO(LineReader& lr, double scale,
542  std::string vehType, bool matrixHasVehType) {
543  PROGRESS_BEGIN_MESSAGE("Reading matrix '" + lr.getFileName() + "' stored as OR");
544  // parse first defs
545  std::string line;
546  if (matrixHasVehType) {
547  line = getNextNonCommentLine(lr);
548  int type = StringUtils::toInt(StringUtils::prune(line));
549  if (vehType == "") {
550  vehType = toString(type);
551  }
552  }
553 
554  const std::pair<SUMOTime, SUMOTime> beginEnd = readTime(lr);
555  const double factor = readFactor(lr, scale);
556 
557  // parse the cells
558  while (lr.hasMore()) {
559  line = getNextNonCommentLine(lr);
560  if (line.length() == 0) {
561  continue;
562  }
564  if (st2.size() == 0) {
565  continue;
566  }
567  try {
568  std::string sourceD = st2.next();
569  std::string destD = st2.next();
570  double vehNumber = StringUtils::toDouble(st2.next()) * factor;
571  if (vehNumber != 0) {
572  add(vehNumber, beginEnd, sourceD, destD, vehType);
573  }
574  } catch (OutOfBoundsException&) {
575  throw ProcessError("Missing at least one information in line '" + line + "'.");
576  } catch (NumberFormatException&) {
577  throw ProcessError("Not numeric vehicle number in line '" + line + "'.");
578  }
579  }
581 }
582 
583 
584 
585 double
587  return myNumLoaded;
588 }
589 
590 
591 double
593  return myNumWritten;
594 }
595 
596 
597 double
599  return myNumDiscarded;
600 }
601 
602 
603 void
604 ODMatrix::applyCurve(const Distribution_Points& ps, ODCell* cell, std::vector<ODCell*>& newCells) {
605  const std::vector<double>& times = ps.getVals();
606  for (int i = 0; i < (int)times.size() - 1; ++i) {
607  ODCell* ncell = new ODCell();
608  ncell->begin = TIME2STEPS(times[i]);
609  ncell->end = TIME2STEPS(times[i + 1]);
610  ncell->origin = cell->origin;
611  ncell->destination = cell->destination;
612  ncell->vehicleType = cell->vehicleType;
613  ncell->vehicleNumber = cell->vehicleNumber * ps.getProbs()[i] / ps.getOverallProb();
614  newCells.push_back(ncell);
615  }
616 }
617 
618 
619 void
621  std::vector<ODCell*> oldCells = myContainer;
622  myContainer.clear();
623  for (std::vector<ODCell*>::iterator i = oldCells.begin(); i != oldCells.end(); ++i) {
624  std::vector<ODCell*> newCells;
625  applyCurve(ps, *i, newCells);
626  copy(newCells.begin(), newCells.end(), back_inserter(myContainer));
627  delete *i;
628  }
629 }
630 
631 
632 void
634  std::vector<std::string> files = oc.getStringVector("od-matrix-files");
635  for (std::vector<std::string>::iterator i = files.begin(); i != files.end(); ++i) {
636  LineReader lr(*i);
637  if (!lr.good()) {
638  throw ProcessError("Could not open '" + (*i) + "'.");
639  }
640  std::string type = lr.readLine();
641  // get the type only
642  if (type.find(';') != std::string::npos) {
643  type = type.substr(0, type.find(';'));
644  }
645  // parse type-dependant
646  if (type.length() > 1 && type[1] == 'V') {
647  // process ptv's 'V'-matrices
648  if (type.find('N') != std::string::npos) {
649  throw ProcessError("'" + *i + "' does not contain the needed information about the time described.");
650  }
651  readV(lr, oc.getFloat("scale"), oc.getString("vtype"), type.find('M') != std::string::npos);
652  } else if (type.length() > 1 && type[1] == 'O') {
653  // process ptv's 'O'-matrices
654  if (type.find('N') != std::string::npos) {
655  throw ProcessError("'" + *i + "' does not contain the needed information about the time described.");
656  }
657  readO(lr, oc.getFloat("scale"), oc.getString("vtype"), type.find('M') != std::string::npos);
658  } else {
659  throw ProcessError("'" + *i + "' uses an unknown matrix type '" + type + "'.");
660  }
661  }
662  std::vector<std::string> amitranFiles = oc.getStringVector("od-amitran-files");
663  for (std::vector<std::string>::iterator i = amitranFiles.begin(); i != amitranFiles.end(); ++i) {
664  if (!FileHelpers::isReadable(*i)) {
665  throw ProcessError("Could not access matrix file '" + *i + "' to load.");
666  }
667  PROGRESS_BEGIN_MESSAGE("Loading matrix in Amitran format from '" + *i + "'");
668  ODAmitranHandler handler(*this, *i);
669  if (!XMLSubSys::runParser(handler, *i)) {
671  } else {
673  }
674  }
675  myVType = oc.getString("vtype");
676  for (std::string file : oc.getStringVector("tazrelation-files")) {
677  if (!FileHelpers::isReadable(file)) {
678  throw ProcessError("Could not access matrix file '" + file + "' to load.");
679  }
680  PROGRESS_BEGIN_MESSAGE("Loading matrix in tazRelation format from '" + file + "'");
681 
682  std::vector<SAXWeightsHandler::ToRetrieveDefinition*> retrieverDefs;
683  retrieverDefs.push_back(new SAXWeightsHandler::ToRetrieveDefinition(oc.getString("tazrelation-attribute"), true, *this));
684  SAXWeightsHandler handler(retrieverDefs, "");
685  if (!XMLSubSys::runParser(handler, file)) {
687  } else {
689  }
690  }
691 }
692 
693 void
694 ODMatrix::addTazRelWeight(const std::string intervalID, const std::string& from, const std::string& to,
695  double val, double beg, double end) {
696  add(val, std::make_pair(TIME2STEPS(beg), TIME2STEPS(end)), from, to, myVType == "" ? intervalID : myVType);
697 }
698 
699 
700 void
702  std::vector<std::string> routeFiles = oc.getStringVector("route-files");
703  for (std::vector<std::string>::iterator i = routeFiles.begin(); i != routeFiles.end(); ++i) {
704  if (!FileHelpers::isReadable(*i)) {
705  throw ProcessError("Could not access route file '" + *i + "' to load.");
706  }
707  PROGRESS_BEGIN_MESSAGE("Loading routes and trips from '" + *i + "'");
708  if (!XMLSubSys::runParser(handler, *i)) {
710  } else {
712  }
713  }
714 }
715 
716 
718 ODMatrix::parseTimeLine(const std::vector<std::string>& def, bool timelineDayInHours) {
719  Distribution_Points result("N/A");
720  if (timelineDayInHours) {
721  if (def.size() != 24) {
722  throw ProcessError("Assuming 24 entries for a day timeline, but got " + toString(def.size()) + ".");
723  }
724  for (int chour = 0; chour < 24; ++chour) {
725  result.add(chour * 3600., StringUtils::toDouble(def[chour]));
726  }
727  result.add(24 * 3600., 0.); // dummy value to finish the last interval
728  } else {
729  for (int i = 0; i < (int)def.size(); i++) {
730  StringTokenizer st2(def[i], ":");
731  if (st2.size() != 2) {
732  throw ProcessError("Broken time line definition: missing a value in '" + def[i] + "'.");
733  }
734  const double time = StringUtils::toDouble(st2.next());
735  result.add(time, StringUtils::toDouble(st2.next()));
736  }
737  }
738  return result;
739 }
740 
741 
742 void
744  std::sort(myContainer.begin(), myContainer.end(), cell_by_begin_comparator());
745 }
746 
747 
748 /****************************************************************************/
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:288
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:280
#define PROGRESS_DONE_MESSAGE()
Definition: MsgHandler.h:284
#define PROGRESS_FAILED_MESSAGE()
Definition: MsgHandler.h:287
#define PROGRESS_BEGIN_MESSAGE(msg)
Definition: MsgHandler.h:283
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:32
@ 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)
SumoXMLAttr
Numbers representing SUMO-XML - attributes.
@ SUMO_ATTR_NUMBER
@ SUMO_ATTR_ARRIVALSPEED
@ SUMO_ATTR_ARRIVALLANE
@ SUMO_ATTR_DEPART
@ SUMO_ATTR_FROMJUNCTION
@ 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
@ SUMO_ATTR_TOJUNCTION
T MAX2(T a, T b)
Definition: StdDefs.h:80
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
static bool isReadable(std::string path)
Checks whether the given file is readable.
Definition: FileHelpers.cpp:49
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:388
Used for sorting vehicles by their departure (latest first)
Definition: ODMatrix.h:424
SUMOTime myEnd
Definition: ODMatrix.h:379
double getNumLoaded() const
Returns the number of loaded vehicles.
Definition: ODMatrix.cpp:586
void readV(LineReader &lr, double scale, std::string vehType, bool matrixHasVehType)
read a VISUM-matrix with the V Format
Definition: ODMatrix.cpp:472
bool add(double vehicleNumber, const std::pair< SUMOTime, SUMOTime > &beginEnd, 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:743
double readFactor(LineReader &lr, double scale)
Definition: ODMatrix.cpp:460
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:155
void addTazRelWeight(const std::string intervalID, const std::string &from, const std::string &to, double val, double beg, double end)
Definition: ODMatrix.cpp:694
SUMOTime myBegin
parsed time bounds
Definition: ODMatrix.h:379
~ODMatrix()
Destructor.
Definition: ODMatrix.cpp:55
SUMOTime parseSingleTime(const std::string &time)
Definition: ODMatrix.cpp:430
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:329
void applyCurve(const Distribution_Points &ps)
Splits the stored cells dividing them on the given time line.
Definition: ODMatrix.cpp:620
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:361
std::pair< SUMOTime, SUMOTime > readTime(LineReader &lr)
Definition: ODMatrix.cpp:441
void readO(LineReader &lr, double scale, std::string vehType, bool matrixHasVehType)
read a VISUM-matrix with the O Format
Definition: ODMatrix.cpp:541
std::set< std::string > myMissingDistricts
The missing districts already warned about.
Definition: ODMatrix.h:367
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:223
const ODDistrictCont & myDistricts
The districts to retrieve sources/sinks from.
Definition: ODMatrix.h:364
Distribution_Points parseTimeLine(const std::vector< std::string > &def, bool timelineDayInHours)
split the given timeline
Definition: ODMatrix.cpp:718
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:194
double myNumLoaded
Number of loaded vehicles.
Definition: ODMatrix.h:370
double myNumWritten
Number of written vehicles.
Definition: ODMatrix.h:373
void loadMatrix(OptionsCont &oc)
read a matrix in one of several formats
Definition: ODMatrix.cpp:633
void loadRoutes(OptionsCont &oc, SUMOSAXHandler &handler)
read SUMO routes
Definition: ODMatrix.cpp:701
double getNumWritten() const
Returns the number of written vehicles.
Definition: ODMatrix.cpp:592
std::vector< ODCell * > myContainer
The loaded cells.
Definition: ODMatrix.h:358
double myNumDiscarded
Number of discarded vehicles.
Definition: ODMatrix.h:376
double getNumDiscarded() const
Returns the number of discarded vehicles.
Definition: ODMatrix.cpp:598
std::string myVType
user-defined vType
Definition: ODMatrix.h:382
std::string getNextNonCommentLine(LineReader &lr)
Definition: ODMatrix.cpp:418
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)
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
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:61
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:248
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
void setPrecision(int precision=gPrecision)
Sets the precision or resets it to default.
A complete router's route.
Definition: RORoute.h:52
static double rand(SumoRNG *rng=nullptr)
Returns a random real number in [0, 1)
Definition: RandHelper.h:119
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.
Complete definition about what shall be retrieved and where to store it.
An XML-handler for network weights.
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:48
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:149
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:269
SUMOTime depart
The departure time of the vehicle.
Definition: ODMatrix.h:273
std::string from
The edge the vehicles shall start at.
Definition: ODMatrix.h:277
ODCell * cell
The cell of the ODMatrix which generated the vehicle.
Definition: ODMatrix.h:275
std::string to
The edge the vehicles shall end at.
Definition: ODMatrix.h:279
std::string id
The id of the vehicle.
Definition: ODMatrix.h:271