第12章 机器人学中的知识表示

摘要:本章深入探讨了机器人学中表示动作与变化的核心形式化工具——情境演算(Situation Calculus)与事件演算(Event Calculus),系统阐述了如何在一阶逻辑框架内严谨地表示“动作如何改变世界”。首先分析了变化表示的三大经典难题:框架问题、限定问题和分支问题,揭示了简洁表示不变性的本质挑战。随后详细介绍了情境演算的核心本体(情境作为动作历史、流、后继状态公理)及其在假设推理、规划(GOLOG 语言)和知识表示(知识流、传感动作)中的应用。接着对比了事件演算的线性时间模型,其通过事件、时间点和惯性公理天然支持并发、持续动作和外部事件。此外,本章还涵盖了定性推理(RCC-8 空间关系、Allen 时间代数)作为连接连续物理世界与离散符号表示的桥梁,以及机器人混合表示架构中符号接地(Symbol Grounding)的关键挑战。最后,通过延伸思考探讨了这些形式化工具与当代大语言模型(LLM)、AI 自我模型及 AI 安全对齐的深刻联系,为理解智能体在动态世界中的推理与行动提供了坚实的理论基础。

对应 Artificial Intelligence: A Modern Approach, 4th Edition 关于动作与变化的知识表示(Knowledge Representation for Robotics / Reasoning about Action and Change)

说明:本章内容在 AIMA 不同版次中分布于"知识表示"与"机器人学"章节。本笔记按"机器人学中的知识表示"这一主题组织:以**情境演算(situation calculus)事件演算(event calculus)**为核心,串联动作描述、时间表示、框架问题、机器人感知与行动的表示。


1. 章节概述

前面五章构建了一条完整的技术链:

  • 第 7 章:命题逻辑,用时间下标笨拙地表示变化。
  • 第 8–9 章:一阶逻辑及其推理,获得了对象与关系。
  • 第 10 章:本体、类别、事件、时空的通用表示框架。
  • 第 11 章:自动规划,用 STRIPS/PDDL 的受限表示换取高效求解。

本章回到一个被第 11 章"绕过"的根本问题:

如何在完整的一阶逻辑中,严格而简洁地表示"动作如何改变世界"?

第 11 章的 PDDL 用 ADD/DEL 列表优雅地解决了框架问题,但代价是表达力的严重限制:不能表达“动作有不确定效果”、“两个动作并发”、“动作有持续时间”、“外部事件”、“智能体的知识状态如何随感知改变”。真实机器人必须处理所有这些。

本章的两大形式化工具:

形式化 核心本体 时间观 主要用途
情境演算(Situation Calculus) 情境(situation)= 动作历史 离散、分支的"可能未来树" 假设推理、规划、知识与感知的表示
事件演算(Event Calculus) 事件(event)+ 时间点/区间 连续、线性时间轴 并发事件、持续过程、叙事推理

两者都建立在完整 FOL 之上,通过具体化(reification,第 10 章的核心技巧)把“情境”或“事件”提升为一等对象。

本章主线:

  1. 变化表示的三大难题:框架问题、限定问题、分支问题。
  2. 情境演算:情境、流、ResultResultResult/DoDoDo 函数、PossPossPoss 谓词、后继状态公理(Reiter 解法)。
  3. 投影、规划与执行:情境演算中的推理任务;GOLOG 语言。
  4. 知识与感知的表示KnowsKnowsKnows 流、传感动作、知识后继状态公理。
  5. 事件演算HappensHappensHappensInitiatesInitiatesInitiatesTerminatesTerminatesTerminatesClippedClippedClipped、惯性公理。
  6. 两者对比与转换
  7. 基于特征的本体与定性推理:定性空间/时间推理、定性物理。
  8. 机器人特有的表示问题:连续状态、不确定性、传感器模型、混合表示。

核心直觉

表示"变化"的全部困难,可以归结为一个矛盾:世界的大部分在大部分时候不变(惯性),但逻辑无法"默认"任何东西。所有解法——后继状态公理、事件演算的 Clipped、STRIPS 的 ADD/DEL——都是在用不同方式把“惯性”编码成有限的公理。


2. 关键概念与定义

2.1 变化表示的三大难题

框架问题(The Frame Problem)

McCarthy & Hayes (1969) 提出。

问题:如何简洁表达“动作没有改变的一切”?

若用朴素方法,对每个动作 aaa 和每个不受影响的流 fff,都要写一条框架公理(frame axiom):

∀s  Color(Box,Red,s)⇒Color(Box,Red,Result(Move(Box),s))\forall s\ \ Color(Box, Red, s) \Rightarrow Color(Box, Red, Result(Move(Box), s))s  Color(Box,Red,s)Color(Box,Red,Result(Move(Box),s))

“移动盒子不改变它的颜色。”

若有 ∣A∣|A|A 个动作、∣F∣|F|F 个流,需要 O(∣A∣×∣F∣)O(|A| \times |F|)O(A×F) 条框架公理——对真实领域是天文数字(100 个动作 × 10000 个流 = 100 万条)。

两个层面

层面 问题 解法
表示性框架问题
(representational)
公理数量爆炸 后继状态公理(Reiter):O(∣F∣)O(|F|)O(F)
推理性框架问题
(inferential)
即使公理简洁,推理时仍要逐步传播每个不变流 状态估计、增量更新、局部推理
限定问题(The Qualification Problem)

问题:一个动作的前提永远无法穷举

“发动汽车”的前提:有钥匙、有油、电池有电、不在真空中、排气管没被土豆堵住、引擎没被外星人偷走……

∀s  HasKey(s)∧HasGas(s)∧¬PotatoInTailpipe(s)∧⋯⇒Running(Result(Start,s))\forall s\ \ HasKey(s)\wedge HasGas(s)\wedge \neg PotatoInTailpipe(s)\wedge \dots \Rightarrow Running(Result(Start, s))s  HasKey(s)HasGas(s)¬PotatoInTailpipe(s)Running(Result(Start,s))

这个列表没有尽头

解法方向

  • 非单调推理(第 10 章 §3.3):∀s HasKey(s)∧¬Ab(Start,s)⇒Running(… )\forall s\ HasKey(s)\wedge\neg Ab(Start, s)\Rightarrow Running(\dots)s HasKey(s)¬Ab(Start,s)Running(),用限定最小化异常。
  • 概率化P(Running∣Start,HasKey)=0.98P(Running | Start, HasKey) = 0.98P(RunningStart,HasKey)=0.98(第 13 章的路线)。
  • 实用主义:只列出显著前提,用执行监控 + 重规划处理失败(第 11 章 §3.7.2)。
分支问题(The Ramification Problem)

问题:动作的间接效果(indirect effects / ramifications)如何表示?

机器人搬动一个盒子 ⇒ 盒子里的东西也跟着移动 ⇒ 盒子上的灰尘也移动 ⇒ ……

若把所有间接效果都写进动作的效果,动作描述会爆炸;且间接效果依赖于当时的状态(盒子里有什么)。

解法方向

  • 状态约束(state constraint / domain constraint):
    ∀x,y,s  In(x,y,s)∧At(y,l,s)⇒At(x,l,s)\forall x, y, s\ \ In(x, y, s) \wedge At(y, l, s) \Rightarrow At(x, l, s)x,y,s  In(x,y,s)At(y,l,s)At(x,l,s)
    声明式地表达“容器内物体随容器移动”,而不写进任何动作的效果。
  • 因果传播(causal propagation):显式区分“直接效果”与“由状态约束导出的间接效果”,并给出传播规则。

⚠️ 状态约束与后继状态公理可能冲突:需要谨慎设计,否则会推出矛盾。这是情境演算实践中的常见陷阱。

2.2 情境演算(Situation Calculus)

McCarthy (1963) 提出,Reiter (1991, 2001) 系统化。

核心本体
概念 记法 说明
情境(Situation) sssS0S_0S0 不是"状态",而是动作历史(a history of actions)
初始情境 S0S_0S0 世界的起点
结果函数 Result(a,s)Result(a, s)Result(a,s)do(a,s)do(a, s)do(a,s) 在情境 sss 执行动作 aaa 后的新情境
(Fluent) At(Robot,[1,1],s)At(Robot, [1,1], s)At(Robot,[1,1],s) 随情境变化的谓词,最后一个参数是情境
永久谓词(Atemporal / Eternal) Gold(G1)Gold(G_1)Gold(G1) 不随情境变化
可执行性谓词 Poss(a,s)Poss(a, s)Poss(a,s) 动作 aaa 在情境 sss 中可执行

⚠️ 最重要的概念澄清

情境 ≠ 状态。情境是一条动作历史路径;状态是世界的快照。两条不同的动作序列可能导致相同的世界状态,但它们是不同的情境

Result(Forward,Result(TurnLeft,Result(TurnRight,S0)))≠Result(Forward,S0)Result(Forward, Result(TurnLeft, Result(TurnRight, S_0))) \neq Result(Forward, S_0)Result(Forward,Result(TurnLeft,Result(TurnRight,S0)))=Result(Forward,S0)

即使两者的物理状态相同(左转再右转等于没转),它们仍是不同的情境项。

情境构成一棵树

                      S₀
        ┌─────────────┼─────────────┐
   do(a₁,S₀)     do(a₂,S₀)     do(a₃,S₀)
      ┌─┴─┐          ┌─┴─┐          │
  do(a₁,·) do(a₂,·)  ...            ...

每个节点是一个情境,每条边是一个动作。这棵树表示所有可能的未来——这使情境演算天然适合假设推理(Hypothetical Reasoning):“如果我做 A 再做 B,会怎样?”

情境演算中的动作描述

可能性公理(Possibility Axiom / Precondition Axiom):

Poss(a,s)⇔Πa(s)Poss(a, s) \Leftrightarrow \Pi_a(s)Poss(a,s)Πa(s)

例(Wumpus world):

