Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-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 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 3357919 : Distribution_Parameterized::Distribution_Parameterized(const std::string& description) :
38 6715838 : Distribution("") {
39 3357919 : myParameter = {0., 0.};
40 3357919 : parse(description, true);
41 3357919 : }
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 677490 : Distribution_Parameterized::Distribution_Parameterized(const std::string& id, double mean, double deviation, double min, double max) :
52 677490 : Distribution(id) {
53 677490 : myParameter.push_back(mean);
54 677490 : myParameter.push_back(deviation);
55 677490 : myParameter.push_back(min);
56 677490 : myParameter.push_back(max);
57 677490 : }
58 :
59 :
60 4329691 : Distribution_Parameterized::~Distribution_Parameterized() {}
61 :
62 :
63 : void
64 3360370 : Distribution_Parameterized::parse(const std::string& description, const bool hardFail) {
65 : try {
66 3360370 : const std::string distName = description.substr(0, description.find('('));
67 3360370 : if (distName == "norm" || distName == "normc") {
68 523 : const std::vector<std::string> params = StringTokenizer(description.substr(distName.size() + 1, description.size() - distName.size() - 2), ',').getVector();
69 523 : myParameter.resize(params.size());
70 : std::transform(params.begin(), params.end(), myParameter.begin(), StringUtils::toDouble);
71 523 : setID(distName);
72 523 : } else {
73 3359847 : myParameter[0] = StringUtils::toDouble(description);
74 : }
75 3360370 : 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 3360370 : }
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 9110473 : Distribution_Parameterized::sample(SumoRNG* which) const {
108 9110473 : if (myParameter[1] <= 0.) {
109 5513034 : return myParameter[0];
110 : }
111 3597439 : double val = RandHelper::randNorm(myParameter[0], myParameter[1], which);
112 3597439 : if (myParameter.size() > 2) {
113 3597365 : const double min = myParameter[2];
114 3597365 : const double max = getMax();
115 3628980 : while (val < min || val > max) {
116 31615 : val = RandHelper::randNorm(myParameter[0], myParameter[1], which);
117 : }
118 : }
119 : return val;
120 : }
121 :
122 :
123 : double
124 7867373 : Distribution_Parameterized::getMax() const {
125 7867373 : if (myParameter[1] <= 0.) {
126 4227589 : return myParameter[0];
127 : }
128 3639784 : return myParameter.size() > 3 ? myParameter[3] : std::numeric_limits<double>::infinity();
129 : }
130 :
131 :
132 : double
133 20142 : Distribution_Parameterized::getMin() const {
134 20142 : if (myParameter[1] <= 0.) {
135 5 : return myParameter[0];
136 : }
137 20137 : return myParameter.size() > 2 ? myParameter[2] : -std::numeric_limits<double>::infinity();
138 : }
139 :
140 :
141 : void
142 498148 : Distribution_Parameterized::setParameter(const int index, const double value) {
143 498148 : myParameter[index] = value;
144 498148 : }
145 :
146 :
147 : std::string
148 462 : Distribution_Parameterized::toStr(std::streamsize accuracy) const {
149 462 : if (myParameter[1] < 0) {
150 : // only write simple speedFactor
151 104 : return toString(myParameter[0]);
152 : } else {
153 : return (myParameter[1] == 0.
154 776 : ? myID + "(" + toString(myParameter[0], accuracy) + "," + toString(myParameter[1], accuracy) + ")"
155 1750 : : myID + "(" + joinToString(myParameter, ",", accuracy) + ")");
156 : }
157 : }
158 :
159 :
160 : const std::string
161 3420523 : Distribution_Parameterized::isValid() const {
162 3420523 : if (myParameter[1] > 0.) {
163 6133 : if (getMin() > getMax()) {
164 0 : return TLF("minimum value % larger than maximum %", getMin(), getMax());
165 : }
166 6133 : if (getMin() > myParameter[0] + 3 * myParameter[1]) {
167 0 : return TLF("minimum value % too large for distribution with mean % and deviation %", myParameter[2], myParameter[0], myParameter[1]);
168 : }
169 6133 : if (getMax() < myParameter[0] - 3 * myParameter[1]) {
170 26 : return TLF("maximum value % too small for distribution with mean % and deviation %", myParameter[3], myParameter[0], myParameter[1]);
171 : }
172 6120 : if (myParameter.size() > 3 && myParameter[3] - myParameter[2] < NUMERICAL_EPS * myParameter[1]) {
173 12 : return TLF("maximum value % and minimum value % too close for distribution with mean % and deviation %", myParameter[3], myParameter[2], myParameter[0], myParameter[1]);
174 : }
175 : }
176 3420504 : return "";
177 : }
178 :
179 :
180 : /****************************************************************************/
|