当前位置: 首页 > 知识库问答 >
问题:

使用alpha beta修剪PYTHON实现迭代深化与极小极大算法

薛滨海
2023-03-14

我已经实现了一个带有alpha beta修剪的NegaMax算法(这只是一个较短版本的极小值算法)。现在我想实现迭代深化,这样我就可以为每个深度找到最佳移动,然后根据之前层的分数重新排序树下的节点,以便我的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是随每一步移动而变化的游戏属性,包含了所有关于游戏在t点的信息,比如是否可以施法或者是否有可能的内移。我的egamax算法如下所示:

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   

如何将时间约束函数添加到此代码中,使其仅在所述时间结束时返回最佳移动,而不是在此之前。

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

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

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

共有1个答案

苗康平
2023-03-14

在我看来,你有两个问题,我会试着回答:

  1. 如何将时间约束函数添加到此代码中,以便它只在提到的时间结束时返回最佳移动,而不是在此之前。

所以你想搜索每个移动的一定秒数,而不是搜索特定的深度?这很容易实现,你所要做的就是让迭代深化到某个大深度,然后将当前时间与每个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

我不知道您当前的排序操作是什么。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()

你可以根据几个标准对动作进行排序,你可以在这里阅读更多关于如何实现每个标准的信息。

 类似资料:
  • 我在做什么:我正在用C编写一个象棋引擎。我最近更新了我的引擎的minimax搜索算法,该算法使用alpha-beta修剪来利用迭代深化,以便在时间限制下运行。这是它的外观: 我的问题:这个实现的问题是,当搜索任何大于1的深度时,它将在搜索所需深度之前搜索所有之前的深度。也就是说,此迭代深化搜索首先搜索深度为1的所有移动。然后,它将再次搜索深度1,然后再搜索深度2,而不是在下一次搜索时选择深度2。然

  • 我最近实现了极小极大和阿尔法贝塔修剪算法,我100%确定(自动分级器)我正确地实现了它们。但是当我执行我的程序时,它们的行为不同。我99%确定极小极大和阿尔法贝塔的结束状态应该是相同的。我说得对吗?它们在实现结果的路径上会有所不同吗?因为我们忽略了min将选择的一些值,而max不会选择这些值,反之亦然。

  • 我已经为游戏跳棋编写了一个带有alpha-beta修剪的minimax算法,现在我正尝试使用negamax方法重写它。我希望这两者是等价的,因为negamax只是一种编写minimax的技术。但由于某种原因,我的两种算法表现不同。当我在相同的输入上运行它们时,negamax版本似乎评估了更多的状态,所以我认为alpha-beta修剪一定有问题。 下面的代码显示了这两种算法(

  • 我想我终于对minimax和Alpha-beta修剪有所了解了,但实现它完全是另一回事! 根据我的理解,基础是:您为某些动作分配一个启发式函数分数(Gomoku为例)。 如果一行有5个,我们应该分配一个高值,比如9999,因为这是一个胜利的举动 当我们必须在Java中实现这一点时,我的问题来了! 我有一块彩色[][]板(8x8),其中黑色是播放器1,白色是播放器2,null表示空白,我不知道我们应

  • 计算机科学中最有趣的事情之一就是编写一个人机博弈的程序。有大量的例子,最出名的是编写一个国际象棋的博弈机器。但不管是什么游戏,程序趋向于遵循一个被称为Minimax算法,伴随着各种各样的子算法在一块。本篇将简要介绍 minimax 算法,并通过实例分析帮助大家更好的理解。 一、概念 Minimax算法又名极小化极大算法,是一种找出失败的最大可能性中的最小值的算法。Minimax算法常用于棋类等由两

  • 我试图在我的象棋引擎中实现alpha-beta剪枝,但没有性能差异,我可能做错了什么?我试着用控制台记录算法剪切一个分支的次数,但它的数量是数百次,因此它可以正确地修剪搜索树。即使这样,该算法也没有明显的性能改进。 董事会评估平均需要80毫秒左右。使用alpha-beta修剪,查看深度3时,minimax/alpha-beta算法需要1.8秒,而不使用minimax/alpha-beta算法需要1