Eclipse SUMO - Simulation of Urban MObility
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>
30 #include <utils/common/SysUtils.h>
32 #include <utils/common/SUMOTime.h>
33 #include <utils/common/ToString.h>
34 //#define ROUTER_DEBUG_HINT
35 //#define ROUTER_DEBUG_COND (true)
36 
37 
38 // ===========================================================================
39 // class definitions
40 // ===========================================================================
45 template<class E, class V>
47 public:
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 
81  bool prohibited;
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),
106  myQueryStartTime(0),
107  myQueryTimeSum(0) {
108  }
109 
114  myBulkMode(false),
115  myAutoBulkMode(false),
118  myType(other->myType),
119  myQueryVisits(0),
120  myNumQueries(0),
121  myQueryStartTime(0),
122  myQueryTimeSum(0) { }
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 
334  inline void startQuery() {
335  myNumQueries++;
337  }
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 
373 protected:
376 
379 
382 
385 
388 
390  bool myAmClean;
391 
393  const bool myHavePermissions;
394 
396  const bool myHaveRestrictions;
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 
409 private:
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 
420 private:
423 };
long long int SUMOTime
Definition: GUI.h:35
#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:118
#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)
virtual SUMOAbstractRouter * clone()=0
Operation myTTOperation
The object's operation to perform for travel times.
long long int myNumQueries
MsgHandler *const myErrorMsgHandler
the handler for routing errors
const std::string & getType() const
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,...
long long int myQueryStartTime
the time spent querying in milliseconds
virtual void setBulkMode(const bool mode)
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
double getEffort(const E *const e, const V *const v, double t) const
const SUMOAbstractRouter< E, V >::EdgeInfo & getEdgeInfo(int index) 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
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
SUMOAbstractRouter & operator=(const SUMOAbstractRouter &s)=delete
Invalidated assignment operator.
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