Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-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 Distribution_Parameterized.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Michael Behrisch
17 : /// @date Sept 2002
18 : ///
19 : // A distribution described by parameters such as the mean value and std-dev
20 : /****************************************************************************/
21 : #include <config.h>
22 :
23 : #include <cassert>
24 : #include <utils/common/RandHelper.h>
25 : #include <utils/common/StringTokenizer.h>
26 : #include <utils/common/ToString.h>
27 : #include <utils/common/StringUtils.h>
28 : #include <utils/common/MsgHandler.h>
29 :
30 : #include "Distribution_Parameterized.h"
31 :
32 :
33 : // ===========================================================================
34 : // method definitions
35 : // ===========================================================================
36 : /// @brief Constructor for any temporary distribution parsed directly from the description
37 1709125 : Distribution_Parameterized::Distribution_Parameterized(const std::string& description) :
38 3418250 : Distribution("") {
39 1709125 : myParameter = {0., 0.};
40 1709125 : parse(description, true);
41 1709125 : }
42 :
43 :
44 269 : Distribution_Parameterized::Distribution_Parameterized(const std::string& id, double mean, double deviation) :
45 269 : Distribution(id) {
46 269 : myParameter.push_back(mean);
47 269 : myParameter.push_back(deviation);
48 269 : }
49 :
50 :
51 779864 : Distribution_Parameterized::Distribution_Parameterized(const std::string& id, double mean, double deviation, double min, double max) :
52 779864 : Distribution(id) {
53 779864 : myParameter.push_back(mean);
54 779864 : myParameter.push_back(deviation);
55 779864 : myParameter.push_back(min);
56 779864 : myParameter.push_back(max);
57 779864 : }
58 :
59 :
60 2791779 : Distribution_Parameterized::~Distribution_Parameterized() {}
61 :
62 :
63 : void
64 1711513 : Distribution_Parameterized::parse(const std::string& description, const bool hardFail) {
65 : try {
66 1711513 : const std::string distName = description.substr(0, description.find('('));
67 1711513 : if (distName == "norm" || distName == "normc") {
68 504 : const std::vector<std::string> params = StringTokenizer(description.substr(distName.size() + 1, description.size() - distName.size() - 2), ',').getVector();
69 504 : myParameter.resize(params.size());
70 : std::transform(params.begin(), params.end(), myParameter.begin(), StringUtils::toDouble);
71 504 : setID(distName);
72 504 : } else {
73 1711009 : myParameter[0] = StringUtils::toDouble(description);
74 : }
75 1711513 : if (myParameter.size() == 1) {
76 4 : myParameter.push_back(0.);
77 : }
78 0 : } catch (...) {
79 : // set default distribution parameterized
80 0 : myParameter = {0., 0.};
81 0 : if (hardFail) {
82 0 : throw ProcessError(TL("Invalid format of distribution parameterized"));
83 : } else {
84 0 : WRITE_ERROR(TL("Invalid format of distribution parameterized"));
85 : }
86 0 : }
87 1711513 : }
88 :
89 :
90 : bool
91 0 : Distribution_Parameterized::isValidDescription(const std::string& description) {
92 : try {
93 0 : Distribution_Parameterized dummy(description);
94 0 : const std::string error = dummy.isValid();
95 0 : if (error == "") {
96 : return true;
97 : }
98 0 : WRITE_ERROR(error);
99 0 : } catch (...) {
100 0 : WRITE_ERROR(TL("Invalid format of distribution parameterized"));
101 0 : }
102 : return false;
103 : }
104 :
105 :
106 : double
107 7202058 : Distribution_Parameterized::sample(SumoRNG* which) const {
108 7202058 : if (myParameter[1] <= 0.) {
109 3814837 : return myParameter[0];
110 : }
111 3387221 : double val = RandHelper::randNorm(myParameter[0], myParameter[1], which);
112 3387221 : if (myParameter.size() > 2) {
113 3387147 : const double min = myParameter[2];
114 3387147 : const double max = getMax();
115 3418773 : while (val < min || val > max) {
116 31626 : val = RandHelper::randNorm(myParameter[0], myParameter[1], which);
117 : }
118 : }
119 : return val;
120 : }
121 :
122 :
123 : double
124 7638122 : Distribution_Parameterized::getMax() const {
125 7638122 : if (myParameter[1] <= 0.) {
126 4209534 : return myParameter[0];
127 : }
128 3428588 : return myParameter.size() > 3 ? myParameter[3] : std::numeric_limits<double>::infinity();
129 : }
130 :
131 :
132 : double
133 19682 : Distribution_Parameterized::getMin() const {
134 19682 : if (myParameter[1] <= 0.) {
135 5 : return myParameter[0];
136 : }
137 19677 : return myParameter.size() > 2 ? myParameter[2] : -std::numeric_limits<double>::infinity();
138 : }
139 :
140 :
141 : std::vector<double>&
142 554038 : Distribution_Parameterized::getParameter() {
143 554038 : return myParameter;
144 : }
145 :
146 :
147 : const std::vector<double>&
148 13753399 : Distribution_Parameterized::getParameter() const {
149 13753399 : return myParameter;
150 : }
151 :
152 :
153 : std::string
154 440 : Distribution_Parameterized::toStr(std::streamsize accuracy) const {
155 440 : if (myParameter[1] < 0) {
156 : // only write simple speedFactor
157 104 : return toString(myParameter[0]);
158 : } else {
159 : return (myParameter[1] == 0.
160 732 : ? myID + "(" + toString(myParameter[0], accuracy) + "," + toString(myParameter[1], accuracy) + ")"
161 1640 : : myID + "(" + joinToString(myParameter, ",", accuracy) + ")");
162 : }
163 : }
164 :
165 :
166 : const std::string
167 1769777 : Distribution_Parameterized::isValid() const {
168 1769777 : if (myParameter[1] > 0.) {
169 5906 : if (getMin() > getMax()) {
170 0 : return TLF("minimum value % larger than maximum %", getMin(), getMax());
171 : }
172 5906 : if (getMin() > myParameter[0] + 3 * myParameter[1]) {
173 0 : return TLF("minimum value % too large for distribution with mean % and deviation %", myParameter[2], myParameter[0], myParameter[1]);
174 : }
175 5906 : if (getMax() < myParameter[0] - 3 * myParameter[1]) {
176 26 : return TLF("maximum value % too small for distribution with mean % and deviation %", myParameter[3], myParameter[0], myParameter[1]);
177 : }
178 5893 : if (myParameter.size() > 3 && myParameter[3] - myParameter[2] < NUMERICAL_EPS * myParameter[1]) {
179 12 : return TLF("maximum value % and minimum value % too close for distribution with mean % and deviation %", myParameter[3], myParameter[2], myParameter[0], myParameter[1]);
180 : }
181 : }
182 1769758 : return "";
183 : }
184 :
185 :
186 : /****************************************************************************/
|