Path: blob/main/src/utils/distribution/RandomDistributor.h
169678 views
/****************************************************************************/1// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo2// Copyright (C) 2005-2025 German Aerospace Center (DLR) and others.3// This program and the accompanying materials are made available under the4// terms of the Eclipse Public License 2.0 which is available at5// https://www.eclipse.org/legal/epl-2.0/6// This Source Code may also be made available under the following Secondary7// Licenses when the conditions for such availability set forth in the Eclipse8// Public License 2.0 are satisfied: GNU General Public License, version 29// or later which is available at10// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html11// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later12/****************************************************************************/13/// @file RandomDistributor.h14/// @author Daniel Krajzewicz15/// @author Michael Behrisch16/// @author Jakob Erdmann17/// @date 2005-09-1518///19// Represents a generic random distribution20/****************************************************************************/21#pragma once22#include <config.h>2324#include <cassert>25#include <limits>26#include <utils/common/RandHelper.h>27#include <utils/common/UtilExceptions.h>282930// ===========================================================================31// class definitions32// ===========================================================================33/**34* @class RandomDistributor35* @brief Represents a generic random distribution36*37* This class allows to create random distributions by assigning38* arbitrary (non-negative) probabilities to its elements. The39* random number generator used is specified in RandHelper.40*41* @see RandHelper42*/4344template<class T>45class RandomDistributor {46public:47/** @brief Constructor for an empty distribution48*/49RandomDistributor() :50myProb(0) {51}5253/// @brief Destructor54~RandomDistributor() { }5556/** @brief Adds a value with an assigned probability to the distribution.57*58* If the value is already member of the distribution and checkDuplicates is59* true (the default) the given probability is added to the current.60* The probability has to be non-negative but values larger than one are61* allowed (and scaled accordingly when an element is drawn).62*63* @param[in] val The value to add to the distribution64* @param[in] prob The probability assigned to the value65* @return true if a new value was added, false if just the probability of an existing one was updated66*/67bool add(T val, double prob, bool checkDuplicates = true) {68myProb += prob;69assert(myProb >= 0);70if (checkDuplicates) {71for (int i = 0; i < (int)myVals.size(); i++) {72if (val == myVals[i]) {73myProbs[i] += prob;74assert(myProbs[i] >= 0);75return false;76}77}78} else {79assert(prob >= 0);80}81myVals.push_back(val);82myProbs.push_back(prob);83return true;84}8586/** @brief Removes a value with an assigned probability from the distribution.87*88* @param[in] val The value to remove from the distribution89* @return true if a new value was added, false if just the probability of an existing one was updated90*/91bool remove(T val) {92for (int i = 0; i < (int)myVals.size(); i++) {93if (myVals[i] == val) {94myProb -= myProbs[i];95myProbs.erase(myProbs.begin() + i);96myVals.erase(myVals.begin() + i);97return true;98}99}100return false;101}102103/** @brief Draw a sample of the distribution.104*105* A random sample is drawn according to the assigned probabilities.106*107* @param[in] which The random number generator to use; the static one will be used if 0 is passed108* @return the drawn member109*/110T get(SumoRNG* which = nullptr) const {111if (myProb == 0) {112throw OutOfBoundsException();113}114double prob = RandHelper::rand(myProb, which);115for (int i = 0; i < (int)myVals.size(); i++) {116if (prob < myProbs[i]) {117return myVals[i];118}119prob -= myProbs[i];120}121return myVals.back();122}123124/** @brief Return the sum of the probabilites assigned to the members.125*126* This should be zero if and only if the distribution is empty.127*128* @return the total probability129*/130double getOverallProb() const {131return myProb;132}133134/// @brief Clears the distribution135void clear() {136myProb = 0;137myVals.clear();138myProbs.clear();139}140141/** @brief Returns the members of the distribution.142*143* See getProbs for the corresponding probabilities.144*145* @return the members of the distribution146* @see RandomDistributor::getProbs147*/148const std::vector<T>& getVals() const {149return myVals;150}151152/** @brief Returns the probabilities assigned to the members of the distribution.153*154* See getVals for the corresponding members.155*156* @return the probabilities assigned to the distribution157* @see RandomDistributor::getVals158*/159const std::vector<double>& getProbs() const {160return myProbs;161}162163private:164/// @brief the total probability165double myProb;166/// @brief the members167std::vector<T> myVals;168/// @brief the corresponding probabilities169std::vector<double> myProbs;170171};172173174