lemon/random.h
author deba
Tue, 17 Oct 2006 10:50:57 +0000
changeset 2247 269a0dcee70b
parent 2242 16523135943d
child 2257 0a9393adc747
permissions -rw-r--r--
Update the Path concept
Concept check for paths

DirPath renamed to Path
The interface updated to the new lemon interface
Make difference between the empty path and the path from one node
Builder interface have not been changed
// I wanted but there was not accordance about it

UPath is removed
It was a buggy implementation, it could not iterate on the
nodes in the right order
Right way to use undirected paths => path of edges in undirected graphs

The tests have been modified to the current implementation
     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
   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
   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
   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
   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
   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
   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