Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2026 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 RandHelper.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Michael Behrisch
17 : /// @date Tue, 29.05.2005
18 : ///
19 : //
20 : /****************************************************************************/
21 : #include <config.h>
22 :
23 : #include <ctime>
24 : #include <utils/options/OptionsCont.h>
25 : #include <utils/common/SysUtils.h>
26 : #include "StdDefs.h"
27 : #include "Translation.h"
28 : #include "RandHelper.h"
29 :
30 :
31 : // debug vehicle movement randomness (dawdling in finalizeSpeed)
32 : //#define DEBUG_FLAG1
33 : //#define DEBUG_RANDCALLS
34 : //#define DEBUG_RANDCALLS_PARALLEL
35 :
36 :
37 : // ===========================================================================
38 : // static member variables
39 : // ===========================================================================
40 : SumoRNG RandHelper::myRandomNumberGenerator("default");
41 :
42 : #ifdef DEBUG_RANDCALLS
43 : unsigned long long int myDebugIndex(7);
44 : std::string myDebugId("");
45 : #endif
46 :
47 : #ifdef DEBUG_RANDCALLS_PARALLEL
48 : #include <thread>
49 : #include <utils/iodevices/OutputDevice.h>
50 : std::map<std::thread::id, int> threadIndices;
51 : std::map<std::string, int> lastThreadIndex; // by rng
52 : #endif
53 :
54 :
55 : // ===========================================================================
56 : // member method definitions
57 : // ===========================================================================
58 :
59 : void
60 52748 : RandHelper::insertRandOptions(OptionsCont& oc) {
61 : // registers random number options
62 52748 : oc.addOptionSubTopic("Random Number");
63 :
64 52748 : oc.doRegister("random", new Option_Bool(false));
65 105496 : oc.addSynonyme("random", "abs-rand", true);
66 105496 : oc.addDescription("random", "Random Number", TL("Initialises the random number generator with the current system time"));
67 :
68 52748 : oc.doRegister("seed", new Option_Integer(23423));
69 105496 : oc.addSynonyme("seed", "srand", true);
70 105496 : oc.addDescription("seed", "Random Number", TL("Initialises the random number generator with the given value"));
71 52748 : }
72 :
73 :
74 : void
75 3024715 : RandHelper::initRand(SumoRNG* which, const bool random, const int seed) {
76 3024715 : if (which == nullptr) {
77 : which = &myRandomNumberGenerator;
78 : }
79 3024715 : if (random) {
80 0 : which->setSeed((unsigned long)time(nullptr));
81 : } else {
82 : which->setSeed(seed);
83 : }
84 3024715 : }
85 :
86 :
87 : void
88 304522 : RandHelper::initRandGlobal(SumoRNG* which) {
89 304522 : OptionsCont& oc = OptionsCont::getOptions();
90 609044 : initRand(which, oc.getBool("random"), oc.getInt("seed"));
91 304522 : }
92 :
93 : int
94 6086812 : RandHelper::getSeed(SumoRNG* which) {
95 6086812 : if (which == nullptr) {
96 : which = &myRandomNumberGenerator;
97 : }
98 6086812 : return which->origSeed;
99 : }
100 :
101 : double
102 886552368 : RandHelper::rand(SumoRNG* rng) {
103 886552368 : if (rng == nullptr) {
104 : rng = &myRandomNumberGenerator;
105 : }
106 886552368 : const double res = double((*rng)() / 4294967296.0);
107 886552368 : rng->count++;
108 : #ifdef DEBUG_RANDCALLS
109 : if (rng->count == myDebugIndex
110 : && (myDebugId == "" || rng->id == myDebugId)) {
111 : std::cout << "DEBUG\n"; // for setting breakpoint
112 : }
113 : std::stringstream stream; // to reduce output interleaving from different threads
114 : #ifdef DEBUG_RANDCALLS_PARALLEL
115 : auto threadID = std::this_thread::get_id();
116 : if (threadIndices.count(threadID) == 0) {
117 : const int tmp = threadIndices.size();
118 : threadIndices[threadID] = tmp;
119 : }
120 : int threadIndex = threadIndices[threadID];
121 : auto it = lastThreadIndex.find(rng->id);
122 : if ((it == lastThreadIndex.end() || it->second != threadIndex)
123 : && (myDebugId == "" || rng->id == myDebugId)) {
124 : std::cout << "DEBUG rng " << rng->id << " change thread old=" << (it == lastThreadIndex.end() ? -1 : it->second) << " new=" << threadIndex << " (" << std::this_thread::get_id() << ")\n"; // for setting breakpoint
125 : }
126 : lastThreadIndex[rng->id] = threadIndex;
127 : stream << "rng " << rng->id << " call=" << rng->count << " thread=" << threadIndex << " val=" << res << "\n";
128 : OutputDevice::getDevice(rng->id) << stream.str();
129 : #else
130 : stream << "rng " << rng->id << " call=" << rng->count << " val=" << res << "\n";
131 : std::cout << stream.str();
132 : #endif
133 : #endif
134 : #ifdef DEBUG_FLAG1
135 : if (gDebugFlag1) {
136 : std::stringstream stream; // to reduce output interleaving from different threads
137 : stream << "rng " << rng->id << " call=" << rng->count << " val=" << res << "\n";
138 : std::cout << stream.str();
139 : }
140 : #endif
141 886552368 : return res;
142 : }
143 :
144 : double
145 38473484 : RandHelper::randNorm(double mean, double variance, SumoRNG* rng) {
146 : // Polar method to avoid cosine
147 : double u, q;
148 : do {
149 49029121 : u = rand(2.0, rng) - 1;
150 49029121 : const double v = rand(2.0, rng) - 1;
151 49029121 : q = u * u + v * v;
152 49029121 : } while (q == 0.0 || q >= 1.0);
153 38473484 : const double logRounded = ceil(log(q) * 1e14) / 1e14;
154 38473484 : return mean + variance * u * sqrt(-2 * logRounded / q);
155 : }
156 :
157 : double
158 338692 : RandHelper::randExp(double rate, SumoRNG* rng) {
159 338692 : double r = rand(rng);
160 338692 : while (r == 0) {
161 0 : r = rand(rng);
162 : }
163 338692 : return -log(r) / rate;
164 : }
165 :
166 : // template<class T>
167 : // void RandHelper::shuffle(const std::vector<T>& v) {
168 : // std::shuffle(v.begin(), v.end(), rng);
169 : // }
170 :
171 : /****************************************************************************/
|