lemon/random.h
author alpar
Mon, 13 Nov 2006 18:46:19 +0000
changeset 2301 eb378706bd3d
parent 2257 0a9393adc747
child 2355 ac0d843b8873
permissions -rw-r--r--
Test the automatic compilation checker 1/2: make a bug
     1 /* -*- C++ -*-
     2  *
     3  * This file is a part of LEMON, a generic C++ optimization library
     4  *
     5  * Copyright (C) 2003-2006
     6  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     7  * (Egervary Research Group on Combinatorial Optimization, EGRES).
     8  *
     9  * Permission to use, modify and distribute this software is granted
    10  * provided that this copyright notice appears in all copies. For
    11  * precise terms see the accompanying LICENSE file.
    12  *
    13  * This software is provided "AS IS" with no warranty of any kind,
    14  * express or implied, and with no claim as to its suitability for any
    15  * purpose.
    16  *
    17  */
    18 
    19 #ifndef LEMON_RANDOM_H
    20 #define LEMON_RANDOM_H
    21 
    22 #include <algorithm>
    23 #include <iterator>
    24 #include <vector>
    25 
    26 #include <ctime>
    27 #include <cmath>
    28 #include <cmath>
    29 
    30 ///\ingroup misc
    31 ///\file
    32 ///\brief Mersenne Twister random number generator
    33 ///
    34 ///\author Balazs Dezso
    35 
    36 namespace lemon {
    37 
    38   namespace _random_bits {
    39     
    40     template <typename _Word, int _bits = std::numeric_limits<_Word>::digits>
    41     struct RandomTraits {};
    42 
    43     template <typename _Word>
    44     struct RandomTraits<_Word, 32> {
    45 
    46       typedef _Word Word;
    47       static const int bits = 32;
    48 
    49       static const int length = 624;
    50       static const int shift = 397;
    51       
    52       static const Word mul = 0x6c078965u;
    53       static const Word arrayInit = 0x012BD6AAu;
    54       static const Word arrayMul1 = 0x0019660Du;
    55       static const Word arrayMul2 = 0x5D588B65u;
    56 
    57       static const Word mask = 0x9908B0DFu;
    58       static const Word loMask = (1u << 31) - 1;
    59       static const Word hiMask = ~loMask;
    60 
    61 
    62       static Word tempering(Word rnd) {
    63         rnd ^= (rnd >> 11);
    64         rnd ^= (rnd << 7) & 0x9D2C5680u;
    65         rnd ^= (rnd << 15) & 0xEFC60000u;
    66         rnd ^= (rnd >> 18);
    67         return rnd;
    68       }
    69 
    70     };
    71 
    72     template <typename _Word>
    73     struct RandomTraits<_Word, 64> {
    74 
    75       typedef _Word Word;
    76       static const int bits = 64;
    77 
    78       static const int length = 312;
    79       static const int shift = 156;
    80 
    81       static const Word mul = (Word)0x5851F42Du << 32 | (Word)0x4C957F2Du;
    82       static const Word arrayInit = (Word)0x00000000u << 32 |(Word)0x012BD6AAu;
    83       static const Word arrayMul1 = (Word)0x369DEA0Fu << 32 |(Word)0x31A53F85u;
    84       static const Word arrayMul2 = (Word)0x27BB2EE6u << 32 |(Word)0x87B0B0FDu;
    85 
    86       static const Word mask = (Word)0xB5026F5Au << 32 | (Word)0xA96619E9u;
    87       static const Word loMask = ((Word)1u << 31) - 1;
    88       static const Word hiMask = ~loMask;
    89 
    90       static Word tempering(Word rnd) {
    91         rnd ^= (rnd >> 29) & ((Word)0x55555555u << 32 | (Word)0x55555555u);
    92         rnd ^= (rnd << 17) & ((Word)0x71D67FFFu << 32 | (Word)0xEDA60000u);
    93         rnd ^= (rnd << 37) & ((Word)0xFFF7EEE0u << 32 | (Word)0x00000000u);
    94         rnd ^= (rnd >> 43);
    95         return rnd;
    96       }
    97 
    98     };
    99 
   100     template <typename _Word>
   101     class RandomCore {
   102     public:
   103 
   104       typedef _Word Word;
   105 
   106     private:
   107 
   108       static const int bits = RandomTraits<Word>::bits;
   109 
   110       static const int length = RandomTraits<Word>::length;
   111       static const int shift = RandomTraits<Word>::shift;
   112 
   113     public:
   114 
   115       void initState() {
   116         static const Word seedArray[4] = {
   117           0x12345u, 0x23456u, 0x34567u, 0x45678u
   118         };
   119     
   120         initState(seedArray, seedArray + 4);
   121       }
   122 
   123       void initState(Word seed) {
   124 
   125         static const Word mul = RandomTraits<Word>::mul;
   126 
   127         current = state; 
   128 
   129         Word *curr = state + length - 1;
   130         curr[0] = seed; --curr;
   131         for (int i = 1; i < length; ++i) {
   132           curr[0] = (mul * ( curr[1] ^ (curr[1] >> (bits - 2)) ) + i);
   133           --curr;
   134         }
   135       }
   136 
   137       template <typename Iterator>
   138       void initState(Iterator begin, Iterator end) {
   139 
   140         static const Word init = RandomTraits<Word>::arrayInit;
   141         static const Word mul1 = RandomTraits<Word>::arrayMul1;
   142         static const Word mul2 = RandomTraits<Word>::arrayMul2;
   143 
   144 
   145         Word *curr = state + length - 1; --curr;
   146         Iterator it = begin; int cnt = 0;
   147         int num;
   148 
   149         initState(init);
   150 
   151         num = length > end - begin ? length : end - begin;
   152         while (num--) {
   153           curr[0] = (curr[0] ^ ((curr[1] ^ (curr[1] >> (bits - 2))) * mul1)) 
   154             + *it + cnt;
   155           ++it; ++cnt;
   156           if (it == end) {
   157             it = begin; cnt = 0;
   158           }
   159           if (curr == state) {
   160             curr = state + length - 1; curr[0] = state[0];
   161           }
   162           --curr;
   163         }
   164 
   165         num = length - 1; cnt = length - (curr - state) - 1;
   166         while (num--) {
   167           curr[0] = (curr[0] ^ ((curr[1] ^ (curr[1] >> (bits - 2))) * mul2))
   168             - cnt;
   169           --curr; ++cnt;
   170           if (curr == state) {
   171             curr = state + length - 1; curr[0] = state[0]; --curr;
   172             cnt = 1;
   173           }
   174         }
   175         
   176         state[length - 1] = (Word)1 << (bits - 1);
   177       }
   178       
   179       void copyState(const RandomCore& other) {
   180         std::copy(other.state, other.state + length, state);
   181         current = state + (other.current - other.state);
   182       }
   183 
   184       Word operator()() {
   185         if (current == state) fillState();
   186         --current;
   187         Word rnd = *current;
   188         return RandomTraits<Word>::tempering(rnd);
   189       }
   190 
   191     private:
   192 
   193   
   194       void fillState() {
   195         static const Word mask[2] = { 0x0ul, RandomTraits<Word>::mask };
   196         static const Word loMask = RandomTraits<Word>::loMask;
   197         static const Word hiMask = RandomTraits<Word>::hiMask;
   198 
   199         current = state + length; 
   200 
   201         register Word *curr = state + length - 1;
   202         register long num;
   203       
   204         num = length - shift;
   205         while (num--) {
   206           curr[0] = (((curr[0] & hiMask) | (curr[-1] & loMask)) >> 1) ^
   207             curr[- shift] ^ mask[curr[-1] & 1ul];
   208           --curr;
   209         }
   210         num = shift - 1;
   211         while (num--) {
   212           curr[0] = (((curr[0] & hiMask) | (curr[-1] & loMask)) >> 1) ^
   213             curr[length - shift] ^ mask[curr[-1] & 1ul];
   214           --curr;
   215         }
   216         curr[0] = (((curr[0] & hiMask) | (curr[length - 1] & loMask)) >> 1) ^
   217           curr[length - shift] ^ mask[curr[length - 1] & 1ul];
   218 
   219       }
   220 
   221   
   222       Word *current;
   223       Word state[length];
   224       
   225     };
   226 
   227 
   228     template <typename Result, 
   229               int shift = (std::numeric_limits<Result>::digits + 1) / 2>
   230     struct Masker {
   231       static Result mask(const Result& result) {
   232         return Masker<Result, (shift + 1) / 2>::
   233           mask((Result)(result | (result >> shift)));
   234       }
   235     };
   236     
   237     template <typename Result>
   238     struct Masker<Result, 1> {
   239       static Result mask(const Result& result) {
   240         return (Result)(result | (result >> 1));
   241       }
   242     };
   243 
   244     template <typename Result, typename Word, 
   245               int rest = std::numeric_limits<Result>::digits, int shift = 0, 
   246               bool last = rest <= std::numeric_limits<Word>::digits>
   247     struct IntConversion {
   248       static const int bits = std::numeric_limits<Word>::digits;
   249     
   250       static Result convert(RandomCore<Word>& rnd) {
   251         return (Result)(rnd() >> (bits - rest)) << shift;
   252       }
   253       
   254     }; 
   255 
   256     template <typename Result, typename Word, int rest, int shift> 
   257     struct IntConversion<Result, Word, rest, shift, false> {
   258       static const int bits = std::numeric_limits<Word>::digits;
   259 
   260       static Result convert(RandomCore<Word>& rnd) {
   261         return ((Result)rnd() << shift) | 
   262           IntConversion<Result, Word, rest - bits, shift + bits>::convert(rnd);
   263       }
   264     };
   265 
   266 
   267     template <typename Result, typename Word,
   268               bool one_word = std::numeric_limits<Word>::digits < 
   269                               std::numeric_limits<Result>::digits>
   270     struct Mapping {
   271       static Result map(RandomCore<Word>& rnd, const Result& bound) {
   272         Word max = (Word)(bound - 1);
   273         Result mask = Masker<Result>::mask(bound - 1);
   274         Result num;
   275         do {
   276           num = IntConversion<Result, Word>::convert(rnd) & mask; 
   277         } while (num > max);
   278         return num;
   279       }
   280     };
   281 
   282     template <typename Result, typename Word>
   283     struct Mapping<Result, Word, false> {
   284       static Result map(RandomCore<Word>& rnd, const Result& bound) {
   285         Word max = (Word)(bound - 1);
   286         Word mask = Masker<Word, (std::numeric_limits<Result>::digits + 1) / 2>
   287           ::mask(max);
   288         Word num;
   289         do {
   290           num = rnd() & mask;
   291         } while (num > max);
   292         return num;
   293       }
   294     };
   295 
   296     template <typename Result, int exp, bool pos = (exp >= 0)>
   297     struct ShiftMultiplier {
   298       static const Result multiplier() {
   299         Result res = ShiftMultiplier<Result, exp / 2>::multiplier();
   300         res *= res;
   301         if ((exp & 1) == 1) res *= (Result)2.0;
   302         return res; 
   303       }
   304     };
   305 
   306     template <typename Result, int exp>
   307     struct ShiftMultiplier<Result, exp, false> {
   308       static const Result multiplier() {
   309         Result res = ShiftMultiplier<Result, exp / 2>::multiplier();
   310         res *= res;
   311         if ((exp & 1) == 1) res *= (Result)0.5;
   312         return res; 
   313       }
   314     };
   315 
   316     template <typename Result>
   317     struct ShiftMultiplier<Result, 0, true> {
   318       static const Result multiplier() {
   319         return (Result)1.0; 
   320       }
   321     };
   322 
   323     template <typename Result>
   324     struct ShiftMultiplier<Result, -20, true> {
   325       static const Result multiplier() {
   326         return (Result)(1.0/1048576.0); 
   327       }
   328     };
   329     
   330     template <typename Result>
   331     struct ShiftMultiplier<Result, -32, true> {
   332       static const Result multiplier() {
   333         return (Result)(1.0/424967296.0); 
   334       }
   335     };
   336 
   337     template <typename Result>
   338     struct ShiftMultiplier<Result, -53, true> {
   339       static const Result multiplier() {
   340         return (Result)(1.0/9007199254740992.0); 
   341       }
   342     };
   343 
   344     template <typename Result>
   345     struct ShiftMultiplier<Result, -64, true> {
   346       static const Result multiplier() {
   347         return (Result)(1.0/18446744073709551616.0); 
   348       }
   349     };
   350 
   351     template <typename Result, int exp>
   352     struct Shifting {
   353       static Result shift(const Result& result) {
   354         return result * ShiftMultiplier<Result, exp>::multiplier();
   355       }
   356     };
   357 
   358     template <typename Result, typename Word,
   359               int rest = std::numeric_limits<Result>::digits, int shift = 0, 
   360               bool last = rest <= std::numeric_limits<Word>::digits>
   361     struct RealConversion{ 
   362       static const int bits = std::numeric_limits<Word>::digits;
   363 
   364       static Result convert(RandomCore<Word>& rnd) {
   365         return Shifting<Result, - shift - rest>::
   366           shift((Result)(rnd() >> (bits - rest)));
   367       }
   368     };
   369 
   370     template <typename Result, typename Word, int rest, int shift>
   371     struct RealConversion<Result, Word, rest, shift, false> { 
   372       static const int bits = std::numeric_limits<Word>::digits;
   373 
   374       static Result convert(RandomCore<Word>& rnd) {
   375         return Shifting<Result, - shift - bits>::shift((Result)rnd()) +
   376           RealConversion<Result, Word, rest-bits, shift + bits>::convert(rnd);
   377       }
   378     };
   379 
   380     template <typename Result, typename Word>
   381     struct Initializer {
   382 
   383       template <typename Iterator>
   384       static void init(RandomCore<Word>& rnd, Iterator begin, Iterator end) {
   385         std::vector<Word> ws;
   386         for (Iterator it = begin; it != end; ++it) {
   387           ws.push_back((Word)*it);
   388         }
   389         rnd.initState(ws.begin(), ws.end());
   390       }
   391 
   392       static void init(RandomCore<Word>& rnd, Result seed) {
   393         rnd.initState(seed);
   394       }
   395     };
   396 
   397     template <typename Word>
   398     struct BoolConversion {
   399       static bool convert(RandomCore<Word>& rnd) {
   400         return (rnd() & 1) == 1;
   401       }
   402     };
   403 
   404   }
   405 
   406   /// \ingroup misc
   407   ///
   408   /// \brief Mersenne Twister random number generator
   409   ///
   410   /// The Mersenne Twister is a twisted generalized feedback
   411   /// shift-register generator of Matsumoto and Nishimura. The period
   412   /// of this generator is \f$ 2^{19937} - 1 \f$ and it is
   413   /// equi-distributed in 623 dimensions for 32-bit numbers. The time
   414   /// performance of this generator is comparable to the commonly used
   415   /// generators.
   416   ///
   417   /// This implementation is specialized for both 32-bit and 64-bit
   418   /// architectures. The generators differ sligthly in the
   419   /// initialization and generation phase so they produce two
   420   /// completly different sequences.
   421   ///
   422   /// The generator gives back random numbers of serveral types. To
   423   /// get a random number from a range of a floating point type you
   424   /// can use one form of the \c operator() or the \c real() member
   425   /// function. If you want to get random number from the {0, 1, ...,
   426   /// n-1} integer range use the \c operator[] or the \c integer()
   427   /// method. And to get random number from the whole range of an
   428   /// integer type you can use the argumentless \c integer() or \c
   429   /// uinteger() functions. After all you can get random bool with
   430   /// equal chance of true and false or given probability of true
   431   /// result with the \c boolean() member functions.
   432   ///
   433   ///\code
   434   /// // The commented code is identical to the other
   435   /// double a = rnd();                     // [0.0, 1.0)
   436   /// // double a = rnd.real();             // [0.0, 1.0)
   437   /// double b = rnd(100.0);                // [0.0, 100.0)
   438   /// // double b = rnd.real(100.0);        // [0.0, 100.0)
   439   /// double c = rnd(1.0, 2.0);             // [1.0, 2.0)
   440   /// // double c = rnd.real(1.0, 2.0);     // [1.0, 2.0)
   441   /// int d = rnd[100000];                  // 0..99999
   442   /// // int d = rnd.integer(100000);       // 0..99999
   443   /// int e = rnd[6] + 1;                   // 1..6
   444   /// // int e = rnd.integer(1, 1 + 6);     // 1..6
   445   /// int b = rnd.uinteger<int>();          // 0 .. 2^31 - 1
   446   /// int c = rnd.integer<int>();           // - 2^31 .. 2^31 - 1
   447   /// bool g = rnd.boolean();               // P(g = true) = 0.5
   448   /// bool h = rnd.boolean(0.8);            // P(h = true) = 0.8
   449   ///\endcode
   450   ///
   451   /// The lemon provides a global instance of the random number
   452   /// generator which name is \ref lemon::rnd "rnd". Usually it is a
   453   /// good programming convenience to use this global generator to get
   454   /// random numbers.
   455   ///
   456   /// \author Balazs Dezso
   457   class Random {
   458   private:
   459 
   460     // architecture word
   461     typedef unsigned long Word;
   462     
   463     _random_bits::RandomCore<Word> core;
   464 
   465   public:
   466 
   467     /// \brief Constructor
   468     ///
   469     /// Constructor with constant seeding.
   470     Random() { core.initState(); }
   471 
   472     /// \brief Constructor
   473     ///
   474     /// Constructor with seed. The current number type will be converted
   475     /// to the architecture word type.
   476     template <typename Number>
   477     Random(Number seed) { 
   478       _random_bits::Initializer<Number, Word>::init(core, seed);
   479     }
   480 
   481     /// \brief Constructor
   482     ///
   483     /// Constructor with array seeding. The given range should contain
   484     /// any number type and the numbers will be converted to the
   485     /// architecture word type.
   486     template <typename Iterator>
   487     Random(Iterator begin, Iterator end) { 
   488       typedef typename std::iterator_traits<Iterator>::value_type Number;
   489       _random_bits::Initializer<Number, Word>::init(core, begin, end);
   490     }
   491 
   492     /// \brief Copy constructor
   493     ///
   494     /// Copy constructor. The generated sequence will be identical to
   495     /// the other sequence. It can be used to save the current state
   496     /// of the generator and later use it to generate the same
   497     /// sequence.
   498     Random(const Random& other) {
   499       core.copyState(other.core);
   500     }
   501 
   502     /// \brief Assign operator
   503     ///
   504     /// Assign operator. The generated sequence will be identical to
   505     /// the other sequence. It can be used to save the current state
   506     /// of the generator and later use it to generate the same
   507     /// sequence.
   508     Random& operator=(const Random& other) {
   509       if (&other != this) {
   510         core.copyState(other.core);
   511       }
   512       return *this;
   513     }
   514 
   515     /// \brief Returns a random real number from the range [0, 1)
   516     ///
   517     /// It returns a random real number from the range [0, 1). The
   518     /// default Number type is double.
   519     template <typename Number>
   520     Number real() {
   521       return _random_bits::RealConversion<Number, Word>::convert(core);
   522     }
   523 
   524     double real() {
   525       return real<double>();
   526     }
   527 
   528     /// \brief Returns a random real number the range [0, b)
   529     ///
   530     /// It returns a random real number from the range [0, b).
   531     template <typename Number>
   532     Number real(Number b) { 
   533       return real<Number>() * b; 
   534     }
   535 
   536     /// \brief Returns a random real number from the range [a, b)
   537     ///
   538     /// It returns a random real number from the range [a, b).
   539     template <typename Number>
   540     Number real(Number a, Number b) { 
   541       return real<Number>() * (b - a) + a; 
   542     }
   543 
   544     /// \brief Returns a random real number from the range [0, 1)
   545     ///
   546     /// It returns a random double from the range [0, 1).
   547     double operator()() {
   548       return real<double>();
   549     }
   550 
   551     /// \brief Returns a random real number from the range [0, b)
   552     ///
   553     /// It returns a random real number from the range [0, b).
   554     template <typename Number>
   555     Number operator()(Number b) { 
   556       return real<Number>() * b; 
   557     }
   558 
   559     /// \brief Returns a random real number from the range [a, b)
   560     ///
   561     /// It returns a random real number from the range [a, b).
   562     template <typename Number>
   563     Number operator()(Number a, Number b) { 
   564       return real<Number>() * (b - a) + a; 
   565     }
   566 
   567     /// \brief Returns a random integer from a range
   568     ///
   569     /// It returns a random integer from the range {0, 1, ..., b - 1}.
   570     template <typename Number>
   571     Number integer(Number b) {
   572       return _random_bits::Mapping<Number, Word>::map(core, b);
   573     }
   574 
   575     /// \brief Returns a random integer from a range
   576     ///
   577     /// It returns a random integer from the range {a, a + 1, ..., b - 1}.
   578     template <typename Number>
   579     Number integer(Number a, Number b) {
   580       return _random_bits::Mapping<Number, Word>::map(core, b - a) + a;
   581     }
   582 
   583     /// \brief Returns a random integer from a range
   584     ///
   585     /// It returns a random integer from the range {0, 1, ..., b - 1}.
   586     template <typename Number>
   587     Number operator[](Number b) {
   588       return _random_bits::Mapping<Number, Word>::map(core, b);
   589     }
   590 
   591     /// \brief Returns a random non-negative integer
   592     ///
   593     /// It returns a random non-negative integer uniformly from the
   594     /// whole range of the current \c Number type.  The default result
   595     /// type of this function is unsigned int.
   596     template <typename Number>
   597     Number uinteger() {
   598       return _random_bits::IntConversion<Number, Word>::convert(core);
   599     }
   600 
   601     unsigned int uinteger() {
   602       return uinteger<unsigned int>();
   603     }
   604 
   605     /// \brief Returns a random integer
   606     ///
   607     /// It returns a random integer uniformly from the whole range of
   608     /// the current \c Number type. The default result type of this
   609     /// function is int.
   610     template <typename Number>
   611     Number integer() {
   612       static const int nb = std::numeric_limits<Number>::digits + 
   613         (std::numeric_limits<Number>::is_signed ? 1 : 0);
   614       return _random_bits::IntConversion<Number, Word, nb>::convert(core);
   615     }
   616 
   617     int integer() {
   618       return integer<int>();
   619     }
   620     
   621     /// \brief Returns a random bool
   622     ///
   623     /// It returns a random bool
   624     bool boolean() {
   625       return _random_bits::BoolConversion<Word>::convert(core);
   626     }
   627 
   628     /// \brief Returns a random bool
   629     ///
   630     /// It returns a random bool with given probability of true result
   631     bool boolean(double p) {
   632       return operator()() < p;
   633     }
   634     
   635   };
   636 
   637 
   638   extern Random rnd;
   639 
   640 }
   641 
   642 #endif