SUMO - Simulation of Urban MObility
AGWorkAndSchool.cpp
Go to the documentation of this file.
00001 /****************************************************************************/
00010 // Generates trips to work and to school
00011 /****************************************************************************/
00012 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
00013 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors
00014 // activitygen module
00015 // Copyright 2010 TUM (Technische Universitaet Muenchen, http://www.tum.de/)
00016 /****************************************************************************/
00017 //
00018 //   This file is part of SUMO.
00019 //   SUMO is free software: you can redistribute it and/or modify
00020 //   it under the terms of the GNU General Public License as published by
00021 //   the Free Software Foundation, either version 3 of the License, or
00022 //   (at your option) any later version.
00023 //
00024 /****************************************************************************/
00025 
00026 
00027 // ===========================================================================
00028 // included modules
00029 // ===========================================================================
00030 #ifdef _MSC_VER
00031 #include <windows_config.h>
00032 #else
00033 #include <config.h>
00034 #endif
00035 
00036 #include "AGWorkAndSchool.h"
00037 #include <list>
00038 #include "../city/AGCar.h"
00039 
00040 
00041 // ===========================================================================
00042 // method definitions
00043 // ===========================================================================
00044 bool
00045 AGWorkAndSchool::generateTrips() {
00046     //buildDestinations();
00047     // generation of the waiting list for the accompaniment
00048     buildChildrenAccompaniment();
00049 
00050     buildWorkDestinations();
00051 
00052     if (hh->getCarNbr() < (int)personsDrivingCars.size()) {
00053         return false;    //to rebuild the household
00054     }
00055     if (childrenNeedingCarAccompaniment.size() != 0 && hh->getCarNbr() == 0) {
00056         return false;    //to rebuild the household
00057     }
00058     if (adultNeedingCarAccompaniment.size() != 0 && hh->getCarNbr() == 0) {
00059         return false;
00060     }
00061 
00062     carAllocation();
00063 
00064     if (personsDrivingCars.empty() && notNeedingDrivers.empty()) {
00065         genDone = true;
00066         return true; // no trip to generate
00067     }
00068 
00069     if (! carsToTrips()) {
00070         return false;
00071     }
00072 
00073     genDone = true;
00074     return true;
00075 }
00076 
00077 void
00078 AGWorkAndSchool::buildChildrenAccompaniment() {
00079     std::list<AGChild>::iterator itC;
00080     for (itC = hh->children.begin() ; itC != hh->children.end() ; ++itC) {
00081         if (itC->haveASchool()) {
00082             if (this->availableTranspMeans(hh->getPosition(), itC->getSchoolLocation()) == 0) {
00083                 //in this case the school is far from home and bus stations too
00084                 this->childrenNeedingCarAccompaniment.push_back(*itC);
00085             }
00086         }
00087     }
00088 }
00089 
00090 void
00091 AGWorkAndSchool::buildWorkDestinations() {
00092     std::list<AGAdult>::iterator itA;
00093     for (itA = hh->adults.begin() ; itA != hh->adults.end() ; ++itA) {
00094         if (itA->isWorking()) {
00095             if (this->possibleTranspMean(itA->getWorkPosition().getPosition()) % 2 == 0) {
00096                 //not too close, to not being able to go by foot
00097                 if (this->possibleTranspMean(itA->getWorkPosition().getPosition()) > 4) {
00098                     //too far from home ==> Car or Bus AND Car and bus are possible
00099                     workingPeoplePossCar.push_back(*itA);
00100                 } else if (this->possibleTranspMean(itA->getWorkPosition().getPosition()) == 4) {
00101                     //only the car is possible (and there is one (use of possibleTranspMean))
00102                     if (hh->getCarNbr() > (int)personsDrivingCars.size()) {
00103                         personsDrivingCars.push_back(*itA);
00104                     } else {
00105                         adultNeedingCarAccompaniment.push_back(*itA);
00106                     }
00107                 }
00108             }
00109         }
00110     }
00111 
00112     // sometimes, people still have choice: when vehicles are available and their car take a bus.
00113     std::list<AGAdult>::iterator it;
00114     for (it = workingPeoplePossCar.begin() ; it != workingPeoplePossCar.end() ; ++it) {
00115         if (possibleTranspMean(it->getWorkPosition().getPosition()) == 6 && hh->getCarNbr() > (int)personsDrivingCars.size()) {
00116             //car or bus (always because of workDestinations' construction) AND at least one car not used
00117             if (hh->adults.front().decide(this->carPreference)) {
00118                 personsDrivingCars.push_back(*it);
00119             }
00120         }
00121     }
00122 }
00123 
00124 void
00125 AGWorkAndSchool::carAllocation() {
00126     // only two adults are possibles: no car, 1 car, 2 cars and more
00127     // the only choice case: 1 car / 2 adults needing this car (otherwise no choice problems)
00128     if (! personsDrivingCars.empty() && ! adultNeedingCarAccompaniment.empty()) {
00129         //in that case there is only one element in each list and only one car.
00130         if (adultNeedingCarAccompaniment.front().getWorkPosition().getOpening() >= personsDrivingCars.front().getWorkPosition().getOpening()) {
00131             //we will invert the driver and the accompanied
00132             personsDrivingCars.push_back(adultNeedingCarAccompaniment.front());
00133             adultNeedingCarAccompaniment.pop_front();
00134             adultNeedingCarAccompaniment.push_back(personsDrivingCars.front());
00135             personsDrivingCars.pop_front();
00136         }
00137     }
00138     if (personsDrivingCars.empty() && ! childrenNeedingCarAccompaniment.empty()) {
00139         //at least one adult exists because no household contains less than one adult
00140         if (workingPeoplePossCar.size() != hh->getAdultNbr()) { //personsDrivingCars.size() + adultNeedingCarAccompaniment.size() is equal to 0
00141             std::list<AGAdult>::iterator itUA;
00142             for (itUA = hh->adults.begin() ; itUA != hh->adults.end() ; ++itUA) {
00143                 if (! itUA->isWorking()) {
00144                     notNeedingDrivers.push_back(*itUA);
00145                     break;
00146                 }
00147             }
00148         } else {
00149             personsDrivingCars.push_back(workingPeoplePossCar.front());
00150             workingPeoplePossCar.pop_front();
00151         }
00152     }
00153 }
00154 
00155 bool
00156 AGWorkAndSchool::carsToTrips() {
00157     std::list<AGAdult>::iterator itDriA;
00158     std::list<AGCar>::iterator itCar = hh->cars.begin();
00159     for (itDriA = personsDrivingCars.begin() ; itDriA != personsDrivingCars.end() ; ++itDriA) {
00160         //check if the number of cars is lower than the number of drivers
00161         if (itCar == hh->cars.end()) {
00162             return false;
00163         }
00164         AGTrip trip(hh->getPosition(), itDriA->getWorkPosition().getPosition(), *itCar, depHour(hh->getPosition(), itDriA->getWorkPosition().getPosition(), itDriA->getWorkPosition().getOpening()));
00165         ++itCar;
00166         tempTrip.push_back(trip);
00167     }
00168 
00169     std::list<AGAdult>::iterator itAccA;
00170     for (itAccA = adultNeedingCarAccompaniment.begin() ; itAccA != adultNeedingCarAccompaniment.end() ; ++itAccA) {
00171         AGTrip trip(hh->getPosition(), itAccA->getWorkPosition().getPosition(), depHour(hh->getPosition(), itAccA->getWorkPosition().getPosition(), itAccA->getWorkPosition().getOpening()));
00172         tempAccTrip.push_back(trip);
00173     }
00174 
00175     std::list<AGChild>::iterator itAccC;
00176     for (itAccC = childrenNeedingCarAccompaniment.begin() ; itAccC != childrenNeedingCarAccompaniment.end() ; ++itAccC) {
00177         AGTrip trip(hh->getPosition(), itAccC->getSchoolLocation(), depHour(hh->getPosition(), itAccC->getSchoolLocation(), itAccC->getSchoolOpeining()));
00178         tempAccTrip.push_back(trip);
00179     }
00180 
00181     checkAndBuildTripConsistancy();
00182     if (isThereUnusedCar() && ! checkDriversScheduleMatching()) {
00183         makePossibleDriversDrive();
00184     }
00185 
00186     generateListTrips();
00187     return true;
00188 }
00189 
00190 bool
00191 AGWorkAndSchool::isThereUnusedCar() {
00192     return (hh->getCarNbr() > static_cast<int>(notNeedingDrivers.size() + personsDrivingCars.size()));
00193 }
00194 
00195 bool
00196 AGWorkAndSchool::checkAndBuildTripConsistancy() {
00197     bool finish = false;
00198     int diff1, diff2;
00199     int arrTime;
00200     std::list<AGTrip>::iterator it1, it2;
00201 
00202     while (!finish) {
00203         finish = true;
00204         for (it1 = tempAccTrip.begin() ; it1 != tempAccTrip.end() ; ++it1) {
00205             for (it2 = tempAccTrip.begin() ; it2 != tempAccTrip.end() ; ++it2) {
00206                 if (it1 == it2) {
00207                     continue;
00208                 }
00209                 diff1 = it2->getTime() - it1->getRideBackArrTime(this->timePerKm);
00210                 diff2 = it1->getTime() - it2->getRideBackArrTime(this->timePerKm);
00211 
00212                 if (diff1 < 0 || diff2 < 0) {
00213                     if (diff2 < diff1) {
00214                         arrTime = it2->getArrTime(this->timePerKm);
00215                         it2->addLayOver(*it1);
00216                         it2->setDepTime(it2->estimateDepTime(arrTime, this->timePerKm));
00217                         tempAccTrip.erase(it1);
00218                     } else {
00219                         arrTime = it1->getArrTime(this->timePerKm);
00220                         it1->addLayOver(*it2);
00221                         it1->setDepTime(it1->estimateDepTime(arrTime, this->timePerKm));
00222                         tempAccTrip.erase(it2);
00223                     }
00224                     finish = false;
00225                     break;
00226                 }
00227             }
00228             if (!finish) {
00229                 break; // return to while
00230             }
00231         }
00232     }
00233     return finish;
00234 }
00235 
00236 bool
00237 AGWorkAndSchool::checkDriversScheduleMatching() {
00238     bool check = false;
00239     std::list<AGTrip>::iterator itAccT;
00240     std::list<AGTrip>::iterator itDriT;
00241     std::list<AGAdult>::iterator itA;
00242     for (itAccT = tempAccTrip.begin() ; itAccT != tempAccTrip.end() ; ++itAccT) {
00243         for (itDriT = tempTrip.begin() ; itDriT != tempTrip.end() ; ++itDriT) {
00244             if (itAccT->getArrTime(this->timePerKm) < itDriT->getArrTime(this->timePerKm)) {
00245                 check = true;
00246             }
00247         }
00248         for (itA = notNeedingDrivers.begin() ; itA != notNeedingDrivers.end() ; ++itA) {
00249             if (!itA->isWorking()) {
00250                 check = true;
00251             } else if (itAccT->getRideBackArrTime(this->timePerKm) < itA->getWorkPosition().getOpening()) {
00252                 check = true;
00253             }
00254         }
00255         if (!check) { //at least one trip is not performed by the existing drivers because it is to late for them
00256             return false;
00257         }
00258         check = false;
00259     }
00260     return true;
00261 }
00262 
00263 void
00264 AGWorkAndSchool::generateListTrips() {
00265     int arrTime;
00266     std::list<AGTrip>::iterator itAccT;
00267     std::list<AGTrip>::iterator itDriT;
00268     std::list<AGAdult>::iterator itA;
00269     bool alreadyDone;
00270 
00274     for (itAccT = tempAccTrip.begin() ; itAccT != tempAccTrip.end() ; ++itAccT) {
00275         alreadyDone = false;
00276         for (itDriT = tempTrip.begin() ; itDriT != tempTrip.end() ; ++itDriT) {
00277             if (!alreadyDone) {
00278                 if (itAccT->getArrTime(this->timePerKm) < itDriT->getArrTime(this->timePerKm) && !alreadyDone) {
00279                     //Add the accompaniment trip to the driver's trip OR new trip
00280                     if (itAccT->getRideBackArrTime(this->timePerKm) < itDriT->getTime()) {
00281                         //there is enough time to accompany people and go back home before going to work
00282                         itAccT->setVehicleName(itDriT->getVehicleName());
00283                         itAccT->addLayOver(itAccT->getArr());   //final destination is the last accompaniment stop: not the destination of the course
00284                         itAccT->setArr(hh->getPosition());      //final destination of the whole trip: home
00285                         partialActivityTrips.push_back(*itAccT);
00286                         alreadyDone = true;
00287                     } else {
00288                         //the driver drives people to their working place or school and goes directly to work after that
00289                         arrTime = itDriT->getArrTime(this->timePerKm);
00290                         itDriT->addLayOver(*itAccT);
00291                         itDriT->setDepTime(itDriT->estimateDepTime(arrTime, this->timePerKm));
00292                         //tempAccTrip.erase(itAccT);
00293                         //--itAccT; //because of erasure
00294                         alreadyDone = true;
00295                     }
00296                 }
00297             }
00298         }
00299 
00300         for (itA = notNeedingDrivers.begin() ; itA != notNeedingDrivers.end() ; ++itA) {
00301             if (!itA->isWorking() && !alreadyDone) {
00302                 std::string nameC = getUnusedCar();
00303                 if (nameC.size() != 0) {
00304                     itAccT->setVehicleName(getUnusedCar());
00305                     itAccT->addLayOver(itAccT->getArr());
00306                     itAccT->setArr(hh->getPosition());
00307                     partialActivityTrips.push_back(*itAccT);
00308                     alreadyDone = true;
00309                 }
00310             } else if (itAccT->getRideBackArrTime(this->timePerKm) < itA->getWorkPosition().getOpening() && !alreadyDone) {
00311                 std::string nameC = getUnusedCar();
00312                 if (nameC.size() != 0) {
00313                     itAccT->setVehicleName(getUnusedCar());
00314                     itAccT->addLayOver(itAccT->getArr());
00315                     itAccT->setArr(hh->getPosition());
00316                     partialActivityTrips.push_back(*itAccT);
00317                     alreadyDone = true;
00318                 }
00319             }
00320         }
00321     }
00322 
00326     for (itDriT = tempTrip.begin() ; itDriT != tempTrip.end() ; ++itDriT) {
00327         partialActivityTrips.push_back(*itDriT);
00328     }
00329 
00333     for (itA = personsDrivingCars.begin() ; itA != personsDrivingCars.end() ; ++itA) {
00334         for (itDriT = tempTrip.begin() ; itDriT != tempTrip.end() ; ++itDriT) {
00335             if (itA->getWorkPosition().getPosition() == itDriT->getArr()) {
00336                 AGTrip trip(itA->getWorkPosition().getPosition(), hh->getPosition(), itDriT->getVehicleName(), itA->getWorkPosition().getClosing());
00337                 partialActivityTrips.push_back(trip);
00338                 tempTrip.erase(itDriT);
00339                 break;
00340             }
00341         }
00342     }
00343 }
00344 
00345 std::string
00346 AGWorkAndSchool::getUnusedCar() {
00347     std::string nameCar = "";
00348     std::string nameCarUsed = "";
00349     //only two cars can be used in the household, so: the first one or the last one is not used.
00350     if (!tempTrip.empty()) {
00351         nameCarUsed = tempTrip.front().getVehicleName();
00352     } else if (!partialActivityTrips.empty()) {
00353         nameCarUsed = partialActivityTrips.front().getVehicleName();
00354     }
00355 
00356     if (nameCarUsed.size() != 0) {
00357         if (hh->cars.front().getName() == nameCarUsed) {
00358             nameCar = hh->cars.back().getName();
00359         } else {
00360             nameCar = hh->cars.front().getName();
00361         }
00362     }
00363     return nameCar;
00364 }
00365 
00366 void
00367 AGWorkAndSchool::makePossibleDriversDrive() {
00368     //give to a non working adult the ability to drive children or someone else.
00369     if (workingPeoplePossCar.size() + personsDrivingCars.size() + adultNeedingCarAccompaniment.size() != hh->getAdultNbr()) {
00370         std::list<AGAdult>::iterator itUA;
00371         for (itUA = hh->adults.begin() ; itUA != hh->adults.end() ; ++itUA) {
00372             if (! itUA->isWorking()) {
00373                 notNeedingDrivers.push_back(*itUA);
00374                 break;
00375             }
00376         }
00377     }
00378 }
00379 
00380 /****************************************************************************/
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines