1. 简介

在本文中,我们将介绍 Expectimax(期望最大化)搜索算法,它适用于解决非确定性游戏中的对抗性问题。

我们主要关注的是包含随机元素的双人博弈,比如掷骰子等。由于 Expectimax 是 Minimax 的变种,因此我们也会先介绍 Minimax,它是用于确定性游戏的经典算法。


2. 对抗性搜索

在经典搜索中,AI 智能体通过寻找一系列最优动作来达成目标。在这个过程中,只有智能体自己可以对环境施加影响。

而在对抗性搜索中,环境中有至少一个其他智能体参与博弈,双方目标冲突,因此需要考虑对手的行为。智能体不仅要建模自己的状态,还要建模对手的状态。

典型的对抗性搜索应用场景包括象棋、扑克等双人或多人游戏。


3. 游戏定义

在 AI 博弈中,游戏的状态通常被称为“位置”,动作被称为“移动”。一个游戏的定义包括以下几个核心组件:

  • S₀:初始状态
  • turn(s):返回在状态 s 中轮到谁行动
  • moves(s):返回状态 s 中合法的移动集合
  • result(s, a):返回在状态 s 中执行动作 a 后的新状态
  • terminal(s):判断状态 s 是否为终止状态
  • utility(s, p):返回玩家 p 在终止状态 s 中的效用值(得分)

我们关注的是零和博弈(zero-sum games),即所有玩家在终止状态下的效用值总和为 0。这意味着一方最大化自己的效用就等于另一方的损失。


4. 确定性游戏

在确定性游戏中,环境、动作选择和状态转移都是完全确定的。例如井字棋(Tic-Tac-Toe)就是一个典型例子。

对于这类游戏,我们使用经典的 Minimax 算法 来寻找最优策略。

4.1. Minimax 算法原理

Minimax 算法中包含两个角色:

  • MAX:我们的 AI 智能体,试图最大化自己的效用
  • MIN:对手,试图最小化 MAX 的效用

算法通过递归构建一个博弈树,从当前状态出发,模拟所有可能的移动路径,计算每个节点的 Minimax 值:

minimax(u) = {
    utility(u, MAX),         如果 u 是终止节点
    max{minimax(result(u, a))}, 如果当前是 MAX 的回合
    min{minimax(result(u, a))}, 如果当前是 MIN 的回合
}

最终,MAX 会选择能使结果值最大的动作。

4.2. 伪代码实现

algorithm Minimax(game_description, u, player):
    (move, value) <- MAXVALUE(u, player)
    return move

function MAXVALUE(u, player):
    if terminal(u):
        return (null, utility(u, player))
    (best_move, max_value) <- (null, -infinity)
    for move in moves(u):
        (min_move, value) <- MINVALUE(result(u, move), player)
        if value > max_value:
            best_move, max_value = move, value
    return (best_move, max_value)

function MINVALUE(u, player):
    if terminal(u):
        return (null, utility(u, player))
    (best_move, min_value) <- (null, +infinity)
    for move in moves(u):
        (max_move, value) <- MAXVALUE(result(u, move), player)
        if value < min_value:
            best_move, min_value = move, value
    return (best_move, min_value)

在实际应用中,我们通常会对搜索树进行剪枝(如 Alpha-Beta 剪枝)或限制搜索深度,以提高效率。


5. Expectimax 算法

5.1. 与 Minimax 的区别

与确定性游戏不同,随机性游戏(stochastic games) 包含概率因素。例如:

  • 某些动作可能产生多个结果,每个结果对应一个概率
  • 某些动作的选择依赖于随机事件(如掷骰子)

在这种情况下,Minimax 不再适用,我们需要引入 Expectimax 算法

5.2. 引入 Chance 节点

Expectimax 在博弈树中引入了 Chance 节点(机会节点),表示在该节点上,动作的选择依赖于概率分布。

Expectimax 值的计算公式如下:

expectimax(u) = {
    utility(u, MAX),         如果 u 是终止节点
    max{expectimax(result(u, a))}, 如果当前是 MAX 的回合
    min{expectimax(result(u, a))}, 如果当前是 MIN 的回合
    sum{P(r) * expectimax(result(u, r))}, 如果当前是 Chance 节点
}

其中 r 是随机事件的结果,P(r) 是其发生的概率。

5.3. 伪代码实现

algorithm Expectimax(u, player):
    (move, value) <- EXPECTIMAX_VALUE(u, player)
    return move

function EXPECTIMAX_VALUE(u, player):
    if u is a chance node:
        expected = 0
        for r in moves(u):
            (move, value) <- EXPECTIMAX_VALUE(result(u, r), player)
            expected += P(r) * value
        return (null, expected)
    else if turn(u) == player:
        return MAX_VALUE(u, player)
    else:
        return MIN_VALUE(u, player)

注意:与 Minimax 不同,Expectimax 中的 MAX 和 MIN 节点不再直接调用对方,而是统一调用 EXPECTIMAX_VALUE

5.4. 剪枝与评估函数

在 Expectimax 中,剪枝技术(如 Alpha-Beta)也可以应用,但需要对评估函数进行上下界约束,才能在未完全展开节点的情况下进行剪枝。

此外,评估函数的设计尤为重要:

  • Minimax 只需保持动作顺序正确即可
  • Expectimax 要求评估函数是效用值的线性正相关函数

这意味着,即使是小的评估值变化,也可能导致智能体选择不同的动作。

如果评估函数设计困难,可以考虑使用 蒙特卡洛树搜索(MCTS) 来辅助评估。


6. 小结 ✅

  • Minimax 适用于确定性游戏,通过模拟对手行为寻找最优策略
  • Expectimax 是其扩展,适用于包含随机因素的博弈问题
  • Expectimax 引入了 Chance 节点,并使用期望值代替最大/最小值
  • 实际应用中通常需要限制搜索深度、使用评估函数或剪枝优化
  • 评估函数的设计对 Expectimax 的表现影响更大

总结一句话:
Expectimax 是 Minimax 的概率扩展,适用于包含随机元素的博弈问题,但对评估函数和剪枝策略提出了更高要求。


原始标题:Expectimax Search Algorithm