SUMO - Simulation of Urban MObility

AGCity.cpp

Go to the documentation of this file.
00001 /****************************************************************************/
00007 // City class that contains all other objects of the city: in particular
00008 // streets, households, bus lines, work positions and school
00009 /****************************************************************************/
00010 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
00011 // Copyright (C) 2001-2011 DLR (http://www.dlr.de/) and contributors
00012 // activitygen module
00013 // Copyright 2010 TUM (Technische Universitaet Muenchen, http://www.tum.de/)
00014 /****************************************************************************/
00015 //
00016 //   This program is free software; you can redistribute it and/or modify
00017 //   it under the terms of the GNU General Public License as published by
00018 //   the Free Software Foundation; either version 2 of the License, or
00019 //   (at your option) any later version.
00020 //
00021 /****************************************************************************/
00022 
00023 
00024 // ===========================================================================
00025 // included modules
00026 // ===========================================================================
00027 #ifdef _MSC_VER
00028 #include <windows_config.h>
00029 #else
00030 #include <config.h>
00031 #endif
00032 
00033 #include <iostream>
00034 #include <vector>
00035 #include <string>
00036 #include <map>
00037 #include <iomanip>
00038 #include <utils/common/RandHelper.h>
00039 #include <router/RONet.h>
00040 #include <router/ROEdge.h>
00041 #include "AGStreet.h"
00042 #include "AGWorkPosition.h"
00043 #include "AGCity.h"
00044 //#define DRIVING_LICENSE_AGE 18
00045 
00046 
00047 // ===========================================================================
00048 // method definitions
00049 // ===========================================================================
00050 void
00051 AGCity::completeStreets() {
00052     if (streetsCompleted) {
00053         return;
00054     } else {
00055         streetsCompleted = true;
00056     }
00057 
00058     NrStreets = 0;
00059     int pop=0, work=0;
00060     std::vector<AGStreet>::iterator it;
00061 
00062     for (it = streets.begin() ; it!=streets.end() ; ++it) {
00063         pop += (int)(it->getPopulation());
00064         work += (int)(it->getWorkplaceNumber());
00065         ++NrStreets;
00066     }
00067     statData.factorInhabitants = (float)statData.inhabitants / (float)pop;
00068     //can be improved with other input data
00069     SUMOReal neededWorkPositionsInCity = (1.0 - statData.unemployement)
00070                                          * ((float)statData.getPeopleYoungerThan(statData.limitAgeRetirement)
00071                                             - (float)statData.getPeopleYoungerThan(statData.limitAgeChildren))
00072                                          + (float)statData.incomingTraffic;
00073     // we generate 5% more work positions that really needed: to avoid any expensive research of random work positions
00074     neededWorkPositionsInCity *= 1.05f;
00075     statData.workPositions = (int)neededWorkPositionsInCity;
00076     statData.factorWorkPositions = neededWorkPositionsInCity / (float) work;
00077 
00078     for (it = streets.begin() ; it!=streets.end() ; ++it) {
00079         it->setPopulation((int)(it->getPopulation() * statData.factorInhabitants));
00080         it->setWorkplaceNumber((int)(it->getWorkplaceNumber() * statData.factorWorkPositions));
00081         //it->print();
00082     }
00083 
00084     //completing streets from edges of the network not handled/present in STAT file (no population no work position)
00085     std::map<std::string, ROEdge*>::const_iterator itE;
00086     std::vector<AGStreet>::iterator itS;
00087 
00088     for (itE = net->getEdgeMap().begin() ; itE != net->getEdgeMap().end() ; ++itE) {
00089         for (itS = streets.begin() ; itS != streets.end() ; ++itS) {
00090             if (itS->getName() == itE->second->getID()) {
00091                 break;
00092             }
00093         }
00094         //if this edge isn't represented by a street
00095         if (itS == streets.end()) {
00096             streets.push_back(AGStreet(itE->second));
00097         }
00098     }
00099 }
00100 
00101 void
00102 AGCity::generateWorkPositions() {
00103     std::vector<AGStreet>::iterator it;
00104     int workPositionCounter = 0;
00105 
00106     try {
00107         for (it = streets.begin() ; it != streets.end() ; ++it) {
00108             //std::cout << "number of work positions in street: " << it->getWorkplaceNumber() << std::endl;
00109             for (int i=0 ; i<it->getWorkplaceNumber() ; ++i) {
00110                 workPositions.push_back(AGWorkPosition(*it, &statData));
00111                 ++workPositionCounter;
00112             }
00113         }
00114     } catch (const std::bad_alloc& e) {
00115         std::cout << "Number of work positions at bad_alloc exception: " << workPositionCounter << std::endl;
00116         throw(e);
00117     }
00118     //std::cout << "Inner work positions done. " << workPositionCounter << " generated." << std::endl;
00119 
00120     // Work positions outside the city
00121     generateOutgoingWP();
00122     std::cout << "--> work position: " << std::endl;
00123     std::cout << "  |-> in city: " << workPositionCounter << std::endl;
00124     std::cout << "  |-> out city: " << statData.workPositions - workPositionCounter << std::endl;
00125     std::cout << "  |-> in+out city: " << statData.workPositions << std::endl;
00126 }
00127 
00128 void
00129 AGCity::generateOutgoingWP() {
00130     // work positions outside the city
00131     SUMOReal nbrWorkers = static_cast<SUMOReal>(statData.getPeopleYoungerThan(statData.limitAgeRetirement) - statData.getPeopleYoungerThan(statData.limitAgeChildren));
00132     if (nbrWorkers <= 0) {
00133         return;
00134     }
00135     nbrWorkers *= (1.0 - statData.unemployement);
00139     int nbrOutWorkPositions = static_cast<int>(workPositions.size() * (static_cast<float>(statData.outgoingTraffic))/(nbrWorkers - static_cast<float>(statData.outgoingTraffic)));
00140 
00141     if (cityGates.empty()) {
00142         return;
00143     }
00144 
00145     for (int i=0 ; i<nbrOutWorkPositions ; ++i) {
00146         int posi = statData.getRandomCityGateByOutgoing();
00147         workPositions.push_back(AGWorkPosition(cityGates[posi].getStreet(), cityGates[posi].getPosition(), &statData));
00148     }
00149     //cout << "outgoing traffic: " << statData.outgoingTraffic << std::endl;
00150     //cout << "total number of workers in the city: " << nbrWorkers << std::endl;
00151     //cout << "work positions out side the city: " << nbrOutWorkPositions << std::endl;
00152     //cout << "work positions in and out of the city: " << workPositions.size() << std::endl;
00153     statData.workPositions = static_cast<int>(workPositions.size());
00154 }
00155 
00156 void
00157 AGCity::completeBusLines() {
00158     std::list<AGBusLine>::iterator it;
00159     for (it=busLines.begin() ; it!=busLines.end() ; ++it) {
00160         //it->generateOpositDirection();
00161         it->setBusNames();
00162     }
00163 }
00164 
00165 void
00166 AGCity::generatePopulation() {
00167     std::vector<AGStreet>::iterator it;
00168     int people;
00169     nbrCars = 0;
00170     int idHouseholds = 0;
00171 
00172     for (it=streets.begin() ; it!=streets.end() ; ++it) {
00173         people = it->getPopulation();
00174         while (people > 0) {
00175             ++idHouseholds;
00176             households.push_back(AGHousehold(&*it, this, idHouseholds));
00177             households.back().generatePeople(); //&statData
00178             //households.back().generateCars(statData.carRate);
00179             people -= households.back().getPeopleNbr();
00180         }
00181     }
00182 
00183     //people from outside of the city generation:
00184     generateIncomingPopulation();
00185 
00186     //TEST
00187     int nbrSingle = 0;
00188     int nbrCouple = 0;
00189     int nbrChild = 0;
00190     int nbrHH = 0;
00191     int workingP = 0;
00192     std::list<AGHousehold>::iterator itt;
00193     for (itt=households.begin() ; itt != households.end() ; ++itt) {
00194         if (itt->getAdultNbr() == 1) {
00195             nbrSingle++;
00196             if (itt->adults.front().isWorking()) {
00197                 workingP++;
00198             }
00199         }
00200         if (itt->getAdultNbr() == 2) {
00201             nbrCouple += 2;
00202             if (itt->adults.front().isWorking()) {
00203                 workingP++;
00204             }
00205             if (itt->adults.back().isWorking()) {
00206                 workingP++;
00207             }
00208         }
00209         nbrChild += itt->getPeopleNbr() - itt->getAdultNbr();
00210         nbrHH++;
00211     }
00212     //cout << "number hh: " << nbrHH << std::endl;
00213     //cout << "number single: " << nbrSingle << std::endl;
00214     //cout << "number couple: " << nbrCouple << std::endl;
00215     //cout << "number 3 or more: " << nbr3More << std::endl;
00216     //cout << "number adults: " << nbrSingle + nbrCouple + nbr3More << std::endl;
00217     //cout << "number children: " << nbrChild << std::endl;
00218     //cout << "number people: " << nbrSingle + nbrCouple + nbr3More + nbrChild << std::endl;
00219     //END TEST
00220 
00221     std::cout << "--> population: " << std::endl;
00222     std::cout << "  |-> city households: " << nbrHH << std::endl;
00223     std::cout << "  |-> city people: " << nbrSingle + nbrCouple + nbrChild << std::endl;
00224     std::cout << "    |-> city single: " << nbrSingle << " / (in) couple: " << nbrCouple << std::endl;
00225     std::cout << "    |-> city adults: " << nbrSingle + nbrCouple << std::endl;
00226     std::cout << "      |-> estimation: " << statData.getPeopleOlderThan(statData.limitAgeChildren) << std::endl;
00227     std::cout << "      |-> retired: " << statData.getPeopleOlderThan(statData.limitAgeRetirement) << std::endl;
00228     std::cout << "    |-> city children: " << nbrChild << std::endl;
00229     std::cout << "      |-> estimation: " << statData.getPeopleYoungerThan(statData.limitAgeChildren) << std::endl;
00230 
00231 }
00232 
00233 void
00234 AGCity::generateIncomingPopulation() {
00235     for (int i=0 ; i<statData.incomingTraffic ; ++i) {
00236         AGAdult ad(statData.getRandomPopDistributed(statData.limitAgeChildren, statData.limitAgeRetirement));
00237         peopleIncoming.push_back(ad);
00238     }
00239 }
00240 
00241 void
00242 AGCity::schoolAllocation() {
00243     std::list<AGHousehold>::iterator it;
00244     bool shortage;
00245     for (it = households.begin() ; it != households.end() ; ++it) {
00246         shortage = !it->allocateChildrenSchool();
00247         if (shortage) {
00248             /*ofstream fichier("test.txt", ios::app);  // ouverture en écriture avec effacement du fichier ouvert
00249             if(fichier)
00250             {
00251                 fichier << "===> WARNING: Not enough school places in the city for all children..." << std::endl;
00252                 fichier.close();
00253             }
00254             else
00255                 cerr << "Impossible d'ouvrir le fichier !" << std::endl;*/
00256 
00257             //std::cout << "===> WARNING: Not enough school places in the city for all children..." << std::endl;
00258         }
00259     }
00260 }
00261 
00262 void
00263 AGCity::workAllocation() {
00264     statData.AdultNbr = 0;
00265     //end tests
00269     std::list<AGHousehold>::iterator it;
00270     bool shortage;
00271 
00272     for (it = households.begin() ; it != households.end() ; ++it) {
00273         if (it->retiredHouseholders()) {
00274             continue;
00275         }
00276         shortage = !it->allocateAdultsWork();
00277         if (shortage) {
00278             std::cout << "===> ERROR: Not enough work positions in the city for all working people..." << std::endl;
00279         }
00280         statData.AdultNbr += it->getAdultNbr(); //TESTING
00281     }
00282 
00286     std::list<AGAdult>::iterator itA;
00287     for (itA=peopleIncoming.begin() ; itA!=peopleIncoming.end() ; ++itA) {
00288         if (statData.workPositions > 0) {
00289             itA->tryToWork(1, &workPositions);
00290         } else {
00291             //shouldn't happen
00292             std::cout << "not enough work for incoming people..." << std::endl;
00293         }
00294     }
00295 
00296     //BEGIN TESTS
00297     int workingP = 0;
00298     std::list<AGHousehold>::iterator itt;
00299     for (itt=households.begin() ; itt != households.end() ; ++itt) {
00300         if (itt->getAdultNbr() == 1) {
00301             if (itt->adults.front().isWorking()) {
00302                 workingP++;
00303             }
00304         }
00305         if (itt->getAdultNbr() == 2) {
00306             if (itt->adults.front().isWorking()) {
00307                 workingP++;
00308             }
00309             if (itt->adults.back().isWorking()) {
00310                 workingP++;
00311             }
00312         }
00313     }
00314     std::cout << "  |-> working people: " << peopleIncoming.size() + workingP << std::endl;
00315     std::cout << "    |-> working people in city: " << workingP << std::endl;
00316     std::cout << "    |-> working people from outside: " << peopleIncoming.size() << std::endl;
00317     //END TESTS
00318 }
00319 
00320 void
00321 AGCity::carAllocation() {
00322     statData.hhFarFromPT = 0;
00323     nbrCars = 0;
00324     std::list<AGHousehold>::iterator it;
00325     for (it=households.begin() ; it!=households.end() ; ++it) {
00326         if (!it->isCloseFromPubTransport(&(statData.busStations))) {
00327             statData.hhFarFromPT++;
00328             nbrCars++;
00329             it->addACar();
00330         }
00331         statData.householdsNbr++;
00332     }
00333     // new rate: the rate on the people that have'nt any car yet:
00334     // nR = (R * Drivers - AlreadyCars) / (Drivers - AlreadyCars)
00335     SUMOReal newRate = (statData.carRate * statData.getPeopleOlderThan(statData.limitAgeChildren) - statData.hhFarFromPT) / (statData.getPeopleOlderThan(statData.limitAgeChildren) - statData.hhFarFromPT);
00336     //std::cout << " - " << newRate << std::endl;
00337     if (newRate < 0 || newRate >= 1) {
00338         newRate = 0;
00339     }
00340 
00341     nbrCars = 0;
00342     int nbrAdults = 0;
00343     for (it=households.begin() ; it!=households.end() ; ++it) {
00344         it->generateCars(newRate);
00345         nbrCars += it->getCarNbr();
00346         nbrAdults += it->getAdultNbr();
00347     }
00348     //TEST RESULTS
00349     //std::cout << "number of cars: " << nbrCars << std::endl;
00350     //std::cout << "number of adults: " << statData.getPeopleOlderThan(statData.limitAgeChildren) << std::endl;
00351     //std::cout << "real number of adults: " << nbrAdults << std::endl;
00352     //std::cout << "number of people far from public transport: " << statData.hhFarFromPT << std::endl;
00353     //std::cout << "original rate: " << setprecision(4) << statData.carRate << std::endl;
00354     //std::cout << "new rate: " << setprecision(4) << newRate << std::endl;
00355     //std::cout << "real rate: " << setprecision(4) << (float)nbrCars / (float)statData.getPeopleOlderThan(statData.limitAgeChildren) << std::endl;
00356     //END TEST RESULTS
00357 }
00358 
00359 const AGStreet&
00360 AGCity::getStreet(const std::string& edge) {
00367     if (!streetsCompleted) {
00368         statData.consolidateStat();
00369         completeStreets();
00370         std::cout << "first completed in getStreet() of City: Consolidation of data not needed in ActivityGen any more" << std::endl;
00371     }
00372     //rest of the function
00373     std::vector<AGStreet>::iterator it = streets.begin();
00374     while (it != streets.end()) {
00375         if (it->getName() == edge) {
00376             return *it;
00377         }
00378         ++it;
00379     }
00380     std::cout << "===> ERROR: WRONG STREET EDGE (" << edge << ") given and not found in street set." << std::endl;
00381     throw(std::runtime_error("Street not found with edge id " + edge));
00382 }
00383 
00384 const AGStreet&
00385 AGCity::getRandomStreet() {
00386     if (streets.empty()) {
00387         throw(std::runtime_error("No street found in this city"));
00388     }
00389     return streets[RandHelper::rand(streets.size())];
00390 }
00391 
00392 /****************************************************************************/
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines