モンティホールのパラドックスとシミュレーション

モンティホールパラドックス



モンティホールのパラドックスは、確率論の既知の問題の1つであり、その解は一見、常識と矛盾します。 このタスクは、アメリカのテレビ番組「Let's Make a Deal」に基づいた架空のゲームの説明として定式化され、このプログラムのホストにちなんで名付けられました。 1990年にParade Magazineで発行されたこの問題の最も一般的な表現は次のとおりです。

あなたが3つのドアのいずれかを選択する必要があるゲームの参加者になったと想像してください。 1つのドアの後ろに車があり、他の2つのドアの後ろにヤギがいます。 ドアの1つ、たとえば1番を選択すると、その後、車がどこにあり、ヤギがどこにいるかを知っているホストが、残りのドアの1つ、たとえば3番を開き、その後ろにヤギがいます。 その後、選択を変更してドア番号2を選択するかどうかを尋ねられます。ホストのオファーを受け入れて選択を変更すると、車に勝つチャンスが増えますか。


解決策



この問題を解決するとき、彼らは通常、次のように推論します。リーダーがヤギの後ろにあるドアを開いた後、車は残りの2つのドアのうちの1つだけの後ろになります。 プレイヤーは車がどのドアにあるかに関する追加情報を受け取ることができないため、各ドアの後ろにある車を見つける確率は同じであり、ドアの最初の選択を変更してもプレイヤーに利点はありません。 ただし、この推論の行は間違っています。 発表者が常にどのドアの後ろにあるかを知っており、ヤギがいる後ろにある残りのドアの1つを常に開き、プレイヤーに選択を変更するように常に誘う場合、車がプレイヤーによって選択されたドアの後ろにある確率は1/3であり、したがって、車が残りのドアの後ろにある確率は2/3です。 したがって、最初の選択肢を変更すると、プレイヤーが車に勝つ可能性が2倍になります。 この結論は、ほとんどの人々による状況の直感的な認識と矛盾するため、説明されているタスクはモンティホールパラドックスと呼ばれます。

詳細は、対応するウィキペディアの記事に記載れています



モデリング



今回はなんらかの理由で抽象的な論理的思考が拒否されたため、ブルートフォースの助けを求めなければなりませんでした。シミュレーションモデルで、さらに確認しました。

スクリプトコード(PHP)。 コードのコメントは大歓迎です。

結果:

ゲーム数: 10000。

ゲーマーは6664回勝ちます。

ゲーマーは3336回失います。



 <?php $wins=0; $looses=0; $change_choice = 1; //  for ($i=1;$i<=10000;$i++){ $car_position = rand(1,3); #Let's begin #Step 1 $gamer_first_choice = rand(1,3); $showman_choice = rand(1,3); while($showman_choice==$gamer_first_choice || $showman_choice==$car_position){ $showman_choice=rand(1,3); } #echo "Car is in ".$car_position." door. Gamer choose ".$gamer_first_choice." door, showman opens ".$showman_choice." door. Continue..."; #Step 2 if ($change_choice!=0){ for($second=1;$second<=3;$second++){ if($second!=$gamer_first_choice && $second!=$showman_choice){ $gamer_second_choice = $second; //  } } } #echo "Gamer's first choice is ".$gamer_first_choice.". Showman opens ".$showman_choice." door. Gamer changes choice to ".$gamer_second_choice."."; if ($gamer_second_choice==$car_position) { #echo 'Gamer won!'; $wins++; } else { #echo 'Gamer loose.'; $looses++; } } echo "Number of games: ".$i.". Gamer wins ".$wins." times. Gamer looses ".$looses." times."; ?> 
      





