SUMO - Simulation of Urban MObility

RORouteDef_Alternatives.cpp

Go to the documentation of this file.
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 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines