ARGoS 3
A parallel, multi-engine simulator for swarm robotics
rng.cpp
Go to the documentation of this file.
1
9#include "rng.h"
10#include <argos3/core/utility/configuration/argos_exception.h>
11#include <argos3/core/utility/logging/argos_log.h>
12#include <cstring>
13#include <limits>
14#include <cmath>
15
16namespace argos {
17
18 /****************************************/
19 /****************************************/
20
21 /* Period parameters */
22 static const SInt32 N = 624;
23 static const SInt32 M = 397;
24 static const UInt32 MATRIX_A = 0x9908b0dfUL; /* constant vector a */
25 static const UInt32 UPPER_MASK = 0x80000000UL; /* most significant w-r bits */
26 static const UInt32 LOWER_MASK = 0x7fffffffUL; /* least significant r bits */
27 static const CRange<UInt32> INT_RANGE = CRange<UInt32>(0, 0xFFFFFFFFUL);
28
29 std::map<std::string, CRandom::CCategory*> CRandom::m_mapCategories;
30
31 /* Checks that a category exists. It internally creates an iterator that points to the category, if found. */
32#define CHECK_CATEGORY(category) \
33 std::map<std::string, CCategory*>::iterator itCategory = m_mapCategories.find(category); \
34 if(itCategory == m_mapCategories.end()) { \
35 THROW_ARGOSEXCEPTION("CRandom:: can't find category \"" << category << "\"."); \
36 }
37
38 /****************************************/
39 /****************************************/
40
42 m_unSeed(un_seed),
43 m_punState(new UInt32[N]),
44 m_nIndex(N+1) {
45 Reset();
46 }
47
48 /****************************************/
49 /****************************************/
50
51 CRandom::CRNG::CRNG(const CRNG& c_rng) :
52 m_unSeed(c_rng.m_unSeed),
53 m_punState(new UInt32[N]),
54 m_nIndex(c_rng.m_nIndex) {
55 ::memcpy(m_punState, c_rng.m_punState, N * sizeof(UInt32));
56 }
57
58 /****************************************/
59 /****************************************/
60
62 delete[] m_punState;
63 }
64
65 /****************************************/
66 /****************************************/
67
69 m_punState[0]= m_unSeed & 0xffffffffUL;
70 for (m_nIndex = 1; m_nIndex < N; ++m_nIndex) {
71 m_punState[m_nIndex] =
72 (1812433253UL * (m_punState[m_nIndex-1] ^ (m_punState[m_nIndex-1] >> 30)) + m_nIndex);
73 m_punState[m_nIndex] &= 0xffffffffUL;
74 }
75 }
76
77 /****************************************/
78 /****************************************/
79
81 return Uniform32bit() < f_true * INT_RANGE.GetMax();
82 }
83
84 /****************************************/
85 /****************************************/
86
88 CRadians cRetVal;
89 INT_RANGE.MapValueIntoRange(cRetVal, Uniform32bit(), c_range);
90 return cRetVal;
91 }
92
93 /****************************************/
94 /****************************************/
95
97 Real fRetVal;
98 INT_RANGE.MapValueIntoRange(fRetVal, Uniform32bit(), c_range);
99 return fRetVal;
100 }
101
102 /****************************************/
103 /****************************************/
104
106 SInt32 nRetVal;
107 INT_RANGE.MapValueIntoRange(nRetVal, Uniform32bit(), c_range);
108 return nRetVal;
109 }
110
111 /****************************************/
112 /****************************************/
113
115 UInt32 unRetVal;
116 INT_RANGE.MapValueIntoRange(unRetVal, Uniform32bit(), c_range);
117 return unRetVal;
118 }
119
120 /****************************************/
121 /****************************************/
122
124 static CRange<Real> fRange(0.0f, 1.0f);
125 return -Log(Uniform(fRange)) * f_mean;
126 }
127
128 /****************************************/
129 /****************************************/
130
132 {
133 /* This is the Devroye method.
134 see http://www.nrbook.com/devroye/Devroye_files/chapter_six.pdf
135 */
136 UInt32 unRetVal = 0;
137 Real fP, fS, fU;
138 fP = Exp(-f_mean);
139 fS = fP;
140 fU = Uniform(CRange<Real>(0.0f, 1.0f));
141 while(fU > fS) {
142 unRetVal += 1;
143 fP *= f_mean / unRetVal;
144 fS += fP;
145 }
146 return unRetVal;
147 }
148
149 /****************************************/
150 /****************************************/
151
153 Real f_mean) {
154 /* This is the Box-Muller method in its cartesian variant
155 see http://www.dspguru.com/dsp/howtos/how-to-generate-white-gaussian-noise
156 */
157 static CRange<Real> fRange(-1.0f, 1.0f);
158 Real fNum1, fNum2;
159 Real fSquare;
160 do {
161 fNum1 = Uniform(fRange);
162 fNum2 = Uniform(fRange);
163 fSquare = fNum1 * fNum1 + fNum2 * fNum2;
164 } while(fSquare >= 1);
165 return f_mean + f_std_dev * fNum1 * Sqrt(-2.0f * Log(fSquare) / fSquare);
166 }
167
168 /****************************************/
169 /****************************************/
170
172 /* Draw a number uniformly from (0,1) --- bounds excluded */
173 static CRange<Real> cUnitRange(0.0f, 1.0f);
174 Real fValue;
175 do {
176 fValue = Uniform(cUnitRange);
177 }
178 while(! cUnitRange.WithinMinBoundExcludedMaxBoundExcluded(fValue));
179 /* Calculate the value to return from the definition of Rayleigh distribution
180 * http://en.wikipedia.org/wiki/Rayleigh_distribution#Generating_Rayleigh-distributed_random_variates
181 */
182 return f_sigma * Sqrt(-2.0f * Log(fValue));
183 }
184
185/****************************************/
186 /****************************************/
187
189 /* Draw a number uniformly from (0,1) */
190 Real fValue;
191 fValue = Gaussian(1,0);
192 /* Calculate the value to return from the definition of Lognormal distribution
193 * http://en.wikipedia.org/wiki/Log-normal_distribution#Generating_log-normally_distributed_random_variates
194 */
195 return std::exp(f_mu + f_sigma * fValue);
196 }
197
198 /****************************************/
199 /****************************************/
200
201 UInt32 CRandom::CRNG::Uniform32bit() {
202 UInt32 y;
203 static UInt32 mag01[2] = { 0x0UL, MATRIX_A };
204 /* mag01[x] = x * MATRIX_A for x=0,1 */
205
206 if (m_nIndex >= N) { /* generate N words at one time */
207 SInt32 kk;
208 for (kk = 0; kk < N - M; ++kk) {
209 y = (m_punState[kk] & UPPER_MASK) | (m_punState[kk+1] & LOWER_MASK);
210 m_punState[kk] = m_punState[kk+M] ^ (y >> 1) ^ mag01[y & 0x1UL];
211 }
212 for (; kk < N - 1; ++kk) {
213 y = (m_punState[kk] & UPPER_MASK) | (m_punState[kk+1] & LOWER_MASK);
214 m_punState[kk] = m_punState[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
215 }
216 y = (m_punState[N-1] & UPPER_MASK) | (m_punState[0] & LOWER_MASK);
217 m_punState[N-1] = m_punState[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL];
218
219 m_nIndex = 0;
220 }
221
222 y = m_punState[m_nIndex++];
223
224 /* Tempering */
225 y ^= (y >> 11);
226 y ^= (y << 7) & 0x9d2c5680UL;
227 y ^= (y << 15) & 0xefc60000UL;
228 y ^= (y >> 18);
229
230 return y;
231 }
232
233 /****************************************/
234 /****************************************/
235
236 CRandom::CCategory::CCategory(const std::string& str_id,
237 UInt32 un_seed) :
238 m_strId(str_id),
239 m_unSeed(un_seed),
240 m_cSeeder(un_seed),
241 m_cSeedRange(1, std::numeric_limits<UInt32>::max()) {}
242
243 /****************************************/
244 /****************************************/
245
247 while(! m_vecRNGList.empty()) {
248 delete m_vecRNGList.back();
249 m_vecRNGList.pop_back();
250 }
251 }
252
253 /****************************************/
254 /****************************************/
255
257 m_unSeed = un_seed;
258 m_cSeeder.SetSeed(m_unSeed);
259 }
260
261 /****************************************/
262 /****************************************/
263
265 /* Get seed from internal RNG */
266 UInt32 unSeed = m_cSeeder.Uniform(m_cSeedRange);
267 /* Create new RNG */
268 m_vecRNGList.push_back(new CRNG(unSeed));
269 return m_vecRNGList.back();
270 }
271
272 /****************************************/
273 /****************************************/
274
276 /* Reset internal RNG */
277 m_cSeeder.Reset();
278 ReseedRNGs();
279 /* Reset the RNGs */
280 for(size_t i = 0; i < m_vecRNGList.size(); ++i) {
281 m_vecRNGList[i]->Reset();
282 }
283 }
284
285 /****************************************/
286 /****************************************/
287
289 for(size_t i = 0; i < m_vecRNGList.size(); ++i) {
290 /* Get seed from internal RNG */
291 m_vecRNGList[i]->SetSeed(m_cSeeder.Uniform(m_cSeedRange));
292 }
293 }
294
295 /****************************************/
296 /****************************************/
297
298 bool CRandom::CreateCategory(const std::string& str_category,
299 UInt32 un_seed) {
300 /* Is there a category already? */
301 auto itCategory = m_mapCategories.find(str_category);
302 if(itCategory == m_mapCategories.end()) {
303 /* No, create it */
304 m_mapCategories.insert(
305 std::pair<std::string,
306 CRandom::CCategory*>(str_category,
307 new CRandom::CCategory(str_category,
308 un_seed)));
309 return true;
310 }
311 return false;
312 }
313
314 /****************************************/
315 /****************************************/
316
317 CRandom::CCategory& CRandom::GetCategory(const std::string& str_category) {
318 CHECK_CATEGORY(str_category);
319 return *(itCategory->second);
320 }
321
322 /****************************************/
323 /****************************************/
324
325 bool CRandom::ExistsCategory(const std::string& str_category) {
326 try {
327 CHECK_CATEGORY(str_category);
328 return true;
329 }
330 catch(CARGoSException& ex) {
331 return false;
332 }
333 }
334
335 /****************************************/
336 /****************************************/
337
338 void CRandom::RemoveCategory(const std::string& str_category) {
339 CHECK_CATEGORY(str_category);
340 delete itCategory->second;
341 m_mapCategories.erase(itCategory);
342 }
343
344 /****************************************/
345 /****************************************/
346
347 CRandom::CRNG* CRandom::CreateRNG(const std::string& str_category) {
348 CHECK_CATEGORY(str_category);
349 return itCategory->second->CreateRNG();
350 }
351
352 /****************************************/
353 /****************************************/
354
355 UInt32 CRandom::GetSeedOf(const std::string& str_category) {
356 CHECK_CATEGORY(str_category);
357 return itCategory->second->GetSeed();
358 }
359
360 /****************************************/
361 /****************************************/
362
363 void CRandom::SetSeedOf(const std::string& str_category,
364 UInt32 un_seed) {
365 CHECK_CATEGORY(str_category);
366 itCategory->second->SetSeed(un_seed);
367 }
368
369 /****************************************/
370 /****************************************/
371
373 for(auto itCategory = m_mapCategories.begin();
374 itCategory != m_mapCategories.end();
375 ++itCategory) {
376 itCategory->second->ResetRNGs();
377 }
378 }
379
380 /****************************************/
381 /****************************************/
382
383}
#define M(row, col)
#define CHECK_CATEGORY(category)
Definition rng.cpp:32
#define Exp
Definition general.h:65
#define Sqrt
Definition general.h:64
#define Log
Definition general.h:63
signed int SInt32
32-bit signed integer.
Definition datatypes.h:93
unsigned int UInt32
32-bit unsigned integer.
Definition datatypes.h:97
float Real
Collects all ARGoS code.
Definition datatypes.h:39
The namespace containing all the ARGoS related code.
Definition ci_actuator.h:12
For argos::CTCPSocket::EEvent to be used in std::unordered_set<> and std::unordered_map<>,...
Definition tcp_socket.h:191
The exception that wraps all errors in ARGoS.
It defines the basic type CRadians, used to store an angle value in radians.
Definition angles.h:42
bool WithinMinBoundExcludedMaxBoundExcluded(const T &t_value) const
Definition range.h:93
T GetMax() const
Definition range.h:48
void MapValueIntoRange(U &t_output_value, const T &t_input_value, const CRange< U > &c_range) const
Definition range.h:109
static UInt32 GetSeedOf(const std::string &str_category)
Returns the seed of the wanted category.
Definition rng.cpp:355
static void Reset()
Resets all the RNG categories.
Definition rng.cpp:372
static CRNG * CreateRNG(const std::string &str_category)
Creates a new RNG inside the given category.
Definition rng.cpp:347
static void RemoveCategory(const std::string &str_category)
Removes the wanted category.
Definition rng.cpp:338
static void SetSeedOf(const std::string &str_category, UInt32 un_seed)
Sets the new seed of the wanted category.
Definition rng.cpp:363
static bool CreateCategory(const std::string &str_category, UInt32 un_seed)
Creates a new category.
Definition rng.cpp:298
static CCategory & GetCategory(const std::string &str_category)
Returns a reference to the wanted category.
Definition rng.cpp:317
static bool ExistsCategory(const std::string &str_category)
Returns true if the given category exists in the pool.
Definition rng.cpp:325
The RNG.
Definition rng.h:90
UInt32 Poisson(Real f_mean)
Returns a random value from a Poisson distribution.
Definition rng.cpp:131
virtual ~CRNG()
Class destructor.
Definition rng.cpp:61
bool Bernoulli(Real f_true=0.5)
Returns a random value from a Bernoulli distribution.
Definition rng.cpp:80
CRNG(UInt32 un_seed)
Class constructor.
Definition rng.cpp:41
void Reset()
Reset the RNG.
Definition rng.cpp:68
Real Lognormal(Real f_sigma, Real f_mu)
Returns a random value from a Lognormal distribution.
Definition rng.cpp:188
Real Rayleigh(Real f_sigma)
Returns a random value from a Rayleigh distribution.
Definition rng.cpp:171
Real Exponential(Real f_mean)
Returns a random value from an exponential distribution.
Definition rng.cpp:123
Real Gaussian(Real f_std_dev, Real f_mean=0.0f)
Returns a random value from a Gaussian distribution.
Definition rng.cpp:152
CRadians Uniform(const CRange< CRadians > &c_range)
Returns a random value from a uniform distribution.
Definition rng.cpp:87
The RNG category.
Definition rng.h:244
void ResetRNGs()
Resets the RNGs in this category.
Definition rng.cpp:275
CCategory(const std::string &str_id, UInt32 un_seed)
Class constructor.
Definition rng.cpp:236
CRNG * CreateRNG()
Creates a new RNG inside this category.
Definition rng.cpp:264
virtual ~CCategory()
Class destructor.
Definition rng.cpp:246
void SetSeed(UInt32 un_seed)
Sets the new seed of the category.
Definition rng.cpp:256
void ReseedRNGs()
Sets new seed for the RNGs in this category.
Definition rng.cpp:288