|
SUMO - Simulation of Urban MObility
|
00001 /****************************************************************************/ 00007 // A route with alternative routes 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 00020 00021 // =========================================================================== 00022 // included modules 00023 // =========================================================================== 00024 #ifdef _MSC_VER 00025 #include <windows_config.h> 00026 #else 00027 #include <config.h> 00028 #endif 00029 00030 #include <iomanip> 00031 #include <string> 00032 #include <vector> 00033 #include <cmath> 00034 #include <math.h> 00035 #include <cassert> 00036 #include <limits> 00037 #include <iostream> 00038 #include "ROEdge.h" 00039 #include "RORouteDef.h" 00040 #include "RORoute.h" 00041 #include "ROVehicle.h" 00042 #include "ROHelper.h" 00043 #include <utils/common/SUMOAbstractRouter.h> 00044 #include "RORouteDef_Alternatives.h" 00045 #include <utils/common/StdDefs.h> 00046 #include <utils/geom/GeomHelper.h> 00047 #include <utils/common/RandHelper.h> 00048 #include <utils/common/UtilExceptions.h> 00049 #include <utils/iodevices/OutputDevice.h> 00050 00051 #ifdef CHECK_MEMORY_LEAKS 00052 #include <foreign/nvwa/debug_new.h> 00053 #endif // CHECK_MEMORY_LEAKS 00054 00055 00056 // =========================================================================== 00057 // method definitions 00058 // =========================================================================== 00059 RORouteDef_Alternatives::RORouteDef_Alternatives(const std::string& id, 00060 unsigned int lastUsed, 00061 const SUMOReal beta, const SUMOReal gawronA, const SUMOReal logitGamma, 00062 const int maxRoutes, const bool keepRoutes, const bool skipRouteCalculation) throw() 00063 : RORouteDef(id, 0), myLastUsed((int) lastUsed), 00064 myBeta(beta), myGawronA(gawronA), myLogitGamma(logitGamma), 00065 myMaxRouteNumber(maxRoutes), myKeepRoutes(keepRoutes), 00066 mySkipRouteCalculation(skipRouteCalculation) { 00067 } 00068 00069 00070 RORouteDef_Alternatives::~RORouteDef_Alternatives() throw() { 00071 for (AlternativesVector::iterator i=myAlternatives.begin(); i!=myAlternatives.end(); i++) { 00072 delete *i; 00073 } 00074 } 00075 00076 00077 void 00078 RORouteDef_Alternatives::addLoadedAlternative(RORoute* alt) { 00079 myAlternatives.push_back(alt); 00080 } 00081 00082 00083 00084 RORoute* 00085 RORouteDef_Alternatives::buildCurrentRoute(SUMOAbstractRouter<ROEdge,ROVehicle> &router, 00086 SUMOTime begin, const ROVehicle& veh) const { 00087 if (mySkipRouteCalculation) { 00088 myLastUsed = 0; 00089 myNewRoute = false; 00090 return myAlternatives[myLastUsed]; 00091 } 00092 // recompute duration of the last route used 00093 // build a new route to test whether it is better 00094 std::vector<const ROEdge*> edges; 00095 router.compute(myAlternatives[0]->getFirst(), myAlternatives[0]->getLast(), &veh, begin, edges); 00096 RORoute* opt = new RORoute(myID, 0, 1, edges, copyColorIfGiven()); 00097 SUMOReal costs = router.recomputeCosts(opt->getEdgeVector(), &veh, begin); 00098 // check whether the same route was already used 00099 myLastUsed = findRoute(opt); 00100 myNewRoute = true; 00101 // delete the route when it already existed 00102 if (myLastUsed>=0) { 00103 delete opt; 00104 myNewRoute = false; 00105 myAlternatives[myLastUsed]->setCosts(costs); 00106 return myAlternatives[myLastUsed]; 00107 } 00108 // return the built route 00109 opt->setCosts(costs); 00110 return opt; 00111 } 00112 00113 00114 int 00115 RORouteDef_Alternatives::findRoute(RORoute* opt) const { 00116 for (unsigned int i=0; i<myAlternatives.size(); i++) { 00117 if (opt->getEdgeVector() == myAlternatives[i]->getEdgeVector()) { 00118 return (int) i; 00119 } 00120 } 00121 return -1; 00122 } 00123 00124 00125 void 00126 RORouteDef_Alternatives::addAlternative(SUMOAbstractRouter<ROEdge,ROVehicle> &router, 00127 const ROVehicle* const veh, RORoute* current, SUMOTime begin) { 00128 // add the route when it's new 00129 if (myLastUsed<0) { 00130 myAlternatives.push_back(current); 00131 myLastUsed = (int) myAlternatives.size() - 1; 00132 } 00133 // recompute the costs and (when a new route was added) the probabilities 00134 for (AlternativesVector::iterator i=myAlternatives.begin(); i!=myAlternatives.end(); i++) { 00135 RORoute* alt = *i; 00136 // apply changes for old routes only 00137 // (the costs for the current were computed already) 00138 if ((*i)!=current||!myNewRoute) { 00139 // recompute the costs for old routes 00140 const SUMOReal oldCosts = alt->getCosts(); 00141 const SUMOReal newCosts = router.recomputeCosts(alt->getEdgeVector(), veh, begin); 00142 if (newCosts<0) { 00143 throw ProcessError("Route '" + current->getID() + "' (vehicle '" + veh->getID() + "') is not valid."); 00144 } 00145 if (myLogitGamma >= 0) { 00146 alt->setCosts(newCosts/3600.); //@todo need configurable scaling factor esp. for non travel time weights 00147 } else { 00148 alt->setCosts(myBeta * newCosts + ((SUMOReal) 1.0 - myBeta) * oldCosts); 00149 } 00150 } 00151 assert(myAlternatives.size()!=0); 00152 if (myNewRoute) { 00153 if ((*i)!=current) { 00154 alt->setProbability( 00155 alt->getProbability() 00156 * SUMOReal(myAlternatives.size()-1) 00157 / SUMOReal(myAlternatives.size())); 00158 } else { 00159 alt->setProbability((SUMOReal)(1.0 / (SUMOReal) myAlternatives.size())); 00160 } 00161 } 00162 } 00163 assert(myAlternatives.size()!=0); 00164 // compute the probabilities 00165 if (myLogitGamma >= 0) { 00166 calculateLogitProbabilities(); 00167 } else { 00168 for (AlternativesVector::iterator i=myAlternatives.begin(); i!=myAlternatives.end()-1; i++) { 00169 RORoute* pR = *i; 00170 for (AlternativesVector::iterator j=i+1; j!=myAlternatives.end(); j++) { 00171 RORoute* pS = *j; 00172 // see [Gawron, 1998] (4.2) 00173 SUMOReal delta = 00174 (pS->getCosts() - pR->getCosts()) / 00175 (pS->getCosts() + pR->getCosts()); 00176 // see [Gawron, 1998] (4.3a, 4.3b) 00177 SUMOReal newPR = gawronF(pR->getProbability(), pS->getProbability(), delta); 00178 SUMOReal newPS = pR->getProbability() + pS->getProbability() - newPR; 00179 if (ISNAN(newPR)||ISNAN(newPS)) { 00180 newPR = pS->getCosts() > pR->getCosts() 00181 ? (SUMOReal) 1. : 0; 00182 newPS = pS->getCosts() > pR->getCosts() 00183 ? 0 : (SUMOReal) 1.; 00184 } 00185 newPR = MIN2((SUMOReal) MAX2(newPR, (SUMOReal) 0), (SUMOReal) 1); 00186 newPS = MIN2((SUMOReal) MAX2(newPS, (SUMOReal) 0), (SUMOReal) 1); 00187 pR->setProbability(newPR); 00188 pS->setProbability(newPS); 00189 } 00190 } 00191 } 00192 if (!myKeepRoutes) { 00193 // remove with probability of 0 (not mentioned in Gawron) 00194 for (AlternativesVector::iterator i=myAlternatives.begin(); i!=myAlternatives.end();) { 00195 if ((*i)->getProbability()==0) { 00196 i = myAlternatives.erase(i); 00197 } else { 00198 i++; 00199 } 00200 } 00201 } 00202 // find the route to use 00203 SUMOReal chosen = RandHelper::rand(); 00204 int pos = 0; 00205 for (AlternativesVector::iterator i=myAlternatives.begin(); i!=myAlternatives.end()-1; i++, pos++) { 00206 chosen = chosen - (*i)->getProbability(); 00207 if (chosen<=0) { 00208 myLastUsed = pos; 00209 return; 00210 } 00211 } 00212 myLastUsed = pos; 00213 } 00214 00215 00216 SUMOReal 00217 RORouteDef_Alternatives::getThetaForCLogit() const { 00218 SUMOReal sum = 0.; 00219 SUMOReal diff = 0.; 00220 SUMOReal min = std::numeric_limits<SUMOReal>::max(); 00221 for (AlternativesVector::const_iterator i=myAlternatives.begin(); i!=myAlternatives.end(); i++) { 00222 const SUMOReal cost = (*i)->getCosts(); 00223 sum += cost; 00224 if (cost < min) { 00225 min = cost; 00226 } 00227 } 00228 const SUMOReal meanCost = sum / SUMOReal(myAlternatives.size()); 00229 for (AlternativesVector::const_iterator i=myAlternatives.begin(); i!=myAlternatives.end(); i++) { 00230 diff += pow((*i)->getCosts() - meanCost, 2); 00231 } 00232 const SUMOReal sdCost = sqrt(diff/SUMOReal(myAlternatives.size())); 00233 if (sdCost > 0.04) { // Magic numbers from Lohse book 00234 return PI / (sqrt(6.) * sdCost * min); 00235 } 00236 return 1.; 00237 } 00238 00239 00240 void 00241 RORouteDef_Alternatives::calculateLogitProbabilities() { 00242 const SUMOReal theta = getThetaForCLogit(); 00243 if (myBeta > 0) { 00244 // calculate commonalities 00245 for (AlternativesVector::const_iterator i=myAlternatives.begin(); i!=myAlternatives.end(); i++) { 00246 const RORoute* pR = *i; 00247 SUMOReal lengthR = 0; 00248 const std::vector<const ROEdge*> &edgesR = pR->getEdgeVector(); 00249 for (std::vector<const ROEdge*>::const_iterator edge = edgesR.begin(); edge != edgesR.end(); ++edge) { 00250 lengthR += (*edge)->getTravelTime(0, 0)/3600.; 00251 } 00252 SUMOReal overlapSum = 0; 00253 for (AlternativesVector::const_iterator j=myAlternatives.begin(); j!=myAlternatives.end(); j++) { 00254 const RORoute* pS = *j; 00255 SUMOReal overlapLength = 0.; 00256 SUMOReal lengthS = 0; 00257 const std::vector<const ROEdge*> &edgesS = pS->getEdgeVector(); 00258 for (std::vector<const ROEdge*>::const_iterator edge = edgesS.begin(); edge != edgesS.end(); ++edge) { 00259 lengthS += (*edge)->getTravelTime(0, 0)/3600.; 00260 if (std::find(edgesR.begin(), edgesR.end(), *edge) != edgesR.end()) { 00261 overlapLength += (*edge)->getTravelTime(0, 0)/3600.; 00262 } 00263 } 00264 overlapSum += pow(overlapLength/sqrt(lengthR * lengthS), myLogitGamma); 00265 } 00266 myCommonalities[pR] = myBeta * log(overlapSum); 00267 } 00268 } 00269 for (AlternativesVector::iterator i=myAlternatives.begin(); i!=myAlternatives.end(); i++) { 00270 RORoute* pR = *i; 00271 SUMOReal weightedSum = 0; 00272 for (AlternativesVector::iterator j=myAlternatives.begin(); j!=myAlternatives.end(); j++) { 00273 RORoute* pS = *j; 00274 weightedSum += exp(theta * (pR->getCosts() - pS->getCosts() + myCommonalities[pR] - myCommonalities[pS])); 00275 } 00276 pR->setProbability(1./weightedSum); 00277 } 00278 } 00279 00280 00281 SUMOReal 00282 RORouteDef_Alternatives::gawronF(SUMOReal pdr, SUMOReal pds, SUMOReal x) { 00283 if (((pdr*gawronG(myGawronA, x)+pds)==0)) { 00284 return std::numeric_limits<SUMOReal>::max(); 00285 } 00286 return (pdr*(pdr+pds)*gawronG(myGawronA, x)) / 00287 (pdr*gawronG(myGawronA, x)+pds); 00288 } 00289 00290 00291 SUMOReal 00292 RORouteDef_Alternatives::gawronG(SUMOReal a, SUMOReal x) { 00293 if (((1.0-(x*x))==0)) { 00294 return std::numeric_limits<SUMOReal>::max(); 00295 } 00296 return (SUMOReal) exp((a*x)/(1.0-(x*x))); 00297 } 00298 00299 00300 RORouteDef* 00301 RORouteDef_Alternatives::copy(const std::string& id) const { 00302 RORouteDef_Alternatives* ret = new RORouteDef_Alternatives(id, 00303 myLastUsed, myBeta, myGawronA, myLogitGamma, myMaxRouteNumber, myKeepRoutes, mySkipRouteCalculation); 00304 for (std::vector<RORoute*>::const_iterator i=myAlternatives.begin(); i!=myAlternatives.end(); i++) { 00305 ret->addLoadedAlternative(new RORoute(*(*i))); 00306 } 00307 return ret; 00308 } 00309 00310 00311 void 00312 RORouteDef_Alternatives::invalidateLast() { 00313 myLastUsed = -1; 00314 } 00315 00316 00317 void 00318 RORouteDef_Alternatives::removeLast() { 00319 assert(myAlternatives.size()>=2); 00320 myAlternatives.erase(myAlternatives.end()-1); 00321 myLastUsed = (int) myAlternatives.size() - 1; 00322 // !!! recompute probabilities 00323 } 00324 00325 00326 OutputDevice& 00327 RORouteDef_Alternatives::writeXMLDefinition(SUMOAbstractRouter<ROEdge,ROVehicle> &router, 00328 OutputDevice& dev, const ROVehicle* const veh, 00329 bool asAlternatives, bool withExitTimes) const { 00330 // (optional) alternatives header 00331 if (asAlternatives) { 00332 dev.openTag("routeDistribution") << " last=\"" << myLastUsed << "\">\n"; 00333 for (size_t i=0; i!=myAlternatives.size(); i++) { 00334 const RORoute& alt = *(myAlternatives[i]); 00335 dev.openTag("route") << " cost=\"" << alt.getCosts(); 00336 dev.setPrecision(8); 00337 dev << "\" probability=\"" << alt.getProbability(); 00338 dev.setPrecision(); 00339 if (alt.getColor()!=0) { 00340 dev << "\" color=\"" << *alt.getColor(); 00341 } else if (myColor!=0) { 00342 dev << "\" color=\"" << *myColor; 00343 } 00344 dev << "\" edges=\"" << alt.getEdgeVector(); 00345 if (withExitTimes) { 00346 SUMOReal time = STEPS2TIME(veh->getDepartureTime()); 00347 dev << "\" exitTimes=\""; 00348 std::vector<const ROEdge*>::const_iterator i = alt.getEdgeVector().begin(); 00349 for (; i!=alt.getEdgeVector().end(); ++i) { 00350 if (i != alt.getEdgeVector().begin()) { 00351 dev << " "; 00352 } 00353 time += (*i)->getTravelTime(veh, (SUMOTime) time); 00354 dev << time; 00355 } 00356 } 00357 (dev << "\"").closeTag(true); 00358 } 00359 dev.closeTag(); 00360 return dev; 00361 } else { 00362 return myAlternatives[myLastUsed]->writeXMLDefinition(router, dev, veh, asAlternatives, withExitTimes); 00363 } 00364 } 00365 00366 00367 00368 /****************************************************************************/ 00369