1

我创建了一个带有 alpha beta 修剪的 minimax 函数,我用迭代加深来调用它。问题是,当计时器完成时,该函数会继续运行,直到它在计时器用完之前开始的深度完成。

我想要什么:当计时器用完时,minimax 函数应该退出并且要么不返回(我将最佳移动保持在 minimax 之外,请参阅下面的 minimax 调用代码),或者返回先前计算的最佳移动。我似乎无法弄清楚如何在 minimax 函数中实现它,我尝试的所有结果都导致它仍然完成它当前的深度。

极小极大函数:

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

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

    gamestate.is_white_turn = not maximizing_player
    children = gamestate.get_valid_moves()

    best_move = children[0]

    if maximizing_player:
        max_eval = -math.inf
        for child in children:
            board_copy = copy.deepcopy(gamestate)
            board_copy.make_move(child)
            current_eval = ai_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(gamestate)
            board_copy.make_move(child)
            current_eval = ai_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 

迭代深化的函数调用:

for depth in range(1, max_search_depth):
    time_start = time.time()
    move, evaluation = minimax(gamestate, depth, alpha, beta, maximizing_player)
    time_end = time.time()
    timer = time_end - time_start
    if timer > max_search_time:
        break 
4

1 回答 1

1

我经常使用自定义类来解决这类问题Timeout

import signal

class TimeoutError(Exception):
    """
    Custom error for Timeout class.
    """

    pass


class Timeout:
    """
    A timeout handler with context manager.
    Based on UNIX signals.
    """

    def __init__(self, seconds=1, error_message="Timeout"):
        self.seconds = seconds
        self.error_message = error_message

    def handle_timeout(self, signum, frame):
        raise TimeoutError(self.error_message)

    def __enter__(self):
        signal.signal(signal.SIGALRM, self.handle_timeout)
        signal.alarm(self.seconds)

    def __exit__(self, type, value, traceback):
        signal.alarm(0)

您可以在with statement这样的内部运行递归函数:

with Timeout(5):
    try:
        result = minimax(gamestate, depth, alpha, beta, maximizing_player)
    except TimeoutError:
        result = None
于 2020-10-13T13:56:53.223 回答