在类失败中调用函数

时间:2015-12-24 13:54:40

标签: python artificial-intelligence

我有问题。我正在尝试建立一个人工智能游戏,我遇到了一个问题。我复制了一个播放器并继承了前一个播放器(类Player(SelectiveAlphaBeta.Player))。现在,我正在制作的游戏树中的搜索是相同的(它只打印每个级别的最高和最低分数 - 只是为了帮助我选择正确的阈值)。然而它崩溃了:

class Player(SelectiveAlphaBeta.Player):
def __init__(self, setup_time, player_color, time_per_k_turns, k):
    SelectiveAlphaBeta.Player.__init__(self, setup_time, player_color, time_per_k_turns, k, 0.25)  # TODO: w

def get_move(self, board_state, possible_moves):
    self.clock = time.process_time()
    self.time_for_current_move = self.time_remaining_in_round / self.turns_remaining_in_round - 0.05
    if len(possible_moves) == 1:
        return possible_moves[0]

    current_depth = 1
    prev_alpha = -INFINITY

    # Choosing an arbitrary move:
    best_move = possible_moves[0]

    if (self.w < 1):
        minimax = MiniMaxWithAlphaBetaPruningWithWDeepeningUntilRestfulness
        (self.utility, self.color, self.no_more_time, self.w)
    else:  # self.w == 1
        minimax = MiniMaxWithAlphaBetaPruning(self.utility, self.color, self.no_more_time)
    time_last_move = 0;
    print('debugger - line 1')

    # Iterative deepening until the time runs out.
    while True:
        print('{} going to depth: {}, remaining time: {}, prev_alpha: {}, best_move: {}'.format(
            self.__repr__(), current_depth, self.time_for_current_move - (time.process_time() - self.clock),
            prev_alpha, best_move))

        time_before = time.process_time()
        time_left = self.time_for_current_move - (time.process_time() - self.clock);
        # if (time_last_move <= time_left):
        try:
            print('debugger - line 2')
            (alpha, move), run_time = run_with_limited_time(
                minimax.search, (board_state, current_depth, -INFINITY, INFINITY, True), {},
                time_left)
            print('debugger - line 3')
        except (ExceededTimeError):
            print('no more time')
            break
        except (MemoryError):
            print('no more memory')
            break
        # else:
        #    print('{} has no enough time ({}) left to go deeper'.format(self.__repr__(), time_left))
        #    break;

        time_after = time.process_time()
        time_last_move = time_after - time_before

        if self.no_more_time():
            print('no more time')
            break

        prev_alpha = alpha
        best_move = move

        if alpha == INFINITY:
            print('the move: {} will guarantee victory.'.format(best_move))
            break

        if alpha == -INFINITY:
            print('all is lost')
            break

        current_depth += 1

    if self.turns_remaining_in_round == 1:
        self.turns_remaining_in_round = self.k
        self.time_remaining_in_round = self.time_per_k_turns
    else:
        self.turns_remaining_in_round -= 1
        self.time_remaining_in_round -= (time.process_time() - self.clock)
    return best_move

def utility(self, state):
    return SelectiveAlphaBeta.Player.utility(self, state)

def no_more_time(self):
    return SelectiveAlphaBeta.Player.no_more_time(self)

def __repr__(self):
    return '{} {}'.format(abstract.AbstractPlayer.__repr__(self), 'SelectiveAlphaBetaWithRestfulness{}'.format(str(self.w)))

没有什么遗漏,因为这是函数的签名:

class MiniMaxWithAlphaBetaPruningWithW(MiniMaxWithAlphaBetaPruning):
def __init__(self, utility, my_color, no_more_time, w):
    MiniMaxWithAlphaBetaPruning.__init__(self, utility, my_color, no_more_time)
    self.w = w

