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-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// 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) {}
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
83 inline void reset() {
84 effort = std::numeric_limits<double>::max();
85 heuristicEffort = std::numeric_limits<double>::max();
86 visited = false;
87 }
88
89 };
90
92 typedef double(* Operation)(const E* const, const V* const, double);
93
95 SUMOAbstractRouter(const std::string& type, bool unbuildIsWarning, Operation operation, Operation ttOperation,
96 const bool havePermissions, const bool haveRestrictions) :
97 myErrorMsgHandler(unbuildIsWarning ? MsgHandler::getWarningInstance() : MsgHandler::getErrorInstance()),
98 myOperation(operation), myTTOperation(ttOperation),
99 myBulkMode(false),
100 myAutoBulkMode(false),
101 myHavePermissions(havePermissions),
102 myHaveRestrictions(haveRestrictions),
103 myType(type),
104 myQueryVisits(0),
105 myNumQueries(0),
107 myQueryTimeSum(0) {
108 }
109
123
124
125
128 if (myNumQueries > 0) {
129 WRITE_MESSAGE(myType + " answered " + toString(myNumQueries) + " queries and explored " + toString((double)myQueryVisits / (double)myNumQueries) + " edges on average.");
130 WRITE_MESSAGE(myType + " spent " + elapsedMs2string(myQueryTimeSum) + " answering queries (" + toString((double)myQueryTimeSum / (double)myNumQueries) + "ms on average).");
131 }
132 }
133
134 virtual SUMOAbstractRouter* clone() = 0;
135
136 inline void init(const int edgeID, const SUMOTime msTime) {
137// if (!myAmClean) {
138 // all EdgeInfos touched in the previous query are either in myFrontierList or myFound: clean those up
139 for (auto& edgeInfo : myFrontierList) {
140 edgeInfo->reset();
141 }
142 myFrontierList.clear();
143 for (auto& edgeInfo : myFound) {
144 edgeInfo->reset();
145 }
146 myFound.clear();
147 if (edgeID > -1) {
148 // add begin node
149 auto& fromInfo = myEdgeInfos[edgeID];
150 fromInfo.effort = 0.;
151 fromInfo.heuristicEffort = 0.;
152 fromInfo.prev = nullptr;
153 fromInfo.leaveTime = STEPS2TIME(msTime);
154 myFrontierList.push_back(&fromInfo);
155 }
156 myAmClean = true;
157// }
158 }
159
161 virtual void reset(const V* const vehicle) {
162 UNUSED_PARAMETER(vehicle);
163 }
164
165 const std::string& getType() const {
166 return myType;
167 }
168
169 inline const typename SUMOAbstractRouter<E, V>::EdgeInfo& getEdgeInfo(int index) const {
170 return myEdgeInfos[index];
171 }
172
175 virtual bool compute(const E* from, const E* to, const V* const vehicle,
176 SUMOTime msTime, std::vector<const E*>& into, bool silent = false) = 0;
177
178
183 inline bool compute(
184 const E* from, double fromPos,
185 const E* to, double toPos,
186 const V* const vehicle,
187 SUMOTime msTime, std::vector<const E*>& into, bool silent = false) {
188 if (from != to || fromPos <= toPos) {
189 return compute(from, to, vehicle, msTime, into, silent);
190 } else {
191 return computeLooped(from, to, vehicle, msTime, into, silent);
192 }
193 }
194
195
198 inline bool computeLooped(const E* from, const E* to, const V* const vehicle,
199 SUMOTime msTime, std::vector<const E*>& into, bool silent = false) {
200 if (from != to) {
201 return compute(from, to, vehicle, msTime, into, silent);
202 }
203 double minEffort = std::numeric_limits<double>::max();
204 std::vector<const E*> best;
205 const SUMOVehicleClass vClass = vehicle == 0 ? SVC_IGNORING : vehicle->getVClass();
206 for (const std::pair<const E*, const E*>& follower : from->getViaSuccessors(vClass)) {
207 std::vector<const E*> tmp;
208 compute(follower.first, to, vehicle, msTime, tmp, true);
209 if (tmp.size() > 0) {
210 double effort = recomputeCosts(tmp, vehicle, msTime);
211 if (effort < minEffort) {
212 minEffort = effort;
213 best = tmp;
214 }
215 }
216 }
217 if (minEffort != std::numeric_limits<double>::max()) {
218 into.push_back(from);
219 std::copy(best.begin(), best.end(), std::back_inserter(into));
220 return true;
221 } else if (!silent && myErrorMsgHandler != nullptr) {
222 myErrorMsgHandler->informf(TL("No connection between edge '%' and edge '%' found."), from->getID(), to->getID());
223 }
224 return false;
225 }
226
227 inline bool isProhibited(const E* const edge, const V* const vehicle) const {
228 return (myHavePermissions && edge->prohibits(vehicle)) || (myHaveRestrictions && edge->restricts(vehicle));
229 }
230
231 inline double getTravelTime(const E* const e, const V* const v, const double t, const double effort) const {
232 return myTTOperation == nullptr ? effort : (*myTTOperation)(e, v, t);
233 }
234
235 inline void updateViaEdgeCost(const E* viaEdge, const V* const v, double& time, double& effort, double& length) const {
236 while (viaEdge != nullptr && viaEdge->isInternal()) {
237 const double viaEffortDelta = this->getEffort(viaEdge, v, time);
238 time += getTravelTime(viaEdge, v, time, viaEffortDelta);
239 effort += viaEffortDelta;
240 length += viaEdge->getLength();
241 viaEdge = viaEdge->getViaSuccessors().front().second;
242 }
243 }
244
245 inline void updateViaCost(const E* const prev, const E* const e, const V* const v, double& time, double& effort, double& length) const {
246 if (prev != nullptr) {
247 for (const std::pair<const E*, const E*>& follower : prev->getViaSuccessors()) {
248 if (follower.first == e) {
249 updateViaEdgeCost(follower.second, v, time, effort, length);
250 break;
251 }
252 }
253 }
254 const double effortDelta = this->getEffort(e, v, time);
255 effort += effortDelta;
256 time += getTravelTime(e, v, time, effortDelta);
257 length += e->getLength();
258 }
259
260 bool isValid(const std::vector<const E*>& edges, const V* const v) const {
261 for (const E* const e : edges) {
262 if (isProhibited(e, v)) {
263 return false;
264 }
265 }
266 return true;
267 }
268
269 virtual double recomputeCosts(const std::vector<const E*>& edges, const V* const v, SUMOTime msTime, double* lengthp = nullptr) const {
270 double time = STEPS2TIME(msTime);
271 double effort = 0.;
272 double length = 0.;
273 if (lengthp == nullptr) {
274 lengthp = &length;
275 } else {
276 *lengthp = 0.;
277 }
278 const E* prev = nullptr;
279 for (const E* const e : edges) {
280 updateViaCost(prev, e, v, time, effort, *lengthp);
281 prev = e;
282 }
283 return effort;
284 }
285
286
287 inline double recomputeCostsPos(const std::vector<const E*>& edges, const V* const v, double fromPos, double toPos, SUMOTime msTime, double* lengthp = nullptr) const {
288 double effort = recomputeCosts(edges, v, msTime, lengthp);
289 if (!edges.empty()) {
290 double firstEffort = this->getEffort(edges.front(), v, STEPS2TIME(msTime));
291 double lastEffort = this->getEffort(edges.back(), v, STEPS2TIME(msTime));
292 effort -= firstEffort * fromPos / edges.front()->getLength();
293 effort -= lastEffort * (edges.back()->getLength() - toPos) / edges.back()->getLength();
294 }
295 return effort;
296 }
297
298
299 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) {
300 double time = STEPS2TIME(msTime);
301 double effort = 0.;
302 double length = 0.;
303 const EdgeInfo* prev = &myEdgeInfos[(*routeBegin)->getNumericalID()];
304 init((*routeBegin)->getNumericalID(), msTime);
305 for (auto e = routeBegin + 1; e != routeEnd; ++e) {
306 if (isProhibited(*e, v)) {
307 return -1;
308 }
309 auto& edgeInfo = myEdgeInfos[(*e)->getNumericalID()];
310 edgeInfo.heuristicEffort = effort;
311 edgeInfo.prev = prev;
312 updateViaCost(prev->edge, *e, v, time, effort, length);
313 edgeInfo.effort = effort;
314 edgeInfo.leaveTime = time;
315 myFound.push_back(&edgeInfo);
316 prev = &edgeInfo;
317#ifdef ROUTER_DEBUG_HINT
318 if (ROUTER_DEBUG_COND) {
319 std::cout << "DEBUG: hit=" << (*e)->getID()
320 << " TT=" << edgeInfo.effort
321 << " EF=" << this->getEffort(*e, v, edgeInfo.leaveTime)
322 << " HT=" << edgeInfo.heuristicEffort << "\n";
323 }
324#endif
325 }
326 return effort;
327 }
328
329
330 inline double getEffort(const E* const e, const V* const v, double t) const {
331 return (*myOperation)(e, v, t);
332 }
333
338
339 inline void endQuery(int visits) {
340 myQueryVisits += visits;
342 }
343
344 virtual void setBulkMode(const bool mode) {
345 myBulkMode = mode;
346 }
347
348 inline void setAutoBulkMode(const bool mode) {
349 myAutoBulkMode = mode;
350 }
351
352 virtual void prohibit(const std::vector<E*>& toProhibit) {
353 for (E* const edge : this->myProhibited) {
354 myEdgeInfos[edge->getNumericalID()].prohibited = false;
355 }
356 for (E* const edge : toProhibit) {
357 myEdgeInfos[edge->getNumericalID()].prohibited = true;
358 }
359 this->myProhibited = toProhibit;
360 }
361
362
364 void buildPathFrom(const typename SUMOAbstractRouter<E, V>::EdgeInfo* rbegin, std::vector<const E*>& edges) {
365 std::vector<const E*> tmp;
366 while (rbegin != nullptr) {
367 tmp.push_back(rbegin->edge);
368 rbegin = rbegin->prev;
369 }
370 std::copy(tmp.rbegin(), tmp.rend(), std::back_inserter(edges));
371 }
372
373protected:
376
379
382
385
388
391
394
397
399 std::vector<E*> myProhibited;
400
402 std::vector<typename SUMOAbstractRouter<E, V>::EdgeInfo> myEdgeInfos;
403
405 std::vector<typename SUMOAbstractRouter<E, V>::EdgeInfo*> myFrontierList;
407 std::vector<typename SUMOAbstractRouter<E, V>::EdgeInfo*> myFound;
408
409private:
411 const std::string myType;
412
414 long long int myQueryVisits;
415 long long int myNumQueries;
417 long long int myQueryStartTime;
418 long long int myQueryTimeSum;
419
420private:
423};
long long int SUMOTime
Definition GUI.h:36
#define WRITE_MESSAGE(msg)
Definition MsgHandler.h:297
#define TL(string)
Definition MsgHandler.h:315
std::string elapsedMs2string(long long int t)
convert ms to string for log output
Definition SUMOTime.cpp:122
#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
#define UNUSED_PARAMETER(x)
Definition StdDefs.h:30
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:122
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)
Operation myTTOperation
The object's operation to perform for travel times.
MsgHandler *const myErrorMsgHandler
the handler for routing errors
std::vector< E * > myProhibited
The list of explicitly prohibited edges.
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
virtual void prohibit(const std::vector< E * > &toProhibit)
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.
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
Definition json.hpp:4471