モンテカルロ法でサイコロ関数を検証

モンテカルロ法をご存知でしょうか?

初めての方に、ちょっとだけ私から解説をさせてください!

例えば、サイコロの目。
サイコロを振って、今出た目が3、だったとしましょう。
この時、3が出た確率は(一回しか振ってないので)100% ですが、更に何回か振ると3以外の目が出て%は下がって行きますよね。

しかし、下がるとは言っても、サイコロですからそれぞれの出目の確率は1/6。最終的には1/6…約16% に落ち着いていくはずです。

振る回数が多いほど1/6 に近くなるというところがポイントで、このように一回の出目はランダムでも、たーーくさんの回数を稼いで期待する答えを導き出すという考え方がモンテカルロ法です。

実際にこれを確かめるPerl プログラムを書いてみました。

このプログラムでは、サイコロを振る関数dicing を、何回も(ENOUGH_MANY_TO_TRY回) 振ってみて、各出目の確率が1/6 に近いか(1/6 との差が0.001 より小さいか) をテストしています。

-[dice_test.pl]---
use Test::More qw/no_plan/;
use strict;

use constant ENOUGH_MANY_TO_TRY => 1000000;

# サイコロ関数
our @dice = qw/1 2 3 4 5 6/;
sub dicing{ return $dice[ int rand @dice ]; }

# テスト
monte_carlo:{
    my %play;
    for(1..ENOUGH_MANY_TO_TRY){
        $play{&dicing} ++;			# %play に各出目の回数を保存しておく
    }

    for(values %play){
        my $delta = abs( (1/6) - ($_ / ENOUGH_MANY_TO_TRY) ); # 期待する値1/6 との差を取得
        is((0.001 > $delta), 1, "1/6 の値と、出目の確率の差が僅少か?($delta)");
    }
}
---

実行結果
% perl dice_test.pl
ok 1 - 1/6 の値と、出目の確率の差が僅少か?(0.000158666666666668)
ok 2 - 1/6 の値と、出目の確率の差が僅少か?(8.33333333333242e-06)
ok 3 - 1/6 の値と、出目の確率の差が僅少か?(1.23333333333364e-05)
ok 4 - 1/6 の値と、出目の確率の差が僅少か?(0.00018866666666667)
ok 5 - 1/6 の値と、出目の確率の差が僅少か?(0.000297666666666668)
ok 6 - 1/6 の値と、出目の確率の差が僅少か?(0.000624333333333338)
1..6

まあサイコロの各出目が1/6 ということはモンテカルロ法を持ち出すまでも無く、直感レベルで分かるわけですが、円周率πを算出(これはもともとモンテカルロ法の例としては有名)するのに使ったり、破壊力のある応用も出来るわけです。
そういう応用を知ると、大胆な考え方が上手くマッチしていて実にシビレます。

モンテカルロ法の応用例

ちょっと前になりますが、2008年11月28日(金) にYokohama.pm #3 というPerl のテクニカルトークの発表会があり、その中のモンテカルロ法の話題も興奮しました。

Perlモンテカルロ法 ?最強の○×ゲームエンジン開発?(id:jukuin2000さん)
http://en.yummy.stripper.jp/?eid=1112130

なんと、モンテカルロ法を応用してゲームのAI まで作れてしまうということなんです。
これはビックリした!
そんな興奮を、ぜひ上のBlog から、スライド資料をご覧になって味わってください。



たくさんの試行錯誤の果てに、どこかにたどり着いた。こんな味わいを、モンテカルロ法は感じさせてくれます。
「なんだよ、俺の人生みたいだな。」
ってセリフでキメる瞬間は*今*ですよ!