std :: mt19937需要预热吗?
我读过很多伪随机数生成器需要许多样例才能被“预热”。 这是什么时候使用std :: random_device种子std :: mt19937,或者我们可以期望它已经准备好后,build设? 有问题的代码:
#include <random> std::random_device rd; std::mt19937 gen(rd());
Mersenne Twister是一个基于移位寄存器的pRNG(伪随机数发生器),因此受到长时间运行0或1的糟糕的种子的影响,直到内部状态充分混合,才导致相对可预测的结果。
然而,构造函数使用一个单一的值,在该种子值上使用了一个复杂的函数,这个函数被devise用于最小化产生这种“坏”状态的可能性。 还有第二种方法来初始化mt19937
,通过符合SeedSequence概念的对象直接设置内部状态。 这是第二种初始化方法,您可能需要关注select“良好”状态或进行热身。
该标准包含一个符合SeedSequence概念的对象,称为seed_seq
。 seed_seq
采用任意数量的input种子值,然后对这些值执行某些操作,以产生适合于直接设置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中读取多less数据,因此您可能需要阅读文档以find您使用的任何引擎的信息。
虽然在这里我从std::random_device
random_device中完全加载了std::random_device
, seed_seq
指定了std::random_device
,这样只有几个不是特别随机的数字才能正常工作。 例如:
std::seed_seq seq{1, 2, 3, 4, 5}; std::mt19937 eng(seq);
在下面的注释中,Cubbi表示seed_seq
通过为您执行热身序列而工作。
以下是播种的默认设置:
std::random_device r; std::seed_seq seed{r(), r(), r(), r(), r(), r(), r(), r()}; std::mt19937 rng(seed);
我相信有些情况下,MT可能被“种植不良”,导致非最佳序列。 如果我没有记错的话,所有零都是这样的情况。 我会build议你尝试使用WELL发电机,如果这是一个严重的问题给你。 我相信他们更灵活 – 种子的质量并不重要。 (也许要更直接地回答你的问题:可能更有效地把重点放在播种上,而不是播种不好,然后试图产生一堆样品使发生器达到最佳状态。)