【问题标题】:Seed sequence initialization in initialization list初始化列表中的种子序列初始化
【发布时间】:2015-01-20 18:33:31
【问题描述】:

我目前正在尝试实现一个使用接受拒绝方法的随机数生成器(类)。因此,我需要不同的 C++11 随机数分布(在我的情况下是正态分布和均匀分布)。我想让随机数尽可能好,因此想使用以下来构建函数:

 [...]
 #include <random>
 #include <vector>
 [...]
 std::vector<int> seeds(16);   
 std::mt19937 mt;
 std::minstd_rand seed_rng(101); // random seed  
 for(size_t i=0;i<16;++i) seeds[i]=seed_rng();
 std::seed_seq seq(seeds.begin(), seeds.end());
 mt.seed(seq);
 rng_normal = std::bind(ndist, std::ref(mt));
 [...]

这非常有效。但是当我现在尝试将所有这些都放在构造函数中时,我不能再使用种子序列的初始化了。我检查了 c++ 参考,但只遇到了 std::seed_seq::generate,这不是正确的解决方案。
有没有办法在填充向量后在我的初始化列表中构造种子序列? 有关 seed_seq 的参考,请参见此处:
http://en.cppreference.com/w/cpp/numeric/random/seed_seq
感谢您的任何建议!

【问题讨论】:

  • 将此代码放入构造函数有什么问题?或者您是在问您可以在初始化列表中完成所有事情吗?
  • @Praetorian 是的,对不起。我想在初始化列表中完成所有工作。

标签: c++ c++11 random-seed


【解决方案1】:

假设您对保留用于构造 mt19937seed_seq 实例不感兴趣,您可以执行以下操作:

 struct foo
 {
    std::mt19937 mt;
    std::normal_distribution<> ndist;
    std::function<decltype(mt)::result_type()> rng_normal;

    foo()
    : mt{make_mersenne_twister()}
    , rng_normal{std::bind(ndist, std::ref(mt))}
    {}

    static std::mt19937 make_mersenne_twister()
    {
        std::minstd_rand seed_rng(std::random_device{}()); // random seed
        std::vector<int> seeds(16);

        std::generate(seeds.begin(), seeds.end(), seed_rng);

        std::seed_seq seq(seeds.begin(), seeds.end());
        return std::mt19937{seq};
    }
 };

我将您的种子 (101) 替换为 std::random_device

保留seed_seq 的问题在于它既不可复制也不可移动,因此不可能将其构造委托给我使用 Mersenne Twister 的函数。

Live demo

【讨论】:

  • 投票!谢谢,该解决方案实际上应该对我有用!我想我会搜索,而 seed_seq 实际上是不可移动也不可复制的,因为我想这是有原因的......
  • @LeoW。由于您是新人,并且您的评论表明我的回答有所帮助,因此我将向您指出有关 accepting a useful answer works 的常见问题解答。
【解决方案2】:

我严重怀疑你的改进是否值得。 std::mt19937 的单值(和默认)构造函数在 C++ 标准中指定。它相当于

static constexpr size_t WS = 32;
static constexpr result_type IM = 1812433253;
static constexpr result_type default_seed = 5489u;

explicit mt19937(result_type value = default_seed)
{
    state[0] = value;
    for (int i = 1; i != state_size; ++i)
    {
        state[i] = i + IM * (state[i - 1] ^ (state[i - 1] >> (WS - 2)));
    }
}

因此,它使用 XOR-SHIFT 随机数生成器来填充状态数组。鉴于参与提出此播种算法的人员以及致力于将&lt;random&gt; 纳入标准的人员,我认为可以肯定地假设他们知道 std::minstd_ran 但发现上述优势为 Mersenne Twister 播种。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-05
    • 2011-08-09
    • 2015-05-22
    相关资源
    最近更新 更多