【问题标题】:Alpha-beta move orderingAlpha-beta 移动排序
【发布时间】:2012-04-01 12:46:22
【问题描述】:

我有一个基本的 alpha-beta 修剪实现,但我不知道如何改进移动排序。我读过它可以通过浅搜索、迭代加深或将 bestMoves 存储到转换表来完成。

有什么建议可以在这个算法中实现这些改进之一吗?

 public double alphaBetaPruning(Board board, int depth, double alpha, double beta, int player) {
    if (depth == 0) {
        return board.evaluateBoard();
    }

    Collection<Move> children = board.generatePossibleMoves(player);
    if (player == 0) {
        for (Move move : children) {
            Board tempBoard = new Board(board);
            tempBoard.makeMove(move);
            int nextPlayer = next(player);
            double result = alphaBetaPruning(tempBoard, depth - 1, alpha,beta,nextPlayer);
            if ((result > alpha)) {
                alpha = result;
                if (depth == this.origDepth) {
                    this.bestMove = move;
                }
            }
            if (alpha >= beta) {
                break;
            }
        }
        return alpha;
    } else {
        for (Move move : children) {
            Board tempBoard = new Board(board);
            tempBoard.makeMove(move);
            int nextPlayer = next(player);
            double result = alphaBetaPruning(tempBoard, depth - 1, alpha,beta,nextPlayer);
            if ((result < beta)) {
                beta = result;
                if (depth == this.origDepth) {
                    this.bestMove = move;
                }
            }
            if (beta <= alpha) {
                break;
            }
        }
        return beta;
    }
}

public int next(int player) {
    if (player == 0) {
        return 4;
    } else {
        return 0;
    }
}

【问题讨论】:

    标签: java algorithm artificial-intelligence minimax alpha-beta-pruning


    【解决方案1】:
    • 浅搜索的节点重新排序是微不足道的:计算 递归之前状态的每个孩子的启发式值 检查它们。然后,对这些状态的值进行排序 [降序 对于最大顶点,对于最小顶点升序],并递归调用 排序列表上的算法。这个想法是 - 如果一个国家擅长 深度较浅,也更有可能擅长深度状态, 如果这是真的 - 你会得到更多的修剪。

      排序应该在之前完成[在ifelse 子句中]

      for (Move move : children) {

    • 存储动作也很简单——许多状态被计算两次, 当你完成计算任何状态时,将其存储[深度为 计算!这很重要!] 在HashMap 中。你做的第一件事 当您开始计算顶点时 - 检查它是否已经 计算 - 如果是,则返回缓存值。背后的想法 这是许多状态可以从不同的路径到达,所以这 方式 - 您可以消除冗余计算。

      应该在方法的第一行进行更改[类似于if (cache.contains((new State(board,depth,player)) return cache.get(new State(board,depth,player))] [请原谅我缺乏优雅和效率 - 只是在这里解释一个想法]。
      您还应该在每个return 语句之前添加cache.put(...)

    【讨论】:

    • 鉴于问题中的代码示例,您能否提供一个可能的实现或排序(因此排序和递归调用排序列表)?我对如何实现它感到困惑。
    • 理论上很好的直观答案,尽管我必须在第二部分学习哈希图。对于 Python,我正在考虑使用嵌套字典,例如 `{depth:{node:score}}`
    【解决方案2】:

    首先,必须了解 alpha-beta 修剪算法中移动排序背后的原因。 Alpha-beta 产生与 minimax 相同的结果,但在很多情况下可以更快,因为它不会搜索不相关的分支。

    它并不总是更快,因为它不能保证修剪,如果事实在更坏的情况下它根本不会修剪并搜索与 minimax 完全相同的树,并且会因为 a/b 值簿记而变慢.在最好的情况下(最大修剪),它允许同时搜索 2 倍深度的树。对于随机树,它可以同时搜索 4/3 倍的深度。

    移动排序可以通过两种方式实现:

    1. 您有一位领域专家会为您提供更好的建议。例如在棋子的国际象棋促销中,用低价值的棋子捕获高价值的棋子通常是好棋。在跳棋中,最好在一步中杀死更多跳棋而不是减少跳棋,并且最好创建一个皇后。所以你的移动生成函数会在之前返回更好的移动
    2. 您可以通过评估更小 1 级的位置(您的浅层搜索/迭代深化)来了解移动的好坏。您计算了深度 n-1 处的评估,对移动进行排序,然后在深度 n 处评估。

    您提到的第二种方法与移动排序无关。这与评估函数可能很昂贵并且许多位置被多次评估的事实有关。要绕过这一点,您可以在计算后将位置的值存储在哈希中,并在以后重复使用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-22
      • 2011-07-26
      • 2023-03-16
      • 2021-04-15
      相关资源
      最近更新 更多