Улучшение производительности этого MiniMax с помощью обрезки AlphaBeta

У меня есть следующая реализация минимаксного альфа-бета для игры othello (reversi). Я исправил несколько проблем из этот нить. На этот раз я хотел бы улучшить производительность этой функции. С MAX_DEPTH = 8 это занимает очень много времени. Что можно сделать, чтобы повысить производительность, сохранив при этом ИИ на приличном уровне?

mm_out minimax(Grid& G, int alpha, int beta, Action& A, uint pn, uint depth, bool stage) {
    if (G.check_terminal_state() || depth == MAX_DEPTH) {
        return mm_out(A, G.get_utility(pn));
    }

    // add end game score total here

    set<Action> succ_temp = G.get_successors(pn);
    for (Action a : succ_temp) {
        Grid gt(G);
        a.evaluate(gt);
    }
    set<Action, action_greater> successors(succ_temp.begin(), succ_temp.end());

    // if no successor, that player passes
    if (successors.size()) {
        for (auto a = successors.begin(); a != successors.end(); ++a) {
            Grid gt(G);
            gt.do_move(pn, a->get_x(), a->get_y(), !PRINT_ERR);
            Action at = *a;
            mm_out mt = minimax(gt, alpha, beta, at, pn ^ 1, depth + 1, !stage);
            int temp = mt.val;
//          A = mt.best_move;

            if (stage == MINIMAX_MAX) {
                if (alpha < temp) {
                    alpha = temp;
                    A = *a;
                }
                if (alpha >= beta) {
                    return mm_out(A, beta);
                }
            }
            else {
                if (beta > temp) {
                    beta = temp;
                    A = *a;
                }
                if (alpha >= beta) {
                    return mm_out(A, alpha);
                }


}
    }
    return mm_out(A, (stage == MINIMAX_MAX) ? alpha : beta);
}
else {
    return mm_out(A, (stage == MINIMAX_MAX) ? (std::numeric_limits<int>::max() - 1) : (std::numeric_limits<int>::min() + 1));
}

}

Вспомогательная функция:

int Grid::get_utility(uint pnum) const {
    if (pnum)
        return wcount - bcount;
    return bcount - wcount;
}

person SenselessCoder    schedule 13.12.2015    source источник
comment
MCVE не должен содержать код, который не является строго необходимым (например, выходные данные отладки). Пожалуйста, отредактируйте свой вопрос, чтобы удалить его.   -  person IInspectable    schedule 13.12.2015
comment
Сделанный. Спасибо, что сообщили.   -  person SenselessCoder    schedule 13.12.2015


Ответы (1)


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

  • Первый метод, который вы можете реализовать, — это таблица транспонирования. Таблицы транспонирования хранят в хэш-таблице все ранее посещенные узлы в дереве поиска вашей игры. Большинство игровых состояний, особенно при глубоком поиске, могут быть достигнуты с помощью различных транспозиций или порядков ходов, которые возвращаются в одно и то же конечное состояние. Сохраняя ранее найденные игровые состояния, если вы найдете уже найденное состояние, вы можете использовать данные, хранящиеся в таблицах, и прекратить углублять поиск в этом узле. Стандартный метод хранения игровых состояний в хеш-таблице называется хэшированием по Зобристу. Подробная информация о реализации таблиц транспонирования доступна в Интернете.
  • Второе, что должна включать ваша программа, — это порядок ходов. По сути, это означает, что вы должны проверять ходы не в том порядке, в котором вы их генерируете, а в том порядке, в котором наиболее вероятно получение альфа-бета-отсечки (т. е. сначала хорошие ходы). Очевидно, вы не можете знать, какие ходы лучше, но большинство ходов можно упорядочить, используя наивную технику. Например, в «Отелло» ход, который находится в углу или ребре, должен быть рассмотрен в первую очередь. Упорядочивание ходов должно привести к большему количеству отсечек и увеличению скорости поиска. Это обеспечивает нулевую потерю точности.

  • Вы также можете добавить открывающие книги. Обычно поиск первых ходов занимает больше всего времени, так как на доске больше возможностей. Книга дебютов — это база данных, в которой хранятся все возможные ходы, которые можно сделать за первые несколько ходов, и лучший ответ на них., В «Отелло» , с низким коэффициентом ветвления, это будет особенно полезно в дебютной игре.

  • Проб. Я не буду вдаваться в подробности здесь, так как это более продвинутая техника. Однако с Отелло он дал хорошие результаты, поэтому я решил опубликовать эту ссылку.https://chessprogramming.wikispaces.com/ProbCut
person chessprogrammer    schedule 14.12.2015
comment
Спасибо за ответ! Сделал 2-й с момента моего поста, заметил небольшой, но заметный прирост скорости. Я собираюсь посмотреть на других. - person SenselessCoder; 14.12.2015