Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
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-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/****************************************************************************/
20//
21/****************************************************************************/
22#pragma once
23#include <config.h>
24
25#include <cassert>
26#include <cstring>
27#include <vector>
28#include <map>
29#include <random>
30#include <sstream>
31#include <iostream>
32#include <algorithm>
33
34// TODO make this configurable
35#define SAVE_ONLY_COUNT 1000000
36
37// ===========================================================================
38// helper function
39// ===========================================================================
40
41#ifdef __clang__
42__attribute__((no_sanitize("unsigned-integer-overflow")))
43#endif
44inline uint64_t splitmix64(const uint64_t seed) {
45 uint64_t z = (seed + 0x9e3779b97f4a7c15);
46 z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
47 z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
48 return z ^ (z >> 31);
49}
50
51
52// ===========================================================================
53// class declaration
54// ===========================================================================
55
56class OptionsCont;
57
58// ===========================================================================
59// class definitions
60// ===========================================================================
66public:
67 inline void seed(const uint64_t seed) {
68 this->state[0] = splitmix64(splitmix64(seed));
69 this->state[1] = splitmix64(this->state[0]);
70 this->state[2] = splitmix64(this->state[1]);
71 this->state[3] = splitmix64(this->state[2]);
72 }
73
74 inline uint64_t operator()() {
75 const uint64_t result = rotl64(this->state[0] + this->state[3], 23) + this->state[0];
76 const uint64_t t = this->state[1] << 17;
77 this->state[2] ^= this->state[0];
78 this->state[3] ^= this->state[1];
79 this->state[1] ^= this->state[2];
80 this->state[0] ^= this->state[3];
81 this->state[2] ^= t;
82 this->state[3] = rotl64(this->state[3], 45);
83 return result;
84 }
85
86 void discard(unsigned long long skip) {
87 while (skip-- > 0) {
88 (*this)();
89 }
90 }
91
92 friend std::ostream& operator<<(std::ostream& os, const XoShiRo256PlusPlus& r) {
93 os << r.state[0] << r.state[1] << r.state[2] << r.state[3];
94 return os;
95 }
96
97 friend std::istream& operator>>(std::istream& is, XoShiRo256PlusPlus& r) {
98 is >> r.state[0] >> r.state[1] >> r.state[2] >> r.state[3];
99 return is;
100 }
101
102
103private:
104 static inline uint64_t rotl64(const uint64_t x, const int k) {
105 return (x << k) | (x >> (64 - k));
106 }
107
108 uint64_t state[4];
109
110};
111
112
113//class SumoRNG : public XoShiRo256PlusPlus {
114class SumoRNG : public std::mt19937 {
115public:
116 SumoRNG(const std::string& _id) : id(_id) {}
117
118 void setSeed(int _seed) {
119 origSeed = _seed;
120 seed(_seed);
121 }
122
123 unsigned long long int count = 0;
124 int origSeed = default_seed;
125 std::string id;
126};
127
128
134
135public:
137 static void insertRandOptions(OptionsCont& oc);
138
140 static void initRand(SumoRNG* which = nullptr, const bool random = false, const int seed = 23423);
141
143 static void initRandGlobal(SumoRNG* which = nullptr);
144
145 static int getSeed(SumoRNG* which = nullptr);
146
148 static double rand(SumoRNG* rng = nullptr);
149
151 static inline double rand(double maxV, SumoRNG* rng = nullptr) {
152 return maxV * rand(rng);
153 }
154
156 static inline double rand(double minV, double maxV, SumoRNG* rng = nullptr) {
157 return minV + (maxV - minV) * rand(rng);
158 }
159
161 static inline int rand(int maxV, SumoRNG* rng = nullptr) {
162 if (rng == nullptr) {
164 }
165 unsigned int usedBits = maxV - 1;
166 usedBits |= usedBits >> 1;
167 usedBits |= usedBits >> 2;
168 usedBits |= usedBits >> 4;
169 usedBits |= usedBits >> 8;
170 usedBits |= usedBits >> 16;
171
172 // Draw numbers until one is found in [0, maxV-1]
173 int result;
174 do {
175 result = (*rng)() & usedBits;
176 rng->count++;
177 } while (result >= maxV);
178 return result;
179 }
180
182 static inline int rand(int minV, int maxV, SumoRNG* rng = nullptr) {
183 return minV + rand(maxV - minV, rng);
184 }
185
187 static inline long long int rand(long long int maxV, SumoRNG* rng = nullptr) {
188 if (maxV <= std::numeric_limits<int>::max()) {
189 return rand((int)maxV, rng);
190 }
191 if (rng == nullptr) {
193 }
194 unsigned long long int usedBits = maxV - 1;
195 usedBits |= usedBits >> 1;
196 usedBits |= usedBits >> 2;
197 usedBits |= usedBits >> 4;
198 usedBits |= usedBits >> 8;
199 usedBits |= usedBits >> 16;
200 usedBits |= usedBits >> 32;
201
202 // Draw numbers until one is found in [0, maxV-1]
203 long long int result;
204 do {
205 result = (((unsigned long long int)(*rng)() << 32) | (*rng)()) & usedBits; // toss unused bits to shorten search
206 rng->count += 2;
207 } while (result >= maxV);
208 return result;
209 }
210
212 static inline long long int rand(long long int minV, long long int maxV, SumoRNG* rng = nullptr) {
213 return minV + rand(maxV - minV, rng);
214 }
215
217 static double randNorm(double mean, double variance, SumoRNG* rng = nullptr);
218
220 static double randExp(double rate, SumoRNG* rng = nullptr);
221
223 template<class T>
224 static inline const T&
225 getRandomFrom(const std::vector<T>& v, SumoRNG* rng = nullptr) {
226 assert(v.size() > 0);
227 return v[rand((int)v.size(), rng)];
228 }
229
231 static std::string saveState(SumoRNG* rng = nullptr) {
232 if (rng == nullptr) {
234 }
235 std::ostringstream oss;
236 oss << rng->count;
237 if (rng->count >= SAVE_ONLY_COUNT) {
238 oss << " " << (*rng);
239 }
240 return oss.str();
241 }
242
244 static void loadState(const std::string& state, SumoRNG* rng = nullptr) {
245 if (rng == nullptr) {
247 }
248 std::istringstream iss(state);
249 iss >> rng->count;
250 if (rng->count < SAVE_ONLY_COUNT) {
251 rng->discard(rng->count);
252 } else {
253 iss >> (*rng);
254 }
255 }
256
257 template<class T>
258 static void shuffle(std::vector<T>& v, SumoRNG* rng = nullptr) {
259 for (int i = (int)(v.size() - 1); i > 0; --i) {
260 std::swap(*(v.begin() + i), *(v.begin() + rand(i, rng)));
261 }
262 }
263
264 static long long int count() {
266 }
267
269 static double randHash(long long int x) {
270 const uint64_t h = splitmix64(x) >> 11;
271 return (double)h / (double(1ULL << 53));
272 }
273
275#ifdef __clang__
276 __attribute__((no_sanitize("integer"))) // left-shift and unsigned-integer-overflow
277#endif
278 static uint32_t murmur3_32(const std::string& key2, int seed) {
279 const uint8_t* key = reinterpret_cast<const uint8_t*>(key2.data());
280 const size_t len = key2.size();
281 uint32_t h = seed;
282 uint32_t k;
283 /* Read in groups of 4. */
284 for (size_t i = len >> 2; i; i--) {
285 memcpy(&k, key, sizeof(uint32_t));
286 key += sizeof(uint32_t);
287 h ^= murmur_32_scramble(k);
288 h = (h << 13) | (h >> 19);
289 h = h * 5 + 0xe6546b64;
290 }
291 /* Read the rest. */
292 k = 0;
293 for (size_t i = len & 3; i; i--) {
294 k <<= 8;
295 k |= key[i - 1];
296 }
297 h ^= murmur_32_scramble(k);
298 /* Finalize. */
299 h ^= len;
300 h ^= h >> 16;
301 h *= 0x85ebca6b;
302 h ^= h >> 13;
303 h *= 0xc2b2ae35;
304 h ^= h >> 16;
305 return h;
306 }
307
308
309protected:
312
314#ifdef __clang__
315 __attribute__((no_sanitize("integer"))) // left-shift and unsigned-integer-overflow
316#endif
317 static inline uint32_t murmur_32_scramble(uint32_t k) {
318 k *= 0xcc9e2d51;
319 k = (k << 15) | (k >> 17);
320 k *= 0x1b873593;
321 return k;
322 }
323
324};
uint64_t splitmix64(const uint64_t seed)
Definition RandHelper.h:44
#define SAVE_ONLY_COUNT
Definition RandHelper.h:35
A storage for options typed value containers)
Definition OptionsCont.h:89
Utility functions for using a global, resetable random number generator.
Definition RandHelper.h:133
static SumoRNG myRandomNumberGenerator
the default random number generator to use
Definition RandHelper.h:311
static void loadState(const std::string &state, SumoRNG *rng=nullptr)
load rng state from string
Definition RandHelper.h:244
static double randExp(double rate, SumoRNG *rng=nullptr)
Access to a random number from an exponential distribution.
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:212
static double randHash(long long int x)
return a value scrambled value from [0, 1]
Definition RandHelper.h:269
static double rand(double minV, double maxV, SumoRNG *rng=nullptr)
Returns a random real number in [minV, maxV)
Definition RandHelper.h:156
static void initRand(SumoRNG *which=nullptr, const bool random=false, const int seed=23423)
Initialises the random number generator with hardware randomness or seed.
static uint32_t murmur3_32(const std::string &key2, int seed)
string hashing adapted from https://en.wikipedia.org/wiki/MurmurHash
Definition RandHelper.h:278
static int rand(int minV, int maxV, SumoRNG *rng=nullptr)
Returns a random integer in [minV, maxV-1].
Definition RandHelper.h:182
static int getSeed(SumoRNG *which=nullptr)
static double rand(SumoRNG *rng=nullptr)
Returns a random real number in [0, 1)
static int rand(int maxV, SumoRNG *rng=nullptr)
Returns a random integer in [0, maxV-1].
Definition RandHelper.h:161
static double randNorm(double mean, double variance, SumoRNG *rng=nullptr)
Access to a random number from a normal distribution.
static long long int count()
Definition RandHelper.h:264
static std::string saveState(SumoRNG *rng=nullptr)
save rng state to string
Definition RandHelper.h:231
static uint32_t murmur_32_scramble(uint32_t k)
helper function for murmur_32_scramble from https://en.wikipedia.org/wiki/MurmurHash
Definition RandHelper.h:317
static double rand(double maxV, SumoRNG *rng=nullptr)
Returns a random real number in [0, maxV)
Definition RandHelper.h:151
static void insertRandOptions(OptionsCont &oc)
Initialises the given options container with random number options.
static const T & getRandomFrom(const std::vector< T > &v, SumoRNG *rng=nullptr)
Returns a random element from the given vector.
Definition RandHelper.h:225
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:187
static void shuffle(std::vector< T > &v, SumoRNG *rng=nullptr)
Definition RandHelper.h:258
static void initRandGlobal(SumoRNG *which=nullptr)
Reads the given random number options and initialises the random number generator in accordance.
std::string id
Definition RandHelper.h:125
int origSeed
Definition RandHelper.h:124
SumoRNG(const std::string &_id)
Definition RandHelper.h:116
unsigned long long int count
Definition RandHelper.h:123
void setSeed(int _seed)
Definition RandHelper.h:118
A random number generator as proposed here https://prng.di.unimi.it/xoshiro256plusplus....
Definition RandHelper.h:65
uint64_t operator()()
Definition RandHelper.h:74
uint64_t state[4]
Definition RandHelper.h:108
friend std::ostream & operator<<(std::ostream &os, const XoShiRo256PlusPlus &r)
Definition RandHelper.h:92
friend std::istream & operator>>(std::istream &is, XoShiRo256PlusPlus &r)
Definition RandHelper.h:97
void discard(unsigned long long skip)
Definition RandHelper.h:86
static uint64_t rotl64(const uint64_t x, const int k)
Definition RandHelper.h:104
void seed(const uint64_t seed)
Definition RandHelper.h:67
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