SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
AGCity.cpp
Go to the documentation of this file.
1 /****************************************************************************/
10 // City class that contains all other objects of the city: in particular
11 // streets, households, bus lines, work positions and school
12 /****************************************************************************/
13 // SUMO, Simulation of Urban MObility; see http://sumo-sim.org/
14 // Copyright (C) 2001-2013 DLR (http://www.dlr.de/) and contributors
15 // activitygen module
16 // Copyright 2010 TUM (Technische Universitaet Muenchen, http://www.tum.de/)
17 /****************************************************************************/
18 //
19 // This file is part of SUMO.
20 // SUMO is free software: you can redistribute it and/or modify
21 // it under the terms of the GNU General Public License as published by
22 // the Free Software Foundation, either version 3 of the License, or
23 // (at your option) any later version.
24 //
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>
43 #include <router/RONet.h>
44 #include <router/ROEdge.h>
45 #include "AGStreet.h"
46 #include "AGWorkPosition.h"
47 #include "AGCity.h"
48 //#define DRIVING_LICENSE_AGE 18
49 
50 
51 // ===========================================================================
52 // method definitions
53 // ===========================================================================
54 void
56  if (streetsCompleted) {
57  return;
58  } else {
59  streetsCompleted = true;
60  }
61 
62  SUMOReal pop = 0, work = 0;
63  std::vector<AGStreet>::iterator it;
64 
65  for (it = streets.begin(); it != streets.end(); ++it) {
66  pop += it->getPopulation();
67  work += it->getWorkplaceNumber();
68  }
70  //can be improved with other input data
71  SUMOReal neededWorkPositionsInCity = (1.0 - statData.unemployement)
75  // we generate 5% more work positions that really needed: to avoid any expensive research of random work positions
76  neededWorkPositionsInCity *= SUMOReal(1.05);
77  statData.workPositions = (int)neededWorkPositionsInCity;
78  statData.factorWorkPositions = neededWorkPositionsInCity / (SUMOReal) work;
79 
80  for (it = streets.begin(); it != streets.end(); ++it) {
81  it->setPopulation(it->getPopulation() * statData.factorInhabitants);
82  it->setWorkplaceNumber(it->getWorkplaceNumber() * statData.factorWorkPositions);
83  //it->print();
84  }
85 
86  //completing streets from edges of the network not handled/present in STAT file (no population no work position)
87  std::map<std::string, ROEdge*>::const_iterator itE;
88  std::vector<AGStreet>::iterator itS;
89 
90  for (itE = net->getEdgeMap().begin(); itE != net->getEdgeMap().end(); ++itE) {
91  for (itS = streets.begin(); itS != streets.end(); ++itS) {
92  if (itS->getName() == itE->second->getID()) {
93  break;
94  }
95  }
96  //if this edge isn't represented by a street
97  if (itS == streets.end() && itE->second->getType() != ROEdge::ET_INTERNAL) {
98  streets.push_back(AGStreet(itE->second));
99  }
100  }
101 }
102 
103 void
105  std::vector<AGStreet>::iterator it;
106  int workPositionCounter = 0;
107 
108  try {
109  for (it = streets.begin(); it != streets.end(); ++it) {
110  //std::cout << "number of work positions in street: " << it->getWorkplaceNumber() << std::endl;
111  for (int i = 0; i < it->getWorkplaceNumber(); ++i) {
112  workPositions.push_back(AGWorkPosition(&statData, *it));
113  ++workPositionCounter;
114  }
115  }
116  } catch (const std::bad_alloc& e) {
117  std::cout << "Number of work positions at bad_alloc exception: " << workPositionCounter << std::endl;
118  throw e;
119  }
120  //std::cout << "Inner work positions done. " << workPositionCounter << " generated." << std::endl;
121 
122  // Work positions outside the city
124  std::cout << "--> work position: " << std::endl;
125  std::cout << " |-> in city: " << workPositionCounter << std::endl;
126  std::cout << " |-> out city: " << statData.workPositions - workPositionCounter << std::endl;
127  std::cout << " |-> in+out city: " << statData.workPositions << std::endl;
128 }
129 
130 void
132  // work positions outside the city
134  if (nbrWorkers <= 0) {
135  return;
136  }
137  nbrWorkers *= (1.0 - statData.unemployement);
141  int nbrOutWorkPositions = static_cast<int>(workPositions.size() * (static_cast<SUMOReal>(statData.outgoingTraffic)) / (nbrWorkers - static_cast<SUMOReal>(statData.outgoingTraffic)));
142 
143  if (cityGates.empty()) {
144  return;
145  }
146 
147  for (int i = 0; i < nbrOutWorkPositions; ++i) {
149  workPositions.push_back(AGWorkPosition(&statData, cityGates[posi].getStreet(), cityGates[posi].getPosition()));
150  }
151  //cout << "outgoing traffic: " << statData.outgoingTraffic << std::endl;
152  //cout << "total number of workers in the city: " << nbrWorkers << std::endl;
153  //cout << "work positions out side the city: " << nbrOutWorkPositions << std::endl;
154  //cout << "work positions in and out of the city: " << workPositions.size() << std::endl;
155  statData.workPositions = static_cast<int>(workPositions.size());
156 }
157 
158 void
160  std::list<AGBusLine>::iterator it;
161  for (it = busLines.begin(); it != busLines.end(); ++it) {
162  //it->generateOpositDirection();
163  it->setBusNames();
164  }
165 }
166 
167 void
169  std::vector<AGStreet>::iterator it;
170  SUMOReal people = 0;
171  nbrCars = 0;
172  unsigned int idHouseholds = 0;
173  std::vector<int> numAdults(statData.households);
174  std::vector<int> numChilds(statData.households);
177  for (int i = 0; i < statData.households; i++) {
178  numAdults[i] = 1;
179  numChilds[i] = 0;
180  if (RandHelper::rand() < retiredProb) {
181  numAdults[i] = -numAdults[i];
182  } else if (totalChildrenLeft > 0) {
184  totalChildrenLeft -= numChilds[i];
185  }
186  }
187  //compensate with adults for too many / missing children
188  const int numSecondPers = statData.getPeopleOlderThan(statData.limitAgeChildren) - statData.households + totalChildrenLeft;
189  for (int i = 0; i < numSecondPers; i++) {
190  unsigned int index = i % numAdults.size();
191  if (numAdults[index] >= 0) {
192  numAdults[index] += 1;
193  } else {
194  numAdults[index] -= 1;
195  }
196  }
197  for (it = streets.begin(); it != streets.end(); ++it) {
198  people += it->getPopulation();
199  while (people > 0 && idHouseholds < (unsigned int)numAdults.size()) {
200  size_t i = RandHelper::rand(numAdults.size() - idHouseholds);
201  ++idHouseholds;
202  households.push_back(AGHousehold(&*it, this, idHouseholds));
203  households.back().generatePeople(abs(numAdults[i]), numChilds[i], numAdults[i] < 0); //&statData
204  //households.back().generateCars(statData.carRate);
205  people -= households.back().getPeopleNbr();
206  numAdults[i] = numAdults[numAdults.size() - idHouseholds];
207  numChilds[i] = numChilds[numAdults.size() - idHouseholds];
208  }
209  }
210 
211  //people from outside of the city generation:
213 
214  //TEST
215  int nbrSingle = 0;
216  int nbrCouple = 0;
217  int nbrChild = 0;
218  int nbrHH = 0;
219  int workingP = 0;
220  std::list<AGHousehold>::iterator itt;
221  for (itt = households.begin(); itt != households.end(); ++itt) {
222  if (itt->getAdultNbr() == 1) {
223  nbrSingle++;
224  if (itt->getAdults().front().isWorking()) {
225  workingP++;
226  }
227  }
228  if (itt->getAdultNbr() == 2) {
229  nbrCouple += 2;
230  if (itt->getAdults().front().isWorking()) {
231  workingP++;
232  }
233  if (itt->getAdults().back().isWorking()) {
234  workingP++;
235  }
236  }
237  nbrChild += itt->getPeopleNbr() - itt->getAdultNbr();
238  nbrHH++;
239  }
240  //cout << "number hh: " << nbrHH << std::endl;
241  //cout << "number single: " << nbrSingle << std::endl;
242  //cout << "number couple: " << nbrCouple << std::endl;
243  //cout << "number 3 or more: " << nbr3More << std::endl;
244  //cout << "number adults: " << nbrSingle + nbrCouple + nbr3More << std::endl;
245  //cout << "number children: " << nbrChild << std::endl;
246  //cout << "number people: " << nbrSingle + nbrCouple + nbr3More + nbrChild << std::endl;
247  //END TEST
248 
249  std::cout << "--> population: " << std::endl;
250  std::cout << " |-> city households: " << nbrHH << std::endl;
251  std::cout << " |-> city people: " << nbrSingle + nbrCouple + nbrChild << std::endl;
252  std::cout << " |-> city single: " << nbrSingle << " / (in) couple: " << nbrCouple << std::endl;
253  std::cout << " |-> city adults: " << nbrSingle + nbrCouple << std::endl;
254  std::cout << " |-> estimation: " << statData.getPeopleOlderThan(statData.limitAgeChildren) << std::endl;
255  std::cout << " |-> retired: " << statData.getPeopleOlderThan(statData.limitAgeRetirement) << std::endl;
256  std::cout << " |-> city children: " << nbrChild << std::endl;
257  std::cout << " |-> estimation: " << statData.getPeopleYoungerThan(statData.limitAgeChildren) << std::endl;
258 
259 }
260 
261 void
263  for (int i = 0; i < statData.incomingTraffic; ++i) {
265  peopleIncoming.push_back(ad);
266  }
267 }
268 
269 void
271  std::list<AGHousehold>::iterator it;
272  bool shortage;
273  for (it = households.begin(); it != households.end(); ++it) {
274  shortage = !it->allocateChildrenSchool();
275  if (shortage) {
276  /*ofstream fichier("test.txt", ios::app); // ouverture en écriture avec effacement du fichier ouvert
277  if(fichier)
278  {
279  fichier << "===> WARNING: Not enough school places in the city for all children..." << std::endl;
280  fichier.close();
281  }
282  else
283  cerr << "Impossible d'ouvrir le fichier !" << std::endl;*/
284 
285  //std::cout << "===> WARNING: Not enough school places in the city for all children..." << std::endl;
286  }
287  }
288 }
289 
290 void
292  statData.AdultNbr = 0;
293  //end tests
297  std::list<AGHousehold>::iterator it;
298  bool shortage;
299 
300  for (it = households.begin(); it != households.end(); ++it) {
301  if (it->retiredHouseholders()) {
302  continue;
303  }
304  shortage = !it->allocateAdultsWork();
305  if (shortage) {
306  std::cout << "===> ERROR: Not enough work positions in the city for all working people..." << std::endl;
307  }
308  statData.AdultNbr += it->getAdultNbr(); //TESTING
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)
364  //std::cout << " - " << newRate << std::endl;
365  if (newRate < 0 || newRate >= 1) {
366  newRate = 0;
367  }
368 
369  nbrCars = 0;
370  int nbrAdults = 0;
371  for (it = households.begin(); it != households.end(); ++it) {
372  it->generateCars(newRate);
373  nbrCars += it->getCarNbr();
374  nbrAdults += it->getAdultNbr();
375  }
376  //TEST RESULTS
377  //std::cout << "number of cars: " << nbrCars << std::endl;
378  //std::cout << "number of adults: " << statData.getPeopleOlderThan(statData.limitAgeChildren) << std::endl;
379  //std::cout << "real number of adults: " << nbrAdults << std::endl;
380  //std::cout << "number of people far from public transport: " << statData.hhFarFromPT << std::endl;
381  //std::cout << "original rate: " << setprecision(4) << statData.carRate << std::endl;
382  //std::cout << "new rate: " << setprecision(4) << newRate << std::endl;
383  //std::cout << "real rate: " << setprecision(4) << (SUMOReal)nbrCars / (SUMOReal)statData.getPeopleOlderThan(statData.limitAgeChildren) << std::endl;
384  //END TEST RESULTS
385 }
386 
387 const AGStreet&
388 AGCity::getStreet(const std::string& edge) {
395  if (!streetsCompleted) {
397  completeStreets();
398  std::cout << "first completed in getStreet() of City: Consolidation of data not needed in ActivityGen any more" << std::endl;
399  }
400  //rest of the function
401  std::vector<AGStreet>::iterator it = streets.begin();
402  while (it != streets.end()) {
403  if (it->getName() == edge) {
404  return *it;
405  }
406  ++it;
407  }
408  std::cout << "===> ERROR: WRONG STREET EDGE (" << edge << ") given and not found in street set." << std::endl;
409  throw(std::runtime_error("Street not found with edge id " + edge));
410 }
411 
412 const AGStreet&
414  if (streets.empty()) {
415  throw(std::runtime_error("No street found in this city"));
416  }
417  return streets[RandHelper::rand(streets.size())];
418 }
419 
420 /****************************************************************************/
void completeStreets()
Definition: AGCity.cpp:55
static SUMOReal rand()
Returns a random real number in [0, 1)
Definition: RandHelper.h:61
AGDataAndStatistics & statData
Definition: AGCity.h:87
A model of the street in the city.
Definition: AGStreet.h:57
An internal edge which models driving across a junction. This is currently not used for routing...
Definition: ROEdge.h:83
void generatePopulation()
Definition: AGCity.cpp:168
int getRandomPopDistributed(int n, int m)
std::vector< AGStreet > streets
Definition: AGCity.h:88
#define abs(a)
Definition: polyfonts.c:63
void completeBusLines()
Definition: AGCity.cpp:159
const AGStreet & getStreet(const std::string &edge)
Definition: AGCity.cpp:388
const std::map< std::string, ROEdge * > & getEdgeMap() const
Definition: RONet.cpp:409
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:413
void generateOutgoingWP()
Definition: AGCity.cpp:131
void schoolAllocation()
Definition: AGCity.cpp:270
void generateWorkPositions()
Definition: AGCity.cpp:104
std::list< AGHousehold > households
Definition: AGCity.h:92
void workAllocation()
Definition: AGCity.cpp:291
std::list< AGAdult > peopleIncoming
Definition: AGCity.h:94
bool streetsCompleted
Definition: AGCity.h:113
void carAllocation()
Definition: AGCity.cpp:349
int nbrCars
Definition: AGCity.h:115
int getPoissonsNumberOfChildren(SUMOReal mean)
RONet * net
Definition: AGCity.h:108
#define SUMOReal
Definition: config.h:215
void generateIncomingPopulation()
Definition: AGCity.cpp:262
std::vector< AGPosition > cityGates
Definition: AGCity.h:93
std::map< int, AGPosition > busStations
std::vector< AGWorkPosition > workPositions
Definition: AGCity.h:89