《對弈程式基本技術》專題

2021-04-13 07:20:21 字數 3761 閱讀 4759

alpha-beta搜尋

bruce moreland (

[email protected]) / 文

最小-最大的問題

alpha-beta 同「最小-最大」非常相似,事實上只多了一條額外的語句。最小最大執行時要檢查整個博弈樹,然後盡可能選擇最好的線路。這是非常好理解的,但效率非常低。每次搜尋更深一層時,樹的大小就呈指數式增長。

通常乙個西洋棋局面都有35個左右的合理著法,所以用最小-最大搜尋來搜尋一層深度,就有35個局面要檢查,如果用這個函式來搜尋兩層,就有352個局面要搜尋。這就已經上千了,看上去還不怎樣,但是數字增長得非常迅速,例如六層的搜尋就接近是二十億,而十層的搜尋就超過兩千萬億了。

要想通過檢查搜尋樹的前面幾層,並且在葉子結點上用啟發式的評價,那麼做盡可能深的搜尋是很重要的。最小-最大搜尋無法做到很深的搜尋,因為有效的分枝因子實在太大了。

口袋的例子

幸運的是我們有辦法來減小分枝因子,這個辦法非常可靠,實際上這樣做絕對沒有壞處,純粹是個有益的辦法。這個方法是建立在乙個思想上的,如果你已經有乙個不太壞的選擇了,那麼當你要作別的選擇並知道它不會更好時,你沒有必要確切地知道它有多壞。有了最好的選擇,任何不比它更好的選擇就是足夠壞的,因此你可以撇開它而不需要完全了解它。只要你能證明它不比最好的選擇更好,你就可以完全拋棄它。

你可能仍舊不明白,那麼我就舉個例子。比如你的死敵面前有很多口袋,他和你打賭賭輸了,因此他必須從中給你一樣東西,而挑選規則卻非常奇怪:

每個口袋裡有幾件物品,你能取其中的一件,你來挑這件物品所在的口袋,而他來挑這個口袋裡的物品。你要趕緊挑出口袋並離開,因為你不願意一直做在那裡翻口袋而讓你的死敵盯著你。

假設你一次只能找乙隻口袋,在找口袋時一次只能從裡面摸出一樣東西。

很顯然,當你挑出口袋時,你的死敵會把口袋裡最糟糕的物品給你,因此你的目標是挑出「諸多最糟的物品當中是最好的」那個口袋。

你很容易把最小-最大原理運用到這個問題上。你是最大一方棋手,你將挑出最好的口袋。而你的死敵是最小一方棋手,他將挑出最好的口袋裡盡可能差的物品。運用最小-最大原理,你需要做的就是挑乙個有「最好的最差的」物品的口袋。

假設你可以估計口袋裡每個物品的準確價值的話,最小-最大原理可以讓你作出正確的選擇。我們討論的話題中,準確評價並不重要,因為它同最小-最大或alpha-beta的工作原理沒有關係。現在我們假設你可以正確地評價物品。

最小-最大原理剛才討論過,它的問題是效率太低。你必須看每個口袋裡的每件物品,這就需要花很多時間。

那麼怎樣才能做得比最小-最大更高效呢?

我們從第乙個口袋開始,看每一件物品,並對口袋作出評價。比方說口袋裡有乙隻花生黃油三明治和一輛新汽車的鑰匙。你知道三明治更糟,因此如果你挑了這只口袋就會得到三明治。事實上只要我們假設對手也會跟我們一樣正確評價物品,那麼口袋裡的汽車鑰匙就是無關緊要的了。

現在你開始翻第二個口袋,這次你採取的方案就和最小-最大方案不同了。你每次看一件物品,並跟你能得到的最好的那件物品(三明治)去比較。只要物品比三明治更好,那麼你就按照最小-最大方案來辦——去找最糟的,或許最糟的要比三明治更好,那麼你就可以挑這個口袋,它比裝有三明治的那個口袋好。

比方這個口袋裡的第一件物品是一張20美元的鈔票,它比三明治好。如果包裡其他東西都沒比這個更糟了,那麼如果你選了這個口袋,它就是對手必須給你的物品,這個口袋就成了你的選擇。

這個口袋裡的下一件物品是六合裝的流行唱片。你認為它比三明治好,但比20美元差,那麼這個口袋仍舊可以選擇。再下一件物品是一條爛魚,這回比三明治差了。於是你就說「不謝了」,把口袋放回去,不再考慮它了。

無論口袋裡還有什麼東西,或許還有另一輛汽車的鑰匙,也沒有用了,因為你會得到那條爛魚。或許還有比爛魚更糟的東西(那麼你看著辦吧)。無論如何爛魚已經夠糟的了,而你知道挑那個有三明治的口袋肯定會更好。

演算法 alpha-beta就是這麼工作的,並且只能用遞迴來實現。稍後我們再來談最小一方的策略,我希望這樣可以更明白些。

