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 51333064 : Distribution_Parameterized::Distribution_Parameterized(const std::string& description) :
38 102666128 : Distribution("") {
39 51333064 : myParameter = {0., 0.};
40 51333064 : parse(description, true);
41 51333064 : }
42 :
43 :
44 266 : Distribution_Parameterized::Distribution_Parameterized(const std::string& id, double mean, double deviation) :
45 266 : Distribution(id) {
46 266 : myParameter.push_back(mean);
47 266 : myParameter.push_back(deviation);
48 266 : }
49 :
50 :
51 1092669 : Distribution_Parameterized::Distribution_Parameterized(const std::string& id, double mean, double deviation, double min, double max) :
52 1092669 : Distribution(id) {
53 1092669 : myParameter.push_back(mean);
54 1092669 : myParameter.push_back(deviation);
55 1092669 : myParameter.push_back(min);
56 1092669 : myParameter.push_back(max);
57 1092669 : }
58 :
59 :
60 52726494 : Distribution_Parameterized::~Distribution_Parameterized() {}
61 :
62 :
63 : void
64 51335428 : Distribution_Parameterized::parse(const std::string& description, const bool hardFail) {
65 : try {
66 51335428 : const std::string distName = description.substr(0, description.find('('));
67 51335428 : if (distName == "norm" || distName == "normc") {
68 493 : const std::vector<std::string> params = StringTokenizer(description.substr(distName.size() + 1, description.size() - distName.size() - 2), ',').getVector();
69 493 : myParameter.resize(params.size());
70 : std::transform(params.begin(), params.end(), myParameter.begin(), StringUtils::toDouble);
71 493 : setID(distName);
72 493 : } else {
73 51334935 : myParameter[0] = StringUtils::toDouble(description);
74 : }
75 51335428 : 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 51335428 : }
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 56792264 : Distribution_Parameterized::sample(SumoRNG* which) const {
108 56792264 : if (myParameter[1] <= 0.) {
109 53428241 : return myParameter[0];
110 : }
111 3364023 : double val = RandHelper::randNorm(myParameter[0], myParameter[1], which);
112 3364023 : if (myParameter.size() > 2) {
113 3363949 : const double min = myParameter[2];
114 3363949 : const double max = getMax();
115 3395496 : while (val < min || val > max) {
116 31547 : val = RandHelper::randNorm(myParameter[0], myParameter[1], which);
117 : }
118 : }
119 : return val;
120 : }
121 :
122 :
123 : double
124 7597896 : Distribution_Parameterized::getMax() const {
125 7597896 : if (myParameter[1] <= 0.) {
126 4193191 : return myParameter[0];
127 : }
128 3404705 : return myParameter.size() > 3 ? myParameter[3] : std::numeric_limits<double>::infinity();
129 : }
130 :
131 :
132 : double
133 19467 : Distribution_Parameterized::getMin() const {
134 19467 : if (myParameter[1] <= 0.) {
135 5 : return myParameter[0];
136 : }
137 19462 : return myParameter.size() > 2 ? myParameter[2] : -std::numeric_limits<double>::infinity();
138 : }
139 :
140 :
141 : std::vector<double>&
142 869759 : Distribution_Parameterized::getParameter() {
143 869759 : return myParameter;
144 : }
145 :
146 :
147 : const std::vector<double>&
148 13609019 : Distribution_Parameterized::getParameter() const {
149 13609019 : return myParameter;
150 : }
151 :
152 :
153 : std::string
154 428 : Distribution_Parameterized::toStr(std::streamsize accuracy) const {
155 428 : if (myParameter[1] < 0) {
156 : // only write simple speedFactor
157 104 : return toString(myParameter[0]);
158 : } else {
159 : return (myParameter[1] == 0.
160 708 : ? myID + "(" + toString(myParameter[0], accuracy) + "," + toString(myParameter[1], accuracy) + ")"
161 1580 : : myID + "(" + joinToString(myParameter, ",", accuracy) + ")");
162 : }
163 : }
164 :
165 :
166 : const std::string
167 51393447 : Distribution_Parameterized::isValid() const {
168 51393447 : if (myParameter[1] > 0.) {
169 5806 : if (getMin() > getMax()) {
170 0 : return TLF("minimum value % larger than maximum %", getMin(), getMax());
171 : }
172 5806 : 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 5806 : 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 5793 : 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 51393428 : return "";
183 : }
184 :
185 :
186 : /****************************************************************************/
|