Java 阿尔法-贝塔移动排序

Java 阿尔法-贝塔移动排序,java,algorithm,artificial-intelligence,minimax,alpha-beta-pruning,Java,Algorithm,Artificial Intelligence,Minimax,Alpha Beta Pruning,我有一个alpha-beta修剪的基本实现,但我不知道如何改进移动顺序。我已经读到,它可以通过浅层搜索、迭代深化或存储最佳移动到转换表来完成 对于如何在这个算法中实现这些改进,有什么建议吗 public double alphaBetaPruning(Board board, int depth, double alpha, double beta, int player) { if (depth == 0) { return board.evaluateBoard()

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

对于如何在这个算法中实现这些改进,有什么建议吗

 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;
    }
}
公共双字母beta调谐(棋盘、整数深度、双字母、双beta、整数播放器){
如果(深度==0){
返回板。评估板();
}
集合子项=板。生成许可移动(玩家);
如果(玩家==0){
对于(移动:儿童){
板温度板=新板(板);
tempBoard.makeMove(移动);
int nextPlayer=next(播放器);
双结果=AlphaBetaPlanning(温度板,深度-1,alpha,beta,下一层);
如果((结果>α)){
α=结果;
if(深度==此.origDepth){
this.bestMove=移动;
}
}
如果(α>=β){
打破
}
}
返回α;
}否则{
对于(移动:儿童){
板温度板=新板(板);
tempBoard.makeMove(移动);
int nextPlayer=next(播放器);
双结果=AlphaBetaPlanning(温度板,深度-1,alpha,beta,下一层);
如果((结果<β)){
β=结果;
if(深度==此.origDepth){
this.bestMove=移动;
}
}
如果(β
  • 使用浅层搜索进行节点重新排序非常简单:计算 递归之前状态的每个子级的启发式值 检查它们。然后,对这些状态的值进行排序[降序] 对于最大顶点,升序对于最小顶点],并递归调用 排序列表上的算法。其思想是-如果一个状态擅长 深度较浅,也更可能处于深部状态, 如果这是真的,你会得到更多的修剪

    排序应在之前进行,[在
    if
    else
    子句中]

    for(移动:子对象){

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

    应该在方法的第一行进行更改[类似于
    if(cache.contains((新状态(棋盘,深度,玩家))返回cache.get(新状态(棋盘,深度,玩家))
    ][请原谅我缺乏优雅和效率-在这里仅解释一个想法]。
    您还应该在每个
    return
    语句之前添加
    cache.put(…)


首先,我们必须理解alpha-beta剪枝算法中移动顺序背后的原因。alpha-beta产生与minimax相同的结果,但在许多情况下,它可以更快地完成,因为它不会搜索不相关的分支

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

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

  • 你有一位领域专家,他会给你建议哪些招式更好。例如,在棋子的国际象棋推广中,用低值棋子捕获高值棋子通常是好的招式。在跳棋中,最好在一次移动中杀死更多的棋子,而不是更少的棋子,最好创建一个皇后。因此,你的招式生成功能将n更好的移动之前
  • 通过计算深度小于1的位置(浅层搜索/迭代深化),您可以得到移动效果的启发。您计算了深度n-1处的评估,对移动进行排序,然后在深度n处进行评估

  • 您提到的第二种方法与移动顺序无关。它与一个事实有关,即求值函数可能非常昂贵,而且许多位置需要多次求值。要绕过此方法,您可以在计算位置值后将其存储在哈希中,然后再重新使用。

    考虑到问题中的代码示例,您是否可以请提供一个可能的实现或排序(因此排序和递归调用都在排序列表上)?我对如何实现这一点感到困惑。这是一个非常直观的理论回答,尽管我必须学习第二部分的哈希映射。对于Python,我正在考虑使用类似`{depth:{node:score}`