4

私はいくつかの場所で乱数を使用しており、通常は必要に応じて乱数ジェネレーターを構築しています。現在、私は Marsaglia Xorshift アルゴリズムを使用して、現在のシステム時刻をシードしています。今、私はこの戦略についていくつかの疑問を持っています: 複数のジェネレーターを使用する場合、ジェネレーター間の数値の独立性 (ランダム性) はシード (同じシードと同じ数値) に依存します。時間 (ns) をシードとして使用しているため、この時間が変更されるため、これは機能しますが、単一のジェネレーターを 1 つだけ使用して、シングルトンとして使用できるようにする方がよいのではないかと考えています。これにより、乱数の品質が向上しますか?

編集: 残念ながら、c++11 はまだオプションではありません

編集:より具体的に言うと、シングルトンが乱数の品質を向上させる可能性があることを示唆しているわけではありませんが、1 つのジェネレーターのみが使用され、シードされているという事実です。それ以外の場合は、異なるジェネレーターのシードが別のジェネレーターから独立 (ランダム) であることを確認する必要があります。極端な例: まったく同じ数の 2 つのジェネレーターをシードします -> それらの間にランダム性はありません

4

5 に答える 5

3

いくつかの変数があり、それぞれがランダムで、他から独立している必要があり、ランダムジェネレーターからの新しいランダム値で定期的に再割り当てされるとします。これは、モンテカルロ分析やゲームで頻繁に発生します (ただし、ゲームの厳密さはモンテカルロの場合よりもはるかに低くなります)。完全な乱数ジェネレーターが存在する場合、そのインスタンス化を 1 つ使用しても問題ありません。ジェネレーターからのn番目の疑似乱数を変数x 1に割り当て、次の乱数を変数x 2に割り当て、次の乱数をx 3に割り当て、以下同様に、最終的に変数x 1に戻します。次のサイクルで。その周り。ここに問題があります: このように使用すると、あまりにも多くの PRNG が独立性テストに失敗し、独立性テストに失敗し、個々のシーケンスのランダム性テストに失敗するものさえあります。

私のアプローチは、単一の PRNG ジェネレーターを自己完結型PRNG のNインスタンスのセットのシード ジェネレーターとして使用することです。これらの後者の PRNG の各インスタンスは、単一の変数をフィードします。自己完結型とは、PRNG がオブジェクトであり、状態が静的メンバーやグローバル変数ではなくインスタンス メンバーで維持されることを意味します。シード ジェネレーターは、他のNと同じファミリーである必要さえありません。PRNG。複数のスレッドがシードジェネレーターを同時に使用しようとする場合に備えて、再入可能である必要があります。ただし、私の使用では、再現性を保証するために、スレッド化を開始する前に PRNG をセットアップするのが最善であることがわかりました。それは 1 回の実行、1 回の実行です。モンテカルロ法では通常、数千回、場合によってはそれ以上の実行が必要です。モンテカルロでは、再現性が不可欠です。そのため、さらに別のランダム シード ジェネレーターが必要です。これは、変数のN 個のジェネレーターを生成するために使用されるシード ジェネレーターをシードします。

少なくともモンテカルロの世界では、再現性は重要です。長いモンテカルロ シミュレーションの実行番号 10234 で、大規模なエラーが発生したとします。世界で何が起こったのかを見るのはいいことです。それは統計的なまぐれだったのかもしれませんし、問題だったのかもしれません。問題は、典型的な MC セットアップでは、統計を計算するのに十分な、最小限のデータしか記録されないことです。実行番号 10234 で何が起こったかを確認するには、その特定のケースを繰り返す必要がありますが、すべてを記録します。

于 2012-10-08T10:47:50.987 に答える
1

クライアントが相互に関連しており、コードで「独立した」乱数が必要な場合は常に、ランダム ジェネレーター クラスの同じインスタンスを使用する必要があります。

クライアントが相互に依存しておらず、同じ数値を受け取るかどうかが問題にならない場合は、ランダム ジェネレーター クラスのさまざまなオブジェクトを使用できます。

テストとデバッグでは、同じ乱数列を再度作成できると非常に便利です。したがって、「ランダムにシード」しすぎてはいけません。

于 2012-10-08T09:50:58.627 に答える
0

ランダム性が高まるとは思いませんが、ランダムジェネレーターを使用するたびにオブジェクトを作成するために必要なメモリが減少します。このジェネレーターにインスタンス固有の設定がない場合は、シングルトンを作成できます。

于 2012-10-08T08:46:53.337 に答える
0

時間 (ns) をシードとして使用しているため、この時間が変更されるため、これは機能しますが、単一のジェネレーターを 1 つだけ使用して、シングルトンとして使用できるようにする方がよいのではないかと考えています。

これは、シングルトンがアンチパターンでない場合の良い例です。何らかの種類の制御の反転を使用することもできます。

これにより、乱数の品質が向上しますか?

いいえ。品質は、乱数を生成するアルゴリズムに依存します。どのように使用するかは問題ではありません (正しく使用されている場合)。

編集するには:RNGクラスのオブジェクトを保持するある種のコンテナを作成できます(または既存のコンテナを使用できます)。このようなもの :

std::vector< Rng > & RngSingleton()
{
  static std::vector< Rng > allRngs( 2 );
  return allRngs;
}

struct Rng
{
  void SetSeed( const int seen );
  int GenerateNumber() const;
//...
};

// ...
RngSingleton().at(0).SetSeed( 55 );
RngSingleton().at(1).SetSeed( 55 );
//...
const auto value1 = RngSingleton().at(0).GenerateNumber;
const auto value2 = RngSingleton().at(1).GenerateNumber;
于 2012-10-08T09:02:25.300 に答える
-1

救助への工場パターン。クライアントは、依存関係のインスタンス化規則について心配する必要はありません。作成方法を交換できます。逆に、別のアルゴリズムを使用する場合は、ジェネレーター クラスを交換でき、クライアントはリファクタリングする必要がありません。 http://www.oodesign.com/factory-pattern.html

- 編集

疑似コードを追加しました (すみません、これは C++ ではありません。私が最後に作業してからずっと前のことです)

interface PRNG{
    function generateRandomNumber():Number;
}

interface Seeder{
    function getSeed() : Number;
}

interface PRNGFactory{
    function createPRNG():PRNG;
}

class MarsagliaPRNG implements PRNG{
    constructor( seed : Number ){
        //store seed
    }

    function generateRandomNumber() : Number{
        //do your magic
    }
}

class SingletonMarsagliaPRNGFactory implements PRNGFactory{
    var seeder : Seeder;
    static var prng : PRNG;
    function createPRNG() : PRNG{
        return prng ||= new MarsagliaPRNG( seeder.getSeed() );
    }
}

class TimeSeeder implements Seeder{
    function getSeed():Number{
        return now();
    }
}

//usage:
seeder : Seeder = new TimeSeeder();
prngFactory : PRNGFactory = new SingletonMarsagliaPRNGFactory();

clientA.prng = prngFactory.createPRNG();
clientB.prng = prngFactory.createPRNG();
//both clients got the same instance.

大きな利点は、実装の詳細を変更したい場合、または変更する必要がある場合、クライアントで何も変更する必要がないことです。シーディング メソッド、RNG アルゴリズム、およびインスタンス化ルールを、どこのクライアントにも触れることなく変更できます。

于 2012-10-08T10:48:02.267 に答える