《人工智能现代方法(第4版)》 第9章 一阶逻辑中的推断 学习笔记

🎯 本章要解决什么?从"知道事实"到"推出结论"

想象你有一个装满知识的"逻辑宝箱":

复制代码
宝箱里有:
1. 所有人都会死
2. 苏格拉底是人

问题 :怎么自动得出"苏格拉底会死"?

这就是推断(Inference)------从已知逻辑语句推导出新语句的过程。

本章核心:一阶逻辑的推断比命题逻辑复杂得多,因为要处理:

  • 变量(x, y, z...)
  • 量词(∀, ∃)
  • 函数(父亲(x), 加(2,3))

一、热身:命题推断 vs 一阶推断

📊 直观对比

推断类型 例子 复杂度 生活比喻
命题推断 P→Q, P ⊢ Q 相对简单 查菜谱做菜:按步骤来就行
一阶推断 ∀x(P(x)→Q(x)), P(a) ⊢ Q(a) 复杂得多 破案推理:要匹配线索、找嫌疑人

🔧 关键挑战:变量和量词

复制代码
已知:∀x (猫(x) → 可爱(x))
      猫(小花)
问:可爱(小花)?

步骤:
1. 从∀x (猫(x)→可爱(x)),可以推出对**任何具体对象**都成立
2. 用"小花"替换x:猫(小花)→可爱(小花)
3. 结合猫(小花),得到可爱(小花)

这个过程叫:全称实例化(Universal Instantiation)


二、约简为命题推断:把"一阶问题"降级

🎯 核心思想

既然命题推断算法(如归结)已经很成熟,能不能: 把一阶逻辑问题转换成命题逻辑问题,然后用现成工具解决?

📝 转换步骤

1. 去掉量词(全称实例化)
复制代码
原知识库:
∀x (猫(x) → 哺乳动物(x))
猫(小花)
猫(小白)

转换后:
猫(小花) → 哺乳动物(小花)
猫(小白) → 哺乳动物(小白)
猫(小花)
猫(小白)

问题:如果论域无限(如所有整数),会生成无限多语句!

2. 函数项的处理更麻烦
复制代码
原:∀x (加(x,0)=x)
论域:所有自然数 {0,1,2,3,...}

实例化:
加(0,0)=0
加(1,0)=1
加(2,0)=2
...
无限!
3. 存在量词∃的挑战
复制代码
原:∃x (猫(x) ∧ 黑(x))
不能简单实例化为:猫(A) ∧ 黑(A)
因为不知道A具体是谁!

需要引入**新常量**(Skolem常量):
猫(Sk1) ∧ 黑(Sk1)
Sk1代表"那个存在的黑猫"

⚠️ 约简法的局限性

复制代码
优点:可以利用成熟的命题逻辑算法
缺点:
1. 可能生成无限多命题(论域无限时)
2. 效率低下(生成太多实例)
3. 存在量词需要特殊处理

所以:需要专门为一阶逻辑设计的推断算法!

三、合一:一阶推断的"匹配引擎"

🤔 问题场景

复制代码
已知规则:∀x (猫(x) → 可爱(x))
已知事实:猫(小花)
目标:证明可爱(小花)

我们需要把规则中的x和事实中的"小花"匹配起来

🔍 什么是合一(Unification)?

合一 :找到变量的替换,使两个逻辑表达式变得相同

例子1:简单合一
复制代码
表达式1:猫(x)
表达式2:猫(小花)

替换:{x/小花}
结果:猫(小花) = 猫(小花) ✓
例子2:多变量合一
复制代码
表达式1:父亲(x,y)
表达式2:父亲(张三,z)

替换:{x/张三, y/z}
或:{x/张三, z/y}
结果:父亲(张三,y) = 父亲(张三,z)(y和z都代表同一个未知)
例子3:函数项合一
复制代码
表达式1:父亲(父亲(x))
表达式2:父亲(y)

替换:{y/父亲(x)}
结果:父亲(父亲(x)) = 父亲(父亲(x)) ✓

❌ 不能合一的情况

复制代码
1. 常量冲突:
   猫(小花) vs 猫(小白) → 不能合一(小花≠小白)

2. 出现检查(Occurs Check):
   x vs 父亲(x) → 不能合一(x不能等于包含x的表达式)
   否则会出现:x = 父亲(x) = 父亲(父亲(x)) = ... 无限循环!

📋 合一算法(伪代码版)