def search(self, state, depth, alpha, beta, maximizing_player):
    """Start the MiniMax algorithm.

    :param state: The state to start from.
    :param depth: The maximum allowed depth for the algorithm.
    :param alpha: The alpha of the alpha-beta pruning.
    :param alpha: The beta of the alpha-beta pruning.
    :param maximizing_player: Whether this is a max node (True) or a min node (False).
    :return: A tuple: (The alpha-beta algorithm value, The move in case of max node or None in min mode)
    """

    if depth == 0 or self.no_more_time():
        return self.utility(state), None

    next_moves = state.legalMoves()
    if not next_moves:
        # This player has no moves. So the previous player is the winner.
        return INFINITY if state.currPlayer != self.my_color else -INFINITY, None

    list = []
    for next_move in next_moves:
        if (self.no_more_time()):
            del list[:]
            return self.utility(state), None
        new_state = copy.deepcopy(state)
        new_state.doMove(next_move)
        list.append((new_state, next_move, self.utility(new_state)))

    list.sort(key=itemgetter(2))
    if (self.no_more_time()):
        del list[:]
        return self.utility(state), None

    if maximizing_player:
        selected_move = next_moves[0]
        best_move_utility = -INFINITY
        for i in range(int(len(list)) - 1, int(len(list)) - int(len(list) * self.w) - 1, -1):
            minimax_value, _ = self.search(list[i][0], depth - 1, alpha, beta, False)
            alpha = max(alpha, minimax_value)
            if minimax_value > best_move_utility:
                best_move_utility = minimax_value
                selected_move = list[i][1]
            if beta <= alpha or self.no_more_time():
                break
        del list[:]
        return alpha, selected_move

    else:
        for i in range(0, int(len(list) * self.w)):
            beta = min(beta, self.search(list[i][0], depth - 1, alpha, beta, True)[0])
            if beta <= alpha or self.no_more_time():
                break
        del list[:]
        return beta, None

class MiniMaxWithAlphaBetaPruningWithWDeepeningUntilRestfulness(MiniMaxWithAlphaBetaPruning):
def __init__(self, utility, my_color, no_more_time, w):
    MiniMaxWithAlphaBetaPruningWithW.__init__(self, utility, my_color, no_more_time, w)
    # self.treshold_restfulness = TODO

def search(self, state, depth, alpha, beta, maximizing_player):
    """Start the MiniMax algorithm.

    :param state: The state to start from.
    :param depth: The maximum allowed depth for the algorithm.
    :param alpha: The alpha of the alpha-beta pruning.
    :param alpha: The beta of the alpha-beta pruning.
    :param maximizing_player: Whether this is a max node (True) or a min node (False).
    :return: A tuple: (The alpha-beta algorithm value, The move in case of max node or None in min mode)
    """

    print('debugger - line 4')

    if depth == 0 or self.no_more_time():
        return self.utility(state), None

    next_moves = state.legalMoves()
    if not next_moves:
        # This player has no moves. So the previous player is the winner.
        return INFINITY if state.currPlayer != self.my_color else -INFINITY, None

    list = []
    for next_move in next_moves:
        if (self.no_more_time()):
            del list[:]
            return self.utility(state), None
        new_state = copy.deepcopy(state)
        new_state.doMove(next_move)
        list.append((new_state, next_move, self.utility(new_state)))

    list.sort(key=itemgetter(2))
    if (self.no_more_time()):
        del list[:]
        return self.utility(state), None

    if maximizing_player:
        selected_move = next_moves[0]
        best_move_utility = -INFINITY
        for i in range(int(len(list)) - 1, int(len(list)) - int(len(list) * self.w) - 1, -1):
            minimax_value, _ = self.search(list[i][0], depth - 1, alpha, beta, False)
            alpha = max(alpha, minimax_value)
            if minimax_value > best_move_utility:
                best_move_utility = minimax_value
                selected_move = list[i][1]
            if beta <= alpha or self.no_more_time():
                break
        print('Utility of best Move in deepening in depth of {} is {}'.format(depth, minimax_value))
        del list[:]
        return alpha, selected_move

    else:
        for i in range(0, int(len(list) * self.w)):
            beta = min(beta, self.search(list[i][0], depth - 1, alpha, beta, True)[0])
            if beta <= alpha or self.no_more_time():
                break
        del list[:]
        return beta, None

错误消息是:

Exception in thread Thread-6:
Traceback (most recent call last):
  File "C:\Python34\lib\threading.py", line 921, in _bootstrap_inner
self.run()
File "C:\Python34\lib\threading.py", line 869, in run
self._target(*self._args, **self._kwargs)
File "C:\Users\Eli\workspace\HW2\amazons\utils.py", line 36, in function_wrapper
result = func(*args, **kwargs)
TypeError: search() missing 1 required positional argument: 'maximizing_player'

