简介:这是一份微分博弈理论入门教学PPT课件,面向需要系统了解对策论与鞍点规划的本科生、研究生及科研人员,适合作为课程讲义或自学材料。课件共1个pptx文件,压缩包约1.27MB,内容从《孙子兵法》《战国策》中的朴素博弈思想讲到现代博弈论建立,依次介绍局中人、策略、得失等基本要素,并重点讲解两人零和对策、纳什均衡、囚徒困境经典案例,以及鞍点的数学定义与鞍点规划数学模型,涵盖“极大值的极小化”等优化思想,最后给出基于微分博弈的防侧翻控制器设计工程实例。已有182人浏览学习。通过本课件,读者可快速把握微分博弈的理论框架与核心概念,理解纳什均衡与最小最大优化问题的内在联系,并借助具体应用案例体会微分博弈在工程控制中的实践方法,为后续深入学习与应用打下基础。
1. 微分博弈理论不是多智能体最优控制,而是对抗均衡的系统化建模
微分博弈理论处理的对象不是多个最优控制决策的简单叠加,而是“一个决策者通过状态方程改变另一个决策者可行集”的强耦合。追逃对抗是最典型的代表:双方控制量出现在同一个微分方程里,目标函数直接对立。工程上常见的“把对手当噪声”的做法,在这里被替换成显式的 min 和 max 嵌套;得到的不再是最优解,而是鞍点解——追方在知道逃方会全力反制的前提下,选择最不坏的策略。准备用这套框架做制导拦截、机器人控制对抗或多智能体训练的工程师,需要先理解这个对抗均衡到底意味着什么。若整理成课件,每一页对应一个可复现代码片段比堆公式更能讲清,下面按模型、数值、落地、验证四个环节展开。
2. 微分博弈建模:状态方程、代价函数与Isaacs方程的由来
2.1 双人零和追逃博弈:先把状态方程和支付函数写全
在做任何数值计算之前,先把博弈规范成一组标准数学对象。状态 x∈R^n 由追方(最小化方)控制 u∈U 和逃方(最大化方)控制 v∈V 共同驱动,状态方程写为:
dx/dt = f(x,u,v,t),x(t0)=x0
把博弈时长固定为 T-t0。追方想让终端状态和全程代价尽量小,逃方恰好相反,于是支付函数写成积分加终值的形式:
J(t0,x0;u,v) = φ(x(T)) + ∫_t0^T L(x(τ),u(τ),v(τ),τ) dτ
这个形式有几点要在实现时就定死。信息模式是一个:双方能否实时看到当前状态。闭环完美信息模式下策略写成 u(t,x)、v(t,x);开环模式下只能预先给定时间函数。同一个模型换一种信息模式解就不同,大多数求解器默认闭环模式,这个假设最好在建模阶段就写进设计文档,否则拿数值解跟实际对抗效果对比时经常对不上。另一个是终端时刻是否固定。上面式子默认 T 已知;如果 T 本身由首次进入某集合决定,方程就变成自由终端问题,HJI 仍然成立,只是终值条件变成了集合的示性函数。
2.2 值函数与HJI方程:把对抗博弈从变分问题变成PDE
由于零和博弈存在行动先后问题,先定义下值和上值。下值 V⁻(x,t)=max_v min_u J 表示逃方先承诺策略、追方再响应对策的结算结果;上值 V⁺(x,t)=min_u max_v J 表示追方先承诺、逃方再相应对策的结算结果。两者可能不相等。只有当 Isaacs 条件成立,也就是 Hamilton 函数满足:
min_u max_v H(x,p) = max_v min_u H(x,p)
时,上下值重合,博弈有明确的值 V=V⁻=V⁺。这个条件正是后面数值实现里可以直接检查的鞍点信号。满足条件时,值函数满足 HJI 方程:
∂V/∂t + H(x,∇V)=0,H(x,p)=min_u max_v [p^T f(x,u,v,t)+L(x,u,v,t)]
终端条件 V(x,T)=φ(x(T))。相比单智能体最优控制里的 HJB 方程,这里 Hamilton 算子被一个内层 min-max 问题替换。这个内层问题通常维度很小,可以解析或数值离线算好;剩下就是个关于状态和值函数梯度的 PDE。工程里很多人把注意力放在怎么解 PDE 上,实际上先把内层 min-max 算对,整个求解质量的瓶颈就已经解决一半。
另一个值得写进课件但常被跳过的点是粘性解。即使在最简单的追逃模型里,值函数也会在某个锥面边界上只连续不可微,经典 PDE 意义下 HJI 方程在那里没有解。工程上实际用的是粘性解:一类满足比较原理的连续函数,光滑处满足 HJI,不可微处仍保持唯一性和稳定性。这是有限差分格式能收敛到“正确”那个解的数学基础。看到值函数出现折痕、角点、值带,那是物理意义的一部分,不是数值 bug。
2.3 三个必调参数:终端时刻T、折扣因子γ、控制约束U/V
微分博弈的参数不像监督学习那样全靠网格搜索,每个参数都有明确的工程含义。终端时刻 T 决定决策窗口:T 太大,值函数趋近稳态,但计算量随时间步数线性上涨;T 太小,终值 φ(x(T)) 占主导,中间博弈结构几乎没有被学到。折扣因子 γ 不直接出现在上面这个有限时域终端问题里;只有把博弈改成无限时域并给积分项加 exp(-γt) 权重时,稳态 HJI 方程才会多出一项 γV(x)。这时它更像一个权重而不是物理时间,先固定到 0.9 或 0.99,不要指望它改变博弈的定性结构。控制约束集合 U/V 直接决定内层 min-max 能取到的范围:U/V 给太大,PDE 的解偏向保守的极端控制;给太小,体现不了对抗强度。建模时推荐把 U/V 写成独立参数而不是写死在状态方程里。
| 参数 | 工程含义 | 调试原则 | 常见误用 |
|---|---|---|---|
| T | 决策窗口长度,决定能看到多远的未来 | 先粗后细,随网格加密同步增大 | 以为越大越精确,忽略计算量 |
| γ | 无限时域折扣权重 | 固定 0.9~0.99,不参与定性判断 | 把 γ 当作可学习超参反复扫描 |
| U/V | 控制可行集,决定对抗强度 | 由执行机构物理限制确定 | 为了收敛调小 U/V,结果失去对抗性 |
from dataclasses import dataclass @dataclass class DifferentialGameConfig: dim: int = 2 # 状态空间维数,如相对位置的x/y T: float = 2.0 # 终端时刻(秒),即决策窗口长度 gamma: float = 0.99 # 折扣因子,仅无限时域转换时使用 u_max: float = 1.0 # 追方控制量的幅值上界 v_max: float = 1.5 # 逃方控制量的幅值上界 grid: int = 201 # 每个方向上的网格点数这里把 u_max 和 v_max 分开写。调试时直接改两个速度上界,观察值函数等值线变化:v_max 持续大于 u_max 时,等值线会以起点为中心向外凸出扩张;反过来追方全面占优,等值线向目标区域收缩。这个现象可以用来做模型合理性的快速目测。
3. 数值求解微分博弈HJI方程:水平集网格、时间倒推与CFL条件
3.1 为什么从终端时刻往回推:水平集网格的基本思路
HJI 方程是一个终端值问题,它天生要求时间反着跑:从 T 时刻的 φ(x) 出发,向 t0 方向推进。这和单智能体最优控制里习惯的“从初始状态正着算”刚好相反,刚接触时极容易踩坑。水平集方法把 V(x,t) 表示成网格格点上的数组,用有限差分近似空间梯度,再按显式格式逐步倒推。状态维数低时物理意义很直观:二维相对位置网格上每个格点代表一组相对距离,倒推一步就是把这组格点上的值按速度场扩张或收缩。
时间步长必须受 CFL 条件约束:max(|u|,|v|)·dt ≤ c·dx,其中 c 是取在 (0,1] 的系数。取速度上界的最大值,而不是当前状态的实际速度,是为了保证波前一个时间步不会越过整格。很多数值发散问题不是格式错了,而是步长超出了 CFL 上限。
3.2 最小可运行的倒推循环:一维追逃博弈演示
把二维的相对距离缩成一条直线,追方速度上限 1.0,逃方速度上限 1.5,终端支付是 |r|。这种情况下 Hamilton 函数退化为 (v_evader - v_pursuer)|V_r|,用 Godunov 迎风差分就能跑通。
import numpy as np # 一维相对距离网格,r = e - p L, N = 10.0, 1001 r = np.linspace(-L, L, N) dr = r[1] - r[0] v_pursuer = 1.0 # 追方控制上界 v_evader = 1.5 # 逃方控制上界 alpha = v_evader - v_pursuer # 值函数逆推时的扩张速率 T_total = 2.0 dt = 0.4 * dr / max(v_pursuer, v_evader) # CFL 步长 steps = int(T_total / dt) V = np.abs(r) # 终端时刻 V(x,T) = |r| for k in range(steps): # 向后差分 V[i] - V[i-1] dV_back = np.zeros(N) dV_back[1:] = (V[1:] - V[:-1]) / dr dV_back[0] = dV_back[1] # 向前差分 V[i+1] - V[i] dV_forw = np.zeros(N) dV_forw[:-1] = (V[1:] - V[:-1]) / dr dV_forw[-1] = dV_forw[-2] # Godunov 迎风近似 |V_r| abs_grad = np.maximum(dV_back, -dV_forw) abs_grad = np.maximum(abs_grad, 0.0) # 从终端往更早时刻倒推:剩余时间增大,值函数向外扩张 V = V + dt * alpha * abs_grad # 可视化(可选):plt.plot(r, V),横轴r,纵轴V先解释差分方向。dV_back 是把 V 向左偏移后做差,得到的是左导数;dV_forw 得到右导数。对绝对值梯度来说,导数为正时选择左导数,导数为负时选择右导数,np.maximum(dV_back, -dV_forw) 正好组合出这个选择,再截断到非负值,防止数值格式选择错误方向。dt 的 0.4 系数是经验值:格式阶数越高,系数可以越接近 1;一阶迎风保守一点没坏处。把一维代码里的差分运算放到 x、y 两个方向并合并成欧几里得范数,就是二维版本的主体。
3.3 收敛性判断与网格分辨率的选择标准
跑完倒推不等于算完。判断收敛我会依次做三件事。第一,从 t0 时刻随机取几十个状态,按得到的策略正向仿真,把仿真末端的支付跟值函数给出的理论值比较,残差应稳定在网格精度的几倍以内。第二,把网格点数翻倍重跑,看感兴趣区域的关键值变化是否小于 1%;如果变化还很大,说明当前分辨率没有进入收敛段。第三,固定某个 y 切片画 V 关于 x 的曲线,确认曲线没有出现锯齿。锯齿出现时先减小 dt,仍存在就需要提高空间差分阶数。
| 网格点数 | 差分格式 | dt 系数 | 适用场景 |
|---|---|---|---|
| 101 | 一阶迎风 | 0.2 | 初版示意与教学演示 |
| 201 | 一阶迎风 | 0.4 | 常规参数调试 |
| 401 以上 | WENO5 或同类高阶格式 | 0.1 | 发布级结果与严格验证 |
注意:CFL 系数 0.4 只是起步值。换了更高阶时间积分或空间格式,第一件事是重新做步长收敛测试,而不是沿用旧参数。
4. 微分博弈从理论到对抗系统:制导拦截与安全控制中的落地路径
4.1 制导拦截:把值函数的梯度当成指令方向
制导拦截最常用的做法是把末端距离和视线角速度放进状态方程,双方加速度作为控制输入。当博弈满足 Isaacs 条件时,最优策略是 bang-bang 形式:追方始终沿着值函数下降最快的方向施加最大控制量,逃方始终沿着上升最快的方向。从数值解提取控制指令的代码很简单,核心是梯度归一化。
# 假设 V 是二维网格上的值函数,dx, dy 是网格步长 vx, vy = np.gradient(V, dx, dy) # 值函数空间梯度 norm = np.hypot(vx, vy) norm = np.where(norm < 1e-12, 1.0, norm) # 梯度为零处做保护 # 追方最小化,取负梯度方向;逃方最大化,取正梯度方向 u_cmd = -u_max * np.stack([vx / norm, vy / norm], axis=-1) v_cmd = v_max * np.stack([vx / norm, vy / norm], axis=-1)np.gradient 在二维输入下返回两个方向上的二阶中心差分。梯度范数出现在分母上,所以要对接近零的格点做保护,避免产生无穷指令。单位化后乘上各自控制幅值,得到的就是“方向正确、幅度满偏”的参考指令。实际模型有升力、阻力和执行机构延迟时,不能直接把幅值发给平台,我会把方向作为目标航向角送进姿态内环,幅值交给限幅逻辑,这样 HJI 的计算结果就能跟工程控制器接上。
4.2 机器人安全控制:把安全规范写成终端集合
制导拦截是“追到目标”,安全控制正好反过来:避免进入某个危险集合。用 Hamilton-Jacobi 可达性分析时,把需要规避的状态集合编码成终端集合,倒推 HJI 后得到一族等值线,把状态空间分成两类:一侧存在某个控制策略能保证系统永不进入目标集合,另一侧无论如何控制都无法避免。具体哪一侧是安全侧,取决于库里值函数的符号约定,使用前先确认 V(x)<0 表示安全还是危险,不要凭记忆写条件。这个思路在无人车十字路口、机械臂避障、多机协同防碰撞里都有应用,计算时通常把完整状态先降维到相对状态空间,再在二维或三维网格上离线算好,在线只做查表和插值。
4.3 应用中最常见的三个问题与参数修正
真机实验里,微分博弈代码最常见的问题集中在三个方面:数值发散、等值线锯齿、控制指令高频切换。对应的修正方向如下表。
| 现象 | 可能原因 | 优先排查 |
|---|---|---|
| 数值发散或出现 NaN | 步长超 CFL 上限或网格过粗 | 先减半 dt,再看网格是否加密 |
| 等值线锯齿状抖动 | 空间差分阶数不足 | 把一阶迎风换成 WENO5,或先加密两倍 |
| 控制指令频繁切换 | 值函数梯度在边界附近数值抖动 | 给指令加滞回带或低通滤波 |
前两类是纯数值问题,按表格顺序排查基本能定位。第三类不是求解器错了,而是值函数倒推得到的边界策略在离散格点上天然存在切换面,工程上把切换面近似成“软边界”就是滞回带的来源。还有一种常见误用是直接把控制约束 U/V 调得很小来获得光滑值函数,这会改变博弈本身,等于用参数偷换了问题。
5. 微分博弈鞍点解验证的三个技巧与多人博弈扩展
连续时间微分博弈的鞍点验证不如离散矩阵博弈直观,但工程上有三个低成本手段可以交叉验证。第一个技巧是把连续问题投影成矩阵博弈:在固定状态点上采样追逃双方的若干备选控制,两两组合后算支付矩阵。追方先选对应 minimax,逃方先选对应 maximin;两者相等才是鞍点。这个检查只是必要条件,却能在毫秒内暴露出 min 与 max 顺序写反的低级错误。
import numpy as np # G[i,j] 为追方选i、逃方选j时的支付,来自HJI数值解附近采样 G = np.array([[1.0, 3.0], [2.0, 4.0]]) # 追方先选:每行最坏列取最大,再在行间取最小 minimax_value = np.min(G.max(axis=1)) # 逃方先选:每列最优行取最小,再在列间取最大 maximin_value = np.max(G.min(axis=0)) print(minimax_value, maximin_value) print("存在纯策略鞍点:", np.isclose(minimax_value, maximin_value))第二个技巧是用已有解析解做对拍。对单积分器或双积分器模型,微分博弈存在解析值函数;用同一套数值代码跑完后,两者误差应随网格细分单调下降。如果细化网格后误差不降反升,基本可以断定格式或边界条件有问题。第三个技巧是倒推结束后做多步正向仿真:在真实状态轨迹上重新计算支付,跟值函数给出的理论值比对,偏差超过一个网格尺度就需要回查 CFL 参数。
多人微分博弈是这套理论的自然扩展方向,但要提醒一个边界:三个及以上玩家时,值函数概念退化成 Nash 均衡下的均衡解,HJI 方程变成一组耦合 PDE 系统,连“鞍点”这个术语都要换成更宽泛的均衡概念。这时候先判别信息模式和各玩家支付的符号结构,再决定用广义 Nash 还是 Stackelberg 框架,直接套双人求解器通常得不到稳定结果。
本文还有配套的精品资源,点击获取