C++ 如何再现相同状态的随机基算法
我正在研究包含随机初始状态的算法。因此,每次运行该算法时,它的输出都不是健壮的。当我捕捉到错误的输出并想要调试它以查看问题所在时,这会让我非常头疼,因为当我再次运行它时,由于算法的随机因素,问题可能不会重新产生。我使用C++随机生成器如下:< /P>C++ 如何再现相同状态的随机基算法,c++,algorithm,c++11,random,C++,Algorithm,C++11,Random,我正在研究包含随机初始状态的算法。因此,每次运行该算法时,它的输出都不是健壮的。当我捕捉到错误的输出并想要调试它以查看问题所在时,这会让我非常头疼,因为当我再次运行它时,由于算法的随机因素,问题可能不会重新产生。我使用C++随机生成器如下:< /P> std::random_device rd; std::mt19937 rnd_generator(rd()); std::uniform_int_distribution<> rnd_distribution(
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);
};
std::随机设备rd;
标准:mt19937 rnd_发生器(rd());
std::统一内部分布rnd分布(0,数据大小-1);
自动获取随机索引=[&](){
返回rnd_分配(rnd_发生器);
};
如何模拟这个函数生成的最后一个随机序列?例如,我可以给它一些静态种子,我可以重新输入它,得到完全相同的随机序列吗?我这样问是因为我认为这是一个常见的问题,所以可能有一些好的、高效的、众所周知的方法。
std::mt19937 rnd_生成器(rd())代码>每次使用不同的随机种子对PRNG进行种子设定。如果您想在测试时使用相同的随机序列,那么您可以只硬编码一个种子,而不是使用rd()
std::mt19937 rnd_生成器(rd())代码>每次使用不同的随机种子对PRNG进行种子设定。如果您想在测试时使用相同的随机序列,那么您可以只硬编码一个种子,而不是使用rd()
将调用的结果保存到rd()
,并在下一个过程中使用该结果初始化rnd\U生成器
例如:
#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;
}
将调用的结果保存到rd()
,并在下一个过程中使用该结果初始化rnd\U生成器
例如:
#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;
}
您可以将RNG引擎打印到std::ostream
以序列化它,然后从std::istream
读取它以反序列化它。请注意,由于您使用的是std::uniform_int_distribution
,因此在使用不同的编译器时不会再现相同的数字序列。您可以将RNG引擎打印到std::ostream
以对其进行序列化,然后从std::istream
读取以对其进行反序列化。请注意,由于您使用的是std::uniform_int_distribution
,因此在使用不同的编译器时,不会再现相同的数字序列。std::mt19937
是随机性的来源。使用一致种子(我认为是uint\u least32\u t
)进行测试是有意义的,但使用random\u device()
(这是一个提供“random”uint\u least32\u t
的函数)也可以
问题是你在错误的地方创造了它。设计代码,使有趣的逻辑与随机源分离。调用调用方/类创建者的问题,并使代码可测试
大概是这样的:
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++中做的第一件事是在<代码> IrANDOM 接口中包装<代码> STD::MT1937 < /Cord>,以便我可以提供精确的指定的模拟实现。当然,这对你来说可能太过分了。尽管如此,在不拖入嘲弄库的情况下,我仍然会展示一个我们可能嘲弄的想法:
class RandallRandom : public IRandom final
{
public:
RandallRandom();
int32_t Next() { return 4; }
};
std::mt19937
是随机性的来源。使用一致种子(我认为是uint\u least32\u t
)进行测试是有意义的,但使用random\u device()
(这是一个提供“random”uint\u least32\u t
的函数)也可以
问题是你在错误的地方创造了它。设计代码,使有趣的逻辑与随机源分离。调用调用方/类创建者的问题,并使代码可测试
大概是这样的:
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++中做的第一件事是在<代码> IrANDOM 接口中包装<代码> STD::MT1937 < /Cord>,以便我可以提供精确的指定的模拟实现。当然,这对你来说可能太过分了。尽管如此,在不拖入嘲弄库的情况下,我仍然会展示一个我们可能嘲弄的想法:
class RandallRandom : public IRandom final
{
public:
RandallRandom();
int32_t Next() { return 4; }
};
那么,不要使用
随机\u设备
。使用固定种子为mt19937
播种。您没有正确播种MT。您至少需要使用std::seed\u seq
。4个字节不足以种子MT的巨大内部状态。请不要使用随机\u设备
。使用固定种子为mt19937
播种。您没有正确播种MT。您至少需要使用std::seed\u seq
。4字节不足以为MT巨大的内部状态设置种子。谢谢,这个解决方案的问题是,如果我在同一个种子上测试所有样本,一些问题可能根本不会发生。特别是,当样本集很小时,OP可能至少应该使用std::seed_seq
;即便如此,这也是次优的。MT有一个巨大的内部状态。然而,它可能是唯一的解决方案,所以我必须将它设置为静态,然后多次更改它,并在每一次测试中测试它们time@HumamHelfawi您可以使用不同的硬编码种子运行测试,以确保捕获不同的种子cases@NathanOliver是的,那是汉克斯,这个解决方案的问题是,如果我在同一个种子上测试所有样本,一些问题可能根本不会发生。特别是,当样本集很小时,OP可能至少应该使用std::seed_seq
;即便如此,这也是次优的。MT有一个巨大的内部状态。然而,它可能是唯一的解决方案,所以我必须将它设置为静态,然后多次更改它,并在每一次测试中测试它们time@HumamHelfawi您可以使用不同的硬编码种子运行测试,以确保捕获不同的种子cases@NathanOliver是的