【问题标题】:Difficulty implementing Alpha-beta pruning to minimax algorithm难以实现 Alpha-beta 修剪到 minimax 算法
【发布时间】:2018-03-05 23:37:21
【问题描述】:

我在让 Alpha-beta 修剪正常工作时遇到了一些困难。 我有一个功能性的 Minimax 算法,我试图适应它,但无济于事。我用了Wikipedia上的例子

目前,该算法似乎在大多数情况下都按预期运行,但随后它无论如何都会选择第一个测试的节点。

这可能是由于缺乏理解,但我已经花了几个小时阅读这个。让我感到困惑的是,当算法在零和游戏中达到其深度限制时,它应该如何知道哪个节点是最佳选择?到那时还不能确定哪位球员会从这样的举动中受益最多,不是吗?

无论如何,我的 .cpp 在下面。我原来的 minimax 函数和任何帮助都将不胜感激!

AIMove ComputerInputComponent::FindBestMove() {

const Graph<HexNode>* graph = HexgameCore::GetInstance().GetGraph();

std::vector<AIMove> possibleMoves;

FindPossibleMoves(*graph, possibleMoves);

AIMove bestMove = AIMove();

int alpha = INT_MIN;
int beta = INT_MAX;
int depth = 6;

Node* currentNode;

for (const AIMove &move : possibleMoves) {

    std::cout << move << std::endl;

    graph->SetNodeOwner(move.x, move.y, (NodeOwner)aiPlayer);
    int v = MiniMaxAlphaBeta(*graph, depth, alpha, beta, true);
    graph->SetNodeOwner(move.x, move.y, NodeOwner::None);

    if (v > alpha) {
        alpha = v;
        bestMove.x = move.x;
        bestMove.y = move.y;
    }
}
return bestMove;

}

template<typename T>

int ComputerInputComponent::MiniMaxAlphaBeta(const Graph& graph, int depth, int alpha, int beta, bool isMaximiser) {

std::vector<AIMove> possibleMoves;
FindPossibleMoves(graph, possibleMoves);

if (lastTestedNode != nullptr) {
    Pathfinder pathFinder;
    bool pathFound = pathFinder.SearchForPath(lastTestedNode, graph.GetMaxX(), graph.GetMaxY());
    if (pathFound) {
        //std::cout << "pathfound-" << std::endl;
        if ((int)lastTestedNode->GetOwner() == aiPlayer) {
            std::cout << "cpuWin-" << std::endl;
            return 10;
        } 
        else if ((int)lastTestedNode->GetOwner() == humanPlayer) {
            std::cout << "playerWin-" << std::endl;
            return -10;
        }
    }
    else {
        if (depth == 0) {           
            //std::cout << "NoPath-" << std::endl;
            return 0;
        }
    }
}


if (isMaximiser) {// Max
    int v = -INT_MAX;
    for (const AIMove &move : possibleMoves) {
        graph.SetNodeOwner(move.x, move.y, (NodeOwner)aiPlayer);
        graph.FindNode(move.x, move.y, lastTestedNode);
        v = std::max(alpha, MiniMaxAlphaBeta(graph, depth - 1, alpha, beta, false));
        alpha = std::max(alpha, v);
        graph.SetNodeOwner(move.x, move.y, NodeOwner::None);
        if (beta <= alpha)
            break;
    }
    return v;
}
else if (!isMaximiser){ // Min
    //std::cout << "Human possiblMoves size  = " << possibleMoves.size() << std::endl;
    int v = INT_MAX;
    for (const AIMove &move : possibleMoves) {
        graph.SetNodeOwner(move.x, move.y, (NodeOwner)humanPlayer);
        v = std::min(beta, MiniMaxAlphaBeta(graph, depth - 1, alpha, beta, true));
        beta = std::min(beta, v);
        graph.SetNodeOwner(move.x, move.y, NodeOwner::None);
        if (beta <= alpha)
            break;
    }
    return v;
}

}

【问题讨论】:

    标签: artificial-intelligence minimax alpha-beta-pruning


    【解决方案1】:

    您的极小极大递归调用和移动生成在逻辑上是正确的,只是您不应该使用它直接在内部得出获胜者的结论。您的叶节点评估应该是 strong ,这是关键,您的代码中似乎缺少。此外,冗长的叶节点函数会使 AI 决策太慢。

    这是递归 MiniMax 函数的伪代码。假设 parent_graph 是评估最佳移动之前的状态,而 leaf_graph 是当前离开节点的状态。您必须在极大极小树中找到相对(不要与绝对混合)最佳分支。

    if (depth == 0) {           
            return EvaluateLeafNode(isMaximizing,parent_graph,leaf_graph);
        }
    

    EvaluateLeafNode 函数可以这样写:

    int EvaluateLeafNode(bool isMaximizing,Graph& parent_graph,Graph& leaf_graph)
    {
       int score = 0;
       int w = find_relative_white_deads(parent_graph,leaf_graph);
       int b = find_relative_black_deads(parent_graph,leaf_graph);
    
       if(isMaximizing)
          score += b;
       else
          score += w;
       return score;
    }
    

    【讨论】:

    • 我仍然遇到这个问题(显然我目前对 AI 编程缺乏足够的洞察力!)但是在按照您的建议进行一些调试后,我可以得出结论,这是我的评估方法失败了我。我的理解是,程序应该根据游戏特有的一组预定义启发式方法(国际象棋、干旱等)达到特定状态的最终得分值。这听起来对吗?
    • 这方面的例子可能是: 1. 状态是否是赢/输状态 2. 每个玩家(例如国际象棋)剩余的棋子数量 3. 友方/敌方节点的邻接等.... 那么挑战就是高效地编程这些启发式方法。
    • @Lich:对于输赢,您可以分配 +INF 或 -INF 而无需进一步评估节点。您在评论中的评估是正确的。您还可以集成最终移动并删除一些不太可能的移动,以使您的搜索树更苗条。即使是简单的叶子评估程序,看到 AI 移动也是非常有趣的。
    • 太好了,感谢您的快速确认和您的帮助。它真的帮助我更好地理解我想要实现的目标。在我尝试实施它的同时,我暂时不回答这个问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-22
    • 2015-10-15
    • 2021-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多