主要變例搜尋

2021-06-24 18:21:51 字數 1648 閱讀 9877

主要變例搜尋

alpha-beta的改進

主要變例搜尋(pvs, principal variation search)是提高「alpha-beta」演算法效率的一種方法。

在alpha-beta搜尋中,任何結點都屬於以下三種型別:

1. alpha結點。每個搜尋都會得到乙個小於或等於alpha的值,這就意味著這裡沒有乙個著法是好的,可能是因為這個局面對於要走的一方太壞了。

2. beta結點。至少乙個著法會返回大於或等於beta的值。

3. 主要變例(pv)結點。有乙個或多個著法會返回大於或等於alpha的值(即pv著法),但是沒有著法會返回大於或等於beta的值。

有些時候你可以很早地判斷出你要處理的是哪類結點。如果你搜尋的第乙個著法高出邊界(返回乙個大於或等於beta的值),那麼很明顯你得到beta結點。如果低出邊界(返回乙個小於或等於alpha的值),假設你的著法順序非常好,那麼你有可能得到alpha結點。如果返回值在alpha和beta之間,你可能得到pv結點。

當然,有兩種情況你可能會判斷錯誤。當你高出邊界時,你返回beta,因此你不會犯錯誤,但是如果第乙個著法低出邊界或者是pv著法時,仍然有可能在下乙個著法得到更高的值。

主要變例搜尋作了假設,如果你在搜尋乙個結點時找到乙個pv著法,那麼你就得到pv結點。也就是說假設你的著法排序已經足夠好了,使得你不必在其餘的著法中找更好的pv著法或者高出邊界的著法(這就會使結點變成beta結點)。

你找到乙個著法其值在alpha和beta之間,那麼對其餘的著法,搜尋的目標就是證明他們都是壞的。跟要搜尋出更好的著法相比,這種搜尋也許要快一些。

如果這個演算法發現判斷是錯的,即其中乙個後續著法比第乙個pv著法好,那麼它會被再一次搜尋,這次使用正常的alpha-beta搜尋方法。這種情況有時會發生,這樣就浪費時間了,但是這些時間通常不會超過面所說的「證明是壞著法」所節約下來的時間。

演算法如下,是從alpha-beta演算法改過來的,改過的地方用醒目的字標出:

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

generatelegalmoves();

while (movesleft())

} else

val = -alphabeta(depth - 1, -beta, -alpha);

} unmakemove();

if (val >= beta)

if (val > alpha)

} return alpha; }

據報道pvs可以提高10%的效率。我沒有試圖檢測pvs用在我的程式裡到底提高了多少,但是確實提高了,所以我用了這個演算法。

搜尋不穩定性的問題

如果你用(alpha, alpha + 1)這個視窗去做搜尋,返回值超過了視窗(但是沒有超過beta),你就必須重新搜尋。你認為重新搜尋的值必定在alpha和beta之間,但是恐怕不一定是。這很有可能是由「搜尋的不穩定性」引起的,我會在別的章節中討論這個問題。

上面寫的那個程式對這個情況作了防禦,並對這種情況的發生作了正確的處理。如果你要使用這個程式並且作一些改動,就要特別當心你的搜尋是否總是穩定的。如果你得到不期望得到的返回值,就必須採取措施避免讓程式陷入故障。

獲取主要變例

要點 經常有人問,如何在搜尋完成後提取主要變例。主要變例是程式認為的對雙方來說都是最好的著法線路。它不會由未修改的 alpha beta函式 來獲得,所有的alpha beta都只返回數值。我們需要做的是對普通的alpha beta搜尋作修改,使得它能獲取主要變例。修改的部分用醒目的顏色標出 typ...

lucene的主要搜尋API

類 用途indexseacher 搜尋操作的入口,所有搜尋操作都是通過indexseacher例項使用乙個過載的search方法來實現 query 及其子類 具體的query子類為每一種特定型別的查詢進行邏輯上的封裝。query例項被傳遞到indexsearcher的search方法中 queryp...

lucene的主要搜尋API

類 用途indexseacher 搜尋操作的入口,所有搜尋操作都是通過indexseacher例項使用乙個過載的search方法來實現 query 及其子類 具體的query子類為每一種特定型別的查詢進行邏輯上的封裝。query例項被傳遞到indexsearcher的search方法中 queryp...