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-sim.org/
15 // Copyright (C) 2010-2014 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>
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  SUMOReal 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  SUMOReal neededWorkPositionsInCity = (1.0 - statData.unemployement)
76  // we generate 5% more work positions that really needed: to avoid any expensive research of random work positions
77  neededWorkPositionsInCity *= SUMOReal(1.05);
78  statData.workPositions = (int)neededWorkPositionsInCity;
79  statData.factorWorkPositions = neededWorkPositionsInCity / (SUMOReal) 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  std::map<std::string, ROEdge*>::const_iterator itE;
89  std::vector<AGStreet>::iterator itS;
90 
91  for (itE = net->getEdgeMap().begin(); itE != net->getEdgeMap().end(); ++itE) {
92  for (itS = streets.begin(); itS != streets.end(); ++itS) {
93  if (itS->getName() == itE->second->getID()) {
94  break;
95  }
96  }
97  //if this edge isn't represented by a street
98  if (itS == streets.end() && itE->second->getType() != ROEdge::ET_INTERNAL) {
99  streets.push_back(AGStreet(itE->second));
100  }
101  }
102 }
103 
104 void
106  std::vector<AGStreet>::iterator it;
107  int workPositionCounter = 0;
108 
109  try {
110  for (it = streets.begin(); it != streets.end(); ++it) {
111  //std::cout << "number of work positions in street: " << it->getWorkplaceNumber() << std::endl;
112  for (int i = 0; i < it->getWorkplaceNumber(); ++i) {
113  workPositions.push_back(AGWorkPosition(&statData, *it));
114  ++workPositionCounter;
115  }
116  }
117  } catch (const std::bad_alloc& e) {
118  std::cout << "Number of work positions at bad_alloc exception: " << workPositionCounter << std::endl;
119  throw e;
120  }
121  //std::cout << "Inner work positions done. " << workPositionCounter << " generated." << std::endl;
122 
123  // Work positions outside the city
125  std::cout << "--> work position: " << std::endl;
126  std::cout << " |-> in city: " << workPositionCounter << std::endl;
127  std::cout << " |-> out city: " << statData.workPositions - workPositionCounter << std::endl;
128  std::cout << " |-> in+out city: " << statData.workPositions << std::endl;
129 }
130 
131 void
133  // work positions outside the city
135  if (nbrWorkers <= 0) {
136  return;
137  }
138  nbrWorkers *= (1.0 - statData.unemployement);
142  int nbrOutWorkPositions = static_cast<int>(workPositions.size() * (static_cast<SUMOReal>(statData.outgoingTraffic)) / (nbrWorkers - static_cast<SUMOReal>(statData.outgoingTraffic)));
143 
144  if (cityGates.empty()) {
145  return;
146  }
147 
148  for (int i = 0; i < nbrOutWorkPositions; ++i) {
150  workPositions.push_back(AGWorkPosition(&statData, cityGates[posi].getStreet(), cityGates[posi].getPosition()));
151  }
152  //cout << "outgoing traffic: " << statData.outgoingTraffic << std::endl;
153  //cout << "total number of workers in the city: " << nbrWorkers << std::endl;
154  //cout << "work positions out side the city: " << nbrOutWorkPositions << std::endl;
155  //cout << "work positions in and out of the city: " << workPositions.size() << std::endl;
156  statData.workPositions = static_cast<int>(workPositions.size());
157 }
158 
159 void
161  std::list<AGBusLine>::iterator it;
162  for (it = busLines.begin(); it != busLines.end(); ++it) {
163  //it->generateOpositDirection();
164  it->setBusNames();
165  }
166 }
167 
168 void
170  std::vector<AGStreet>::iterator it;
171  SUMOReal people = 0;
172  nbrCars = 0;
173  unsigned int idHouseholds = 0;
174  std::vector<int> numAdults(statData.households);
175  std::vector<int> numChilds(statData.households);
178  for (int i = 0; i < statData.households; i++) {
179  numAdults[i] = 1;
180  numChilds[i] = 0;
181  if (RandHelper::rand() < retiredProb) {
182  numAdults[i] = -numAdults[i];
183  } else if (totalChildrenLeft > 0) {
185  totalChildrenLeft -= numChilds[i];
186  }
187  }
188  //compensate with adults for too many / missing children
189  const int numSecondPers = statData.getPeopleOlderThan(statData.limitAgeChildren) - statData.households + totalChildrenLeft;
190  for (int i = 0; i < numSecondPers; i++) {
191  unsigned int index = i % numAdults.size();
192  if (numAdults[index] >= 0) {
193  numAdults[index] += 1;
194  } else {
195  numAdults[index] -= 1;
196  }
197  }
198  for (it = streets.begin(); it != streets.end(); ++it) {
199  people += it->getPopulation();
200  while (people > 0 && idHouseholds < (unsigned int)numAdults.size()) {
201  size_t i = RandHelper::rand(numAdults.size() - idHouseholds);
202  ++idHouseholds;
203  households.push_back(AGHousehold(&*it, this, idHouseholds));
204  households.back().generatePeople(abs(numAdults[i]), numChilds[i], numAdults[i] < 0); //&statData
205  //households.back().generateCars(statData.carRate);
206  people -= households.back().getPeopleNbr();
207  numAdults[i] = numAdults[numAdults.size() - idHouseholds];
208  numChilds[i] = numChilds[numAdults.size() - idHouseholds];
209  }
210  }
211 
212  //people from outside of the city generation:
214 
215  //TEST
216  int nbrSingle = 0;
217  int nbrCouple = 0;
218  int nbrChild = 0;
219  int nbrHH = 0;
220  int workingP = 0;
221  std::list<AGHousehold>::iterator itt;
222  for (itt = households.begin(); itt != households.end(); ++itt) {
223  if (itt->getAdultNbr() == 1) {
224  nbrSingle++;
225  if (itt->getAdults().front().isWorking()) {
226  workingP++;
227  }
228  }
229  if (itt->getAdultNbr() == 2) {
230  nbrCouple += 2;
231  if (itt->getAdults().front().isWorking()) {
232  workingP++;
233  }
234  if (itt->getAdults().back().isWorking()) {
235  workingP++;
236  }
237  }
238  nbrChild += itt->getPeopleNbr() - itt->getAdultNbr();
239  nbrHH++;
240  }
241  //cout << "number hh: " << nbrHH << std::endl;
242  //cout << "number single: " << nbrSingle << std::endl;
243  //cout << "number couple: " << nbrCouple << std::endl;
244  //cout << "number 3 or more: " << nbr3More << std::endl;
245  //cout << "number adults: " << nbrSingle + nbrCouple + nbr3More << std::endl;
246  //cout << "number children: " << nbrChild << std::endl;
247  //cout << "number people: " << nbrSingle + nbrCouple + nbr3More + nbrChild << std::endl;
248  //END TEST
249 
250  std::cout << "--> population: " << std::endl;
251  std::cout << " |-> city households: " << nbrHH << std::endl;
252  std::cout << " |-> city people: " << nbrSingle + nbrCouple + nbrChild << std::endl;
253  std::cout << " |-> city single: " << nbrSingle << " / (in) couple: " << nbrCouple << std::endl;
254  std::cout << " |-> city adults: " << nbrSingle + nbrCouple << std::endl;
255  std::cout << " |-> estimation: " << statData.getPeopleOlderThan(statData.limitAgeChildren) << std::endl;
256  std::cout << " |-> retired: " << statData.getPeopleOlderThan(statData.limitAgeRetirement) << std::endl;
257  std::cout << " |-> city children: " << nbrChild << std::endl;
258  std::cout << " |-> estimation: " << statData.getPeopleYoungerThan(statData.limitAgeChildren) << std::endl;
259 
260 }
261 
262 void
264  for (int i = 0; i < statData.incomingTraffic; ++i) {
266  peopleIncoming.push_back(ad);
267  }
268 }
269 
270 void
272  std::list<AGHousehold>::iterator it;
273  bool shortage;
274  for (it = households.begin(); it != households.end(); ++it) {
275  shortage = !it->allocateChildrenSchool();
276  if (shortage) {
277  /*ofstream fichier("test.txt", ios::app); // ouverture en écriture avec effacement du fichier ouvert
278  if(fichier)
279  {
280  fichier << "===> WARNING: Not enough school places in the city for all children..." << std::endl;
281  fichier.close();
282  }
283  else
284  cerr << "Impossible d'ouvrir le fichier !" << std::endl;*/
285 
286  //std::cout << "===> WARNING: Not enough school places in the city for all children..." << std::endl;
287  }
288  }
289 }
290 
291 void
293  statData.AdultNbr = 0;
294  //end tests
298  std::list<AGHousehold>::iterator it;
299  bool shortage;
300 
301  for (it = households.begin(); it != households.end(); ++it) {
302  if (it->retiredHouseholders()) {
303  continue;
304  }
305  shortage = !it->allocateAdultsWork();
306  if (shortage) {
307  std::cout << "===> ERROR: Not enough work positions in the city for all working people..." << std::endl;
308  }
309  statData.AdultNbr += it->getAdultNbr(); //TESTING
310  }
311 
315  std::list<AGAdult>::iterator itA;
316  for (itA = peopleIncoming.begin(); itA != peopleIncoming.end(); ++itA) {
317  if (statData.workPositions > 0) {
318  itA->tryToWork(1, &workPositions);
319  } else {
320  //shouldn't happen
321  std::cout << "not enough work for incoming people..." << std::endl;
322  }
323  }
324 
325  //BEGIN TESTS
326  int workingP = 0;
327  std::list<AGHousehold>::iterator itt;
328  for (itt = households.begin(); itt != households.end(); ++itt) {
329  if (itt->getAdultNbr() == 1) {
330  if (itt->getAdults().front().isWorking()) {
331  workingP++;
332  }
333  }
334  if (itt->getAdultNbr() == 2) {
335  if (itt->getAdults().front().isWorking()) {
336  workingP++;
337  }
338  if (itt->getAdults().back().isWorking()) {
339  workingP++;
340  }
341  }
342  }
343  std::cout << " |-> working people: " << peopleIncoming.size() + workingP << std::endl;
344  std::cout << " |-> working people in city: " << workingP << std::endl;
345  std::cout << " |-> working people from outside: " << peopleIncoming.size() << std::endl;
346  //END TESTS
347 }
348 
349 void
351  statData.hhFarFromPT = 0;
352  nbrCars = 0;
353  std::list<AGHousehold>::iterator it;
354  for (it = households.begin(); it != households.end(); ++it) {
355  if (!it->isCloseFromPubTransport(&(statData.busStations))) {
357  nbrCars++;
358  it->addACar();
359  }
361  }
362  // new rate: the rate on the people that have'nt any car yet:
363  // nR = (R * Drivers - AlreadyCars) / (Drivers - AlreadyCars)
366  newRate = 0.;
367  } else {
369  }
370  //std::cout << " - " << newRate << std::endl;
371  if (newRate < 0 || newRate >= 1) {
372  newRate = 0;
373  }
374 
375  nbrCars = 0;
376  int nbrAdults = 0;
377  for (it = households.begin(); it != households.end(); ++it) {
378  it->generateCars(newRate);
379  nbrCars += it->getCarNbr();
380  nbrAdults += it->getAdultNbr();
381  }
382  //TEST RESULTS
383  //std::cout << "number of cars: " << nbrCars << std::endl;
384  //std::cout << "number of adults: " << statData.getPeopleOlderThan(statData.limitAgeChildren) << std::endl;
385  //std::cout << "real number of adults: " << nbrAdults << std::endl;
386  //std::cout << "number of people far from public transport: " << statData.hhFarFromPT << std::endl;
387  //std::cout << "original rate: " << setprecision(4) << statData.carRate << std::endl;
388  //std::cout << "new rate: " << setprecision(4) << newRate << std::endl;
389  //std::cout << "real rate: " << setprecision(4) << (SUMOReal)nbrCars / (SUMOReal)statData.getPeopleOlderThan(statData.limitAgeChildren) << std::endl;
390  //END TEST RESULTS
391 }
392 
393 const AGStreet&
394 AGCity::getStreet(const std::string& edge) {
401  if (!streetsCompleted) {
403  completeStreets();
404  std::cout << "first completed in getStreet() of City: Consolidation of data not needed in ActivityGen any more" << std::endl;
405  }
406  //rest of the function
407  std::vector<AGStreet>::iterator it = streets.begin();
408  while (it != streets.end()) {
409  if (it->getName() == edge) {
410  return *it;
411  }
412  ++it;
413  }
414  std::cout << "===> ERROR: WRONG STREET EDGE (" << edge << ") given and not found in street set." << std::endl;
415  throw(std::runtime_error("Street not found with edge id " + edge));
416 }
417 
418 const AGStreet&
420  if (streets.empty()) {
421  throw(std::runtime_error("No street found in this city"));
422  }
423  return streets[RandHelper::rand(streets.size())];
424 }
425 
426 /****************************************************************************/
void completeStreets()
Definition: AGCity.cpp:56
static SUMOReal rand()
Returns a random real number in [0, 1)
Definition: RandHelper.h:62
AGDataAndStatistics & statData
Definition: AGCity.h:88
A model of the street in the city.
Definition: AGStreet.h:58
An internal edge which models vehicles driving across a junction. This is currently not used for rout...
Definition: ROEdge.h:89
void generatePopulation()
Definition: AGCity.cpp:169
int getRandomPopDistributed(int n, int m)
std::vector< AGStreet > streets
Definition: AGCity.h:89
#define abs(a)
Definition: polyfonts.c:67
void completeBusLines()
Definition: AGCity.cpp:160
const AGStreet & getStreet(const std::string &edge)
Definition: AGCity.cpp:394
const std::map< std::string, ROEdge * > & getEdgeMap() const
Definition: RONet.cpp:407
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:419
void generateOutgoingWP()
Definition: AGCity.cpp:132
void schoolAllocation()
Definition: AGCity.cpp:271
void generateWorkPositions()
Definition: AGCity.cpp:105
std::list< AGHousehold > households
Definition: AGCity.h:93
void workAllocation()
Definition: AGCity.cpp:292
std::list< AGAdult > peopleIncoming
Definition: AGCity.h:95
bool streetsCompleted
Definition: AGCity.h:114
void carAllocation()
Definition: AGCity.cpp:350
int nbrCars
Definition: AGCity.h:116
int getPoissonsNumberOfChildren(SUMOReal mean)
RONet * net
Definition: AGCity.h:109
#define SUMOReal
Definition: config.h:215
void generateIncomingPopulation()
Definition: AGCity.cpp:263
std::vector< AGPosition > cityGates
Definition: AGCity.h:94
std::map< int, AGPosition > busStations
std::vector< AGWorkPosition > workPositions
Definition: AGCity.h:90