|
SUMO - Simulation of Urban MObility
|
00001 /****************************************************************************/ 00007 // Dijkstra shortest path algorithm using travel time 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 DijkstraRouterTT_h 00020 #define DijkstraRouterTT_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 <iterator> 00039 #include <utils/common/InstancePool.h> 00040 #include <utils/common/MsgHandler.h> 00041 #include <utils/common/StdDefs.h> 00042 #include "SUMOAbstractRouter.h" 00043 00044 00045 // =========================================================================== 00046 // class definitions 00047 // =========================================================================== 00063 template<class E, class V, class PF> 00064 class DijkstraRouterTTBase : public SUMOAbstractRouter<E, V>, public PF { 00065 public: 00067 DijkstraRouterTTBase(size_t noE, bool unbuildIsWarning) : 00068 myErrorMsgHandler(unbuildIsWarning ? MsgHandler::getWarningInstance() : MsgHandler::getErrorInstance()) { 00069 for (size_t i = 0; i < noE; i++) { 00070 myEdgeInfos.push_back(EdgeInfo(i)); 00071 } 00072 } 00073 00075 virtual ~DijkstraRouterTTBase() { } 00076 00082 class EdgeInfo { 00083 public: 00085 EdgeInfo(size_t id) 00086 : edge(E::dictionary(id)), traveltime(0), prev(0), visited(false) {} 00087 00089 const E* edge; 00090 00092 SUMOReal traveltime; 00093 00095 EdgeInfo* prev; 00096 00098 bool visited; 00099 00100 }; 00101 00106 class EdgeInfoByTTComparator { 00107 public: 00109 bool operator()(const EdgeInfo* nod1, const EdgeInfo* nod2) const { 00110 if (nod1->traveltime == nod2->traveltime) { 00111 return nod1->edge->getNumericalID() > nod2->edge->getNumericalID(); 00112 } 00113 return nod1->traveltime>nod2->traveltime; 00114 } 00115 }; 00116 00117 virtual SUMOReal getEffort(const E* const e, const V* const v, SUMOReal t) = 0; 00118 00119 00122 virtual void compute(const E* from, const E* to, const V* const vehicle, 00123 SUMOTime msTime, std::vector<const E*> &into) { 00124 00125 SUMOReal time = (SUMOReal) msTime / 1000.; 00126 for (typename std::vector<EdgeInfo>::iterator i=myEdgeInfos.begin(); i!=myEdgeInfos.end(); i++) { 00127 (*i).traveltime = std::numeric_limits<SUMOReal>::max(); 00128 (*i).visited = false; 00129 } 00130 assert(from!=0&&to!=0); 00131 myFrontierList.clear(); 00132 // add begin node 00133 EdgeInfo* const fromInfo = &(myEdgeInfos[from->getNumericalID()]); 00134 fromInfo->traveltime = 0; 00135 fromInfo->prev = 0; 00136 myFrontierList.push_back(fromInfo); 00137 // loop 00138 while (!myFrontierList.empty()) { 00139 // use the node with the minimal length 00140 EdgeInfo* const minimumInfo = myFrontierList.front(); 00141 const E* const minEdge = minimumInfo->edge; 00142 pop_heap(myFrontierList.begin(), myFrontierList.end(), myComparator); 00143 myFrontierList.pop_back(); 00144 // check whether the destination node was already reached 00145 if (minEdge == to) { 00146 buildPathFrom(minimumInfo, into); 00147 return; 00148 } 00149 minimumInfo->visited = true; 00150 const SUMOReal traveltime = minimumInfo->traveltime + getEffort(minEdge, vehicle, time + (SUMOTime)minimumInfo->traveltime); 00151 // check all ways from the node with the minimal length 00152 unsigned int i = 0; 00153 const unsigned int length_size = minEdge->getNoFollowing(); 00154 for (i=0; i<length_size; i++) { 00155 const E* const follower = minEdge->getFollower(i); 00156 EdgeInfo* const followerInfo = &(myEdgeInfos[follower->getNumericalID()]); 00157 // check whether it can be used 00158 if (PF::operator()(follower, vehicle)) { 00159 continue; 00160 } 00161 const SUMOReal oldEffort = followerInfo->traveltime; 00162 if (!followerInfo->visited && traveltime < oldEffort) { 00163 followerInfo->traveltime = traveltime; 00164 followerInfo->prev = minimumInfo; 00165 if (oldEffort == std::numeric_limits<SUMOReal>::max()) { 00166 myFrontierList.push_back(followerInfo); 00167 push_heap(myFrontierList.begin(), myFrontierList.end(), myComparator); 00168 } else { 00169 push_heap(myFrontierList.begin(), 00170 find(myFrontierList.begin(), myFrontierList.end(), followerInfo) + 1, 00171 myComparator); 00172 } 00173 } 00174 } 00175 } 00176 myErrorMsgHandler->inform("No connection between '" + from->getID() + "' and '" + to->getID() + "' found."); 00177 } 00178 00179 00180 SUMOReal recomputeCosts(const std::vector<const E*> &edges, const V* const v, SUMOTime msTime) throw() { 00181 SUMOReal time = (SUMOReal) msTime / 1000.; 00182 SUMOReal costs = 0; 00183 for (typename std::vector<const E*>::const_iterator i=edges.begin(); i!=edges.end(); ++i) { 00184 if (PF::operator()(*i, v)) { 00185 return -1; 00186 } 00187 costs += getEffort(*i, v, (SUMOTime)(time + costs)); 00188 } 00189 return costs; 00190 } 00191 00192 public: 00194 void buildPathFrom(EdgeInfo* rbegin, std::vector<const E*> &edges) { 00195 std::deque<const E*> tmp; 00196 while (rbegin!=0) { 00197 tmp.push_front((E*) rbegin->edge); // !!! 00198 rbegin = rbegin->prev; 00199 } 00200 std::copy(tmp.begin(), tmp.end(), std::back_inserter(edges)); 00201 } 00202 00203 protected: 00205 std::vector<EdgeInfo> myEdgeInfos; 00206 00208 std::vector<EdgeInfo*> myFrontierList; 00209 00210 EdgeInfoByTTComparator myComparator; 00211 00213 MsgHandler* const myErrorMsgHandler; 00214 00215 }; 00216 00217 00218 template<class E, class V, class PF, class EC> 00219 class DijkstraRouterTT_ByProxi : public DijkstraRouterTTBase<E, V, PF> { 00220 public: 00222 typedef SUMOReal(EC::* Operation)(const E* const, const V* const, SUMOReal) const; 00223 00224 DijkstraRouterTT_ByProxi(size_t noE, bool unbuildIsWarningOnly, EC* receiver, Operation operation) 00225 : DijkstraRouterTTBase<E, V, PF>(noE, unbuildIsWarningOnly), 00226 myReceiver(receiver), myOperation(operation) {} 00227 00228 inline SUMOReal getEffort(const E* const e, const V* const v, SUMOReal t) { 00229 return (myReceiver->*myOperation)(e, v, t); 00230 } 00231 00232 private: 00234 EC* myReceiver; 00235 00237 Operation myOperation; 00238 00239 00240 }; 00241 00242 00243 template<class E, class V, class PF> 00244 class DijkstraRouterTT_Direct : public DijkstraRouterTTBase<E, V, PF> { 00245 public: 00247 typedef SUMOReal(E::* Operation)(const V* const, SUMOReal) const; 00248 00249 DijkstraRouterTT_Direct(size_t noE, bool unbuildIsWarningOnly, Operation operation) 00250 : DijkstraRouterTTBase<E, V, PF>(noE, unbuildIsWarningOnly), myOperation(operation) {} 00251 00252 inline SUMOReal getEffort(const E* const e, const V* const v, SUMOReal t) { 00253 return (e->*myOperation)(v, t); 00254 } 00255 00256 private: 00257 Operation myOperation; 00258 00259 }; 00260 00261 00262 #endif 00263 00264 /****************************************************************************/ 00265