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-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>
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 for (RORoute* const r : cell->pathsVector) {
66 delete r;
67 }
68 delete cell;
69 }
70 myContainer.clear();
71}
72
73
74bool
75ODMatrix::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
129bool
130ODMatrix::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
167double
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
206void
208 const ODCell* const cell) {
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
235void
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;
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
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 }
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
345void
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;
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 }
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
434std::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
447ODMatrix::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
457std::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
476double
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
488void
489ODMatrix::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
557void
558ODMatrix::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
602double
604 return myNumLoaded;
605}
606
607
608double
610 return myNumWritten;
611}
612
613
614double
616 return myNumDiscarded;
617}
618
619
620void
621ODMatrix::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
636void
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
649void
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
710void
711ODMatrix::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
717void
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
735ODMatrix::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
759void
763
764
765/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
#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.
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: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.
Static storage of an output device and its base (abstract) implementation.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
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)
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