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-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/****************************************************************************/
20// An abstract router base class
21/****************************************************************************/
22#pragma once
23#include <config.h>
24
25#include <iostream>
26#include <string>
27#include <vector>
28#include <algorithm>
29#include <iterator>
30#include <assert.h>
35
36//#define ROUTER_DEBUG_HINT
37//#define ROUTER_DEBUG_COND (true)
38
39
40// ===========================================================================
41// class definitions
42// ===========================================================================
43
46 double begin = 0;
47 double end = std::numeric_limits<double>::max();
49};
50
55template<class E, class V>
57public:
63 class EdgeInfo {
64 public:
66 EdgeInfo(const E* const e)
67 : edge(e), effort(std::numeric_limits<double>::max()),
68 heuristicEffort(std::numeric_limits<double>::max()),
70
72 const E* const edge;
73
75 double effort;
76
78 // only used by A*
80
82 double leaveTime;
83
85 const EdgeInfo* prev;
86
88 bool visited;
89
92
95
98
99 inline void reset() {
100 effort = std::numeric_limits<double>::max();
101 heuristicEffort = std::numeric_limits<double>::max();
102 visited = false;
103 }
104
105 };
106
108 typedef double(* Operation)(const E* const, const V* const, double);
109
110 typedef std::map<const E*, RouterProhibition> Prohibitions;
111
113 SUMOAbstractRouter(const std::string& type, bool unbuildIsWarning, Operation operation, Operation ttOperation,
114 const bool havePermissions, const bool haveRestrictions) :
115 myErrorMsgHandler(unbuildIsWarning ? MsgHandler::getWarningInstance() : MsgHandler::getErrorInstance()),
116 myOperation(operation), myTTOperation(ttOperation),
117 myBulkMode(false),
118 myAutoBulkMode(false),
119 myAmClean(true),
120 myHavePermissions(havePermissions),
121 myHaveRestrictions(haveRestrictions),
122 myType(type),
123 myQueryVisits(0),
124 myNumQueries(0),
126 myQueryTimeSum(0) {
127 }
128
143
144
145
148 if (myNumQueries > 0) {
149 WRITE_MESSAGE(myType + " answered " + toString(myNumQueries) + " queries and explored " + toString((double)myQueryVisits / (double)myNumQueries) + " edges on average.");
150 WRITE_MESSAGE(myType + " spent " + elapsedMs2string(myQueryTimeSum) + " answering queries (" + toString((double)myQueryTimeSum / (double)myNumQueries) + "ms on average).");
151 }
152 }
153
154 virtual SUMOAbstractRouter* clone() = 0;
155
156 inline void init(const int edgeID, const SUMOTime msTime) {
157// if (!myAmClean) {
158 // all EdgeInfos touched in the previous query are either in myFrontierList or myFound: clean those up
159 for (auto& edgeInfo : myFrontierList) {
160 edgeInfo->reset();
161 }
162 myFrontierList.clear();
163 for (auto& edgeInfo : myFound) {
164 edgeInfo->reset();
165 }
166 myFound.clear();
167 if (edgeID > -1) {
168 // add begin node
169 auto& fromInfo = myEdgeInfos[edgeID];
170 fromInfo.effort = 0.;
171 fromInfo.heuristicEffort = 0.;
172 fromInfo.prev = nullptr;
173 fromInfo.leaveTime = STEPS2TIME(msTime);
174 myFrontierList.push_back(&fromInfo);
175 }
176 myAmClean = true;
177// }
178 }
179
181 virtual void reset(const V* const vehicle) {
182 UNUSED_PARAMETER(vehicle);
183 }
184
185 virtual void setMsgHandler(MsgHandler* const errorMsgHandler) {
186 myErrorMsgHandler = errorMsgHandler;
187 }
188
189 const std::string& getType() const {
190 return myType;
191 }
192
193 inline const typename SUMOAbstractRouter<E, V>::EdgeInfo& getEdgeInfo(int index) const {
194 return myEdgeInfos[index];
195 }
196
199 virtual bool compute(const E* from, const E* to, const V* const vehicle,
200 SUMOTime msTime, std::vector<const E*>& into, bool silent = false) = 0;
201
202
207 inline bool compute(
208 const E* from, double fromPos,
209 const E* to, double toPos,
210 const V* const vehicle,
211 SUMOTime msTime, std::vector<const E*>& into, bool silent = false) {
212 if (from != to || fromPos <= toPos) {
213 return compute(from, to, vehicle, msTime, into, silent);
214 } else {
215 return computeLooped(from, to, vehicle, msTime, into, silent);
216 }
217 }
218
219
222 inline bool computeLooped(const E* from, const E* to, const V* const vehicle,
223 SUMOTime msTime, std::vector<const E*>& into, bool silent = false) {
224 if (from != to) {
225 return compute(from, to, vehicle, msTime, into, silent);
226 }
227 double minEffort = std::numeric_limits<double>::max();
228 std::vector<const E*> best;
229 const SUMOVehicleClass vClass = vehicle == 0 ? SVC_IGNORING : vehicle->getVClass();
230 for (const std::pair<const E*, const E*>& follower : from->getViaSuccessors(vClass)) {
231 std::vector<const E*> tmp;
232 compute(follower.first, to, vehicle, msTime, tmp, true);
233 if (tmp.size() > 0) {
234 double effort = recomputeCosts(tmp, vehicle, msTime);
235 if (effort < minEffort) {
236 minEffort = effort;
237 best = tmp;
238 }
239 }
240 }
241 if (minEffort != std::numeric_limits<double>::max()) {
242 into.push_back(from);
243 std::copy(best.begin(), best.end(), std::back_inserter(into));
244 return true;
245 } else if (!silent && myErrorMsgHandler != nullptr) {
246 myErrorMsgHandler->informf(TL("No connection between edge '%' and edge '%' found."), from->getID(), to->getID());
247 }
248 return false;
249 }
250
251 inline bool isProhibited(const E* const edge, const V* const vehicle, double t) const {
252 return (myProhibited.size() > 0
253 && (myEdgeInfos[edge->getNumericalID()].prohibitedPermissions & vehicle->getVClass()) != vehicle->getVClass()
254 && myEdgeInfos[edge->getNumericalID()].prohibitionBegin <= t
255 && myEdgeInfos[edge->getNumericalID()].prohibitionEnd == std::numeric_limits<double>::max())
256 || (myHavePermissions && edge->prohibits(vehicle)) || (myHaveRestrictions && edge->restricts(vehicle));
257 }
258
259 inline double getTravelTime(const E* const e, const V* const v, const double t, const double effort) const {
260 return myTTOperation == nullptr ? effort : (*myTTOperation)(e, v, t);
261 }
262
263 inline void updateViaEdgeCost(const E* viaEdge, const V* const v, double& time, double& effort, double& length) const {
264 while (viaEdge != nullptr && viaEdge->isInternal()) {
265 const double viaEffortDelta = this->getEffort(viaEdge, v, time);
266 time += getTravelTime(viaEdge, v, time, viaEffortDelta);
267 effort += viaEffortDelta;
268 length += viaEdge->getLength();
269 viaEdge = viaEdge->getViaSuccessors().front().second;
270 }
271 }
272
273 inline void updateViaCost(const E* const prev, const E* const e, const V* const v, double& time, double& effort, double& length) const {
274 if (prev != nullptr) {
275 for (const std::pair<const E*, const E*>& follower : prev->getViaSuccessors()) {
276 if (follower.first == e) {
277 updateViaEdgeCost(follower.second, v, time, effort, length);
278 break;
279 }
280 }
281 }
282 const double effortDelta = this->getEffort(e, v, time);
283 effort += effortDelta;
284 time += getTravelTime(e, v, time, effortDelta);
285 length += e->getLength();
286 }
287
288 bool isValid(const std::vector<const E*>& edges, const V* const v, double t) const {
289 for (const E* const e : edges) {
290 if (isProhibited(e, v, t)) {
291 return false;
292 }
293 }
294 return true;
295 }
296
297 virtual double recomputeCosts(const std::vector<const E*>& edges, const V* const v, SUMOTime msTime, double* lengthp = nullptr) const {
298 double time = STEPS2TIME(msTime);
299 double effort = 0.;
300 double length = 0.;
301 if (lengthp == nullptr) {
302 lengthp = &length;
303 } else {
304 *lengthp = 0.;
305 }
306 const E* prev = nullptr;
307 for (const E* const e : edges) {
308 updateViaCost(prev, e, v, time, effort, *lengthp);
309 prev = e;
310 }
311 return effort;
312 }
313
314
315 inline double recomputeCostsPos(const std::vector<const E*>& edges, const V* const v, double fromPos, double toPos, SUMOTime msTime, double* lengthp = nullptr) const {
316 double effort = recomputeCosts(edges, v, msTime, lengthp);
317 if (!edges.empty()) {
318 const E* first = edges.front();
319 if (first->getLength() == 0) {
320 if (edges.size() > 1 && edges[1]->getLength() > 0) {
321 first = edges[1];
322 } else {
323 return effort;
324 }
325 }
326 const E* last = edges.back();
327 if (last->getLength() == 0) {
328 if (edges.size() > 1 && edges[edges.size() - 2]->getLength() > 0) {
329 last = edges[edges.size() - 2];
330 } else {
331 return effort;
332 }
333 }
334 assert(first->getLength() > 0);
335 assert(last->getLength() > 0);
336 double firstEffort = this->getEffort(first, v, STEPS2TIME(msTime));
337 double lastEffort = this->getEffort(last, v, STEPS2TIME(msTime));
338 effort -= firstEffort * fromPos / first->getLength();
339 effort -= lastEffort * (last->getLength() - toPos) / last->getLength();
340 if (lengthp != nullptr) {
341 (*lengthp) -= fromPos + last->getLength() - toPos;
342 }
343 }
344 return effort;
345 }
346
347
348 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) {
349 double time = STEPS2TIME(msTime);
350 double effort = 0.;
351 double length = 0.;
352 const EdgeInfo* prev = &myEdgeInfos[(*routeBegin)->getNumericalID()];
353 init((*routeBegin)->getNumericalID(), msTime);
354 for (auto e = routeBegin + 1; e != routeEnd; ++e) {
355 if (isProhibited(*e, v)) {
356 return -1;
357 }
358 auto& edgeInfo = myEdgeInfos[(*e)->getNumericalID()];
359 edgeInfo.heuristicEffort = effort;
360 edgeInfo.prev = prev;
361 updateViaCost(prev->edge, *e, v, time, effort, length);
362 edgeInfo.effort = effort;
363 edgeInfo.leaveTime = time;
364 myFound.push_back(&edgeInfo);
365 prev = &edgeInfo;
366#ifdef ROUTER_DEBUG_HINT
367 if (ROUTER_DEBUG_COND) {
368 std::cout << "DEBUG: hit=" << (*e)->getID()
369 << " TT=" << edgeInfo.effort
370 << " EF=" << this->getEffort(*e, v, edgeInfo.leaveTime)
371 << " HT=" << edgeInfo.heuristicEffort << "\n";
372 }
373#endif
374 }
375 return effort;
376 }
377
378
379 inline double getEffort(const E* const e, const V* const v, double t) const {
380 if (this->myProhibited.size() > 0 && myEdgeInfos.size() > 0
381 && myEdgeInfos[e->getNumericalID()].prohibitionEnd > t
382 && myEdgeInfos[e->getNumericalID()].prohibitionBegin <= t
383 && (myEdgeInfos[e->getNumericalID()].prohibitedPermissions & v->getVClass()) != v->getVClass()) {
384 // pass edge after prohibition ends
385 return (myEdgeInfos[e->getNumericalID()].prohibitionEnd - t) + (*myOperation)(e, v, myEdgeInfos[e->getNumericalID()].prohibitionEnd);
386 } else {
387 return (*myOperation)(e, v, t);
388 }
389 }
390
395
396 inline void endQuery(int visits) {
397 myQueryVisits += visits;
399 }
400
401 virtual void setBulkMode(const bool mode) {
402 myBulkMode = mode;
403 }
404
405 inline void setAutoBulkMode(const bool mode) {
406 myAutoBulkMode = mode;
407 }
408
409 virtual void prohibit(const Prohibitions& toProhibit) {
410 for (auto item : this->myProhibited) {
411 myEdgeInfos[item.first->getNumericalID()].prohibitedPermissions = SVCAll;
412 myEdgeInfos[item.first->getNumericalID()].prohibitionBegin = -1;
413 myEdgeInfos[item.first->getNumericalID()].prohibitionEnd = -1;
414 }
415 for (auto item : toProhibit) {
416 myEdgeInfos[item.first->getNumericalID()].prohibitionBegin = item.second.begin;
417 myEdgeInfos[item.first->getNumericalID()].prohibitionEnd = item.second.end;
418 myEdgeInfos[item.first->getNumericalID()].prohibitedPermissions = item.second.permissions;
419 //std::cout << item.first->getID() << " " << item.second.begin << " " << item.second.end << " (" << getVehicleClassNames(item.second.permissions) << ")\n";
420 }
421 this->myProhibited = toProhibit;
422 }
423
424 bool hasProhibitions() const {
425 return this->myProhibited.size() > 0;
426 }
427
428 virtual bool supportsProhibitions() const {
429 return true;
430 }
431
433 void buildPathFrom(const typename SUMOAbstractRouter<E, V>::EdgeInfo* rbegin, std::vector<const E*>& edges) {
434 std::vector<const E*> tmp;
435 while (rbegin != nullptr) {
436 tmp.push_back(rbegin->edge);
437 rbegin = rbegin->prev;
438 }
439 std::copy(tmp.rbegin(), tmp.rend(), std::back_inserter(edges));
440 }
441
442protected:
445
448
451
454
457
460
463
466
469
471 std::vector<typename SUMOAbstractRouter<E, V>::EdgeInfo> myEdgeInfos;
472
474 std::vector<typename SUMOAbstractRouter<E, V>::EdgeInfo*> myFrontierList;
476 std::vector<typename SUMOAbstractRouter<E, V>::EdgeInfo*> myFound;
477
478private:
480 const std::string myType;
481
483 long long int myQueryVisits;
484 long long int myNumQueries;
486 long long int myQueryStartTime;
487 long long int myQueryTimeSum;
488
489private:
492};
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:58
const SVCPermissions SVCAll
all VClasses are allowed
long long int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
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:49
void informf(const std::string &format, T value, Targs... Fargs)
adds a new formatted message
Definition MsgHandler.h:116
double prohibitionBegin
the time at which a temporary prohibition begins
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.
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 prohibition ends
SVCPermissions prohibitedPermissions
temporary permission change
Operation myTTOperation
The object's operation to perform for travel times.
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::map< const E *, RouterProhibition > Prohibitions
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
bool isProhibited(const E *const edge, const V *const vehicle, 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 myAmClean
whether we are already initialized
virtual bool supportsProhibitions() const
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...
bool isValid(const std::vector< const E * > &edges, const V *const v, double t) const
virtual double recomputeCosts(const std::vector< const E * > &edges, const V *const v, SUMOTime msTime, double *lengthp=nullptr) const
virtual void setMsgHandler(MsgHandler *const errorMsgHandler)
void endQuery(int visits)
virtual ~SUMOAbstractRouter()
Destructor.
MsgHandler * myErrorMsgHandler
the handler for routing errors
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:45
#define UNUSED_PARAMETER(x)
Definition json.hpp:4471
Prohibitions and their estimated end time.
SVCPermissions permissions