为方便原始玩家:

class Player(players.simple_player.Player):
def __init__(self, setup_time, player_color, time_per_k_turns, k, w):
    players.simple_player.Player.__init__(self, setup_time, player_color, time_per_k_turns, k)
    self.w = w;

def get_move(self, board_state, possible_moves):
    self.clock = time.process_time()
    self.time_for_current_move = self.time_remaining_in_round / self.turns_remaining_in_round - 0.05
    if len(possible_moves) == 1:
        return possible_moves[0]

    current_depth = 1
    prev_alpha = -INFINITY

    # Choosing an arbitrary move:
    best_move = possible_moves[0]

    if (self.w < 1):
        minimax = MiniMaxWithAlphaBetaPruningWithW(self.utility, self.color, self.no_more_time, self.w)
    else:  # self.w == 1
        minimax = MiniMaxWithAlphaBetaPruning(self.utility, self.color, self.no_more_time)
    time_last_move = 0;

    # Iterative deepening until the time runs out.
    while True:
        print('{} going to depth: {}, remaining time: {}, prev_alpha: {}, best_move: {}'.format(
            self.__repr__(), current_depth, self.time_for_current_move - (time.process_time() - self.clock),
            prev_alpha, best_move))

        time_before = time.process_time()
        time_left = self.time_for_current_move - (time.process_time() - self.clock);
        # if (time_last_move <= time_left):
        try:
            (alpha, move), run_time = run_with_limited_time(
                minimax.search, (board_state, current_depth, -INFINITY, INFINITY, True), {},
                time_left)
        except (ExceededTimeError):
            print('no more time')
            break
        except (MemoryError):
            print('no more memory')
            break
        # else:
        #    print('{} has no enough time ({}) left to go deeper'.format(self.__repr__(), time_left))
        #    break;

        time_after = time.process_time()
        time_last_move = time_after - time_before

        if self.no_more_time():
            print('no more time')
            break

        prev_alpha = alpha
        best_move = move

        if alpha == INFINITY:
            print('the move: {} will guarantee victory.'.format(best_move))
            break

        if alpha == -INFINITY:
            print('all is lost')
            break

        current_depth += 1

    if self.turns_remaining_in_round == 1:
        self.turns_remaining_in_round = self.k
        self.time_remaining_in_round = self.time_per_k_turns
    else:
        self.turns_remaining_in_round -= 1
        self.time_remaining_in_round -= (time.process_time() - self.clock)
    return best_move

为方便起见 - run_with_limited_time:

def run_with_limited_time(func, args, kwargs, time_limit):
"""Runs a function with time limit

:param func: The function to run.
:param args: The functions args, given as tuple.
:param kwargs: The functions keywords, given as dict.
:param time_limit: The time limit in seconds (can be float).
:return: A tuple: The function's return value unchanged, and the running time for the function.
:raises PlayerExceededTimeError: If player exceeded its given time.
"""
q = Queue()
t = Thread(target=function_wrapper, args=(func, args, kwargs, q))
t.start()

# This is just for limiting the runtime of the other thread, so we stop eventually.
# It doesn't really measure the runtime.
t.join(time_limit)

if t.is_alive():
    raise ExceededTimeError

q_get = q.get()
if isinstance(q_get, MemoryError):
    raise q_get
return q_get

当然没有提及对象仅运行它的游戏的功能。我不知道为什么会这样。它一定是非常愚蠢但我不知道......我只做了一个简单的代码副本,我没有改变这一行......

提前致谢, 利

1 个答案:

答案 0 :(得分:2)

你的问题在这里:

    minimax = MiniMaxWithAlphaBetaPruningWithWDeepeningUntilRestfulness
    (self.utility, self.color, self.no_more_time, self.w)

这些实际上是两个单独的行,第二行没有任何作用,而你打算将它作为单个表达式。它会将minimax指定为类本身而不是实例,这会在以后调用类上的方法时导致问题。

您可以将所有内容放在一行上,或者只是将左括号移到第一行(因为当括号打开时,Python允许表达式在下一行继续):

minimax = MiniMaxWithAlphaBetaPruningWithWDeepeningUntilRestfulness(
    self.utility, self.color, self.no_more_time, self.w)