Poss(Grab(g),s)⇔At(Agent,l,s)∧At(g,l,s)∧Portable(g)Poss(Forward,s)⇔∃l′  Adjacent(Location(Agent,s),l′)∧¬Wall(l′) \begin{aligned} &Poss(Grab(g), s) \Leftrightarrow At(Agent, l, s)\wedge At(g, l, s)\wedge Portable(g)\\ &Poss(Forward, s) \Leftrightarrow \exists l'\ \ Adjacent(Location(Agent, s), l') \wedge \neg Wall(l') \end{aligned} Poss(Grab(g),s)At(Agent,l,s)At(g,l,s)Portable(g)Poss(Forward,s)l  Adjacent(Location(Agent,s),l)¬Wall(l)

效果公理(Effect Axiom)—— 朴素写法:

Poss(Grab(g),s)⇒Holding(g,Result(Grab(g),s))Poss(Release(g),s)⇒¬Holding(g,Result(Release(g),s)) \begin{aligned} &Poss(Grab(g), s) \Rightarrow Holding(g, Result(Grab(g), s))\\ &Poss(Release(g), s) \Rightarrow \neg Holding(g, Result(Release(g), s)) \end{aligned} Poss(Grab(g),s)Holding(g,Result(Grab(g),s))Poss(Release(g),s)¬Holding(g,Result(Release(g),s))

⚠️ 效果公理不够! 它们只说了什么改变,没说什么不变。从上述公理无法推出 Holding(g,Result(TurnLeft,s))Holding(g, Result(TurnLeft, s))Holding(g,Result(TurnLeft,s))——即使转身显然不会让机器人松手。这正是框架问题

朴素框架公理(不可行):

Poss(a,s)∧Holding(g,s)∧a≠Release(g)⇒Holding(g,Result(a,s))Poss(a,s)∧¬Holding(g,s)∧a≠Grab(g)⇒¬Holding(g,Result(a,s)) \begin{aligned} &Poss(a,s)\wedge Holding(g,s)\wedge a\neq Release(g) \Rightarrow Holding(g, Result(a,s))\\ &Poss(a,s)\wedge \neg Holding(g,s)\wedge a\neq Grab(g) \Rightarrow \neg Holding(g, Result(a,s)) \end{aligned} Poss(a,s)Holding(g,s)a=Release(g)Holding(g,Result(a,s))Poss(a,s)¬Holding(g,s)a=Grab(g)¬Holding(g,Result(a,s))

对每个流写两条,O(∣F∣)O(|F|)O(F) 条——看似可接受,但要为每个流列出所有影响它的动作,且随动作增加要修改每条公理。维护性差

后继状态公理(Successor-State Axiom)—— Reiter 解法

这是情境演算最重要的技术贡献。

通用形式

Poss(a,s)⇒[F(x⃗,Result(a,s))⇔γF+(x⃗,a,s) ∨ (F(x⃗,s)∧¬γF−(x⃗,a,s))]Poss(a,s) \Rightarrow \Big[ F(\vec{x}, Result(a,s)) \Leftrightarrow \gamma_F^+(\vec{x}, a, s)\ \vee\ \big(F(\vec{x},s)\wedge\neg\gamma_F^-(\vec{x},a,s)\big)\Big]Poss(a,s)[F(x ,Result(a,s))γF+(x ,a,s)  (F(x ,s)¬γF(x ,a,s))]

读法(极其重要,务必记住):

FFF 在动作后为真,当且仅当:
(a)该动作使它变为真(γ+\gamma^+γ+,正效果条件),或
(b)它本来就为真,且该动作没有使它变为假(γ−\gamma^-γ,负效果条件)。

示例

Poss(a,s)⇒[Holding(g,Result(a,s))⇔a=Grab(g) ∨ (Holding(g,s)∧a≠Release(g))]Poss(a,s)\Rightarrow \Big[Holding(g, Result(a,s)) \Leftrightarrow a = Grab(g) \ \vee\ \big(Holding(g,s)\wedge a\neq Release(g)\big)\Big]Poss(a,s)[Holding(g,Result(a,s))a=Grab(g)  (Holding(g,s)a=Release(g))]

Poss(a,s)⇒[At(Agent,l,Result(a,s))⇔(a=Go(l′,l))∨(At(Agent,l,s)∧¬∃l′′ a=Go(l,l′′))] \begin{aligned} Poss(a,s)\Rightarrow \Big[&At(Agent, l, Result(a,s)) \Leftrightarrow\\ &\big(a = Go(l', l)\big) \vee \big(At(Agent,l,s)\wedge \neg\exists l''\ a = Go(l, l'')\big)\Big] \end{aligned} Poss(a,s)[At(Agent,l,Result(a,s))(a=Go(l,l))(At(Agent,l,s)¬∃l′′ a=Go(l,l′′))]

为什么这解决了框架问题

指标 朴素框架公理 后继状态公理
公理数量 O(∥A∥×∥F∥)O(\|A\|\times\|F\|)O(A×F) O(∥F∥)O(\|F\|)O(F) —— 每个流一条
添加新动作 要修改所有 ∥F∥\|F\|F 条框架公理 只需修改受影响的流的公理
逻辑形式 一堆蕴涵 等价式⇔\Leftrightarrow),信息完整

关键前提:完备性假设(Completeness Assumption)

后继状态公理的正确性依赖于"我们已经列出了所有能影响 FFF 的动作"。这本质上是对因果关系的封闭世界假设。若遗漏了某个动作,公理就是错的。

⚠️ 这也说明:后继状态公理不能处理外部事件(非智能体引发的变化)——因为那些"动作"不在 aaa 的取值范围内。这是情境演算的固有局限,也是事件演算的动机之一。

情境演算中的推理任务
任务 形式 说明
投影(projection / temporal projection) KB⊨ϕ(Result(an,…Result(a1,S0)))KB \models \phi(Result(a_n, \dots Result(a_1, S_0)))KBϕ(Result(an,Result(a1,S0))) “执行这些动作后 ϕ\phiϕ 成立吗?”
可执行性(executability) KB⊨Executable([a1,…,an],S0)KB\models Executable([a_1,\dots,a_n], S_0)KBExecutable([a1,,an],S0) 每步的 PossPossPoss 都成立
规划(planning) KB⊨∃s  Executable(s)∧ϕ(s)KB\models\exists s\ \ Executable(s) \wedge \phi(s)KBs  Executable(s)ϕ(s) 存在性证明,从证明中抽取动作序列
遗留(legacy / explanation) 已知当前观察,推断过去发生了什么 溯因推理(abduction)

规划作为演绎(deductive planning)

KB⊨∃s  [Executable(s)∧At(Gold,[1,1],s)]KB \models \exists s\ \ \Big[ Executable(s) \wedge At(Gold, [1,1], s)\Big]KBs  [Executable(s)At(Gold,[1,1],s)]

用第 9 章的归结证明这个存在句,从证明中读出 sss 的绑定:

s=Result(Go([2,1],[1,1]),Result(Grab(G1),Result(Go([1,1],[2,1]),S0)))s = Result(Go([2,1],[1,1]), Result(Grab(G_1), Result(Go([1,1],[2,1]), S_0)))s=Result(Go([2,1],[1,1]),Result(Grab(G1),Result(Go([1,1],[2,1]),S0)))

即方案 [Go([1,1],[2,1]), Grab(G1), Go([2,1],[1,1])][Go([1,1],[2,1]),\ Grab(G_1),\ Go([2,1],[1,1])][Go([1,1],[2,1]), Grab(G1), Go([2,1],[1,1])]

这被称为"answer extraction"(答案抽取)——把规划完全归约为定理证明。

⚠️ 实践评价:这在理论上优雅,在实践中远不如第 11 章的专用规划器高效。原因:

  1. 通用定理证明器无法利用规划问题的特殊结构(如启发式、可达性分析)。
  2. 搜索空间是证明空间而非状态空间,剪枝困难。
  3. 情境项会变得极长,合一代价高。

Green (1969) 的 QA3 系统是这条路线的早期尝试,正是它的低效催生了 STRIPS(1971)—— 用表达力换效率。这是 AI 历史上一次典型的范式转换

GOLOG:情境演算的编程语言

Levesque et al. (1997) 提出。在情境演算之上加入程序结构,让程序员指定"部分方案",由推理器填补细节。

GOLOG 构造

构造 语法 含义
原语动作 aaa 执行 aaa
测试 ϕ?\phi?ϕ? 检查条件 ϕ\phiϕ
序列 δ1;δ2\delta_1;\delta_2δ1;δ2 δ1\delta_1δ1δ2\delta_2δ2
非确定选择 δ1∣δ2\delta_1 \mid \delta_2δ1δ2 任选其一(由规划器决定
非确定参数 πx. δ(x)\pi x.\ \delta(x)πx. δ(x) 任选 xxx 的值
循环 while ϕ do δ\textbf{while}\ \phi\ \textbf{do}\ \deltawhile ϕ do δ 条件循环
过程 proc P(x⃗) δ end\textbf{proc}\ P(\vec{x})\ \delta\ \textbf{end}proc P(x ) δ end 命名过程

示例(送咖啡机器人):

proc serveCoffee(person)
    π loc. (at(person, loc)? ;
            goto(kitchen) ;
            pickup(coffee) ;
            goto(loc) ;
            handover(coffee, person))
end

语义Do(δ,s,s′)Do(\delta, s, s')Do(δ,s,s) 表示"从情境 sss 执行程序 δ\deltaδ 可以到达情境 s′s's"。

Do(a,s,s′)≡Poss(a,s)∧s′=Result(a,s)Do(ϕ?,s,s′)≡ϕ[s]∧s′=sDo(δ1;δ2,s,s′)≡∃s′′ Do(δ1,s,s′′)∧Do(δ2,s′′,s′)Do(δ1∣δ2,s,s′)≡Do(δ1,s,s′)∨Do(δ2,s,s′)Do(πx.δ,s,s′)≡∃x Do(δ,s,s′) \begin{aligned} Do(a, s, s') &\equiv Poss(a,s)\wedge s' = Result(a,s)\\ Do(\phi?, s, s') &\equiv \phi[s] \wedge s'=s\\ Do(\delta_1;\delta_2, s, s') &\equiv \exists s''\ Do(\delta_1,s,s'')\wedge Do(\delta_2,s'',s')\\ Do(\delta_1\mid\delta_2, s,s') &\equiv Do(\delta_1,s,s')\vee Do(\delta_2,s,s')\\ Do(\pi x.\delta, s,s') &\equiv \exists x\ Do(\delta,s,s') \end{aligned} Do(a,s,s)Do(ϕ?,s,s)Do(δ1;δ2,s,s)Do(δ1δ2,s,s)Do(πx.δ,s,s)Poss(a,s)s=Result(a,s)ϕ[s]s=ss′′ Do(δ1,s,s′′)Do(δ2,s′′,s)Do(δ1,s,s)Do(δ2,s,s)x Do(δ,s,s)

GOLOG 的价值

它处在"完全手写程序"与"完全自动规划"之间的甜点:程序员用确定性结构编码领域知识(大幅剪枝),用非确定性构造留出需要推理的空隙。

⚠️ 这与第 11 章的 HTN 精神高度一致:都是"人给结构,机器填细节"。区别在于 GOLOG 建立在完整 FOL 语义上,表达力更强但求解更难。

变体

  • ConGolog:加入并发(concurrency)。
  • IndiGolog:增量执行 + 在线传感,适合真实机器人。
  • DTGolog:结合决策论(MDP),处理概率与效用。

2.3 知识与感知的表示

真实机器人必须表示自己知道什么,以及感知如何改变知识

知识流(Knowledge Fluent)

在情境演算中把"知识"具体化。Moore (1985)、Scherl & Levesque (1993) 的方法:

引入可及关系 K(s′,s)K(s', s)K(s,s):读作“在情境 sss 中,情境 s′s's 是(就智能体所知)认知上可能的”。

Knows(ϕ,s) ≡ ∀s′  K(s′,s)⇒ϕ[s′]Knows(\phi, s) \ \equiv\ \forall s'\ \ K(s', s) \Rightarrow \phi[s']Knows(ϕ,s)  s  K(s,s)ϕ[s]

“智能体在 sss 中知道 ϕ\phiϕ,当且仅当 ϕ\phiϕ 在所有认知可及的情境中都成立。”

⚠️ 这就是第 10 章 §2.7 的模态逻辑可能世界语义,但用 FOL 中的显式关系 KKK 实现,而非引入模态算子。这称为可能世界的具体化,好处是保持在 FOL 内(可用第 9 章的推理机)。

传感动作与知识后继状态公理

传感动作(sensing action):不改变物理世界,只改变知识。

SenseBreeze: 返回 Breeze 的真值SenseBreeze:\ \text{返回 } Breeze \text{ 的真值}SenseBreeze: 返回 Breeze 的真值

知识的后继状态公理

K(s′′,Result(a,s))⇔∃s′ [K(s′,s)∧s′′=Result(a,s′)∧Poss(a,s′)∧(SR(a,s′)=SR(a,s))]K(s'', Result(a,s)) \Leftrightarrow \exists s'\ \Big[K(s',s)\wedge s''=Result(a,s')\wedge Poss(a,s') \wedge \big(SR(a,s') = SR(a,s)\big)\Big]K(s′′,Result(a,s))s [K(s,s)s′′=Result(a,s)Poss(a,s)(SR(a,s)=SR(a,s))]

其中 SR(a,s)SR(a,s)SR(a,s)(sensing result)是动作 aaasss 中的感知返回值。

读法

执行 aaa 后,认知可及的情境是"原先可及的情境执行 aaa 后的结果",但只保留那些感知结果与实际观察一致的

这个公理同时实现了两件事

  1. 物理效果传播s′′=Result(a,s′)s'' = Result(a, s')s′′=Result(a,s)
  2. 知识增益(信念更新)SR(a,s′)=SR(a,s)SR(a,s')=SR(a,s)SR(a,s)=SR(a,s) 过滤掉与观察不符的可能世界。

知识增益的形式化

Knows(ϕ,s)⇒Knows(ϕ,Result(a,s))(对不影响 ϕ 的 a)Knows(\phi, s) \Rightarrow Knows(\phi, Result(a,s)) \quad\text{(对不影响 } \phi \text{ 的 } a)Knows(ϕ,s)Knows(ϕ,Result(a,s))(对不影响 ϕ  a)

执行 SenseP 后:Knows(P,Result(SenseP,s))∨Knows(¬P,Result(SenseP,s))\text{执行 } SenseP \text{ 后:}\quad Knows(P, Result(SenseP, s)) \vee Knows(\neg P, Result(SenseP,s))执行 SenseP 后:Knows(P,Result(SenseP,s))Knows(¬P,Result(SenseP,s))

后者称为 KWhether(知道是否):

KWhether(ϕ,s)≡Knows(ϕ,s)∨Knows(¬ϕ,s)KWhether(\phi, s) \equiv Knows(\phi,s)\vee Knows(\neg\phi, s)KWhether(ϕ,s)Knows(ϕ,s)Knows(¬ϕ,s)

规划中的知识前提

要执行 Dial(combination)Dial(combination)Dial(combination),机器人必须知道组合密码,而不只是"密码存在":
Poss(Dial(x),s)⇒Knows(Combination(Safe)=x, s)Poss(Dial(x), s) \Rightarrow Knows(Combination(Safe) = x,\ s)Poss(Dial(x),s)Knows(Combination(Safe)=x, s)

这称为 knowledge precondition,是信息收集规划(information-gathering planning)的基础——机器人可能需要先执行传感动作获取信息,才能执行后续动作。这直接对应第 11 章的应急规划与第 17 章的 POMDP

2.4 事件演算(Event Calculus)

Kowalski & Sergot (1986) 提出。见第 10 章 §2.6 的介绍,此处深化。

核心谓词(完整版)
谓词 含义
HoldsAt(f,t)HoldsAt(f, t)HoldsAt(f,t)T(f,t)T(f,t)T(f,t) fff 在时刻 ttt 为真
Happens(e,t)Happens(e, t)Happens(e,t) 事件 eee 在时刻 ttt 发生
Initiates(e,f,t)Initiates(e, f, t)Initiates(e,f,t) eeettt 发生,则 fffttt 后为真
Terminates(e,f,t)Terminates(e, f, t)Terminates(e,f,t) eeettt 发生,则 fffttt 后为假
InitiallyP(f)InitiallyP(f)InitiallyP(f) / InitiallyN(f)InitiallyN(f)InitiallyN(f) fff 在时间起点为真/为假
Clipped(t1,f,t2)Clipped(t_1, f, t_2)Clipped(t1,f,t2) 存在事件在 (t1,t2)(t_1,t_2)(t1,t2) 内终止 fff
Declipped(t1,f,t2)Declipped(t_1,f,t_2)Declipped(t1,f,t2) 存在事件在 (t1,t2)(t_1,t_2)(t1,t2) 内启动 fff
Releases(e,f,t)Releases(e,f,t)Releases(e,f,t) eee 使 fff 脱离惯性(值变得不确定)
Trajectory(f1,t1,f2,t2)Trajectory(f_1, t_1, f_2, t_2)Trajectory(f1,t1,f2,t2) 连续变化:若 f1f_1f1t1t_1t1 启动,则 f2f_2f2t1+t2t_1+t_2t1+t2 成立
核心公理(离散事件演算 DEC/简化版)

正惯性公理

HoldsAt(f,t2) ← Happens(e,t1)∧Initiates(e,f,t1)∧t1<t2∧¬Clipped(t1,f,t2)HoldsAt(f, t_2) \ \leftarrow\ Happens(e,t_1)\wedge Initiates(e,f,t_1)\wedge t_1 < t_2 \wedge \neg Clipped(t_1, f, t_2)HoldsAt(f,t2)  Happens(e,t1)Initiates(e,f,t1)t1<t2¬Clipped(t1,f,t2)

负惯性公理

¬HoldsAt(f,t2) ← Happens(e,t1)∧Terminates(e,f,t1)∧t1<t2∧¬Declipped(t1,f,t2)\neg HoldsAt(f,t_2)\ \leftarrow\ Happens(e,t_1)\wedge Terminates(e,f,t_1)\wedge t_1<t_2\wedge\neg Declipped(t_1,f,t_2)¬HoldsAt(f,t2)  Happens(e,t1)Terminates(e,f,t1)t1<t2¬Declipped(t1,f,t2)

初始状态传播

HoldsAt(f,t) ← InitiallyP(f)∧¬Clipped(0,f,t)HoldsAt(f,t)\ \leftarrow\ InitiallyP(f)\wedge \neg Clipped(0, f, t)HoldsAt(f,t)  InitiallyP(f)¬Clipped(0,f,t)

Clipped/Declipped 定义

Clipped(t1,f,t2) ↔ ∃e,t [Happens(e,t)∧t1≤t<t2∧Terminates(e,f,t)]Clipped(t_1,f,t_2) \ \leftrightarrow\ \exists e, t\ \big[Happens(e,t)\wedge t_1\le t < t_2 \wedge Terminates(e,f,t)\big]Clipped(t1,f,t2)  e,t [Happens(e,t)t1t<t2Terminates(e,f,t)]

Declipped(t1,f,t2) ↔ ∃e,t [Happens(e,t)∧t1≤t<t2∧Initiates(e,f,t)]Declipped(t_1,f,t_2)\ \leftrightarrow\ \exists e,t\ \big[Happens(e,t)\wedge t_1\le t<t_2\wedge Initiates(e,f,t)\big]Declipped(t1,f,t2)  e,t [Happens(e,t)t1t<t2Initiates(e,f,t)]

领域描述示例(机器人送货)
%% 事件效果
Initiates(PickUp(r, o), Holding(r, o), t) ←
    HoldsAt(At(r, l), t) ∧ HoldsAt(At(o, l), t) ∧ ¬∃o'. HoldsAt(Holding(r,o'), t)

Terminates(PickUp(r,o), At(o, l), t) ← HoldsAt(At(o,l), t)

Initiates(Drop(r,o), At(o,l), t) ← HoldsAt(At(r,l),t) ∧ HoldsAt(Holding(r,o),t)
Terminates(Drop(r,o), Holding(r,o), t)

Initiates(Move(r, l1, l2), At(r, l2), t) ← HoldsAt(At(r,l1), t)
Terminates(Move(r, l1, l2), At(r, l1), t)

%% 状态约束处理分支问题(被携带的物体跟随移动)
Initiates(Move(r,l1,l2), At(o,l2), t) ← HoldsAt(Holding(r,o), t)
Terminates(Move(r,l1,l2), At(o,l1), t) ← HoldsAt(Holding(r,o), t)

%% 叙事(narrative)
Happens(PickUp(R1, Box1), 5)
Happens(Move(R1, RoomA, RoomB), 10)
Happens(Drop(R1, Box1), 15)

%% 查询
?- HoldsAt(At(Box1, RoomB), 20).      % → yes
连续变化(Trajectory)

事件演算可以处理连续过程,如水位随时间上升:

Trajectory(FillingTank,t1,WaterLevel(x),t2) ← x=InitialLevel+Rate×t2Trajectory(FillingTank, t_1, WaterLevel(x), t_2) \ \leftarrow\ x = InitialLevel + Rate \times t_2Trajectory(FillingTank,t1,WaterLevel(x),t2)  x=InitialLevel+Rate×t2

HoldsAt(f2,t1+t2)←Happens(e,t1)∧Initiates(e,f1,t1)∧Trajectory(f1,t1,f2,t2)∧¬Clipped(t1,f1,t1+t2)HoldsAt(f_2, t_1+t_2) \leftarrow Happens(e,t_1)\wedge Initiates(e,f_1,t_1)\wedge Trajectory(f_1,t_1,f_2,t_2)\wedge\neg Clipped(t_1,f_1,t_1+t_2)HoldsAt(f2,t1+t2)Happens(e,t1)Initiates(e,f1,t1)Trajectory(f1,t1,f2,t2)¬Clipped(t1,f1,t1+t2)

这使事件演算能表达混合系统(离散事件 + 连续动态),对机器人(速度、位置连续变化)至关重要。

ReleasesReleasesReleases:处理非确定性

Releases(e,f,t)Releases(e, f, t)Releases(e,f,t)

表示"eee 使 fff 脱离惯性"——之后 fff 的值不由惯性决定,可以任意(用于表示非确定效果或外部影响)。

例:抛硬币后,HeadsHeadsHeads 的值被 ReleaseReleaseRelease,需要额外的观察或约束才能确定。

2.5 情境演算 vs 事件演算

维度 情境演算 事件演算
本体核心 情境(动作历史) 事件 + 时间点
时间结构 分支树(可能未来) 线性轴(单一时间线)
主要用途 假设推理、规划(“如果…会怎样”) 叙事推理、时序数据库(“实际发生了什么”)
并发事件 困难(需 ConGolog 扩展) 天然支持(多个 HappensHappensHappens 同一 ttt
持续动作 困难 天然支持(区间 + Trajectory)
外部事件 困难(后继状态公理假设动作封闭) 天然支持
连续变化 需扩展 支持(Trajectory)
框架问题解法 后继状态公理 Clipped/Declipped + 惯性公理
实现方式 常用 Prolog / 定理证明器 常用 Prolog + abduction、ASP
典型系统 GOLOG、IndiGolog DEC reasoner、ASP 编码

互补性

情境演算问"如果我这样做会怎样"(前瞻、规划);事件演算问"已经发生了什么、现在什么成立"(回溯、监控)。

一个完整的机器人系统两者都需要:用情境演算式的推理规划未来,用事件演算式的推理维护世界模型。

理论关系:两者在合适的条件下可以互相转换(Kowalski & Sadri 的工作),但转换后往往失去各自的自然性。

2.6 基于特征的本体与定性推理

机器人面对的是连续的物理世界(位置是实数、力是向量),而符号推理需要离散的表示。桥梁是定性推理(qualitative reasoning)。

定性表示(Qualitative Representation)

不表示精确数值,只表示有意义的区分

定量 定性
位置 x=3.7mx = 3.7\text{m}x=3.7m InRoom(A)InRoom(A)InRoom(A)Near(Door)Near(Door)Near(Door)
速度 v=−0.5v=-0.5v=0.5 {−,0,+}\{-, 0, +\}{,0,+}(后退/静止/前进)
温度 T=95°CT = 95°CT=95°C {Below,At,Above}\{Below, At, Above\}{Below,At,Above} 沸点
液位 h=0.8h=0.8h=0.8 {Empty,Partial,Full}\{Empty, Partial, Full\}{Empty,Partial,Full}

定性微积分(qualitative calculus):

[+]+[+]=[+],[+]+[−]=[?],[+]×[−]=[−][+] + [+] = [+],\quad [+] + [-] = [?],\quad [+]\times[-] = [-][+]+[+]=[+],[+]+[]=[?],[+]×[]=[]

[?][?][?] 表示歧义——定性推理的固有代价:信息少,结论可能不唯一。

定性物理(qualitative physics, de Kleer & Brown, Forbus):

  • QSIMQualitative Process Theory:从定性方程推导系统可能的行为序列(envisionment)。
  • 用途:故障诊断、教学系统、常识物理推理。
定性空间推理

RCC-8(Region Connection Calculus)—— 8 种拓扑关系:

DC(a,b)     断开        ( a )  ( b )
EC(a,b)     外部相接    ( a )( b )
PO(a,b)     部分重叠    ( a(∩)b )
TPP(a,b)    切向真部分  ( b( a) )
NTPP(a,b)   非切向真部分( b ( a ) )
TPPi, NTPPi 上述的逆
EQ(a,b)     相等        (ab)

性质:8 种关系互斥且穷尽。推理通过组合表(composition table)+ 路径一致性:

DC(a,b)∘EC(b,c)⇒{DC,EC,PO,TPP,NTPP}(a,c)DC(a,b) \circ EC(b,c) \Rightarrow \{DC, EC, PO, TPP, NTPP\}(a,c)DC(a,b)EC(b,c){DC,EC,PO,TPP,NTPP}(a,c)

⚠️ 组合结果通常是一个集合(歧义),需要约束传播缩小。这是一个 CSP(第 6 章)。

方向关系

  • 基本方向(cardinal direction):N、NE、E、SE、S、SW、W、NW。
  • 双十字演算(double-cross calculus):相对方向(“在我左前方”)。
定性时间推理

见第 10 章 §2.6 的 Allen 区间代数(13 种关系)。

推理复杂度

  • 完整 Allen 代数的一致性判定:NP-完全
  • 点代数(point algebra,只有 <,=,><,=,><,=,>):多项式时间
  • Allen 代数的极大可处理子类(ORD-Horn class):多项式,且包含约 10% 的关系。

实用做法:路径一致性(path consistency)作为不完备但快速的近似。

为什么机器人需要定性表示
  1. 传感器不精确:与其说“物体在 x=3.7241x=3.7241x=3.7241”,不如说“物体在桌上”。
  2. 符号规划的接口:第 11 章的规划器需要离散谓词。
  3. 可解释性:人类用定性语言交流(“把杯子放在盘子左边”)。
  4. 泛化:定性描述跨实例迁移(“抓取杯柄”适用于所有杯子)。

关键挑战:符号接地(Symbol Grounding)

谓词 On(Cup,Table)On(Cup, Table)On(Cup,Table) 的真值必须从传感器数据判定。这个映射(perceptual grounding)是机器人 KR 最困难的部分——它不是逻辑问题,而是感知问题。


3. 核心理论与算法

3.1 情境演算的投影算法(Projection/Regression)

任务:给定 KBKBKB、初始情境 S0S_0S0、动作序列 [a1,…,an][a_1,\dots,a_n][a1,,an],判断 ϕ\phiϕResult(an,…Result(a1,S0))Result(a_n,\dots Result(a_1,S_0))Result(an,Result(a1,S0)) 中是否成立。

方法 1:前推(Progression)

function PROGRESS(S₀_description, [a₁,...,aₙ]) returns 最终状态描述
    s ← S₀_description
    for i = 1 to n do
        if not Poss(aᵢ, s) then return failure
        s' ← {}
        for each fluent F do
            // 应用后继状态公理
            if γ⁺_F(aᵢ, s) holds then add F to s'
            else if F ∈ s and not γ⁻_F(aᵢ, s) then add F to s'
        s ← s'
    return s
  • 优点:直观,得到完整的最终状态。
  • 缺点:需要完整的初始状态描述。若 S0S_0S0 只是部分已知,前推会产生复杂的析取式(状态描述爆炸)。
  • 一阶前推的困难:Lin & Reiter 证明,一般情形下前推的结果可能不是一阶可表达的。只有在特定条件下(如局部效果动作)才保证一阶闭合。

方法 2:回归(Regression)—— Reiter 的主力方法

function REGRESS(φ, [a₁,...,aₙ]) returns 关于 S₀ 的公式
    ψ ← φ                                  // 目标公式
    for i = n down to 1 do
        ψ ← REGRESS-ONE-STEP(ψ, aᵢ)
    return ψ                               // 现在只涉及 S₀

function REGRESS-ONE-STEP(ψ, a) returns 公式
    // 用后继状态公理反向替换
    for each fluent atom F(x̄, Result(a,s)) in ψ do
        用其后继状态公理的右侧替换:
            γ⁺_F(x̄, a, s) ∨ (F(x̄,s) ∧ ¬γ⁻_F(x̄,a,s))
    return 简化后的 ψ

示例

已知后继状态公理:
Holding(g,Result(a,s))⇔a=Grab(g)∨(Holding(g,s)∧a≠Release(g))Holding(g, Result(a,s)) \Leftrightarrow a=Grab(g)\vee (Holding(g,s)\wedge a\neq Release(g))Holding(g,Result(a,s))a=Grab(g)(Holding(g,s)a=Release(g))

回归 Holding(G1,Result(Grab(G1),S0))Holding(G_1, Result(Grab(G_1), S_0))Holding(G1,Result(Grab(G1),S0))

⇝ [Grab(G1)=Grab(G1)]∨[Holding(G1,S0)∧Grab(G1)≠Release(G1)]⇝ True∨… = True✓ \begin{aligned} &\leadsto\ \big[Grab(G_1) = Grab(G_1)\big] \vee \big[Holding(G_1, S_0)\wedge Grab(G_1)\neq Release(G_1)\big]\\ &\leadsto\ True \vee \dots \ =\ True \quad ✓ \end{aligned}  [Grab(G1)=Grab(G1)][Holding(G1,S0)Grab(G1)=Release(G1)] True = True

回归的优势(Reiter 定理)

回归把"关于未来情境的查询"归约为关于 S0S_0S0 的查询。因此只需在初始情境的(可能不完全的)描述上做一次定理证明,而无需推理中间情境。

复杂度:回归后的公式规模可能随动作数指数增长(每步替换可能使公式变大)。实用系统需要简化(simplification)与缓存

与第 11 章的对应

  • 情境演算的 progression ↔ 第 11 章的前向搜索(§3.1.1)
  • 情境演算的 regression ↔ 第 11 章的后向搜索(§3.1.2)

思想完全一致,只是情境演算在完整 FOL 中操作(更表达力强,更慢)。

Python 实现示例:基于后继状态公理的投影算法

下面是一个简化的 Python 实现,演示如何基于后继状态公理进行前向投影(progression)。我们以经典的机器人搬箱子世界为例。

class SituationCalculusProgression:
    """
    基于后继状态公理的前向投影算法实现
    领域:机器人搬箱子(Wumpus world 简化版)
    流:At(robot, loc, s), Holding(obj, s), At(obj, loc, s)
    动作:Grab(obj), Release(obj), Go(from, to)
    """
    
    def __init__(self):
        # 初始情境 S0 的状态描述(流为真的集合)
        self.fluents = {
            'At': [('robot', 'room1'), ('box1', 'room1'), ('box2', 'room2')],
            'Holding': []  # 初始没有拿着任何东西
        }
        
        # 后继状态公理的正负效果条件
        self.gamma_plus = {
            'Holding': lambda a, s: a[0] == 'Grab' and (a[1],) in self._get_fluent('At', s) and ('robot', a[2]) in self._get_fluent('At', s),
            'At_robot': lambda a, s: a[0] == 'Go' and a[2] == 'robot',
            'At_obj': lambda a, s: a[0] == 'Go' and (a[1],) in self._get_fluent('Holding', s)
        }
        
        self.gamma_minus = {
            'Holding': lambda a, s: a[0] == 'Release' and a[1] == s[1],
            'At_robot': lambda a, s: a[0] == 'Go' and a[1] == s[1] and s[2] == 'robot',
            'At_obj': lambda a, s: a[0] == 'Go' and a[1] == s[1] and s[2] == 'obj'
        }
    
    def _get_fluent(self, fluent_name, args=None):
        """获取特定流在当前情境下的真值"""
        if fluent_name == 'At':
            return [(obj, loc) for (obj, loc) in self.fluents['At']]
        elif fluent_name == 'Holding':
            return [(obj,) for obj in self.fluents['Holding']]
        return []
    
    def _poss(self, action):
        """可能性公理:检查动作是否可执行"""
        if action[0] == 'Grab':
            obj = action[1]
            # 机器人和物体在同一位置,且物体可携带
            robot_loc = next(loc for (obj_name, loc) in self.fluents['At'] if obj_name == 'robot')
            obj_loc = next((loc for (obj_name, loc) in self.fluents['At'] if obj_name == obj), None)
            return obj_loc == robot_loc and obj in ['box1', 'box2']
        elif action[0] == 'Release':
            obj = action[1]
            return obj in self.fluents['Holding']
        elif action[0] == 'Go':
            from_loc, to_loc, _ = action[1], action[2], action[3]
            # 简化:假设所有房间都相邻
            return from_loc != to_loc and from_loc in ['room1', 'room2', 'room3'] and to_loc in ['room1', 'room2', 'room3']
        return False
    
    def progress(self, action):
        """执行单个动作的前向投影"""
        if not self._poss(action):
            print(f"动作 {action} 不可执行")
            return False
        
        # 应用后继状态公理更新每个流
        new_fluents = {'At': [], 'Holding': []}
        
        # 更新 Holding 流
        for obj in ['box1', 'box2']:
            # γ⁺: Grab 使 Holding 为真
            if self.gamma_plus['Holding'](action, ('Holding', obj)):
                new_fluents['Holding'].append(obj)
            # 惯性:原本为真且没有使之为假的动作
            elif obj in self.fluents['Holding'] and not self.gamma_minus['Holding'](action, ('Holding', obj)):
                new_fluents['Holding'].append(obj)
        
        # 更新 At 流(机器人和物体)
        for (obj, loc) in self.fluents['At']:
            if obj == 'robot':
                # γ⁺: Go 使机器人到达新位置
                if self.gamma_plus['At_robot'](action, ('At', obj, loc)):
                    new_loc = action[2]  # Go 的目标位置
                    new_fluents['At'].append(('robot', new_loc))
                # 惯性
                elif not self.gamma_minus['At_robot'](action, ('At', obj, loc)):
                    new_fluents['At'].append(('robot', loc))
            else:
                # γ⁺: 如果机器人拿着物体移动,物体也移动
                if obj in self.fluents['Holding'] and self.gamma_plus['At_obj'](action, ('At', obj, loc)):
                    new_loc = action[2]  # 随机器人移动
                    new_fluents['At'].append((obj, new_loc))
                # 惯性
                elif not self.gamma_minus['At_obj'](action, ('At', obj, loc)):
                    new_fluents['At'].append((obj, loc))
        
        self.fluents = new_fluents
        return True
    
    def query(self, fluent, args):
        """查询流在当前情境下是否成立"""
        if fluent == 'At':
            return args in self.fluents['At']
        elif fluent == 'Holding':
            return args[0] in self.fluents['Holding']
        return False
    
    def print_state(self):
        """打印当前状态"""
        print("当前状态:")
        print(f"  机器人位置: {next(loc for (obj, loc) in self.fluents['At'] if obj == 'robot')}")
        print(f"  持有的物体: {self.fluents['Holding']}")
        for obj in ['box1', 'box2']:
            loc = next((loc for (o, loc) in self.fluents['At'] if o == obj), None)
            print(f"  {obj}的位置: {loc}")

# 运行示例
if __name__ == "__main__":
    sc = SituationCalculusProgression()
    print("初始状态:")
    sc.print_state()
    
    # 执行动作序列
    actions = [
        ('Go', 'room1', 'room2', 'robot'),  # 机器人从 room1 移动到 room2
        ('Grab', 'box2'),                    # 抓起 box2
        ('Go', 'room2', 'room3', 'robot'),  # 带着 box2 移动到 room3
        ('Release', 'box2')                  # 放下 box2
    ]
    
    for i, action in enumerate(actions):
        print(f"\n执行动作 {i+1}: {action}")
        if sc.progress(action):
            sc.print_state()
    
    # 最终查询
    print("\n最终查询:")
    print(f"  At(box2, room3)? {sc.query('At', ('box2', 'room3'))}")  # 应为 True
    print(f"  Holding(box2)? {sc.query('Holding', ('box2',))}")        # 应为 False
    print(f"  At(robot, room3)? {sc.query('At', ('robot', 'room3'))}") # 应为 True

运行结果注释:

初始状态:
  机器人位置: room1
  持有的物体: []
  box1的位置: room1
  box2的位置: room2

执行动作 1: ('Go', 'room1', 'room2', 'robot')
当前状态:
  机器人位置: room2
  持有的物体: []
  box1的位置: room1
  box2的位置: room2

执行动作 2: ('Grab', 'box2')
当前状态:
  机器人位置: room2
  持有的物体: ['box2']
  box1的位置: room1
  box2的位置: room2

执行动作 3: ('Go', 'room2', 'room3', 'robot')
当前状态:
  机器人位置: room3
  持有的物体: ['box2']
  box1的位置: room1
  box2的位置: room3  # 注意:box2 随机器人移动!

执行动作 4: ('Release', 'box2')
当前状态:
  机器人位置: room3
  持有的物体: []
  box1的位置: room1
  box2的位置: room3

最终查询:
  At(box2, room3)? True
  Holding(box2)? False
  At(robot, room3)? True

代码要点:

  1. 后继状态公理实现progress() 方法严格遵循 F(Result(a,s)) ⇔ γ⁺ ∨ (F(s) ∧ ¬γ⁻) 的形式。
  2. 框架问题解决:每个流只需一条更新规则,无需为每个"不变"的情况单独编码。
  3. 分支问题处理:当机器人移动时,被持有的物体自动跟随移动(通过 gamma_plus['At_obj'] 实现),这是间接效果。
  4. 与理论对应:这实现了前向投影(progression),需要完整初始状态。回归(regression)算法需要符号操作,更适合用 Prolog 等逻辑编程语言实现。

3.2 事件演算的推理:演绎、溯因、归纳

事件演算的三类推理任务(Shanahan 的分类):

演绎(Deduction)—— 时序投影

已知:叙事(HappensHappensHappens 事实)+ 领域描述(Initiates/TerminatesInitiates/TerminatesInitiates/Terminates
:某时刻哪些流成立(HoldsAtHoldsAtHoldsAt

%% Prolog 实现(简化)
holdsAt(F, T2) :-
    happens(E, T1), T1 < T2,
    initiates(E, F, T1),
    \+ clipped(T1, F, T2).

clipped(T1, F, T2) :-
    happens(E, T), T1 =< T, T < T2,
    terminates(E, F, T).

⚠️ \+(否定即失败)实现了非单调的惯性——这依赖第 10 章 §3.3 讨论的封闭世界假设。

溯因(Abduction)—— 规划与解释

已知:领域描述 + 目标(HoldsAtHoldsAtHoldsAt 查询)
:使目标成立的叙事HappensHappensHappens 事实集合)

这正是规划! 在事件演算中,规划 = 溯因推理。

function ABDUCE(goal, domain) returns 事件序列
    // 目标导向的后向链接,但允许"假设" Happens 事实
    residue ← {}                          // 溯因残余:假设的 Happens
    solve(goal):
        if goal 可由 domain 演绎得到 then return
        if goal 形如 happens(E, T) then
            residue ← residue ∪ {happens(E,T)}     // 假设它发生了
        else
            展开 goal 的定义,递归求解子目标
    return 排序后的 residue(加上时间约束)

溯因规划的特点

  • 天然产生偏序计划(只约束必要的时间顺序)—— 呼应第 11 章 §3.3 的 POP。
  • 可以处理并发(多个事件同一时刻)。
  • 效率通常低于专用规划器,但表达力更强。

实用工具

  • ASP 编码(Answer Set Programming):把事件演算编码为 ASP 程序,用 clingo 求解。这是当前最实用的事件演算实现方式。
  • DEC reasoner(Mueller):把离散事件演算编码为 SAT。
归纳(Induction)—— 学习动作模型

已知:叙事 + 观察到的 HoldsAtHoldsAtHoldsAt
:领域描述(Initiates/TerminatesInitiates/TerminatesInitiates/Terminates 规则)

这是动作模型学习(action model learning),与第 19 章的 ILP 直接相关。

算法思路(ARMS、LOCM、FAMA 等):

  1. 从执行轨迹中提取“动作前后的状态变化”。
  2. 归纳出哪些谓词被添加/删除。
  3. 用约束求解或 ILP 找出最简洁的一致假设。

3.3 定性空间推理:路径一致性算法

function PATH-CONSISTENCY(constraints) returns 精化的约束网络或 inconsistent
    // constraints[i][j] 是 i 与 j 之间可能关系的集合
    queue ← 所有三元组 (i, j, k)
    while queue 非空 do
        (i, j, k) ← POP(queue)
        newRel ← constraints[i][j] ∩ COMPOSE(constraints[i][k], constraints[k][j])
        if newRel = {} then return inconsistent
        if newRel ≠ constraints[i][j] then
            constraints[i][j] ← newRel
            constraints[j][i] ← INVERSE(newRel)
            把所有涉及 (i, j) 的三元组加回 queue
    return constraints

其中 COMPOSECOMPOSECOMPOSE组合表(composition table)——一个预先计算好的 8×88\times88×8(RCC-8)或 13×1313\times1313×13(Allen)表格。

复杂度O(n3)O(n^3)O(n3) 次组合操作(nnn 为区域/区间数)。

性质

  • 可靠:若返回 inconsistent,则约束网络确实不一致。
  • 不完备:路径一致 ≠ 全局一致(对完整 Allen 代数)。
  • 可处理子类(点代数、ORD-Horn):路径一致性是完备的

应用

  • 机器人的空间知识维护(“杯子在盘子上,盘子在桌上 ⇒ 杯子在桌上方”)。
  • 自然语言的空间描述理解。
  • GIS 与地理信息推理。

3.4 机器人的混合表示架构

真实机器人不能只用符号表示。典型的三层架构

┌─────────────────────────────────────────────┐
│  慎思层(Deliberative Layer)                 │
│  · 符号世界模型(FOL / 事件演算 / PDDL)        │
│  · 任务规划(第 11 章)                        │
│  · 时间尺度:秒~分钟                           │
└──────────────┬──────────────────────────────┘
               │ 符号动作 ↓    ↑ 符号状态(谓词)
┌──────────────┴──────────────────────────────┐
│  执行层(Executive / Sequencing Layer)       │
│  · 计划执行与监控(execution monitoring)      │
│  · 动作分解(HTN / GOLOG 程序)               │
│  · 失败检测与重规划触发                        │
│  · 时间尺度:0.1~1 秒                         │
└──────────────┬──────────────────────────────┘
               │ 运动指令 ↓    ↑ 状态估计
┌──────────────┴──────────────────────────────┐
│  反应层(Reactive / Control Layer)           │
│  · 运动控制(PID、MPC)                       │
│  · 传感器融合(Kalman filter、粒子滤波)        │
│  · 避障、伺服                                 │
│  · 时间尺度:1~100 ms                         │
└─────────────────────────────────────────────┘

关键接口问题

方向 问题 技术
向上(感知 → 符号) 从连续传感器数据判定符号谓词的真值 分类器、目标检测、SLAM、符号接地
向下(符号 → 控制) 把符号动作 Pick(cup)Pick(cup)Pick(cup) 转为关节轨迹 运动规划、逆运动学、抓取规划

符号接地的形式化

Holds(On(A,B),t) ⇐ Classifier(Percept(t))="A on B" with confidence>τHolds(On(A, B), t) \ \Leftarrow\ \text{Classifier}\big(\text{Percept}(t)\big) = \text{"A on B"} \text{ with confidence} > \tauHolds(On(A,B),t)  Classifier(Percept(t))="A on B" with confidence>τ

⚠️ 这个箭头是整个架构最脆弱的环节

  1. 分类器有错误率 ⇒ 符号世界模型可能错误。
  2. 符号推理是确定性的 ⇒ 一个错误谓词可能导致整个推理链失效(第 7 章的爆炸原理)。
  3. 阈值 τ\tauτ 的选择是任意的,丢弃了置信度信息。

这直接推动了向概率表示的转移(第 13–17 章):

  • 用概率图模型代替确定性谓词。
  • 用 POMDP 代替确定性规划。
  • 但代价是失去了逻辑的组合性与可解释性

折中方案

  • 概率逻辑:Markov Logic Networks、ProbLog、概率情境演算(DTGolog)。给逻辑规则加权重,兼顾结构与不确定性。
  • 符号层保守化:只在高置信度时断言谓词,低置信度时保持 unknown(开放世界),用第 11 章的应急规划处理。

4. 关键图示/表格说明

4.1 情境树(Situation Tree)

                          S₀
                    [初始情境]
          ┌───────────────┼───────────────┐
       Forward         TurnLeft        Grab
          ↓               ↓               ↓
    do(Fwd,S₀)      do(TL,S₀)      do(Grab,S₀)
       ┌──┴──┐         ┌──┴──┐            │
    Grab   TurnR    Forward  ...          ...
       ↓      ↓         ↓
do(Grab,do(Fwd,S₀))   ...

读图要点

  1. 每个节点是一个情境项(一个 FOL 的 term),不是一个状态。
  2. 树而非图:即使两条路径导致相同的物理状态,它们是不同的情境(不合并)。
  3. 这棵树表示所有可能的未来,规划就是在其中找一条到达目标的路径。
  4. ⚠️ 与第 3 章搜索树的区别:搜索树的节点是状态(可合并/去重);情境树的节点是历史(不可合并)。这使情境演算能表达“我做过什么”,代价是无法做状态去重。
  5. 流的真值依附于节点At(Robot,[1,2],do(Fwd,S0))At(Robot,[1,2], do(Fwd, S_0))At(Robot,[1,2],do(Fwd,S0)) 是一个原子句子。

4.2 后继状态公理的结构图解

        流 F 在 Result(a,s) 中为真
                    ⇕
        ┌───────────────────────────┐
        │                           │
   γ⁺(a,s) 成立              F(s) 成立
   「a 使 F 变真」                │  且
        │                    ¬γ⁻(a,s)
        │                 「a 没使 F 变假」
        │                           │
      正效果                      惯性
        └─────────── ∨ ────────────┘

例:Holding(g, do(a,s)) ⟺
       a = Grab(g)                    ← γ⁺:抓取使其为真
    ∨ (Holding(g,s) ∧ a ≠ Release(g)) ← 惯性:本来握着且没放开

读图要点

  • 左支处理“变化”,右支处理“不变”
  • ⇔\Leftrightarrow(而非 ⇒\Rightarrow)使公理信息完整——它同时告诉我们何时为真、何时为假。
  • 公理数量 = 流的数量,与动作数无关。这就是解决表示性框架问题的关键。
  • ⚠️ 前提:γ+\gamma^+γ+γ−\gamma^-γ 必须穷举所有影响 FFF 的动作(完备性假设)。

4.3 事件演算的时间线图解

时间轴 ─────────────────────────────────────────────────→
        0        t₁        t₂        t₃        t₄
        │        │         │         │         │
事件    │      PickUp    Move      Drop        │
        │        ●─────────●─────────●         │
        │        │         │         │         │
流:     │        │         │         │         │
Holding │        ╔═════════════════╗           │
(R,Box) │        ║ Initiates       ║Terminates │
        │        ╚═════════════════╝           │
        │                                       │
At(Box, │═══════════╗                          │
 RoomA) │Initially  ║ Terminated by PickUp     │
        │           ╚                           │
        │                                       │
At(Box, │                             ╔════════════════
 RoomB) │                             ║ Initiated by Drop
        │                             ╚════════════════

查询:HoldsAt(At(Box, RoomB), t₄)?
推理:Happens(Drop, t₃) ∧ Initiates(Drop, At(Box,RoomB), t₃)
      ∧ t₃ < t₄ ∧ ¬Clipped(t₃, At(Box,RoomB), t₄)
   ⇒ HoldsAt(At(Box,RoomB), t₄)   ✓

读图要点

  1. 单一线性时间轴(对比情境演算的分支树)。
  2. 流的真值区间由 InitiatesInitiatesInitiatesTerminatesTerminatesTerminates 事件划定。
  3. ClippedClippedClipped 是“守卫”:检查区间内是否有终止事件。
  4. 多个事件可以在同一时刻发生(并发)——这是事件演算相对情境演算的关键优势。
  5. 外部事件(非智能体引发)可以自由加入叙事,无需修改动作定义。

4.4 三大难题对照表

难题 问题描述 情境演算解法 事件演算解法 STRIPS/PDDL 解法
框架问题 如何表达"什么没变" 后继状态公理O(∥F∥)O(\|F\|)O(F) 条) 惯性公理 + Clipped ADD/DEL 列表(隐式框架假设)
限定问题 前提无法穷举 非单调扩展(AbAbAb 谓词 + 限定) 同左 忽略(+ 执行监控与重规划)
分支问题 间接效果 状态约束 + 因果传播 状态约束(作为额外的 Initiates 规则) 条件效果(ADL)/ 派生谓词

核心观察

STRIPS 之所以高效,正是因为它用表示上的假设"绕过"了这三个问题,而不是解决它们。这在封闭的规划领域可行,在开放的机器人场景则不断出问题——这就是为什么机器人研究不能完全抛弃情境演算/事件演算这类完整形式化。

4.5 定性 vs 定量表示对照

层面 定量(连续) 定性(符号) 桥接技术
位置 (x,y,θ)∈R3(x,y,\theta)\in\mathbb{R}^3(x,y,θ)R3 At(Robot,RoomA)At(Robot, RoomA)At(Robot,RoomA) 地图分割、拓扑地图
物体关系 6D 姿态矩阵 On(A,B)On(A,B)On(A,B)In(A,B)In(A,B)In(A,B) RCC-8 + 几何判定
时间 t∈R+t\in\mathbb{R}^+tR+ Before(e1,e2)Before(e_1,e_2)Before(e1,e2) Allen 代数 + 时间戳
动作 关节轨迹 q(t)q(t)q(t) Pick(cup)Pick(cup)Pick(cup) 运动规划、技能库
不确定性 概率分布 Unknown / 可能世界集 阈值化、概率逻辑
感知 像素、点云 谓词真值 符号接地(最难)

读表要点最右列的每一项都是一个活跃的研究方向,且"符号接地"是公认最困难的。

4.6 情境演算与事件演算的选择决策树

需要表示动作与变化
        │
        ├─ 主要做「假设推理/规划」(如果我做X会怎样)?
        │       └─→ 情境演算(分支时间,天然支持 what-if)
        │
        ├─ 主要做「叙事理解/监控」(已经发生了什么)?
        │       └─→ 事件演算(线性时间,天然支持叙事)
        │
        ├─ 需要并发事件、持续动作、外部事件?
        │       └─→ 事件演算(或 ConGolog)
        │
        ├─ 需要表示智能体的知识与感知?
        │       └─→ 情境演算 + 知识流(K 关系)
        │
        └─ 只需高效求解封闭的规划问题?
                └─→ PDDL + 专用规划器(第 11 章)✓ 实践首选

5. 与其他章节的关联

5.1 承前

章节 关联
第 7 章 命题逻辑的"后继状态公理"(Ft+1⇔…F^{t+1}\Leftrightarrow \dotsFt+1)是情境演算后继状态公理的命题版本;框架问题在此首次出现
第 8 章 情境演算完全建立在 FOL 之上;情境、事件、流都是通过具体化成为 FOL 中的项
第 9 章 情境演算的推理用归结/Prolog;事件演算的溯因规划用后向链接 + 假设生成;情境项的合一是主要计算开销
第 10 章 事件演算在第 10 章 §2.6 首次引入;本章深化。定性时空推理、Allen 代数、具体化技巧全部来自第 10 章
第 11 章 PDDL 是情境演算的受限片段(ADD/DEL = 简化的后继状态公理);本章解释了 PDDL “为什么能这么简单"以及"代价是什么”;GOLOG ↔ HTN;执行监控与重规划直接对应

5.2 启后

章节 关联
第 13–14 章 概率 符号接地的不确定性推动向概率表示转移;贝叶斯网络可表示"传感器读数 → 状态"的软映射
第 14 章 时序概率模型 HMM/DBN 是"概率化的事件演算":状态随时间演化 + 观测。转移模型 ≈ 后继状态公理的概率版本
第 17 章 MDP/POMDP DTGolog、概率情境演算是决策论与逻辑的融合;知识流与 POMDP 的信念状态是同一概念的两种表示(符号 vs 概率)
第 22 章 强化学习 关系型 RL(relational RL)用逻辑表示状态与策略,是本章表示与 RL 的结合
第 26 章 机器人学 本章提供符号层,第 26 章提供运动规划与控制;TAMP 是两者的结合点
第 24–25 章 NLP 事件演算的叙事推理与语言中的时体(tense/aspect)理解直接相关;语义解析把自然语言映射到事件表示

5.3 表示"变化"的技术演进主线

第7章:命题 + 时间下标
   │ 表示冗长(每个时刻一套符号),框架公理 O(|A|×|F|)
   ↓
情境演算 + 朴素效果公理
   │ 仍需 O(|A|×|F|) 框架公理
   ↓
情境演算 + 后继状态公理(Reiter)  ← 本章核心
   │ O(|F|) 条,但推理仍慢;不支持并发/外部事件
   ↓
事件演算  ← 本章核心
   │ 支持并发、持续、外部事件;但推理更慢
   ↓
STRIPS / PDDL(第11章)
   │ 用表示假设绕过三大难题,换来高效求解
   │ 代价:不能表达不确定性、并发、知识
   ↓
概率转移模型:DBN / MDP / POMDP(第14、17章)
   │ 用概率吸收不确定性,但失去逻辑组合性
   ↓
概率逻辑 / 神经符号(前沿)
     试图兼得:MLN、ProbLog、DTGolog、神经-符号 Agent

这条主线揭示了 AI 表示研究的根本张力

表达力(能说清楚多少)↔ 可推理性(能算多快)↔ 鲁棒性(能容忍多少噪声)

三者不可兼得,每个时代的主流方法都是在特定约束下的一个取舍点。


6. 延伸思考

6.1 LLM 是"隐式的事件演算推理器"吗?

本章的事件演算处理的核心任务是叙事推理(narrative reasoning):给定一串事件,推断任意时刻世界的状态。

这恰好是 LLM 极为擅长的任务:

"小明把书放在桌上。然后他去了厨房。他把咖啡端到客厅。"
问:书现在在哪里?
LLM: 书在桌上。(正确应用了惯性!)

LLM 没有 HoldsAtHoldsAtHoldsAt、没有 ClippedClippedClipped、没有惯性公理,却能正确推理。这引出几个深刻问题:

观察 1:LLM 在"默认惯性"上表现优异,在"追踪多个流"上表现脆弱。

研究(如 bAbI 任务、Entity Tracking 基准)表明:

  • 单个物体、少量事件 ⇒ LLM 准确率很高。
  • 5+ 个物体、10+ 个事件、含嵌套容器(“把书放进包,把包放进车”)⇒ 准确率显著下降。

这与事件演算的形式化直接对应:LLM 似乎学到了惯性的统计模式,但缺乏系统性的状态维护机制。事件演算的 ClippedClippedClipped 谓词是一个显式的、可靠的检查;LLM 的对应机制是隐式的注意力,容量有限且随流数量退化。

开放性问题 1

LLM 的上下文窗口能否被视为一种隐式的事件演算数据库?如果是,那么它的"ClippedClippedClipped 检查"是如何实现的——是注意力回溯扫描所有历史事件(O(n)O(n)O(n) 每查询),还是维护了某种压缩的状态摘要?

这不是纯理论问题。它预测了不同的失效模式:

  • 若是回溯扫描 ⇒ 性能随上下文长度线性退化,但不会遗漏。
  • 若是状态摘要 ⇒ 性能对长度不敏感,但会系统性遗漏某些更新(“更新盲区”)。

可解释性研究(entity tracking circuits)的初步证据支持混合机制。这提示了一个实用方向:用显式的事件演算状态表作为 LLM 的外部工具——让模型在每个事件后调用工具更新状态表,而非依赖上下文推理。这与本章 §3.1 的"progression"完全同构。

开放性问题 2

§2.1 的分支问题(ramification)——间接效果——是形式化方法的老大难。而 LLM 处理得出奇地好:“把杯子放进包里,然后带包出门” ⇒ 杯子也出门了。LLM 是从海量文本中学到了"容器传递性"这类朴素物理常识

那么:能否让 LLM 生成状态约束公理(∀x,y,l In(x,y)∧At(y,l)⇒At(x,l)\forall x,y,l\ In(x,y)\wedge At(y,l)\Rightarrow At(x,l)x,y,l In(x,y)At(y,l)At(x,l)),交给符号推理器可靠地传播?

这是"LLM 提供知识,符号引擎提供可靠性"范式在本章的具体化。与第 11 章 §6.1 讨论的"LLM 生成 PDDL"是同一思路的不同层面:那里生成的是动作模型,这里生成的是领域约束

6.2 知识流与 AI 自我模型:机器人"知道自己不知道"

§2.3 的知识表示(Knows(ϕ,s)Knows(\phi, s)Knows(ϕ,s)KWhetherKWhetherKWhether)在当前 AI 讨论中有直接的重要性。

核心能力:一个系统能否表示"我不知道 X,但执行动作 A 后我就会知道"?

¬KWhether(ϕ,s) ∧ KWhether(ϕ,Result(Senseϕ,s))\neg KWhether(\phi, s) \ \wedge\ KWhether(\phi, Result(Sense_\phi, s))¬KWhether(ϕ,s)  KWhether(ϕ,Result(Senseϕ,s))

这个能力支撑三件关键的事:

  1. 主动信息收集:机器人主动去看、去问、去试探。这是从"被动执行"到"主动求知"的分界线。
  2. 校准的不确定性表达:“我不确定,需要更多信息”——而非自信地编造。
  3. 知识前提检查:在执行 Dial(x)Dial(x)Dial(x) 前,检查 Knows(Combination=x)Knows(Combination = x)Knows(Combination=x)。若不知道,先规划获取信息。

LLM 的现状

  • 校准(calibration)研究表明,模型的置信度与准确率有一定相关性,但远非可靠
  • 更关键的是:LLM 缺乏"我可以通过某个动作获知 X"的显式表示。它可以说"我不知道",但不能系统地规划"如何知道"。
  • ReAct 类 Agent 通过工具调用部分实现了这一点,但缺乏形式化的知识前提检查。

开放性问题

能否为 LLM Agent 建立显式的知识状态模型——一个记录"我知道什么、不知道什么、如何能知道"的结构化表示,并把工具调用规划为知识获取动作

技术上,这需要:

  1. 把工具的效果建模为知识流的变化(Initiates(Search(q),Knows(answer(q)),t)Initiates(Search(q), Knows(answer(q)), t)Initiates(Search(q),Knows(answer(q)),t))。
  2. 在规划时检查知识前提。
  3. 用第 11 章的应急规划处理"搜索可能失败"的情况。

这实质上是把 POMDP 的信念状态(第 17 章)用符号方式表示——牺牲精确的概率,换取可解释性与组合性。

6.3 符号接地:多模态模型的机会与陷阱

§3.4 指出:机器人 KR 最脆弱的环节是从感知到符号的映射。

多模态大模型带来的机会

  • VLM 可以直接回答"On(Cup,Table)On(Cup, Table)On(Cup,Table) 现在为真吗?"——无需为每个谓词训练专用分类器。
  • 开放词汇:可以查询训练时未见过的谓词(“这个物体是否易碎?”)。
  • 零样本泛化:新场景、新物体无需重新标注。

但陷阱同样明确

陷阱 1:确定性推理 + 概率感知 = 灾难

若 VLM 对每个谓词有 95% 准确率,一个涉及 20 个谓词的规划有 0.9520≈36%0.95^{20}\approx 36\%0.952036% 的概率全部正确。而符号规划器假设输入完全正确——它会自信地基于错误状态生成方案。

这不是可以通过"提高准确率"解决的问题——它是架构问题。正确的做法是:

  • 让符号层承认不确定性:用三值逻辑(true/false/unknown)而非二值。
  • 用第 11 章 §3.7.2 的计划监控:不只检查下一步,而是持续验证整个剩余计划的前提。
  • 或者彻底转向 POMDP(代价是计算复杂度)。

陷阱 2:VLM 的谓词判断不满足逻辑约束

分别问 VLM “On(A,B)On(A,B)On(A,B)?” 和 “On(B,A)On(B,A)On(B,A)?”,它可能都回答 yes——违反了反对称性。分别问 “In(A,B)In(A,B)In(A,B)”、“In(B,C)In(B,C)In(B,C)”、“In(A,C)In(A,C)In(A,C)”,可能违反传递性。

这是纯神经方法的固有问题:每个查询独立,没有全局一致性保证。

开放性问题

能否用本章的定性推理框架(RCC-8 组合表、路径一致性算法,§3.3)作为 VLM 输出的一致性后处理器?即:

  1. VLM 给出所有物体对的空间关系(带置信度)。
  2. 用路径一致性算法检测冲突。
  3. 冲突时,保留高置信度关系,重新查询低置信度的。

这是一个具体可实现的神经-符号混合,且有明确的评估指标(一致性违反率)。它把符号推理用在最合适的地方:不是替代感知,而是约束感知

6.4 AI 对齐视角:动作表示与可问责性

本章的形式化对 AI 安全有几个直接的贡献,值得单独强调。

1. 情境作为"完整的动作历史"—— 天然的审计日志

情境演算的一个"缺点"(不合并等价状态)在安全语境下变成优点

情境项 do(an,…do(a1,S0))do(a_n, \dots do(a_1, S_0))do(an,do(a1,S0)) 完整记录了智能体做过的每一件事

这正是 Agent 系统需要的可审计性:不只知道"当前状态是什么",还知道"是通过哪些动作到达的"。当出问题时,可以精确回溯。

实践建议:Agent 框架应该维护完整的动作历史(情境项),而非只维护当前状态。这个开销是线性的,而收益是完整的可问责性。

2. PossPossPoss 谓词作为动作授权的形式化载体

Poss(a,s)⇔Πa(s)Poss(a, s) \Leftrightarrow \Pi_a(s)Poss(a,s)Πa(s)

Πa\Pi_aΠa 通常表示物理可行性。但它可以自然地扩展为包含授权条件

Poss(Transfer(amount,account),s)⇔Balance(s)≥amount∧Authorized(user,amount,s)∧amount<DailyLimitPoss(Transfer(amount, account), s) \Leftrightarrow Balance(s)\ge amount \wedge Authorized(user, amount, s) \wedge amount < DailyLimitPoss(Transfer(amount,account),s)Balance(s)amountAuthorized(user,amount,s)amount<DailyLimit

关键优势

  • 授权条件与动作定义在同一处,不会被绕过。
  • 可以形式化验证"不存在使 PossPossPoss 为真但违反安全策略的情境"。
  • 与第 11 章 §6.4 讨论的"执行前验证"架构完美契合。

3. 知识前提 = 知情同意的形式化

Poss(a,s)⇒Knows(Consequences(a),s)Poss(a, s) \Rightarrow Knows(Consequences(a), s)Poss(a,s)Knows(Consequences(a),s)

“只有在知道后果时才可以执行动作。”

这条元级约束可以形式化"不要在无知的情况下采取不可逆行动"这一安全原则。它比"列出禁止动作清单"更根本——因为清单永远不完整(这正是 §2.1 的限定问题!)。

4. 一个警示:限定问题就是"规则永远不完整"的形式化

本章 §2.1 的限定问题告诉我们:动作的前提永远无法穷举

把这个结论迁移到 AI 安全:

任何基于"禁止清单"的安全约束都是不完整的。 这不是工程质量问题,而是逻辑上的必然——正如"发动汽车"的前提列表没有尽头,"有害行为"的清单也没有尽头。

这为两类方法提供了理论依据:

  • 非单调 / 默认安全:默认禁止,显式允许(allowlist 而非 blocklist)。对应 §2.1 的 ¬Ab\neg Ab¬Ab 结构。
  • 基于价值学习而非规则:从人类反馈中学习"什么是有害",而非枚举(第 18、22 章的路线)。

但两者都有代价:

  • Allowlist 严重限制能力(Agent 只能做预先批准的事)。
  • 价值学习无形式保证(可能学错)。

这个张力没有干净的解——但至少,本章的形式化让我们能精确地说出问题在哪,而不是含糊地说"AI 可能做坏事"。

收束思考

本章是全书逻辑与知识表示部分的终章。它的核心教训或许是:

表示"世界如何变化"比表示"世界是什么样"困难得多。

静态知识(第 8–10 章)可以用 FOL 优雅地表达;一旦引入动作与时间,就撞上框架、限定、分支三大难题,任何形式化都必须做出痛苦的取舍。

这个教训在今天依然成立。当我们讨论"AI Agent 能否可靠地在真实世界中行动"时,问的正是本章的问题——只不过现在的答案是用神经网络的隐式表示给出的,而它的取舍比情境演算更不透明。理解本章,就是获得了一副审视这些新系统的诊断眼镜

4. 总结与延伸思考

本章系统阐述了机器人学中表示动作与变化的两大形式化工具——情境演算与事件演算,它们为智能体在动态世界中的推理与行动提供了坚实的逻辑基础。本节将对两者的核心思想、适用场景及局限性进行总结,并探讨它们与现代机器人系统(如 ROS)和大语言模型(LLM)在规划与推理方面的潜在结合点。

4.1 核心思想与适用场景总结

情境演算(Situation Calculus)情境(动作历史)为基本本体,采用分支时间模型,天然支持假设推理(what‑if)和前瞻性规划。其核心贡献是 Reiter 后继状态公理,以 O(∣F∣)O(|F|)O(F) 条公理优雅解决了表示性框架问题,并通过知识流(KnowsKnowsKnows)和知识后继状态公理将感知与知识更新纳入同一框架。适用场景包括:

  • 封闭世界的规划与验证:智能体的动作是唯一的变化来源,且动作效果可完全枚举。
  • 知识与感知的显式表示:需要建模“智能体知道什么”以及“感知如何改变知识”的认知任务。
  • 程序化控制:通过 GOLOG 等语言将部分确定性程序与非确定性选择结合,实现“人给结构,机器填细节”的混合规划。

事件演算(Event Calculus)事件时间点为基本本体,采用线性时间模型,天然支持并发事件、持续过程和外部事件。其核心是惯性公理ClippedClippedClipped/DeclippedDeclippedDeclipped 谓词,通过声明式叙事(HappensHappensHappens 事实)描述已发生的事件,并推导任意时刻的流真值。适用场景包括:

  • 叙事理解与监控:从观察到的(或记录的)事件序列推断世界状态。
  • 并发与持续过程建模:多个事件同时发生、动作有持续时间、连续变化(如水位上升)。
  • 开放世界推理:外部事件(非智能体引发的变化)可自由加入叙事,无需修改动作定义。

局限性对比

  • 情境演算难以处理并发、持续动作和外部事件;其分支时间模型在记录实际历史时显得冗余;规划作为定理证明在实践中效率较低。
  • 事件演算的推理(尤其是溯因)计算复杂度高;对大规模状态空间的扩展性不足;惯性公理依赖否定即失败(非单调推理),在复杂因果链中可能产生意外结果。

4.2 与现代机器人系统(如 ROS)的结合

现代机器人操作系统(如 ROS)通常采用分层架构(慎思层、执行层、反应层),本章的形式化工具主要位于慎思层,为高层任务规划提供符号表示与推理能力。

潜在结合点

  1. 符号‑连续接口:情境演算的 PossPossPoss 谓词或事件演算的 HappensHappensHappens 可触发底层的运动规划(如 MoveIt!)或技能执行。例如,Poss(Pick(cup),s)Poss(Pick(cup), s)Poss(Pick(cup),s) 在验证几何可行性(抓取位姿存在)后,调用逆运动学求解器生成关节轨迹。
  2. 执行监控与重规划:事件演算的叙事推理可用于在线监控——将传感器事件(如“物体掉落”)作为 HappensHappensHappens 事实插入,实时更新 HoldsAtHoldsAtHoldsAt 状态,并在前提违反时触发重规划(对应第 11 章的应急规划)。
  3. 混合系统建模:事件演算的 TrajectoryTrajectoryTrajectory 谓词可描述连续过程(如机器人移动中的位姿变化),与 ROS 中的 TF 坐标变换、odometry 流自然对接。符号层提供定性目标(“到达房间 A”),连续层提供定量控制。
  4. 知识状态维护:在部分可观察环境中,ROS 的感知流水线(目标检测、SLAM)可输出带置信度的谓词(如 On(cup,table)On(cup, table)On(cup,table) 的概率),进而用概率情境演算(如 DTGolog)或概率逻辑(如 Markov Logic Networks)进行决策。

挑战

  • 符号接地仍是瓶颈:从点云、图像到符号谓词的映射不可避免地存在噪声与歧义,而符号推理对错误敏感。
  • 实时性:形式化推理(如溯因、路径一致性)的计算开销可能无法满足实时控制要求,常需近似或编译为高效数据结构(如将 RCC‑8 关系缓存为位矩阵)。

4.3 与大语言模型(LLM)在规划与推理中的结合

LLM 在自然语言理解与生成上的突破,为本章形式化工具的实用化提供了新的可能性。

互补优势分析

  • LLM 的长处:从非结构化文本中提取常识性动作效果、状态约束(如“打开门后通常可以穿过”);生成符合人类直觉的任务描述与分解;处理开放词汇和未见过的谓词。
  • 形式化工具的长处:提供可靠的状态追踪(无遗忘、无矛盾);支持反事实推理(what‑if);保证逻辑一致性(传递性、反对称性等);实现可解释的决策链

结合范式

  1. LLM 作为“常识知识编译器”:让 LLM 阅读领域描述(如机器人操作手册),自动生成情境演算的后继状态公理或事件演算的 InitiatesInitiatesInitiates/TerminatesTerminatesTerminates 规则。例如,输入“抓取物体需要机器人靠近该物体且手空闲”,输出:
    Poss(Grab(obj), s) :- At(robot, loc, s), At(obj, loc, s), not Holding(robot, _, s).
    
    这解决了手工编写领域模型的瓶颈。
  2. 形式化引擎作为“可靠的状态管理器”:LLM 解析自然语言指令生成初始目标,形式化推理器(如 Prolog 实现的事件演算)进行投影、规划或解释,并将结果(动作序列、状态轨迹)返回给 LLM 转换为自然语言答复。这样,LLM 不再依赖有限的上下文窗口进行脆弱的状态维护。
  3. 混合推理框架:对简单、常识性推理(如“书在桌上,桌子没动,所以书还在桌上”)由 LLM 快速完成;对复杂、多步骤的推理(如涉及 10 个物体、嵌套容器的传递性)则调用形式化引擎确保正确性。这类似第 11 章中 HTN 的“高层规划由人/LLM 提供,细节由符号规划器填充”。
  4. 可问责性增强:如 §6.4 所述,情境演算的完整动作历史可作为 Agent 的审计日志。LLM 生成的每个动作都记录在 dododo 链中,一旦出现问题可精确回溯到具体决策点,便于调试与归责。

前沿方向

  • 神经‑符号状态估计:用 VLM(视觉语言模型)感知场景,输出带置信度的谓词集合,再用 RCC‑8 路径一致性算法(§3.3)进行一致性修正,形成符号世界模型。
  • 从 LLM 隐式知识到显式公理的蒸馏:通过提示工程让 LLM 输出 Allen 区间代数关系或状态约束,将其编译为可推理的符号规则,逐步构建可扩展的领域知识库。
  • LLM 驱动的 GOLOG 程序合成:用户用自然语言描述任务,LLM 生成 GOLOG 式的部分程序(确定性的序列与非确定性的选择点),由情境演算推理器填充细节并验证可行性。

4.4 局限性与未来展望

尽管情境演算与事件演算在理论上优雅且表达力强,其实际应用仍受限于:

  • 计算复杂度:一阶逻辑推理的复杂度较高,难以扩展到超大规模状态空间。
  • 知识工程负担:手工编写完备、一致的后继状态公理或 InitiatesInitiatesInitiates/TerminatesTerminatesTerminates 规则极易出错。
  • 对不确定性的处理不足:虽然概率扩展(如 DTGolog、概率事件演算)存在,但融合概率与逻辑的推理仍很沉重。

未来可能的发展路径

  1. 编译化:将形式化描述编译为可高效执行的数据结构(如 BDD、SAT 编码),类似 PDDL 到规划器的编译。
  2. 神经符号混合系统的成熟:LLM 负责知识提取与泛化,符号引擎负责可靠推理与状态维护,两者通过明确定义的接口(如谓词、动作模式)协作。
  3. 在线学习与适应:结合第 19 章的归纳逻辑编程(ILP),从执行轨迹中学习动作模型与状态约束,减少手工编码。

最终启示
本章揭示的“表达力‑可推理性‑鲁棒性”不可能三角,至今仍是 AI 系统设计的核心张力。情境演算与事件演算站在表达力的一极,为我们提供了理解动态世界的精确语言;而现代机器人系统与 LLM 则试图在可推理性与鲁棒性上寻求突破。未来的智能体很可能不是单一范式的胜利,而是多层架构的协同:底层是连续的传感器‑控制器环路,中层是符号化的状态管理与逻辑推理,顶层是自然语言交互与常识理解。本章的形式化工具,正是连接这些层次不可或缺的桥梁。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