博弈 Game 的分類維度
- Deterministic or stochastic?
- One, two, or more players?
- Zero sum?
- Perfect information (can you see the state)?
Adversarial Search
對抗搜索 Adversarial Search 關注的是 perfect information, deterministic, two players, zero-sum, alternate turns 的博弈。典型的例子有 Tic-tac-toe, chess, Go, Gomoku 等。
在雙人博弈的場景下,由於是零和游戲一方分數為正,則另一方則必為相應的負數。這樣的話,我們可以給場上的局勢統一「打分」,一方欲求最大化該分數,而另一方意圖最小化該分數。例如對 MAX 節點來說
這樣的話,我們給出 Minimax Search 的定義:
A state-space search tree. Players alternate turns
Compute each node’s minimax value: the best achievable utility against a rational (optimal) adversary
具體到算法層面,對於一個特定的節點,我們可以給出一個統一的求其值的形式
對於一個 MAX 節點來說,玩家希望最大化分數,所以肯定會選擇最有利的那一個策略(后繼中分數最高的),對於 MIN 節點同理。
Note:我們對於「局勢」的打分一般不是根據最終的結果來決定的(例如若 A 勝利則給 1,A 負則設為-1),因為受到資源的約束我們沒法搜索很深(顯然會采用 DFS,時間空間復雜度分別為 \(O(b^m )\), \(O(bm)\),對於 chess 來說,b 約為 35,m 約為 100);所以我們會給中間節點基於場上的「形勢」打分,也就是說,我們采用的是 Depth-limited search,限制了搜索深度,需要 Evaluation function 對於 non-terminal positions 評分。當然,算法給出的策略的 optimal 無法保障;我們總希望越深越好,所以可以采用 iterative deepening 的策略。對於 Evaluation function 來說,理想的顯然是返回這一狀態的真實「價值」,但其計算就會變得相當復雜,因此其體現的是 tradeoff between complexity of features and complexity of computation;對於其我們的要求有
- Utility for a win state should be higher than a tie. (correct)
- The computation of evaluation function should be efficient. (quick)
- It should be related to the chance of wining the game. (consistent)
Game Tree Pruning
當然是最有名的 Alpha-Beta Pruning 了。其想法非常簡單(然而,在具體實現中代碼有難度,所以我們詳細講一下):對於一個 MAX 節點來說,若其第一個子節點 A 返回的是 3,那么對於第二個子節點 B(注意是 MIN 節點),若 B 的第一個子節點返回的是 2,那么我們可以確定 B 的值肯定要 ≤2(因為 B 為 MIN 節點),也就必 ❤️,因此我們沒有必要繼續探索 B 的剩余子節點了。
注意到,上述是對於 MIN 節點進行的剪枝,MIN 的子節點返回的一個值與其維護的一個值(\(\alpha\))進行比較,若小於了這個值則直接將此 MIN 節點剪去不去看齊剩下的子節點。上述只是一個特例,下圖是一般情況
這里的邏輯是這樣的:在之前的例子中我們只關注了 MIN 的父 MAX 節點,事實上我們可以「看」得更遠(剪枝也就更有效率),也就是這里標識出來的兩個 MAX 節點,實際上是一條 MAX 節點序列,為什么可以這樣呢?這里要注意我們所維護的 \(\alpha\) 的含義,它是這條路徑上 MAX 節點的最優選擇。
對於 MIN 節點 n 來說,一方面,它要從它的子節點這里選出最小的那一個(Note:我們結合下圖中右邊的偽碼來看),也就是算法中的 v,若這個值小於了 \(\alpha\) ,即這條路徑上 MAX 節點的最優選擇(標紅行),那么我們直接返回 v(對於該 MIN 節點值的一個保守估計)。那么,關鍵在於 \(\alpha\) 究竟是從哪里來的呢?我們來看算法中左邊的 MAX 節點的操作(注意,對於 \(\alpha\) 的更新只在 MAX 節點進行):\(\alpha=\max(\alpha, v)\) 。分開來討論,若 1. max 取到的是 v,那么 \(\alpha\) 就表示了該 MAX 節點在 for 循環中取到的最優結果(此前的子節點中的最優結果),在下一個循環中我們在標紫行調用了子節點的 min-value,即右邊的算法;2. max 取到的 \(\alpha\) 來自本身傳入 max-value 中的那個值(這里我們結合上圖),也就是這條路徑之上的 MAX 節點的最優選擇,比如說,對於上面的那個藍色 MAX 節點 A,我們在其左孩子取到了 3,我們把這個 \(\alpha\) 值傳給了 n 的父 MAX 節點 B:老大 A 告訴小弟 B:我另一個小弟已經獻給我 3 了,你如果比這個值小就甭給我拿出來丟人了,於是 B 也會拿這個 \(\alpha\) 來給其子 MIN 節點進行剪枝(也就是右邊算法中標紅的操作)。另一方面,MIN 節點要維護一個\(\beta\) :該條路徑下 MIN 節點的最優選擇,分析和上述是相一致的。
上圖總結得真的完美,若還有不懂的再多看兩遍,或者畫一棵樹自己跑一下吧。對於 alpha-beta 剪枝我們有如下說明:1. This pruning has no effect on minimax value computed for the root. Minimax values of intermediate nodes might be wrong. 對於根節點來說,我們初始化 \(\alpha=-\infty, \beta=+\infty\) 並進行搜索,注意到 alpha-beta 剪枝僅僅是把一些肯定對結果沒有影響的節點刪去了,因此不會影響最終的值;然而,對於中層的節點來說,alpha-beta 剪枝所給出值是在減去了一些分支的情況下得到的,這樣給出的「分數」就可能不是其真值了。2. Ordering Matters 顯然,若所有可剪的分支都排在最后那么對於最終的效率就沒什么影響了,一般情況下,alpha-beta 剪枝可以Doubles solvable depth!
Uncertain Outcomes
主體就這些內容,后面介紹了一下非確定情況下的節點,增加了隨機性:例如玩家是非理性的,或游戲本身就有隨機性如 Dice,這樣的話我們可以取期望。
Utilities
這部分更多是簡單抽象的博弈中超脫了出來,畢竟這種情況是確定的理想的;事實上,相同的結果對於不同人的價值是不一樣的,也就是效用這一概念的由來。
Utilities are functions from outcomes (states of the world) to real numbers that describe an agent’s preferences
In a game, may be simple (+1/-1)
Utilities summarize the agent’s goals
Theorem: any “rational” preferences can be summarized as a utility function
注意,我們這里討論的並非上述的雙方博弈,而是 Maximum Expected Utility 算法
最后再對 Utilities 的概念做一點說明,正如定義中所說它反映的是一個人的 preferences ,相較於簡單的 outcomes 更具有現實性,例如一個不愛冒風險的人和一個賭徒的偏好是不同的。另外,很少有人的真正理性的,例如:Famous example of Allais (1953)
A: \([0.8,\$4k; 0.2,\$0]\)
B: \([1.0, \$3k; 0.0, \$0]\)C: \([0.2, \$4k; 0.8, \$0]\)
D: \([0.25, \$3k; 0.75, \$0]\)
Most people prefer B > A, C > D
然而,人是否真的是理性的呢?假若 \(U(\$0) = 0\),那么 B > A 可推出 \(U(\$3k) > 0.8 U(\$4k)\),而 C > D 則可推出 \(0.8 U(\$4k) > U(\$3k)\)——出現了兩個矛盾的結果。
一下僅僅是個人感想:我們假定 utility 正是回報,那么這里例子深刻地反映了人對於概率/數字並不敏感。對於 A 和 B,3k 和 4k 刀差別不大,我們可能出於厭惡風險的原則選 B;對於 C 和 D,兩者都有一定的風險,而我們對於 .2 和 .25 的區別並不敏感,這時候 4k 和 3k 刀的差距就顯現出來,也就更傾向於選大一點的 C(雖然這時是一個正確的選擇)。