【问题标题】:Optimizing chess engine using minimax使用 minimax 优化国际象棋引擎
【发布时间】:2020-08-06 10:40:38
【问题描述】:

我在 python 中使用 minimax 算法开发了一个国际象棋引擎,并且我还使用 Alpha-Beta Pruning 对其进行了进一步优化。目前我正在搜索 4 的深度,虽然不是很多,但仍然需要 10 - 60 秒才能想到一个动作。

减慢程序的主要因素是一次又一次地迭代。我首先在deque.collection() 中生成所有可能的移动,然后我遍历它一次以验证它。现在我再次遍历它以评估这些动作,然后比较它们以获得最佳可能的动作。我在整个过程中都使用 for 循环,所有可能的移动的格式是集合(移动)的集合(mainmoves)

我可以做些什么来优化它并减少生成移动所需的时间。

def minimaxRoot(depth,isMaximizing):
    global board
    possibleMoves = gen(False)
    bestMove = -math.inf
    bestMoveFinal = None
    for move in possibleMoves:
        orig = normperform(move)
        value = max(bestMove, minimax(depth - 1,not isMaximizing,-math.inf,math.inf))
        undo(move,orig)
        if value > bestMove:
            bestMove = value
            bestMoveFinal = move
    return bestMoveFinal

def minimax(depth,ismax,alpha,beta):
    global board
    if depth == 0:
        return calcpoints()
    maxeval = -math.inf
    mineval = math.inf
    if ismax == True:
        mainmoves = gen(False)
        if mainmoves == 'mate':
            return 8000
        for move in mainmoves:
            orig = normperform(move)
            eval = minimax(depth-1,False,alpha,beta)
            undo(move,orig)
            maxeval=max(eval,maxeval)
            alpha = max(alpha,eval)
            if beta <= alpha:
                break
        return maxeval
    elif ismax == False:
        mainmoves2 = gen(True)
        if mainmoves2 == 'mate':
            return 8000
        for move2 in mainmoves2:
            orig2 = normperform(move2)
            eval2 = minimax(depth-1,True,alpha,beta)
            undo(move2,orig2)
            mineval = min(mineval,eval2)
            if eval2 < beta:
                beta = eval2
            if beta <= alpha:
                break
        return mineval

【问题讨论】:

    标签: python loops optimization chess minimax


    【解决方案1】:

    有两个主要问题导致您的国际象棋引擎搜索深度低:

    1. 首先,您没有实施移动排序。搜索完成所需的时间在很大程度上取决于它访问的节点。我建议您在每次搜索迭代中计算引擎访问的节点数。理想情况下,您不应该一次计算所有移动,或者至少搜索那些很有可能首先成为最佳移动的移动(例如捕获)。这样,您可以增加早期 Beta 截止的机会。移动排序对于搜索算法至关重要。您可以阅读更多关于移动订购的信息here
    2. Python 并不是实现高性能国际象棋引擎的最佳语言。使用 CC++ 之类的编译语言会更好。虽然 Python 中有一个名为 Sunfish 的引擎,但我认为它的 ELO 强度约为 2000。

    【讨论】:

      【解决方案2】:

      我试图用 Python 做同样的事情,这就是我所做的让我的引擎在大约 30 秒内搜索深度为 5 的板。

      • 缓存移动生成。使用functools.lru_cache,这样库就不必重复生成动作。 这是让我的引擎从深度 4 跳到深度 5 的步骤。请注意,lru_cache 使用哈希表来缓存键,但 chess.Board 默认情况下不可哈希。然而,这可以通过使用chess.Board.__hash__ = chess.polyglot.zobrist_hash 来解决。这样,您可以缓存有序移动列表,进一步提高其速度。
      • 如@Momo 所述,使用移动排序。他/她做了很好的推理和解释,所以我不会再重复一遍了。
      • 使用 Python chess library。我不确定你是否在使用它,但它提供了一个速度不错的棋盘模型。它也适用于functools.lru_cache,使用上述方法。
      • 使用职位空缺数据和职位空缺搜索器。您可以使用数据here 让您的引擎使用空位,无需时间计算,同时也为早期游戏提供更好的结果。

      您可能只是为了好玩和实验而在 Python 中进行此操作,因此我鼓励您首先在 Python 中尝试此操作。但如果这是为了认真使用,您可能希望在 C 或 C++ 中实现它,或者使用 Stockfish 等引擎。

      嗯,就是这样。希望能帮助到你。 ;)

      【讨论】:

        猜你喜欢
        • 2015-05-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-11
        • 2022-01-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多