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