|
SUMO - Simulation of Urban MObility
|
00001 /****************************************************************************/ 00009 // Dijkstra shortest path algorithm using other values 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 DijkstraRouterEffort_h 00023 #define DijkstraRouterEffort_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 <utils/common/InstancePool.h> 00042 #include <utils/common/MsgHandler.h> 00043 #include <utils/common/StdDefs.h> 00044 #include "SUMOAbstractRouter.h" 00045 00046 00047 // =========================================================================== 00048 // class definitions 00049 // =========================================================================== 00065 template<class E, class V, class PF> 00066 class DijkstraRouterEffortBase : public SUMOAbstractRouter<E, V>, public PF { 00067 public: 00069 DijkstraRouterEffortBase(size_t noE, bool unbuildIsWarning) : 00070 myErrorMsgHandler(unbuildIsWarning ? MsgHandler::getWarningInstance() : MsgHandler::getErrorInstance()) { 00071 for (size_t i = 0; i < noE; i++) { 00072 myEdgeInfos.push_back(EdgeInfo(i)); 00073 } 00074 } 00075 00077 virtual ~DijkstraRouterEffortBase() { } 00078 00084 class EdgeInfo { 00085 public: 00087 EdgeInfo() : edge(0), effort(0), leaveTime(0), prev(0), visited(false) {} 00088 00090 EdgeInfo(size_t id) 00091 : edge(E::dictionary(id)), effort(0), leaveTime(0), prev(0), visited(false) {} 00092 00094 const E* edge; 00095 00097 SUMOReal effort; 00098 00100 SUMOReal leaveTime; 00101 00103 EdgeInfo* prev; 00104 00106 bool visited; 00107 00108 }; 00109 00114 class EdgeInfoByEffortComparator { 00115 public: 00117 bool operator()(EdgeInfo* nod1, EdgeInfo* nod2) const { 00118 if (nod1->effort == nod2->effort) { 00119 return nod1->edge->getNumericalID() > nod2->edge->getNumericalID(); 00120 } 00121 return nod1->effort > nod2->effort; 00122 } 00123 }; 00124 00125 virtual SUMOReal getEffort(const E* const e, const V* const v, SUMOReal t) const = 0; 00126 virtual SUMOReal getTravelTime(const E* const e, const V* const v, SUMOReal t) const = 0; 00127 00128 00131 virtual void compute(const E* from, const E* to, const V* const vehicle, 00132 SUMOTime msTime, std::vector<const E*> &into) { 00133 for (typename std::vector<EdgeInfo>::iterator i = myEdgeInfos.begin(); i != myEdgeInfos.end(); i++) { 00134 (*i).effort = std::numeric_limits<SUMOReal>::max(); 00135 (*i).visited = false; 00136 } 00137 assert(from != 0 && to != 0); 00138 myFrontierList.clear(); 00139 // add begin node 00140 EdgeInfo* const fromInfo = &(myEdgeInfos[from->getNumericalID()]); 00141 fromInfo->effort = 0; 00142 fromInfo->prev = 0; 00143 fromInfo->leaveTime = STEPS2TIME(msTime); 00144 myFrontierList.push_back(fromInfo); 00145 // loop 00146 while (!myFrontierList.empty()) { 00147 // use the node with the minimal length 00148 EdgeInfo* const minimumInfo = myFrontierList.front(); 00149 const E* const minEdge = minimumInfo->edge; 00150 pop_heap(myFrontierList.begin(), myFrontierList.end(), myComparator); 00151 myFrontierList.pop_back(); 00152 // check whether the destination node was already reached 00153 if (minEdge == to) { 00154 buildPathFrom(minimumInfo, into); 00155 return; 00156 } 00157 minimumInfo->visited = true; 00158 const SUMOReal effort = minimumInfo->effort + getEffort(minEdge, vehicle, minimumInfo->leaveTime); 00159 const SUMOReal leaveTime = minimumInfo->leaveTime + getTravelTime(minEdge, vehicle, minimumInfo->leaveTime); 00160 // check all ways from the node with the minimal length 00161 unsigned int i = 0; 00162 const unsigned int length_size = minEdge->getNoFollowing(); 00163 for (i = 0; i < length_size; i++) { 00164 const E* const follower = minEdge->getFollower(i); 00165 EdgeInfo* const followerInfo = &(myEdgeInfos[follower->getNumericalID()]); 00166 // check whether it can be used 00167 if (PF::operator()(follower, vehicle)) { 00168 continue; 00169 } 00170 const SUMOReal oldEffort = followerInfo->effort; 00171 if (!followerInfo->visited && effort < oldEffort) { 00172 followerInfo->effort = effort; 00173 followerInfo->leaveTime = leaveTime; 00174 followerInfo->prev = minimumInfo; 00175 if (oldEffort == std::numeric_limits<SUMOReal>::max()) { 00176 myFrontierList.push_back(followerInfo); 00177 push_heap(myFrontierList.begin(), myFrontierList.end(), myComparator); 00178 } else { 00179 push_heap(myFrontierList.begin(), 00180 find(myFrontierList.begin(), myFrontierList.end(), followerInfo) + 1, 00181 myComparator); 00182 } 00183 } 00184 } 00185 } 00186 myErrorMsgHandler->inform("No connection between '" + from->getID() + "' and '" + to->getID() + "' found."); 00187 } 00188 00189 00190 SUMOReal recomputeCosts(const std::vector<const E*> &edges, const V* const v, SUMOTime msTime) const { 00191 SUMOReal costs = 0; 00192 SUMOReal t = STEPS2TIME(msTime); 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, t); 00198 t += getTravelTime(*i, v, 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) const { 00240 return (myReceiver->*myEffortOperation)(e, v, t); 00241 } 00242 00243 inline SUMOReal getTravelTime(const E* const e, const V* const v, SUMOReal t) const { 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) const { 00271 return (e->*myEffortOperation)(v, t); 00272 } 00273 00274 inline SUMOReal getTravelTime(const E* const e, const V* const v, SUMOReal t) const { 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