lemon/random.h
author athos
Mon, 30 Oct 2006 16:12:44 +0000
changeset 2273 507232469f5e
parent 2245 f09b1ea5c249
child 2285 8c5c4b5ae31c
permissions -rw-r--r--
Small bugs in the documentation.
     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       template <typename Iterator>
   393       static void init(RandomCore<Word>& rnd, Result seed) {
   394         rnd.initState(seed);
   395       }
   396     };
   397 
   398     template <typename Word>
   399     struct BoolConversion {
   400       static bool convert(RandomCore<Word>& rnd) {
   401         return (rnd() & 1) == 1;
   402       }
   403     };
   404 
   405   }
   406 
   407   /// \ingroup misc
   408   ///
   409   /// \brief Mersenne Twister random number generator
   410   ///
   411   /// The Mersenne Twister is a twisted generalized feedback
   412   /// shift-register generator of Matsumoto and Nishimura. The period
   413   /// of this generator is \f$ 2^{19937} - 1 \f$ and it is
   414   /// equi-distributed in 623 dimensions for 32-bit numbers. The time
   415   /// performance of this generator is comparable to the commonly used
   416   /// generators.
   417   ///
   418   /// This implementation is specialized for both 32-bit and 64-bit
   419   /// architectures. The generators differ sligthly in the
   420   /// initialization and generation phase so they produce two
   421   /// completly different sequences.
   422   ///
   423   /// The generator gives back random numbers of serveral types. To
   424   /// get a random number from a range of a floating point type you
   425   /// can use one form of the \c operator() or the \c real() member
   426   /// function. If you want to get random number from the {0, 1, ...,
   427   /// n-1} integer range use the \c operator[] or the \c integer()
   428   /// method. And to get random number from the whole range of an
   429   /// integer type you can use the argumentless \c integer() or \c
   430   /// uinteger() functions. After all you can get random bool with
   431   /// equal chance of true and false or given probability of true
   432   /// result with the \c boolean() member functions.
   433   ///
   434   ///\code
   435   /// // The commented code is identical to the other
   436   /// double a = rnd();                     // [0.0, 1.0)
   437   /// // double a = rnd.real();             // [0.0, 1.0)
   438   /// double b = rnd(100.0);                // [0.0, 100.0)
   439   /// // double b = rnd.real(100.0);        // [0.0, 100.0)
   440   /// double c = rnd(1.0, 2.0);             // [1.0, 2.0)
   441   /// // double c = rnd.real(1.0, 2.0);     // [1.0, 2.0)
   442   /// int d = rnd[100000];                  // 0..99999
   443   /// // int d = rnd.integer(100000);       // 0..99999
   444   /// int e = rnd[6] + 1;                   // 1..6
   445   /// // int e = rnd.integer(1, 1 + 6);     // 1..6
   446   /// int b = rnd.uinteger<int>();          // 0 .. 2^31 - 1
   447   /// int c = rnd.integer<int>();           // - 2^31 .. 2^31 - 1
   448   /// bool g = rnd.boolean();               // P(g = true) = 0.5
   449   /// bool h = rnd.boolean(0.8);            // P(h = true) = 0.8
   450   ///\endcode
   451   ///
   452   /// The lemon provides a global instance of the random number
   453   /// generator which name is \ref lemon::rnd "rnd". Usually it is a
   454   /// good programming convenience to use this global generator to get
   455   /// random numbers.
   456   ///
   457   /// \author Balazs Dezso
   458   class Random {
   459   private:
   460 
   461     // architecture word
   462     typedef unsigned long Word;
   463     
   464     _random_bits::RandomCore<Word> core;
   465 
   466   public:
   467 
   468     /// \brief Constructor
   469     ///
   470     /// Constructor with constant seeding.
   471     Random() { core.initState(); }
   472 
   473     /// \brief Constructor
   474     ///
   475     /// Constructor with seed. The current number type will be converted
   476     /// to the architecture word type.
   477     template <typename Number>
   478     Random(Number seed) { 
   479       _random_bits::Initializer<Number, Word>::init(core, seed);
   480     }
   481 
   482     /// \brief Constructor
   483     ///
   484     /// Constructor with array seeding. The given range should contain
   485     /// any number type and the numbers will be converted to the
   486     /// architecture word type.
   487     template <typename Iterator>
   488     Random(Iterator begin, Iterator end) { 
   489       typedef typename std::iterator_traits<Iterator>::value_type Number;
   490       _random_bits::Initializer<Number, Word>::init(core, begin, end);
   491     }
   492 
   493     /// \brief Copy constructor
   494     ///
   495     /// Copy constructor. The generated sequence will be identical to
   496     /// the other sequence. It can be used to save the current state
   497     /// of the generator and later use it to generate the same
   498     /// sequence.
   499     Random(const Random& other) {
   500       core.copyState(other.core);
   501     }
   502 
   503     /// \brief Assign operator
   504     ///
   505     /// Assign operator. The generated sequence will be identical to
   506     /// the other sequence. It can be used to save the current state
   507     /// of the generator and later use it to generate the same
   508     /// sequence.
   509     Random& operator=(const Random& other) {
   510       if (&other != this) {
   511         core.copyState(other.core);
   512       }
   513       return *this;
   514     }
   515 
   516     /// \brief Returns a random real number from the range [0, 1)
   517     ///
   518     /// It returns a random real number from the range [0, 1). The
   519     /// default Number type is double.
   520     template <typename Number>
   521     Number real() {
   522       return _random_bits::RealConversion<Number, Word>::convert(core);
   523     }
   524 
   525     double real() {
   526       return real<double>();
   527     }
   528 
   529     /// \brief Returns a random real number the range [0, b)
   530     ///
   531     /// It returns a random real number from the range [0, b).
   532     template <typename Number>
   533     Number real(Number b) { 
   534       return real<Number>() * b; 
   535     }
   536 
   537     /// \brief Returns a random real number from the range [a, b)
   538     ///
   539     /// It returns a random real number from the range [a, b).
   540     template <typename Number>
   541     Number real(Number a, Number b) { 
   542       return real<Number>() * (b - a) + a; 
   543     }
   544 
   545     /// \brief Returns a random real number from the range [0, 1)
   546     ///
   547     /// It returns a random double from the range [0, 1).
   548     double operator()() {
   549       return real<double>();
   550     }
   551 
   552     /// \brief Returns a random real number from the range [0, b)
   553     ///
   554     /// It returns a random real number from the range [0, b).
   555     template <typename Number>
   556     Number operator()(Number b) { 
   557       return real<Number>() * b; 
   558     }
   559 
   560     /// \brief Returns a random real number from the range [a, b)
   561     ///
   562     /// It returns a random real number from the range [a, b).
   563     template <typename Number>
   564     Number operator()(Number a, Number b) { 
   565       return real<Number>() * (b - a) + a; 
   566     }
   567 
   568     /// \brief Returns a random integer from a range
   569     ///
   570     /// It returns a random integer from the range {0, 1, ..., b - 1}.
   571     template <typename Number>
   572     Number integer(Number b) {
   573       return _random_bits::Mapping<Number, Word>::map(core, b);
   574     }
   575 
   576     /// \brief Returns a random integer from a range
   577     ///
   578     /// It returns a random integer from the range {a, a + 1, ..., b - 1}.
   579     template <typename Number>
   580     Number integer(Number a, Number b) {
   581       return _random_bits::Mapping<Number, Word>::map(core, b - a) + a;
   582     }
   583 
   584     /// \brief Returns a random integer from a range
   585     ///
   586     /// It returns a random integer from the range {0, 1, ..., b - 1}.
   587     template <typename Number>
   588     Number operator[](Number b) {
   589       return _random_bits::Mapping<Number, Word>::map(core, b);
   590     }
   591 
   592     /// \brief Returns a random non-negative integer
   593     ///
   594     /// It returns a random non-negative integer uniformly from the
   595     /// whole range of the current \c Number type.  The default result
   596     /// type of this function is unsigned int.
   597     template <typename Number>
   598     Number uinteger() {
   599       return _random_bits::IntConversion<Number, Word>::convert(core);
   600     }
   601 
   602     unsigned int uinteger() {
   603       return uinteger<unsigned int>();
   604     }
   605 
   606     /// \brief Returns a random integer
   607     ///
   608     /// It returns a random integer uniformly from the whole range of
   609     /// the current \c Number type. The default result type of this
   610     /// function is int.
   611     template <typename Number>
   612     Number integer() {
   613       static const int nb = std::numeric_limits<Number>::digits + 
   614         (std::numeric_limits<Number>::is_signed ? 1 : 0);
   615       return _random_bits::IntConversion<Number, Word, nb>::convert(core);
   616     }
   617 
   618     int integer() {
   619       return integer<int>();
   620     }
   621     
   622     /// \brief Returns a random bool
   623     ///
   624     /// It returns a random bool
   625     bool boolean() {
   626       return _random_bits::BoolConversion<Word>::convert(core);
   627     }
   628 
   629     /// \brief Returns a random bool
   630     ///
   631     /// It returns a random bool with given probability of true result
   632     bool boolean(double p) {
   633       return operator()() < p;
   634     }
   635     
   636   };
   637 
   638 
   639   extern Random rnd;
   640 
   641 }
   642 
   643 #endif