复制代码
function 合一(表达式1, 表达式2, 替换集):
    if 替换集包含冲突: return 失败
    if 表达式1 == 表达式2: return 替换集
    
    if 表达式1是变量:
        return 合一变量(表达式1, 表达式2, 替换集)
    if 表达式2是变量:
        return 合一变量(表达式2, 表达式1, 替换集)
    
    if 表达式1和表达式2都是复合项:
        return 合一(表达式1的各个部分, 表达式2的各个部分, 替换集)
    
    return 失败

四、前向链接:从已知事实"向前推"

🚀 工作方式

前向链接 :像数据驱动的推理,不断用规则推出新事实,直到推出目标或无法再推。

生活比喻:破案时收集线索
复制代码
已知线索(事实):
1. 现场有猫毛
2. 邻居听到猫叫

规则:
如果有猫毛→可能有猫
如果听到猫叫→可能有猫

推出:可能有猫(新事实)
再用新规则:如果有猫→调查宠物店记录...

📝 算法步骤

复制代码
1. 初始化:所有已知事实放入"已证事实集"
2. 循环:
   a. 遍历所有规则
   b. 对每条规则:如果前提都能合一匹配到已证事实
   c. 应用合一得到的替换,推出结论(新事实)
   d. 新事实加入已证事实集
3. 直到:推出目标事实,或没有新事实产生

🌰 具体例子:家族关系

复制代码
已知事实:
父母(张三, 李四)
父母(张三, 王五)
男性(张三)
女性(李四)
男性(王五)

规则:
1. ∀x∀y (父母(x,y) ∧ 男性(x) → 父亲(x,y))
2. ∀x∀y (父母(x,y) ∧ 女性(x) → 母亲(x,y))
3. ∀x∀y (父亲(x,y) → 子女(y,x))

前向链接过程:
步骤1:用规则1 + 事实父母(张三,李四)+男性(张三)
       → 父亲(张三,李四)(新事实)
步骤2:同理 → 父亲(张三,王五)
步骤3:用规则3 + 父亲(张三,李四)
       → 子女(李四,张三)
步骤4:同理 → 子女(王五,张三)
...

⚡ 高效前向链接的技巧

1. 索引化存储
复制代码
不要每次遍历所有事实!
建立索引:
谓词"父母" → [父母(张三,李四), 父母(张三,王五)...]
谓词"男性" → [男性(张三), 男性(王五)...]
2. 增量更新
复制代码
新事实产生时,只检查相关规则
而不是每次重新检查所有规则
3. 确定子句(Definite Clause)限制
复制代码
规则必须是这种形式:
P₁ ∧ P₂ ∧ ... ∧ Pₙ → Q
其中Q是单个原子(不能是¬Q或P∨Q)

好处:推出的事实总是确定的(真/假)

✅ 前向链接适合的场景

  1. 需要推出所有可能结论(如监控系统)
  2. 数据不断到达(如传感器数据流)
  3. 规则前提都是具体事实(没有"不存在"这种否定前提)

五、反向链接:从目标"向后找"

🎯 工作方式

反向链接 :像目标驱动的推理,从目标出发,找能推出它的规则,再递归证明规则的前提。

生活比喻:医生诊断
复制代码
目标:证明病人得流感
找规则:发烧∧咳嗽∧流鼻涕→流感
子目标1:证明发烧
子目标2:证明咳嗽
子目标3:证明流鼻涕

📝 算法步骤(递归版)

复制代码
function 反向链接(目标, 知识库):
    if 目标在已证事实中: return True
    if 目标已被标记为失败: return False
    
    标记目标为正在证明(防循环)
    
    对每条能推出目标的规则:
        对规则中的每个前提:
            if not 反向链接(前提, 知识库):
                跳出,试下一条规则
        所有前提都成立 → 目标得证,return True
    
    标记目标为失败
    return False

🌰 具体例子:证明"李四是张三的子女"

复制代码
知识库:
事实:父母(张三,李四)
规则:∀x∀y (父母(y,x) → 子女(x,y))

目标:子女(李四,张三)

反向链接过程:
1. 目标:子女(李四,张三)
2. 匹配规则:父母(张三,李四) → 子女(李四,张三)
   (合一:{x/李四, y/张三})
3. 新子目标:父母(张三,李四)
4. 在事实中找到!✓
5. 目标得证 ✓

💻 逻辑编程:Prolog语言

