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