Альфа-бета-обрезка: узлы сортировки

Я создаю соединение четырех ИИ. У меня проблемы с оптимизацией сокращения альфа-бета. В Википедии говорится, что сортировка узлов таким образом, что мы сначала пробуем наиболее вероятные (то есть те, которые с наибольшей вероятностью вызовут отсечку альфа/бета), повысит производительность без изменения результатов. Вот мой код без сортировки. Кажется, это работает нормально.

def minimax_i(board, start_depth):
    """Return the highest valued move by minimaxing."""
    best_value = -100000
    best_move = None
    alpha = -100000
    beta = 100000
    moves = board.get_valid_moves()
    for move in moves:
        value = minimax_r(board.make_move(move), board.nextplayer, alpha, beta, start_depth)
        if value > best_value:
            best_value = value
            best_move = move
        if alpha >= beta:
            break
    return best_move

def minimax_r(board, player, alpha, beta, depth):
    result = board.winner()
    if result != -1: # If game is finished
        if result == 0:
            return 0
        if result == player:
            return 1000 + depth
        return -(1000 + depth)
    if depth <= 0:
        return heuristic(board, player)

    moves = board.get_valid_moves()
    if board.nextplayer == player: # Maximizing
        best_value = -100000
        for move in moves:
            score = minimax_r(board.make_move(move), player, alpha, beta, depth-1)
            best_value = max(best_value, score)
            alpha = max(alpha, best_value)
            if alpha >= beta:
                break
        return best_value

    else: # Minimizing
        best_value = 100000
        for move in moves:
            score = minimax_r(board.make_move(move), player, alpha, beta, depth-1)
            best_value = min(best_value, score)
            beta = min(beta, best_value)
            if alpha >= beta:
                break
        return best_value

Изменение moves = board.get_valid_moves() на moves = sorted(board.get_valid_moves(), key = lambda x: abs(board.lastmove[0]-x)) должно заставить его сначала проверять ходы, которые граничат с последним ходом, наивная, но, надеюсь, полезная эвристика упорядочения. Проблема в том, что он изменяет результаты поиска.

Единственное, о чем я могу думать, это то, что я должен распространять изменения в альфа- и бета-версии, которые происходят в дочерних узлах, на родительские узлы. Любые идеи?


person Slickytail    schedule 19.01.2018    source источник


Ответы (1)


Невозможно точно определить вашу проблему, но я могу дать вам некоторые идеи, которые помогут вам. Во-первых, вы написали:

Единственное, о чем я могу думать, это то, что я должен распространять изменения в альфа- и бета-версии, которые происходят в дочерних узлах, на родительские узлы. Любые идеи?

Это неправильно. Интуиция, стоящая за альфа-бета-отсечением, заключается в том, что если эта ветвь никогда не будет достигнута, потому что более ранний узел не выбрал ее, эту ветвь обрезают. Альфа и бета — это границы лучших ходов, найденных ранее узлами. Распространение альфы и беты вверх по дереву не имеет смысла. Если это все еще неясно для вас, я предлагаю убедиться, что вы хорошо понимаете алгоритм, прежде чем двигаться дальше.

Теперь, что касается вашей проблемы: в вашем предположении есть небольшая неточность, но она имеет очень большое значение. Вы написали:

В Википедии говорится, что сортировка узлов таким образом, что мы сначала пробуем наиболее вероятные (то есть те, которые с наибольшей вероятностью вызовут отсечку альфа/бета), повысит производительность без изменения результатов.

Это в основном верно, но не полностью, хотя Википедия и говорит об этом. Сокращение альфа-бета не изменит значение результата. Это означает, что если обычный минимакс говорит, что ход x стоит 5 в соответствии с используемой вами эвристической функцией оценки, сокращение альфа-бета также вернет это. Однако, если два хода имеют одинаковую ценность, то есть ни один из них не лучше другого, для сокращения альфа-бета нормально возвращать другой ход, поскольку изменение порядка ходов может привести к тому, что один ход будет виден первым.

Так что проверьте. это возвращает другой ход равной ценности, но все же оценивает все ходы как имеющие ту же ценность, что и минимакс? Это нормально. Это приводит к тому, что ходы на самом деле оцениваются по-разному? Это серьезная ошибка.

Если вы обнаружите, что последнее верно, это, вероятно, вызвано тем, что ваш порядок ходов непреднамеренно пропускает ходы из списка. Другой возможной причиной может быть неправильная реализация алгоритма, но, судя по вашему коду, все в порядке.

person chessprogrammer    schedule 22.01.2018