Java 用换位表改进gomokuai的minimax算法?
我正在为Gomoku(16x16)构建一个带有极大极小值和alpha-beta修剪的AI,但速度非常慢。到目前为止,我已经尝试过对动作顺序进行预排序,而不是深度复制棋盘,添加和删除动作。此外,我还使用了一个相关移动的arraylist(与已放置的块的半径在2以内)来减少搜索栏。然而,即使在3的深度搜索中,人工智能仍在挣扎。Java 用换位表改进gomokuai的minimax算法?,java,artificial-intelligence,Java,Artificial Intelligence,我正在为Gomoku(16x16)构建一个带有极大极小值和alpha-beta修剪的AI,但速度非常慢。到目前为止,我已经尝试过对动作顺序进行预排序,而不是深度复制棋盘,添加和删除动作。此外,我还使用了一个相关移动的arraylist(与已放置的块的半径在2以内)来减少搜索栏。然而,即使在3的深度搜索中,人工智能仍在挣扎。 编辑:我发现了一个叫做换位表的东西,但我不知道从哪里开始。任何帮助都会很好 private double minimax(Board node, String player,
编辑:我发现了一个叫做换位表的东西,但我不知道从哪里开始。任何帮助都会很好
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平均而言,我可以在不必计算的情况下删除搜索树的大部分。如果我删除它们,我会得到最坏的情况。这是否意味着你为了更好的最坏情况而牺牲了你最好的情况?你一定要有个人资料