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