Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/utils/distribution/RandomDistributor.h
169678 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2005-2025 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
class RandomDistributor {
47
public:
48
/** @brief Constructor for an empty distribution
49
*/
50
RandomDistributor() :
51
myProb(0) {
52
}
53
54
/// @brief Destructor
55
~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
bool add(T val, double prob, bool checkDuplicates = true) {
69
myProb += prob;
70
assert(myProb >= 0);
71
if (checkDuplicates) {
72
for (int i = 0; i < (int)myVals.size(); i++) {
73
if (val == myVals[i]) {
74
myProbs[i] += prob;
75
assert(myProbs[i] >= 0);
76
return false;
77
}
78
}
79
} else {
80
assert(prob >= 0);
81
}
82
myVals.push_back(val);
83
myProbs.push_back(prob);
84
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
bool remove(T val) {
93
for (int i = 0; i < (int)myVals.size(); i++) {
94
if (myVals[i] == val) {
95
myProb -= myProbs[i];
96
myProbs.erase(myProbs.begin() + i);
97
myVals.erase(myVals.begin() + i);
98
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
T get(SumoRNG* which = nullptr) const {
112
if (myProb == 0) {
113
throw OutOfBoundsException();
114
}
115
double prob = RandHelper::rand(myProb, which);
116
for (int i = 0; i < (int)myVals.size(); i++) {
117
if (prob < myProbs[i]) {
118
return myVals[i];
119
}
120
prob -= myProbs[i];
121
}
122
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
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
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
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
};
173
174