|
SUMO - Simulation of Urban MObility
|
00001 /****************************************************************************/ 00009 // Dijkstra shortest path algorithm using travel time 00010 /****************************************************************************/ 00011 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/ 00012 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors 00013 /****************************************************************************/ 00014 // 00015 // This file is part of SUMO. 00016 // SUMO is free software: you can redistribute it and/or modify 00017 // it under the terms of the GNU General Public License as published by 00018 // the Free Software Foundation, either version 3 of the License, or 00019 // (at your option) any later version. 00020 // 00021 /****************************************************************************/ 00022 #ifndef DijkstraRouterTT_h 00023 #define DijkstraRouterTT_h 00024 00025 00026 // =========================================================================== 00027 // included modules 00028 // =========================================================================== 00029 #ifdef _MSC_VER 00030 #include <windows_config.h> 00031 #else 00032 #include <config.h> 00033 #endif 00034 00035 #include <string> 00036 #include <functional> 00037 #include <vector> 00038 #include <set> 00039 #include <limits> 00040 #include <algorithm> 00041 #include <iterator> 00042 #include <utils/common/InstancePool.h> 00043 #include <utils/common/MsgHandler.h> 00044 #include <utils/common/StdDefs.h> 00045 #include "SUMOAbstractRouter.h" 00046 00047 00048 // =========================================================================== 00049 // class definitions 00050 // =========================================================================== 00066 template<class E, class V, class PF> 00067 class DijkstraRouterTTBase : public SUMOAbstractRouter<E, V>, public PF { 00068 public: 00070 DijkstraRouterTTBase(size_t noE, bool unbuildIsWarning) : 00071 myErrorMsgHandler(unbuildIsWarning ? MsgHandler::getWarningInstance() : MsgHandler::getErrorInstance()) { 00072 for (size_t i = 0; i < noE; i++) { 00073 myEdgeInfos.push_back(EdgeInfo(i)); 00074 } 00075 } 00076 00078 virtual ~DijkstraRouterTTBase() { } 00079 00085 class EdgeInfo { 00086 public: 00088 EdgeInfo(size_t id) 00089 : edge(E::dictionary(id)), traveltime(0), prev(0), visited(false) {} 00090 00092 const E* edge; 00093 00095 SUMOReal traveltime; 00096 00098 EdgeInfo* prev; 00099 00101 bool visited; 00102 00103 }; 00104 00109 class EdgeInfoByTTComparator { 00110 public: 00112 bool operator()(const EdgeInfo* nod1, const EdgeInfo* nod2) const { 00113 if (nod1->traveltime == nod2->traveltime) { 00114 return nod1->edge->getNumericalID() > nod2->edge->getNumericalID(); 00115 } 00116 return nod1->traveltime > nod2->traveltime; 00117 } 00118 }; 00119 00120 virtual SUMOReal getEffort(const E* const e, const V* const v, SUMOReal t) const = 0; 00121 00122 00125 virtual void compute(const E* from, const E* to, const V* const vehicle, 00126 SUMOTime msTime, std::vector<const E*> &into) { 00127 const SUMOReal time = STEPS2TIME(msTime); 00128 for (typename std::vector<EdgeInfo>::iterator i = myEdgeInfos.begin(); i != myEdgeInfos.end(); i++) { 00129 (*i).traveltime = std::numeric_limits<SUMOReal>::max(); 00130 (*i).visited = false; 00131 } 00132 assert(from != 0 && to != 0); 00133 myFrontierList.clear(); 00134 // add begin node 00135 EdgeInfo* const fromInfo = &(myEdgeInfos[from->getNumericalID()]); 00136 fromInfo->traveltime = 0; 00137 fromInfo->prev = 0; 00138 myFrontierList.push_back(fromInfo); 00139 // loop 00140 while (!myFrontierList.empty()) { 00141 // use the node with the minimal length 00142 EdgeInfo* const minimumInfo = myFrontierList.front(); 00143 const E* const minEdge = minimumInfo->edge; 00144 pop_heap(myFrontierList.begin(), myFrontierList.end(), myComparator); 00145 myFrontierList.pop_back(); 00146 // check whether the destination node was already reached 00147 if (minEdge == to) { 00148 buildPathFrom(minimumInfo, into); 00149 return; 00150 } 00151 minimumInfo->visited = true; 00152 const SUMOReal traveltime = minimumInfo->traveltime + getEffort(minEdge, vehicle, time + minimumInfo->traveltime); 00153 // check all ways from the node with the minimal length 00154 unsigned int i = 0; 00155 const unsigned int length_size = minEdge->getNoFollowing(); 00156 for (i = 0; i < length_size; i++) { 00157 const E* const follower = minEdge->getFollower(i); 00158 EdgeInfo* const followerInfo = &(myEdgeInfos[follower->getNumericalID()]); 00159 // check whether it can be used 00160 if (PF::operator()(follower, vehicle)) { 00161 continue; 00162 } 00163 const SUMOReal oldEffort = followerInfo->traveltime; 00164 if (!followerInfo->visited && traveltime < oldEffort) { 00165 followerInfo->traveltime = traveltime; 00166 followerInfo->prev = minimumInfo; 00167 if (oldEffort == std::numeric_limits<SUMOReal>::max()) { 00168 myFrontierList.push_back(followerInfo); 00169 push_heap(myFrontierList.begin(), myFrontierList.end(), myComparator); 00170 } else { 00171 push_heap(myFrontierList.begin(), 00172 find(myFrontierList.begin(), myFrontierList.end(), followerInfo) + 1, 00173 myComparator); 00174 } 00175 } 00176 } 00177 } 00178 myErrorMsgHandler->inform("No connection between '" + from->getID() + "' and '" + to->getID() + "' found."); 00179 } 00180 00181 00182 SUMOReal recomputeCosts(const std::vector<const E*> &edges, const V* const v, SUMOTime msTime) const { 00183 const SUMOReal time = STEPS2TIME(msTime); 00184 SUMOReal costs = 0; 00185 for (typename std::vector<const E*>::const_iterator i = edges.begin(); i != edges.end(); ++i) { 00186 if (PF::operator()(*i, v)) { 00187 return -1; 00188 } 00189 costs += getEffort(*i, v, time + costs); 00190 } 00191 return costs; 00192 } 00193 00194 public: 00196 void buildPathFrom(EdgeInfo* rbegin, std::vector<const E*> &edges) { 00197 std::deque<const E*> tmp; 00198 while (rbegin != 0) { 00199 tmp.push_front((E*) rbegin->edge); // !!! 00200 rbegin = rbegin->prev; 00201 } 00202 std::copy(tmp.begin(), tmp.end(), std::back_inserter(edges)); 00203 } 00204 00205 protected: 00207 std::vector<EdgeInfo> myEdgeInfos; 00208 00210 std::vector<EdgeInfo*> myFrontierList; 00211 00212 EdgeInfoByTTComparator myComparator; 00213 00215 MsgHandler* const myErrorMsgHandler; 00216 00217 }; 00218 00219 00220 template<class E, class V, class PF, class EC> 00221 class DijkstraRouterTT_ByProxi : public DijkstraRouterTTBase<E, V, PF> { 00222 public: 00224 typedef SUMOReal(EC::* Operation)(const E* const, const V* const, SUMOReal) const; 00225 00226 DijkstraRouterTT_ByProxi(size_t noE, bool unbuildIsWarningOnly, EC* receiver, Operation operation) 00227 : DijkstraRouterTTBase<E, V, PF>(noE, unbuildIsWarningOnly), 00228 myReceiver(receiver), myOperation(operation) {} 00229 00230 inline SUMOReal getEffort(const E* const e, const V* const v, SUMOReal t) const { 00231 return (myReceiver->*myOperation)(e, v, t); 00232 } 00233 00234 private: 00236 EC* myReceiver; 00237 00239 Operation myOperation; 00240 00241 00242 }; 00243 00244 00245 template<class E, class V, class PF> 00246 class DijkstraRouterTT_Direct : public DijkstraRouterTTBase<E, V, PF> { 00247 public: 00249 typedef SUMOReal(E::* Operation)(const V* const, SUMOReal) const; 00250 00251 DijkstraRouterTT_Direct(size_t noE, bool unbuildIsWarningOnly, Operation operation) 00252 : DijkstraRouterTTBase<E, V, PF>(noE, unbuildIsWarningOnly), myOperation(operation) {} 00253 00254 inline SUMOReal getEffort(const E* const e, const V* const v, SUMOReal t) const { 00255 return (e->*myOperation)(v, t); 00256 } 00257 00258 private: 00259 Operation myOperation; 00260 00261 }; 00262 00263 00264 #endif 00265 00266 /****************************************************************************/ 00267