Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
SUMOAbstractRouter.h
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2006-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/****************************************************************************/
20// An abstract router base class
21/****************************************************************************/
22#pragma once
23#include <config.h>
24
25#include <string>
26#include <vector>
27#include <algorithm>
28#include <iterator>
29#include <assert.h>
34//#define ROUTER_DEBUG_HINT
35//#define ROUTER_DEBUG_COND (true)
36
37
38// ===========================================================================
39// class definitions
40// ===========================================================================
45template<class E, class V>
47public:
53 class EdgeInfo {
54 public:
56 EdgeInfo(const E* const e)
57 : edge(e), effort(std::numeric_limits<double>::max()),
58 heuristicEffort(std::numeric_limits<double>::max()),
59 leaveTime(0.), prev(nullptr), visited(false), prohibited(false), prohibitionEnd(0) {}
60
62 const E* const edge;
63
65 double effort;
66
68 // only used by A*
70
72 double leaveTime;
73
75 const EdgeInfo* prev;
76
78 bool visited;
79
82
85
86 inline void reset() {
87 effort = std::numeric_limits<double>::max();
88 heuristicEffort = std::numeric_limits<double>::max();
89 visited = false;
90 }
91
92 };
93
95 typedef double(* Operation)(const E* const, const V* const, double);
96
98 typedef std::map<const E*, double> Prohibitions;
99
101 SUMOAbstractRouter(const std::string& type, bool unbuildIsWarning, Operation operation, Operation ttOperation,
102 const bool havePermissions, const bool haveRestrictions) :
103 myErrorMsgHandler(unbuildIsWarning ? MsgHandler::getWarningInstance() : MsgHandler::getErrorInstance()),
104 myOperation(operation), myTTOperation(ttOperation),
105 myBulkMode(false),
106 myAutoBulkMode(false),
107 myAmClean(true),
108 myHavePermissions(havePermissions),
109 myHaveRestrictions(haveRestrictions),
110 myType(type),
111 myQueryVisits(0),
112 myNumQueries(0),
114 myQueryTimeSum(0) {
115 }
116
131
132
133
136 if (myNumQueries > 0) {
137 WRITE_MESSAGE(myType + " answered " + toString(myNumQueries) + " queries and explored " + toString((double)myQueryVisits / (double)myNumQueries) + " edges on average.");
138 WRITE_MESSAGE(myType + " spent " + elapsedMs2string(myQueryTimeSum) + " answering queries (" + toString((double)myQueryTimeSum / (double)myNumQueries) + "ms on average).");
139 }
140 }
141
142 virtual SUMOAbstractRouter* clone() = 0;
143
144 inline void init(const int edgeID, const SUMOTime msTime) {
145// if (!myAmClean) {
146 // all EdgeInfos touched in the previous query are either in myFrontierList or myFound: clean those up
147 for (auto& edgeInfo : myFrontierList) {
148 edgeInfo->reset();
149 }
150 myFrontierList.clear();
151 for (auto& edgeInfo : myFound) {
152 edgeInfo->reset();
153 }
154 myFound.clear();
155 if (edgeID > -1) {
156 // add begin node
157 auto& fromInfo = myEdgeInfos[edgeID];
158 fromInfo.effort = 0.;
159 fromInfo.heuristicEffort = 0.;
160 fromInfo.prev = nullptr;
161 fromInfo.leaveTime = STEPS2TIME(msTime);
162 myFrontierList.push_back(&fromInfo);
163 }
164 myAmClean = true;
165// }
166 }
167
169 virtual void reset(const V* const vehicle) {
170 UNUSED_PARAMETER(vehicle);
171 }
172
173 const std::string& getType() const {
174 return myType;
175 }
176
177 inline const typename SUMOAbstractRouter<E, V>::EdgeInfo& getEdgeInfo(int index) const {
178 return myEdgeInfos[index];
179 }
180
183 virtual bool compute(const E* from, const E* to, const V* const vehicle,
184 SUMOTime msTime, std::vector<const E*>& into, bool silent = false) = 0;
185
186
191 inline bool compute(
192 const E* from, double fromPos,
193 const E* to, double toPos,
194 const V* const vehicle,
195 SUMOTime msTime, std::vector<const E*>& into, bool silent = false) {
196 if (from != to || fromPos <= toPos) {
197 return compute(from, to, vehicle, msTime, into, silent);
198 } else {
199 return computeLooped(from, to, vehicle, msTime, into, silent);
200 }
201 }
202
203
206 inline bool computeLooped(const E* from, const E* to, const V* const vehicle,
207 SUMOTime msTime, std::vector<const E*>& into, bool silent = false) {
208 if (from != to) {
209 return compute(from, to, vehicle, msTime, into, silent);
210 }
211 double minEffort = std::numeric_limits<double>::max();
212 std::vector<const E*> best;
213 const SUMOVehicleClass vClass = vehicle == 0 ? SVC_IGNORING : vehicle->getVClass();
214 for (const std::pair<const E*, const E*>& follower : from->getViaSuccessors(vClass)) {
215 std::vector<const E*> tmp;
216 compute(follower.first, to, vehicle, msTime, tmp, true);
217 if (tmp.size() > 0) {
218 double effort = recomputeCosts(tmp, vehicle, msTime);
219 if (effort < minEffort) {
220 minEffort = effort;
221 best = tmp;
222 }
223 }
224 }
225 if (minEffort != std::numeric_limits<double>::max()) {
226 into.push_back(from);
227 std::copy(best.begin(), best.end(), std::back_inserter(into));
228 return true;
229 } else if (!silent && myErrorMsgHandler != nullptr) {
230 myErrorMsgHandler->informf(TL("No connection between edge '%' and edge '%' found."), from->getID(), to->getID());
231 }
232 return false;
233 }
234
235 inline bool isProhibited(const E* const edge, const V* const vehicle) const {
236 return (myHavePermissions && edge->prohibits(vehicle)) || (myHaveRestrictions && edge->restricts(vehicle));
237 }
238
239 inline double getTravelTime(const E* const e, const V* const v, const double t, const double effort) const {
240 return myTTOperation == nullptr ? effort : (*myTTOperation)(e, v, t);
241 }
242
243 inline void updateViaEdgeCost(const E* viaEdge, const V* const v, double& time, double& effort, double& length) const {
244 while (viaEdge != nullptr && viaEdge->isInternal()) {
245 const double viaEffortDelta = this->getEffort(viaEdge, v, time);
246 time += getTravelTime(viaEdge, v, time, viaEffortDelta);
247 effort += viaEffortDelta;
248 length += viaEdge->getLength();
249 viaEdge = viaEdge->getViaSuccessors().front().second;
250 }
251 }
252
253 inline void updateViaCost(const E* const prev, const E* const e, const V* const v, double& time, double& effort, double& length) const {
254 if (prev != nullptr) {
255 for (const std::pair<const E*, const E*>& follower : prev->getViaSuccessors()) {
256 if (follower.first == e) {
257 updateViaEdgeCost(follower.second, v, time, effort, length);
258 break;
259 }
260 }
261 }
262 const double effortDelta = this->getEffort(e, v, time);
263 effort += effortDelta;
264 time += getTravelTime(e, v, time, effortDelta);
265 length += e->getLength();
266 }
267
268 bool isValid(const std::vector<const E*>& edges, const V* const v) const {
269 for (const E* const e : edges) {
270 if (isProhibited(e, v)) {
271 return false;
272 }
273 }
274 return true;
275 }
276
277 virtual double recomputeCosts(const std::vector<const E*>& edges, const V* const v, SUMOTime msTime, double* lengthp = nullptr) const {
278 double time = STEPS2TIME(msTime);
279 double effort = 0.;
280 double length = 0.;
281 if (lengthp == nullptr) {
282 lengthp = &length;
283 } else {
284 *lengthp = 0.;
285 }
286 const E* prev = nullptr;
287 for (const E* const e : edges) {
288 updateViaCost(prev, e, v, time, effort, *lengthp);
289 prev = e;
290 }
291 return effort;
292 }
293
294
295 inline double recomputeCostsPos(const std::vector<const E*>& edges, const V* const v, double fromPos, double toPos, SUMOTime msTime, double* lengthp = nullptr) const {
296 double effort = recomputeCosts(edges, v, msTime, lengthp);
297 if (!edges.empty()) {
298 double firstEffort = this->getEffort(edges.front(), v, STEPS2TIME(msTime));
299 double lastEffort = this->getEffort(edges.back(), v, STEPS2TIME(msTime));
300 effort -= firstEffort * fromPos / edges.front()->getLength();
301 effort -= lastEffort * (edges.back()->getLength() - toPos) / edges.back()->getLength();
302 }
303 return effort;
304 }
305
306
307 inline double setHint(const typename std::vector<const E*>::const_iterator routeBegin, const typename std::vector<const E*>::const_iterator routeEnd, const V* const v, SUMOTime msTime) {
308 double time = STEPS2TIME(msTime);
309 double effort = 0.;
310 double length = 0.;
311 const EdgeInfo* prev = &myEdgeInfos[(*routeBegin)->getNumericalID()];
312 init((*routeBegin)->getNumericalID(), msTime);
313 for (auto e = routeBegin + 1; e != routeEnd; ++e) {
314 if (isProhibited(*e, v)) {
315 return -1;
316 }
317 auto& edgeInfo = myEdgeInfos[(*e)->getNumericalID()];
318 edgeInfo.heuristicEffort = effort;
319 edgeInfo.prev = prev;
320 updateViaCost(prev->edge, *e, v, time, effort, length);
321 edgeInfo.effort = effort;
322 edgeInfo.leaveTime = time;
323 myFound.push_back(&edgeInfo);
324 prev = &edgeInfo;
325#ifdef ROUTER_DEBUG_HINT
326 if (ROUTER_DEBUG_COND) {
327 std::cout << "DEBUG: hit=" << (*e)->getID()
328 << " TT=" << edgeInfo.effort
329 << " EF=" << this->getEffort(*e, v, edgeInfo.leaveTime)
330 << " HT=" << edgeInfo.heuristicEffort << "\n";
331 }
332#endif
333 }
334 return effort;
335 }
336
337
338 inline double getEffort(const E* const e, const V* const v, double t) const {
339 if (this->myProhibited.size() > 0 && myEdgeInfos.size() > 0 && myEdgeInfos[e->getNumericalID()].prohibitionEnd > 0) {
340 // pass edge after prohibition ends
341 return (myEdgeInfos[e->getNumericalID()].prohibitionEnd - t) + (*myOperation)(e, v, myEdgeInfos[e->getNumericalID()].prohibitionEnd);
342 } else {
343 return (*myOperation)(e, v, t);
344 }
345 }
346
351
352 inline void endQuery(int visits) {
353 myQueryVisits += visits;
355 }
356
357 virtual void setBulkMode(const bool mode) {
358 myBulkMode = mode;
359 }
360
361 inline void setAutoBulkMode(const bool mode) {
362 myAutoBulkMode = mode;
363 }
364
365 virtual void prohibit(const Prohibitions& toProhibit) {
366 for (auto item : this->myProhibited) {
367 myEdgeInfos[item.first->getNumericalID()].prohibited = false;
368 myEdgeInfos[item.first->getNumericalID()].prohibitionEnd = 0;
369 }
370 for (auto item : toProhibit) {
371 if (item.second >= 0 && item.second != std::numeric_limits<double>::max()) {
372 myEdgeInfos[item.first->getNumericalID()].prohibitionEnd = item.second;
373 } else {
374 myEdgeInfos[item.first->getNumericalID()].prohibited = true;
375 }
376 }
377 this->myProhibited = toProhibit;
378 }
379
380
382 void buildPathFrom(const typename SUMOAbstractRouter<E, V>::EdgeInfo* rbegin, std::vector<const E*>& edges) {
383 std::vector<const E*> tmp;
384 while (rbegin != nullptr) {
385 tmp.push_back(rbegin->edge);
386 rbegin = rbegin->prev;
387 }
388 std::copy(tmp.rbegin(), tmp.rend(), std::back_inserter(edges));
389 }
390
391protected:
394
397
400
403
406
409
412
415
418
420 std::vector<typename SUMOAbstractRouter<E, V>::EdgeInfo> myEdgeInfos;
421
423 std::vector<typename SUMOAbstractRouter<E, V>::EdgeInfo*> myFrontierList;
425 std::vector<typename SUMOAbstractRouter<E, V>::EdgeInfo*> myFound;
426
427private:
429 const std::string myType;
430
432 long long int myQueryVisits;
433 long long int myNumQueries;
435 long long int myQueryStartTime;
436 long long int myQueryTimeSum;
437
438private:
441};
long long int SUMOTime
Definition GUI.h:36
#define WRITE_MESSAGE(msg)
Definition MsgHandler.h:288
#define TL(string)
Definition MsgHandler.h:304
std::string elapsedMs2string(long long int t)
convert ms to string for log output
Definition SUMOTime.cpp:145
#define STEPS2TIME(x)
Definition SUMOTime.h:55
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ SVC_IGNORING
vehicles ignoring classes
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
bool visited
whether the edge was already evaluated
EdgeInfo(const E *const e)
Constructor.
const E *const edge
The current edge.
double leaveTime
The time the vehicle leaves the edge.
double effort
Effort to reach the edge.
bool prohibited
whether the edge is currently not allowed
const EdgeInfo * prev
The previous edge.
double heuristicEffort
Estimated effort to reach the edge (effort + lower bound on remaining effort).
double prohibitionEnd
the time at which a temporary prohibitione ends
std::map< const MSEdge *, double > Prohibitions
bool isProhibited(const E *const edge, const V *const vehicle) const
bool computeLooped(const E *from, const E *to, const V *const vehicle, SUMOTime msTime, std::vector< const E * > &into, bool silent=false)
Builds the route between the given edges using the minimum effort at the given time if from == to,...
virtual SUMOAbstractRouter * clone()=0
virtual void setBulkMode(const bool mode)
SUMOAbstractRouter & operator=(const SUMOAbstractRouter &s)=delete
Invalidated assignment operator.
std::vector< typename SUMOAbstractRouter< MSEdge, SUMOVehicle >::EdgeInfo > myEdgeInfos
bool compute(const E *from, double fromPos, const E *to, double toPos, const V *const vehicle, SUMOTime msTime, std::vector< const E * > &into, bool silent=false)
Builds the route between the given edges using the minimum effort at the given time,...
SUMOAbstractRouter(SUMOAbstractRouter *other)
Copy Constructor.
double(* Operation)(const MSEdge *const, const SUMOVehicle *const, double)
double getTravelTime(const E *const e, const V *const v, const double t, const double effort) const
void updateViaCost(const E *const prev, const E *const e, const V *const v, double &time, double &effort, double &length) const
virtual void reset(const V *const vehicle)
reset internal caches, used by CHRouter
const std::string & getType() const
double getEffort(const E *const e, const V *const v, double t) const
SUMOAbstractRouter(const std::string &type, bool unbuildIsWarning, Operation operation, Operation ttOperation, const bool havePermissions, const bool haveRestrictions)
Constructor.
virtual void prohibit(const Prohibitions &toProhibit)
void updateViaEdgeCost(const E *viaEdge, const V *const v, double &time, double &effort, double &length) const
double setHint(const typename std::vector< const E * >::const_iterator routeBegin, const typename std::vector< const E * >::const_iterator routeEnd, const V *const v, SUMOTime msTime)
void init(const int edgeID, const SUMOTime msTime)
void setAutoBulkMode(const bool mode)
bool isValid(const std::vector< const E * > &edges, const V *const v) const
const SUMOAbstractRouter< E, V >::EdgeInfo & getEdgeInfo(int index) const
void buildPathFrom(const typename SUMOAbstractRouter< E, V >::EdgeInfo *rbegin, std::vector< const E * > &edges)
Builds the path from marked edges.
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
void endQuery(int visits)
virtual ~SUMOAbstractRouter()
Destructor.
std::vector< typename SUMOAbstractRouter< MSEdge, SUMOVehicle >::EdgeInfo * > myFrontierList
double recomputeCostsPos(const std::vector< const E * > &edges, const V *const v, double fromPos, double toPos, SUMOTime msTime, double *lengthp=nullptr) const
std::vector< typename SUMOAbstractRouter< MSEdge, SUMOVehicle >::EdgeInfo * > myFound
static long getCurrentMillis()
Returns the current time in milliseconds.
Definition SysUtils.cpp:44
#define UNUSED_PARAMETER(x)
Definition json.hpp:4471