EvolvingObjects
|
00001 00025 #ifndef EO_RANDOM_NUMBER_GENERATOR 00026 #define EO_RANDOM_NUMBER_GENERATOR 00027 00032 # if (defined _MSC_VER) 00033 00040 typedef unsigned long uint32_t; 00041 #else 00042 #if (! defined __sun) 00043 // The C99-standard defines uint32_t to be declared in stdint.h, but some 00044 // systems don't have that and implement it in inttypes.h. 00045 #include <stdint.h> 00046 #else 00047 #include <inttypes.h> 00048 #endif 00049 #endif 00050 00051 #include <cmath> 00052 #include <vector> 00053 #include "eoPersistent.h" 00054 #include "eoObject.h" 00055 00056 00115 class eoRng : public eoObject, public eoPersistent 00116 { 00117 public : 00118 00125 eoRng(uint32_t s) 00126 : state(0), next(0), left(-1), cached(false) 00127 { 00128 state = new uint32_t[N+1]; 00129 initialize(2*s); 00130 } 00131 00133 ~eoRng() 00134 { 00135 delete [] state; 00136 } 00137 00148 void reseed(uint32_t s) 00149 { 00150 initialize(2*s); 00151 } 00152 00153 /* FIXME remove in next release 00154 ** Re-initializes the Random Number Generator 00155 00156 This is the traditional seeding procedure. This version is deprecated and 00157 only provided for compatibility with old code. In new projects you should 00158 use reseed. 00159 00160 @see reseed for details on usage of the seeding value. 00161 00162 @version old version (deprecated) 00163 * 00164 void oldReseed(uint32_t s) 00165 { 00166 initialize(s); 00167 } 00168 */ 00169 00175 double uniform(double m = 1.0) 00176 { // random number between [0, m] 00177 return m * double(rand()) / double(1.0 + rand_max()); 00178 } 00179 00186 double uniform(double min, double max) 00187 { // random number between [min, max] 00188 return min + uniform(max - min); 00189 } 00190 00196 uint32_t random(uint32_t m) 00197 { 00198 // C++ Standard (4.9 Floatingintegral conversions [conv.fpint]) 00199 // defines floating point to integer conversion as truncation 00200 // ("rounding towards zero"): "An rvalue of a floating point type 00201 // can be converted to an rvalue of an integer type. The conversion 00202 // truncates; that is, the fractional part is discarded" 00203 return uint32_t(uniform() * double(m)); 00204 } 00205 00213 bool flip(double bias=0.5) 00214 { 00215 return uniform() < bias; 00216 } 00217 00225 double normal(); 00226 00234 double normal(double stdev) 00235 { return stdev * normal(); } 00236 00245 double normal(double mean, double stdev) 00246 { return mean + normal(stdev); } 00247 00253 double negexp(double mean) 00254 { 00255 return -mean*log(double(rand()) / rand_max()); 00256 } 00257 00261 uint32_t rand(); 00262 00266 uint32_t rand_max() const { return uint32_t(0xffffffff); } 00267 00274 template <typename TYPE> 00275 int roulette_wheel(const std::vector<TYPE>& vec, TYPE total = 0) 00276 { 00277 if (total == 0) 00278 { // count 00279 for (unsigned i = 0; i < vec.size(); ++i) 00280 total += vec[i]; 00281 } 00282 double fortune = uniform() * total; 00283 int i = 0; 00284 while (fortune >= 0) 00285 { 00286 fortune -= vec[i++]; 00287 } 00288 return --i; 00289 } 00290 00291 00296 template <typename TYPE> 00297 const TYPE& choice(const std::vector<TYPE>& vec) 00298 { return vec[random(vec.size())]; } 00299 00300 00311 template <typename TYPE> 00312 TYPE& choice(std::vector<TYPE>& vec) 00313 { return vec[random(vec.size())]; } 00314 00319 void printOn(std::ostream& _os) const 00320 { 00321 for (int i = 0; i < N; ++i) 00322 { 00323 _os << state[i] << ' '; 00324 } 00325 _os << int(next - state) << ' '; 00326 _os << left << ' ' << cached << ' ' << cacheValue; 00327 } 00328 00333 void readFrom(std::istream& _is) 00334 { 00335 for (int i = 0; i < N; ++i) 00336 { 00337 _is >> state[i]; 00338 } 00339 00340 int n; 00341 _is >> n; 00342 next = state + n; 00343 00344 _is >> left; 00345 _is >> cached; 00346 _is >> cacheValue; 00347 } 00348 00349 std::string className() const { return "Mersenne-Twister"; } 00350 00351 private: 00352 00353 uint32_t restart(); 00354 00355 /* @brief Initialize state 00356 00357 We initialize state[0..(N-1)] via the generator 00358 00359 <tt>x_new = (69069 * x_old) mod 2^32</tt> 00360 00361 from Line 15 of Table 1, p. 106, Sec. 3.3.4 of Knuth's _The Art of Computer 00362 Programming_, Volume 2, 3rd ed. 00363 00364 Notes (SJC): I do not know what the initial state requirements of the 00365 Mersenne Twister are, but it seems this seeding generator could be better. 00366 It achieves the maximum period for its modulus (2^30) iff x_initial is odd 00367 (p. 20-21, Sec. 3.2.1.2, Knuth); if x_initial can be even, you have 00368 sequences like 0, 0, 0, ...; 2^31, 2^31, 2^31, ...; 2^30, 2^30, 2^30, ...; 00369 2^29, 2^29 + 2^31, 2^29, 2^29 + 2^31, ..., etc. so I force seed to be odd 00370 below. 00371 00372 Even if x_initial is odd, if x_initial is 1 mod 4 then 00373 00374 the lowest bit of x is always 1, 00375 the next-to-lowest bit of x is always 0, 00376 the 2nd-from-lowest bit of x alternates ... 0 1 0 1 0 1 0 1 ... , 00377 the 3rd-from-lowest bit of x 4-cycles ... 0 1 1 0 0 1 1 0 ... , 00378 the 4th-from-lowest bit of x has the 8-cycle ... 0 0 0 1 1 1 1 0 ... , 00379 ... 00380 00381 and if x_initial is 3 mod 4 then 00382 00383 the lowest bit of x is always 1, 00384 the next-to-lowest bit of x is always 1, 00385 the 2nd-from-lowest bit of x alternates ... 0 1 0 1 0 1 0 1 ... , 00386 the 3rd-from-lowest bit of x 4-cycles ... 0 0 1 1 0 0 1 1 ... , 00387 the 4th-from-lowest bit of x has the 8-cycle ... 0 0 1 1 1 1 0 0 ... , 00388 ... 00389 00390 The generator's potency (min. s>=0 with (69069-1)^s = 0 mod 2^32) is 16, 00391 which seems to be alright by p. 25, Sec. 3.2.1.3 of Knuth. It also does well 00392 in the dimension 2..5 spectral tests, but it could be better in dimension 6 00393 (Line 15, Table 1, p. 106, Sec. 3.3.4, Knuth). 00394 00395 Note that the random number user does not see the values generated here 00396 directly since restart() will always munge them first, so maybe none of all 00397 of this matters. In fact, the seed values made here could even be 00398 extra-special desirable if the Mersenne Twister theory says so-- that's why 00399 the only change I made is to restrict to odd seeds. 00400 */ 00401 void initialize(uint32_t seed); 00402 00404 uint32_t *state; 00405 00407 uint32_t *next; 00408 00410 int left; 00411 00413 bool cached; 00414 00416 double cacheValue; 00417 00419 static const int N; 00420 00422 static const int M; 00423 00425 static const uint32_t K; 00426 00427 00436 eoRng(const eoRng&); 00437 00442 eoRng& operator=(const eoRng&); 00443 }; 00449 namespace eo 00450 { 00452 extern eoRng rng; 00453 } 00454 using eo::rng; 00455 00461 // Implementation of some eoRng members.... Don't mind the mess, it does work. 00462 00463 #define hiBit(u) ((u) & 0x80000000U) // mask all but highest bit of u 00464 #define loBit(u) ((u) & 0x00000001U) // mask all but lowest bit of u 00465 #define loBits(u) ((u) & 0x7FFFFFFFU) // mask the highest bit of u 00466 #define mixBits(u, v) (hiBit(u)|loBits(v)) // move hi bit of u to hi bit of v 00467 00468 00469 inline void eoRng::initialize(uint32_t seed) 00470 { 00471 left = -1; 00472 00473 register uint32_t x = (seed | 1U) & 0xFFFFFFFFU, *s = state; 00474 register int j; 00475 00476 for(left=0, *s++=x, j=N; --j; 00477 *s++ = (x*=69069U) & 0xFFFFFFFFU) ; 00478 } 00479 00480 00481 00482 inline uint32_t eoRng::restart() 00483 { 00484 register uint32_t *p0=state, *p2=state+2, *pM=state+M, s0, s1; 00485 register int j; 00486 00487 left=N-1, next=state+1; 00488 00489 for(s0=state[0], s1=state[1], j=N-M+1; --j; s0=s1, s1=*p2++) 00490 *p0++ = *pM++ ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U); 00491 00492 for(pM=state, j=M; --j; s0=s1, s1=*p2++) 00493 *p0++ = *pM++ ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U); 00494 00495 s1=state[0], *p0 = *pM ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U); 00496 s1 ^= (s1 >> 11); 00497 s1 ^= (s1 << 7) & 0x9D2C5680U; 00498 s1 ^= (s1 << 15) & 0xEFC60000U; 00499 return(s1 ^ (s1 >> 18)); 00500 } 00501 00502 00503 00504 inline uint32_t eoRng::rand() 00505 { 00506 if(--left < 0) 00507 return(restart()); 00508 uint32_t y = *next++; 00509 y ^= (y >> 11); 00510 y ^= (y << 7) & 0x9D2C5680U; 00511 y ^= (y << 15) & 0xEFC60000U; 00512 return(y ^ (y >> 18)); 00513 } 00514 00515 00516 00517 inline double eoRng::normal() 00518 { 00519 if (cached) { 00520 cached = false; 00521 return cacheValue; 00522 } 00523 double rSquare, var1, var2; 00524 do { 00525 var1 = 2.0 * uniform() - 1.0; 00526 var2 = 2.0 * uniform() - 1.0; 00527 rSquare = var1 * var1 + var2 * var2; 00528 } while (rSquare >= 1.0 || rSquare == 0.0); 00529 double factor = sqrt(-2.0 * log(rSquare) / rSquare); 00530 cacheValue = var1 * factor; 00531 cached = true; 00532 return (var2 * factor); 00533 } 00534 00535 00536 00537 namespace eo 00538 { 00555 template <typename T> 00556 inline T random(const T& min, const T& max) { 00557 return static_cast<T>(rng.uniform() * (max-min)) + min; } 00558 00576 template <typename T> 00577 inline T random(const T& max) { 00578 return static_cast<T>(rng.uniform() * max); } 00579 00587 inline double normal() { return rng.normal(); } 00588 } 00589 00590 00591 #endif 00592 00593 00594 // Local Variables: 00595 // coding: iso-8859-1 00596 // mode: C++ 00597 // c-file-offsets: ((c . 0)) 00598 // c-file-style: "Stroustrup" 00599 // fill-column: 80 00600 // End: