2015-10-08 9 views
10

Mersenne Twister C++ 11のど​​の種類が提供されているかを判断するのに問題があります。松本、西村ACM論文をMersenne twister: A 623 Dimensionally Equidistributed Uniform Pseudorandom Number Generatorに見ると、著者はアルゴリズムとそのアルゴリズムの実装を提供し、それをMT19937と呼ぶ。どのMersenne TwisterにC++ 11が提供していますか?

しかし、以下の小さなプログラムでC++ 11の同じ名前のジェネレータをテストすると、私はMatsumotoとNishimuraのMT19937で作成されたストリームを再現できません。ストリームは、生成された最初の32ビットワードとは異なります。

どのMersenne TwisterにC++ 11が提供していますか?


以下のプログラムはGCC、-std=c++11とGNUのstdlibc++を使用してのFedora 22で実行しました。

自分の論文にリンクされていると我々は見ている場合MT19937が、それは彼らが同じであるように見えますが、焼戻しの追加の層を加え、標準的な初期化乗数

で定義されてからMT19937を見る

std::mt19937 prng(102013); 
for (unsigned int i = 0; i <= 625; i++) 
{ 
    cout << std::hex << prng(); 

    if(i+1 != 625) 
     cout << ","; 

    if(i && i%8 == 0) 
     cout << endl; 
} 
+0

Boost.Randomの[header](http://www.boost.org/doc/libs/release/boost/random/mersenne_twister.hpp)を見ると、次のように書かれています。 2005年4月に[弱点](http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html)*に対処するために変更されました。その変更が行われる前に公開された論文の結果を比較しているのでしょうか? – Praetorian

+0

@Praetorian - まあ、わかりませんが、私はそう信じていません。私はブーストを使用していません。むしろ、私は 'libstdC++ 'を介してGNUの実装を使用しています。 – jww

+0

http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/CODES/mt19937ar.cを使用しています。 IOW、@Praetorianにリンクされているもの。 –

答えて

4

【rand.predef]で定義された値で26.5.5(3)紙によって定義されたパラメータ対我々は差がどこから来ているからである

32,624,397,31,0x9908b0df,11,0xffffffff,7,0x9d2c5680,15,0xefc60000,18,1812433253 <- standard 
w ,n ,m ,r ,a   ,u ,d   ,s,b   ,t ,c   ,l ,f 
32,624,397,31,0x9908b0df,11,   ,7,0x9d2c5680,15,0xefc60000,18,   <- paper 

有します。また、標準に従ってstd::mt19937の10,000反復はそれは私がちょうどオリジナルのCの実装を抽出し、C++と比較しましたMersenne Twister with improved initialization

を提供11 C++思わ399268537

+0

32ビットバージョンでは、 'd 'の' 0xffffffff'値は実際には何の変更も起こらないことを意味します。 –

+0

元の紙では乗算器として69069が使用されています(1812433253はAR改訂版の一部です)。 – jww

+0

私は元のパラメータを使用していないので、C++が* MT19937という名前を使用してはならないと感じることはできません。 'EMT19937'、' MT19937ar'、 'eMT19937ar'などが良い選択肢でした。実際、["AR"( "Array"用)は、著者がこの変更を区別するために使用するものです](http://www.math.sci.hiroshima-u.ac.jp/~m-mat/ MT/MT2002/emt19937ar.html)をオリジナルから削除します。 – jww

1

です。

#include <iostream> 
#include <cstdio> 
#include <random> 

#define N 624 
#define M 397 
#define MATRIX_A 0x9908b0dfUL /* constant vector a */ 
#define UPPER_MASK 0x80000000UL /* most significant w-r bits */ 
#define LOWER_MASK 0x7fffffffUL /* least significant r bits */ 

static unsigned long mt[N]; /* the array for the state vector */ 
static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */ 

void init_genrand(unsigned long s) 
{ 
    mt[0]= s & 0xffffffffUL; 
    for (mti=1; mti<N; mti++) { 
     mt[mti] = 
     (1812433253UL * (mt[mti-1]^(mt[mti-1] >> 30)) + mti); 
     mt[mti] &= 0xffffffffUL; 
    } 
} 

unsigned long genrand_int32() 
{ 
    unsigned long y; 
    static unsigned long mag01[2]={0x0UL, MATRIX_A}; 

    if (mti >= N) { /* generate N words at one time */ 
     int kk; 

     if (mti == N+1) /* if init_genrand() has not been called, */ 
      init_genrand(5489UL); /* a default initial seed is used */ 

     for (kk=0;kk<N-M;kk++) { 
      y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK); 
      mt[kk] = mt[kk+M]^(y >> 1)^mag01[y & 0x1UL]; 
     } 
     for (;kk<N-1;kk++) { 
      y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK); 
      mt[kk] = mt[kk+(M-N)]^(y >> 1)^mag01[y & 0x1UL]; 
     } 
     y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK); 
     mt[N-1] = mt[M-1]^(y >> 1)^mag01[y & 0x1UL]; 

     mti = 0; 
    } 

    y = mt[mti++]; 

    y ^= (y >> 11); 
    y ^= (y << 7) & 0x9d2c5680UL; 
    y ^= (y << 15) & 0xefc60000UL; 
    y ^= (y >> 18); 

    return y; 
} 

