Java Minimax Alpha-Beta Pruning Recursion Return

我正在尝试在Java中为跳棋游戏实现带有alpha-beta剪枝的minimax算法。我的minimax算法运行得很完美,我的代码也已经包含了alpha-beta剪枝的部分。不幸的是,当我与标准的minimax算法进行1000场比赛时,alpha-beta算法总是落后大约50场。

由于alpha-beta剪枝不应该降低移动的质量,而只是减少实现这些移动所需的时间,所以一定是哪里出了问题。然而,我已经用纸笔画出了假设的叶节点值,并使用我的算法来预测它是否会计算出正确的移动,但似乎没有逻辑错误。我使用了这个视频中的树来追踪我的算法:Alpha-Beta Pruning,逻辑上它应该做出相同的选择,因此应该是一个有效的实现。

我还在代码中添加了打印语句(为了减少混乱,这些语句已经被移除),看起来值是正确返回的,并且确实发生了剪枝。尽管我尽了最大努力,我还是无法找到逻辑错误所在。这是我的第三次尝试实现这个算法,每次都遇到了相同的问题。

我无法在这里发布完整的代码,代码太长了,所以我只包含了与错误相关的部分方法。我不确定,但问题可能出在非递归的move()方法中,尽管我找不到其中的逻辑错误,所以我只是在里面盲目地尝试,可能会使情况变得更糟而不是更好,没有任何理由和根据。

在for循环中从递归调用中恢复多个整数值有什么技巧吗? 它在我的minimax和negamax实现中都能正常工作,但alpha-beta剪枝似乎会产生一些奇怪的结果。

@Overridepublic GameState move(GameState state) {    int alpha = -INFINITY;    int beta = INFINITY;    int bestScore = -Integer.MAX_VALUE;    GameTreeNode gameTreeRoot = new GameTreeNode(state);    GameState bestMove = null;    for(GameTreeNode child: gameTreeRoot.getChildren())    {        if(bestMove == null)        {            bestMove = child.getState();        }        alpha = Math.max(alpha, miniMax(child, plyDepth - 1, alpha, beta));        if(alpha > bestScore)        {            bestMove = child.getState();            bestScore = alpha;        }    }    return bestMove;}private int miniMax(GameTreeNode currentNode, int depth, int alpha, int beta) {    if(depth <= 0 || terminalNode(currentNode.getState()))     {        return getHeuristic(currentNode.getState());    }    if(currentNode.getState().getCurrentPlayer().equals(selfColor))    {        for(GameTreeNode child: currentNode.getChildren())        {            alpha = Math.max(alpha, miniMax(child, depth - 1, alpha, beta));            if(alpha >= beta)            {                return beta;            }        }        return alpha;    }    else    {        for(GameTreeNode child: currentNode.getChildren())        {            beta = Math.min(beta, miniMax(child, depth - 1, alpha, beta));            if(alpha >= beta)            {                return alpha;            }        }        return beta;    }}//Checks to see if the node is terminalprivate boolean terminalNode(GameState state){if(state.getStatus().equals(win) || state.getStatus().equals(lose) || state.getStatus().equals(draw))    {        return true;    }    else    {        return false;    }}

回答:

你已经解决了你的问题,但你遇到的问题相当普遍。所以每当你为AI代理构建算法的一部分时,你必须正确地测试它。因此,一旦你的minimax算法正确,你就可以生成许多随机树并检查结果是否相同。例如,在Python中你可以这样做:

class Node():    def __init__(self, data, children):        self.data = data        self.children = childrendef generateTree(depth, branching):    total = branching**depth    values = [randint(-100, 100) for _ in xrange(total)]    level = [Node(values[i], []) for i in xrange(total)]    for _ in xrange(depth):        total /= branching        level = [Node(None, level[i * branching: (i+1) * branching]) for i in xrange(total)]    return level[0], values

现在你可以生成一个包含许多随机树的树并比较结果。

tree, values = generateTree(depth, branching)print negamax(tree, depth, 1) == alpha_beta_negamax(tree, depth, float('-inf'), float('inf'), 1)

不要忘记minimax和alpha-beta只返回最佳值,而在实际游戏中你感兴趣的是移动。修改它们以返回移动是直接的,但这取决于开发者决定如何返回移动。这是因为可能有许多移动导致最佳解决方案(你可以返回第一个、最后一个,或者最常见的是找到所有移动并返回一个随机的)。

在你的情况下,问题出在返回值的随机性上,所以在测试过程中,固定随机性是一个好的方法。

Related Posts

Keras Dense层输入未被展平

这是我的测试代码: from keras import…

无法将分类变量输入随机森林

我有10个分类变量和3个数值变量。我在分割后直接将它们…

如何在Keras中对每个输出应用Sigmoid函数?

这是我代码的一部分。 model = Sequenti…

如何选择类概率的最佳阈值?

我的神经网络输出是一个用于多标签分类的预测类概率表: …

在Keras中使用深度学习得到不同的结果

我按照一个教程使用Keras中的深度神经网络进行文本分…

‘MatMul’操作的输入’b’类型为float32,与参数’a’的类型float64不匹配

我写了一个简单的TensorFlow代码,但不断遇到T…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注