Prolog就是基于反向链接的逻辑编程语言:

复制代码
% 知识库(规则和事实)
父母(张三, 李四).
子女(X, Y) :- 父母(Y, X).  % 规则:如果父母(Y,X)则子女(X,Y)

% 查询
?- 子女(李四, 张三).  % Prolog回答:Yes

⚠️ 反向链接的陷阱

1. 冗余推断
复制代码
规则1:A → B
规则2:B → A
查询:A?

会无限循环:A→需要B→需要A→需要B...
2. 无限循环
复制代码
规则:祖先(X,Y) :- 父母(X,Z), 祖先(Z,Y).
事实:父母(张三,李四), 父母(李四,张三)  % 循环关系!

查询祖先(张三,王五)可能无限递归
3. Prolog的数据库语义

Prolog使用封闭世界假设

  • 知识库没说为真 → 就认为假
  • 使用深度优先搜索(可能陷入死胡同)
  • 使用回溯(失败时尝试其他选择)

🔗 约束逻辑编程

复制代码
传统反向链接:值在推理过程中确定
约束逻辑编程:先建立约束关系,最后一起求解

例:解方程
传统:X=1? 不行→X=2? 不行→X=3?...
约束:X>0, X<10, X是偶数 → 直接得到{2,4,6,8}

六、归结:一阶逻辑的"终极证明武器"

🎯 归结法回顾(命题逻辑版)

复制代码
已知:P ∨ Q
      ¬P ∨ R
归结:Q ∨ R  (消去P和¬P)

思想:如果P成立则R必须成立,如果P不成立则Q必须成立
所以要么Q成立,要么R成立

🔥 一阶逻辑归结:加入合一

复制代码
已知:猫(x) ∨ 黑(x)
      ¬猫(小花)
不能直接归结!因为猫(x)和¬猫(小花)不完全相反

步骤:
1. 合一:{x/小花},使猫(x)=猫(小花)
2. 应用替换:猫(小花) ∨ 黑(小花)
3. 与¬猫(小花)归结:黑(小花)

📋 一阶归结算法步骤

复制代码
1. 将知识库和目标否定转化为合取范式(CNF)
2. 不断归结,直到:
   a. 推出空子句(□)→ 原目标成立
   b. 无法再归结 → 原目标不成立

🌰 归结证明示例(简化版)

复制代码
要证明:苏格拉底会死

知识库:
1. ∀x (人(x) → 会死(x))
2. 人(苏格拉底)

目标:会死(苏格拉底)

步骤:
1. 将知识库转化为CNF:
   (1) ¬人(x) ∨ 会死(x)
   (2) 人(苏格拉底)
   
2. 否定目标:¬会死(苏格拉底)

3. 归结:
   (a) ¬人(x) ∨ 会死(x)
   (b) 人(苏格拉底)
   (c) ¬会死(苏格拉底)
   
   用合一{x/苏格拉底}:
   (a)变成:¬人(苏格拉底) ∨ 会死(苏格拉底)
   
   与(b)归结:会死(苏格拉底)
   
   与(c)归结:□(空子句,矛盾!)
   
4. 矛盾说明原目标成立:苏格拉底会死 ✓

📊 图9-10解析:证明"韦斯特有罪"

复制代码
知识库包含:
American(x) ∨ ¬Weapon(y) ∨ ¬Sells(x,y,z) ∨ ¬Hostile(z) ∨ Criminal(x)
¬Criminal(West)
American(West)
Missile(x) ∨ Weapon(x)
...
(图中展示归结步骤,每一步消去一对互补文字)

最终推出空子句,证明Criminal(West)成立

🎯 归结策略:提高效率的技巧

1. 单元归结
复制代码
优先使用单文字子句归结
例:有子句P和¬P∨Q,先归结这两个
2. 输入归结
复制代码
每次归结至少有一个输入是原始子句(不是中间结果)
避免生成太多中间子句
3. 线性归结
复制代码
保持线性推导链,每个新子句都和前一个子句归结
4. 集支持归结
复制代码
优先归结涉及目标否定的子句
更快导向矛盾

✅ 归结的完备性

好消息:一阶归结是完备的!

  • 如果语句逻辑蕴含结论,归结一定能证明
  • 如果无法证明,要么结论不成立,要么一直运行下去(半可判定)

坏消息:可能非常慢,甚至无限循环(一阶逻辑不可判定)


