在Negamax中保存有效的移动几乎不会导致速度差异

问题描述

我有一个带有alpha-beta修剪的普通Negamax算法,该算法是通过迭代加深(ID)启动的。我认为要真正使用ID,我会将计算出的深度1的有效移动保存在表中,所以下次我去深度2且原始位置相同时,我可以直接从表中获取有效的移动以节省时间。但是,我发现这个想法根本没有节省任何时间,这确实让我觉得:

  1. 我从未见过有人这样做,出于某种原因值得吗?
  2. 我对此的实现是错误的吗?
  3. 我对Negamax的工作方式感到困惑,也许一开始这不可能做到?

这是原始的迭代调用,以及Negamax函数本身的摘要

self.valid_moves_history = []
for depth in range(1,s.max_search_depth):
    move,evaluation = self.negamax(gamestate,depth,-math.inf,math.inf,s.start_color)

# ----------------------------------------------------------------------------

def negamax(self,gamestate,alpha,beta,color):

    if self.zobrist_key in self.valid_moves_history:
        children = self.valid_moves_history[self.zobrist_key]
    else:
        children = gamestate.get_valid_moves()
        self.valid_moves_history[key] = children

    if depth == 0 or gamestate.is_check_mate or gamestate.is_stale_mate:
        return None,e.evaluate(gamestate,depth) * color

    # Negamax loop
    max_eval = -math.inf
    for child in reversed(children):
        gamestate.make_move(child[0],child[1])
        score = -self.negamax(gamestate,depth - 1,-beta,-alpha,-color)[1]
        gamestate.unmake_move()
        if score > max_eval:
            max_eval = score
            best_move = child
        alpha = max(alpha,max_eval)
        if beta <= alpha:
            break

我的完整程序中最耗时的任务分配如下(占游戏总运行时间的百分比):

  • 计算有效举动:60%
  • 评估功能(目前中等复杂度):25%
  • Negamax本身具有查找,表保存等功能:5%
  • 进行/取消动作:4%

计算出的移动时间这么高是否正常/合理?这就是为什么我首先想到将有效移动保存在列表中的主要原因。

或者有人可以解释一下为什么这是个好主意,我应该怎么做?谢谢您的投入。

解决方法

我知道这个帖子在这一点上已经很老了,但我认为这对某些人来说仍然有用。您正在谈论的整个主题在 Minimax 中称为换位表,您可以找到许多指向该主题的链接。 Negamax 与 Minimax 相同,只是您没有针对 Max 和 Min 玩家的单独函数,而您只需调用 max 函数并将其转换为负数。我认为首先实现移动排序对您来说可能更有用,因为它可以使您的程序速度加倍。您还可以找到一种更有效的方法来找到有效的动作来加速程序。