使用带有 alpha beta 剪枝的 minimax 算法实现迭代加深 PYTHON

Implementing Iterative Deepening with minimax algorithm with alpha beta pruning PYTHON

我已经实现了一个带有 alpha beta 剪枝的 NegaMax 算法(它只是 minimax 算法的一个较短版本)。现在我想实现迭代深化,以便我可以为每个深度找到最佳移动,然后根据前几层的分数对树下的节点重新排序,以便我的 alphabeta 修剪工作更有效。

这是我目前所做的:

InitialDEPTH = 1

def findBestMove(gs, validMoves):
    global nextMove
    global InitialDEPTH 
    nextMove = None
    
    for d in range(2):
        CurrentDEPTH = InitialDEPTH + d
        findMoveNegaMaxAlphaBeta(gs, validMoves, CurrentDEPTH, -CHECKMATE, CHECKMATE, 1 if gs.whiteToMove else -1)
    
    return nextMove    

这里的 gs 是随着每一步移动而变化的游戏状态,它包含了当时游戏的所有信息,比如是否可以易位或是否可以进行顺势移动。我的 negamax 算法如下所示:

def findMoveNegaMaxAlphaBeta(gs, validMoves, depth, alpha, beta, turnMultiplier):
    global nextMove
    if depth == 0 :
       return turnMultiplier * scoreBoard(gs)    

    maxScore = -CHECKMATE

    # I have a felling i need to add some code here to make it work
    for move in validMoves :
        gs.makeMove(move)
        nextMoves = gs.getValidMoves()
        score = -findMoveNegaMaxAlphaBeta(gs, nextMoves, depth - 1 , -beta, -alpha, -turnMultiplier)
        if score > maxScore:
            maxScore = score
            if depth == DEPTH :
                nextMove = move
        gs.undoMove() 
        if maxScore > alpha:   # This is were pruning happens
            alpha = maxScore
        if alpha >= beta :
            break    

    return maxScore   

我如何将时间限制功能添加到此代码中,以便它仅在提到的时间结束时 returns 最佳移动,而不是在此之前。

另外,如何在每个深度之后重新排序节点以便在下一个深度进行有效修剪。我已经为此编写了某种功能,但我不知道如何实现它。我写的函数:

def sorting(move):
    gs.makeMove(move)
    score = scoreBoard(gs)
    gs.undoMove()

    return turnMultiplier * score
validMoves.sort(key = sorting)
    

据我所知,您有 2 个问题,我将尝试回答这些问题:

  1. 如何将时间限制功能添加到此代码中,以便它仅在上述时间结束时 returns 最佳移动,而不是在此之前。

所以你想搜索每次移动的特定秒数而不是搜索特定深度?这很容易实现,你所要做的就是让迭代加深到某个较大的深度,然后每x个节点将当前时间与搜索开始时间进行比较。像这样:

import time

start_time = time.time()
move_time = 5  # 5 seconds per move
for depth in range(100):
    ...
    score, move = negamax()
    
    # Only save move if you haven't aborted the search at current depth due to time out.
    if move:
        best_score, best_move = score, move

def negamax():
    if time.time() - start_time > move_time:
        return None, None


    ....
    return score, move
  1. 另外,如何在每个深度后重新排序节点以便在下一个深度进行有效修剪。

我不知道您要对当前排序做什么。下面是 negamax 框架通常的样子:

def negamax():
    if depth = 0:
        return evaluation()

    valid_moves = gs.get_valid_moves()

    # Here you sort the moves
    sorted_valid_moves = sort(valid_moves)

    for move in sorted_valid_moves():
        gs.make_move()
        score = -negamax(...)
        gs.unmake_move()

您可以根据多个标准对移动进行排序,您可以阅读有关如何实施每个标准的更多信息here