/home/fwph/code/wurde/rde/core/Random.H

Go to the documentation of this file.
00001 #ifndef Random_H
00002 #define Random_H
00003 
00024 #include <cmath>
00025 #include <unistd.h>
00026 #include <fcntl.h>
00027 
00029 
00041 
00042 
00052 class MTRand {
00053 public:
00057   MTRand(const unsigned long &oneSeed) {setSeed(oneSeed);}
00058 
00060 
00061   void setSeed(unsigned long seed);
00062 
00064   void randomize();
00065   
00067 
00068 
00069   virtual double mean() const = 0;
00071   virtual double variance() const = 0;
00073   virtual double stdDev() const = 0;
00075 
00076 private:
00077   typedef unsigned long uint32;
00078   
00079 protected:
00082   double rand() {return double(randInt()) * 2.3283064370807974e-10;}
00083 
00086   uint32 randInt();
00090   uint32 randInt(const uint32 &n);
00091 
00092 private:
00093   enum {N = 624, M = 397, MAGIC = 0x9908b0dfU};
00094   
00095   uint32 state[N];
00096   uint32 *pNext;
00097   int left;
00098   
00099   void reload();
00100 
00101   uint32 hiBit(const uint32 &u) const {return u & 0x80000000U;}
00102   uint32 loBit(const uint32 &u) const {return u & 0x00000001U;}
00103   uint32 loBits(const uint32 &u) const {return u & 0x7fffffffU;}
00104   uint32 mixBits(const uint32 &u, const uint32 &v) const {
00105     return hiBit(u) | loBits(v);}
00106   uint32 twist(const uint32 &m, const uint32 &s0, const uint32 &s1) const {
00107     return m ^ (mixBits(s0,s1)>>1) ^ (loBit(s1) ? MAGIC : 0U);}
00108 
00109   // Not allowed to use these
00110   MTRand(const MTRand &mtrand);
00111   MTRand &operator=(const MTRand &mtrand);
00112 };
00113 
00114 
00116 
00123 class RealRandom : public MTRand {
00124 public:
00128   RealRandom(const unsigned long seed) :MTRand(seed) {}
00129 
00131 
00132 
00133 
00139   RealRandom &operator>>(double &random_number) {
00140     random_number = number(); return *this;}
00142 
00145   double operator()() {return number();}
00147 
00152   operator double() {return number();}
00153 
00155 
00159   virtual double number() = 0;
00161 
00163 
00164   virtual double mean() const = 0;
00165   virtual double variance() const = 0;
00166   virtual double stdDev() const = 0;
00168 };
00169 
00170 
00172 
00179 class IntegerRandom : public MTRand {
00180 public:
00184   IntegerRandom(const unsigned long seed) :MTRand(seed) {}
00185 
00187 
00188 
00189 
00194   IntegerRandom &operator>>(int &random_number) {
00195     random_number = number(); return *this;}
00197 
00200   int operator()() {return number();}
00202 
00207   operator int() {return number();}
00208 
00210 
00214   virtual int number() = 0;
00216 
00218 
00219   virtual double mean() const = 0;
00220   virtual double variance() const = 0;
00221   virtual double stdDev() const = 0;
00223 };
00224 
00225 
00227 
00235 class UniformRandomSimple : public RealRandom {
00236 public:
00240   UniformRandomSimple(const unsigned long seed = 1UL) :RealRandom(seed) {}
00241 
00243 
00244   double number() {return MTRand::rand();}
00246 
00248 
00249   double mean() const {return 0.5;}
00250   double variance() const {return (1.0 / 12.0);}
00251   double stdDev() const {return sqrt(1.0 / 12.0);}
00253 };
00254 
00255 
00257 
00264 class UniformRandom : public RealRandom {
00265 public:
00281   UniformRandom(const double low = 1.0, const double high = 0.0,
00282                 const unsigned long seed = 1UL)
00283     :RealRandom(seed), m_low((low < high)?low:high),
00284      m_range((low < high)?(high - low):(low - high)) {}
00285 
00287 
00288   double number() {return (MTRand::rand() * m_range) + m_low;}
00290 
00292 
00293   double mean() const {return ((m_range / 2.0) + m_low);}
00294   double variance() const {return ((m_range * m_range) / 12.0);}
00295   double stdDev() const {return sqrt(variance());}
00297 
00299 
00300 
00301   double lowValue() const {return m_low;}
00303   double highValue() const {return (m_low + m_range);}
00305   double range() const {return m_range;}
00307 
00309 
00310 
00312   void setLowValue(const double low) {m_low = low;}
00315   void setHighValue(const double high) {m_range = high - m_low;}  
00319   void setValues(const double low, const double high) {
00320     setLowValue(low); setHighValue(high);}
00322 
00323 private:
00324   double m_low;
00325   double m_range;
00326 };
00327 
00328 
00330 
00338 class NormalRandom : public RealRandom {
00339 public:
00346   NormalRandom(const double mean = 0.0, const double variance = 1.0,
00347                const unsigned long seed = 1UL)
00348     :RealRandom(seed), m_mean(mean), m_std_dev(sqrt(fabs(variance))) {}
00349   
00351 
00352   double number();
00354 
00356 
00357   double mean() const {return m_mean;}
00358   double variance() const {return (m_std_dev * m_std_dev);}
00359   double stdDev() const {return m_std_dev;}
00361 
00363 
00364 
00366   void setMean(const double mean) {m_mean = mean;}
00369   void setVariance(const double variance) {m_std_dev = sqrt(fabs(variance));}
00372   void setStdDev(const double std_dev) {m_std_dev = fabs(std_dev);}
00376   void setParameters(const double mean, const double variance) {
00377       setMean(mean); setVariance(variance);}
00379 
00380 private:
00381   double m_mean;
00382   double m_std_dev;
00383 };
00384 
00385 
00387 
00393 class ExponentialRandom : public RealRandom {
00394 public:
00400   ExponentialRandom(const double lambda = 1.0, const unsigned long seed = 1UL)
00401     :RealRandom(seed), m_lambda(lambda) {}
00402   
00404 
00405   double number();
00407 
00409 
00410   double mean() const {return (1.0 / m_lambda);}
00411   double variance() const {return (1.0 / (m_lambda * m_lambda));}
00412   double stdDev() const {return (1.0 / m_lambda);}
00414 
00416 
00417 
00418   double lambda() const {return m_lambda;}
00420 
00422 
00423 
00425   void setMean(const double mean) {m_lambda = (1.0 / mean);}
00428   void setVariance(const double variance) {m_lambda = sqrt(1.0 / variance);}
00431   void setStdDev(const double std_dev) {m_lambda = (1.0 / std_dev);}
00434   void setLambda(const double lambda) {m_lambda = lambda;}
00438   void setParameters(const double mean, const double variance) {
00439       setMean(mean); setVariance(variance);}
00441 
00442 private:
00443   double m_lambda;
00444 };
00445 
00446 
00448 
00454 class DiscreteUniformRandom : public IntegerRandom {
00455 public:
00464   DiscreteUniformRandom(const int low, const int high,
00465                        const unsigned long seed = 1UL)
00466     :IntegerRandom(seed), m_low((low < high)?low:high),
00467      m_range((unsigned long)((low < high)?(high - low):(low - high))) {}
00475   DiscreteUniformRandom(const int range, const unsigned long seed = 1UL)
00476     :IntegerRandom(seed), m_low(0), m_range(range - 1) {}
00477 
00479 
00480   int number() {return MTRand::randInt(m_range) + m_low;}
00482 
00484 
00485   double mean() const {return (((double)m_range / 2.0));}
00486   double variance() const {return ((double)(m_range * m_range) / 12.0);}
00487   double stdDev() const {return sqrt(variance());}
00489 
00491 
00492 
00493   int lowValue() const {return m_low;}
00495   int highValue() const {return (m_low + m_range);}
00497   int range() const {return m_range + 1;}
00499 
00501 
00502 
00504   void setLowValue(const int low) {m_low = low;}
00507   void setHighValue(const int high) {m_range = (unsigned long)(high - m_low);}
00511   void setValues(const int low, const int high) {
00512     setLowValue(low); setHighValue(high);}
00514 
00515 private:
00516   int m_low;
00517   unsigned long m_range;
00518 };
00519 
00520 
00522 
00528 class BernoulliRandom : public IntegerRandom {
00529 public:
00535   BernoulliRandom(const double success = 0.5, const unsigned long seed = 1UL)
00536     :IntegerRandom(seed), m_success(success) {}
00537 
00539 
00540   int number() {return (rand() <= m_success)?1:0;}
00542 
00544 
00545   double mean() const {return m_success;}
00546   double variance() const {return (m_success * (1.0 - m_success));}
00547   double stdDev() const {return sqrt(variance());}
00549 
00551 
00552 
00553   double success() const {return m_success;}
00555   double probSuccess() const {return success();}
00557   double failure() const {return (1.0 - m_success);}
00559   double probFailure() const {return failure();}
00561 
00563 
00564 
00566   void setProbSuccess(const double success) {m_success = success;}
00569   void setProbFailure(const double failure) {m_success = 1.0 - failure;}
00571 
00572 private:
00573   double m_success;
00574 };
00575 
00576 
00577 // This is ugly, but half of the cost of these calls is in the function
00578 // call overhead.
00579 
00580 
00581 inline MTRand::uint32 MTRand::randInt() {
00582   if(left == 0)
00583     reload();
00584   --left;
00585                 
00586   register uint32 s1;
00587   s1 = *pNext++;
00588   s1 ^= (s1 >> 11);
00589   s1 ^= (s1 <<  7) & 0x9d2c5680U;
00590   s1 ^= (s1 << 15) & 0xefc60000U;
00591   return (s1 ^ (s1 >> 18));
00592 }
00593 
00594 
00595 inline MTRand::uint32 MTRand::randInt(const uint32 &n) {
00596         // RLG: this is a problem; ~0 has the sign bit set.
00597   // Find which bits are used in n
00598         //  uint32 used = ~0;
00599         long int used = ~0;
00600   for(uint32 m = n; m; used <<= 1, m >>= 1 ) {}
00601   used = ~used;
00602         
00603   // Draw numbers until one is found in [0,n]
00604   uint32 i;
00605   do
00606     i = randInt() & used;  // toss unused bits to shorten search
00607   while(i > n);
00608   return i;
00609 }
00610 
00611 
00612 inline void MTRand::setSeed(unsigned long seed) {
00613   // Seed the generator with a simple uint32
00614   register uint32 *s;
00615   register int i;
00616   for(i = N, s = state; i--;
00617       *s = seed & 0xffff0000,
00618         *s++ |= ((seed *= 69069U)++ & 0xffff0000) >> 16,
00619         (seed *= 69069U)++) {}  // hard to read, but fast
00620   reload();
00621 }
00622 
00623 
00624 inline void MTRand::randomize() {
00625   unsigned long seed_number;
00626 
00627   int fp = open("/dev/urandom", O_RDONLY);
00628   read(fp, &seed_number, sizeof(seed_number));
00629   close(fp);
00630 
00631   MTRand::setSeed(seed_number);
00632 }
00633 
00634 
00635 
00636 inline void MTRand::reload() {
00637   // Generate N new values in state
00638   // Made clearer and faster by Matthew Bellew (matthew.bellew@home.com)
00639   register uint32 *p = state;
00640   register int i;
00641   for(i = N - M; i--;) {
00642                 //              *p++ = twist(p[M], p[0], p[1]);    // RLG: Precedence poorly defined
00643                 *p = twist(p[M], p[0], p[1]);
00644                 p++;
00645         }
00646   for(i = M; --i;) {
00647                 //              *p++ = twist(p[M-N], p[0], p[1]);  // RLG: Precedence poorly defined.
00648                 *p = twist(p[M-N], p[0], p[1]);
00649                 p++;
00650         }
00651   *p = twist(p[M-N], p[0], state[0]);
00652   left = N, pNext = state;
00653 }
00654 
00655 
00656 // We could cache another number m_std_dev * r * sin(theta) + m_mean, but
00657 // this introduces non-randomness into the stream of numbers, although it
00658 // speeds things up a bit.
00659 inline double NormalRandom::number() {
00660   double theta = 2.0 * M_PI * MTRand::rand();
00661   double r = sqrt(-2.0 * log(MTRand::rand()));
00662   
00663   return ((m_std_dev * r * cos(theta)) + m_mean);
00664 }
00665 
00666 
00667 #endif

Generated on Thu Feb 1 15:31:54 2007 for WURDE by  doxygen 1.5.1