Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/315.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
极小极大函数中的Python深度复制_Python_Chess_Minimax - Fatal编程技术网

极小极大函数中的Python深度复制

极小极大函数中的Python深度复制,python,chess,minimax,Python,Chess,Minimax,我正在使用带有alpha-beta修剪的minimax算法,用Python创建一个国际象棋引擎。然而,目前速度非常慢,我发现在minimax中执行deepcopy每次迭代的速度与我所有其他函数的速度之和一样慢 有没有办法绕过deepcopy,或者让它更快?下面是我今天的minimax函数。它只能想向前移动3-4步左右,这不是一个很好的引擎。。。任何关于加速算法的建议都将不胜感激 def minimax(board, depth, alpha, beta, maximizing_player):

我正在使用带有alpha-beta修剪的minimax算法,用Python创建一个国际象棋引擎。然而,目前速度非常慢,我发现在minimax中执行deepcopy每次迭代的速度与我所有其他函数的速度之和一样慢

有没有办法绕过deepcopy,或者让它更快?下面是我今天的minimax函数。它只能想向前移动3-4步左右,这不是一个很好的引擎。。。任何关于加速算法的建议都将不胜感激

def minimax(board, depth, alpha, beta, maximizing_player):

    board.is_human_turn = not maximizing_player 

    children = board.get_all_possible_moves()

    if depth == 0 or board.is_draw or board.is_check_mate:
        return None, evaluate(board)

    best_move = random.choice(children)

    if maximizing_player:
        max_eval = -math.inf
        for child in children:
            board_copy = copy.deepcopy(board)
            board_copy.move(child[0][0], child[0][1], child[1][0], child[1][1])
            current_eval = minimax(board_copy, depth - 1, alpha, beta, False)[1]
            if current_eval > max_eval:
                max_eval = current_eval
                best_move = child
            alpha = max(alpha, current_eval)
            if beta <= alpha:
                break
        return best_move, max_eval

    else:
        min_eval = math.inf
        for child in children:
            board_copy = copy.deepcopy(board)
            board_copy.move(child[0][0], child[0][1], child[1][0], child[1][1])
            current_eval = minimax(board_copy, depth - 1, alpha, beta, True)[1]
            if current_eval < min_eval:
                min_eval = current_eval
                best_move = child
            beta = min(beta, current_eval)
            if beta <= alpha:
                break
        return best_move, min_eval
def minimax(棋盘、深度、阿尔法、贝塔、最大化玩家):
board.is_human_turn=未最大化_玩家
儿童=董事会。获得所有可能的动作()
如果深度=0或board.is\u draw或board.is\u check\u mate:
返回无,评估(板)
最佳移动=随机选择(儿童)
如果您是您的玩家:
max_eval=-math.inf
对于儿童中的儿童:
board_copy=复制。深度复制(board)
板拷贝移动(子[0][0]、子[0][1]、子[1][0]、子[1][1])
当前评估=最小最大值(板拷贝,深度-1,α,β,假)[1]
如果当前评估>最大评估:
最大值=当前值
最佳动作=孩子
alpha=最大值(alpha,当前值)

如果beta关于如何优化程序的一些想法(无特定顺序):

1) 如果深度==0或board.is\u draw或board.is\u check\u mate
minimax
函数中执行的第一件事是检查
。现在你调用
board。获取所有可能的移动()
,这些移动可能是多余的(例如,在
深度==0的情况下)

2) 我不知道如何实现
get\u all\u apability\u moves()
方法,并假设它不进行任何排序。一个很好的做法是为minimax算法排序移动,以便从最好的移动到最坏的移动(在这种情况下,您可能会修剪更多节点并加快程序的速度)

3)
for child in children
循环中的
child
变量是一个二维矩阵。我还猜想
board
也是一个多维数组。多维数组可能比一维数组慢,因为它们的内存布局(例如,如果按列遍历它们)。如果可能,请使用一维数组(例如,可以将二维数组表示为一维数组的“串联”)

4) 使用生成器进行延迟计算。例如,您可以将
获取所有可能的移动()
转化为一个生成器,并对其进行迭代,而无需创建列表和消耗额外内存。如果alpha/beta修剪条件提前触发,则不需要扩展该位置中的所有子项列表

5) 通过进行和取消当前移动,避免深入复制板。在这种情况下,您不创建电路板的副本,而是重用原始电路板,这可能会更快:

current_move_info=…#收集并存储进行/取消当前移动所需的信息

board.move(当前移动信息)

current\u eval=minimax(电路板,…[1]

board.unmake_move(当前_move_info)#通过撤消上次移动恢复板位置


6) 添加更经典的优化国际象棋引擎功能,如迭代深化、主要变量搜索、换位表、位盘等。

关于如何优化程序的一些想法(无特定顺序):

1) 如果深度==0或board.is\u draw或board.is\u check\u mate
minimax
函数中执行的第一件事是检查
。现在你调用
board。获取所有可能的移动()
,这些移动可能是多余的(例如,在
深度==0的情况下)

2) 我不知道如何实现
get\u all\u apability\u moves()
方法,并假设它不进行任何排序。一个很好的做法是为minimax算法排序移动,以便从最好的移动到最坏的移动(在这种情况下,您可能会修剪更多节点并加快程序的速度)

3)
for child in children
循环中的
child
变量是一个二维矩阵。我还猜想
board
也是一个多维数组。多维数组可能比一维数组慢,因为它们的内存布局(例如,如果按列遍历它们)。如果可能,请使用一维数组(例如,可以将二维数组表示为一维数组的“串联”)

4) 使用生成器进行延迟计算。例如,您可以将
获取所有可能的移动()
转化为一个生成器,并对其进行迭代,而无需创建列表和消耗额外内存。如果alpha/beta修剪条件提前触发,则不需要扩展该位置中的所有子项列表

5) 通过进行和取消当前移动,避免深入复制板。在这种情况下,您不创建电路板的副本,而是重用原始电路板,这可能会更快:

current_move_info=…#收集并存储进行/取消当前移动所需的信息

board.move(当前移动信息)

current\u eval=minimax(电路板,…[1]

board.unmake_move(当前_move_info)#通过撤消上次移动恢复板位置


6) 添加更经典的优化国际象棋引擎功能,如迭代深化、主要变量搜索、换位表、位盘等。

您好,谢谢您的回答:)1。是的,你是对的。我首先计算,因为这就是它如何找到对位或抽签的。但是如果深度为0,我应该有一个单独的if语句。2.是的,没有分类。它计算每一个动作,一个一个。有没有关于如何排序的实践?例如,是否有需要首先检查的特定部件或需要考虑的其他事项?3-4. 谢谢