這個思想是在搜尋中傳遞兩個值,第乙個值是alpha,即搜尋到的最好值,任何比它更小的值就沒用了,因為策略就是知道alpha的值,任何小於或等於alpha的值都不會有所提高。

第二個值是beta,即對於對手來說最壞的值。這是對手所能承受的最壞的結果,因為我們知道在對手看來,他總是會找到乙個對策不比beta更壞的。如果搜尋過程中返回beta或比beta更好的值,那就夠好的了,走棋的一方就沒有機會使用這種策略了。

在搜尋著法時,每個搜尋過的著法都返回跟alpha和beta有關的值,它們之間的關係非常重要,或許意味著搜尋可以停止並返回。

如果某個著法的結果小於或等於alpha,那麼它就是很差的著法,因此可以拋棄。因為我前面說過,在這個策略中,局面對走棋的一方來說是以alpha為評價的。

如果某個著法的結果大於或等於beta,那麼整個結點就作廢了,因為對手不希望走到這個局面,而它有別的著法可以避免到達這個局面。因此如果我們找到的評價大於或等於beta,就證明了這個結點是不會發生的,因此剩下的合理著法沒有必要再搜尋。

如果某個著法的結果大於alpha但小於beta,那麼這個著法就是走棋一方可以考慮走的,除非以後有所變化。因此alpha會不斷增加以反映新的情況。有時候可能乙個合理著法也不超過alpha,這在實戰中是經常發生的,此時這種局面是不予考慮的,因此為了避免這樣的局面,我們必須在博弈樹的上乙個層局面選擇另外乙個著法。

在第二個口袋裡找到爛魚就相當於超過了beta,如果口袋裡沒有爛魚,那麼考慮六盒裝流行唱片的口袋會比三明治的口袋好,這就相當於超過了alpha(在上一層)。演算法如下,醒目的部分是在最小-最大演算法上改過的:

int alphabeta(int depth, int alpha, int beta)

generatelegalmoves();

while (movesleft())

if (val > alpha)

} return alpha;

} 把醒目的部分去掉,剩下的就是最小-最大函式。可以看出現在的演算法沒有太多的改變。

這個函式需要傳遞的引數有:需要搜尋的深度,負無窮大即alpha,以及正無窮大即beta:

val = alphabeta(5, -infinity, infinity);

這樣就完成了5層的搜尋。我在寫最小-最大函式時,用了乙個訣竅來避免用了「min」還用「max」函式。在那個演算法中,我從遞迴中返回時簡單地對返回值取了負數。這樣就使函式值在每一次遞迴中改變評價的角度,以反映雙方棋手的交替著子,並且它們的目標是對立的。

在alpha-beta函式中我們做了同樣的處理。唯一使演算法感到複雜的是,alpha和beta是不斷互換的。當函式遞迴時,alpha和beta不但取負數而且位置交換了,這就使得情況比口袋的例子複雜,但是可以證明它只是比最小-最大演算法更好而已。

最終出現的情況是,在搜尋樹的很多地方,beta是很容易超過的,因此很多任務作都免去了。

可能的弱點

這個演算法嚴重依賴於著法的尋找順序。如果你總是先去搜尋最壞的著法,那麼beta截斷就不會發生,因此該演算法就如同最小-最大一樣,效率非常低。該演算法最終會找遍整個博弈樹,就像最小-最大演算法一樣。

如果程式總是能挑最好的著法來首先搜尋,那麼數學上有效分枝因子就接近於實際分枝因子的平方根。這是alpha-beta演算法可能達到的最好的情況。

由於西洋棋的分枝因子在35左右,這就意味著alpha-beta演算法能使西洋棋搜尋樹的分枝因子變成6。

這是很大的改進,在搜尋結點數一樣的情況下,可以使你的搜尋深度達到原來的兩倍。這就是為什麼使用alpha-beta搜尋時,著法順序至關重要的原因。

原文:http://www.seanet.com/~brucemo/topics/alphabeta.htm

譯者:黃晨 (

[email protected])

型別:全譯 

對弈程式基本技術 Alpha Beta搜尋

專題 alpha beta 搜尋 bruce moreland 文 最小 最大的問題 alpha beta 同 最小 最大 非常相似,事實上只多了一條額外的語句。最小最大執行時要檢查整個博弈樹,然後盡可能選擇最好的線路。這是非常好理解的,但效率非常低。每次搜尋更深一層時,樹的大小就呈指數式增長。通常...

程式入口 專題

test 1 26 t 裸函式.exe test 行 90 kernel32.dll 775a337a 未知 ntdll.dll 77c39882 未知 ntdll.dll 77c39855 未知 預設 1 26 t 裸函式.exe wmain int argc,wchar t argv 行 99 ...

專題整理 搜尋技術

bfs 題解型別 hdu1253勝利大逃亡 題解簡單bfs poj3278 catch that cow 題解簡單bfs poj 3126 prime path 題解簡單bfs hdu 2102 a計畫 題解簡單bfs codeforces 520b two buttons 題解bfs 剪枝 fzu...