SUMO - Simulation of Urban MObility
AGCity.cpp
Go to the documentation of this file.
1 /****************************************************************************/
11 // City class that contains all other objects of the city: in particular
12 // streets, households, bus lines, work positions and school
13 /****************************************************************************/
14 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
15 // Copyright (C) 2010-2017 DLR (http://www.dlr.de/) and contributors
16 // activitygen module
17 // Copyright 2010 TUM (Technische Universitaet Muenchen, http://www.tum.de/)
18 /****************************************************************************/
19 //
20 // This file is part of SUMO.
21 // SUMO is free software: you can redistribute it and/or modify
22 // it under the terms of the GNU General Public License as published by
23 // the Free Software Foundation, either version 3 of the License, or
24 // (at your option) any later version.
25 //
26 /****************************************************************************/
27 
28 
29 // ===========================================================================
30 // included modules
31 // ===========================================================================
32 #ifdef _MSC_VER
33 #include <windows_config.h>
34 #else
35 #include <config.h>
36 #endif
37 
38 #include <iostream>
39 #include <vector>
40 #include <string>
41 #include <map>
42 #include <iomanip>
45 #include <router/RONet.h>
46 #include <router/ROEdge.h>
47 #include "AGStreet.h"
48 #include "AGWorkPosition.h"
49 #include "AGCity.h"
50 //#define DRIVING_LICENSE_AGE 18
51 
52 
53 // ===========================================================================
54 // method definitions
55 // ===========================================================================
56 void
58  if (streetsCompleted) {
59  return;
60  } else {
61  streetsCompleted = true;
62  }
63 
64  double pop = 0, work = 0;
65  std::vector<AGStreet*>::iterator it;
66 
67  for (it = streets.begin(); it != streets.end(); ++it) {
68  pop += (*it)->getPopulation();
69  work += (*it)->getWorkplaceNumber();
70  }
72  //can be improved with other input data
73  double neededWorkPositionsInCity = (1.0 - statData.unemployement)
76  + (double)statData.incomingTraffic;
77  // we generate 5% more work positions that really needed: to avoid any expensive research of random work positions
78  neededWorkPositionsInCity *= double(1.05);
79  statData.workPositions = (int)neededWorkPositionsInCity;
80  statData.factorWorkPositions = neededWorkPositionsInCity / (double) work;
81 
82  for (it = streets.begin(); it != streets.end(); ++it) {
83  (*it)->setPopulation((*it)->getPopulation() * statData.factorInhabitants);
84  (*it)->setWorkplaceNumber((*it)->getWorkplaceNumber() * statData.factorWorkPositions);
85  //it->print();
86  }
87 
88  //completing streets from edges of the network not handled/present in STAT file (no population no work position)
89  std::map<std::string, ROEdge*>::const_iterator itE;
90  std::vector<AGStreet*>::iterator itS;
91 
92  for (itE = net->getEdgeMap().begin(); itE != net->getEdgeMap().end(); ++itE) {
93  for (itS = streets.begin(); itS != streets.end(); ++itS) {
94  if (*itS == itE->second) {
95  break;
96  }
97  }
98  //if this edge isn't represented by a street
99  if (itS == streets.end() && itE->second->getFunc() != ROEdge::ET_INTERNAL) {
100  streets.push_back(static_cast<AGStreet*>(itE->second));
101  }
102  }
103 }
104 
105 void
107  std::vector<AGStreet*>::iterator it;
108  int workPositionCounter = 0;
109 
110  try {
111  for (it = streets.begin(); it != streets.end(); ++it) {
112  //std::cout << "number of work positions in street: " << it->getWorkplaceNumber() << std::endl;
113  for (int i = 0; i < (*it)->getWorkplaceNumber(); ++i) {
114  workPositions.push_back(AGWorkPosition(&statData, **it));
115  ++workPositionCounter;
116  }
117  }
118  } catch (const std::bad_alloc& e) {
119  std::cout << "Number of work positions at bad_alloc exception: " << workPositionCounter << std::endl;
120  throw e;
121  }
122  //std::cout << "Inner work positions done. " << workPositionCounter << " generated." << std::endl;
123 
124  // Work positions outside the city
126  std::cout << "--> work position: " << std::endl;
127  std::cout << " |-> in city: " << workPositionCounter << std::endl;
128  std::cout << " |-> out city: " << statData.workPositions - workPositionCounter << std::endl;
129  std::cout << " |-> in+out city: " << statData.workPositions << std::endl;
130 }
131 
132 void
134  // work positions outside the city
136  if (nbrWorkers <= 0) {
137  return;
138  }
139  nbrWorkers *= (1.0 - statData.unemployement);
143  int nbrOutWorkPositions = static_cast<int>(workPositions.size() * (static_cast<double>(statData.outgoingTraffic)) / (nbrWorkers - static_cast<double>(statData.outgoingTraffic)));
144 
145  if (cityGates.empty()) {
146  return;
147  }
148 
149  for (int i = 0; i < nbrOutWorkPositions; ++i) {
151  workPositions.push_back(AGWorkPosition(&statData, cityGates[posi].getStreet(), cityGates[posi].getPosition()));
152  }
153  //cout << "outgoing traffic: " << statData.outgoingTraffic << std::endl;
154  //cout << "total number of workers in the city: " << nbrWorkers << std::endl;
155  //cout << "work positions out side the city: " << nbrOutWorkPositions << std::endl;
156  //cout << "work positions in and out of the city: " << workPositions.size() << std::endl;
157  statData.workPositions = static_cast<int>(workPositions.size());
158 }
159 
160 void
162  std::list<AGBusLine>::iterator it;
163  for (it = busLines.begin(); it != busLines.end(); ++it) {
164  //it->generateOpositDirection();
165  it->setBusNames();
166  }
167 }
168 
169 void
171  std::vector<AGStreet*>::iterator it;
172  double people = 0;
173  nbrCars = 0;
174  int idHouseholds = 0;
175  std::vector<int> numAdults(statData.households);
176  std::vector<int> numChilds(statData.households);
179  for (int i = 0; i < statData.households; i++) {
180  numAdults[i] = 1;
181  numChilds[i] = 0;
182  if (RandHelper::rand() < retiredProb) {
183  numAdults[i] = -numAdults[i];
184  } else if (totalChildrenLeft > 0) {
186  totalChildrenLeft -= numChilds[i];
187  }
188  }
189  //compensate with adults for too many / missing children
190  const int numSecondPers = statData.getPeopleOlderThan(statData.limitAgeChildren) - statData.households + totalChildrenLeft;
191  for (int i = 0; i < numSecondPers; i++) {
192  int index = i % numAdults.size();
193  if (numAdults[index] >= 0) {
194  numAdults[index] += 1;
195  } else {
196  numAdults[index] -= 1;
197  }
198  }
199  for (it = streets.begin(); it != streets.end(); ++it) {
200  people += (*it)->getPopulation();
201  while (people > 0 && idHouseholds < (int)numAdults.size()) {
202  int i = RandHelper::rand((int)numAdults.size() - idHouseholds);
203  ++idHouseholds;
204  households.push_back(AGHousehold(*it, this, idHouseholds));
205  households.back().generatePeople(abs(numAdults[i]), numChilds[i], numAdults[i] < 0); //&statData
206  //households.back().generateCars(statData.carRate);
207  people -= households.back().getPeopleNbr();
208  numAdults[i] = numAdults[numAdults.size() - idHouseholds];
209  numChilds[i] = numChilds[numAdults.size() - idHouseholds];
210  }
211  }
212 
213  //people from outside of the city generation:
215 
216  //TEST
217  int nbrSingle = 0;
218  int nbrCouple = 0;
219  int nbrChild = 0;
220  int nbrHH = 0;
221  int workingP = 0;
222  std::list<AGHousehold>::iterator itt;
223  for (itt = households.begin(); itt != households.end(); ++itt) {
224  if (itt->getAdultNbr() == 1) {
225  nbrSingle++;
226  if (itt->getAdults().front().isWorking()) {
227  workingP++;
228  }
229  }
230  if (itt->getAdultNbr() == 2) {
231  nbrCouple += 2;
232  if (itt->getAdults().front().isWorking()) {
233  workingP++;
234  }
235  if (itt->getAdults().back().isWorking()) {
236  workingP++;
237  }
238  }
239  nbrChild += itt->getPeopleNbr() - itt->getAdultNbr();
240  nbrHH++;
241  }
242  //cout << "number hh: " << nbrHH << std::endl;
243  //cout << "number single: " << nbrSingle << std::endl;
244  //cout << "number couple: " << nbrCouple << std::endl;
245  //cout << "number 3 or more: " << nbr3More << std::endl;
246  //cout << "number adults: " << nbrSingle + nbrCouple + nbr3More << std::endl;
247  //cout << "number children: " << nbrChild << std::endl;
248  //cout << "number people: " << nbrSingle + nbrCouple + nbr3More + nbrChild << std::endl;
249  //END TEST
250 
251  std::cout << "--> population: " << std::endl;
252  std::cout << " |-> city households: " << nbrHH << std::endl;
253  std::cout << " |-> city people: " << nbrSingle + nbrCouple + nbrChild << std::endl;
254  std::cout << " |-> city single: " << nbrSingle << " / (in) couple: " << nbrCouple << std::endl;
255  std::cout << " |-> city adults: " << nbrSingle + nbrCouple << std::endl;
256  std::cout << " |-> estimation: " << statData.getPeopleOlderThan(statData.limitAgeChildren) << std::endl;
257  std::cout << " |-> retired: " << statData.getPeopleOlderThan(statData.limitAgeRetirement) << std::endl;
258  std::cout << " |-> city children: " << nbrChild << std::endl;
259  std::cout << " |-> estimation: " << statData.getPeopleYoungerThan(statData.limitAgeChildren) << std::endl;
260 
261 }
262 
263 void
265  for (int i = 0; i < statData.incomingTraffic; ++i) {
267  peopleIncoming.push_back(ad);
268  }
269 }
270 
271 void
273  std::list<AGHousehold>::iterator it;
274  bool shortage;
275  for (it = households.begin(); it != households.end(); ++it) {
276  shortage = !it->allocateChildrenSchool();
277  if (shortage) {
278  /*ofstream fichier("test.txt", ios::app); // ouverture en écriture avec effacement du fichier ouvert
279  if(fichier)
280  {
281  fichier << "===> WARNING: Not enough school places in the city for all children..." << std::endl;
282  fichier.close();
283  }
284  else
285  cerr << "Impossible d'ouvrir le fichier !" << std::endl;*/
286 
287  //std::cout << "===> WARNING: Not enough school places in the city for all children..." << std::endl;
288  }
289  }
290 }
291 
292 void
294  const bool debug = OptionsCont::getOptions().getBool("debug");
295  statData.AdultNbr = 0;
296  //end tests
300  std::list<AGHousehold>::iterator it;
301  bool shortage;
302 
303  if (debug) {
304  std::cout << "\n";
305  }
306 
307  for (it = households.begin(); it != households.end(); ++it) {
308  if (it->retiredHouseholders()) {
309  continue;
310  }
311  shortage = !it->allocateAdultsWork();
312  if (shortage) {
313  std::cout << "===> ERROR: Not enough work positions in the city for all working people..." << std::endl;
314  }
315  statData.AdultNbr += it->getAdultNbr(); //TESTING
316  if (debug) {
317  std::cout << " processed " << statData.AdultNbr << " adults\r";
318  }
319  }
320 
324  std::list<AGAdult>::iterator itA;
325  for (itA = peopleIncoming.begin(); itA != peopleIncoming.end(); ++itA) {
326  if (statData.workPositions > 0) {
327  itA->tryToWork(1, &workPositions);
328  } else {
329  //shouldn't happen
330  std::cout << "not enough work for incoming people..." << std::endl;
331  }
332  }
333 
334  //BEGIN TESTS
335  int workingP = 0;
336  std::list<AGHousehold>::iterator itt;
337  for (itt = households.begin(); itt != households.end(); ++itt) {
338  if (itt->getAdultNbr() == 1) {
339  if (itt->getAdults().front().isWorking()) {
340  workingP++;
341  }
342  }
343  if (itt->getAdultNbr() == 2) {
344  if (itt->getAdults().front().isWorking()) {
345  workingP++;
346  }
347  if (itt->getAdults().back().isWorking()) {
348  workingP++;
349  }
350  }
351  }
352  std::cout << " |-> working people: " << peopleIncoming.size() + workingP << std::endl;
353  std::cout << " |-> working people in city: " << workingP << std::endl;
354  std::cout << " |-> working people from outside: " << peopleIncoming.size() << std::endl;
355  //END TESTS
356 }
357 
358 void
360  statData.hhFarFromPT = 0;
361  nbrCars = 0;
362  std::list<AGHousehold>::iterator it;
363  for (it = households.begin(); it != households.end(); ++it) {
364  if (!it->isCloseFromPubTransport(&(statData.busStations))) {
366  nbrCars++;
367  it->addACar();
368  }
370  }
371  // new rate: the rate on the people that have'nt any car yet:
372  // nR = (R * Drivers - AlreadyCars) / (Drivers - AlreadyCars)
375  newRate = 0.;
376  } else {
378  }
379  //std::cout << " - " << newRate << std::endl;
380  if (newRate < 0 || newRate >= 1) {
381  newRate = 0;
382  }
383 
384  nbrCars = 0;
385  int nbrAdults = 0;
386  for (it = households.begin(); it != households.end(); ++it) {
387  it->generateCars(newRate);
388  nbrCars += it->getCarNbr();
389  nbrAdults += it->getAdultNbr();
390  }
391  //TEST RESULTS
392  //std::cout << "number of cars: " << nbrCars << std::endl;
393  //std::cout << "number of adults: " << statData.getPeopleOlderThan(statData.limitAgeChildren) << std::endl;
394  //std::cout << "real number of adults: " << nbrAdults << std::endl;
395  //std::cout << "number of people far from public transport: " << statData.hhFarFromPT << std::endl;
396  //std::cout << "original rate: " << setprecision(4) << statData.carRate << std::endl;
397  //std::cout << "new rate: " << setprecision(4) << newRate << std::endl;
398  //std::cout << "real rate: " << setprecision(4) << (double)nbrCars / (double)statData.getPeopleOlderThan(statData.limitAgeChildren) << std::endl;
399  //END TEST RESULTS
400 }
401 
402 const AGStreet&
403 AGCity::getStreet(const std::string& edge) {
410  if (!streetsCompleted) {
412  completeStreets();
413  std::cout << "first completed in getStreet() of City: Consolidation of data not needed in ActivityGen any more" << std::endl;
414  }
415  //rest of the function
416  std::vector<AGStreet*>::iterator it = streets.begin();
417  while (it != streets.end()) {
418  if ((*it)->getID() == edge) {
419  return **it;
420  }
421  ++it;
422  }
423  std::cout << "===> ERROR: WRONG STREET EDGE (" << edge << ") given and not found in street set." << std::endl;
424  throw (std::runtime_error("Street not found with edge id " + edge));
425 }
426 
427 const AGStreet&
429  if (streets.empty()) {
430  throw (std::runtime_error("No street found in this city"));
431  }
433 }
434 
435 /****************************************************************************/
static const T & getRandomFrom(const std::vector< T > &v)
Returns a random element from the given vector.
Definition: RandHelper.h:114
void completeStreets()
Definition: AGCity.cpp:57
AGDataAndStatistics & statData
Definition: AGCity.h:88
A model of the street in the city.
Definition: AGStreet.h:60
An internal edge which models vehicles driving across a junction. This is currently not used for rout...
Definition: ROEdge.h:97
void generatePopulation()
Definition: AGCity.cpp:170
int getRandomPopDistributed(int n, int m)
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
#define abs(a)
Definition: polyfonts.c:67
void completeBusLines()
Definition: AGCity.cpp:161
const AGStreet & getStreet(const std::string &edge)
Definition: AGCity.cpp:403
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:65
std::list< AGBusLine > busLines
Definition: AGCity.h:92
An adult person who can have a job.
Definition: AGAdult.h:58
const AGStreet & getRandomStreet()
Definition: AGCity.cpp:428
void generateOutgoingWP()
Definition: AGCity.cpp:133
void schoolAllocation()
Definition: AGCity.cpp:272
void generateWorkPositions()
Definition: AGCity.cpp:106
std::list< AGHousehold > households
Definition: AGCity.h:93
static double rand()
Returns a random real number in [0, 1)
Definition: RandHelper.h:62
void workAllocation()
Definition: AGCity.cpp:293
std::vector< AGStreet * > streets
Definition: AGCity.h:89
std::list< AGAdult > peopleIncoming
Definition: AGCity.h:95
int getPoissonsNumberOfChildren(double mean)
bool streetsCompleted
Definition: AGCity.h:114
void carAllocation()
Definition: AGCity.cpp:359
int nbrCars
Definition: AGCity.h:116
const std::map< std::string, ROEdge * > & getEdgeMap() const
Definition: RONet.cpp:659
RONet * net
Definition: AGCity.h:109
void generateIncomingPopulation()
Definition: AGCity.cpp:264
std::vector< AGPosition > cityGates
Definition: AGCity.h:94
std::map< int, AGPosition > busStations
std::vector< AGWorkPosition > workPositions
Definition: AGCity.h:90