スポンサーリンク
※サイト運営にサーバーは必須です※
~ ロリポップ! はコスパのよい初心者向けサーバーです~
目次
モンテカルロシミュレーションの例
上のアニメーションはProcessingというプログラミング言語で書いています。
※シミュレーションを最初から見たい場合はページを再度読み込んでください。興味があれば、ソースコードを実際に動かしてみてください。
ソースコードは以下のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
void setup(){ size(200, 260); colorMode(RGB,256); background(255); rect(0, 0, 200, 200); } int cy = 100; int cx = 100; int radius = 100; int totalcount=0; int count=0; void draw(){ clearToWhite(); for(int i=0;i<100;i++){ totalcount++; float x = random(200); float y = random(200); if ((x - cx)*(x - cx) + (y - cy)*(y - cy) <= radius*radius) { stroke(255,0,0);//red color count+=1; } else { stroke(0,0,255);//blue color } point(x, y); } textSize(12); textAlign(CENTER); fill(0,0,0); text("pi="+count+"/"+totalcount+"×4=",width/2,220); float pi=(float)count/totalcount*4; String pi_strig=nf(pi,1,6); text(pi_strig,width/2,240); } void clearToWhite(){ noStroke(); fill(255,255,255); rect(0,200,200,50); } |
※スローバージョン
一番目のシミュレーションでは、100点ごとに描画しています。一方で、以下のシミュレーションは1点ごとに描画しているので、その分遅くなります。
ソースコードは以下のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
void setup(){ size(200, 260); colorMode(RGB,256); background(255); rect(0, 0, 200, 200); } int cy = 100; int cx = 100; int radius = 100; int totalcount=0; int count=0; void draw(){ clearToWhite(); totalcount++; float x = random(200); float y = random(200); if ((x - cx)*(x - cx) + (y - cy)*(y - cy) <= radius*radius) { stroke(255,0,0); count+=1; } else { stroke(0,0,255); } point(x, y); textSize(12); textAlign(CENTER); fill(0,0,0); text("pi="+count+"/"+totalcount+"×4=",width/2,220); float pi=(float)count/totalcount*4; String pi_strig=nf(pi,1,6); text(pi_strig,width/2,240); } void clearToWhite(){ noStroke(); fill(255,255,255); rect(0,200,200,50); } |
モンテカルロシミュレーションとは?
モンテカルロシミュレーションとは、乱数を用いたシミュレーションのことです。
解析的に解くことが不可能(または難解)な問題に対して非常に有効です。
(例1)円の面積の演算
半径1の円の面積を求めたいと考えたとする。
まず、円を囲む四角形につくります。
その四角形の中に入るように、点を落とします。
点が、円の中に入ったらカウントします。
(点が円の中に入った数)/(点を落とした数)で円の面積と四角形の面積の割合がわかります。
(点が円の中に入った数)/(点を落とした数)= (円の面積)/(四角形の面積)
最後に4を掛けます。(4は一辺が2の四角形の面積に対応します)
(円の面積)= (点が円の中に入った数)/(点を落とした数)×4
(例2)誕生日が同じペアの数 (期待値)
例えば、100人の集団を考えて、その中に同じ誕生日のペアが何組いるか考えます。
ある人の取りうる誕生日のパターンは365通りです。
別の人の取りうる誕生日のパターンも365通りです。
ある人と別の人の誕生日間に相関はありません。
そのため、この問題をまじめに考えるなら、以下の場合の数だけ考えないといけません。
365×365×365…通り
この問題をしらみつぶしで解く場合、365の100乗というあまりに大きな数字を扱う必要があります。(現在の普通のパソコンで、これだけ大きな数字を扱うのはほぼ無理でしょう)
さらに、うるう年を考え始めると問題はより複雑になります。
そこで発想を変えます。
100人の集団を用意します。
その100人に対して、乱数を用いて、誕生日を割り振ります。
そして、その中に同じ誕生日の人が何組いるかカウントします。
この手順を何度も繰り返してカウントを取ります。
最後に、平均化すれば、100人の集団の中に同じ誕生日のペアが何組(期待値)いるかわかります。
注意点
モンテカルロシミュレーションで得られる結果は、乱数を用いた近似的な解にすぎません。
厳密な解ではないので、誤差が生じます。
誤差を減らす簡単な方法は、サンプル数を増やすことです。
当然ではありますが、サンプル数を増やすとそれだけ時間がかかります。
~ギャンブルに絶対儲かる必勝法があるのだろうか?~
私(サイト主)はこの疑問に対して非常に興味を持ち、プログラミングで検証してみました。
このサイトを応援してもいいかなと思う人はぜひとも購入を検討してみてください。