|
SUMO - Simulation of Urban MObility
|
00001 /****************************************************************************/ 00007 // Dijkstra shortest path algorithm using other values 00008 /****************************************************************************/ 00009 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/ 00010 // Copyright (C) 2001-2011 DLR (http://www.dlr.de/) and contributors 00011 /****************************************************************************/ 00012 // 00013 // This program is free software; you can redistribute it and/or modify 00014 // it under the terms of the GNU General Public License as published by 00015 // the Free Software Foundation; either version 2 of the License, or 00016 // (at your option) any later version. 00017 // 00018 /****************************************************************************/ 00019 #ifndef DijkstraRouterEffort_h 00020 #define DijkstraRouterEffort_h 00021 00022 00023 // =========================================================================== 00024 // included modules 00025 // =========================================================================== 00026 #ifdef _MSC_VER 00027 #include <windows_config.h> 00028 #else 00029 #include <config.h> 00030 #endif 00031 00032 #include <string> 00033 #include <functional> 00034 #include <vector> 00035 #include <set> 00036 #include <limits> 00037 #include <algorithm> 00038 #include <utils/common/InstancePool.h> 00039 #include <utils/common/MsgHandler.h> 00040 #include <utils/common/StdDefs.h> 00041 #include "SUMOAbstractRouter.h" 00042 00043 00044 // =========================================================================== 00045 // class definitions 00046 // =========================================================================== 00062 template<class E, class V, class PF> 00063 class DijkstraRouterEffortBase : public SUMOAbstractRouter<E, V>, public PF { 00064 public: 00066 DijkstraRouterEffortBase(size_t noE, bool unbuildIsWarning) : 00067 myErrorMsgHandler(unbuildIsWarning ? MsgHandler::getWarningInstance() : MsgHandler::getErrorInstance()) { 00068 for (size_t i = 0; i < noE; i++) { 00069 myEdgeInfos.push_back(EdgeInfo(i)); 00070 } 00071 } 00072 00074 virtual ~DijkstraRouterEffortBase() { } 00075 00081 class EdgeInfo { 00082 public: 00084 EdgeInfo() : edge(0), effort(0), leaveTime(0), prev(0), visited(false) {} 00085 00087 EdgeInfo(size_t id) 00088 : edge(E::dictionary(id)), effort(0), leaveTime(0), prev(0), visited(false) {} 00089 00091 const E* edge; 00092 00094 SUMOReal effort; 00095 00097 SUMOReal leaveTime; 00098 00100 EdgeInfo* prev; 00101 00103 bool visited; 00104 00105 }; 00106 00111 class EdgeInfoByEffortComparator { 00112 public: 00114 bool operator()(EdgeInfo* nod1, EdgeInfo* nod2) const { 00115 if (nod1->effort == nod2->effort) { 00116 return nod1->edge->getNumericalID() > nod2->edge->getNumericalID(); 00117 } 00118 return nod1->effort>nod2->effort; 00119 } 00120 }; 00121 00122 virtual SUMOReal getEffort(const E* const e, const V* const v, SUMOReal t) = 0; 00123 virtual SUMOReal getTravelTime(const E* const e, const V* const v, SUMOReal t) = 0; 00124 00125 00128 virtual void compute(const E* from, const E* to, const V* const vehicle, 00129 SUMOTime msTime, std::vector<const E*> &into) { 00130 00131 SUMOReal time = (SUMOReal) msTime / 1000.; 00132 for (typename std::vector<EdgeInfo>::iterator i=myEdgeInfos.begin(); i!=myEdgeInfos.end(); i++) { 00133 (*i).effort = std::numeric_limits<SUMOReal>::max(); 00134 (*i).visited = false; 00135 } 00136 assert(from!=0&&to!=0); 00137 myFrontierList.clear(); 00138 // add begin node 00139 EdgeInfo* const fromInfo = &(myEdgeInfos[from->getNumericalID()]); 00140 fromInfo->effort = 0; 00141 fromInfo->prev = 0; 00142 fromInfo->leaveTime = (SUMOReal) time; 00143 myFrontierList.push_back(fromInfo); 00144 // loop 00145 while (!myFrontierList.empty()) { 00146 // use the node with the minimal length 00147 EdgeInfo* const minimumInfo = myFrontierList.front(); 00148 const E* const minEdge = minimumInfo->edge; 00149 pop_heap(myFrontierList.begin(), myFrontierList.end(), myComparator); 00150 myFrontierList.pop_back(); 00151 // check whether the destination node was already reached 00152 if (minEdge == to) { 00153 buildPathFrom(minimumInfo, into); 00154 return; 00155 } 00156 minimumInfo->visited = true; 00157 const SUMOReal effort = minimumInfo->effort + getEffort(minEdge, vehicle, (SUMOTime) minimumInfo->leaveTime); 00158 const SUMOReal leaveTime = minimumInfo->leaveTime + getTravelTime(minEdge, vehicle, (SUMOTime)minimumInfo->leaveTime); 00159 // check all ways from the node with the minimal length 00160 unsigned int i = 0; 00161 unsigned int length_size = minEdge->getNoFollowing(); 00162 for (i=0; i<length_size; i++) { 00163 const E* const follower = minEdge->getFollower(i); 00164 EdgeInfo* const followerInfo = &(myEdgeInfos[follower->getNumericalID()]); 00165 // check whether it can be used 00166 if (PF::operator()(follower, vehicle)) { 00167 continue; 00168 } 00169 const SUMOReal oldEffort = followerInfo->effort; 00170 if (!followerInfo->visited && effort < oldEffort) { 00171 followerInfo->effort = effort; 00172 followerInfo->leaveTime = leaveTime; 00173 followerInfo->prev = minimumInfo; 00174 if (oldEffort == std::numeric_limits<SUMOReal>::max()) { 00175 myFrontierList.push_back(followerInfo); 00176 push_heap(myFrontierList.begin(), myFrontierList.end(), myComparator); 00177 } else { 00178 push_heap(myFrontierList.begin(), 00179 find(myFrontierList.begin(), myFrontierList.end(), followerInfo) + 1, 00180 myComparator); 00181 } 00182 } 00183 } 00184 } 00185 myErrorMsgHandler->inform("No connection between '" + from->getID() + "' and '" + to->getID() + "' found."); 00186 } 00187 00188 00189 SUMOReal recomputeCosts(const std::vector<const E*> &edges, const V* const v, SUMOTime msTime) throw() { 00190 SUMOReal time = (SUMOReal) msTime / 1000.; 00191 SUMOReal costs = 0; 00192 SUMOReal t = (SUMOReal) time; 00193 for (typename std::vector<const E*>::const_iterator i=edges.begin(); i!=edges.end(); ++i) { 00194 if (PF::operator()(*i, v)) { 00195 return -1; 00196 } 00197 costs += getEffort(*i, v, (SUMOTime) t); 00198 t += getTravelTime(*i, v, (SUMOTime) t); 00199 } 00200 return costs; 00201 } 00202 00203 public: 00205 void buildPathFrom(EdgeInfo* rbegin, std::vector<const E*> &edges) { 00206 std::deque<const E*> tmp; 00207 while (rbegin!=0) { 00208 tmp.push_front((E*) rbegin->edge); // !!! 00209 rbegin = rbegin->prev; 00210 } 00211 std::copy(tmp.begin(), tmp.end(), std::back_inserter(edges)); 00212 } 00213 00214 protected: 00216 std::vector<EdgeInfo> myEdgeInfos; 00217 00219 std::vector<EdgeInfo*> myFrontierList; 00220 00221 EdgeInfoByEffortComparator myComparator; 00222 00224 MsgHandler* const myErrorMsgHandler; 00225 00226 }; 00227 00228 00229 template<class E, class V, class PF, class EC> 00230 class DijkstraRouterEffort_ByProxi : public DijkstraRouterEffortBase<E, V, PF> { 00231 public: 00233 typedef SUMOReal(EC::* Operation)(const E* const, const V* const, SUMOReal) const; 00234 00235 DijkstraRouterEffort_ByProxi(size_t noE, bool unbuildIsWarningOnly, EC* receiver, Operation effortOperation, Operation ttOperation) 00236 : DijkstraRouterEffortBase<E, V, PF>(noE, unbuildIsWarningOnly), 00237 myReceiver(receiver), myEffortOperation(effortOperation), myTTOperation(ttOperation) {} 00238 00239 inline SUMOReal getEffort(const E* const e, const V* const v, SUMOReal t) { 00240 return (myReceiver->*myEffortOperation)(e, v, t); 00241 } 00242 00243 inline SUMOReal getTravelTime(const E* const e, const V* const v, SUMOReal t) { 00244 return (myReceiver->*myTTOperation)(e, v, t); 00245 } 00246 00247 private: 00249 EC* myReceiver; 00250 00252 Operation myEffortOperation; 00253 00255 Operation myTTOperation; 00256 00257 }; 00258 00259 00260 template<class E, class V, class PF> 00261 class DijkstraRouterEffort_Direct : public DijkstraRouterEffortBase<E, V, PF> { 00262 public: 00264 typedef SUMOReal(E::* Operation)(const V* const, SUMOReal) const; 00265 00266 DijkstraRouterEffort_Direct(size_t noE, bool unbuildIsWarningOnly, Operation effortOperation, Operation ttOperation) 00267 : DijkstraRouterEffortBase<E, V, PF>(noE, unbuildIsWarningOnly), 00268 myEffortOperation(effortOperation), myTTOperation(ttOperation) {} 00269 00270 inline SUMOReal getEffort(const E* const e, const V* const v, SUMOReal t) { 00271 return (e->*myEffortOperation)(v, t); 00272 } 00273 00274 inline SUMOReal getTravelTime(const E* const e, const V* const v, SUMOReal t) { 00275 return (e->*myTTOperation)(v, t); 00276 } 00277 00278 private: 00280 Operation myEffortOperation; 00281 00283 Operation myTTOperation; 00284 00285 00286 }; 00287 00288 00289 #endif 00290 00291 /****************************************************************************/ 00292