Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2005-2024 German Aerospace Center (DLR) and others.
4 : // This program and the accompanying materials are made available under the
5 : // terms of the Eclipse Public License 2.0 which is available at
6 : // https://www.eclipse.org/legal/epl-2.0/
7 : // This Source Code may also be made available under the following Secondary
8 : // Licenses when the conditions for such availability set forth in the Eclipse
9 : // Public License 2.0 are satisfied: GNU General Public License, version 2
10 : // or later which is available at
11 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 : /****************************************************************************/
14 : /// @file RandomDistributor.h
15 : /// @author Daniel Krajzewicz
16 : /// @author Michael Behrisch
17 : /// @author Jakob Erdmann
18 : /// @date 2005-09-15
19 : ///
20 : // Represents a generic random distribution
21 : /****************************************************************************/
22 : #pragma once
23 : #include <config.h>
24 :
25 : #include <cassert>
26 : #include <limits>
27 : #include <utils/common/RandHelper.h>
28 : #include <utils/common/UtilExceptions.h>
29 :
30 :
31 : // ===========================================================================
32 : // class definitions
33 : // ===========================================================================
34 : /**
35 : * @class RandomDistributor
36 : * @brief Represents a generic random distribution
37 : *
38 : * This class allows to create random distributions by assigning
39 : * arbitrary (non-negative) probabilities to its elements. The
40 : * random number generator used is specified in RandHelper.
41 : *
42 : * @see RandHelper
43 : */
44 :
45 : template<class T>
46 70 : class RandomDistributor {
47 : public:
48 : /** @brief Constructor for an empty distribution
49 : */
50 117077 : RandomDistributor() :
51 447548 : myProb(0) {
52 : }
53 :
54 : /// @brief Destructor
55 440937 : ~RandomDistributor() { }
56 :
57 : /** @brief Adds a value with an assigned probability to the distribution.
58 : *
59 : * If the value is already member of the distribution and checkDuplicates is
60 : * true (the default) the given probability is added to the current.
61 : * The probability has to be non-negative but values larger than one are
62 : * allowed (and scaled accordingly when an element is drawn).
63 : *
64 : * @param[in] val The value to add to the distribution
65 : * @param[in] prob The probability assigned to the value
66 : * @return true if a new value was added, false if just the probability of an existing one was updated
67 : */
68 1324493 : bool add(T val, double prob, bool checkDuplicates = true) {
69 1324493 : myProb += prob;
70 : assert(myProb >= 0);
71 1324493 : if (checkDuplicates) {
72 3181646 : for (int i = 0; i < (int)myVals.size(); i++) {
73 1863656 : if (val == myVals[i]) {
74 4641 : myProbs[i] += prob;
75 : assert(myProbs[i] >= 0);
76 4641 : return false;
77 : }
78 : }
79 : } else {
80 : assert(prob >= 0);
81 : }
82 1319852 : myVals.push_back(val);
83 1319852 : myProbs.push_back(prob);
84 1319852 : return true;
85 : }
86 :
87 : /** @brief Removes a value with an assigned probability from the distribution.
88 : *
89 : * @param[in] val The value to remove from the distribution
90 : * @return true if a new value was added, false if just the probability of an existing one was updated
91 : */
92 192 : bool remove(T val) {
93 536 : for (int i = 0; i < (int)myVals.size(); i++) {
94 454 : if (myVals[i] == val) {
95 110 : myProb -= myProbs[i];
96 110 : myProbs.erase(myProbs.begin() + i);
97 110 : myVals.erase(myVals.begin() + i);
98 110 : return true;
99 : }
100 : }
101 : return false;
102 : }
103 :
104 : /** @brief Draw a sample of the distribution.
105 : *
106 : * A random sample is drawn according to the assigned probabilities.
107 : *
108 : * @param[in] which The random number generator to use; the static one will be used if 0 is passed
109 : * @return the drawn member
110 : */
111 991153 : T get(SumoRNG* which = nullptr) const {
112 991153 : if (myProb == 0) {
113 0 : throw OutOfBoundsException();
114 : }
115 : double prob = RandHelper::rand(myProb, which);
116 1452726 : for (int i = 0; i < (int)myVals.size(); i++) {
117 1452726 : if (prob < myProbs[i]) {
118 458738 : return myVals[i];
119 : }
120 461573 : prob -= myProbs[i];
121 : }
122 0 : return myVals.back();
123 : }
124 :
125 : /** @brief Return the sum of the probabilites assigned to the members.
126 : *
127 : * This should be zero if and only if the distribution is empty.
128 : *
129 : * @return the total probability
130 : */
131 : double getOverallProb() const {
132 1884642 : return myProb;
133 : }
134 :
135 : /// @brief Clears the distribution
136 : void clear() {
137 : myProb = 0;
138 : myVals.clear();
139 : myProbs.clear();
140 : }
141 :
142 : /** @brief Returns the members of the distribution.
143 : *
144 : * See getProbs for the corresponding probabilities.
145 : *
146 : * @return the members of the distribution
147 : * @see RandomDistributor::getProbs
148 : */
149 : const std::vector<T>& getVals() const {
150 59150 : return myVals;
151 : }
152 :
153 : /** @brief Returns the probabilities assigned to the members of the distribution.
154 : *
155 : * See getVals for the corresponding members.
156 : *
157 : * @return the probabilities assigned to the distribution
158 : * @see RandomDistributor::getVals
159 : */
160 : const std::vector<double>& getProbs() const {
161 58720 : return myProbs;
162 : }
163 :
164 : private:
165 : /// @brief the total probability
166 : double myProb;
167 : /// @brief the members
168 : std::vector<T> myVals;
169 : /// @brief the corresponding probabilities
170 : std::vector<double> myProbs;
171 :
172 : };
|