如何在不使用C++ 11的情况下使用多个值初始化boost :: mt19937

use*_*315 6 c++ boost

我可以用:

boost::mt19937 gen(43);   
Run Code Online (Sandbox Code Playgroud)

这工作得很好,但如果我在使用随机数生成器之前需要超过32位的种子怎么办?有没有一种简单的方法可以将64位或128位种子放入Mersenne Twister中?

我发现了一些在生成结果之前加载多个值的示例,但没有一个代码可以工作.

这段代码有几个问题:

std::vector<unsigned int> seedv(1000, 11);
std::vector<unsigned int>::iterator i=seedv.begin();
boost::mt19937 gen2(i, seedv.end());
Run Code Online (Sandbox Code Playgroud)

首先,调用gen2()始终返回相同的值.我不知道我是怎么搞砸的.

其次,我不想要1000个种子,但是当我将它降低到600时,它会"抛出一个std :: invalid_argument的实例,并在调用种子时注释足够的元素"

这种方法可以缩短为少数种子吗?

这是另一个看起来很简单的代码示例:

std::string seedv("thisistheseed");
std::seed_seq q(seedv.begin(),seedv.end());
boost::mt19937 gen2(q);
Run Code Online (Sandbox Code Playgroud)

但它不会编译.我终于发现std :: seed_seq仅在c ++ 11中可用.我坚持使用gcc 4.7,直到我依赖的库是稳定的.

我想我可以坚持使用32位种子,但我想要更多一点.

我读过这篇文章: Boost Mersenne Twister:如何使用多个值种子?

我喜欢初始化整个矢量的想法:

mersenne_twister(seed1) ^ mersenne_twister(seed2)
Run Code Online (Sandbox Code Playgroud)

但是如果不修改Mersenne_Twister.hpp,我就没有办法做到这一点

有什么建议?

更新:还有一种方法不做!

unsigned long seedv[4];
seedv[0]=1;
seedv[1]=2;
seedv[2]=3;
seedv[3]=4;
boost::mt19937 gen2(seedv,4);
Run Code Online (Sandbox Code Playgroud)

使用正确的强制转换,这应该可行,但是我尝试过的每个强制转换都不会超过编译器.我可以使用C语言进行任何操作,但C++仍然有时会让我感到困惑......

bam*_*s53 5

使用boost::seed_seq代替std::seed_seq

更新:使用

boost::random_device rd;
boost::mt19937 eng(rd);
Run Code Online (Sandbox Code Playgroud)

boost::mt19937允许您使用最多 32 位宽度的单个值(w底层的参数boost::mersenne_twister_engine)或 624 个值的序列(n底层模板的参数)为其播种。624 是mt19937内部状态的元素数。

如果您阅读文档,您会发现这两种机制以不同的方式为引擎的状态设定种子。

  • 使用单个值播种使用该单个值的复杂函数设置引擎状态的每个元素。
  • 使用 624 个值序列进行种子设置将引擎状态的每个元素设置为准确对应的种子值。

关键是它boost::mt19937 本身不包含将任意数量的种子值映射到其内部状态中固定数量的元素的机制。它允许您直接设置状态(使用 624 个值),并且为方便起见,它提供了从单个 32 位值到完整的 624 个元素状态的内置映射。


如果要使用任意数量的输入种子值,则需要实现从任意大小的序列到 624 个元素状态的映射。

请记住,映射的设计应使得生成的内部状态对于梅森扭曲器算法而言是“良好”状态。该算法是基于移位寄存器的,并且可以受到产生相对可预测输出的内部状态的影响。单个值的内置映射旨在最大程度地减少此问题,并且您实施的任何内容也应该如此。

实现这种映射的最好方法,而不是自己进行数学分析,可能是简单地使用标准的梅森扭曲预热算法。根据对此答案的评论,std::seed_seq指定C++11来执行这样的预热。Boost includes boost::seed_seq,它大概做了同样的事情。


更新:不是使用任意数量的值来计算 624 个值的序列,您可以简单地使用 624 个随机值。如果这些值是无偏的并且均匀分布在 32 位值的范围内,那么您将不需要任何预热(好吧,除非您在天文上不走运)。

boost<random>库非常直接地支持这一点:

boost::random_device rd;
boost::mt19937 eng(rd);
Run Code Online (Sandbox Code Playgroud)

请注意,C++11<random>库不支持以这种方式播种。

  • Boost 有一个 [`seed_seq`](http://www.boost.org/doc/libs/1_57_0/boost/random/seed_seq.hpp),显然是从 [1.47](http://www.boost.org/ doc/libs/1_47_0/boost/random/seed_seq.hpp)。 (4认同)

Tho*_*ell 2

标准 Mersenne Twister 的 typedef 如下:

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

第一个模板类型称为 UintType,用作种子方法的参数:

void seed(UIntType value);

因此,您可以使用预定义的 boost::mt19937_64 来获得 64 位种子。如果您想进行更多自定义,您还可以创建自己的 mersenne_twister_engine。

  • “如果您想更多地自定义它,您也可以创建自己的 mersenne_twister_engine。”...不要这样做。 (7认同)