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 myHavePermissions(havePermissions),
108 myHaveRestrictions(haveRestrictions),
109 myType(type),
110 myQueryVisits(0),
111 myNumQueries(0),
113 myQueryTimeSum(0) {
114 }
115
129
130
131
134 if (myNumQueries > 0) {
135 WRITE_MESSAGE(myType + " answered " + toString(myNumQueries) + " queries and explored " + toString((double)myQueryVisits / (double)myNumQueries) + " edges on average.");
136 WRITE_MESSAGE(myType + " spent " + elapsedMs2string(myQueryTimeSum) + " answering queries (" + toString((double)myQueryTimeSum / (double)myNumQueries) + "ms on average).");
137 }
138 }
139
140 virtual SUMOAbstractRouter* clone() = 0;
141
142 inline void init(const int edgeID, const SUMOTime msTime) {
143// if (!myAmClean) {
144 // all EdgeInfos touched in the previous query are either in myFrontierList or myFound: clean those up
145 for (auto& edgeInfo : myFrontierList) {
146 edgeInfo->reset();
147 }
148 myFrontierList.clear();
149 for (auto& edgeInfo : myFound) {
150 edgeInfo->reset();
151 }
152 myFound.clear();
153 if (edgeID > -1) {
154 // add begin node
155 auto& fromInfo = myEdgeInfos[edgeID];
156 fromInfo.effort = 0.;
157 fromInfo.heuristicEffort = 0.;
158 fromInfo.prev = nullptr;
159 fromInfo.leaveTime = STEPS2TIME(msTime);
160 myFrontierList.push_back(&fromInfo);
161 }
162 myAmClean = true;
163// }
164 }
165
167 virtual void reset(const V* const vehicle) {
168 UNUSED_PARAMETER(vehicle);
169 }
170
171 const std::string& getType() const {
172 return myType;
173 }
174
175 inline const typename SUMOAbstractRouter<E, V>::EdgeInfo& getEdgeInfo(int index) const {
176 return myEdgeInfos[index];
177 }
178
181 virtual bool compute(const E* from, const E* to, const V* const vehicle,
182 SUMOTime msTime, std::vector<const E*>& into, bool silent = false) = 0;
183
184
189 inline bool compute(
190 const E* from, double fromPos,
191 const E* to, double toPos,
192 const V* const vehicle,
193 SUMOTime msTime, std::vector<const E*>& into, bool silent = false) {
194 if (from != to || fromPos <= toPos) {
195 return compute(from, to, vehicle, msTime, into, silent);
196 } else {
197 return computeLooped(from, to, vehicle, msTime, into, silent);
198 }
199 }
200
201
204 inline bool computeLooped(const E* from, const E* to, const V* const vehicle,
205 SUMOTime msTime, std::vector<const E*>& into, bool silent = false) {
206 if (from != to) {
207 return compute(from, to, vehicle, msTime, into, silent);
208 }
209 double minEffort = std::numeric_limits<double>::max();
210 std::vector<const E*> best;
211 const SUMOVehicleClass vClass = vehicle == 0 ? SVC_IGNORING : vehicle->getVClass();
212 for (const std::pair<const E*, const E*>& follower : from->getViaSuccessors(vClass)) {
213 std::vector<const E*> tmp;
214 compute(follower.first, to, vehicle, msTime, tmp, true);
215 if (tmp.size() > 0) {
216 double effort = recomputeCosts(tmp, vehicle, msTime);
217 if (effort < minEffort) {
218 minEffort = effort;
219 best = tmp;
220 }
221 }
222 }
223 if (minEffort != std::numeric_limits<double>::max()) {
224 into.push_back(from);
225 std::copy(best.begin(), best.end(), std::back_inserter(into));
226 return true;
227 } else if (!silent && myErrorMsgHandler != nullptr) {
228 myErrorMsgHandler->informf(TL("No connection between edge '%' and edge '%' found."), from->getID(), to->getID());
229 }
230 return false;
231 }
232
233 inline bool isProhibited(const E* const edge, const V* const vehicle) const {
234 return (myHavePermissions && edge->prohibits(vehicle)) || (myHaveRestrictions && edge->restricts(vehicle));
235 }
236
237 inline double getTravelTime(const E* const e, const V* const v, const double t, const double effort) const {
238 return myTTOperation == nullptr ? effort : (*myTTOperation)(e, v, t);
239 }
240
241 inline void updateViaEdgeCost(const E* viaEdge, const V* const v, double& time, double& effort, double& length) const {
242 while (viaEdge != nullptr && viaEdge->isInternal()) {
243 const double viaEffortDelta = this->getEffort(viaEdge, v, time);
244 time += getTravelTime(viaEdge, v, time, viaEffortDelta);
245 effort += viaEffortDelta;
246 length += viaEdge->getLength();
247 viaEdge = viaEdge->getViaSuccessors().front().second;
248 }
249 }
250
251 inline void updateViaCost(const E* const prev, const E* const e, const V* const v, double& time, double& effort, double& length) const {
252 if (prev != nullptr) {
253 for (const std::pair<const E*, const E*>& follower : prev->getViaSuccessors()) {
254 if (follower.first == e) {
255 updateViaEdgeCost(follower.second, v, time, effort, length);
256 break;
257 }
258 }
259 }
260 const double effortDelta = this->getEffort(e, v, time);
261 effort += effortDelta;
262 time += getTravelTime(e, v, time, effortDelta);
263 length += e->getLength();
264 }
265
266 bool isValid(const std::vector<const E*>& edges, const V* const v) const {
267 for (const E* const e : edges) {
268 if (isProhibited(e, v)) {
269 return false;
270 }
271 }
272 return true;
273 }
274
275 virtual double recomputeCosts(const std::vector<const E*>& edges, const V* const v, SUMOTime msTime, double* lengthp = nullptr) const {
276 double time = STEPS2TIME(msTime);
277 double effort = 0.;
278 double length = 0.;
279 if (lengthp == nullptr) {
280 lengthp = &length;
281 } else {
282 *lengthp = 0.;
283 }
284 const E* prev = nullptr;
285 for (const E* const e : edges) {
286 updateViaCost(prev, e, v, time, effort, *lengthp);
287 prev = e;
288 }
289 return effort;
290 }
291
292
293 inline double recomputeCostsPos(const std::vector<const E*>& edges, const V* const v, double fromPos, double toPos, SUMOTime msTime, double* lengthp = nullptr) const {
294 double effort = recomputeCosts(edges, v, msTime, lengthp);
295 if (!edges.empty()) {
296 double firstEffort = this->getEffort(edges.front(), v, STEPS2TIME(msTime));
297 double lastEffort = this->getEffort(edges.back(), v, STEPS2TIME(msTime));
298 effort -= firstEffort * fromPos / edges.front()->getLength();
299 effort -= lastEffort * (edges.back()->getLength() - toPos) / edges.back()->getLength();
300 }
301 return effort;
302 }
303
304
305 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) {
306 double time = STEPS2TIME(msTime);
307 double effort = 0.;
308 double length = 0.;
309 const EdgeInfo* prev = &myEdgeInfos[(*routeBegin)->getNumericalID()];
310 init((*routeBegin)->getNumericalID(), msTime);
311 for (auto e = routeBegin + 1; e != routeEnd; ++e) {
312 if (isProhibited(*e, v)) {
313 return -1;
314 }
315 auto& edgeInfo = myEdgeInfos[(*e)->getNumericalID()];
316 edgeInfo.heuristicEffort = effort;
317 edgeInfo.prev = prev;
318 updateViaCost(prev->edge, *e, v, time, effort, length);
319 edgeInfo.effort = effort;
320 edgeInfo.leaveTime = time;
321 myFound.push_back(&edgeInfo);
322 prev = &edgeInfo;
323#ifdef ROUTER_DEBUG_HINT
324 if (ROUTER_DEBUG_COND) {
325 std::cout << "DEBUG: hit=" << (*e)->getID()
326 << " TT=" << edgeInfo.effort
327 << " EF=" << this->getEffort(*e, v, edgeInfo.leaveTime)
328 << " HT=" << edgeInfo.heuristicEffort << "\n";
329 }
330#endif
331 }
332 return effort;
333 }
334
335
336 inline double getEffort(const E* const e, const V* const v, double t) const {
337 if (this->myProhibited.size() > 0 && myEdgeInfos.size() > 0 && myEdgeInfos[e->getNumericalID()].prohibitionEnd > 0) {
338 // pass edge after prohibition ends
339 return (myEdgeInfos[e->getNumericalID()].prohibitionEnd - t) + (*myOperation)(e, v, myEdgeInfos[e->getNumericalID()].prohibitionEnd);
340 } else {
341 return (*myOperation)(e, v, t);
342 }
343 }
344
349
350 inline void endQuery(int visits) {
351 myQueryVisits += visits;
353 }
354
355 virtual void setBulkMode(const bool mode) {
356 myBulkMode = mode;
357 }
358
359 inline void setAutoBulkMode(const bool mode) {
360 myAutoBulkMode = mode;
361 }
362
363 virtual void prohibit(const Prohibitions& toProhibit) {
364 for (auto item : this->myProhibited) {
365 myEdgeInfos[item.first->getNumericalID()].prohibited = false;
366 myEdgeInfos[item.first->getNumericalID()].prohibitionEnd = 0;
367 }
368 for (auto item : toProhibit) {
369 if (item.second >= 0 && item.second != std::numeric_limits<double>::max()) {
370 myEdgeInfos[item.first->getNumericalID()].prohibitionEnd = item.second;
371 } else {
372 myEdgeInfos[item.first->getNumericalID()].prohibited = true;
373 }
374 }
375 this->myProhibited = toProhibit;
376 }
377
378
380 void buildPathFrom(const typename SUMOAbstractRouter<E, V>::EdgeInfo* rbegin, std::vector<const E*>& edges) {
381 std::vector<const E*> tmp;
382 while (rbegin != nullptr) {
383 tmp.push_back(rbegin->edge);
384 rbegin = rbegin->prev;
385 }
386 std::copy(tmp.rbegin(), tmp.rend(), std::back_inserter(edges));
387 }
388
389protected:
392
395
398
401
404
407
410
413
416
418 std::vector<typename SUMOAbstractRouter<E, V>::EdgeInfo> myEdgeInfos;
419
421 std::vector<typename SUMOAbstractRouter<E, V>::EdgeInfo*> myFrontierList;
423 std::vector<typename SUMOAbstractRouter<E, V>::EdgeInfo*> myFound;
424
425private:
427 const std::string myType;
428
430 long long int myQueryVisits;
431 long long int myNumQueries;
433 long long int myQueryStartTime;
434 long long int myQueryTimeSum;
435
436private:
439};
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
void informf(const std::string &format, T value, Targs... Fargs)
adds a new formatted message
Definition MsgHandler.h:116
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
Operation myTTOperation
The object's operation to perform for travel times.
MsgHandler *const myErrorMsgHandler
the handler for routing errors
std::map< const E *, double > Prohibitions
Prohibitions and their estimated end time.
bool isProhibited(const E *const edge, const V *const vehicle) const
const bool myHavePermissions
whether edge permissions need to be considered
bool myBulkMode
whether we are currently operating several route queries in a bulk
long long int myQueryVisits
counters for performance logging
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
long long int myQueryStartTime
the time spent querying in milliseconds
virtual void setBulkMode(const bool mode)
SUMOAbstractRouter & operator=(const SUMOAbstractRouter &s)=delete
Invalidated assignment operator.
std::vector< typename SUMOAbstractRouter< E, V >::EdgeInfo > myEdgeInfos
The container of edge information.
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 E *const, const V *const, double)
Type of the function that is used to retrieve the edge effort.
Operation myOperation
The object's operation to perform.
double getTravelTime(const E *const e, const V *const v, const double t, const double effort) const
long long int myQueryTimeSum
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)
Prohibitions myProhibited
The list of explicitly prohibited edges and estimated end time of prohibition.
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
bool myAmClean
whether we are already initialized
const bool myHaveRestrictions
whether edge restrictions need to be considered
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.
bool myAutoBulkMode
whether we are currently trying to detect bulk mode automatically
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< E, V >::EdgeInfo * > myFrontierList
A container for reusage of the min edge heap.
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< E, V >::EdgeInfo * > myFound
list of visited Edges (for resetting)
const std::string myType
the type of this router
static long getCurrentMillis()
Returns the current time in milliseconds.
Definition SysUtils.cpp:44
#define UNUSED_PARAMETER(x)
Definition json.hpp:4471