Alpha-Beta修剪:对节点

时间:2018-01-19 08:44:44

标签: python optimization minimax

我正在创建一个连接四个AI。我遇到了alpha-beta修剪优化的问题。维基百科说,对节点进行排序,以便我们首先尝试最可能的节点(即最有可能强制执行alpha / beta截断的节点)将在不改变结果的情况下提高性能。这是我的代码没有排序。它似乎工作正常。

def minimax_i(board, start_depth):
    """Return the highest valued move by minimaxing."""
    best_value = -100000
    best_move = None
    alpha = -100000
    beta = 100000
    moves = board.get_valid_moves()
    for move in moves:
        value = minimax_r(board.make_move(move), board.nextplayer, alpha, beta, start_depth)
        if value > best_value:
            best_value = value
            best_move = move
        if alpha >= beta:
            break
    return best_move

def minimax_r(board, player, alpha, beta, depth):
    result = board.winner()
    if result != -1: # If game is finished
        if result == 0:
            return 0
        if result == player:
            return 1000 + depth
        return -(1000 + depth)
    if depth <= 0:
        return heuristic(board, player)

    moves = board.get_valid_moves()
    if board.nextplayer == player: # Maximizing
        best_value = -100000
        for move in moves:
            score = minimax_r(board.make_move(move), player, alpha, beta, depth-1)
            best_value = max(best_value, score)
            alpha = max(alpha, best_value)
            if alpha >= beta:
                break
        return best_value

    else: # Minimizing
        best_value = 100000
        for move in moves:
            score = minimax_r(board.make_move(move), player, alpha, beta, depth-1)
            best_value = min(best_value, score)
            beta = min(beta, best_value)
            if alpha >= beta:
                break
        return best_value

moves = board.get_valid_moves()更改为moves = sorted(board.get_valid_moves(), key = lambda x: abs(board.lastmove[0]-x)) 应该使其检查最后一次移动边界的移动,这是一种天真但有希望有用的排序启发式算法。问题是它会更改搜索结果。

我唯一能想到的是,我应该将对子节点中发生的alpha和beta的更改传播回父节点。有什么想法吗?

1 个答案:

答案 0 :(得分:0)

无法确定您的问题,但我可以为您提供一些有用的见解。首先,你写道:

  

我唯一能想到的是,我应该将对子节点中发生的alpha和beta的更改传播回父节点。有什么想法吗?

这是不正确的。 alpha-beta修剪背后的直觉是,如果因为早期节点不会选择它而永远不会到达此分支,则修剪此分支。 Alpha和beta是早期节点找到的最佳移动的边界。传播alpha和beta备份树是没有意义的。如果您仍然不清楚,我建议您在继续之前确保掌握算法。

现在,关于你的问题是什么:你的假设存在轻微的不准确性,但它会产生很大的差异。你写道:

  

维基百科说,对节点进行排序,以便我们首先尝试最可能的节点(即最有可能强制执行alpha / beta截断的节点),这样可以在不改变结果的情况下提高性能。

这大部分都是正确的,但并非完全如此,尽管维基百科确实这么说。 Alpha-beta修剪不会改变结果的值。这意味着如果常规极小极大显示根据您正在使用的启发式评估函数,移动x值为5,则alpha-beta修剪也将返回该值。但是,如果两个移动具有相同的值,那么这两个移动都不比另一个更好,alpha-beta修剪返回不同的移动是正常的,因为移动顺序的变化可能导致首先看到一个移动。

所以检查一下。这是否会返回同等价值的不同移动,但仍然评估所有移动与minimax具有相同的值?这个是正常的。是否导致实际上不同地评估了移动?这是一个严重的错误。

如果你发现后者是真的,很可能是因为你的移动命令无意中忽略了列表中的移动。另一个可能的原因是算法的实现不正确,但是从你的代码来看似乎没问题。