データ発見隊

最終回 乱数思考

この記事を読むのに必要な時間:およそ 6 分

火曜日に生まれた男の子問題

先の例を少し複雑にしたものとして,⁠2人の子どもの一方が男の子で火曜日生まれの場合,もう一方も男の子である確率は?」という問題を考えてみましょう。⁠火曜日生まれ」という条件が意味不明なので,この問題の答えは1/2か1/3だと考えるのが普通ですが,あらゆる可能性をきちんと考えて計算すると確率は13/27=0.48148になることがわかります。

実際にシミュレーションするRubyプログラムは次のようになります。

trials = (ARGV.shift || 100000).to_i # 試行回数
boys = 0; girls = 0
BOY = 0; GIRL = 1

trials.times {
  # 子どもの性別と生まれた曜日をランダムにセット
  gender = []
  gender[0] = rand(2)
  gender[1] = rand(2)
  weekday = []
  weekday[0] = rand(7)
  weekday[1] = rand(7)

  # 一方が男の子で火曜日生まれだった場合だけ計算
  if (gender[0] == BOY && weekday[0] == 2) ||
      (gender[1] == BOY && weekday[1] == 2) then
    # 男の子のどちらかを選択してind1に格納
    if (gender[0] == BOY && weekday[0] == 2) &&
        (gender[1] == BOY && weekday[1] == 2) then
      ind1 = rand(2)
    elsif gender[0] == BOY && weekday[0] == 2 then
      ind1 = 0
    elsif gender[1] == BOY && weekday[1] == 2 then
      ind1 = 1
    end
    # もう一方をind2に格納
    ind2 = (ind1 == 0 ? 1 : 0)
    boys += 1 if gender[ind2] == BOY
    girls += 1 if gender[ind2] == GIRL
  end
}

puts "BOY: #{boys}"
puts "GIRL: #{girls}"
puts "Ratio: #{boys.to_f/(boys+girls)}"

実行結果は次のようになります。

% ruby kayou.rb
BOY: 6619
GIRL: 7233
Ratio: 0.477837135431707

確率は1/2より少しだけ小さな値になることがわかります。

モンティ・ホール問題

確率の見積りを誰もが間違えやすい問題として,⁠モンティ・ホール問題」が有名です。これはモンティ・ホールという司会者のゲームショー番組に由来するもので,次のようなものです。

「プレイヤーの前に3つのドアがあって,1つのドアの後ろには景品の新車が,2つのドアの後ろにはヤギ(はずれを意味する)がいる。プレイヤーは新車のドアを当てると新車がもらえる。プレイヤーが1つのドアを選択した後,モンティが残りのドアのうちヤギがいるドアを開けてヤギを見せる。

ここでプレイヤーは最初に選んだドアを,残っている開けられていないドアに変更しても良いと言われる。プレイヤーはドアを変更すべきだろうか?」

─⁠─「モンティ・ホール問題」⁠Wikipedia日本語版』
2011年1月24日 12:12(UTC)

直感的には,ドアを変更してもしなくても,当たりの確率は1/2だと思えます。

この問題は非常に勘違いしやすいものであり,有名な数学者でも間違えたという逸話が残っています。こういう問題を間違えずに解くためには,理屈を考えるだけでは不十分で,乱数を使ったシミュレーションで確認するのが確実だと思われます。

この問題を忠実に再現するRubyプログラムを書くと次のようになります。

trials = (ARGV.shift || 100000).to_i # 試行回数
fail = 0 # 当たりを引いた回数
success = 0 # ハズレを引いた回数

trials.times {
  # 0,1,2の3つのドアから当たりドアをランダムに決める
  # プレイヤーは0番のドアをもらう
  hit = []
  hit[rand(3)] = true

  # モンティ・ホールの操作
  # ランダムにドア1,2を開け,ハズレが出るまで繰り返す
  while true do
    opendoor = rand(2) + 1 # ランダムに1か2を選択
    break if ! hit[opendoor]
  end
  print "モンティは#{opendoor}番のドアを開けました。"

  if hit[0] then #
    success += 1; puts "当たりです!"
  else
    fail += 1; puts "ハズレです!"
  end
}

puts "Success: #{success}"
puts "Fail: #{fail}"
puts "Ratio: #{success.to_f/trials}"

これを実行すると,選択を変更しない場合は当たりを引く確率がおよそ1/3である(選択を変更すれば当たりを引く確率が2/3に高まる)ことが明らかになります。

% ruby monty.rb
モンティは2番のドアを開けました。ハズレです!
モンティは2番のドアを開けました。ハズレです!
モンティは2番のドアを開けました。ハズレです!
モンティは1番のドアを開けました。当たりです!
モンティは1番のドアを開けました。ハズレです!
....
モンティは1番のドアを開けました。ハズレです!
モンティは1番のドアを開けました。当たりです!
Success: 3354
Fail: 6646
Ratio: 0.3354

プログラムを見ると,モンティの行為はプレイヤーの当たりハズレに何の効果も与えていないことが明白なので,モンティが何をしても当たりの確率が1/3のまま変化しないことも明らかですが,頭の中だけで考えると確率が1/2になったように勘違いしてしまうことが多いようです。

確率の計算をするとき,少しでも根拠に疑問がある場合は,乱数を用いたシミュレーションによって確認することが有効でしょう。

著者プロフィール

増井俊之(ますいとしゆき)

慶應義塾大学教授。ユビキタス時代のインタフェース技術の研究開発に従事。

本棚.orgGyazoQuickMLFeedTVなど各種のネットサービスを運用中。

http://www.pitecan.com/