#include <config.h>
#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <iomanip>
#include <utils/common/RandHelper.h>
#include <utils/common/SUMOVehicleClass.h>
#include <utils/options/OptionsCont.h>
#include <router/RONet.h>
#include <router/ROEdge.h>
#include "AGAdult.h"
#include "AGStreet.h"
#include "AGWorkPosition.h"
#include "AGCity.h"
void
AGCity::completeStreets() {
if (streetsCompleted) {
return;
} else {
streetsCompleted = true;
}
double pop = 0, work = 0;
std::vector<AGStreet*>::iterator it;
for (it = streets.begin(); it != streets.end(); ++it) {
pop += (*it)->getPopulation();
work += (*it)->getWorkplaceNumber();
if (((*it)->getPermissions() & SVC_PASSENGER) == SVC_PASSENGER) {
passengerStreets.push_back(*it);
}
}
statData.factorInhabitants = (double)statData.inhabitants / pop;
double neededWorkPositionsInCity = (1.0 - statData.unemployement)
* ((double)statData.getPeopleYoungerThan(statData.limitAgeRetirement)
- (double)statData.getPeopleYoungerThan(statData.limitAgeChildren))
+ (double)statData.incomingTraffic;
neededWorkPositionsInCity *= statData.laborDemand;
statData.workPositions = (int)neededWorkPositionsInCity;
statData.factorWorkPositions = neededWorkPositionsInCity / (double) work;
for (it = streets.begin(); it != streets.end(); ++it) {
(*it)->setPopulation((*it)->getPopulation() * statData.factorInhabitants);
(*it)->setWorkplaceNumber((*it)->getWorkplaceNumber() * statData.factorWorkPositions);
}
for (const auto& itE : net->getEdgeMap()) {
std::vector<AGStreet*>::iterator itS;
for (itS = streets.begin(); itS != streets.end(); ++itS) {
if (*itS == itE.second) {
break;
}
}
if (itS == streets.end() && !itE.second->isInternal()) {
streets.push_back(static_cast<AGStreet*>(itE.second));
if (((itE.second)->getPermissions() & SVC_PASSENGER) == SVC_PASSENGER) {
passengerStreets.push_back(static_cast<AGStreet*>(itE.second));
}
}
}
}
void
AGCity::generateWorkPositions() {
std::vector<AGStreet*>::iterator it;
int workPositionCounter = 0;
try {
for (it = streets.begin(); it != streets.end(); ++it) {
for (int i = 0; i < (*it)->getWorkplaceNumber(); ++i) {
workPositions.push_back(AGWorkPosition(&statData, **it));
++workPositionCounter;
}
}
} catch (const std::bad_alloc&) {
std::cout << "Number of work positions at bad_alloc exception: " << workPositionCounter << std::endl;
throw;
}
generateOutgoingWP();
std::cout << "--> work position:" << std::endl;
std::cout << " |-> in city: " << workPositionCounter << std::endl;
std::cout << " |-> out city: " << statData.workPositions - workPositionCounter << std::endl;
std::cout << " |-> in+out city: " << statData.workPositions << std::endl;
}
void
AGCity::generateOutgoingWP() {
double nbrWorkers = static_cast<double>(statData.getPeopleYoungerThan(statData.limitAgeRetirement) - statData.getPeopleYoungerThan(statData.limitAgeChildren));
if (nbrWorkers <= 0) {
return;
}
nbrWorkers *= (1.0 - statData.unemployement);
int nbrOutWorkPositions = (int)((double)workPositions.size() * (double)statData.outgoingTraffic / (nbrWorkers - (double)statData.outgoingTraffic));
if (cityGates.empty()) {
statData.workPositions = static_cast<int>(workPositions.size());
return;
}
for (int i = 0; i < nbrOutWorkPositions; ++i) {
int posi = statData.getRandomCityGateByOutgoing();
workPositions.push_back(AGWorkPosition(&statData, cityGates[posi].getStreet(), cityGates[posi].getPosition()));
}
statData.workPositions = static_cast<int>(workPositions.size());
}
void
AGCity::completeBusLines() {
std::list<AGBusLine>::iterator it;
for (it = busLines.begin(); it != busLines.end(); ++it) {
it->setBusNames();
}
}
void
AGCity::generatePopulation() {
std::vector<AGStreet*>::iterator it;
double people = 0;
nbrCars = 0;
int idHouseholds = 0;
std::vector<int> numAdults(statData.households);
std::vector<int> numChilds(statData.households);
int totalChildrenLeft = statData.inhabitants - statData.getPeopleOlderThan(statData.limitAgeChildren);
const double retiredProb = statData.getPeopleOlderThan(statData.limitAgeRetirement) / statData.getPeopleOlderThan(statData.limitAgeChildren);
for (int i = 0; i < statData.households; i++) {
numAdults[i] = 1;
numChilds[i] = 0;
if (RandHelper::rand() < retiredProb) {
numAdults[i] = -numAdults[i];
} else if (totalChildrenLeft > 0) {
numChilds[i] = statData.getPoissonsNumberOfChildren(statData.meanNbrChildren);
totalChildrenLeft -= numChilds[i];
}
}
const int numSecondPers = statData.getPeopleOlderThan(statData.limitAgeChildren) - statData.households + totalChildrenLeft;
for (int i = 0; i < numSecondPers; i++) {
int index = i % numAdults.size();
if (numAdults[index] >= 0) {
numAdults[index] += 1;
} else {
numAdults[index] -= 1;
}
}
for (it = streets.begin(); it != streets.end(); ++it) {
people += (*it)->getPopulation();
while (people > 0 && idHouseholds < (int)numAdults.size()) {
int i = RandHelper::rand((int)numAdults.size() - idHouseholds);
++idHouseholds;
households.push_back(AGHousehold(*it, this, idHouseholds));
households.back().generatePeople(abs(numAdults[i]), numChilds[i], numAdults[i] < 0);
people -= households.back().getPeopleNbr();
numAdults[i] = numAdults[numAdults.size() - idHouseholds];
numChilds[i] = numChilds[numAdults.size() - idHouseholds];
}
}
generateIncomingPopulation();
int nbrSingle = 0;
int nbrCouple = 0;
int nbrChild = 0;
int nbrHH = 0;
std::list<AGHousehold>::iterator itt;
for (itt = households.begin(); itt != households.end(); ++itt) {
if (itt->getAdultNbr() == 1) {
nbrSingle++;
}
if (itt->getAdultNbr() == 2) {
nbrCouple += 2;
}
nbrChild += itt->getPeopleNbr() - itt->getAdultNbr();
nbrHH++;
}
std::cout << "--> population:" << std::endl;
std::cout << " |-> city households: " << nbrHH << std::endl;
std::cout << " |-> city people: " << nbrSingle + nbrCouple + nbrChild << std::endl;
std::cout << " |-> city single: " << nbrSingle << " / (in) couple: " << nbrCouple << std::endl;
std::cout << " |-> city adults: " << nbrSingle + nbrCouple << std::endl;
std::cout << " |-> estimation: " << statData.getPeopleOlderThan(statData.limitAgeChildren) << std::endl;
std::cout << " |-> retired: " << statData.getPeopleOlderThan(statData.limitAgeRetirement) << std::endl;
std::cout << " |-> city children: " << nbrChild << std::endl;
std::cout << " |-> estimation: " << statData.getPeopleYoungerThan(statData.limitAgeChildren) << std::endl;
}
void
AGCity::generateIncomingPopulation() {
for (int i = 0; i < statData.incomingTraffic; ++i) {
AGAdult ad(statData.getRandomPopDistributed(statData.limitAgeChildren, statData.limitAgeRetirement));
peopleIncoming.push_back(ad);
}
}
void
AGCity::schoolAllocation() {
std::list<AGHousehold>::iterator it;
bool shortage;
for (it = households.begin(); it != households.end(); ++it) {
shortage = !it->allocateChildrenSchool();
if (shortage) {
}
}
}
void
AGCity::workAllocation() {
const bool debug = OptionsCont::getOptions().getBool("debug");
statData.AdultNbr = 0;
std::list<AGHousehold>::iterator it;
bool shortage;
if (debug) {
std::cout << "\n";
}
for (it = households.begin(); it != households.end(); ++it) {
if (it->retiredHouseholders()) {
continue;
}
shortage = !it->allocateAdultsWork();
if (shortage) {
std::cout << "===> ERROR: Not enough work positions in the city for all working people..." << std::endl;
}
statData.AdultNbr += it->getAdultNbr();
if (debug) {
std::cout << " processed " << statData.AdultNbr << " adults\r";
}
}
std::list<AGAdult>::iterator itA;
for (itA = peopleIncoming.begin(); itA != peopleIncoming.end(); ++itA) {
if (statData.workPositions > 0) {
itA->tryToWork(1, &workPositions);
} else {
std::cout << "not enough work for incoming people..." << std::endl;
}
}
int workingP = 0;
std::list<AGHousehold>::iterator itt;
for (itt = households.begin(); itt != households.end(); ++itt) {
if (itt->getAdultNbr() == 1) {
if (itt->getAdults().front().isWorking()) {
workingP++;
}
}
if (itt->getAdultNbr() == 2) {
if (itt->getAdults().front().isWorking()) {
workingP++;
}
if (itt->getAdults().back().isWorking()) {
workingP++;
}
}
}
std::cout << " |-> working people: " << peopleIncoming.size() + workingP << std::endl;
std::cout << " |-> working people in city: " << workingP << std::endl;
std::cout << " |-> working people from outside: " << peopleIncoming.size() << std::endl;
}
void
AGCity::carAllocation() {
statData.hhFarFromPT = 0;
nbrCars = 0;
std::list<AGHousehold>::iterator it;
for (it = households.begin(); it != households.end(); ++it) {
if (!it->isCloseFromPubTransport(&(statData.busStations))) {
statData.hhFarFromPT++;
nbrCars++;
it->addACar();
}
statData.householdsNbr++;
}
double newRate = statData.carRate * statData.getPeopleOlderThan(statData.limitAgeChildren) - statData.hhFarFromPT;
if (statData.getPeopleOlderThan(statData.limitAgeChildren) == statData.hhFarFromPT) {
newRate = 0.;
} else {
newRate /= statData.getPeopleOlderThan(statData.limitAgeChildren) - statData.hhFarFromPT;
}
if (newRate < 0 || newRate >= 1) {
newRate = 0;
}
nbrCars = 0;
for (it = households.begin(); it != households.end(); ++it) {
it->generateCars(newRate);
nbrCars += it->getCarNbr();
}
}
const AGStreet&
AGCity::getStreet(const std::string& edge) {
if (!streetsCompleted) {
statData.consolidateStat();
completeStreets();
std::cout << "first completed in getStreet() of City: Consolidation of data not needed in ActivityGen any more" << std::endl;
}
std::vector<AGStreet*>::iterator it = streets.begin();
while (it != streets.end()) {
if ((*it)->getID() == edge) {
return **it;
}
++it;
}
std::cout << "===> ERROR: WRONG STREET EDGE (" << edge << ") given and not found in street set." << std::endl;
throw ProcessError("Street not found with edge id " + edge);
}
const AGStreet&
AGCity::getRandomStreet() {
if (passengerStreets.empty()) {
throw ProcessError(TL("No street that allows passenger vehicles found in this city."));
}
return *RandHelper::getRandomFrom(passengerStreets);
}