Eclipse SUMO - Simulation of Urban MObility
ROMAAssignments.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 // Copyright (C) 2001-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 /****************************************************************************/
20 // Assignment methods
21 /****************************************************************************/
22 #include <config.h>
23 
24 #include <vector>
25 #include <algorithm>
26 #include <utils/common/SUMOTime.h>
30 #include <router/ROEdge.h>
31 #include <router/RONet.h>
32 #include <router/RORoute.h>
33 #include <od/ODMatrix.h>
34 #include "ROMAEdge.h"
35 #include "ROMAAssignments.h"
36 
37 
38 // ===========================================================================
39 // static member variables
40 // ===========================================================================
41 std::map<const ROEdge* const, double> ROMAAssignments::myPenalties;
42 
43 
44 // ===========================================================================
45 // method definitions
46 // ===========================================================================
47 
48 ROMAAssignments::ROMAAssignments(const SUMOTime begin, const SUMOTime end, const bool additiveTraffic,
49  const double adaptionFactor, const int maxAlternatives, const bool defaultCapacities,
51  OutputDevice* netloadOutput)
52  : myBegin(begin), myEnd(end), myAdditiveTraffic(additiveTraffic), myAdaptionFactor(adaptionFactor),
53  myMaxAlternatives(maxAlternatives), myUseDefaultCapacities(defaultCapacities),
54  myNet(net), myMatrix(matrix), myRouter(router), myNetloadOutput(netloadOutput) {
56 }
57 
58 
60  delete myDefaultVehicle;
61 }
62 
63 // based on the definitions in PTV-Validate and in the VISUM-Cologne network
64 double
66  if (edge->isTazConnector()) {
67  return 0;
68  }
69  const int roadClass = myUseDefaultCapacities ? -1 : -edge->getPriority();
70  // TODO: differ road class 1 from the unknown road class 1!!!
71  if (edge->getNumLanes() == 0) {
72  // TAZ have no cost
73  return 0;
74  } else if (roadClass == 0 || roadClass == 1) {
75  return edge->getNumLanes() * 2000.; //CR13 in table.py
76  } else if (roadClass == 2 && edge->getSpeedLimit() <= 11.) {
77  return edge->getNumLanes() * 1333.33; //CR5 in table.py
78  } else if (roadClass == 2 && edge->getSpeedLimit() > 11. && edge->getSpeedLimit() <= 16.) {
79  return edge->getNumLanes() * 1500.; //CR3 in table.py
80  } else if (roadClass == 2 && edge->getSpeedLimit() > 16.) {
81  return edge->getNumLanes() * 2000.; //CR13 in table.py
82  } else if (roadClass == 3 && edge->getSpeedLimit() <= 11.) {
83  return edge->getNumLanes() * 800.; //CR5 in table.py
84  } else if (roadClass == 3 && edge->getSpeedLimit() > 11. && edge->getSpeedLimit() <= 13.) {
85  return edge->getNumLanes() * 875.; //CR5 in table.py
86  } else if (roadClass == 3 && edge->getSpeedLimit() > 13. && edge->getSpeedLimit() <= 16.) {
87  return edge->getNumLanes() * 1500.; //CR4 in table.py
88  } else if (roadClass == 3 && edge->getSpeedLimit() > 16.) {
89  return edge->getNumLanes() * 1800.; //CR13 in table.py
90  } else if ((roadClass >= 4 || roadClass == -1) && edge->getSpeedLimit() <= 5.) {
91  return edge->getNumLanes() * 200.; //CR7 in table.py
92  } else if ((roadClass >= 4 || roadClass == -1) && edge->getSpeedLimit() > 5. && edge->getSpeedLimit() <= 7.) {
93  return edge->getNumLanes() * 412.5; //CR7 in table.py
94  } else if ((roadClass >= 4 || roadClass == -1) && edge->getSpeedLimit() > 7. && edge->getSpeedLimit() <= 9.) {
95  return edge->getNumLanes() * 600.; //CR6 in table.py
96  } else if ((roadClass >= 4 || roadClass == -1) && edge->getSpeedLimit() > 9. && edge->getSpeedLimit() <= 11.) {
97  return edge->getNumLanes() * 800.; //CR5 in table.py
98  } else if ((roadClass >= 4 || roadClass == -1) && edge->getSpeedLimit() > 11. && edge->getSpeedLimit() <= 13.) {
99  return edge->getNumLanes() * 1125.; //CR5 in table.py
100  } else if ((roadClass >= 4 || roadClass == -1) && edge->getSpeedLimit() > 13. && edge->getSpeedLimit() <= 16.) {
101  return edge->getNumLanes() * 1583.; //CR4 in table.py
102  } else if ((roadClass >= 4 || roadClass == -1) && edge->getSpeedLimit() > 16. && edge->getSpeedLimit() <= 18.) {
103  return edge->getNumLanes() * 1100.; //CR3 in table.py
104  } else if ((roadClass >= 4 || roadClass == -1) && edge->getSpeedLimit() > 18. && edge->getSpeedLimit() <= 22.) {
105  return edge->getNumLanes() * 1200.; //CR3 in table.py
106  } else if ((roadClass >= 4 || roadClass == -1) && edge->getSpeedLimit() > 22. && edge->getSpeedLimit() <= 26.) {
107  return edge->getNumLanes() * 1300.; //CR3 in table.py
108  } else if ((roadClass >= 4 || roadClass == -1) && edge->getSpeedLimit() > 26.) {
109  return edge->getNumLanes() * 1400.; //CR3 in table.py
110  }
111  return edge->getNumLanes() * 800.; //CR5 in table.py
112 }
113 
114 
115 // based on the definitions in PTV-Validate and in the VISUM-Cologne network
116 double
117 ROMAAssignments::capacityConstraintFunction(const ROEdge* edge, const double flow) const {
118  if (edge->isTazConnector()) {
119  return 0;
120  }
121  const int roadClass = myUseDefaultCapacities ? -1 : -edge->getPriority();
122  const double capacity = getCapacity(edge);
123  // TODO: differ road class 1 from the unknown road class 1!!!
124  if (edge->getNumLanes() == 0) {
125  // TAZ have no cost
126  return 0;
127  } else if (roadClass == 0 || roadClass == 1) {
128  return edge->getLength() / edge->getSpeedLimit() * (1. + 1.*(flow / (capacity * 1.3)) * 2.); //CR13 in table.py
129  } else if (roadClass == 2 && edge->getSpeedLimit() <= 11.) {
130  return edge->getLength() / edge->getSpeedLimit() * (1. + 1.*(flow / (capacity * 0.9)) * 3.); //CR5 in table.py
131  } else if (roadClass == 2 && edge->getSpeedLimit() > 11. && edge->getSpeedLimit() <= 16.) {
132  return edge->getLength() / edge->getSpeedLimit() * (1. + 1.*(flow / (capacity * 1.)) * 2.); //CR3 in table.py
133  } else if (roadClass == 2 && edge->getSpeedLimit() > 16.) {
134  return edge->getLength() / edge->getSpeedLimit() * (1. + 1.*(flow / (capacity * 1.3)) * 2.); //CR13 in table.py
135  } else if (roadClass == 3 && edge->getSpeedLimit() <= 11.) {
136  return edge->getLength() / edge->getSpeedLimit() * (1. + 1.*(flow / (capacity * 0.9)) * 3.); //CR5 in table.py
137  } else if (roadClass == 3 && edge->getSpeedLimit() > 11. && edge->getSpeedLimit() <= 13.) {
138  return edge->getLength() / edge->getSpeedLimit() * (1. + 1.*(flow / (capacity * 0.9)) * 3.); //CR5 in table.py
139  } else if (roadClass == 3 && edge->getSpeedLimit() > 13. && edge->getSpeedLimit() <= 16.) {
140  return edge->getLength() / edge->getSpeedLimit() * (1. + 1.7 * (flow / (capacity * 1.)) * 2.); //CR4 in table.py
141  } else if (roadClass == 3 && edge->getSpeedLimit() > 16.) {
142  return edge->getLength() / edge->getSpeedLimit() * (1. + 1.*(flow / (capacity * 1.3)) * 2.); //CR13 in table.py
143  } else if ((roadClass >= 4 || roadClass == -1) && edge->getSpeedLimit() <= 5.) {
144  return edge->getLength() / edge->getSpeedLimit() * (1. + 1.*(flow / (capacity * 0.5)) * 3.); //CR7 in table.py
145  } else if ((roadClass >= 4 || roadClass == -1) && edge->getSpeedLimit() > 5. && edge->getSpeedLimit() <= 7.) {
146  return edge->getLength() / edge->getSpeedLimit() * (1. + 1.*(flow / (capacity * 0.5)) * 3.); //CR7 in table.py
147  } else if ((roadClass >= 4 || roadClass == -1) && edge->getSpeedLimit() > 7. && edge->getSpeedLimit() <= 9.) {
148  return edge->getLength() / edge->getSpeedLimit() * (1. + 1.*(flow / (capacity * 0.8)) * 3.); //CR6 in table.py
149  } else if ((roadClass >= 4 || roadClass == -1) && edge->getSpeedLimit() > 9. && edge->getSpeedLimit() <= 11.) {
150  return edge->getLength() / edge->getSpeedLimit() * (1. + 1.*(flow / (capacity * 0.9)) * 3.); //CR5 in table.py
151  } else if ((roadClass >= 4 || roadClass == -1) && edge->getSpeedLimit() > 11. && edge->getSpeedLimit() <= 13.) {
152  return edge->getLength() / edge->getSpeedLimit() * (1. + 1.*(flow / (capacity * 0.9)) * 3.); //CR5 in table.py
153  } else if ((roadClass >= 4 || roadClass == -1) && edge->getSpeedLimit() > 13. && edge->getSpeedLimit() <= 16.) {
154  return edge->getLength() / edge->getSpeedLimit() * (1. + 1.7 * (flow / (capacity * 1.)) * 2.); //CR4 in table.py
155  } else if ((roadClass >= 4 || roadClass == -1) && edge->getSpeedLimit() > 16. && edge->getSpeedLimit() <= 18.) {
156  return edge->getLength() / edge->getSpeedLimit() * (1. + 1.*(flow / (capacity * 1.)) * 2.); //CR3 in table.py
157  } else if ((roadClass >= 4 || roadClass == -1) && edge->getSpeedLimit() > 18. && edge->getSpeedLimit() <= 22.) {
158  return edge->getLength() / edge->getSpeedLimit() * (1. + 1.*(flow / (capacity * 1.)) * 2.); //CR3 in table.py
159  } else if ((roadClass >= 4 || roadClass == -1) && edge->getSpeedLimit() > 22. && edge->getSpeedLimit() <= 26.) {
160  return edge->getLength() / edge->getSpeedLimit() * (1. + 1.*(flow / (capacity * 1.)) * 2.); //CR3 in table.py
161  } else if ((roadClass >= 4 || roadClass == -1) && edge->getSpeedLimit() > 26.) {
162  return edge->getLength() / edge->getSpeedLimit() * (1. + 1.*(flow / (capacity * 1.)) * 2.); //CR3 in table.py
163  }
164  return edge->getLength() / edge->getSpeedLimit() * (1. + 1.*(flow / (capacity * 0.9)) * 3.); //CR5 in table.py
165 }
166 
167 
168 bool
169 ROMAAssignments::addRoute(const ConstROEdgeVector& edges, std::vector<RORoute*>& paths, std::string routeId, double prob) {
170  std::vector<RORoute*>::iterator p;
171  for (p = paths.begin(); p != paths.end(); p++) {
172  if (edges == (*p)->getEdgeVector()) {
173  break;
174  }
175  }
176  if (p == paths.end()) {
177  paths.push_back(new RORoute(routeId, 0., prob, edges, nullptr, std::vector<SUMOVehicleParameter::Stop>()));
178  return true;
179  }
180  (*p)->addProbability(prob);
181  std::iter_swap(paths.end() - 1, p);
182  return false;
183 }
184 
185 
186 const ConstROEdgeVector
187 ROMAAssignments::computePath(ODCell* cell, const SUMOTime time, const double probability, SUMOAbstractRouter<ROEdge, ROVehicle>* router, bool setBulkMode) {
188  const ROEdge* const from = myNet.getEdge(cell->origin + (cell->originIsEdge ? "" : "-source"));
189  if (from == nullptr) {
190  throw ProcessError(TLF("Unknown origin '%'.", cell->origin));
191  }
192  const ROEdge* const to = myNet.getEdge(cell->destination + (cell->destinationIsEdge ? "" : "-sink"));
193  if (to == nullptr) {
194  throw ProcessError(TLF("Unknown destination '%'.", cell->destination));
195  }
196  ConstROEdgeVector edges;
197  if (router == nullptr) {
198  router = &myRouter;
199  }
200  if (myMaxAlternatives > 0 && (int)cell->pathsVector.size() < myMaxAlternatives) {
201  router->compute(from, to, myDefaultVehicle, time, edges);
202  if (setBulkMode) {
203  router->setBulkMode(true);
204  }
205  if (addRoute(edges, cell->pathsVector, cell->origin + cell->destination + toString(cell->pathsVector.size()), probability)) {
206  return edges;
207  }
208  } else {
209  double minCost = std::numeric_limits<double>::max();
210  RORoute* minRoute = nullptr;
211  for (RORoute* const p : cell->pathsVector) {
212  const double cost = router->recomputeCosts(edges, myDefaultVehicle, time);
213  if (cost < minCost) {
214  minCost = cost;
215  minRoute = p;
216  }
217  }
218  minRoute->addProbability(probability);
219  }
220  return ConstROEdgeVector();
221 }
222 
223 
224 void
225 ROMAAssignments::getKPaths(const int kPaths, const double penalty) {
226  for (ODCell* const c : myMatrix.getCells()) {
227  myPenalties.clear();
228  for (int k = 0; k < kPaths; k++) {
229  for (const ROEdge* const e : computePath(c)) {
230  myPenalties[e] += penalty;
231  }
232  }
233  }
234  myPenalties.clear();
235 }
236 
237 
238 void
240  const double begin = STEPS2TIME(MIN2(myBegin, myMatrix.getCells().front()->begin));
241  for (std::map<std::string, ROEdge*>::const_iterator i = myNet.getEdgeMap().begin(); i != myNet.getEdgeMap().end(); ++i) {
242  ROMAEdge* edge = static_cast<ROMAEdge*>(i->second);
243  edge->setFlow(begin, STEPS2TIME(myEnd), 0.);
244  edge->setHelpFlow(begin, STEPS2TIME(myEnd), 0.);
245  }
246 }
247 
248 
249 void
251  if (myNetloadOutput != nullptr) {
253  for (std::map<std::string, ROEdge*>::const_iterator i = myNet.getEdgeMap().begin(); i != myNet.getEdgeMap().end(); ++i) {
254  ROMAEdge* edge = static_cast<ROMAEdge*>(i->second);
255  if (edge->getFunction() == SumoXMLEdgeFunc::NORMAL) {
257  const double traveltime = edge->getTravelTime(getDefaultVehicle(), STEPS2TIME(begin));
258  const double speed = edge->getLength() / traveltime;
259  const double flow = edge->getFlow(STEPS2TIME(begin));
260  const double timeGap = STEPS2TIME(end - begin) / flow;
261  const double spaceGap = timeGap * speed;
262  const double density = 1000.0 / spaceGap;
263  const double laneDensity = density / edge->getNumLanes();
270  myNetloadOutput->writeAttr("flowCapacityRatio", 100. * flow / getCapacity(edge));
272  }
273  }
275  }
276 }
277 
278 
279 void
280 ROMAAssignments::incremental(const int numIter, const bool verbose) {
281  SUMOTime lastBegin = -1;
282  std::vector<int> intervals;
283  int count = 0;
284  for (const ODCell* const c : myMatrix.getCells()) {
285  if (c->begin != lastBegin) {
286  intervals.push_back(count);
287  lastBegin = c->begin;
288  }
289  count++;
290  }
291  lastBegin = -1;
292  for (std::vector<int>::const_iterator offset = intervals.begin(); offset != intervals.end(); offset++) {
293  std::vector<ODCell*>::const_iterator firstCell = myMatrix.getCells().begin() + (*offset);
294  std::vector<ODCell*>::const_iterator lastCell = myMatrix.getCells().end();
295  if (offset != intervals.end() - 1) {
296  lastCell = myMatrix.getCells().begin() + (*(offset + 1));
297  }
298  const SUMOTime intervalStart = (*firstCell)->begin;
299  if (verbose) {
300  WRITE_MESSAGE(" starting interval " + time2string(intervalStart));
301  }
302  std::map<const ROMAEdge*, double> loadedTravelTimes;
303  for (std::map<std::string, ROEdge*>::const_iterator i = myNet.getEdgeMap().begin(); i != myNet.getEdgeMap().end(); ++i) {
304  ROMAEdge* edge = static_cast<ROMAEdge*>(i->second);
305  if (edge->hasLoadedTravelTime(STEPS2TIME(intervalStart))) {
306  loadedTravelTimes[edge] = edge->getTravelTime(myDefaultVehicle, STEPS2TIME(intervalStart));
307  }
308  }
309  if (loadedTravelTimes.empty()) {
310  // we don't have loaded travel times for this interval but we may have set ourselves some for the interval before but no need to warn
312  }
313  for (int t = 0; t < numIter; t++) {
314  if (verbose) {
315  WRITE_MESSAGE(" starting iteration " + toString(t));
316  }
317  std::string lastOrigin = "";
318  int workerIndex = 0;
319  for (std::vector<ODCell*>::const_iterator i = firstCell; i != lastCell; i++) {
320  ODCell* const c = *i;
321  const double linkFlow = c->vehicleNumber / numIter;
322  const SUMOTime begin = myAdditiveTraffic ? myBegin : c->begin;
323 #ifdef HAVE_FOX
324  if (myNet.getThreadPool().size() > 0) {
325  if (lastOrigin != c->origin) {
326  workerIndex++;
327  if (workerIndex == myNet.getThreadPool().size()) {
328  workerIndex = 0;
329  }
330  myNet.getThreadPool().add(new RONet::BulkmodeTask(false), workerIndex);
331  lastOrigin = c->origin;
332  myNet.getThreadPool().add(new RoutingTask(*this, c, begin, linkFlow), workerIndex);
333  } else {
334  myNet.getThreadPool().add(new RoutingTask(*this, c, begin, linkFlow), workerIndex);
335  }
336  continue;
337  }
338 #endif
339  if (lastOrigin != c->origin) {
340  myRouter.setBulkMode(false);
341  lastOrigin = c->origin;
342  }
343  computePath(c, begin, linkFlow, &myRouter, true);
344  }
345 #ifdef HAVE_FOX
346  if (myNet.getThreadPool().size() > 0) {
347  myNet.getThreadPool().waitAll();
348  }
349 #endif
350  for (std::vector<ODCell*>::const_iterator i = firstCell; i != lastCell; i++) {
351  ODCell* const c = *i;
352  const double linkFlow = c->vehicleNumber / numIter;
353  const SUMOTime begin = myAdditiveTraffic ? myBegin : c->begin;
354  const SUMOTime end = myAdditiveTraffic ? myEnd : c->end;
355  const double intervalLengthInHours = STEPS2TIME(end - begin) / 3600.;
356  const ConstROEdgeVector& edges = c->pathsVector.back()->getEdgeVector();
357  for (ConstROEdgeVector::const_iterator e = edges.begin(); e != edges.end(); e++) {
358  ROMAEdge* edge = static_cast<ROMAEdge*>(myNet.getEdge((*e)->getID()));
359  const double newFlow = edge->getFlow(STEPS2TIME(begin)) + linkFlow;
360  edge->setFlow(STEPS2TIME(begin), STEPS2TIME(end), newFlow);
361  double travelTime = capacityConstraintFunction(edge, newFlow / intervalLengthInHours);
362  if (lastBegin >= 0 && myAdaptionFactor > 0.) {
363  if (loadedTravelTimes.count(edge) != 0) {
364  travelTime = loadedTravelTimes[edge] * myAdaptionFactor + (1. - myAdaptionFactor) * travelTime;
365  } else {
366  travelTime = edge->getTravelTime(myDefaultVehicle, STEPS2TIME(lastBegin)) * myAdaptionFactor + (1. - myAdaptionFactor) * travelTime;
367  }
368  }
369  edge->addTravelTime(travelTime, STEPS2TIME(begin), STEPS2TIME(end));
370  }
371  }
373  }
374  writeInterval(intervalStart, (*(lastCell - 1))->end);
375  lastBegin = intervalStart;
376  }
377 }
378 
379 
380 void
381 ROMAAssignments::sue(const int maxOuterIteration, const int maxInnerIteration, const int kPaths, const double penalty, const double tolerance, const std::string /* routeChoiceMethod */) {
382  getKPaths(kPaths, penalty);
383  std::map<const SUMOTime, SUMOTime> intervals;
384  if (myAdditiveTraffic) {
385  intervals[myBegin] = myEnd;
386  } else {
387  for (const ODCell* const c : myMatrix.getCells()) {
388  intervals[c->begin] = c->end;
389  }
390  }
391  for (int outer = 0; outer < maxOuterIteration; outer++) {
392  for (int inner = 0; inner < maxInnerIteration; inner++) {
393  for (const ODCell* const c : myMatrix.getCells()) {
394  const SUMOTime begin = myAdditiveTraffic ? myBegin : c->begin;
395  const SUMOTime end = myAdditiveTraffic ? myEnd : c->end;
396  // update path cost
397  for (std::vector<RORoute*>::const_iterator j = c->pathsVector.begin(); j != c->pathsVector.end(); ++j) {
398  RORoute* r = *j;
400  // std::cout << std::setprecision(20) << r->getID() << ":" << r->getCosts() << std::endl;
401  }
402  // calculate route utilities and probabilities
403  RouteCostCalculator<RORoute, ROEdge, ROVehicle>::getCalculator().calculateProbabilities(c->pathsVector, myDefaultVehicle, 0);
404  // calculate route flows
405  for (std::vector<RORoute*>::const_iterator j = c->pathsVector.begin(); j != c->pathsVector.end(); ++j) {
406  RORoute* r = *j;
407  const double pathFlow = r->getProbability() * c->vehicleNumber;
408  // assign edge flow deltas
409  for (ConstROEdgeVector::const_iterator e = r->getEdgeVector().begin(); e != r->getEdgeVector().end(); e++) {
410  ROMAEdge* edge = static_cast<ROMAEdge*>(myNet.getEdge((*e)->getID()));
411  edge->setHelpFlow(STEPS2TIME(begin), STEPS2TIME(end), edge->getHelpFlow(STEPS2TIME(begin)) + pathFlow);
412  }
413  }
414  }
415  // calculate new edge flows and check for stability
416  int unstableEdges = 0;
417  for (const auto& it : intervals) {
418  const double intervalLengthInHours = STEPS2TIME(it.second - it.first) / 3600.;
419  const double intBegin = STEPS2TIME(it.first);
420  const double intEnd = STEPS2TIME(it.second);
421  for (std::map<std::string, ROEdge*>::const_iterator e = myNet.getEdgeMap().begin(); e != myNet.getEdgeMap().end(); ++e) {
422  ROMAEdge* edge = static_cast<ROMAEdge*>(e->second);
423  const double oldFlow = edge->getFlow(intBegin);
424  double newFlow = oldFlow;
425  if (inner == 0 && outer == 0) {
426  newFlow += edge->getHelpFlow(intBegin);
427  } else {
428  newFlow += (edge->getHelpFlow(intBegin) - oldFlow) / (inner + 1);
429  }
430  // if not lohse:
431  if (newFlow > 0.) {
432  if (fabs(newFlow - oldFlow) / newFlow > tolerance) {
433  unstableEdges++;
434  }
435  } else if (newFlow == 0.) {
436  if (oldFlow != 0. && (fabs(newFlow - oldFlow) / oldFlow > tolerance)) {
437  unstableEdges++;
438  }
439  } else { // newFlow < 0.
440  unstableEdges++;
441  newFlow = 0.;
442  }
443  edge->setFlow(intBegin, intEnd, newFlow);
444  const double travelTime = capacityConstraintFunction(edge, newFlow / intervalLengthInHours);
445  edge->addTravelTime(travelTime, intBegin, intEnd);
446  edge->setHelpFlow(intBegin, intEnd, 0.);
447  }
448  }
449  // if stable break
450  if (unstableEdges == 0) {
451  break;
452  }
453  // additional stability check from python script: if notstable < math.ceil(net.geteffEdgeCounts()*0.005) or notstable < 3: stable = True
454  }
455  // check for a new route, if none available, break
456  // several modifications about when a route is new and when to break are in the original script
457  bool newRoute = false;
458  for (ODCell* const c : myMatrix.getCells()) {
459  newRoute |= !computePath(c).empty();
460  }
461  if (!newRoute) {
462  break;
463  }
464  }
465  // final round of assignment
466  for (const ODCell* const c : myMatrix.getCells()) {
467  // update path cost
468  for (std::vector<RORoute*>::const_iterator j = c->pathsVector.begin(); j != c->pathsVector.end(); ++j) {
469  RORoute* r = *j;
471  }
472  // calculate route utilities and probabilities
473  RouteCostCalculator<RORoute, ROEdge, ROVehicle>::getCalculator().calculateProbabilities(c->pathsVector, myDefaultVehicle, 0);
474  // calculate route flows
475  for (std::vector<RORoute*>::const_iterator j = c->pathsVector.begin(); j != c->pathsVector.end(); ++j) {
476  RORoute* r = *j;
477  r->setProbability(r->getProbability() * c->vehicleNumber);
478  }
479  }
480  for (const auto& it : intervals) {
481  writeInterval(it.first, it.second);
482  }
483 }
484 
485 
486 double
487 ROMAAssignments::getPenalizedEffort(const ROEdge* const e, const ROVehicle* const v, double t) {
488  const std::map<const ROEdge* const, double>::const_iterator i = myPenalties.find(e);
489  return i == myPenalties.end() ? e->getEffort(v, t) : e->getEffort(v, t) + i->second;
490 }
491 
492 
493 double
494 ROMAAssignments::getPenalizedTT(const ROEdge* const e, const ROVehicle* const v, double t) {
495  const std::map<const ROEdge* const, double>::const_iterator i = myPenalties.find(e);
496  return i == myPenalties.end() ? e->getTravelTime(v, t) : e->getTravelTime(v, t) + i->second;
497 }
498 
499 
500 double
501 ROMAAssignments::getTravelTime(const ROEdge* const e, const ROVehicle* const v, double t) {
502  return e->getTravelTime(v, t);
503 }
504 
505 
506 #ifdef HAVE_FOX
507 // ---------------------------------------------------------------------------
508 // ROMAAssignments::RoutingTask-methods
509 // ---------------------------------------------------------------------------
510 void
511 ROMAAssignments::RoutingTask::run(MFXWorkerThread* context) {
512  myAssign.computePath(myCell, myBegin, myLinkFlow, &static_cast<RONet::WorkerThread*>(context)->getVehicleRouter(SVC_IGNORING), mySetBulkMode);
513 }
514 #endif
long long int SUMOTime
Definition: GUI.h:35
#define WRITE_MESSAGE(msg)
Definition: MsgHandler.h:297
#define TLF(string,...)
Definition: MsgHandler.h:317
std::vector< const ROEdge * > ConstROEdgeVector
Definition: ROEdge.h:54
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
const std::string DEFAULT_VTYPE_ID
@ SVC_IGNORING
vehicles ignoring classes
@ SUMO_TAG_INTERVAL
an aggreagated-output interval
@ SUMO_TAG_EDGE
begin/end of the description of an edge
@ SUMO_ATTR_SPEED
@ SUMO_ATTR_TRAVELTIME
@ SUMO_ATTR_BEGIN
weights: time range begin
@ SUMO_ATTR_SPEEDREL
@ SUMO_ATTR_END
weights: time range end
@ SUMO_ATTR_ENTERED
@ SUMO_ATTR_ID
@ SUMO_ATTR_LANEDENSITY
@ SUMO_ATTR_DENSITY
T MIN2(T a, T b)
Definition: StdDefs.h:76
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
A thread repeatingly calculating incoming tasks.
const std::string & getID() const
Returns the id.
Definition: Named.h:74
IDMap::const_iterator begin() const
Returns a reference to the begin iterator for the internal map.
IDMap::const_iterator end() const
Returns a reference to the end iterator for the internal map.
An O/D (origin/destination) matrix.
Definition: ODMatrix.h:68
const std::vector< ODCell * > & getCells()
Definition: ODMatrix.h:248
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:61
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:254
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
A basic edge for routing applications.
Definition: ROEdge.h:70
bool hasLoadedTravelTime(double time) const
Returns whether a travel time for this edge was loaded.
Definition: ROEdge.cpp:184
int getNumLanes() const
Returns the number of lanes this edge has.
Definition: ROEdge.h:260
int getPriority() const
get edge priority (road class)
Definition: ROEdge.h:508
bool isTazConnector() const
Definition: ROEdge.h:168
double getSpeedLimit() const
Returns the speed allowed on this edge.
Definition: ROEdge.h:234
static void disableTimelineWarning()
Definition: ROEdge.h:500
SumoXMLEdgeFunc getFunction() const
Returns the function of the edge.
Definition: ROEdge.h:203
double getTravelTime(const ROVehicle *const veh, double time) const
Returns the travel time for this edge.
Definition: ROEdge.cpp:190
void addTravelTime(double value, double timeBegin, double timeEnd)
Adds a travel time value.
Definition: ROEdge.cpp:147
double getEffort(const ROVehicle *const veh, double time) const
Returns the effort for this edge.
Definition: ROEdge.cpp:154
double getLength() const
Returns the length of the edge.
Definition: ROEdge.h:219
const ConstROEdgeVector computePath(ODCell *cell, const SUMOTime time=0, const double probability=0., SUMOAbstractRouter< ROEdge, ROVehicle > *router=nullptr, bool setBulkMode=false)
const double myAdaptionFactor
ODMatrix & myMatrix
void sue(const int maxOuterIteration, const int maxInnerIteration, const int kPaths, const double penalty, const double tolerance, const std::string routeChoiceMethod)
void getKPaths(const int kPaths, const double penalty)
get the k shortest paths
static double getPenalizedEffort(const ROEdge *const e, const ROVehicle *const v, double t)
Returns the effort to pass an edge including penalties.
void incremental(const int numIter, const bool verbose)
double capacityConstraintFunction(const ROEdge *edge, const double flow) const
double getCapacity(const ROEdge *edge) const
const bool myAdditiveTraffic
const int myMaxAlternatives
void writeInterval(const SUMOTime begin, const SUMOTime end)
ROMAAssignments(const SUMOTime begin, const SUMOTime end, const bool additiveTraffic, const double adaptionFactor, const int maxAlternatives, const bool defaultCapacities, RONet &net, ODMatrix &matrix, SUMOAbstractRouter< ROEdge, ROVehicle > &router, OutputDevice *netloadOutput)
Constructor.
ROVehicle * myDefaultVehicle
const SUMOTime myEnd
OutputDevice *const myNetloadOutput
static double getPenalizedTT(const ROEdge *const e, const ROVehicle *const v, double t)
Returns the traveltime on an edge including penalties.
static double getTravelTime(const ROEdge *const e, const ROVehicle *const v, double t)
Returns the traveltime on an edge without penalties.
static std::map< const ROEdge *const, double > myPenalties
SUMOAbstractRouter< ROEdge, ROVehicle > & myRouter
ROVehicle * getDefaultVehicle() const
const bool myUseDefaultCapacities
bool addRoute(const ConstROEdgeVector &edges, std::vector< RORoute * > &paths, std::string routeId, double prob)
add a route and check for duplicates
const SUMOTime myBegin
~ROMAAssignments()
Destructor.
A basic edge for routing applications.
Definition: ROMAEdge.h:55
double getHelpFlow(const double time) const
Definition: ROMAEdge.h:91
void setFlow(const double begin, const double end, const double flow)
Definition: ROMAEdge.h:79
double getFlow(const double time) const
Definition: ROMAEdge.h:83
void setHelpFlow(const double begin, const double end, const double flow)
Definition: ROMAEdge.h:87
The router's network representation.
Definition: RONet.h:62
SUMOVTypeParameter * getVehicleTypeSecure(const std::string &id)
Retrieves the named vehicle type.
Definition: RONet.cpp:364
ROEdge * getEdge(const std::string &name) const
Retrieves an edge from the network.
Definition: RONet.h:157
const NamedObjectCont< ROEdge * > & getEdgeMap() const
Definition: RONet.h:422
A complete router's route.
Definition: RORoute.h:52
void setProbability(double prob)
Sets the probability of the route.
Definition: RORoute.cpp:70
double getProbability() const
Returns the probability the driver will take this route with.
Definition: RORoute.h:120
void addProbability(double prob)
add additional vehicles/probability
Definition: RORoute.cpp:96
const ConstROEdgeVector & getEdgeVector() const
Returns the list of edges this route consists of.
Definition: RORoute.h:152
void setCosts(double costs)
Sets the costs of the route.
Definition: RORoute.cpp:64
A vehicle as used by router.
Definition: ROVehicle.h:50
static RouteCostCalculator< R, E, V > & getCalculator()
virtual void setBulkMode(const bool mode)
virtual void reset(const V *const vehicle)
reset internal caches, used by CHRouter
virtual bool compute(const E *from, const E *to, const V *const vehicle, SUMOTime msTime, std::vector< const E * > &into, bool silent=false)=0
Builds the route between the given edges using the minimum effort at the given time The definition of...
virtual double recomputeCosts(const std::vector< const E * > &edges, const V *const v, SUMOTime msTime, double *lengthp=nullptr) const
Structure representing possible vehicle parameter.
A single O/D-matrix cell.
Definition: ODCell.h:48
std::string destination
Name of the destination district.
Definition: ODCell.h:62
std::string origin
Name of the origin district.
Definition: ODCell.h:59
std::vector< RORoute * > pathsVector
the list of paths / routes
Definition: ODCell.h:68
double vehicleNumber
The number of vehicles.
Definition: ODCell.h:50
bool originIsEdge
the origin "district" is an edge id
Definition: ODCell.h:74
SUMOTime end
The end time this cell describes.
Definition: ODCell.h:56
SUMOTime begin
The begin time this cell describes.
Definition: ODCell.h:53
bool destinationIsEdge
the destination "district" is an edge id
Definition: ODCell.h:77