電腦模擬與賭局
楊大緯
前言: 大家都知道電腦的計算速度相當的快, 藉助這個特性, 可以用來模擬一些複雜 的事物, 並從中發現一些規律, 從這些規律中, 或許就可以找到一些隱藏在這個複雜 事物背後的理論、 公式。
內文
假設玩家 A 和玩家 B 進行賭博, 玩家 A 有 m 元, 玩家 B 有 n 元, 然後投一個公正的 硬幣, 如果出現正面就算玩家 A 贏, 如果出現反面就算玩家 B 贏, 每一次賭注都是 1 元, 如果 A 贏則 A 有 m+ 1 元, 而 B 有 n − 1 元, 並稱此為一回合, 雙方不斷的進行賭博, 直到某一 方的錢歸零為止, 在這個賭博中, 以下有兩個問題令人感到興趣:
1. 玩家 A 和玩家 B 贏的機率各是多少?
2. 每投一次硬幣決勝負, 都稱為一回合, 平均要幾回合賭局才會結束? (某方錢輸光)
一開始思考這個問題的時候, 就會想到玩家的錢如果比對方的多, 贏的機率當然就比較大, 而且如果雙方的錢都很多的話, 就要賭很久, 自然地平均賭局結束的回合數就會變大, 為了模擬 這個情況, 所以我們用電腦語言 C++ 寫一個程式, 並藉助電腦的強大計算力, 來觀察一些規 律。 (程式碼放於文末的附錄 1)
這個程式在做什麼事情呢? 首先程式會先要求輸入玩家 A 和玩家 B 的賭金, 然後還有 輸入局數, 這裡的局數是指賭到某方沒錢了算一局, 一局結束後又重新開始下一局, 雙方賭金又 回到一開始的設定值, 在一局中, 玩家們每回合下注一塊錢進行賭博直到某方的錢輸光為止, 這 個程式會紀錄每一局發生的回合數, 並算出回合數的平均值, 還有玩家 A 和玩家 B 贏的局數, 如果把程式碼中的第一個雙斜線 “//” 刪掉, 就可以看到每一局的每一回合賭博的情況, 如果 把程式碼中第二個雙斜線 “//” 刪掉的話則可以看到每一局在第幾回結束。
用這個程式, 就輸入幾個數據來測試一下,
玩家 A: 1 元 玩家 B: 100 元 幾局: 1000000 局
在還沒有跑程式之前, 可以猜猜看, 玩家 A 和玩家 B 大概會各贏幾局? 而一局平均要幾
57
回合才會結束 ?
跑完程式的結果如下:
玩家 A 的賭金 1 玩家 B 的賭金 100 玩家 A 勝 9900 局 玩家 B 勝 990100 局
玩家 A 與 B 的初始賭金比率 0.01 玩家 A 與 B 的勝局比率 0.009999 平均一局賭 108.144890 回
進行的局數 10000 1000000 1000000 1000000
玩家 A 賭金 1 1 3 3
玩家 B 賭金 100 100 5 10
回合數的平均值 108.78 108.13 14.97 29.48 進行的局數 1000000 1000000 1000000 1000000
玩家 A 賭金 6 2 1 50
玩家 B 賭金 5 15 30 50
回合數的平均值 29.71 29.09 29.36 2621.43
如上表所示, 如果再多輸入不同的賭金, 並且局數都維持很大, 就會發現平均一局結束的 回合數接近玩家 A 和玩家 B 的賭金相乘, 而且玩家 A 與 B 的賭金比率也接近玩家 A 與 B 的勝局比率, 平均一局的回合數接近雙方賭金相乘, 這件事情相當的有趣, 以雙方賭金 1 元對 100 元為例, 有一半的機率, 一回就結束了, 剩下的很多也是耐不住波動, 幾回合就結束了, 平 均起來一局有個 20 ∼ 30 回就不錯了, 到底剩下的 70 ∼ 80 回是從哪裡生出來的? 所以又想 想會不會是賭金 1 元的玩家, 在少數幾次特別幸運, 然後一路幾乎一直贏, 把對方一半的錢都 贏過來, 雙方握有大筆賭金 50 元左右, 然後開始打持久戰, 使回合數大大的增加, 如果雙方賭 金都是 50, 那麼平均可以玩幾回呢? 輸入玩家 A: 50, 玩家 B: 50, 局數: 1000000 得到了平 均一局 2621.43 回, 這說明發生機率小, 但是一旦發生可以讓這一局撐很久, 這是輸入一些數 據、 觀察所做的一個解釋, 但是如果訴諸實際的計算呢? 我們是否可以確實證明出一局的平均 回合數就是雙方的賭金相乘呢?
玩家 A 和玩家 B 贏的機率
我們先回答第一個問題, 玩家 A 和玩家 B 贏的機率各是多少?
設一開始玩家 A 有 i 元, 玩家 B 有 m + n − i 元, 其中 i = 0, 1, 2, . . . , m + n, 並假設 玩家 A 贏的機率是 Ai, 如果玩家 A 一開始有 0 元, 則玩家 A 贏的機率是 0, 如果玩家 A 一 開始有 m + n 元, 則玩家 A 贏的機率是 1, 所以 A0 = 0, Am+n= 1, 我們要建立 Ai 之間的 關係式, 然後解方程式, 當玩家 A 有 i 元, 玩家 B 有 m + n − i 元, 賭完一回玩家 A 有 i − 1 元或是 i + 1 元, 機率各是 1
2, 玩家 A 從 i − 1 元或是 i + 1 元開始, 而贏了整局的機率分別是 Ai−1 和 Ai+1, 所以可以建立方程式, Ai = Ai−1+ Ai+1
2 , 其中 i = 1, 2, 3, . . . , m + n − 1, 將方程式改寫成 Ai− Ai−1 = Ai+1− Ai, 經過簡單的遞迴可以得到 Ai+1− Ai = A1− A0, 進行加總 m+n−1P
i=1
(Ai+1− Ai) = m+n−1P
i=1
(A1 − A0), 可以解出 A1 = 1
m+ n, 同樣地從式子
m−1P
i=1
(Ai+1− Ai) =m−1P
i=1
(A1 − A0) 出發, 可以得到 Am− A1 = (m − 1)(A1− A0), 進而推 出 Am = m
m+ n, 這個方程解告訴我們當玩家 A 有 m 元, 玩家 B 有 n 元, 玩家 A 贏的機 率是 m
m+ n, 玩家 B 贏的機率是 1 − m
m+ n = n
m+ n, 所以玩家 A 和玩家 B 贏的機率的 比值, 就是一開始的賭金的比值, 接下來我們要討論賭局平均回合數的問題, 先從一些簡單的特 例切入。
玩家 A 和 B 各有 1 元的情況
先考慮雙方都只有一塊錢的情況, 不管誰贏誰輸, 第一回合就結束了, 所以平均的回合數 是一回, 這個猜測在這個特殊的情況下成立。
玩家 A 和 B 各有 2 元的情況
初始條件 P0(2) = 1, 即一開始玩家 A 有 2 元, 一開始的狀態是唯一的, 所以機率是 1, Pk(n) 代表第 k 回玩家 A 有 n 塊錢的機率, 其中 n = 0, 1, 2, 3, 4 第一回後玩家 A 必定有 1 元或是 3 元, 其機率皆是 1
2, 但不會是 2 元, 故 P1(1) = 1
2, P1(2) = 0, P1(3) = 1
2, 第二回 合後, 玩家 A 有 0 元和 4 元的機率是 1
4, 不會發生 1 元和 3 元的狀況, 有 2 元的機率是 1 2, 故 P2(0) = 1
4, P2(1) = 0, P2(2) = 1
2, P2(3) = 0, P2(4) = 1
4 根據這些計算可以觀察到, 每 經過兩回合, 玩家有 2 元的機率會減半, 所以我可以得到 P2k(2) = 1
2k, k = 0, 1, 2, 3, . . ., 在 第 2k 回有 2 塊錢再賭兩回變成 0 塊錢或是 4 塊錢的機率各是 1
4, 所以平均回合數
=
∞
X
k=0
h(2k + 2)P2k(2) 4 × 2
i=
∞
X
k=0
(k + 1) 2k =
∞
X
n=0
∞
X
k=n
1 2k
=
∞
X
n=0
1 2n
1 1 −12
= 2
∞
X
n=0
1
2n = 2 1 1 − 12
= 4
所以玩家 A 和 B 各有兩元的情況也符合猜測。
玩家 A 和 B 各有 4 元的情況
初始條件 P0(4) = 1, 即一開始玩家 A 有 4 元, 賭兩回之後, 連贏兩回或是連輸兩回, 此 時玩家 A 有 2 元或是 6 元的機率都是 1
4, 亦或一回贏一回輸, 此時玩家 A 有 4 元的機率是1 2, 即 P2(2) = 1
4, P2(4) = 1
2, P2(6) = 1
4 再賭兩回, P4(0) = 1
16, P4(2) = 4
16, P4(4) = 6 16, P4(6) = 4
16, P4(8) = 1
16, 觀察發現從 2k − 2 回到 2k 回, 玩家 A 有 2, 4, 6 元的機率 存在著關係式, 亦即 P2k−2(2), P2k−2(4), P2k−2(6), 和 P2k(2), P2k(4), P2k(6), 存在著關係 式。(關係式如下)
P2k(2) = 1
2P2k−2(2) + 1
4P2k−2(4) P2k(4) = 1
4P2k−2(2) + 1
2P2k−2(4) + 1
4P2k−2(6) P2k(6) = 1
4P2k−2(4) + 1
2P2k−2(6)
, 其中 k = 1, 2, 3, . . .
關係式
P2k(2) P2k(4) P2k(6)
=
1 2
1 4 0 1
4 1 2
1 4 0 1
4 1 2
P2k−2(2) P2k−2(4) P2k−2(6)
, 其中 k = 1, 2, 3, . . .
進行遞迴可以得到下面的式子
P2k(2) P2k(4) P2k(6)
=
1 2
1 4 0 1
4 1 2
1 4 0 1
4 1 2
k
P0(2) P0(4) P0(6)
, (∗)
對矩陣進行對角化 (對角化的介紹請看文章後面的附錄 2)
1 2
1 4 0 1
4 1 2
1 4 0 1
4 1 2
= SDS, 其中 S =
1
2 − 1
√2 1 2
− 1
√2 0 1
√2 1
2
√1 2
1 2
,
D=
2 −√ 2
4 0 0
0 2 4 0 0 0 2 +√
2 4
, 其中 S2 = I =
1 0 0 0 1 0 0 0 1
將式子 (∗) 中的矩陣用 SDS 取代
P2k(2) P2k(4) P2k(6)
= (SDS)k
P0(2) P0(4) P0(6)
= SDkS
0 1 0
可以得到
P2k(2) = P2k(6) = −
√2 4
2 −√ 2 4
k +
√2 4
2 +√ 2 4
k
P2k(4) = 1 2
2 −√ 2 4
k +1
2
2 +√ 2 4
k
此時我們可以藉此計算平均回合數, 在第 2k 回有 2 塊錢或是 6 塊錢, 再賭兩回變成 0 塊錢或 是 8 塊錢的機率各是 1
4, 所以平均回合數
=
∞
X
k=0
(2k + 2)P2k(2) 4 +
∞
X
k=0
(2k + 2)P2k(6) 4
=
∞
X
k=0
(k + 1)h
−
√2 4
2 −√ 2 4
k +
√2 4
2 +√ 2 4
ki
此時使用公式
X∞ k=0
(k + 1)rk= X∞ n=0
X∞ k=n
rk = X∞ n=0
rn X∞ k=0
rk
= 1 1 − r
∞
X
n=0
rn= 1 (1 − r)2
= −
√2 4
1
1 − 2−4√2
2
+
√2 4
1
1 −2+4√2
2
= 16
玩家 A 和 B 各有 4 元的情況亦符合我們的猜測。
玩家 A 和 B 分別有 2 元和 6 元的情況
跟前面的算式一樣, 但初始值要改成 P0(2) = 1, P0(4) = 0, P0(6) = 0
P2k(2) P2k(4) P2k(6)
= SDkS
1 0 0
P2k(2) = 1 4
2 −√ 2 4
k + 1
2
1 2
k +1
4
2 +√ 2 4
k
P2k(4) = −
√2 4
2 −√ 2 4
k +
√2 4
2 +√ 2 4
k
P2k(6) = 1 4
2 −√ 2 4
k
− 1 2
1 2
k + 1
4
2 +√ 2 4
k
平均回合數 =
∞
X
k=0
(2k + 2)P2k(2) 4 +
∞
X
k=0
(2k + 2)P2k(6) 4 = 12
這個情況也符合我們的猜測, 在計算完這些例子以後, 讓我們對這個猜測有更深的信心了。
玩家 A 和 B 共有 m + n 元的情況
一開始我們用了跟前面一樣的方法, 寫成矩陣, 然後矩陣對角化, 但是發現在這個情況中 矩陣對角化不是一件容易的事情, 是一個複雜的計算, 所以我們改用解線性方程組的方式來求 平均回合數。
假設一開始玩家 A 有 i 元, 玩家 B 有 m + n − i 元, 平均一局的回合數為 ui, i = 0, 1, 2, . . . , m + n 且 u0 = um+n = 0, 當賭完一回合, 玩家 A 有 i − 1 元或是 i + 1 元, 機 率各是 12, 如果玩家 A 從 i − 1 元或是 i + 1 元開始, 直到整局結束, 平均回合數是 ui−1 和 ui+1 , 因此有方程式
ui = (ui−1+ 1)
2 +(ui+1+ 1)
2 , i= 1, 2, . . . , m + n − 1
我們可以將方程式改寫成 ui+1− ui = ui − ui−1− 2, for i = 1, 2, . . . , m + n − 1 然後 進行迭代 ui+1 − ui = ui − ui−1− 2 = ui−1− ui−2 − 4 = · · · = (u1 − u0) − 2i, for i= 1, 2, . . . , m + n − 1 把他們加總起來,
m+n−1
X
i=1
(ui+1− ui) =
m+n−1
X
i=1
((u1− u0) − 2i), 可以得到
um+n− u1 = (m + n − 1)(u1− u0) − 2(m + n − 1)(m + n) 2
,
其中 u0 和 um+n= 0, 進而算出 u1 = m + n − 1。
同樣地從方程式
k−1
X
i=1
(ui+1− ui) =
k−1
X
i=1
((u1− u0) − 2i),
出發, 可以算出 uk= k(m + n − k), 這個解告訴我們當玩家 A 有 k 元, 玩家 B 有 m + n − k 元, 則賭局的平均回合數是 k(m + n − k), 當 k = m 時, 即是我們要回答的, 玩家 A 有 m 元, 玩家 B 有 n 元, 賭局的平均回合數是 mn, 也就是一開始雙方的賭金相乘, 這就回答了文 章一開始問的第二個問題。
附錄 1:
#include<stdlib.h>
#include<time.h>
#include"math.h"
#include<iostream>
using namespace std;
void main() {
int i,a,b,v,g=0;
double n;
double r,s;
double m=0,p=0;
double q=0;
printf("以一方輸完所有的錢為一局\n");
printf("請輸入玩家 A 的錢\n");
cin>>r;
printf("請輸入玩家 B 的錢\n");
cin>>s;
printf("幾局?\n");
cin>>n;
srand((unsigned)time(NULL));
for(i=1;i<=n;i++) {
a=r;
b=s;
g=0;
while(a!=0&&b!=0) {
v=rand()%2;
if(v==0) {
a=a+1;
b=b-1;
} else { a=a-1;
b=b+1;
}
// printf("玩家 A:%d 玩家 B:%d\n",a,b);
g++;
q++;
}
// printf("%d 回\n",g);
if(a==0) {
p=p+1;
} else { m=m+1;
} }
printf("局數%f\n\n",n);
printf("玩家 A 的賭金%f\n\n",r);
printf("玩家 B 的賭金%f\n\n",s);
printf("玩家 A 勝%f 局\n\n",m);
printf("玩家 B 勝%f 局\n\n",p);
printf("玩家 A 與 B 的初始賭金比率%f\n\n",r/s);
printf("玩家 A 與 B 的勝局比率%f\n\n",m/p);
printf("平均一局賭%f 回\n\n",q/n);
}
上面程式碼的解說: r 和 s 是玩家 A 和玩家 B 的初始金額, n 是設定欲賭博的局數, m 和 p 紀錄了玩家 A 和 B 贏得的局數, g 是每一局所發生的回合數, q 是把每一局所發生的回 合數全部加總起來, v 在程式中代表著硬幣, 他會在每一回合隨機的出現 0 或 1, 如果 v = 0 則玩家 A 贏, 如果 v = 1 則玩家 B 贏, a 和 b 代表著玩家 A 和玩家 B 在每一回合當下所 擁有的賭金, 所以隨著每一回合的進行, a 和 b 的數值是一直不斷地在變動的。
附錄 2:
矩陣對角化是大學線性代數課程中的內容, 對角化可以用來簡化矩陣的運算, 他將方陣 A 化成 P DP−1 的樣子, 其中方陣 D 只在對角線上有非 0 的值, 其餘都是 0, 所以 Dn 相 當容易計算, 此外方陣 P 的每一行都是方陣 A 的特徵向量, 且向量間彼此線性獨立, 那麼 An= (P DP−1)n= (P DP−1)(P DP−1) · · · (P DP−1) = P DnP−1, 用這個方法 An 很容 易的就被算出來了, 更詳盡的內容可以參考 [3]。
那麼給定方陣 A 要如何做對角化呢? (以 2 × 2 的方陣來說明) 先找到相異的兩非零向量 x1
y1
!
、 x2
y2
!
使得 A = x1
y1
!
= λ1
x1
y1
!
, A x1
y1
!
= λ2
x2
y2
!
然後將其合併 A x1x2
y1 y2
!
= λ1x1λ2x2
λ1y1 λ2y2
!
= x1x2
y1 y2
! λ1 0 0 λ2
!
, 並同乘 x1x2
y1 y2
!−1
,
可以得到 A = x1x2
y1 y2
! λ1 0 0 λ2
! x1x2
y1 y2
!−1
, 其中 x1x2
y1 y2
!
就是 P , λ1 0 0 λ2
!
就是 D。
舉個實際的例子, 若 A = 1 2 4 3
!
, 則有 A 1 2
!
= 5 1 2
!
, A 1
−1
!
= −1 1
−1
! ,
將其合併並稍為改寫 A 1 1 2 −1
!
= 5 −1 10 1
!
= 1 1 2 −1
! 5 0 0 −1
!
, 同乘 1 1 2 −1
!−1
就可以得到 A = 1 1 2 −1
! 5 0 0 −1
! 1 1 2 −1
!−1
, 其中 1 1 2 −1
!−1
=
1 3
1 2 3 3 −1
3
。
結語:
我們可以借由電腦的計算, 來為模型找到一些規律、 趨勢, 雖然這並不是精確的數學證明, 可是當我們觀察到規律時, 這些規律就會給我們許多啟發, 指引我們一條道路, 也就是說, 電腦 模擬可以幫助我們猜測結果, 再利用數學方法加以證明之。
參 考資料
1. 黃文璋。《機率論》。 台北: 華泰文化, 2010。
2. Feller, William, An Introduction to Probability Theory and Its Applications, Volume I and Volume II, John Wiley and Sons, New York, 1968 and 1971.
3. Stephen H. Friedberg, Arnold J. Insel, Lawrence E. Spence, Diagonalization, Linear Algebra, Pearson Education, Inc, New Jersey, 2003, pp.245-279.
—本文作者就讀國立台灣大學數學研究所—