Eclipse SUMO - Simulation of Urban MObility
RandHelper.cpp
Go to the documentation of this file.
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 /****************************************************************************/
19 //
20 /****************************************************************************/
21 #include <config.h>
22 
23 #include <ctime>
25 #include <utils/common/SysUtils.h>
26 #include "StdDefs.h"
27 #include "RandHelper.h"
28 
29 
30 // debug vehicle movement randomness (dawdling in finalizeSpeed)
31 //#define DEBUG_FLAG1
32 //#define DEBUG_RANDCALLS
33 //#define DEBUG_RANDCALLS_PARALLEL
34 
35 
36 // ===========================================================================
37 // static member variables
38 // ===========================================================================
40 
41 #ifdef DEBUG_RANDCALLS
42 unsigned long long int myDebugIndex(7);
43 std::string myDebugId("");
44 #endif
45 
46 #ifdef DEBUG_RANDCALLS_PARALLEL
47 #include <thread>
49 std::map<std::thread::id, int> threadIndices;
50 std::map<std::string, int> lastThreadIndex; // by rng
51 #endif
52 
53 
54 // ===========================================================================
55 // member method definitions
56 // ===========================================================================
57 
58 void
60  // registers random number options
61  oc.addOptionSubTopic("Random Number");
62 
63  oc.doRegister("random", new Option_Bool(false));
64  oc.addSynonyme("random", "abs-rand", true);
65  oc.addDescription("random", "Random Number", TL("Initialises the random number generator with the current system time"));
66 
67  oc.doRegister("seed", new Option_Integer(23423));
68  oc.addSynonyme("seed", "srand", true);
69  oc.addDescription("seed", "Random Number", TL("Initialises the random number generator with the given value"));
70 }
71 
72 
73 void
74 RandHelper::initRand(SumoRNG* which, const bool random, const int seed) {
75  if (which == nullptr) {
76  which = &myRandomNumberGenerator;
77  }
78  if (random) {
79  which->seed((unsigned long)time(nullptr));
80  } else {
81  which->seed(seed);
82  }
83 }
84 
85 
86 void
89  initRand(which, oc.getBool("random"), oc.getInt("seed"));
90 }
91 
92 
93 double
95  if (rng == nullptr) {
97  }
98  const double res = double((*rng)() / 4294967296.0);
99  rng->count++;
100 #ifdef DEBUG_RANDCALLS
101  if (rng->count == myDebugIndex
102  && (myDebugId == "" || rng->id == myDebugId)) {
103  std::cout << "DEBUG\n"; // for setting breakpoint
104  }
105  std::stringstream stream; // to reduce output interleaving from different threads
106 #ifdef DEBUG_RANDCALLS_PARALLEL
107  auto threadID = std::this_thread::get_id();
108  if (threadIndices.count(threadID) == 0) {
109  const int tmp = threadIndices.size();
110  threadIndices[threadID] = tmp;
111  }
112  int threadIndex = threadIndices[threadID];
113  auto it = lastThreadIndex.find(rng->id);
114  if ((it == lastThreadIndex.end() || it->second != threadIndex)
115  && (myDebugId == "" || rng->id == myDebugId)) {
116  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
117  }
118  lastThreadIndex[rng->id] = threadIndex;
119  stream << "rng " << rng->id << " call=" << rng->count << " thread=" << threadIndex << " val=" << res << "\n";
120  OutputDevice::getDevice(rng->id) << stream.str();
121 #else
122  stream << "rng " << rng->id << " call=" << rng->count << " val=" << res << "\n";
123  std::cout << stream.str();
124 #endif
125 #endif
126 #ifdef DEBUG_FLAG1
127  if (gDebugFlag1) {
128  std::stringstream stream; // to reduce output interleaving from different threads
129  stream << "rng " << rng->id << " call=" << rng->count << " val=" << res << "\n";
130  std::cout << stream.str();
131  }
132 #endif
133  return res;
134 }
135 
136 double
137 RandHelper::randNorm(double mean, double variance, SumoRNG* rng) {
138  // Polar method to avoid cosine
139  double u, q;
140  do {
141  u = rand(2.0, rng) - 1;
142  const double v = rand(2.0, rng) - 1;
143  q = u * u + v * v;
144  } while (q == 0.0 || q >= 1.0);
145  const double logRounded = ceil(log(q) * 1e14) / 1e14;
146  return mean + variance * u * sqrt(-2 * logRounded / q);
147 }
148 
149 double
150 RandHelper::randExp(double rate, SumoRNG* rng) {
151  return -log(rand(rng)) / rate;
152 }
153 
154 // template<class T>
155 // void RandHelper::shuffle(const std::vector<T>& v) {
156 // std::shuffle(v.begin(), v.end(), rng);
157 // }
158 
159 /****************************************************************************/
#define TL(string)
Definition: MsgHandler.h:315
bool gDebugFlag1
global utility flags for debugging
Definition: StdDefs.cpp:35
A storage for options typed value containers)
Definition: OptionsCont.h:89
void addDescription(const std::string &name, const std::string &subtopic, const std::string &description)
Adds a description for an option.
int getInt(const std::string &name) const
Returns the int-value of the named option (only for Option_Integer)
void addSynonyme(const std::string &name1, const std::string &name2, bool isDeprecated=false)
Adds a synonyme for an options name (any order)
void doRegister(const std::string &name, Option *o)
Adds an option under the given name.
Definition: OptionsCont.cpp:76
void addOptionSubTopic(const std::string &topic)
Adds an option subtopic.
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:60
static OutputDevice & getDevice(const std::string &name, bool usePrefix=true)
Returns the described OutputDevice.
static SumoRNG myRandomNumberGenerator
the default random number generator to use
Definition: RandHelper.h:248
static double randExp(double rate, SumoRNG *rng=nullptr)
Access to a random number from an exponential distribution.
Definition: RandHelper.cpp:150
static void initRand(SumoRNG *which=nullptr, const bool random=false, const int seed=23423)
Initialises the random number generator with hardware randomness or seed.
Definition: RandHelper.cpp:74
static double rand(SumoRNG *rng=nullptr)
Returns a random real number in [0, 1)
Definition: RandHelper.cpp:94
static double randNorm(double mean, double variance, SumoRNG *rng=nullptr)
Access to a random number from a normal distribution.
Definition: RandHelper.cpp:137
static void insertRandOptions(OptionsCont &oc)
Initialises the given options container with random number options.
Definition: RandHelper.cpp:59
static void initRandGlobal(SumoRNG *which=nullptr)
Reads the given random number options and initialises the random number generator in accordance.
Definition: RandHelper.cpp:87
std::string id
Definition: RandHelper.h:108
unsigned long long int count
Definition: RandHelper.h:107