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,
347 bool asPoisson,
348 bool pedestrians, bool persontrips,
349 const std::string& modes) {
350 if (myContainer.size() == 0) {
351 return;
352 }
353 int flowName = 0;
355 // recheck begin time
356 for (std::vector<ODCell*>::const_iterator i = myContainer.begin(); i != myContainer.end(); ++i) {
357 const ODCell* const c = *i;
358 if (c->end > begin && c->begin < end) {
359 const double probability = float(c->vehicleNumber) / STEPS2TIME(c->end - c->begin);
360 if (probability <= 0) {
361 continue;
362 }
363 //Person flows
364 if (pedestrians) {
365 dev.openTag(SUMO_TAG_PERSONFLOW).writeAttr(SUMO_ATTR_ID, prefix + toString(flowName++));
367 if (asPoisson) {
368 dev.writeAttr(SUMO_ATTR_PERIOD, "exp(" + StringUtils::adjustDecimalValue(probability, 10) + ")");
369 } else if (!asProbability) {
371 } else {
372 if (probability > 1) {
373 WRITE_WARNINGF(TL("Flow density of % vehicles per second, cannot be represented with a simple probability. Falling back to even spacing."), toString(probability));
375 } else {
376 dev.setPrecision(6);
377 dev.writeAttr(SUMO_ATTR_PROB, probability);
378 dev.setPrecision();
379 }
380 }
383 dev.writeAttr(SUMO_ATTR_ARRIVALPOS, "random");
384 dev.closeTag();
385 dev.closeTag();
386 } else if (persontrips) {
387 dev.openTag(SUMO_TAG_PERSONFLOW).writeAttr(SUMO_ATTR_ID, prefix + toString(flowName++));
389 if (asPoisson) {
390 dev.writeAttr(SUMO_ATTR_PERIOD, "exp(" + StringUtils::adjustDecimalValue(probability, 10) + ")");
391 } else if (!asProbability) {
393 } else {
394 if (probability > 1) {
395 WRITE_WARNINGF(TL("Flow density of % vehicles per second, cannot be represented with a simple probability. Falling back to even spacing."), toString(probability));
397 } else {
398 dev.setPrecision(6);
399 dev.writeAttr(SUMO_ATTR_PROB, probability);
400 dev.setPrecision();
401 }
402 }
405 dev.writeAttr(SUMO_ATTR_ARRIVALPOS, "random");
406 if (modes != "") {
407 dev.writeAttr(SUMO_ATTR_MODES, modes);
408 }
409 dev.closeTag();
410 dev.closeTag();
411 } else {
412 // Normal flow output
413 dev.openTag(SUMO_TAG_FLOW).writeAttr(SUMO_ATTR_ID, prefix + toString(flowName++));
416 if (asPoisson) {
417 dev.writeAttr(SUMO_ATTR_PERIOD, "exp(" + StringUtils::adjustDecimalValue(probability, 10) + ")");
418 } else if (!asProbability) {
420 } else {
421 if (probability > 1) {
422 WRITE_WARNINGF(TL("Flow density of % vehicles per second, cannot be represented with a simple probability. Falling back to even spacing."), toString(probability));
424 } else {
425 dev.setPrecision(6);
426 dev.writeAttr(SUMO_ATTR_PROB, probability);
427 dev.setPrecision();
428 }
429 }
430 writeDefaultAttrs(dev, noVtype, *i);
431 dev.closeTag();
432 }
433 }
434 }
435}
436
437
438std::string
440 while (lr.good() && lr.hasMore()) {
441 const std::string line = lr.readLine();
442 if (line[0] != '*') {
443 return StringUtils::prune(line);
444 }
445 }
446 throw ProcessError(TLF("End of file while reading %.", lr.getFileName()));
447}
448
449
451ODMatrix::parseSingleTime(const std::string& time) {
452 if (time.find('.') == std::string::npos) {
453 throw NumberFormatException("no separator");
454 }
455 const std::string hours = time.substr(0, time.find('.'));
456 const std::string minutes = time.substr(time.find('.') + 1);
457 return TIME2STEPS(StringUtils::toInt(hours) * 3600 + StringUtils::toInt(minutes) * 60);
458}
459
460
461std::pair<SUMOTime, SUMOTime>
463 std::string line = getNextNonCommentLine(lr);
464 try {
466 const SUMOTime begin = parseSingleTime(st.next());
467 const SUMOTime end = parseSingleTime(st.next());
468 if (begin >= end) {
469 throw ProcessError("Matrix begin time " + time2string(begin) + " is larger than end time " + time2string(end) + ".");
470 }
471 return std::make_pair(begin, end);
472 } catch (OutOfBoundsException&) {
473 throw ProcessError(TLF("Broken period definition '%'.", line));
474 } catch (NumberFormatException& e) {
475 throw ProcessError("Broken period definition '" + line + "' (" + e.what() + ").");
476 }
477}
478
479
480double
482 std::string line = getNextNonCommentLine(lr);
483 double factor = -1;
484 try {
485 factor = StringUtils::toDouble(line) * scale;
486 } catch (NumberFormatException&) {
487 throw ProcessError(TLF("Broken factor: '%'.", line));
488 }
489 return factor;
490}
491
492void
493ODMatrix::readV(LineReader& lr, double scale,
494 std::string vehType, bool matrixHasVehType) {
495 PROGRESS_BEGIN_MESSAGE("Reading matrix '" + lr.getFileName() + "' stored as VMR");
496 // parse first defs
497 std::string line;
498 if (matrixHasVehType) {
499 line = getNextNonCommentLine(lr);
500 if (vehType == "") {
501 vehType = StringUtils::prune(line);
502 }
503 }
504
505 const std::pair<SUMOTime, SUMOTime> beginEnd = readTime(lr);
506 const double factor = readFactor(lr, scale);
507
508 // districts
509 line = getNextNonCommentLine(lr);
510 const int numDistricts = StringUtils::toInt(StringUtils::prune(line));
511 // parse district names (normally ints)
512 std::vector<std::string> names;
513 while ((int)names.size() != numDistricts && lr.hasMore()) {
514 line = getNextNonCommentLine(lr);
516 while (st2.hasNext()) {
517 names.push_back(st2.next());
518 }
519 }
520 if (!lr.hasMore()) {
521 throw ProcessError(TLF("Missing line with % district names.", toString(numDistricts)));
522 }
523
524 // parse the cells
525 for (std::vector<std::string>::iterator si = names.begin(); si != names.end(); ++si) {
526 std::vector<std::string>::iterator di = names.begin();
527 do {
528 try {
529 line = getNextNonCommentLine(lr);
530 } catch (ProcessError&) {
531 throw ProcessError(TLF("Missing line for district %.", (*si)));
532 }
533 if (line.length() == 0) {
534 continue;
535 }
536 try {
538 while (st2.hasNext()) {
539 assert(di != names.end());
540 double vehNumber = StringUtils::toDouble(st2.next()) * factor;
541 if (vehNumber != 0) {
542 add(vehNumber, beginEnd, *si, *di, vehType);
543 }
544 if (di == names.end()) {
545 throw ProcessError(TL("More entries than districts found."));
546 }
547 ++di;
548 }
549 } catch (NumberFormatException&) {
550 throw ProcessError(TLF("Not numeric vehicle number in line '%'.", line));
551 }
552 if (!lr.hasMore()) {
553 break;
554 }
555 } while (di != names.end());
556 }
558}
559
560
561void
562ODMatrix::readO(LineReader& lr, double scale,
563 std::string vehType, bool matrixHasVehType) {
564 PROGRESS_BEGIN_MESSAGE("Reading matrix '" + lr.getFileName() + "' stored as OR");
565 // parse first defs
566 std::string line;
567 if (matrixHasVehType) {
568 line = getNextNonCommentLine(lr);
569 int type = StringUtils::toInt(StringUtils::prune(line));
570 if (vehType == "") {
571 vehType = toString(type);
572 }
573 }
574
575 const std::pair<SUMOTime, SUMOTime> beginEnd = readTime(lr);
576 const double factor = readFactor(lr, scale);
577
578 // parse the cells
579 while (lr.hasMore()) {
580 line = getNextNonCommentLine(lr);
581 if (line.length() == 0) {
582 continue;
583 }
585 if (st2.size() == 0) {
586 continue;
587 }
588 try {
589 std::string sourceD = st2.next();
590 std::string destD = st2.next();
591 double vehNumber = StringUtils::toDouble(st2.next()) * factor;
592 if (vehNumber != 0) {
593 add(vehNumber, beginEnd, sourceD, destD, vehType);
594 }
595 } catch (OutOfBoundsException&) {
596 throw ProcessError(TLF("Missing at least one information in line '%'.", line));
597 } catch (NumberFormatException&) {
598 throw ProcessError(TLF("Not numeric vehicle number in line '%'.", line));
599 }
600 }
602}
603
604
605
606double
608 return myNumLoaded;
609}
610
611
612double
614 return myNumWritten;
615}
616
617
618double
620 return myNumDiscarded;
621}
622
623
624void
625ODMatrix::applyCurve(const Distribution_Points& ps, ODCell* cell, std::vector<ODCell*>& newCells) {
626 const std::vector<double>& times = ps.getVals();
627 for (int i = 0; i < (int)times.size() - 1; ++i) {
628 ODCell* ncell = new ODCell();
629 ncell->begin = TIME2STEPS(times[i]);
630 ncell->end = TIME2STEPS(times[i + 1]);
631 ncell->origin = cell->origin;
632 ncell->destination = cell->destination;
633 ncell->vehicleType = cell->vehicleType;
634 ncell->vehicleNumber = cell->vehicleNumber * ps.getProbs()[i] / ps.getOverallProb();
635 newCells.push_back(ncell);
636 }
637}
638
639
640void
642 std::vector<ODCell*> oldCells = myContainer;
643 myContainer.clear();
644 for (std::vector<ODCell*>::iterator i = oldCells.begin(); i != oldCells.end(); ++i) {
645 std::vector<ODCell*> newCells;
646 applyCurve(ps, *i, newCells);
647 copy(newCells.begin(), newCells.end(), back_inserter(myContainer));
648 delete *i;
649 }
650}
651
652
653void
655 std::vector<std::string> files = oc.getStringVector("od-matrix-files");
656 for (std::vector<std::string>::iterator i = files.begin(); i != files.end(); ++i) {
657 LineReader lr(*i);
658 if (!lr.good()) {
659 throw ProcessError(TLF("Could not open '%'.", (*i)));
660 }
661 std::string type = lr.readLine();
662 // get the type only
663 if (type.find(';') != std::string::npos) {
664 type = type.substr(0, type.find(';'));
665 }
666 // parse type-dependant
667 if (type.length() > 1 && type[1] == 'V') {
668 // process ptv's 'V'-matrices
669 if (type.find('N') != std::string::npos) {
670 throw ProcessError(TLF("'%' does not contain the needed information about the time described.", *i));
671 }
672 readV(lr, 1, oc.getString("vtype"), type.find('M') != std::string::npos);
673 } else if (type.length() > 1 && type[1] == 'O') {
674 // process ptv's 'O'-matrices
675 if (type.find('N') != std::string::npos) {
676 throw ProcessError(TLF("'%' does not contain the needed information about the time described.", *i));
677 }
678 readO(lr, 1, oc.getString("vtype"), type.find('M') != std::string::npos);
679 } else {
680 throw ProcessError("'" + *i + "' uses an unknown matrix type '" + type + "'.");
681 }
682 }
683 std::vector<std::string> amitranFiles = oc.getStringVector("od-amitran-files");
684 for (std::vector<std::string>::iterator i = amitranFiles.begin(); i != amitranFiles.end(); ++i) {
685 if (!FileHelpers::isReadable(*i)) {
686 throw ProcessError(TLF("Could not access matrix file '%' to load.", *i));
687 }
688 PROGRESS_BEGIN_MESSAGE("Loading matrix in Amitran format from '" + *i + "'");
689 ODAmitranHandler handler(*this, *i);
690 if (!XMLSubSys::runParser(handler, *i)) {
692 } else {
694 }
695 }
696 myVType = oc.getString("vtype");
697 for (std::string file : oc.getStringVector("tazrelation-files")) {
698 if (!FileHelpers::isReadable(file)) {
699 throw ProcessError(TLF("Could not access matrix file '%' to load.", file));
700 }
701 PROGRESS_BEGIN_MESSAGE("Loading matrix in tazRelation format from '" + file + "'");
702
703 std::vector<SAXWeightsHandler::ToRetrieveDefinition*> retrieverDefs;
704 retrieverDefs.push_back(new SAXWeightsHandler::ToRetrieveDefinition(oc.getString("tazrelation-attribute"), true, *this));
705 SAXWeightsHandler handler(retrieverDefs, "");
706 if (!XMLSubSys::runParser(handler, file)) {
708 } else {
710 }
711 }
712}
713
714void
715ODMatrix::addTazRelWeight(const std::string intervalID, const std::string& from, const std::string& to,
716 double val, double beg, double end) {
717 add(val, std::make_pair(TIME2STEPS(beg), TIME2STEPS(end)), from, to, myVType == "" ? intervalID : myVType);
718}
719
720
721void
723 std::vector<std::string> routeFiles = oc.getStringVector("route-files");
724 for (std::vector<std::string>::iterator i = routeFiles.begin(); i != routeFiles.end(); ++i) {
725 if (!FileHelpers::isReadable(*i)) {
726 throw ProcessError(TLF("Could not access route file '%' to load.", *i));
727 }
728 PROGRESS_BEGIN_MESSAGE("Loading routes and trips from '" + *i + "'");
729 if (!XMLSubSys::runParser(handler, *i)) {
731 } else {
733 }
734 }
735}
736
737
739ODMatrix::parseTimeLine(const std::vector<std::string>& def, bool timelineDayInHours) {
740 Distribution_Points result("N/A");
741 if (timelineDayInHours) {
742 if (def.size() != 24) {
743 throw ProcessError(TLF("Assuming 24 entries for a day timeline, but got %.", toString(def.size())));
744 }
745 for (int chour = 0; chour < 24; ++chour) {
746 result.add(chour * 3600., StringUtils::toDouble(def[chour]));
747 }
748 result.add(24 * 3600., 0.); // dummy value to finish the last interval
749 } else {
750 for (int i = 0; i < (int)def.size(); i++) {
751 StringTokenizer st2(def[i], ":");
752 if (st2.size() != 2) {
753 throw ProcessError(TLF("Broken time line definition: missing a value in '%'.", def[i]));
754 }
755 const double time = StringUtils::toDouble(st2.next());
756 result.add(time, StringUtils::toDouble(st2.next()));
757 }
758 }
759 return result;
760}
761
762
763void
767
768
769/****************************************************************************/
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_PERIOD
@ 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:391
Used for sorting vehicles by their departure (latest first)
Definition ODMatrix.h:427
SUMOTime myEnd
Definition ODMatrix.h:379
void writeFlows(const SUMOTime begin, const SUMOTime end, OutputDevice &dev, const bool noVtype, const std::string &prefix, bool asProbability=false, bool asPoisson=false, bool pedestrians=false, bool persontrips=false, const std::string &modes="")
Writes the flows stored in the matrix.
Definition ODMatrix.cpp:343
double getNumLoaded() const
Returns the number of loaded vehicles.
Definition ODMatrix.cpp:607
void readV(LineReader &lr, double scale, std::string vehType, bool matrixHasVehType)
read a VISUM-matrix with the V Format
Definition ODMatrix.cpp:493
void sortByBeginTime()
Definition ODMatrix.cpp:764
double readFactor(LineReader &lr, double scale)
Definition ODMatrix.cpp:481
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:715
SUMOTime myBegin
parsed time bounds
Definition ODMatrix.h:379
~ODMatrix()
Destructor.
Definition ODMatrix.cpp:63
SUMOTime parseSingleTime(const std::string &time)
Definition ODMatrix.cpp:451
double myScale
the scaling factor for traffic
Definition ODMatrix.h:385
void applyCurve(const Distribution_Points &ps)
Splits the stored cells dividing them on the given time line.
Definition ODMatrix.cpp:641
std::map< const std::pair< const std::string, const std::string >, std::vector< ODCell * > > myShortCut
The loaded cells indexed by origin and destination.
Definition ODMatrix.h:361
std::pair< SUMOTime, SUMOTime > readTime(LineReader &lr)
Definition ODMatrix.cpp:462
void readO(LineReader &lr, double scale, std::string vehType, bool matrixHasVehType)
read a VISUM-matrix with the O Format
Definition ODMatrix.cpp:562
std::set< std::string > myMissingDistricts
The missing districts already warned about.
Definition ODMatrix.h:367
void write(SUMOTime begin, const SUMOTime end, OutputDevice &dev, const bool uniform, const bool differSourceSink, const bool noVtype, const std::string &prefix, const bool stepLog, bool pedestrians, bool persontrips, const std::string &modes)
Writes the vehicles stored in the matrix assigning the sources and sinks.
Definition ODMatrix.cpp:233
const ODDistrictCont & myDistricts
The districts to retrieve sources/sinks from.
Definition ODMatrix.h:364
Distribution_Points parseTimeLine(const std::vector< std::string > &def, bool timelineDayInHours)
split the given timeline
Definition ODMatrix.cpp:739
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:370
double myNumWritten
Number of written vehicles.
Definition ODMatrix.h:373
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:654
void loadRoutes(OptionsCont &oc, SUMOSAXHandler &handler)
read SUMO routes
Definition ODMatrix.cpp:722
double getNumWritten() const
Returns the number of written vehicles.
Definition ODMatrix.cpp:613
std::vector< ODCell * > myContainer
The loaded cells.
Definition ODMatrix.h:358
double myNumDiscarded
Number of discarded vehicles.
Definition ODMatrix.h:376
double getNumDiscarded() const
Returns the number of discarded vehicles.
Definition ODMatrix.cpp:619
std::string myVType
user-defined vType
Definition ODMatrix.h:382
std::string getNextNonCommentLine(LineReader &lr)
Definition ODMatrix.cpp:439
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 std::string adjustDecimalValue(double value, int precision)
write with maximum precision if needed but remove trailing zeros
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:269
SUMOTime depart
The departure time of the vehicle.
Definition ODMatrix.h:273
std::string from
The edge the vehicles shall start at.
Definition ODMatrix.h:277
ODCell * cell
The cell of the ODMatrix which generated the vehicle.
Definition ODMatrix.h:275
std::string to
The edge the vehicles shall end at.
Definition ODMatrix.h:279
std::string id
The id of the vehicle.
Definition ODMatrix.h:271