誰かがどのようにシミュレートするために、私に教えてもらえます、(あなたが必要な回数だけ)コインを使用しては、投げると?、B∈NP(H)=P
拒否のサンプリングを使用することを考えていましたが、それを明確にすることはできませんでした。
誰かがどのようにシミュレートするために、私に教えてもらえます、(あなたが必要な回数だけ)コインを使用しては、投げると?、B∈NP(H)=P
拒否のサンプリングを使用することを考えていましたが、それを明確にすることはできませんでした。
回答:
数え切れないほど多くの解決策があるので、効率的な解決策を見つけましょう。
この背後にあるアイデアは、ベルヌーイ変数を実装する標準的な方法から始まります。一様確率変数をパラメーターと比較します。場合、リターン。それ以外の場合は返し。a / b U < a / b 1 0
-coinを一様乱数ジェネレータとして使用できます。任意の間隔内で数値均一に生成するには、コインを裏返します。頭になったら、間隔の最初の部分に均一な値再帰的に生成します。末尾の場合、間隔の最後の部分からを再帰的に生成します。ある時点で、ターゲット間隔が非常に小さくなり、そこから数値をどのように選択するかは重要ではありません。それが再帰の開始方法です。誘導によって容易に証明されるように、この手順が(任意の精度まで)均一な変量を生成することは明らかです。[ x 、y )X p X 1 − p
このアイデアは効率的ではありませんが、効率的な方法につながります。 各段階で、ある与えられた間隔から数値を描画するので、まずそれを描画する必要があるかどうかを最初に確認しませんか?ターゲット値がこの間隔の外にある場合、ランダム値とターゲットの比較結果はすでにわかっています。 したがって、このアルゴリズムは急速に終了する傾向があります。(これは、質問で要求された拒否サンプリング手順として解釈される可能性があります。)
このアルゴリズムをさらに最適化できます。 どの段階でも、実際に使用できるコインは2つあります。コインのラベルを変更することで、偶然にコインにすることができます。したがって、事前計算として、再ラベル付けにより、終了に必要なフリップの予想される回数が少なくなる方を再帰的に選択できます。 (この計算は高価なステップになる可能性があります。)
たとえば、ベルヌーイ変数を直接エミュレートするためにコインを使用することは非効率的です。平均でほぼ10回のフリップが必要です。しかし、コインを使用する場合、2回のフリップで確実に実行され、予想されるフリップの数はます。(0.01 )p = 1 − 0.0 = 0.1 1.2
詳細はこちら。
与えられたハーフオープン間隔を間隔に分割します
これは、半開区間で動作する2つの変換およびを定義します。
用語の問題として、が実数のセットである場合、式を
意味では下行きである:すべてのための。同様に、意味上部にバインドされている。
書きます。(実際、が有理数ではなく実数である場合、違いはありません。必要なのはのみです。)
次に、目的のベルヌーイパラメーターを使用して変量を生成するアルゴリズムを示します。
セットと。
while {コインをを生成します。セット 増分します。}
もし次にセット。それ以外の場合は、設定し。
説明のためにR
、関数としてのアルゴリズムの実装を次に示しますdraw
。その引数は、ターゲット値と間隔、最初はです。実装する補助関数を使用します。必要はありませんが、コインのトスの数も追跡します。ランダム変数、トスの数、および検査した最後の間隔を返します。s
s <- function(x, ab, p) {
d <- diff(ab) * p
if (x == 1) c(ab[1], ab[1] + d) else c(ab[1] + d, ab[2])
}
draw <- function(target, p) {
between <- function(z, ab) prod(z - ab) <= 0
ab <- c(0,1)
n <- 0
while(between(target, ab)) {
n <- n+1; ab <- s(runif(1) < p, ab, p)
}
return(c(target > ab[2], n, ab))
}
その使用とその精度のテストの例として、との場合を考えます。アルゴリズムを使用して値を描画し、平均(およびその標準誤差)をレポートして、使用されたフリップの平均数を示します。
target <- 0.01
p <- 0.9
set.seed(17)
sim <- replicate(1e4, draw(target, p))
(m <- mean(sim[1, ])) # The mean
(m - target) / (sd(sim[1, ]) / sqrt(ncol(sim))) # A Z-score to compare to `target`
mean(sim[2, ]) # Average number of flips
このシミュレーションでは、フリップのがヘッドでした。ターゲットのよりは低いですが、Zスコアは重要ではありません。この偏差は偶然に起因する可能性があります。フリップの平均回数は回で、10弱弱でした。私たちが使用していた場合はコインを、平均はあったであろう --stillない大幅に異なるターゲットよりも、唯一のフリップは平均的に必要とされていたであろう。
ここに解決策があります(少し厄介なものですが、それは私の最初の刺し傷です)。実際にはを無視することができ、WLOGは 1/2と仮定します。どうして?2つのバイアスされたコインフリップから公平なコインフリップを生成するための巧妙なアルゴリズムが存在します。したがって、 1/2と仮定できます。
を生成するために、2つの解決策を考えることができます(最初の解決策は自分のものではありませんが、2番目の解決策は一般化です):
公平なコインを回反転させます。頭がない場合、最初からやり直します。場合ヘッドがある(ので、最初の硬貨がヘッドであるか否かリターン本)
これは任意の値に拡張できます。書き込みバイナリ形式インチ たとえば、
コイン投げを使用して新しい2進数を作成します。から始め、頭(1)または尾(0)が表示されるかどうかに応じて数字を追加します。フリップするたびに、新しい2進数をの2進数表現と同じ桁まで比較します。最終的に2つは分岐し、が2進数より大きい場合に戻ります。p b i n (p )
Pythonの場合:
def simulate(p):
binary_p = float_to_binary(p)
binary_string = '0.'
index = 3
while True:
binary_string += '0' if random.random() < 0.5 else '1'
if binary_string != binary_p[:index]:
return binary_string < binary_p[:index]
index += 1
いくつかの証拠:
np.mean([simulate(0.4) for i in range(10000)])
約0.4(ただし速くない)
私は簡単な解決策を見つけましたが、間違いなくそれを行う方法はたくさんあります。おそらくこれよりも簡単な方法もあります。このアプローチは、次の2つのステップに分けることができます。
不当なコイン投げの手順(特定のコインとそれを投げる方法を組み合わせて確率頭を発生させる方法の組み合わせ)を与えられた2つのイベントから等しい確率で生成します。これら2つの同等の可能性のあるイベントをおよびと呼ぶことができます。[これには単純なアプローチがあり、トスとペアを取り同等の可能性が高い2つの結果を生成し、他のすべての結果は新しいペアの生成につながります。再試行するロールの。]H ∗ T ∗ H ∗ = (H 、T )T ∗ = (T 、H )
次に、シミュレーションされたフェアコインを使用して、2つの吸収状態のランダムウォークを生成します。原点からの吸収状態の距離(1つ上および1つ下)を選択することにより、たとえば、上部の吸収状態を整数の望ましい比率になるように吸収の可能性を設定できます。具体的には、あなたがで上方吸収バリア配置する場合とでより低い1(と原点からプロセスを開始)、および吸収されるまでランダムウォークを実行し、上部バリアでの吸収の確率はある。− (b − a )a
(これを示すためにここで行ういくつかの計算がありますが、再帰関係を操作することで確率をかなり簡単に得ることができます...または無限系列を合計することでそれを行うことができます...または他の方法があります。)
[self-study]
タグを追加してWikiをお読みください。質問の最後に助けを求める必要がないことに注意してください。ここに投稿するすべての人が助けを望んでいることはわかっています。