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