エンジンの現在の状態を追跡するために、あるランダムジェネレーターから別のランダムジェネレーターにストリームストリングを渡しています (ブーストランダムライブラリ)。これにより、任意の時点で停止して現在の状態を保存し、後で一連のコードを再現したり、続行したりできます。
同じ文字列ストリームを渡しながら別の乱数発生器を使用するまでは正常に動作します (以下で再現します)。実際の例では、クラスがランダムな順序で異なるディストリビューションを呼び出すため、2 つに異なるストリームを使用することはできません...
#ifndef RANDOM_HPP
#define RANDOM_HPP
namespace RandomG{
using namespace std;
using namespace boost::random;
int getSeed()
{
ifstream rand("/dev/urandom");
char tmp[sizeof(int)];
rand.read(tmp,sizeof(int));
rand.close();
int* number = reinterpret_cast<int*>(tmp);
return (*number);
}
void Get_Rstream(stringstream &s)
{
mt19937 randgen(getSeed());
s.clear();
s << randgen;
}
template<class distribution>
class Random
{
public:
Random(distribution nd)
{
mt19937 randgen(getSeed());
rng=new variate_generator<mt19937,distribution >(randgen, nd);
}
virtual ~Random()
{
delete rng;
}
void reset(void)
{
(*rng).distribution().reset();
}
double operator()(stringstream &s)
{
double x;
s >> (*rng).engine();
x=(*rng)();
return x;
}
variate_generator<mt19937,distribution > *rng;
};
}
#endif
したがって、これらのクラスの 2 つのインスタンスをインスタンス化すると (2 つのユニフォームの下にあるが、ユニフォームとガウスまたはその他のものである可能性があり、ランダムな順序で呼び出すことができます)。
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/normal_distribution.hpp>
#include <boost/random/variate_generator.hpp>
#include "Random.hpp"
using namespace boost::random;
using namespace std;
int main()
{
int M=20;
stringstream ss;
RandomG::Get_Rstream(ss);
string ss2=ss.str();
stringstream ss3;
ss3.clear();
ss3.str(ss.str());
boost::random::uniform_01<> N;
RandomG::Random<boost::random::uniform_01<> > *unif_rand1= new RandomG::Random<boost::random::uniform_01<> >(N);
boost::random::uniform_01<> U;
RandomG::Random<boost::random::uniform_01<> > *unif_rand2=new RandomG::Random<boost::random::uniform_01<> >(U);
(*unif_rand1).reset();
(*unif_rand2).reset();
for(int i=0;i<M;i++)
{
cout << (*unif_rand1)(ss) << " ";
}
for(int i=0;i<M;i++)
{
cout << (*unif_rand2)(ss) << " ";
}
cout <<"\\\\\\\\\\\\\\\\\\\\"<<"\n";
(*unif_rand1).reset();
(*unif_rand2).reset();
for(int i=0;i<M;i++)
{
cout << (*unif_rand1)(ss3) << " ";
}
for(int i=0;i<M;i++)
{
cout << (*unif_rand2)(ss3) << " ";
}
return 0;
}
これにより、同じ乱数の 2 つのシリーズが得られるはずですが、代わりに、 ではなく に対して同じ乱数unif_rand1
が得られunif_rand2
ます。私が理解したところから、同じ状態を2つの異なる乱数ジェネレーターに供給すると同じ結果が得られるはずですか、それとも描画間でそれらをリセットする方法がありますか?
結果:
0.525384 0.038626 0.563798 0.705042 0.725001 0.311586 0.843047 0.606338 0.163695 0.437574 \\\\\\\\\\
0.525384 0.038626 0.563798 0.705042 0.725001 0.0566288 0.93966 0.417343 0.686245 0.84118
回答やアドバイスをありがとうございます (コードは Linux で再現できるはずです)。