Eclipse SUMO - Simulation of Urban MObility
RandHelper.h
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 // Copyright (C) 2005-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 /****************************************************************************/
20 //
21 /****************************************************************************/
22 #pragma once
23 #include <config.h>
24 
25 #include <cassert>
26 #include <vector>
27 #include <map>
28 #include <random>
29 #include <sstream>
30 #include <iostream>
31 #include <algorithm>
32 
33 
34 // ===========================================================================
35 // class declaration
36 // ===========================================================================
37 
38 class OptionsCont;
39 
40 // ===========================================================================
41 // class definitions
42 // ===========================================================================
48 public:
49  inline void seed(const uint64_t seed) {
50  this->state[0] = splitmix64(splitmix64(seed));
51  this->state[1] = splitmix64(this->state[0]);
52  this->state[2] = splitmix64(this->state[1]);
53  this->state[3] = splitmix64(this->state[2]);
54  }
55 
56  inline uint64_t operator()() {
57  const uint64_t result = rotl64(this->state[0] + this->state[3], 23) + this->state[0];
58  const uint64_t t = this->state[1] << 17;
59  this->state[2] ^= this->state[0];
60  this->state[3] ^= this->state[1];
61  this->state[1] ^= this->state[2];
62  this->state[0] ^= this->state[3];
63  this->state[2] ^= t;
64  this->state[3] = rotl64(this->state[3], 45);
65  return result;
66  }
67 
68  void discard(unsigned long long skip) {
69  while (skip-- > 0) {
70  (*this)();
71  }
72  }
73 
74  friend std::ostream& operator<<(std::ostream& os, const XoShiRo256PlusPlus& r) {
75  os << r.state[0] << r.state[1] << r.state[2] << r.state[3];
76  return os;
77  }
78 
79  friend std::istream& operator>>(std::istream& is, XoShiRo256PlusPlus& r) {
80  is >> r.state[0] >> r.state[1] >> r.state[2] >> r.state[3];
81  return is;
82  }
83 
84 
85 private:
86  static inline uint64_t rotl64(const uint64_t x, const int k) {
87  return (x << k) | (x >> (64 - k));
88  }
89 
90  static inline uint64_t splitmix64(const uint64_t seed) {
91  uint64_t z = (seed + 0x9e3779b97f4a7c15);
92  z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
93  z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
94  return z ^ (z >> 31);
95  }
96 
97  uint64_t state[4];
98 
99 };
100 
101 
102 //class SumoRNG : public XoShiRo256PlusPlus {
103 class SumoRNG : public std::mt19937 {
104 public:
105  SumoRNG(const std::string& _id) : id(_id) {}
106 
107  unsigned long long int count = 0;
108  std::string id;
109 };
110 
111 
116 class RandHelper {
117 
118 public:
120  static void insertRandOptions(OptionsCont& oc);
121 
123  static void initRand(SumoRNG* which = nullptr, const bool random = false, const int seed = 23423);
124 
126  static void initRandGlobal(SumoRNG* which = nullptr);
127 
129  static double rand(SumoRNG* rng = nullptr);
130 
132  static inline double rand(double maxV, SumoRNG* rng = nullptr) {
133  return maxV * rand(rng);
134  }
135 
137  static inline double rand(double minV, double maxV, SumoRNG* rng = nullptr) {
138  return minV + (maxV - minV) * rand(rng);
139  }
140 
142  static inline int rand(int maxV, SumoRNG* rng = nullptr) {
143  if (rng == nullptr) {
145  }
146  unsigned int usedBits = maxV - 1;
147  usedBits |= usedBits >> 1;
148  usedBits |= usedBits >> 2;
149  usedBits |= usedBits >> 4;
150  usedBits |= usedBits >> 8;
151  usedBits |= usedBits >> 16;
152 
153  // Draw numbers until one is found in [0, maxV-1]
154  int result;
155  do {
156  result = (*rng)() & usedBits;
157  rng->count++;
158  } while (result >= maxV);
159  return result;
160  }
161 
163  static inline int rand(int minV, int maxV, SumoRNG* rng = nullptr) {
164  return minV + rand(maxV - minV, rng);
165  }
166 
168  static inline long long int rand(long long int maxV, SumoRNG* rng = nullptr) {
169  if (maxV <= std::numeric_limits<int>::max()) {
170  return rand((int)maxV, rng);
171  }
172  if (rng == nullptr) {
174  }
175  unsigned long long int usedBits = maxV - 1;
176  usedBits |= usedBits >> 1;
177  usedBits |= usedBits >> 2;
178  usedBits |= usedBits >> 4;
179  usedBits |= usedBits >> 8;
180  usedBits |= usedBits >> 16;
181  usedBits |= usedBits >> 32;
182 
183  // Draw numbers until one is found in [0, maxV-1]
184  long long int result;
185  do {
186  result = (((unsigned long long int)(*rng)() << 32) | (*rng)()) & usedBits; // toss unused bits to shorten search
187  rng->count += 2;
188  } while (result >= maxV);
189  return result;
190  }
191 
193  static inline long long int rand(long long int minV, long long int maxV, SumoRNG* rng = nullptr) {
194  return minV + rand(maxV - minV, rng);
195  }
196 
198  static double randNorm(double mean, double variance, SumoRNG* rng = nullptr);
199 
201  static double randExp(double rate, SumoRNG* rng = nullptr);
202 
204  template<class T>
205  static inline const T&
206  getRandomFrom(const std::vector<T>& v, SumoRNG* rng = nullptr) {
207  assert(v.size() > 0);
208  return v[rand((int)v.size(), rng)];
209  }
210 
212  static std::string saveState(SumoRNG* rng = nullptr) {
213  if (rng == nullptr) {
215  }
216  std::ostringstream oss;
217  if (rng->count < 1000000) { // TODO make this configurable
218  oss << rng->count;
219  } else {
220  oss << (*rng);
221  }
222  return oss.str();
223  }
224 
226  static void loadState(const std::string& state, SumoRNG* rng = nullptr) {
227  if (rng == nullptr) {
229  }
230  std::istringstream iss(state);
231  if (state.size() < 10) {
232  iss >> rng->count;
233  rng->discard(rng->count);
234  } else {
235  iss >> (*rng);
236  }
237  }
238 
239  template<class T>
240  static void shuffle(std::vector<T>& v, SumoRNG* rng = nullptr) {
241  for (int i = (int)(v.size() - 1); i > 0; --i) {
242  std::swap(*(v.begin() + i), *(v.begin() + rand(i, rng)));
243  }
244  }
245 
246 protected:
249 
250 };
A storage for options typed value containers)
Definition: OptionsCont.h:89
Utility functions for using a global, resetable random number generator.
Definition: RandHelper.h:116
static SumoRNG myRandomNumberGenerator
the default random number generator to use
Definition: RandHelper.h:248
static void loadState(const std::string &state, SumoRNG *rng=nullptr)
load rng state from string
Definition: RandHelper.h:226
static double randExp(double rate, SumoRNG *rng=nullptr)
Access to a random number from an exponential distribution.
Definition: RandHelper.cpp:150
static const T & getRandomFrom(const std::vector< T > &v, SumoRNG *rng=nullptr)
Returns a random element from the given vector.
Definition: RandHelper.h:206
static long long int rand(long long int minV, long long int maxV, SumoRNG *rng=nullptr)
Returns a random 64 bit integer in [minV, maxV-1].
Definition: RandHelper.h:193
static double rand(double minV, double maxV, SumoRNG *rng=nullptr)
Returns a random real number in [minV, maxV)
Definition: RandHelper.h:137
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 int rand(int minV, int maxV, SumoRNG *rng=nullptr)
Returns a random integer in [minV, maxV-1].
Definition: RandHelper.h:163
static double rand(SumoRNG *rng=nullptr)
Returns a random real number in [0, 1)
Definition: RandHelper.cpp:94
static int rand(int maxV, SumoRNG *rng=nullptr)
Returns a random integer in [0, maxV-1].
Definition: RandHelper.h:142
static double randNorm(double mean, double variance, SumoRNG *rng=nullptr)
Access to a random number from a normal distribution.
Definition: RandHelper.cpp:137
static std::string saveState(SumoRNG *rng=nullptr)
save rng state to string
Definition: RandHelper.h:212
static double rand(double maxV, SumoRNG *rng=nullptr)
Returns a random real number in [0, maxV)
Definition: RandHelper.h:132
static void insertRandOptions(OptionsCont &oc)
Initialises the given options container with random number options.
Definition: RandHelper.cpp:59
static long long int rand(long long int maxV, SumoRNG *rng=nullptr)
Returns a random 64 bit integer in [0, maxV-1].
Definition: RandHelper.h:168
static void shuffle(std::vector< T > &v, SumoRNG *rng=nullptr)
Definition: RandHelper.h:240
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
SumoRNG(const std::string &_id)
Definition: RandHelper.h:105
unsigned long long int count
Definition: RandHelper.h:107
A random number generator as proposed here https://prng.di.unimi.it/xoshiro256plusplus....
Definition: RandHelper.h:47
uint64_t operator()()
Definition: RandHelper.h:56
uint64_t state[4]
Definition: RandHelper.h:97
friend std::ostream & operator<<(std::ostream &os, const XoShiRo256PlusPlus &r)
Definition: RandHelper.h:74
friend std::istream & operator>>(std::istream &is, XoShiRo256PlusPlus &r)
Definition: RandHelper.h:79
void discard(unsigned long long skip)
Definition: RandHelper.h:68
static uint64_t rotl64(const uint64_t x, const int k)
Definition: RandHelper.h:86
void seed(const uint64_t seed)
Definition: RandHelper.h:49
static uint64_t splitmix64(const uint64_t seed)
Definition: RandHelper.h:90
NLOHMANN_BASIC_JSON_TPL_DECLARATION void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL &j1, nlohmann::NLOHMANN_BASIC_JSON_TPL &j2) noexcept(//NOLINT(readability-inconsistent-declaration-parameter-name) is_nothrow_move_constructible< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value &&//NOLINT(misc-redundant-expression) is_nothrow_move_assignable< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value)
exchanges the values of two JSON objects
Definition: json.hpp:21884