当前位置: 首页 > 知识库问答 >
问题:

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

岳正浩
2023-03-14

我有以下奥赛罗(reversi)游戏的阿尔法-贝塔极小值的实现。我已经修复了这个线程中的一些问题。这一次我想改进这个函数的性能。MAX_DEPTH=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));
}

}

实用功能:

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

共有1个答案

屠兴旺
2023-03-14

有几种方法可以加快搜索功能的性能。如果您正确地实现这些技术,那么在修剪许多节点时,它们对算法的准确性几乎不会造成任何损害。

>

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

    您还可以添加开场书。通常,开局动作需要最长的时间来搜索,因为棋盘上充满了更多的可能性。开场白是一个数据库,它存储了前几圈可能做出的每一个动作,以及对它的最佳反应。,在《奥赛罗》中,分支因子很低,这将在开场比赛中特别有用

  •  类似资料:
    • 我目前正在从事我的第一个C项目,并选择使用基于Minimax的AI编写一个Connect Four(又名Score 4),更具体地说是基于Alpha-Beta修剪方法。 到目前为止,我了解到AB修剪包含在一个递归算法中,该算法考虑了一个alpha和一个beta参数,这是您在游戏树中找不到的“极限”。此外,我们定义了最大化和最小化玩家,前者是第一个开始玩游戏的玩家。最后,还有一个“深度”,我把它理解

    • 这是我的极小极大方法,它实现了alpha beta修剪和记忆: 作为一个测试游戏,在我的主要方法中,我在某处放置一个X(X是玩家),然后调用newminimax499查看我应该在哪里放置O(计算机): } 该方法返回计算机应该在何处播放它的O(在本场景中为6),因此我按照指示放置O,自己播放X,调用newminimax499并再次运行代码以查看O要在何处播放,依此类推。 在这次特殊的运行之后,我得

    • 我试图让Alpha-beta修剪工作,但与我的Minimax函数相比,它给了我完全错误的动作。这是我的极大极小函数,它现在工作得很好。 这是我的Alphabeta修剪函数 两者都使用相同的评估,不确定这里出了什么问题。谢谢你的帮助。

    • 在我的方法newminimax49中,我有一个minimax算法,它利用了本文中建议给我的记忆和其他一般性改进。该方法使用一个简单的启发式电路板评估函数。我的问题基本上是关于alpha-beta修剪,即我的minimax方法是否使用alpha-beta修剪。据我所知,我相信这是真的,然而,我用来实现它的东西似乎太简单了,不可能是真的。此外,其他人建议我使用alpha-beta剪枝,正如我所说的,我

    • 我不明白为什么表条目的标志被原样使用。例如,考虑具有α-β修剪和转置表的Negamax的伪代码,并集中于TT部分。 没关系。如果条目包含确切值的下限,我们尝试从左侧缩小窗口,依此类推。 而这部分我不明白。如果值太小,为什么我们设置上限标志?值位于搜索窗口的左侧 - 它小于已知的下限 - alpha。所以看起来值应该是一个下限。 从我的测试和每个人都使用那个版本的事实来看,我肯定是错的。但我不明白为

    • 我正在尝试为一个游戏创建一个AI播放器,使用带有alpha-beta修剪的minimax算法。我在正确地执行它时遇到了一些困难。我有两个功能要使用,一个用于评估给定玩家(返回一些分数)getBoardScore的当前棋盘状态,另一个用于返回每个可能移动(从给定玩家的给定棋盘状态)GetPossibleBoard创建的所有可能棋盘状态。 我的AI通过最初调用alphaBeta,将其传递到当前的板状态