使用boost :: random作为std :: random_shuffle的RNG
时间:2020-03-06 14:51:32 来源:igfitidea点击:
我有一个程序使用boost :: random的mt19937随机数生成器。我需要执行random_shuffle并希望为此生成的随机数来自此共享状态,以便可以相对于mersenne Twister先前生成的数来确定性。
我尝试过这样的事情:
void foo(std::vector<unsigned> &vec, boost::mt19937 &state) { struct bar { boost::mt19937 &_state; unsigned operator()(unsigned i) { boost::uniform_int<> rng(0, i - 1); return rng(_state); } bar(boost::mt19937 &state) : _state(state) {} } rand(state); std::random_shuffle(vec.begin(), vec.end(), rand); }
但是我收到一个模板错误,用rand调用random_shuffle。但这有效:
unsigned bar(unsigned i) { boost::mt19937 no_state; boost::uniform_int<> rng(0, i - 1); return rng(no_state); } void foo(std::vector<unsigned> &vec, boost::mt19937 &state) { std::random_shuffle(vec.begin(), vec.end(), bar); }
可能是因为它是实际的函数调用。但是很明显,这并不能阻止原始的梅森纳扭曲者的状态。是什么赋予了?没有全局变量,有什么方法可以做我想做的事情吗?
解决方案
在C ++ 03中,我们不能基于函数本地类型实例化模板。如果将rand类从函数中移出,它应该可以正常工作(免责声明:未经测试,可能还有其他险恶的bug)。
在C ++ 0x中已经放宽了此要求,但是我不知道该更改是否已经在GCC的C ++ 0x模式中实现,并且如果在其他任何编译器中都可以看到它,我将感到非常惊讶。
在评论中,罗伯特·古尔德(Robert Gould)要求提供后代的工作版本:
#include <algorithm> #include <functional> #include <vector> #include <boost/random.hpp> struct bar : std::unary_function<unsigned, unsigned> { boost::mt19937 &_state; unsigned operator()(unsigned i) { boost::uniform_int<> rng(0, i - 1); return rng(_state); } bar(boost::mt19937 &state) : _state(state) {} }; void foo(std::vector<unsigned> &vec, boost::mt19937 &state) { bar rand(state); std::random_shuffle(vec.begin(), vec.end(), rand); }
我在这里使用tr1而不是boost :: random,但是应该没什么大不了的。
以下内容有些棘手,但可以。
#include <algorithm> #include <tr1/random> std::tr1::mt19937 engine; std::tr1::uniform_int<> unigen; std::tr1::variate_generator<std::tr1::mt19937, std::tr1::uniform_int<> >gen(engine, unigen); std::random_shuffle(vec.begin(), vec.end(), gen);