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