奇妙な確率
次のような問題を考えてみよう。
あなたは、コインの裏表を当てるゲームを行っている。
9回連続で表が出ているときに、次は何に賭けるべきか。
ここで、どちらかに賭ける正当な理由があるだろうか。実はこの問題は、コイントスで決めてもよいような、どうでもよい事柄なのである。
今回はParenで簡単なモンテカルロ法のプログラムを書いて、このことを検証してみたい。
コイントス
コインがとる値は表か裏の2値で、いずれも出る確率は同様に確からしいとする。
プログラムでシミュレーションするために、表と裏を真偽値に対応させよう。ランダムに真偽値を返す関数rand.bool
を用いれば、コイントスは以下のように表現できる。
(function coin-toss ()
(rand.bool))
念のため、乱数に大きな偏りがないか確認してみよう。関数simulate-cointoss
は引数で指定した回数コインを投げる。
(function simulate-cointoss (n)
(let (heads 0)
(dotimes (_ n)
(if (coin-toss) (<- heads (++ heads))))
(list :tossing n :heads heads :tails (- n heads))))
次のようにして、10万回のコイントスを試行できる。十分な回数の試行を行えばほとんど理想的なコインとして使用できるといってよいだろう。
) (simulate-cointoss 100000)
(:tossing 100000 :heads 50062 :tails 49938)
何に賭けるべきか
コインを投げる仕組みができたので、試行してみよう。関数simulate-10-heads-in-a-row
は引数で指定した回数コイン投げのゲームを行い、表に賭け続けた場合に、9回以上表が出た場合と10回以上表が出た場合の数を計数する。
(function simulate-10-heads-in-a-row (n)
(let (cc9 0 cc10 0)
(dotimes (_ n)
(let (cc 0)
(while (coin-toss)
(when (= (<- cc (++ cc)) 9)
(<- cc9 (++ cc9))
(if (coin-toss) (<- cc10 (++ cc10)))))))
(list :trials n
:_9-heads-in-a-row cc9
:_10-heads-in-a-row cc10
:probability (/ cc10 cc9))))
10万回ゲームを試行した場合は次のようになった。
) (simulate-10-heads-in-a-row 100000)
(:trials 100000 :_9-heads-in-a-row 210 :_10-heads-in-a-row 108 :probability 0.514286)
この結果は100000
回試行したうち、210
回は9回連続で表が出て、108
回は10回連続で表が出たということを表している。このことは、9回表が出た後に表が出る確率は50%らしいといってよいであろう。
つまるところ、n回目までのコイントスの結果と、n+1回目のコイントスとは独立した事象にほかならないのである。
また、この結果は「とうてい起こりそうにないことも、十分な試行が行われた場合に起きることは微塵も不思議ではない」という重大な教訓を含んでいる。
ヒストグラム
表が出続ける回数の分布は以下のような関数make-histgram
によって推定できる。
(function make-histgram (n)
(let (histogram (fill! (array 30) 0))
(dotimes (_ n)
(let (cc 0)
(while (coin-toss)
(<- cc (++ cc)))
([] histogram cc (++ ([] histogram cc)))))
histogram))
) (make-histgram 100000)
#[ 49928 25152 12398 6276 3138 1512 809 374 187 111 53 32 15 5 5 3 1 0 0 0 1 0 0 0 0 0 0 0 0 0 ]
表が出続ける回数は\( \frac{1}{2} \)ずつ減少している事が分かる。