|
針對(duì)目前火爆的2048游戲,有人實(shí)現(xiàn) 了一個(gè)AI程序,可以以較大概率(高于90%)贏得游戲,并且作者在stackoverflow上簡(jiǎn)要介紹了AI的算法框架和實(shí)現(xiàn)思路。但是這個(gè)回答主要集中在啟發(fā)函數(shù)的選取上,對(duì)AI用到的核心算法并沒(méi)有仔細(xì)說(shuō)明。這篇文章將主要分為兩個(gè)部分,第一部分介紹其中用到的基礎(chǔ)算法,即Minimax和Alpha-beta剪枝;第二部分分析作者具體的實(shí)現(xiàn)。
基礎(chǔ)算法2048本質(zhì)上可以抽象成信息對(duì)稱雙人對(duì)弈模型(玩家向四個(gè)方向中的一個(gè)移動(dòng),然后計(jì)算機(jī)在某個(gè)空格中填入2或4)。這里“信息對(duì)稱”是指在任一時(shí)刻對(duì)弈雙方對(duì)格局的信息完全一致,移動(dòng)策略僅依賴對(duì)接下來(lái)格局的推理。作者使用的核心算法為對(duì)弈模型中常用的帶Alpha-beta剪枝的Minimax。這個(gè)算法也常被用于如國(guó)際象棋等信息對(duì)稱對(duì)弈AI中。 Minimax下面先介紹不帶剪枝的Minimax。首先本文將通過(guò)一個(gè)簡(jiǎn)單的例子說(shuō)明Minimax算法的思路和決策方式。 問(wèn)題現(xiàn)在考慮這樣一個(gè)游戲:有三個(gè)盤子A、B和C,每個(gè)盤子分別放有三張紙幣。A放的是1、20、50;B放的是5、10、100;C放的是1、5、20。單位均為“元”。有甲、乙兩人,兩人均對(duì)三個(gè)盤子和上面放置的紙幣有可以任意查看。游戲分三步:
其中甲的目標(biāo)是最后拿到的紙幣面值盡量大,乙的目標(biāo)是讓甲最后拿到的紙幣面值盡量小。 下面用Minimax算法解決這個(gè)問(wèn)題。 基本思路一般解決博弈類問(wèn)題的自然想法是將格局組織成一棵樹(shù),樹(shù)的每一個(gè)節(jié)點(diǎn)表示一種格局,而父子關(guān)系表示由父格局經(jīng)過(guò)一步可以到達(dá)子格局。Minimax也不例外,它通過(guò)對(duì)以當(dāng)前格局為根的格局樹(shù)搜索來(lái)確定下一步的選擇。而一切格局樹(shù)搜索算法的核心都是對(duì)每個(gè)格局價(jià)值的評(píng)價(jià)。Minimax算法基于以下樸素思想確定格局價(jià)值:
上面的表述有些抽象,下面看具體示例。 解題下圖是上述示例問(wèn)題的格局樹(shù):
注意,由于示例問(wèn)題格局?jǐn)?shù)非常少,我們可以給出完整的格局樹(shù)。這種情況下我可以找到Minimax算法的全局最優(yōu)解。而真實(shí)情況中,格局樹(shù)非常龐大,即使是計(jì)算機(jī)也不可能給出完整的樹(shù),因此我們往往只搜索一定深度,這時(shí)只能找到局部最優(yōu)解。 我們從甲的角度考慮。其中正方形節(jié)點(diǎn)表示輪到我方(甲),而三角形表示輪到對(duì)方(乙)。經(jīng)過(guò)三輪對(duì)弈后(我方-對(duì)方-我方),將進(jìn)入終局。黃色葉結(jié)點(diǎn)表示所有可能的結(jié)局。從甲方看,由于最終的收益可以通過(guò)紙幣的面值評(píng)價(jià),我們自然可以用結(jié)局中甲方拿到的紙幣面值表示終格局的價(jià)值。 下面考慮倒數(shù)第二層節(jié)點(diǎn),在這些節(jié)點(diǎn)上,輪到我方選擇,所以我們應(yīng)該引入可選擇的最大價(jià)值格局,因此每個(gè)節(jié)點(diǎn)的價(jià)值為其子節(jié)點(diǎn)的最大值:
這些輪到我方的節(jié)點(diǎn)叫做max節(jié)點(diǎn),max節(jié)點(diǎn)的值是其子節(jié)點(diǎn)最大值。 倒數(shù)第三層輪到對(duì)方選擇,假設(shè)對(duì)方會(huì)盡力將局勢(shì)引入讓我方價(jià)值最小的格局,因此這些節(jié)點(diǎn)的價(jià)值取決于子節(jié)點(diǎn)的最小值。這些輪到對(duì)方的節(jié)點(diǎn)叫做min節(jié)點(diǎn)。 最后,根節(jié)點(diǎn)是max節(jié)點(diǎn),因此價(jià)值取決于葉子節(jié)點(diǎn)的最大值。最終完整賦值的格局樹(shù)如下:
總結(jié)一下Minimax算法的步驟:
在上面的例子中,根節(jié)點(diǎn)的價(jià)值為20,表示如果對(duì)方每一步都完美決策,則我方按照上述算法可最終拿到20元,這是我方在Minimax算法下最好的決策。格局轉(zhuǎn)換路徑如下圖紅色路徑所示:
對(duì)于真實(shí)問(wèn)題中的Minimax,再次強(qiáng)調(diào)幾點(diǎn):
Alpha-beta剪枝簡(jiǎn)單的Minimax算法有一個(gè)很大的問(wèn)題就是計(jì)算復(fù)雜性。由于所需搜索的節(jié)點(diǎn)數(shù)隨最大深度呈指數(shù)膨脹,而算法的效果往往和深度相關(guān),因此這極大限制了算法的效果。 Alpha-beta剪枝是對(duì)Minimax的補(bǔ)充和改進(jìn)。采用Alpha-beta剪枝后,我們可不必構(gòu)造和搜索最大深度D內(nèi)的所有節(jié)點(diǎn),在構(gòu)造過(guò)程中,如果發(fā)現(xiàn)當(dāng)前格局再往下不能找到更好的解,我們就停止在這個(gè)格局及以下的搜索,也就是剪枝。 Alpha-beta基于這樣一種樸素的思想:時(shí)時(shí)刻刻記得當(dāng)前已經(jīng)知道的最好選擇,如果從當(dāng)前格局搜索下去,不可能找到比已知最優(yōu)解更好的解,則停止這個(gè)格局分支的搜索(剪枝),回溯到父節(jié)點(diǎn)繼續(xù)搜索。 Alpha-beta算法可以看成變種的Minimax,基本方法是從根節(jié)點(diǎn)開(kāi)始采用深度優(yōu)先的方式構(gòu)造格局樹(shù),在構(gòu)造每個(gè)節(jié)點(diǎn)時(shí),都會(huì)讀取此節(jié)點(diǎn)的alpha和beta兩個(gè)值,其中alpha表示搜索到當(dāng)前節(jié)點(diǎn)時(shí)已知的最好選擇的下界,而beta表示從這個(gè)節(jié)點(diǎn)往下搜索最壞結(jié)局的上界。由于我們假設(shè)對(duì)手會(huì)將局勢(shì)引入最壞結(jié)局之一,因此當(dāng)beta小于alpha時(shí),表示從此處開(kāi)始不論最終結(jié)局是哪一個(gè),其上限價(jià)值也要低于已知的最優(yōu)解,也就是說(shuō)已經(jīng)不可能此處向下找到更好的解,所以就會(huì)剪枝。 下面同樣以上述示例介紹Alpha-beta剪枝算法的工作原理。我們從根節(jié)點(diǎn)開(kāi)始,詳述使用Alpha-beta的每一個(gè)步驟:
此時(shí)搜索全部完畢,而我們也得到了這一步的策略:應(yīng)該走A分支。 可以看到相比普通Minimax要搜索18個(gè)葉子節(jié)點(diǎn)相比,這里只搜索了9個(gè)。采用Alpha-beta剪枝,可以在相同時(shí)間內(nèi)加大Minimax的搜索深度,因此可以獲得更好的效果。并且Alpha-beta的解和普通Minimax的解是一致的。
針對(duì)2048游戲的實(shí)現(xiàn)下面看一下ov3y同學(xué)針對(duì)2048實(shí)現(xiàn)的AI。程序的github在這里,主要程序都在ai.js中。 建模上面說(shuō)過(guò)Minimax和Alpha-beta都是針對(duì)信息對(duì)稱的輪流對(duì)弈問(wèn)題,這里作者是這樣抽象游戲的:
如此2048游戲就被建模成一個(gè)信息對(duì)稱的雙人對(duì)弈問(wèn)題。 格局評(píng)價(jià)作為算法的核心,如何評(píng)價(jià)當(dāng)前格局的價(jià)值是重中之重。在2048中,除了終局外,中間格局并無(wú)非常明顯的價(jià)值評(píng)價(jià)指標(biāo),因此需要用一些啟發(fā)式的指標(biāo)來(lái)評(píng)價(jià)格局。那些分?jǐn)?shù)高的“好”格局是容易引向勝利的格局,而分低的“壞”格局是容易引向失敗的格局。 作者采用了如下幾個(gè)啟發(fā)式指標(biāo)。 單調(diào)性單調(diào)性指方塊從左到右、從上到下均遵從遞增或遞減。一般來(lái)說(shuō),越單調(diào)的格局越好。下面是一個(gè)具有良好單調(diào)格局的例子:
平滑性平滑性是指每個(gè)方塊與其直接相鄰方塊數(shù)值的差,其中差越小越平滑。例如2旁邊是4就比2旁邊是128平滑。一般認(rèn)為越平滑的格局越好。下面是一個(gè)具有極端平滑性的例子:
空格數(shù)這個(gè)很好理解,因?yàn)橐话銇?lái)說(shuō),空格子越少對(duì)玩家越不利。所以我們認(rèn)為空格越多的格局越好。 孤立空格數(shù)這個(gè)指標(biāo)評(píng)價(jià)空格被分開(kāi)的程度,空格越分散則格局越差。 具體來(lái)說(shuō),2048-AI在評(píng)價(jià)格局時(shí),對(duì)這些啟發(fā)指標(biāo)采用了加權(quán)策略。具體代碼如下:
有興趣的同學(xué)可以調(diào)整一下權(quán)重看看有什么效果。 對(duì)對(duì)方選擇的剪枝在這個(gè)程序中,除了采用Alpha-beta剪枝外,在min節(jié)點(diǎn)還采用了另一種剪枝,即只考慮對(duì)方走出讓格局最差的那一步(而實(shí)際2048中計(jì)算機(jī)的選擇是隨機(jī)的),而不是搜索全部對(duì)方可能的走法。這是因?yàn)閷?duì)方所有可能的選擇為“空格數(shù)×2”,如果全部搜索的話會(huì)嚴(yán)重限制搜索深度。 相關(guān)剪枝代碼如下:
搜索深度在2048-AI的實(shí)現(xiàn)中,并沒(méi)有限制搜索的最大深度,而是限制每次“思考”的時(shí)間。這里設(shè)定了一個(gè)超時(shí)時(shí)間,默認(rèn)為100ms,在這個(gè)時(shí)間內(nèi),會(huì)從1開(kāi)始,搜索到所能達(dá)到的深度。相關(guān)代碼:
因此這個(gè)算法實(shí)現(xiàn)的效果實(shí)際上依賴于執(zhí)行javascript引擎機(jī)器的性能。當(dāng)然可以通過(guò)增加超時(shí)時(shí)間來(lái)達(dá)到更好的效果,但此時(shí)每一步行走速度會(huì)相應(yīng)變慢。 算法的改進(jìn)目前這個(gè)實(shí)現(xiàn)作者聲稱成功合成2048的概率超過(guò)90%,但是合成4096甚至8192的概率并不高。作者在github項(xiàng)目的REAMDE中同時(shí)給出了一些優(yōu)化建議,這些建議包括:
參考文獻(xiàn)
原文鏈接:http://blog./articles/2048-ai-analysis.html 【編輯推薦】
【責(zé)任編輯:林師授 TEL:(010)68476606】
|
|
|