
- プレイヤーの前にA・B・Cの3つのドアがあり、3つとも扉は閉じている。
- そのうち1つのドアの奥には景品の自動車があり、残りはハズレのヤギがいる。
- プレイヤーはドアを1つ選択する。ここではドアを開けない。
- 正解のドアを知っているモンティは、残ったドアのうちハズレのドアを開ける。
- モンティは「今なら選択を変更してもいいですよ」とプレイヤーに問いかける。
サンプル・プログラムの実行例

ランダムに1万回のドア開け試行を行い、ドアを変えない場合のアタリ確率は \( \displaystyle \frac{1}{3} \) に、変えた場合のアタリ確率は \( \displaystyle \frac{2}{3} \) に収束することが分かる。試行回数は横軸に対数目盛として示している。
この結論については。いくつかの数学的解説があるが、条件付き確率の問題として、機械学習で紹介したベイズの定理を用いるのが王道である。
サンプル・プログラム
MontyHall.php | サンプル・プログラム本体 |
バージョン | 更新日 | 内容 |
---|---|---|
1.3.0 | 2023/05/05 | グラフにフッタを追加 |
1.2 | 2022/04/17 | PHP8対応,リファラ・チェック改良 |
1.1 | 2018/06/05 | JpGraph 4.2.1対応 |
1.0 | 2018/02/11 |
準備
MontyHall.php
33: //エラー表示用フォント・ファイル名;各自の環境に合わせて
34: define('FONT', '../../../../common/font/ipagp.ttf');
35:
36: //JpGraph(各自の環境に合わせて)
37: require_once('jpgraph/jpgraph.php');
38: require_once('jpgraph/jpgraph_log.php');
39: require_once('jpgraph/jpgraph_line.php');
40:
41: //ドア識別子
42: define('DOOR_LABEL', 'ABC');
43:
44: //試行回数
45: $Counter = 10000;
ドア識別子をA・B・C・D‥‥のように増やすことも可能で、増やしたとしてもドアを変更した方がアタリ確率がアップすることが分かる。
解説:モンティ・ホール問題
MontyHall.php
133: /**
134: * モンティ・ホール問題(1回)
135: * @param なし
136: * @return array(介入なし,介入あり)
137: */
138: function MontyHall_once() {
139: $doors = array();
140: makeDoors($doors);
141:
142: //プレイヤーがドアを1つ選ぶ
143: $user = getRandomDoor($doors);
144: $doors[$user]['status'] = TRUE;
145:
146: //モンティがドアを1つ開ける
147: make_seed();
148: do {
149: $monty = getRandomDoor($doors);
150: } while ($doors[$monty]['hit'] == TRUE);
151: $doors[$monty]['status'] = TRUE;
152:
153: //プレイヤーはドアを変えない
154: if ($doors[$user]['hit']) $res0 = TRUE;
155: else $res0 = FALSE;
156:
157: //プレイヤーはドアを変える
158: $user = getRandomDoor($doors);
159: if ($doors[$user]['hit']) $res1 = TRUE;
160: else $res1 = FALSE;
161:
162: return array($res0, $res1);
163: }
冒頭に記したゲームのルールを、そのままプログラムに落とし込んである。
MontyHall.php
166: /**
167: * モンティ・ホール問題
168: * @param int $n = 試行回数
169: * @return array 確率配列
170: */
171: function MontyHall($n) {
172: $prob = array();
173: $cnt0 = 0;
174: $cnt1 = 0;
175:
176: for ($i = 0; $i < $n; $i++) {
177: list($res0, $res1) = MontyHall_once();
178: if ($res0) $cnt0++;
179: if ($res1) $cnt1++;
180: $prob[$i][0] = (double)$cnt0 / ($i + 1);
181: $prob[$i][1] = (double)$cnt1 / ($i + 1);
182: }
183:
184: return $prob;
185: }
解説:グラフを描く
MontyHall.php
187: /**
188: * グラフ描画
189: * @param array $items データ
190: * @param int $year_min 最小年
191: * @param int $year_max 最大年
192: * @return object graphオブジェクト
193: */
194: function drawGraph($items, $n) {
195: $plotdata = array();
196:
197: //プロット配列を作成
198: for ($i = 0; $i < $n; $i++) {
199: $data_x[$i] = $i; //横軸
200: $data_y0[$i] = $items[$i][0];
201: $data_y1[$i] = $items[$i][1];
202: }
203:
204: //グラフ描画処理開始
205: $graph = new Graph(600, 500, 'auto');
206: $graph->SetScale('loglin', 0.0, 1.0); //X軸:対数,Y軸:小数
207: $graph->SetBackgroundGradient('#FFFFCC','#FFFFCC', GRAD_HOR, BGRAD_MARGIN);
208:
209: //タイトル、凡例などの設定
210: $graph->img->SetImgFormat('png');
211: $graph->img->SetMargin(60, 60, 20, 40);
212: $graph->title->SetFont(FF_PGOTHIC, FS_NORMAL, 16);
213: $graph->title->Set('モンティ・ホール問題');
214: $graph->xaxis->title->SetFont(FF_PGOTHIC);
215: $graph->xaxis->SetTitle('試行回数','center');
216: $graph->yaxis->title->SetFont(FF_PGOTHIC);
217: $graph->yaxis->title->Set('当たり確率');
218: $graph->yscale->ticks->Set(0.1);
219: $graph->yaxis->SetTitleMargin(40);
220: //フッタを設定する.
221: $graph->footer->right->SetFont(FF_PGOTHIC, FS_NORMAL, 10);
222: $graph->footer->right->Set('produced by JpGraph');
223:
224: //ドアを変更しない場合
225: $plotdata[0] = new LinePlot($data_y0);
226: $plotdata[0]->SetLegend('ドアを変更しない'); //凡例
227: $graph->Add($plotdata[0]);
228:
229: //ドアを変更する場合
230: $plotdata[1] = new LinePlot($data_y1);
231: $plotdata[1]->SetLegend('ドアを変更する'); //凡例
232: $graph->Add($plotdata[1]);
233:
234: //色指定は最後に
235: $plotdata[0]->SetColor('#0000FF'); //色
236: $plotdata[0]->SetWeight(2); //太さ
237: $plotdata[1]->SetColor('#FF0000'); //色
238: $plotdata[1]->SetWeight(2); //太さ
239:
240: //凡例
241: $graph->legend->SetFont(FF_PGOTHIC); //フォント
242: $graph->legend->SetColumns(1); //表示列数
243: $graph->legend->SetPos(0.15, 0.85, 'right', 'bottom'); //位置
244:
245: return $graph;
246: }
参考サイト
- PHPとJpGraphで人口ピラミッドを表示する:ぱふぅ家のホームページ
- PHPで機械学習(その3):単純ベイズ分類機:ぱふぅ家のホームページ
- JpGraph公式サイト
(2023年5月5日)グラフにフッタを追加した。