Path: blob/main/src/activitygen/city/AGDataAndStatistics.cpp
169678 views
/****************************************************************************/1// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo2// Copyright (C) 2001-2025 German Aerospace Center (DLR) and others.3// activitygen module4// Copyright 2010 TUM (Technische Universitaet Muenchen, http://www.tum.de/)5// This program and the accompanying materials are made available under the6// terms of the Eclipse Public License 2.0 which is available at7// https://www.eclipse.org/legal/epl-2.0/8// This Source Code may also be made available under the following Secondary9// Licenses when the conditions for such availability set forth in the Eclipse10// Public License 2.0 are satisfied: GNU General Public License, version 211// or later which is available at12// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html13// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later14/****************************************************************************/15/// @file AGDataAndStatistics.cpp16/// @author Piotr Woznica17/// @author Daniel Krajzewicz18/// @author Michael Behrisch19/// @author Walter Bamberger20/// @date July 201021///22// Contains various data, statistical values and functions from input used23// by various objects24/****************************************************************************/25#include <config.h>2627#include "AGDataAndStatistics.h"28#include <utils/common/RandHelper.h>29#include <cmath>30#include <iomanip>31#define LIMIT_CHILDREN_NUMBER 3323334// ===========================================================================35// method definitions36// ===========================================================================37AGDataAndStatistics&38AGDataAndStatistics::getDataAndStatistics() {39static AGDataAndStatistics ds;40return ds;41}4243int44AGDataAndStatistics::getRandom(int n, int m) {45if (m < n) {46return 0;47}48int num = RandHelper::rand(m - n);49num += n;50return num;51}5253int54AGDataAndStatistics::getRandomPopDistributed(int n, int m) {55if (m < n || n >= limitEndAge) {56return -1;57}58if (m > limitEndAge) {59m = limitEndAge;60}61const double alea = RandHelper::rand(getPropYoungerThan(n), getPropYoungerThan(m));62for (int a = n; a < m; ++a) {63if (alea < getPropYoungerThan(a + 1)) {64return a;65}66}67return -1;68}6970int71AGDataAndStatistics::getPoissonsNumberOfChildren(double mean) {72double alea = RandHelper::rand();73double cumul = 0;74for (int nbr = 0; nbr < LIMIT_CHILDREN_NUMBER; ++nbr) {75cumul += poisson(mean, nbr);76if (cumul > alea) {77return nbr;78}79}80return LIMIT_CHILDREN_NUMBER;81}8283double84AGDataAndStatistics::poisson(double mean, int occ) {85return exp(-mean) * pow(mean, occ) / (double)factorial(occ);86}8788int89AGDataAndStatistics::factorial(int fact) {90if (fact > 0) {91return fact * factorial(fact - 1);92}93return 1;94}9596void97AGDataAndStatistics::consolidateStat() {98normalizeMapProb(&beginWorkHours);99normalizeMapProb(&endWorkHours);100normalizeMapProb(&population);101normalizeMapProb(&incoming);102normalizeMapProb(&outgoing);103limitEndAge = population.rbegin()->first;104105oldAgeHhProb = (double)getPeopleOlderThan(limitAgeRetirement) / (double)getPeopleOlderThan(limitAgeChildren);106secondPersProb = (double)(getPeopleOlderThan(limitAgeChildren) - households) / (double)households;107meanNbrChildren = (double)getPeopleYoungerThan(limitAgeChildren) / ((1 - oldAgeHhProb) * (double)households);108//cout << " --> oldAgeHhProb = " << setprecision(3) << oldAgeHhProb << " - retAge? " << getPeopleOlderThan(limitAgeRetirement) << " adAge? " << getPeopleOlderThan(limitAgeChildren) << endl;109//cout << " --> secondPersProb = " << setprecision(3) << secondPersProb << " - adAge? " << getPeopleOlderThan(limitAgeChildren) << " hh?" << households << endl;110//cout << " --> meanNbrChildren = " << setprecision(3) << meanNbrChildren << " - chAge? " << getPeopleYoungerThan(limitAgeChildren) << endl;111}112113double114AGDataAndStatistics::getPropYoungerThan(int age) {115std::map<int, double>::iterator it;116double sum = 0;117int previousAge = 0;118double prop = 0;119120for (it = population.begin(); it != population.end(); ++it) {121if (it->first < age) {122sum += it->second;123} else if (it->first >= age && previousAge < age) {124prop = ((double)(age - previousAge) / (double)(it->first - previousAge));125sum += prop * it->second;126break;127}128previousAge = it->first;129}130return sum;131}132133int134AGDataAndStatistics::getPeopleYoungerThan(int age) {135return (int)((double)inhabitants * getPropYoungerThan(age) + .5);136}137138int139AGDataAndStatistics::getPeopleOlderThan(int age) {140return (inhabitants - getPeopleYoungerThan(age));141}142143void144AGDataAndStatistics::normalizeMapProb(std::map<int, double>* myMap) {145double sum = 0;146std::map<int, double>::iterator it;147for (it = myMap->begin(); it != myMap->end(); ++it) {148sum += it->second;149}150if (sum == 0) {151return;152}153for (it = myMap->begin(); it != myMap->end(); ++it) {154it->second = it->second / sum;155}156}157158double159AGDataAndStatistics::getInverseExpRandomValue(double mean, double maxVar) {160if (maxVar <= 0) {161return mean;162}163double p = RandHelper::rand(static_cast<double>(0.0001), static_cast<double>(1));164//we have to scale the distribution because maxVar is different from INF165double scale = exp((-1) * maxVar);166//new p: scaled167p = p * (1 - scale) + scale; // p = [scale; 1) ==> (1-p) = (0; 1-scale]168169double variation = (-1) * log(p);170//decide the side of the mean value171if (RandHelper::rand(1000) < 500) {172return mean + variation;173} else {174return mean - variation;175}176177}178179int180AGDataAndStatistics::getRandomCityGateByIncoming() {181double alea = RandHelper::rand();182double total = 0;183std::map<int, double>::iterator it;184for (it = incoming.begin(); it != incoming.end(); ++it) {185total += it->second;186if (alea < total) {187return it->first;188}189}190std::cout << "ERROR: incoming at city gates not normalized" << std::endl;191return 0;192}193194int195AGDataAndStatistics::getRandomCityGateByOutgoing() {196double alea = RandHelper::rand();197double total = 0;198std::map<int, double>::iterator it;199for (it = outgoing.begin(); it != outgoing.end(); ++it) {200total += it->second;201if (alea < total) {202return it->first;203}204}205std::cout << "ERROR: outgoing at city gates not normalized" << std::endl;206return 0;207}208209210/****************************************************************************/211212213