2013-03-19 2 views
40

多くの擬似乱数ジェネレータは、「ウォームアップ」するために多くのサンプルが必要です。 std :: random_deviceを使用してstd :: mt19937をシードする場合、または構築後に準備ができていると期待できますか?問題のコード:std :: mt19937にウォームアップが必要ですか?

#include <random> 
std::random_device rd; 
std::mt19937 gen(rd()); 
+7

?私はそれを聞いたことがありません、私が知っているのは、彼らが播種すべきだということです。... – PlasmaHH

+0

たとえば、この論文では、いくつかの議論があります:http://www.cs.ucl.ac.uk/staff/d。 jones/GoodPracticeRNG.pdf – Brent

+1

PRNGの大部分については、これはまったく意味がありません。種まきは内部状態を設定し、内部状態をすべて「ウォーミングアップ」すると、この新しい状態が種として選択されたのとまったく同じ効果があります。 – PlasmaHH

答えて

51

メルセンヌツイスターはシフトですレジスタベースのpRNG(擬似乱数ジェネレータ)であるため、内部状態が十分に混合されるまで、比較的予測可能な結果につながる0または1の長いランで不良なシードが発生します。

しかし、単一の値をとるコンストラクタは、そのような「不良」状態を生成する可能性を最小限に抑えるように設計されたシード値に対して複雑な関数を使用します。 を初期化するもう一つの方法は、SeedSequenceのコンセプトに従ったオブジェクトを使って内部状態を直接設定する方法です。この2番目の初期化方法は、「良い」状態の選択やウォームアップの実行を心配する必要があるかもしれません。


標準はseed_seqと呼ばれるSeedSequenceコンセプトに準拠したオブジェクトが含まれています。 seed_seqは任意の数の入力シード値をとり、これらの値に対して特定の操作を実行して、pRNGの内部状態を直接設定するのに適した異なる値のシーケンスを生成します。

は、ここで全体std::mt19937状態を満たすのに十分なランダムなデータでシード配列をアップロードの例です:

std::array<int, 624> seed_data; 
std::random_device r; 
std::generate_n(seed_data.data(), seed_data.size(), std::ref(r)); 
std::seed_seq seq(std::begin(seed_data), std::end(seed_data)); 

std::mt19937 eng(seq); 

これは、全体の状態がランダム化されることを保証します。また、各エンジンは、seed_sequenceから読み取るデータの量を指定するので、使用するエンジンの情報を見つけるためにドキュメントを読むことができます。

ここでは、seed_seqを完全にstd::random_deviceからロードしていますが、特にランダムではない数のほうがうまくいくように、seed_seqが指定されています。例えば:Cubbi以下のコメントで

std::seed_seq seq{1, 2, 3, 4, 5}; 
std::mt19937 eng(seq); 

はあなたのためのウォームアップ・シーケンスを実行することによりseed_seq作品ということを示しています。

はここで播種のためのあなたの「デフォルト」のあるべき姿だ:

あなたはそれを読みました
std::random_device r; 
std::seed_seq seed{r(), r(), r(), r(), r(), r(), r(), r()}; 
std::mt19937 rng(seed); 
+2

デフォルトでは、C++ 11の 'seed_seq' *はMersenne Twisterウォーミングアップシーケンスです(例えば、既存の実装では、libC++の' mt19937'は単一値のシードが与えられたときにウォーミングアップがより簡単になります)。 – Cubbi

+1

'std :: generate_n'は新しいMSVCコンパイラでSDL Warning C4996を生成するので、代わりに 'std :: generate(seed_data.begin()、seed_data.end()、std :: ref(r));'を使うことができます。 – NightElfik

+0

ジェネレータの 'state_size'は常に' sizeof(int) 'の倍数で表現されると仮定するのは安全でしょうか?たとえば、ジェネレータのバイト数を 'state_size'とした場合、' seed_data'配列は大きすぎます。 – Wyzard

2

私は非最適シーケンスになりMTが「不十分」播種することができるような状況があると信じています。私が正しく覚えていれば、すべてのゼロを播種することがそのようなケースの1つです。これがあなたにとって重大な問題である場合は、WELLジェネレータを使用することをお勧めします。私は彼らがより柔軟であると信じています - 種子の品質はあまり重要ではありません。 (おそらくあなたの質問にもっと直接的に答えてください:ジェネレーションを最適な状態にするためにサンプルを生成するのが難しいかもしれません)

関連する問題