如何重现相同状态的基于随机的算法

时间:2015-12-09 13:48:18

标签: c++ algorithm c++11 random

我正在研究包含随机初始状态的算法。因此,每次运行时,此算法的输出都不稳健。这会给我带来很多麻烦,因为我收到错误的输出并想调试它以查看问题所在,因为当我再次运行它时,由于算法的随机因素,问题可能无法重新生成。我正在使用C ++随机生成器如下:

    std::random_device rd;
    std::mt19937 rnd_generator(rd());
    std::uniform_int_distribution<> rnd_distribution(0, data_size - 1);

    auto get_random_index = [&](){
        return rnd_distribution(rnd_generator);
    };

我如何模仿这个函数生成的最后一个随机序列?例如,我可以给它一些静态种子,我可以重新输入它并获得完全相同的随机序列吗?我在问,因为我觉得这是常见的问题所以可能有一些好的和有效的知名方式。

4 个答案:

答案 0 :(得分:6)

将调用结果保存到rd()并使用该结果在下一次传递时初始化rnd_generator

示例:

#include <iostream>
#include <random>


auto main() -> int
{
    using namespace std;

    random_device rd;
    auto seed = rd();

    for (int pass = 0 ; pass < 3 ; ++pass)
    {
        mt19937 rnd_generator(seed);
        uniform_int_distribution<> rnd_distribution(0, 9);

        for (int i = 0 ; i < 5 ; ++i)
        {
            cout << rnd_distribution(rnd_generator) << ", ";
        }
        cout << endl;
    }

    return 0;
}

示例输出:

9, 5, 3, 5, 4,
9, 5, 3, 5, 4,
9, 5, 3, 5, 4,

答案 1 :(得分:3)

std::mt19937 rnd_generator(rd());每次使用不同的随机种子为PRNG播种。如果您想在测试时使用相同的随机序列,那么您只需硬编码种子而不是使用rd()

std::mt19937 rnd_generator(0);  // each run will use the seed value of 0

答案 2 :(得分:1)

您可以将RNG引擎打印到std::ostream进行序列化,然后从std::istream读取它以对其进行反序列化。请注意,由于您使用了std::uniform_int_distribution<>,因此在使用不同的编译器时,不会重现相同的数字序列。

答案 3 :(得分:0)

std::mt19937是您随机性的来源。使用consitant种子(我认为是uint_least32_t)进行测试是有道理的,但使用random_device()(这是一个随机的&#39}的功能也很好。 ; uint_least32_t)。

问题是你在错误的地方创造它。设计你的代码,使有趣的逻辑与随机源分开。提供随机性调用者/类创建者问题称为Dependency Injection并使代码可测试。

这样的事情:

    class ThingDooer final
    {
        std::mt19937 _prng;
    public:
        // ThingDooer(uint_least32_t seed);
        // ThingDooer() : ThingDoor(std::_Random_device()) {}; // these two or
        ThingDooer(std::mt19937 prng);
        void DoThing();
    };

我在C ++(It's terrible and reads like C#)中做的第一件事就是将std::mt19937包装在IRandom接口中,以便我可以提供具有精确指定数字的模拟实现。当然,这可能对你来说太过分了。永远不会拖着嘲弄的图书馆,我仍然会想到我们可能会嘲笑的东西:

    class RandallRandom : public IRandom final
    {
    public:
        RandallRandom();
        int32_t Next() { return 4; }
    };