boost :: randomをstd :: random_shuffleのRNGとして使用する
-
02-07-2019 - |
質問
boost :: randomのmt19937乱数ジェネレーターを使用するプログラムがあります。 random_shuffleを実行し、このために生成された乱数をこの共有状態から取得する必要があります。これにより、メルセンヌツイスターの以前に生成された数に関して決定論的になります。
次のようなものを試しました:
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クラスを関数の外に移動すると、正常に動作するはずです(免責事項:テストされていないため、他の不吉なバグがある可能性があります)。
この要件はC ++ 0xでは緩和されましたが、変更がGCCのC ++ 0xモードでまだ実装されているかどうかはわかりません。
他のヒント
コメントで、ロバート・グールドは後世の作業バージョンを要求しました:
#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);
}
ここではboost :: randomの代わりにtr1を使用していますが、それほど重要ではありません。
以下は少し注意が必要ですが、動作します。
#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);
標準ライブラリのみを使用するC ++ 11では、これは今やかなり簡単であると指摘する価値があると思いました。
#include <random>
#include <algorithm>
std::random_device rd;
std::mt19937 randEng(rd());
std::shuffle(vec.begin(), vec.end(), randEng);
所属していません StackOverflow