<?php $wins=0; $looses=0; $change_choice = 1; // for ($i=1;$i<=10000;$i++){ $car_position = rand(1,3); #Let's begin #Step 1 $gamer_first_choice = rand(1,3); $showman_choice = rand(1,3); while($showman_choice==$gamer_first_choice || $showman_choice==$car_position){ $showman_choice=rand(1,3); } #echo "Car is in ".$car_position." door. Gamer choose ".$gamer_first_choice." door, showman opens ".$showman_choice." door. Continue..."; #Step 2 if ($change_choice!=0){ for($second=1;$second<=3;$second++){ if($second!=$gamer_first_choice && $second!=$showman_choice){ $gamer_second_choice = $second; // } } } #echo "Gamer's first choice is ".$gamer_first_choice.". Showman opens ".$showman_choice." door. Gamer changes choice to ".$gamer_second_choice."."; if ($gamer_second_choice==$car_position) { #echo 'Gamer won!'; $wins++; } else { #echo 'Gamer loose.'; $looses++; } } echo "Number of games: ".$i.". Gamer wins ".$wins." times. Gamer looses ".$looses." times."; ?>









perlの友人によって書かれた代替:


 #!/usr/bin/perl use strict; use warnings; my $iteration = 10000; my $change_choice = 1; print "\n"; print modelingMontyHall($change_choice); print "\n"; sub modelingMontyHall { my $change_choice = shift; my $success_counter = 0; my ( $i, $j ); my @doors; # 0 - animal, 1 - car my $gamer_choice; my $showman_open_door; my $result = 0; my $success_door; if ($change_choice) { print "Gamer change choice\n" } else { print "Gamer NOT change choice\n" }; for ( $i = 0 ; $i < $iteration ; $i++ ) { # Preparing @doors = ( 0, 0, 0 ); $success_door = int( rand() * 3 ); $doors[$success_door] = 1; # door with car # First step $gamer_choice = 0; for ( $j = 0 ; $j < 3 ; $j++ ) { if ( ( $j != $gamer_choice ) and ( $doors[$j] == 0 ) ) { $showman_open_door = $j; last; } } # Second step if ($change_choice) { for ( $j = 0 ; $j < 3 ; $j++ ) { if ( ( $j != $gamer_choice ) and ( $j != $showman_open_door ) ) { $gamer_choice = $j; last; } } } # Count result if ( $doors[$gamer_choice] ) { $result++; } } return $result; } 
      





#!/usr/bin/perl use strict; use warnings; my $iteration = 10000; my $change_choice = 1; print "\n"; print modelingMontyHall($change_choice); print "\n"; sub modelingMontyHall { my $change_choice = shift; my $success_counter = 0; my ( $i, $j ); my @doors; # 0 - animal, 1 - car my $gamer_choice; my $showman_open_door; my $result = 0; my $success_door; if ($change_choice) { print "Gamer change choice\n" } else { print "Gamer NOT change choice\n" }; for ( $i = 0 ; $i < $iteration ; $i++ ) { # Preparing @doors = ( 0, 0, 0 ); $success_door = int( rand() * 3 ); $doors[$success_door] = 1; # door with car # First step $gamer_choice = 0; for ( $j = 0 ; $j < 3 ; $j++ ) { if ( ( $j != $gamer_choice ) and ( $doors[$j] == 0 ) ) { $showman_open_door = $j; last; } } # Second step if ($change_choice) { for ( $j = 0 ; $j < 3 ; $j++ ) { if ( ( $j != $gamer_choice ) and ( $j != $showman_open_door ) ) { $gamer_choice = $j; last; } } } # Count result if ( $doors[$gamer_choice] ) { $result++; } } return $result; }









実行結果:

ゲーマーは選択を変更しません: 2562

ゲーマーの変更選択: 7586



PS:ところで、この特定のスクリプトを書いた後、Zendエンジンの疑似乱数ジェネレーターにある程度の不信感を抱き始めました。 PHPとPerlで実行した結果をもう一度見てください:)

PPS:コードをおaびします。 すべてが「膝の上で」行われ、読みやすさを改善するタスクは立っていませんでした。



All Articles