關於alphabeta剪枝的文章太多,這個方法是所有其它搜尋方法的基礎,得多花些時間認真地理解。
先把基本概念再回顧一遍:
節點:在中國象棋中就是乙個棋盤的當前局面board,當然該輪到誰走棋也是確定的。這裡的圓形節點表示終止節點,在中國象棋裡就是一方被將死的情況(或者到達了搜尋的最大深度),後續不會再有著法產生,遊戲如果走到這裡就會結束。在引擎裡通常給紅方乙個很大的評估值,如+30000,給黑方乙個很小的評估值,如-30000,來方便地判斷這種結束局面。(勝利局面有稍微不同的表示法,用-30000+層數ply來表示)
連線:表示一步著法move,通過這步著法後,局面發生變化,先後手也要交換。
層:通常的術語是ply,複數形式是plies,也有稱為levels,當然與depth也是對應的。這個術語是為了與比賽裡常說的回合相區分,乙個回合通常包含2步,這個ply就表示某一方走了一步。根節點記為0層,以下的層數遞增。
深度depth:要注意是從下到上的,還是從上到下的。(1)通常的演算法書中都是從下到上遞增的,即根節點為最大搜尋深度,走到最底部的葉子結點為0,這種演算法只要記住乙個depth值就可以了。(2)而另一種記法是根部結點為0,越向下depth增加,這時在搜尋時就要傳遞2個引數值,depth和maxdepth,稍微有點囉嗦,應該也會影響一點效率。另外在探查置換表中的結點時,用第(1)種記法也方便一些,因為要知道從當前節點迭代的深度值,否則還要在置換表中儲存depth和maxdepth兩個值。
alphabeta剪枝方法是對minimax方法的優化,它們產生的結果是完全相同的,只不過執行效率不一樣。
這種方法的前提假設與minimax也是一樣的:
1)雙方都按自己認為的最佳著法行棋。
2)對給定的盤面用乙個分值來評估,這個評估值永遠是從一方(搜尋程式)來評價的,紅方有利時給乙個正數,黑方有利時給乙個負數。(如果紅方有利時返回正數,當輪到黑方走棋時,評估值又轉換到黑方的觀點,如果認為黑方有利,也返回正數,這種評估方法都不適合於常規的演算法描述)
3)從我們的搜尋程式(通常把它稱為max)看來,分值大的數表示對己方有利,而對於對方min來說,它會選擇分值小的著法。
但要注意:用negamax風格來描述的alphabeta中的評估函式,對輪到誰走棋是敏感的。
也就是說:
在minimax風格的alphabeta演算法中,輪紅方走棋時,評估值為100,輪黑方走棋評估值仍是100。
但在negamax風格的alphabeta演算法中,輪紅方走棋時,評估值為100,輪黑方走棋**估值要為-100。
貼一段偽**:
def abnegamax (board, depth, maxdepth, alpha, beta)abnegamax(board, player, maxdepth,if ( board.isgameover() or depth ==maxdepth )
return board.evaluate(), null
bestmove =null
bestscore = -infinity
for move in
board.getmoves()
newboard =board.makemove(move)
score = abnegamax(newboard, maxdepth, depth+1
, -beta, -max(alpha, bestscore))
score = -score
if ( score >bestscore )
bestscore =score
bestmove =move
# early loop exit (pruning)
if ( bestscore >=beta ) return bestscore, bestmove
return bestscore, bestmove
用下列語句開始呼叫:
0, -infinity, infinity)
//下面這個pdf更清楚地說明了negamax風格的alphabeta演算法的過程:method call with depth 5 and minimum and maximum boundaries
//minimaxvalue = alphabeta(board, 5, -mate, +mate)
int alphabeta(chessboard board, int depth, int alpha, int
beta)
board.getorderedmoves();
int best = -mate-1;
intmove;
chessboard nextboard;
while
(board.hasmoremoves())
return
best;
}
為了更準確地理解minmax和negamax兩種不同風格的搜尋執行過程,畫出了詳細的**,發現negamax更容易理解了,**也確實精練了不少。
當採用了置換表演算法後,還需要對pv-nodes, cut-nodes和all-nodes三種型別結點的含義以及如何變化有更準確地了解。
可以發現,negamax風格的演算法有下面的特點(**來自象棋巫師):
int alphabeta(int depth, int alpha, int beta)
generatelegalmoves();
while (movesleft())
if (val > alpha)
} recordhash(depth, alpha, hashf);
return alpha; // 此時的alpha就是記錄了當前結點的所有子結點的最大的負評估值!
}這面的**在置換表探查方面感覺有點問題,又從marek strejczek的**《some aspects of chess programming》的第87頁上找到一段**,感覺這段**充分利用了置換表中儲存的資訊。
chscore alphabetawithtt(chposition node,chscore alpha,beta)if (entry.score
beta =flag.score;}}
if (entry.flag ==lower)
if (entry.score >alpha)
}if (entry.flag ==exact)
}else
}}g =alpha;
x =left_most_child(node);
hash_flag =upper;
best_move =null;
while
(isnotnull (x) )
hash_flag =exact;
best_move =current_move;
}x =next_brother(x);
}puttohash(node, g, hash_flag, best_move)
return
alpha;
} //
end of alphabetawithtt
Alpha beta剪枝演算法例項分析
看本章之前,請先參看前一篇文章 minimax演算法及例項分析 由於minimax演算法有乙個很大的問題就是計算複雜性。由於所需搜尋的節點數隨最大深度呈指數膨脹,而演算法的效果往往和深度相關,因此這極大限制了演算法的效果。alpha beta剪枝是對minimax的補充和改進。採用alpha bet...
Alpha beta剪枝演算法例項分析
原帖 看本章之前,請先參看前一篇文章 minimax演算法及例項分析 由於minimax演算法有乙個很大的問題就是計算複雜性。由於所需搜尋的節點數隨最大深度呈指數膨脹,而演算法的效果往往和深度相關,因此這極大限制了演算法的效果。alpha beta剪枝是對minimax的補充和改進。採用alpha ...
Alpha beta剪枝演算法例項分析
看本章之前,請先參看前一篇文章 minimax演算法及例項分析 由於minimax演算法有乙個很大的問題就是計算複雜性。由於所需搜尋的節點數隨最大深度呈指數膨脹,而演算法的效果往往和深度相關,因此這極大限制了演算法的效果。alpha beta剪枝是對minimax的補充和改進。採用alpha bet...