Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
MSStopOptimizer.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-2025 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/****************************************************************************/
18// Optimizes prioritized stops
19/****************************************************************************/
20#include <config.h>
21#include <queue>
22#include "MSLane.h"
23#include "MSEdge.h"
24#include "MSStoppingPlace.h"
25#include "MSStopOptimizer.h"
26
27//#define DEBUG_OPTIMIZE_SKIPPED
28
29// ===========================================================================
30// method definitions
31// ===========================================================================
32
34MSStopOptimizer::optimizeSkipped(const MSEdge* source, double sourcePos, std::vector<StopEdgeInfo>& stops, ConstMSEdgeVector edges) const {
35 // intial solution is an upper bound on the acceptle total skipped priority
36 double minSkipped = 0;
37 double maxReached = 0;
38 double totalPrio = 0;
39 std::vector<StopEdgeInfo> bestStops = stops;
40 std::shared_ptr<StopPathNode> bestNode = nullptr;
41 double bestCost = myRouter.recomputeCostsPos(edges, myVehicle, sourcePos, 0, myT);
42 std::vector<int> skipped;
43
44 // each upcoming stop is part of a graph where we can start to search for a
45 // better solution. We evaluate followers lazily and prune based on the best
46 // solution already found
47 std::priority_queue<std::shared_ptr<StopPathNode>, std::vector<std::shared_ptr<StopPathNode> >, spnCompare> queue;
48
49 auto prev = std::make_shared<StopPathNode>(*this, StopEdgeInfo(source, -1, SIMSTEP, sourcePos));
50 prev->stopIndex = -1;
51 prev->cost = bestCost;
52 prev->checked = true;
53 //std::cout << " i=-1 e=" << prev->edge->getID() << " sp=" << prev->skippedPrio << " rp=" << prev->reachedPrio << "\n";
54 queue.push(prev);
55
56 for (int i = 0; i < (int)stops.size(); i++) {
57 const StopEdgeInfo& stop = stops[i];
58 if (stop.skipped) {
59 skipped.push_back(i);
60 minSkipped += stops[i].priority;
61 } else {
62 maxReached += stop.priority;
63 auto ptr = std::make_shared<StopPathNode>(*this, stop);
64 ptr->skippedPrio = minSkipped;
65 ptr->reachedPrio = prev->reachedPrio + stop.priority;
66 ptr->prev = prev;
67 ptr->stopIndex = i;
68 prev = ptr;
69 queue.push(ptr);
70 }
71 totalPrio += stop.priority;
72 //std::cout << " i=" << i << " e=" << ptr->edge->getID() << " sp=" << ptr->skippedPrio << " rp=" << ptr->reachedPrio << "\n";
73 }
74 bestNode = prev;
75#ifdef DEBUG_OPTIMIZE_SKIPPED
76 std::cout << SIMTIME << " optimizeSkipped veh=" << myVehicle->getID()
77 << " source=" << source->getID() << " sourcePos=" << sourcePos
78 << " nStops=" << stops.size() << " skipped=" << toString(skipped) << " qSize=" << queue.size()
79 << " minSkipped=" << minSkipped << " maxReached=" << maxReached << "\n";
80#endif
81
82 while (!queue.empty()) {
83 auto ptr = queue.top();
84 queue.pop();
85#ifdef DEBUG_OPTIMIZE_SKIPPED
86 std::cout << " qSize=" << queue.size() << " topNode edge=" << ptr->edge->getID()
87 << " name='" << ptr->nameTag.first << "' skippedPrio=" << ptr->skippedPrio
88 << " trackChanges=" << ptr->trackChanges
89 << " cost=" << ptr->cost
90 << " reachedPrio=" << ptr->reachedPrio
91 << " stopIndex=" << ptr->stopIndex << "\n";
92#endif
93 auto succ = ptr->getSuccessor(stops, minSkipped);
94 if (ptr->skippedPrio < minSkipped && ptr->reachedPrio > maxReached) {
95 minSkipped = MIN2(minSkipped, totalPrio - ptr->reachedPrio);
96 maxReached = ptr->reachedPrio;
97 bestNode = ptr;
98#ifdef DEBUG_OPTIMIZE_SKIPPED
99 std::cout << " newBest minSkipped=" << minSkipped << " maxReached=" << maxReached << "\n";
100#endif
101 }
102 if (succ != nullptr) {
103 queue.push(ptr);
104 queue.push(succ);
105 }
106 }
107 for (auto& stop : stops) {
108 // init true and later set false for all used stops
109 if (!stop.skipped) {
110 stop.backtracked = true;
111 stop.skipped = true;
112 }
113 }
114 ConstMSEdgeVector bestEdges;
115 while (bestNode != nullptr && bestNode->stopIndex >= 0) {
116 stops[bestNode->stopIndex].skipped = false;
117 stops[bestNode->stopIndex].backtracked = false;
118 stops[bestNode->stopIndex].origEdge = bestNode->origEdge;
119 if (!bestEdges.empty() && !bestNode->edges.empty()) {
120 bestNode->edges.pop_back();
121 }
122 bestEdges.insert(bestEdges.begin(), bestNode->edges.begin(), bestNode->edges.end());
123 bestNode = bestNode->prev;
124 }
125 //std::cout << "oldEdges=" << toString(edges) << "\nnewEdges=" << toString(bestEdges) << "\n";
126 return bestEdges;
127}
128
129
130std::shared_ptr<MSStopOptimizer::StopPathNode>
131MSStopOptimizer::StopPathNode::getSuccessor(const std::vector<StopEdgeInfo>& stops, double minSkipped) {
132 if (!checked) {
133 checked = true;
134 // @todo caching, bulk-routing
135 if (!so.reachableInTime(prev->edge, prev->pos, edge, pos, arrival, edges)) {
136#ifdef DEBUG_OPTIMIZE_SKIPPED
137 std::cout << " prevIndex=" << prev->stopIndex << " prevEdge=" << prev->edge->getID() << " i=" << stopIndex << " edge=" << edge->getID() << " unreachable\n";
138#endif
139 return nullptr;
140 } else {
141#ifdef DEBUG_OPTIMIZE_SKIPPED
142 std::cout << " prevIndex=" << prev->stopIndex << " prevEdge=" << prev->edge->getID() << " i=" << stopIndex << " edge=" << edge->getID() << " reached with edges=" << toString(edges) << "\n";
143#endif
144 }
146 }
147 int nextIndex = stopIndex + numSkipped + 1;
148 while (nextIndex < (int)stops.size()) {
149 const StopEdgeInfo& next = stops[nextIndex];
150 if (next.priority < 0) {
151 // next stop can neither be skipped nor changed
152#ifdef DEBUG_OPTIMIZE_SKIPPED
153 std::cout << " i=" << stopIndex << " next=" << nextIndex << " unskipped\n";
154#endif
155 return nullptr;
156 }
157 const std::vector<MSStoppingPlace*>& alternatives = MSNet::getInstance()->getStoppingPlaceAlternatives(next.nameTag.first, next.nameTag.second);
158#ifdef DEBUG_OPTIMIZE_SKIPPED
159 std::cout << " i=" << stopIndex << " next=" << nextIndex << " numSkipped=" << numSkipped << " altIndex=" << altIndex << " nAlt=" << alternatives.size() << "\n";
160#endif
161 if (alternatives.empty() && altIndex == 0 && numSkipped > 0) {
162 altIndex++;
163 auto succ = std::make_shared<StopPathNode>(so, next);
164 succ->skippedPrio = skippedPrio;
165 succ->reachedPrio = reachedPrio;
166 succ->trackChanges = trackChanges;
167 succ->prev = shared_from_this();
168 succ->stopIndex = nextIndex;
169 return succ;
170 }
171 while (altIndex < (int)alternatives.size()) {
172 MSStoppingPlace* alt = alternatives[altIndex];
173 const MSEdge* altEdge = &alt->getLane().getEdge();
174 altIndex++;
175 if ((altEdge == edge && numSkipped == 0) || !alt->getLane().allowsVehicleClass(so.myVehicle->getVClass())) {
176 continue;
177 }
178 auto succ = std::make_shared<StopPathNode>(so, next);
179 if (altEdge != succ->edge) {
180 succ->origEdge = succ->edge;
181 succ->edge = altEdge;
182 }
183 succ->pos = alt->getEndLanePosition();
184 succ->skippedPrio = skippedPrio;
185 succ->reachedPrio = reachedPrio;
186 succ->trackChanges = trackChanges + 1;
187 succ->prev = shared_from_this();
188 succ->stopIndex = nextIndex;
189 return succ;
190 }
191 skippedPrio =+ next.priority;
192 if (skippedPrio >= minSkipped) {
193 // cannot improve on current best solution
194#ifdef DEBUG_OPTIMIZE_SKIPPED
195 std::cout << " i=" << stopIndex << " next=" << nextIndex << " skippedPrio=" << skippedPrio << " minSkipped=" << minSkipped << " pruned\n";
196#endif
197 return nullptr;
198 }
199 nextIndex++;
200 altIndex = 0;
201 numSkipped++;
202 }
203#ifdef DEBUG_OPTIMIZE_SKIPPED
204 std::cout << " i=" << stopIndex << " noSuccessors\n";
205#endif
206 return nullptr;
207}
208
209
210bool
211MSStopOptimizer::reachableInTime(const MSEdge* from, double fromPos,
212 const MSEdge* to, double toPos,
213 SUMOTime arrival,
214 ConstMSEdgeVector& into) const {
215 myRouter.compute(from, fromPos, to, toPos, myVehicle, myT, into, true);
216 if (into.size() > 0) {
217 SUMOTime cost = TIME2STEPS(myRouter.recomputeCostsPos(into, myVehicle, fromPos, toPos, myT));
218 //std::cout << " from=" << from->getID() << " fromPos=" << fromPos << " to=" << to->getID() << " toPos=" << toPos << " t=" << myT << " cost=" << cost << " arrival=" << arrival << " maxDelay=" << myMaxDelay << "\n";
219 if (myT + cost <= arrival + myMaxDelay) {
220 return true;
221 }
222 }
223 return false;
224}
225
226
227/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
std::vector< const MSEdge * > ConstMSEdgeVector
Definition MSEdge.h:74
MSBaseVehicle::StopEdgeInfo StopEdgeInfo
#define SIMSTEP
Definition SUMOTime.h:61
#define SIMTIME
Definition SUMOTime.h:62
#define TIME2STEPS(x)
Definition SUMOTime.h:57
T MIN2(T a, T b)
Definition StdDefs.h:80
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
SUMOVehicleClass getVClass() const
Returns the vehicle's access class.
A road/street connecting two junctions.
Definition MSEdge.h:77
bool allowsVehicleClass(SUMOVehicleClass vclass) const
Definition MSLane.h:932
MSEdge & getEdge() const
Returns the lane's edge.
Definition MSLane.h:769
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:187
const std::vector< MSStoppingPlace * > & getStoppingPlaceAlternatives(const std::string &name, SumoXMLTag category) const
Definition MSNet.cpp:1502
SUMOAbstractRouter< MSEdge, SUMOVehicle > & myRouter
ConstMSEdgeVector optimizeSkipped(const MSEdge *source, double sourcePos, std::vector< StopEdgeInfo > &stops, ConstMSEdgeVector edges) const
bool reachableInTime(const MSEdge *from, double fromPos, const MSEdge *to, double toPos, SUMOTime arrival, ConstMSEdgeVector &into) const
MSBaseVehicle * myVehicle
A lane area vehicles can halt at.
double getEndLanePosition() const
Returns the end position of this stop.
const MSLane & getLane() const
Returns the lane this stop is located at.
const std::string & getID() const
Returns the id.
Definition Named.h:74
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...
double recomputeCostsPos(const std::vector< const E * > &edges, const V *const v, double fromPos, double toPos, SUMOTime msTime, double *lengthp=nullptr) const
std::pair< std::string, SumoXMLTag > nameTag
optional info about stopping place
const MSStopOptimizer & so
std::shared_ptr< StopPathNode > prev
std::shared_ptr< StopPathNode > getSuccessor(const std::vector< StopEdgeInfo > &stops, double minSkipped)