Mat*_*200 30 c++ random mersenne-twister c++11 random-seed
我正在研究一个运行蒙特卡罗模拟的程序; 具体来说,我正在使用Metropolis算法.该程序需要产生数十亿的"随机"数字.我知道梅森捻线机在蒙特卡罗模拟中非常受欢迎,但我想确保以最佳方式播种发电机.
目前我正在使用以下方法计算32位种子:
mt19937_64 prng; //pseudo random number generator
unsigned long seed; //store seed so that every run can follow the same sequence
unsigned char seed_count; //to help keep seeds from repeating because of temporal proximity
unsigned long genSeed() {
return ( static_cast<unsigned long>(time(NULL)) << 16 )
| ( (static_cast<unsigned long>(clock()) & 0xFF) << 8 )
| ( (static_cast<unsigned long>(seed_count++) & 0xFF) );
}
//...
seed = genSeed();
prng.seed(seed);
Run Code Online (Sandbox Code Playgroud)
我有一种感觉,有更好的方法来确保不重复的新种子,我很确定mt19937_64可以播种超过32位.有没有人有什么建议?
Pra*_*ian 25
使用std::random_device产生的种子.它将提供非确定性随机数,只要您的实现支持它.否则允许使用其他随机数引擎.
std::mt19937_64 prng;
seed = std::random_device{}();
prng.seed(seed);
Run Code Online (Sandbox Code Playgroud)
operator()的std::random_device返回unsigned int,所以如果你的平台有32位intS,和你想有一个64位的种子,你需要两次调用它.
std::mt19937_64 prng;
std::random_device device;
seed = (static_cast<uint64_t>(device()) << 32) | device();
prng.seed(seed);
Run Code Online (Sandbox Code Playgroud)
另一个可用选项是std::seed_seq用于播种PRNG.这允许PRNG调用seed_seq::generate,其在[0≤i<2 32 ]的范围内产生非偏置序列,其输出范围足够大以填充其整个状态.
std::mt19937_64 prng;
std::random_device device;
std::seed_seq seq{device(), device(), device(), device()};
prng.seed(seq);
Run Code Online (Sandbox Code Playgroud)
我正在调用random_device4次来创建一个4元素的初始序列seed_seq.但是,就初始序列中元素的长度或来源而言,我不确定最佳做法是什么.
让我们回顾一下(也是注释),我们想生成不同的种子,以在以下每种情况下获得独立的随机数序列:
1是从纪元以来使用时间来解决的,2是通过全局原子计数器来解决的,3是通过平台相关的id来解决的(请参阅如何以跨平台的方式获取(几乎)唯一的系统标识符?)
现在的重点是,将它们组合成uint_fast64_t的种子类型的最佳方法是什么std::mt19937_64?我在这里假设我们不知道每个参数的范围是先验的,或者它们太大,以至于我们不能只是简单地通过移位来获得唯一的种子。
A std::seed_seq是最简单的方法,但是它的返回类型uint_least32_t不是我们的最佳选择。
一个好的64位哈希器是一个更好的选择。STL std::hash在functional标题下提供了一种可能性,可以将上面的三个数字连接成一个字符串,然后将其传递给哈希器。返回类型是size_t在64台机器上很可能符合我们要求的返回类型。
冲突不太可能发生,但当然有可能发生,如果您要确保不要建立包含一个以上序列的统计信息,则只能存储种子并丢弃重复的运行。
std::random_device也可以使用A 生成种子(冲突可能仍然会发生,很难说是多多少少),但是由于实现依赖于库,并且可能会归结为伪随机生成器,因此必须检查A的熵避免使用零熵设备,因为您可能会破坏上面的几点(尤其是第3点)。不幸的是,只有将程序带到特定计算机上并使用已安装的库进行测试时,才能发现熵。