2018年11月23日金曜日

アントワーヌ・ゴンボーの疑問をPythonで検証してみる

確率論の始まりの話でよく出てくるアントワーヌ・ゴンボーの疑問

17世紀、フランスの貴族シュバリエ・ド・メレ卿(アントワーヌ・ゴンボー)という人はギャンブル好きだった。
彼は、サイコロのギャンブルが好きで、
1つのサイコロを4回投げて、6が出れば勝ちというゲームをした時は2/3の確率で勝つと考えた。
勝率は予想に届かなったが、勝ち越すことは出来た。
そして、2つのサイコロを24回投げて、6,6のゾロ目が出れば勝ちというダブルシックスも同じように、6,6のゾロ目が出る確率は1/36なのだから24回投げれば2/3で勝てるはずと考えた。
しかし、実際は予想に反してあまり勝てなかった。
そこで、ゴンボーは数学者パスカルに、何がおかしいか相談してみた。
パスカルはゴンボーの考え違いを見抜き、出る目から計算するのでなく、出ない目から計算するのが正しいと答えたそう。

さてそれをPythonで検証してみましょう。

まずは1つのサイコロから6の目が出れば勝つというゲーム
4回投げてどれくらいの確率で勝つかrandomを使って試してみましょう。

#! /usr/bin/env python

# -*- coding: utf-8 -*-

import random

print("[probability]")

#試行回数
trial = 10000

#投げる回数
roll = 4

#勝った回数
win = 0

def dice(trial, roll):
    win = 0
    reset = False
    for i in range(trial):
        reset = False
        for j in range(roll):
            if reset == False:
                #サイの目をランダムに出す
                pip = random.randrange(1, 7)
                #目が6なら勝ち
                if pip == 6:
                    win += 1
                    reset = True
    return win

win = dice(trial, roll)
print("試行回数: ", trial)
print("勝った回数: ", win)
print("勝率: ", (win / trial))


結果:
[probability]
試行回数:  10000
勝った回数:  5218
勝率:  0.5218

[probability]
試行回数:  10000
勝った回数:  5184
勝率:  0.5184

[probability]
試行回数:  10000
勝った回数:  5140
勝率:  0.514

[probability]
試行回数:  10000
勝った回数:  5144
勝率:  0.5144

[probability]
試行回数:  10000
勝った回数:  5222
勝率:  0.5222


2/3には届きませんが勝ち越すことは出来ます。
次に、2つのサイコロを24回投げ、6,6のゾロ目が出たら勝ちというゲーム


#! /usr/bin/env python

# -*- coding: utf-8 -*-

import random

print("[probability]")

#試行回数
trial = 10000

#投げる回数
roll = 24

#勝った回数
win = 0

def dice(trial, roll):
    win = 0
    #ゲームリセットフラグ
    reset = False
    for i in range(trial):
        reset = False
        for j in range(roll):
            if reset == False:
                #サイの目をランダムに出す
                pip1 = random.randrange(1, 7)
                pip2 = random.randrange(1, 7)
                #print("({}, {})".format(pip1, pip2), end=" ")
                #目が6, 6なら勝ち
                if pip1 == 6 & pip2 == 6:
                    win += 1
                    reset = True
                    #print()

    return win

win = dice(trial, roll)
print("試行回数: ", trial)
print("勝った回数: ", win)
print("勝率: ", (win / trial))


結果:

試行回数:  10000
勝った回数:  4939
勝率:  0.4939

[probability]
試行回数:  10000
勝った回数:  4997
勝率:  0.4997

[probability]
試行回数:  10000
勝った回数:  4900
勝率:  0.49

[probability]
試行回数:  10000
勝った回数:  4957
勝率:  0.4957

[probability]
試行回数:  10000
勝った回数:  4961
勝率:  0.4961

10000万回試行した結果では勝率5割を割りました。
パスカルの計算したとおりですね。
ポイントは勝った場合にゲームリセットすることです。
これが無いと一つのゲームに複数勝利することになりますので2/3に近い数字が出ます。

パスカルの計算式
1つのサイコロを4回投げて6が出たら勝つゲームの勝率
1 - (5/6) ^4 = 0.5177469

2つのサイコロを24回投げて6, 6のゾロ目が出たら勝つゲームの勝率
1 - (35/36) ^4 = 0.491403876

実際にランダムに試行した結果も計算に近い数字が出ましたね。