七、等词的处理:说"两个东西相同"

🤔 等词(=)的特殊性

复制代码
等词不是普通谓词!
普通谓词:父亲(张三,李四) 只是陈述事实
等词:父亲(小明)=张三 表示"是同一个对象"

🔧 等词公理

要在归结中使用等词,需要添加公理:

复制代码
1. 自反性:∀x (x=x)
2. 对称性:∀x∀y (x=y → y=x)
3. 传递性:∀x∀y∀z (x=y ∧ y=z → x=z)
4. 替换性:∀x∀y (x=y → (P(x)↔P(y))) 对所有谓词P

⚡ 等词归结的特殊规则

复制代码
参数化归结:允许用等词进行替换
例:已知P(a)和a=b,可以推出P(b)

八、实际应用与选择指南

📊 算法选择矩阵

场景 推荐算法 理由
实时监控(如入侵检测) 前向链接 数据驱动,新事实立即触发推理
问答系统(如"谁是谁的父亲") 反向链接 目标驱动,只求所需答案
定理证明(数学证明) 归结 完备,能处理复杂逻辑
数据库查询 反向链接+索引 类似SQL查询优化
有函数和等词 归结+等词处理 其他算法处理等词困难

⚡ 性能优化技巧

  1. 索引化:为每个谓词建索引,快速查找
  2. 子句排序:简单子句先处理,复杂子句后处理
  3. 缓存结果:记住已证明的目标,避免重复计算
  4. 启发式:优先处理涉及常量的子句,减少变量匹配

⚠️ 一阶推断的现实限制

复制代码
理论很美好,现实很骨感:
1. **计算复杂度**:一阶逻辑推断是半可判定的(可能永远算不完)
2. **知识工程难度**:把现实知识写成逻辑规则很难
3. **不确定性**:现实世界充满"可能"、"大概"
4. **规模问题**:知识库太大会组合爆炸

所以实际系统常:
- 使用受限子集(如确定子句)
- 结合概率(下一部分内容)
- 使用专门领域推理机

🧠 第9章思维升华

从"静态知识"到"动态推理"

  • 知识表示 (第8章):建立逻辑世界模型
  • 逻辑推断 (本章):让模型运转起来,产生新知识

推理的哲学

复制代码
前向链接:经验主义------从观察出发,归纳规律
反向链接:理性主义------从假设出发,验证理论
归结法:归谬法------假设结论错,推出矛盾

实际系统设计启示

复制代码
没有"最好"的算法,只有"最适合"的算法:
- 专家系统常用反向链接(Prolog风格)
- 业务规则引擎常用前向链接(数据触发)
- 数学证明器常用归结(追求完备性)
- 实际系统常混合使用

连接后续章节

复制代码
本章:确定性逻辑推理
第13-14章:概率推理(处理不确定性)
第10章:知识表示扩展(处理默认、例外)
现实AI系统 = 逻辑推理 + 概率 + 学习 + 搜索

最后一句大实话
一阶逻辑推断就像"逻辑计算器"------给定规则和事实,能算出新结论。
但现实问题往往没有明确规则,或规则互相矛盾,或信息不全。
所以AI需要更灵活的工具:概率推理、机器学习、常识推理...

相关推荐
阿杰学AI1 小时前
AI核心知识37——大语言模型之ASI(简洁且通俗易懂版)
人工智能·ai·语言模型·自然语言处理·agi·asi·超人工智能
喜欢吃燃面1 小时前
算法竞赛之排序算法
c++·学习·算法
jtymyxmz1 小时前
《Maya 2024 超级学习手册》3.4.5 实例:制作沙发模型
学习·maya
nix.gnehc1 小时前
Agentic AI
人工智能·agentic ai
秋深枫叶红1 小时前
嵌入式第三十篇——数据结构——哈希表
数据结构·学习·算法·哈希算法
xqlily1 小时前
PyTorch:深度学习研究的核心引擎(上)
人工智能·pytorch·深度学习
虎头金猫1 小时前
从杂乱到有序,Paperless-ngx 加个cpolar更好用
linux·运维·人工智能·docker·开源·beautifulsoup·pandas
roman_日积跬步-终至千里1 小时前
【计算机视觉(6)】边缘与直线检测基础篇:从Canny到Hough变换
人工智能·计算机视觉
Keep__Fighting1 小时前
【机器学习:决策树】
人工智能·算法·决策树·机器学习·scikit-learn