|
SUMO - Simulation of Urban MObility
|
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 /****************************************************************************/