C++ 使用AlphaBeta修剪改进此MiniMax的性能

C++ 使用AlphaBeta修剪改进此MiniMax的性能,c++,artificial-intelligence,minimax,alpha-beta-pruning,C++,Artificial Intelligence,Minimax,Alpha Beta Pruning,我为奥赛罗(reversi)游戏实现了以下alpha-beta-minimax。我已经从线程修复了它的一些问题。这次我想改进这个函数的性能。最大深度=8需要很长时间。可以做些什么来提高性能,同时保持AI的良好性能 mm_out minimax(Grid& G, int alpha, int beta, Action& A, uint pn, uint depth, bool stage) { if (G.check_terminal_state() || depth ==

我为奥赛罗(reversi)游戏实现了以下alpha-beta-minimax。我已经从线程修复了它的一些问题。这次我想改进这个函数的性能。最大深度=8需要很长时间。可以做些什么来提高性能,同时保持AI的良好性能

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));
}

有几种方法可以加快搜索功能的性能。如果您正确地实现了这些技术,那么在修剪多个节点时,它们对算法的准确性几乎没有影响

  • 您可以实现的第一种技术是转置表。换位表将游戏搜索树中以前访问过的所有节点存储在哈希表中。大多数游戏状态,特别是在深度搜索中,都可以通过各种换位,或者在相同的最终状态下重新出现的移动顺序来达到。通过存储先前搜索的游戏状态,如果您发现已搜索的状态,则可以使用存储在表中的数据并停止在该节点深化搜索。将游戏状态存储在哈希表中的标准技术称为Zobrist哈希。有关转置表实现的详细信息可在web上获得
  • 你的程序应该包括的第二件事是移动顺序。这本质上意味着检查移动不是按照你生成移动的顺序,而是按照最有可能产生alpha-beta截止的顺序(即先检查好的移动)。显然,你不知道哪一步是最好的,但大多数动作都可以使用简单的技术来排序。例如,在《奥赛罗》中,一个在角落或边缘的动作应该首先被检查。排序移动应该会导致更多的截取和搜索速度的提高。这对精度造成了零损失

  • 您还可以添加打开的书籍。通常,开场白的搜索时间最长,因为棋盘上充满了更多的可能性。开场白是一个数据库,它存储了在前几个回合中可以做出的每一个可能的动作,以及对它的最佳反应。在《奥赛罗》中,分支因子较低,这在开场白游戏中尤其有用

  • 普罗布卡特。我不打算在这里详细介绍,因为这是一种更先进的技术。然而,它在奥赛罗身上有很好的效果,所以我想我应该发布这个链接

不应包含严格不需要的代码(如调试输出)。请编辑您的问题以将其删除。完成。谢谢通知。谢谢回复!我已经做了第二次,因为我的文章,我注意到一个小,但明显的速度增加。我去看看其他的。
int Grid::get_utility(uint pnum) const {
    if (pnum)
        return wcount - bcount;
    return bcount - wcount;
}