11

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);
}

おそらくそれは実際の関数呼び出しだからです。しかし、明らかにこれは元のメルセンヌツイスターからの状態を維持しません。何が得られますか?グローバル変数なしで私がやろうとしていることをする方法はありますか?

4

4 に答える 4

13

コメントの中で、ロバート・グールドは後世のための実用的なバージョンを求めました:

#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);
}
于 2008-09-29T03:42:31.137 に答える
11

C ++ 03では、関数ローカルタイプに基づいてテンプレートをインスタンス化することはできません。randクラスを関数の外に移動すると、正常に機能するはずです(免責事項:テストされていません。他の不吉なバグがある可能性があります)。

この要件はC++0xで緩和されましたが、変更がGCCのC ++ 0xモードで実装されているかどうかはまだわかりません。また、他のコンパイラーにこの要件が存在することに非常に驚いています。

于 2008-09-29T03:29:36.160 に答える
5

ここでは 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);
于 2010-03-16T19:55:09.380 に答える