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