SUMO - Simulation of Urban MObility

RORouteDef_Alternatives.cpp

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