【发布时间】:2019-08-14 09:03:17
【问题描述】:
我正在尝试构建一个国际象棋 AI。我使用 alpha-beta 剪枝 (ABP) 的 negamax 函数比使用 ABP 的单独的 min 和 max 函数运行得慢得多(大约 8 倍),尽管返回的移动是相等的。
我的棋盘评估函数总是返回一个关于红色玩家的值,即红色越高越好。仅适用于 Negamax,黑色玩家返回深度 0 时,此值乘以 -1。
我的 Negamax 函数:
int alphaBeta(Board board, int depth, int alpha, int beta) {
if (depth <= 0 || board.isGameOver()) { // game over == checkmate/stalemate
int color = board.getCurrPlayer().getAlliance().isRed() ? 1 : -1;
return BoardEvaluator.evaluate(board, depth) * color;
}
int bestVal = Integer.MIN_VALUE + 1;
for (Move move : MoveSorter.simpleSort(board.getCurrPlayer().getLegalMoves())) {
MoveTransition transition = board.getCurrPlayer().makeMove(move);
if (transition.getMoveStatus().isAllowed()) { // allowed == legal && non-suicidal
int val = -alphaBeta(transition.getNextBoard(), depth - 1, -beta, -alpha);
if (val >= beta) {
return val; // fail-soft
}
if (val > bestVal) {
bestVal = val;
alpha = Math.max(alpha, val);
}
}
}
return bestVal;
}
根调用:
-alphaBeta(transition.getNextBoard(), searchDepth - 1,
Integer.MIN_VALUE + 1, Integer.MAX_VALUE); // +1 to avoid overflow when negating
我的最小值和最大值函数:
int min(Board board, int depth, int alpha, int beta) {
if (depth <= 0 || board.isGameOver()) {
return BoardEvaluator.evaluate(board, depth);
}
int minValue = Integer.MAX_VALUE;
for (Move move : MoveSorter.simpleSort(board.getCurrPlayer().getLegalMoves())) {
MoveTransition transition = board.getCurrPlayer().makeMove(move);
if (transition.getMoveStatus().isAllowed()) {
minValue = Math.min(minValue, max(transition.getNextBoard(), depth - 1, alpha, beta));
beta = Math.min(beta, minValue);
if (alpha >= beta) break; // cutoff
}
}
return minValue;
}
int max(Board board, int depth, int alpha, int beta) {
if (depth <= 0 || board.isGameOver()) {
return BoardEvaluator.evaluate(board, depth);
}
int maxValue = Integer.MIN_VALUE;
for (Move move : MoveSorter.simpleSort(board.getCurrPlayer().getLegalMoves())) {
MoveTransition transition = board.getCurrPlayer().makeMove(move);
if (transition.getMoveStatus().isAllowed()) {
maxValue = Math.max(maxValue, min(transition.getNextBoard(), depth - 1, alpha, beta));
alpha = Math.max(alpha, maxValue);
if (alpha >= beta) break; // cutoff
}
}
return maxValue;
}
root分别呼唤红黑玩家:
min(transition.getNextBoard(), searchDepth - 1, Integer.MIN_VALUE, Integer.MAX_VALUE);
max(transition.getNextBoard(), searchDepth - 1, Integer.MIN_VALUE, Integer.MAX_VALUE);
我猜测 Negamax 函数中的截止存在错误,尽管我遵循了来自 here 的伪代码。任何帮助表示赞赏,谢谢!
编辑:alphaBeta() 的调用次数大约是 min() 和 max() 加起来的 6 倍,而 beta 截止值的数量只有大约 2 倍。
【问题讨论】:
-
很确定你不应该在深度零返回上“偏向”颜色。除非您的 BoardEvaluator 也这样做? (不应该。)所有评估都应该与红色相关。递归调用的否定处理颜色切换。
-
看看这个wikipedia page。如果从红色玩家的角度计算节点的启发式值,则需要颜色参数。
-
也许你是对的。我仍然认为放缓是从那里来的。深度为零的情况是所有叶子,因此将执行最多。您是否考虑过将颜色作为参数传递,而不是像在每片叶子上那样从板上计算?
-
试过了,结果一样。这是有道理的,因为颜色的计算只涉及一个 getter 方法。
-
嗯,3 个方法调用,?: 操作和赋值,但没关系。抱歉,我无法提供更多帮助。
标签: java artificial-intelligence chess minimax alpha-beta-pruning