問題描述
我讀到許多偽隨機數生成器需要許多樣本才能預熱".使用 std::random_device 播種 std::mt19937 時是這種情況,還是我們可以期望它在構建后準備就緒?有問題的代碼:
I've read that many pseudo-random number generators require many samples in ordered to be "warmed up". Is that the case when using std::random_device to seed std::mt19937, or can we expect that it's ready after construction? The code in question:
#include <random>
std::random_device rd;
std::mt19937 gen(rd());
推薦答案
Mersenne Twister 是一種基于移位寄存器的 pRNG(偽隨機數生成器),因此會受到長期運行 0 或 1 的壞種子的影響,導致相對可預測的結果,直到內部狀態足夠混合為止.
Mersenne Twister is a shift-register based pRNG (pseudo-random number generator) and is therefore subject to bad seeds with long runs of 0s or 1s that lead to relatively predictable results until the internal state is mixed up enough.
然而,采用單個值的構造函數在該種子值上使用了一個復雜的函數,該函數旨在最大限度地減少產生這種壞"狀態的可能性.還有第二種初始化 mt19937
的方法,您可以通過符合 SeedSequence 概念的對象直接設置內部狀態.這是第二種初始化方法,您可能需要關注選擇良好"狀態或進行熱身.
However the constructor which takes a single value uses a complicated function on that seed value which is designed to minimize the likelihood of producing such 'bad' states. There's a second way to initialize mt19937
where you directly set the internal state, via an object conforming to the SeedSequence concept. It's this second method of initialization where you may need to be concerned about choosing a 'good' state or doing warmup.
該標準包含一個符合 SeedSequence 概念的對象,稱為 seed_seq
.seed_seq
獲取任意數量的輸入種子值,然后對這些值執行某些操作,以生成適合直接設置 pRNG 內部狀態的不同值序列.
The standard includes an object conforming to the SeedSequence concept, called seed_seq
. seed_seq
takes an arbitrary number of input seed values, and then performs certain operations on these values in order to produce a sequence of different values suitable for directly setting the internal state of a pRNG.
以下是加載具有足夠隨機數據的種子序列以填充整個 std::mt19937
狀態的示例:
Here's an example of loading up a seed sequence with enough random data to fill the entire std::mt19937
state:
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 讀取的數據量,因此您可能需要閱讀文檔以找到您使用的任何引擎的信息.
This ensures that the entire state is randomized. Also, each engine specifies how much data it reads from the seed_sequence so you may want to read the docs to find that info for whatever engine you use.
雖然在這里我完全從 std::random_device
加載了 seed_seq,但指定了 seed_seq
以便只有幾個不是特別隨機的數字應該可以很好地工作.例如:
Although here I load up the seed_seq entirely from std::random_device
, seed_seq
is specified such that just a few numbers that aren't particularly random should work well. For example:
std::seed_seq seq{1, 2, 3, 4, 5};
std::mt19937 eng(seq);
在下面的評論中,Cubbi 表示 seed_seq
通過為您執行預熱序列來工作.
In the comments below Cubbi indicates that seed_seq
works by performing a warmup sequence for you.
以下是您的默認"播種:
Here's what should be your 'default' for seeding:
std::random_device r;
std::seed_seq seed{r(), r(), r(), r(), r(), r(), r(), r()};
std::mt19937 rng(seed);
這篇關于std::mt19937 需要預熱嗎?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!