eoRNG.h

00001 
00024 #ifndef EO_RANDOM_NUMBER_GENERATOR
00025 #define EO_RANDOM_NUMBER_GENERATOR
00026 
00027 // uint32_t is an unsigned integer type capable of holding 32 bits.
00028 //
00029 // In the applicatione here exactly 32 but should typically be fastest, but 64
00030 // might be better on an Alpha with GCC at -O3 optimization so try your options
00031 // and see what's best for you.
00032 //
00033 // The C99-standard defines uint32_t to be declared in stdint.h, but some
00034 // systmes don't have that and implement it in inttypes.h.
00035 #if (! defined __sun)
00036 #include <stdint.h>
00037 #else
00038 #include <inttypes.h>
00039 #endif
00040 
00041 #include <vector>
00042 #include "eoPersistent.h"
00043 #include "eoObject.h"
00044 
00103 class eoRng : public eoObject, public eoPersistent
00104 {
00105 public :
00106 
00113     eoRng(uint32_t s)
00114         : state(0), next(0), left(-1), cached(false), N(624), M(397), K(0x9908B0DFU)
00115         {
00116             state = new uint32_t[N+1];
00117             initialize(2*s);
00118         }
00119 
00120     ~eoRng(void)
00121         {
00122             delete [] state;
00123         }
00124 
00135     void reseed(uint32_t s)
00136         {
00137             initialize(2*s);
00138         }
00139 
00150     void oldReseed(uint32_t s)
00151         {
00152             initialize(s);
00153         }
00154 
00158     double uniform(double m = 1.0)
00159         { // random number between [0, m]
00160             return m * double(rand()) / double(1.0 + rand_max());
00161         }
00162 
00166     uint32_t random(uint32_t m)
00167         {
00168             return uint32_t(uniform() * double(m));
00169         }
00170 
00175     bool flip(float bias=0.5)
00176         {
00177             return uniform() < bias;
00178         }
00179 
00183     double normal(void);        // gaussian mutation, stdev 1
00184 
00188     double normal(double stdev)
00189         {
00190             return stdev * normal();
00191         }
00192 
00196     double normal(double mean, double stdev)
00197         {
00198             return mean + normal(stdev);
00199         }
00200 
00204     double negexp(double mean)
00205         {
00206             return ( -mean*log((double)rand() / rand_max()));
00207         }
00208 
00212     uint32_t rand();
00213 
00217     uint32_t rand_max(void) const { return uint32_t(0xffffffff); }
00218 
00224     template <typename TYPE>
00225     int roulette_wheel(const std::vector<TYPE>& vec, TYPE total = 0)
00226         {
00227             if (total == 0)
00228             { // count
00229                 for (unsigned    i = 0; i < vec.size(); ++i)
00230                     total += vec[i];
00231             }
00232             double fortune = uniform() * total;
00233             int i = 0;
00234             while (fortune > 0)
00235             {
00236                 fortune -= vec[i++];
00237             }
00238             return --i;
00239         }
00240 
00241 
00246     template <typename TYPE>
00247     const TYPE& choice(const std::vector<TYPE>& vec) const
00248         { return vec[random(vec.size())]; }
00249 
00250 
00261     template <typename TYPE>
00262     TYPE& choice(std::vector<TYPE>& vec)
00263         { return vec[random(vec.size())]; }
00264 
00266     void printOn(std::ostream& _os) const
00267         {
00268             for (int i = 0; i < N; ++i)
00269             {
00270                 _os << state[i] << ' ';
00271             }
00272             _os << int(next - state) << ' ';
00273             _os << left << ' ' << cached << ' ' << cacheValue;
00274         }
00275 
00277     void readFrom(std::istream& _is)
00278         {
00279             for (int i = 0; i < N; ++i)
00280             {
00281                 _is >> state[i];
00282             }
00283 
00284             int n;
00285             _is >> n;
00286             next = state + n;
00287 
00288             _is >> left;
00289             _is >> cached;
00290             _is >> cacheValue;
00291         }
00292 
00293     std::string className(void) const { return "Mersenne-Twister"; }
00294 
00295 private:
00296 
00297     uint32_t restart(void);
00298 
00299 
00300     /* @brief Initialize state
00301 
00302     We initialize state[0..(N-1)] via the generator
00303 
00304     <tt>x_new = (69069 * x_old) mod 2^32</tt>
00305 
00306     from Line 15 of Table 1, p. 106, Sec. 3.3.4 of Knuth's _The Art of Computer
00307     Programming_, Volume 2, 3rd ed.
00308 
00309     Notes (SJC): I do not know what the initial state requirements of the
00310     Mersenne Twister are, but it seems this seeding generator could be better.
00311     It achieves the maximum period for its modulus (2^30) iff x_initial is odd
00312     (p. 20-21, Sec. 3.2.1.2, Knuth); if x_initial can be even, you have
00313     sequences like 0, 0, 0, ...; 2^31, 2^31, 2^31, ...; 2^30, 2^30, 2^30, ...;
00314     2^29, 2^29 + 2^31, 2^29, 2^29 + 2^31, ..., etc. so I force seed to be odd
00315     below.
00316 
00317     Even if x_initial is odd, if x_initial is 1 mod 4 then
00318 
00319     the          lowest bit of x is always 1,
00320     the  next-to-lowest bit of x is always 0,
00321     the 2nd-from-lowest bit of x alternates      ... 0 1 0 1 0 1 0 1 ... ,
00322     the 3rd-from-lowest bit of x 4-cycles        ... 0 1 1 0 0 1 1 0 ... ,
00323     the 4th-from-lowest bit of x has the 8-cycle ... 0 0 0 1 1 1 1 0 ... ,
00324     ...
00325 
00326     and if x_initial is 3 mod 4 then
00327 
00328     the          lowest bit of x is always 1,
00329     the  next-to-lowest bit of x is always 1,
00330     the 2nd-from-lowest bit of x alternates      ... 0 1 0 1 0 1 0 1 ... ,
00331     the 3rd-from-lowest bit of x 4-cycles        ... 0 0 1 1 0 0 1 1 ... ,
00332     the 4th-from-lowest bit of x has the 8-cycle ... 0 0 1 1 1 1 0 0 ... ,
00333     ...
00334 
00335     The generator's potency (min. s>=0 with (69069-1)^s = 0 mod 2^32) is 16,
00336     which seems to be alright by p. 25, Sec. 3.2.1.3 of Knuth. It also does well
00337     in the dimension 2..5 spectral tests, but it could be better in dimension 6
00338     (Line 15, Table 1, p. 106, Sec. 3.3.4, Knuth).
00339 
00340     Note that the random number user does not see the values generated here
00341     directly since restart() will always munge them first, so maybe none of all
00342     of this matters. In fact, the seed values made here could even be
00343     extra-special desirable if the Mersenne Twister theory says so-- that's why
00344     the only change I made is to restrict to odd seeds.
00345     */
00346     void initialize(uint32_t seed);
00347 
00349     uint32_t* state;
00350 
00351     uint32_t* next;
00352 
00353     int left;
00354 
00355     // for normal distribution
00356     bool cached;
00357 
00358     float cacheValue;
00359 
00360     const int N;
00361 
00362     const int M;
00363 
00365     const uint32_t K;
00366 
00367 
00376     eoRng(const eoRng&);
00377 
00382     eoRng& operator=(const eoRng&);
00383 };
00384 
00385 
00386 
00387 namespace eo
00388 {
00390     extern eoRng rng;
00391 }
00392 using eo::rng;
00393 
00394 
00395 
00396 
00397 
00398 // Implementation of some eoRng members.... Don't mind the mess, it does work.
00399 
00400 
00401 #define hiBit(u)       ((u) & 0x80000000U)   // mask all but highest   bit of u
00402 #define loBit(u)       ((u) & 0x00000001U)   // mask all but lowest    bit of u
00403 #define loBits(u)      ((u) & 0x7FFFFFFFU)   // mask     the highest   bit of u
00404 #define mixBits(u, v)  (hiBit(u)|loBits(v))  // move hi bit of u to hi bit of v
00405 
00406 inline void eoRng::initialize(uint32_t seed)
00407 {
00408     left = -1;
00409 
00410     register uint32_t x = (seed | 1U) & 0xFFFFFFFFU, *s = state;
00411     register int    j;
00412 
00413     for(left=0, *s++=x, j=N; --j;
00414         *s++ = (x*=69069U) & 0xFFFFFFFFU);
00415 }
00416 
00417 
00418 
00419 inline uint32_t eoRng::restart(void)
00420 {
00421     register uint32_t *p0=state, *p2=state+2, *pM=state+M, s0, s1;
00422     register int    j;
00423 
00424     left=N-1, next=state+1;
00425 
00426     for(s0=state[0], s1=state[1], j=N-M+1; --j; s0=s1, s1=*p2++)
00427         *p0++ = *pM++ ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U);
00428 
00429     for(pM=state, j=M; --j; s0=s1, s1=*p2++)
00430         *p0++ = *pM++ ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U);
00431 
00432     s1=state[0], *p0 = *pM ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U);
00433     s1 ^= (s1 >> 11);
00434     s1 ^= (s1 <<  7) & 0x9D2C5680U;
00435     s1 ^= (s1 << 15) & 0xEFC60000U;
00436     return(s1 ^ (s1 >> 18));
00437 }
00438 
00439 
00440 
00441 inline uint32_t eoRng::rand(void)
00442 {
00443 
00444     uint32_t y;
00445 
00446     if(--left < 0)
00447         return(restart());
00448 
00449     y  = *next++;
00450     y ^= (y >> 11);
00451     y ^= (y <<  7) & 0x9D2C5680U;
00452     y ^= (y << 15) & 0xEFC60000U;
00453     return(y ^ (y >> 18));
00454 }
00455 
00456 
00457 
00458 inline double eoRng::normal(void)
00459 {
00460     if (cached)
00461     {
00462         cached = false;
00463         return cacheValue;
00464     }
00465 
00466     float rSquare, factor, var1, var2;
00467 
00468     do
00469     {
00470         var1 = 2.0 * uniform() - 1.0;
00471         var2 = 2.0 * uniform() - 1.0;
00472 
00473         rSquare = var1 * var1 + var2 * var2;
00474     }
00475     while (rSquare >= 1.0 || rSquare == 0.0);
00476 
00477     factor = sqrt(-2.0 * log(rSquare) / rSquare);
00478 
00479     cacheValue = var1 * factor;
00480     cached = true;
00481 
00482     return (var2 * factor);
00483 }
00484 
00485 
00486 
00487 namespace eo {
00488     // a few convenience functions for generating numbers
00489 
00503     template <typename T>
00504     inline T random(const T& max) {
00505         return static_cast<T>(rng.uniform() * max); }
00506 
00516     template <typename T>
00517     inline T random(const T& min, const T& max) {
00518         return static_cast<T>(rng.uniform() * (max-min)) + min; }
00519 
00521     inline double normal() { return rng.normal(); }
00522 }
00523 
00524 
00525 #endif
00526 
00527 
00528 // Local Variables:
00529 // coding: iso-8859-1
00530 // mode: C++
00531 // c-file-style: "Stroustrup"
00532 // fill-column: 80
00533 // End:

Generated on Thu Oct 19 05:06:38 2006 for EO by  doxygen 1.3.9.1