人工智能:现代方法读书笔记(十二)
第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 章的核心技巧)把“情境”或“事件”提升为一等对象。
本章主线:
- 变化表示的三大难题:框架问题、限定问题、分支问题。
- 情境演算:情境、流、ResultResultResult/DoDoDo 函数、PossPossPoss 谓词、后继状态公理(Reiter 解法)。
- 投影、规划与执行:情境演算中的推理任务;GOLOG 语言。
- 知识与感知的表示:KnowsKnowsKnows 流、传感动作、知识后继状态公理。
- 事件演算:HappensHappensHappens、InitiatesInitiatesInitiates、TerminatesTerminatesTerminates、ClippedClippedClipped、惯性公理。
- 两者对比与转换。
- 基于特征的本体与定性推理:定性空间/时间推理、定性物理。
- 机器人特有的表示问题:连续状态、不确定性、传感器模型、混合表示。
核心直觉:
表示"变化"的全部困难,可以归结为一个矛盾:世界的大部分在大部分时候不变(惯性),但逻辑无法"默认"任何东西。所有解法——后继状态公理、事件演算的 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(Running∣Start,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) | sss、S0S_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)KB⊨Executable([a1,…,an],S0) | 每步的 PossPossPoss 都成立 |
| 规划(planning) | KB⊨∃s Executable(s)∧ϕ(s)KB\models\exists s\ \ Executable(s) \wedge \phi(s)KB⊨∃s 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]KB⊨∃s [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 章的专用规划器高效。原因:
- 通用定理证明器无法利用规划问题的特殊结构(如启发式、可达性分析)。
- 搜索空间是证明空间而非状态空间,剪枝困难。
- 情境项会变得极长,合一代价高。
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′=s≡∃s′′ 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)是动作 aaa 在 sss 中的感知返回值。
读法:
执行 aaa 后,认知可及的情境是"原先可及的情境执行 aaa 后的结果",但只保留那些感知结果与实际观察一致的。
这个公理同时实现了两件事:
- 物理效果传播:s′′=Result(a,s′)s'' = Result(a, s')s′′=Result(a,s′)。
- 知识增益(信念更新):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) | 若 eee 在 ttt 发生,则 fff 从 ttt 后为真 |
| Terminates(e,f,t)Terminates(e, f, t)Terminates(e,f,t) | 若 eee 在 ttt 发生,则 fff 从 ttt 后为假 |
| 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_1f1 在 t1t_1t1 启动,则 f2f_2f2 在 t1+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)∧t1≤t<t2∧Terminates(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)∧t1≤t<t2∧Initiates(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):
- QSIM、Qualitative 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)作为不完备但快速的近似。
为什么机器人需要定性表示
- 传感器不精确:与其说“物体在 x=3.7241x=3.7241x=3.7241”,不如说“物体在桌上”。
- 符号规划的接口:第 11 章的规划器需要离散谓词。
- 可解释性:人类用定性语言交流(“把杯子放在盘子左边”)。
- 泛化:定性描述跨实例迁移(“抓取杯柄”适用于所有杯子)。
关键挑战:符号接地(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
代码要点:
- 后继状态公理实现:
progress()方法严格遵循F(Result(a,s)) ⇔ γ⁺ ∨ (F(s) ∧ ¬γ⁻)的形式。 - 框架问题解决:每个流只需一条更新规则,无需为每个"不变"的情况单独编码。
- 分支问题处理:当机器人移动时,被持有的物体自动跟随移动(通过
gamma_plus['At_obj']实现),这是间接效果。 - 与理论对应:这实现了前向投影(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 等):
- 从执行轨迹中提取“动作前后的状态变化”。
- 归纳出哪些谓词被添加/删除。
- 用约束求解或 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>τ
⚠️ 这个箭头是整个架构最脆弱的环节:
- 分类器有错误率 ⇒ 符号世界模型可能错误。
- 符号推理是确定性的 ⇒ 一个错误谓词可能导致整个推理链失效(第 7 章的爆炸原理)。
- 阈值 τ\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₀)) ...
读图要点:
- 每个节点是一个情境项(一个 FOL 的 term),不是一个状态。
- 树而非图:即使两条路径导致相同的物理状态,它们是不同的情境(不合并)。
- 这棵树表示所有可能的未来,规划就是在其中找一条到达目标的路径。
- ⚠️ 与第 3 章搜索树的区别:搜索树的节点是状态(可合并/去重);情境树的节点是历史(不可合并)。这使情境演算能表达“我做过什么”,代价是无法做状态去重。
- 流的真值依附于节点: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₄) ✓
读图要点:
- 单一线性时间轴(对比情境演算的分支树)。
- 流的真值区间由 InitiatesInitiatesInitiates 与 TerminatesTerminatesTerminates 事件划定。
- ClippedClippedClipped 是“守卫”:检查区间内是否有终止事件。
- 多个事件可以在同一时刻发生(并发)——这是事件演算相对情境演算的关键优势。
- 外部事件(非智能体引发)可以自由加入叙事,无需修改动作定义。
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}^+t∈R+ | 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))
这个能力支撑三件关键的事:
- 主动信息收集:机器人主动去看、去问、去试探。这是从"被动执行"到"主动求知"的分界线。
- 校准的不确定性表达:“我不确定,需要更多信息”——而非自信地编造。
- 知识前提检查:在执行 Dial(x)Dial(x)Dial(x) 前,检查 Knows(Combination=x)Knows(Combination = x)Knows(Combination=x)。若不知道,先规划获取信息。
LLM 的现状:
- 校准(calibration)研究表明,模型的置信度与准确率有一定相关性,但远非可靠。
- 更关键的是:LLM 缺乏"我可以通过某个动作获知 X"的显式表示。它可以说"我不知道",但不能系统地规划"如何知道"。
- ReAct 类 Agent 通过工具调用部分实现了这一点,但缺乏形式化的知识前提检查。
开放性问题:
能否为 LLM Agent 建立显式的知识状态模型——一个记录"我知道什么、不知道什么、如何能知道"的结构化表示,并把工具调用规划为知识获取动作?
技术上,这需要:
- 把工具的效果建模为知识流的变化(Initiates(Search(q),Knows(answer(q)),t)Initiates(Search(q), Knows(answer(q)), t)Initiates(Search(q),Knows(answer(q)),t))。
- 在规划时检查知识前提。
- 用第 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.9520≈36% 的概率全部正确。而符号规划器假设输入完全正确——它会自信地基于错误状态生成方案。
这不是可以通过"提高准确率"解决的问题——它是架构问题。正确的做法是:
- 让符号层承认不确定性:用三值逻辑(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 输出的一致性后处理器?即:
- VLM 给出所有物体对的空间关系(带置信度)。
- 用路径一致性算法检测冲突。
- 冲突时,保留高置信度关系,重新查询低置信度的。
这是一个具体可实现的神经-符号混合,且有明确的评估指标(一致性违反率)。它把符号推理用在最合适的地方:不是替代感知,而是约束感知。
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)≥amount∧Authorized(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)通常采用分层架构(慎思层、执行层、反应层),本章的形式化工具主要位于慎思层,为高层任务规划提供符号表示与推理能力。
潜在结合点:
- 符号‑连续接口:情境演算的 PossPossPoss 谓词或事件演算的 HappensHappensHappens 可触发底层的运动规划(如 MoveIt!)或技能执行。例如,Poss(Pick(cup),s)Poss(Pick(cup), s)Poss(Pick(cup),s) 在验证几何可行性(抓取位姿存在)后,调用逆运动学求解器生成关节轨迹。
- 执行监控与重规划:事件演算的叙事推理可用于在线监控——将传感器事件(如“物体掉落”)作为 HappensHappensHappens 事实插入,实时更新 HoldsAtHoldsAtHoldsAt 状态,并在前提违反时触发重规划(对应第 11 章的应急规划)。
- 混合系统建模:事件演算的 TrajectoryTrajectoryTrajectory 谓词可描述连续过程(如机器人移动中的位姿变化),与 ROS 中的 TF 坐标变换、odometry 流自然对接。符号层提供定性目标(“到达房间 A”),连续层提供定量控制。
- 知识状态维护:在部分可观察环境中,ROS 的感知流水线(目标检测、SLAM)可输出带置信度的谓词(如 On(cup,table)On(cup, table)On(cup,table) 的概率),进而用概率情境演算(如 DTGolog)或概率逻辑(如 Markov Logic Networks)进行决策。
挑战:
- 符号接地仍是瓶颈:从点云、图像到符号谓词的映射不可避免地存在噪声与歧义,而符号推理对错误敏感。
- 实时性:形式化推理(如溯因、路径一致性)的计算开销可能无法满足实时控制要求,常需近似或编译为高效数据结构(如将 RCC‑8 关系缓存为位矩阵)。
4.3 与大语言模型(LLM)在规划与推理中的结合
LLM 在自然语言理解与生成上的突破,为本章形式化工具的实用化提供了新的可能性。
互补优势分析:
- LLM 的长处:从非结构化文本中提取常识性动作效果、状态约束(如“打开门后通常可以穿过”);生成符合人类直觉的任务描述与分解;处理开放词汇和未见过的谓词。
- 形式化工具的长处:提供可靠的状态追踪(无遗忘、无矛盾);支持反事实推理(what‑if);保证逻辑一致性(传递性、反对称性等);实现可解释的决策链。
结合范式:
- LLM 作为“常识知识编译器”:让 LLM 阅读领域描述(如机器人操作手册),自动生成情境演算的后继状态公理或事件演算的 InitiatesInitiatesInitiates/TerminatesTerminatesTerminates 规则。例如,输入“抓取物体需要机器人靠近该物体且手空闲”,输出:
这解决了手工编写领域模型的瓶颈。Poss(Grab(obj), s) :- At(robot, loc, s), At(obj, loc, s), not Holding(robot, _, s). - 形式化引擎作为“可靠的状态管理器”:LLM 解析自然语言指令生成初始目标,形式化推理器(如 Prolog 实现的事件演算)进行投影、规划或解释,并将结果(动作序列、状态轨迹)返回给 LLM 转换为自然语言答复。这样,LLM 不再依赖有限的上下文窗口进行脆弱的状态维护。
- 混合推理框架:对简单、常识性推理(如“书在桌上,桌子没动,所以书还在桌上”)由 LLM 快速完成;对复杂、多步骤的推理(如涉及 10 个物体、嵌套容器的传递性)则调用形式化引擎确保正确性。这类似第 11 章中 HTN 的“高层规划由人/LLM 提供,细节由符号规划器填充”。
- 可问责性增强:如 §6.4 所述,情境演算的完整动作历史可作为 Agent 的审计日志。LLM 生成的每个动作都记录在 dododo 链中,一旦出现问题可精确回溯到具体决策点,便于调试与归责。
前沿方向:
- 神经‑符号状态估计:用 VLM(视觉语言模型)感知场景,输出带置信度的谓词集合,再用 RCC‑8 路径一致性算法(§3.3)进行一致性修正,形成符号世界模型。
- 从 LLM 隐式知识到显式公理的蒸馏:通过提示工程让 LLM 输出 Allen 区间代数关系或状态约束,将其编译为可推理的符号规则,逐步构建可扩展的领域知识库。
- LLM 驱动的 GOLOG 程序合成:用户用自然语言描述任务,LLM 生成 GOLOG 式的部分程序(确定性的序列与非确定性的选择点),由情境演算推理器填充细节并验证可行性。
4.4 局限性与未来展望
尽管情境演算与事件演算在理论上优雅且表达力强,其实际应用仍受限于:
- 计算复杂度:一阶逻辑推理的复杂度较高,难以扩展到超大规模状态空间。
- 知识工程负担:手工编写完备、一致的后继状态公理或 InitiatesInitiatesInitiates/TerminatesTerminatesTerminates 规则极易出错。
- 对不确定性的处理不足:虽然概率扩展(如 DTGolog、概率事件演算)存在,但融合概率与逻辑的推理仍很沉重。
未来可能的发展路径:
- 编译化:将形式化描述编译为可高效执行的数据结构(如 BDD、SAT 编码),类似 PDDL 到规划器的编译。
- 神经符号混合系统的成熟:LLM 负责知识提取与泛化,符号引擎负责可靠推理与状态维护,两者通过明确定义的接口(如谓词、动作模式)协作。
- 在线学习与适应:结合第 19 章的归纳逻辑编程(ILP),从执行轨迹中学习动作模型与状态约束,减少手工编码。
最终启示:
本章揭示的“表达力‑可推理性‑鲁棒性”不可能三角,至今仍是 AI 系统设计的核心张力。情境演算与事件演算站在表达力的一极,为我们提供了理解动态世界的精确语言;而现代机器人系统与 LLM 则试图在可推理性与鲁棒性上寻求突破。未来的智能体很可能不是单一范式的胜利,而是多层架构的协同:底层是连续的传感器‑控制器环路,中层是符号化的状态管理与逻辑推理,顶层是自然语言交互与常识理解。本章的形式化工具,正是连接这些层次不可或缺的桥梁。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐



所有评论(0)