1 /// <要約> 2 /// エイリアス别名算法 3 /// </要約> 4つの パブリック クラスAliasMethod 5 { 6 / * 確率とエイリアステーブル。* / 7 プライベート int型[] _alias。 8 プライベート ダブル[] _probability。 9 10 パブリック AliasMethod(一覧<ダブル> 確率) 11 { 12 13 / * 確率とエイリアステーブルに領域を割り当てます。* / 14 _probability = 新しい ダブル[probabilities.Count]。 15 _alias = 新しい INT [probabilities.Count]。 16 17 / * 計算平均確率と、後で使用するためにそれをキャッシュします。* / 18 ダブル平均= 1.0 / probabilities.Count。 19 20 / * 我々は、テーブルを移入としてワークリストとして動作するように2つのスタックを作成します。* / 21 のvar小さな= 新しいスタック< 整数 > (); 22 VAR大= 新しいスタック<整数 > (); 23 24 / * 入力確率でスタックを移入します。* / 25 のために(INTは iは= 0 ; I <probabilities.Count; ++ I) 26 { 27 / * 確率が平均確率を下回っている場合、我々は、追加 28の 小さなリストに*こと。そうでない場合は、我々は大規模なリストに追加します。 29 * / 30 であれば(確率[I]> = 平均) 31 large.Push(I)。 32 他 33 small.Push(I); 34 } 35 36 / * 注意点としては:アルゴリズムの数学的な仕様では、我々は 37 *は、常に大きなリストの前に小さなリストを排出します。しかし、 38 浮動小数点の不正確さに起因する*、これは必ずしも真実ではありません。 39 *したがって、(大小のペアリングしようと、この内側ループ 40 *の要素)は、両方のリストが空でないことを確認しなければなりません。 41 * / 42 ながら(small.Count> 0 && large.Count> 0 ) 43 { 44 / *は、小規模および大規模な確率のインデックスを取得します。* / 45 INT少ない= small.Pop()。 46 INTより= large.Pop()。 47 48 / * これらの確率はまだようになるようにスケールアップされていない 49 * 1 / nの重み1.0が与えられます。私たちは、代わりにここにこれを行います。 50 * / 51 _probability [縮小] =確率[縮小] * probabilities.Count。 52 _alias [縮小] = 以上; 53 54 / *適切で大きい方の確率を減少させる 55 *量。 56 * / 57 の確率[全] =(確率[全] +確率[縮小] - 平均値)。 58 59 / * 新しい確率が平均よりも小さい場合、にそれを追加 60 *小さなリスト。それ以外の場合は大規模なリストに追加します。 61 * / 62 であれば(確率[全]> = 平均) 63 large.Push(複数) 64 他 65 small.Push(もっと); 66 } 67 68 / * この時点で、すべてがいることをどの手段、1つのリストにある 69の *残りの確率は、すべてのn / 1にする必要があります。これに基づき、それらを設定する 70 *適切に。数値の問題のために、我々は確認することはできません 71 我々は両方を空にして*スタックは、エントリを保持します。 72 * / 73 ながら(small.Count> 0 ) 74 _probability [small.Pop()] = 1.0 。 75 一方(large.Count> 0 ) 76 _probability [large.Pop()] = 1.0 。 77 } 78 79 / * * 80 *サンプル基礎となる分布からの値。 81 * 82 下地分布からサンプリング* @return Aランダム値。 83 * / 84 パブリック INT )(次の 85 { 86 87 長いティック= DateTime.Now.Ticks。 88 のvarシード=((int型)(ダニ&0xffffffffL)|(int型)(ダニ>> 32 )); 89 未確認 90 { 91 種=(シード+ Guid.NewGuid()メソッドGetHashCode()+。新しいランダム()次(0、100 )); 92 } 93 VARランダム= 新しいランダム(シード) 94 int型のカラム= random.Next(_probability.Length)。 95 96 / * 選択するためにどのオプションを決定するためにバイアスコイントスを生成します。* / 97 BOOL coinToss = random.NextDouble()< _probability [列]。 98 99 リターン coinToss?カラム:_alias [列]。 100 } 101 }
初期化:
VAR別名= 新新 AliasMethod(nList.Select(= O>(ダブル)o.probability).ToList()); // 初期化aliasMethod例、パッシングリストの確率
使用します。
VaRの列= alias.next(); // ランダムに、一覧着信ビルダー確率インデックスを返します