Java 用换位表改进gomokuai的minimax算法?

Java 用换位表改进gomokuai的minimax算法?,java,artificial-intelligence,Java,Artificial Intelligence,我正在为Gomoku(16x16)构建一个带有极大极小值和alpha-beta修剪的AI,但速度非常慢。到目前为止,我已经尝试过对动作顺序进行预排序,而不是深度复制棋盘,添加和删除动作。此外,我还使用了一个相关移动的arraylist(与已放置的块的半径在2以内)来减少搜索栏。然而,即使在3的深度搜索中,人工智能仍在挣扎。 编辑:我发现了一个叫做换位表的东西,但我不知道从哪里开始。任何帮助都会很好 private double minimax(Board node, String player,

我正在为Gomoku(16x16)构建一个带有极大极小值和alpha-beta修剪的AI,但速度非常慢。到目前为止,我已经尝试过对动作顺序进行预排序,而不是深度复制棋盘,添加和删除动作。此外,我还使用了一个相关移动的arraylist(与已放置的块的半径在2以内)来减少搜索栏。然而,即使在3的深度搜索中,人工智能仍在挣扎。
编辑:我发现了一个叫做换位表的东西,但我不知道从哪里开始。任何帮助都会很好

private double minimax(Board node, String player, int depth, double lowerBound, double upperBound){
    if (depth==3){
        return node.evaluate();
    }

    if (player.equals(humanPiece)) {// min node
        // sort setup
        ArrayList<int[]> relevantMoves = node.relevantMoves();
        HashMap<int[], Double> moveValueTable = new HashMap<>();

        for (int[] move: relevantMoves){
            node.addMove(move[0], move[1], player);
            double val = node.evaluate();
            moveValueTable.put(move, val);
            node.retractMove(move[0], move[1]);
        }
        // insertion sort from small to big (alpha-beta optimization)
        insertionSort(relevantMoves, moveValueTable);
        result = Double.POSITIVE_INFINITY;
        // minimax
        for (int[] move : relevantMoves) {  // y first, x second
            node.addMove(move[0], move[1], player);
            double score = minimax(node, node.getEnemy(player), depth+1, lowerBound, upperBound);
            node.retractMove(move[0], move[1]);
            if (score < upperBound) {
                upperBound = score;
            }
            if (score < result) result = score;
            if (lowerBound > upperBound) {
                break;
            }
        }
        return result;
    }

    else{// max node
        // sort setup
        ArrayList<int[]> relevantMoves = node.relevantMoves();
        HashMap<int[], Double> moveValueTable = new HashMap<>();

        for (int[] move: relevantMoves){
            node.addMove(move[0], move[1], player);
            double val = node.evaluate();
            moveValueTable.put(move, val);
            node.retractMove(move[0], move[1]);
        }
        // insertion sort from big to small (alpha-beta optimization)
        reversedInsertionSort(relevantMoves, moveValueTable);
        result = Double.NEGATIVE_INFINITY;
        // minimax
        for (int[] move : relevantMoves) {  // y first, x second
            node.addMove(move[0], move[1], player);
            double score = minimax(node, node.getEnemy(player), depth+1, lowerBound, upperBound);
            node.retractMove(move[0], move[1]);
            if (score > lowerBound) {
                lowerBound = score;
            }
            if (score > result) result = score;
            if (lowerBound > upperBound) {
                break;
            }
        }
        return result;
    }
}
private double minimax(棋盘节点、字符串播放器、整数深度、双下界、双上界){
如果(深度==3){
返回node.evaluate();
}
if(player.equals(humanPiece)){//min节点
//排序设置
ArrayList relevantMoves=节点。relevantMoves();
HashMap moveValueTable=新HashMap();
for(int[]移动:相关移动){
node.addMove(移动[0],移动[1],玩家);
double val=node.evaluate();
moveValueTable.put(move,val);
节点移动(移动[0],移动[1]);
}
//从小到大的插入排序(alpha-beta优化)
insertionSort(相关移动、移动值表);
结果=双正无穷大;
//极小极大
对于(int[]移动:相关移动){//y第一,x第二
node.addMove(移动[0],移动[1],玩家);
双倍得分=极大极小值(节点,节点。敌人(玩家),深度+1,下界,上界);
节点移动(移动[0],移动[1]);
如果(分数<上限){
上限=分数;
}
如果(分数<结果)结果=分数;
如果(下限>上限){
打破
}
}
返回结果;
}
else{//max节点
//排序设置
ArrayList relevantMoves=节点。relevantMoves();
HashMap moveValueTable=新HashMap();
for(int[]移动:相关移动){
node.addMove(移动[0],移动[1],玩家);
double val=node.evaluate();
moveValueTable.put(move,val);
节点移动(移动[0],移动[1]);
}
//从大到小的插入排序(alpha-beta优化)
反向插入排序(相关移动、移动值表);
结果=双负无穷大;
//极小极大
对于(int[]移动:相关移动){//y第一,x第二
node.addMove(移动[0],移动[1],玩家);
双倍得分=极大极小值(节点,节点。敌人(玩家),深度+1,下界,上界);
节点移动(移动[0],移动[1]);
如果(分数>下限){
lowerBound=分数;
}
如果(分数>结果)结果=分数;
如果(下限>上限){
打破
}
}
返回结果;
}
}

以下是关于换位表工作原理的一个很好的解释:

它可以通过消除搜索树中的换位来提高搜索速度。换位是可以通过两个或多个不同的动作序列获得的位置。有些游戏,如国际象棋或跳棋,有大量的换位,其他的很少,甚至没有


一旦你有了转置表,就可以很容易地添加更多依赖于它的速度优化。

下面是转置表工作原理的一个很好的解释:

它可以通过消除搜索树中的换位来提高搜索速度。换位是可以通过两个或多个不同的动作序列获得的位置。有些游戏,如国际象棋或跳棋,有大量的换位,其他的很少,甚至没有


一旦你有了转置表,就很容易添加更多依赖于它的速度优化。

从来没有遇到过这种人工智能的东西,你似乎在做大量的
addMove
retractMove
,但你实际上对它看起来的分钟和最大值感兴趣。与其收集一个包含所有值的表格,不如做一次寻找有趣值的过程?@M.Prokhorov我不明白。你能澄清一下吗?对于你遇到的每个节点,你会重复所有相关的动作两次。我建议只进行一次迭代。不幸的是,这禁止您进行“alpha-beta优化”,不管是什么。您是否实际分析了有无此优化的代码?有帮助吗?如果删除它会发生什么?@M.Prokhorov它帮助了很多bc平均而言,我可以在不必计算的情况下删除搜索树的大部分。如果我删除它们,我会得到最坏的情况。这是否意味着你为了更好的最坏情况而牺牲了你最好的情况?您肯定应该对此进行分析,看看瓶颈在哪里。它甚至可能是
addMove/retractMove
,我们不知道,因为没有关于它的实现细节。由于从未遇到过这种人工智能的东西,您似乎做了很多
addMove
retractMove
,但实际上您对它看起来的分钟和最大值感兴趣。与其收集一个包含所有值的表格,不如做一次寻找有趣值的过程?@M.Prokhorov我不明白。你能澄清一下吗?对于你遇到的每个节点,你会重复所有相关的动作两次。我建议只进行一次迭代。不幸的是,这禁止您进行“alpha-beta优化”,不管是什么。您是否实际分析了有无此优化的代码?有帮助吗?如果删除它会发生什么?@M.Prokhorov它帮助了很多bc平均而言,我可以在不必计算的情况下删除搜索树的大部分。如果我删除它们,我会得到最坏的情况。这是否意味着你为了更好的最坏情况而牺牲了你最好的情况?你一定要有个人资料