int main() 
{ 
    init_genrand(102013); 

    std::mt19937 prng(102013); 

    for (size_t i = 0; i < 10000; ++i) { 
     if (genrand_int32() != prng()) { 
      std::cout << "ERROR" << std::endl; 
      return 1; 
     } 
    } 

    std::cout << "OK" << std::endl; 
    return 0; 
} 
+0

それでMT19937arではなく、MT19937arを提供しているようです。あれは正しいですか? – jww

+0

@jwwいいえ、正しい名前は 'MT19937'です。 'MT19937ar'はファイルの名前にすぎず、配列の初期化を追加したようです。 – Stas

+0

@jwwまた、C実装のリストもご覧ください:http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/VERSIONS/C-LANG/c-lang.html 2つのバージョン(1998年と1999年)は古くなっています。 – Stas

1

私はC++ 11は、実際にテンプレートクラスを経由して多くメルセンヌ・ツイスタを提供していることを指摘しなければならない:誰もがこれらのレバーやノブを探検する勇気を持って

template <class UIntType, 
      size_t word_size, 
      size_t state_size, 
      size_t shift_size, 
      size_t mask_bits, 
      UIntType xor_mask, 
      size_t tempering_u, 
      UIntType tempering_d, 
      size_t tempering_s, 
      UIntType tempering_b, 
      size_t tempering_t, 
      UIntType tempering_c, 
      size_t tempering_l, 
      UIntType initialization_multiplier> 
    class mersenne_twister_engine; 

場合.. 。 もちろん、これらの2つの標準的なインスタンス化があります:

using mt19937 
    = mersenne_twister_engine<uint_fast32_t, 
          32, 
          624, 
          397, 
          31, 
          0x9908b0df, 
          11, 
          0xffffffff, 
          7, 
          0x9d2c5680, 
          15, 
          0xefc60000, 
          18, 
          1812433253>; 

および64ビット版:私は人々が新しいインスタンス化を試みることができるようなRNGの品質をチェックするためのツールボックスを提供するためにいいだろうと思ってきました

using mt19937_64 
    = mersenne_twister_engine<uint_fast64_t, 
          64, 
          312, 
          156, 
          31, 
          0xb5026f5aa96619e9, 
          29, 
          0x5555555555555555, 
          17, 
          0x71d67fffeda60000, 
          37, 
          0xfff7eee000000000, 
          43, 
          6364136223846793005>; 

。 @NathanOliverのおかげで

32,624,397,31,  0x9908b0df,11,  0xffffffff,7 ,  0x9d2c5680,15,  0xefc60000,18,1812433253   <- std::mt19937 
64,312,156,31,0xb5026f5aa96619e9,29,0x5555555555555555,17,0x71d67fffeda60000,37,0xfff7eee000000000,43,6364136223846793005 <- std::mt19937_64 
w ,n ,m ,r ,a     ,u ,d     ,s ,b     ,t ,c     ,l ,f 
32,624,397,31,  0x9908b0df,11,     ,7 ,  0x9d2c5680,15,  0xefc60000,18,     <- paper 

:ここ

は、テンプレートPARMSの比較です。

関連する問題