First-Order Logic(FOL, 一阶逻辑)
从命题逻辑到一阶逻辑
命题逻辑的局限性
命题逻辑在处理具有重复性结构或一般性规律的问题时,显得非常臃肿且低效:
- 命题逻辑很难简洁地描述某个对象具有某种性质(属性局限)
- 命题逻辑在描述物体间的相对位置(如在旁边、在上方)时非常繁琐(关系局限)
- 命题逻辑无法用一句话表达“每一个”,比如无法表示“每一个坑都会导致邻格产生微风”这样的模式(通用模式上的局限)
为了解决这些问题吗,人工智能引入了一阶逻辑,它在命题逻辑(如与 \(\wedge\)、或 \(\vee\)、非 \(\neg\)、蕴含 \(\rightarrow\))的基础上,额外增加了以下内容:
- 对象(Objects): 如方格 \(x, y\)。
- 谓词(Predicates): 如 \(Pit(x)\) 表示 \(x\) 是坑,\(Breeze(y)\) 表示 \(y\) 有微风。
- 量词(Quantifiers): 比如使用 全称量词 (\(\forall\)) ,一句话就能顶替成千上万条命题逻辑公式:
(对于任意两个相邻的方格 \(s_1\) 和 \(s_2\),如果 \(s_1\) 有坑,那么 \(s_2\) 必有微风。)
一阶逻辑示例

在上图中,蓝色的是对象(Objects),也称为常量符号(Constant Symbols),它们代表现实中具体的名词或实体,比如:Square1, Me, Boston等。
红色的对象是谓词(Predicates),用来描述对象的属性,或者多个对象之间的关系,比如:
- Sqaure1有微风
- 我开车从波士顿去Wilmington
黑色的是连接词(Connectives),这些是命题逻辑中就有的老工具,用来把几个短小的判断连接成一个复杂的长句子。
一阶逻辑中的 句子 ,就是把“谓词”应用到“对象”上,然后再用连接词拼起来。
- 示例 1: \(Cute(Animal) \rightarrow (Kitty(Animal) \vee Puppy(Animal))\)
- 翻译: 如果一个动物很可爱,那么它要么是小猫,要么是小狗。
- 示例 2: \(Succeeds(You) \leftrightarrow Practices(You)\)
- 翻译: 你能成功,当且仅当你不断练习。
“量词”(Quantifiers)在这几张图的示例中并没有出现。 量词是一阶逻辑引入的新用法,专门用来表达数量范围。最常见的有:
- 全称量词 \(\forall\)**** :表示“所有/每一个”。
- 存在量词 \(\exists\)**** :表示“存在/至少有一个”。
在严格的一阶逻辑格式里,所有的谓词都是写在最前面的,这叫 前缀表示法(Prefix Notation) 。比如要表达“2 小于 3”,严格的写法必须是把“小于”当成一个谓词关系:
- 严格写法:
LessThan(2, 3)
但是,对于数学家和人类来说,这种写法太反直觉了!所以为了“书写习惯上的便利(notational ease)”,对于那些我们非常熟悉的数学运算符,一阶逻辑允许我们把符号直接写在两个对象中间,这也就是 中缀表示法(Infix Notation) 。
- 简写为: \(2 < 3\)
这就像在 Python 编程里,虽然底层是调用了对象的内置方法 (2).__lt__(3),但你写代码时依然会写成 2 < 3 一样。逻辑学也懂得通过这种“语法糖”来让表达式更具可读性。
这里值得注意的一点是,在一阶逻辑中,= 不是简单的数学运算符号,它是系统自带的、专门用来描述关系的 谓词 。它的唯一工作就是判断: 两个“对象(Objects)”在现实世界中是否完全等同,指的是同一个东西 。
示例:
- \(Venus = MorningStar\) (金星 = 启明星)
- \(MountEverest = Sagarmatha\) (珠穆朗玛峰 = 萨加玛塔峰,后者是珠峰的尼泊尔语名字)
这两个例子完美展示了 = 的作用:即使我们在逻辑表达式中使用了不同的“常量符号”(名字),但只要它们指向同一个物理实体,这个等式谓词就会返回 True。铁律:"Can't have predicates equal to each other!"(不能让谓词彼此相等!)
- ❌ 错误写法: \(Succeeds(You) = Practices(You)\)
- ✅ 正确写法: \(Succeeds(You) \leftrightarrow Practices(You)\)
Succeeds(You) 作为一个谓词应用在对象上,它的结果是一个 命题(True 或 False) ,它不再是一个“对象”了。而 = 号只能用来对比对象。用程序员的话说,这叫“类型不匹配(Type Mismatch)”。既然左右两边都已经成了命题(True/False),我们就必须动用上一层级的“胶水”—— 标准逻辑连接词 (这里的双向箭头代表“当且仅当”)来连接它们。
逻辑编程
一阶逻辑(FOL)早在 19世纪末(现代计算机发明之前很久)就被数学家和哲学家发明出来了。当时发明的目的根本不是为了写代码,而是为了 用严谨的符号来准确描述复杂的数学定理和人类自然语言 ,因为早期的命题逻辑表达能力太苍白了。
虽然不是为了电脑发明的,但现代计算机科学、数据库理论(如 SQL 的关系代数)以及编程语言的设计, 非常深刻地受到了数理逻辑的启发 。
在现在的软件开发中:
- Objects(对象): 演变成了编程里的 变量(Variables) 、 数据结构 ,或者是面向对象编程(OOP)中的 实例(Instances) ,它们被储存在电脑的内存中。就像前面幻灯片里的
Ziggy。 - Predicates(谓词): 完美对应了编程语言中那些 返回布尔值(Boolean:
True或False)的函数(Functions)或方法(Methods) 。就像Cute()这个函数接收了Ziggy作为一个参数,经过运算后返回了True。
上述理念成为早期人工智能(特别是在专家系统时代)的核心基石,并由此催生了一个重要的编程流派—— 逻辑编程(Logic Programming) 。有一门非常经典的 AI 编程语言叫 Prolog (Programming in Logic),它就是直接把一阶逻辑搬到了电脑上。在这个语言里,你不需要写传统的 for 循环或 if/else,你只需要把“对象”和“谓词(规则)”输入进去,电脑底层的逻辑推理引擎就会自己去推导并回答你的问题。
函数
谓词最终的计算结果是命题(真或假),而函数的计算结果是一个具体的 对象 。
HomeState(Me)并不表示“我的老家是特拉华州吗?(True/False)”,而是直接映射并返回了Delaware(特拉华州)这个对象。RightArmOf(Robot)接收了“机器人”这个对象,返回了RobotRightArm(机器人的右臂)这个新对象。
从语法格式上看,函数和谓词长得一模一样,根本无法区分(都是首字母大写加上括号里的参数)。在实际书写时,必须要靠语境或者提前定义来区分它们。
因为函数和谓词长得太像,所以初学者极容易把对象(Objects)和命题(Propositions,即 True/False)搞混。最后一张幻灯片明确指出了两种最常见的“语法报错”:
❌ 错误 1:不能用连接词去连接对象
- 错例: \(Venus \rightarrow TheSun\) (金星 \(\rightarrow\) 太阳)
- 解析: \(\rightarrow\) 是逻辑连接词,它两边必须是能判断真假的命题(比如“天下雨 \(\rightarrow\) 地会湿”)。金星和太阳只是两个像石头一样的死物(对象),它们之间不存在逻辑推理关系。
❌ 错误 2:不能把命题当成参数传给函数
- 错例: \(StarOf(IsRed(Sun) \wedge IsGreen(Mars))\)
- 解析: 括号里的 \(IsRed(Sun) \wedge IsGreen(Mars)\) 是一个谓词组合,它的结果是一个 布尔值(True/False) 。但是函数
StarOf()就像一个榨汁机,它需要塞进去一个“水果”(对象),你塞进去一个“对/错”的概念,逻辑系统当场崩溃。
Quantifiers
Existential Quantifiers
存在量词(Existential Quantifier, \(\exists\))解决的核心问题是:我们不需要穷举世界上的所有东西,只要能找到至少一个满足条件的对象,整个逻辑判断就成立。
其本质上相当于:
# 伪代码理解 ∃x. formula
for x in all_objects_in_the_world:
if formula(x) == True:
return True # 只要找到一个,立刻判定为真!
return False
示例1:\(\exists x. \text{Even}(x) \wedge \text{Prime}(x)\)
存在一个数 \(x\),它既是偶数,又是素数。逻辑引擎会在数字海洋里寻找。当它把 \(x=2\) 代入进去,发现 \(\text{Even}(2) \wedge \text{Prime}(2)\) 是 True。任务完成,整个命题为 True!
示例2:\(\exists x. \text{TallerThan}(x, me) \wedge \text{HeavierThan}(x, me)\)
世界上存在某个人 \(x\),他/她比我高,并且比我重。这个句子极其强大。在以前的命题逻辑里,你必须穷举全世界 80 亿人(姚明比我高且重 \(\vee\) 泰森比我高且重 \(\vee \dots\))。但在使用了一阶逻辑和量词后,只需短短一行符号就能完美表达这个宏大的概念。
Universal Quantifiers
全称量词 (Universal Quantifier) 用来表达“ 对于所有的... ”或“ 每一个... ”这样的绝对概念。它通常用倒写的字母 A 来表示,即 \(\forall\)(代表英文单词 "All")。
基本格式:
\(\forall x. \text{some-formula}\)
这句话的意思是,在你所讨论的范围(定义域)内,对于每一个被选中的 \(x\),当你把 \(x\) 代入到后面的公式 some-formula 中时,该公式的结果都必须为 真 (True) 。只要有一个 \(x\) 让公式为假,那么整个全称命题就为假。
示例1:\(\forall p. \text{Puppy}(p) \rightarrow \text{Cute}(p)\)
对于每一个个体 \(p\),如果 \(p\) 是一只小狗 (Puppy),那么 \(\rightarrow\) (推出) \(p\) 是可爱的 (Cute)。即“所有的小狗都是可爱的。”
示例2:\(\forall x. \text{Happy}(x) \lor \text{Sad}(x)\)
对于每一个个体 \(x\),\(x\) 要么是快乐的 (Happy),\(\lor\) (或者) \(x\) 是悲伤的 (Sad)。即“每个人要么开心,要么难过。”
在编程中,全称量词 \(\forall\) 完美对应于对一个集合进行遍历的 for 循环 ,并且常常结合一个提前返回 (Early Return) 的逻辑。为了证明 \(\forall x. P(x)\) 为真,程序需要检查集合中的所有元素是否都满足条件 \(P(x)\)。如果发现哪怕 一个反例 (即不满足条件),就会立刻判定为假 (False)。
// 假设 domain 是我们要检查的所有 x 的集合
function evaluate_universal_quantifier(domain):
for x in domain:
// 如果把 x 代入公式计算结果为假 (找到了反例)
if some_formula(x) == False:
return False // 只要有一个不满足,整个全称命题就是假的
// 循环结束,没有找到任何反例
return True
在许多现代编程语言中,全称量词的逻辑被封装成了现成的高阶函数:
# 对集合中的每一个 x,计算 some_formula(x),如果全都为真,则返回 True
result = all(some_formula(x) for x in domain)
全称量词的本质就是一个要求“零容错”的遍历检查器——必须全员通过,才算成功。
Vacuous Truth
这里有一个值得注意的特例,叫做“空泛为真 (Vacuous Truth)”,这是逻辑学中的一个非常有趣的特例。
比如说,如果我说:“我车库里所有的喷火龙都是粉红色的。”——因为我的车库里根本没有喷火龙(空集),你永远没法牵出一条绿色的喷火龙来打我的脸。所以在严格的逻辑意义上,我这句话不能算错(即为真)。
在逻辑学中,对于全称量词(“所有的...”),系统的默认态度是“无罪推定”——也就是默认它为 True,除非你能证明它是 False。如何证明它是 False? 你必须拿出一个 反例 。
从编程角度来看,计算机必须这样设计,因为如果空集不返回 True,程序的世界会大乱。我们可以看一个实际的软件工程例子。假设你写了一个安全监控系统,你需要检查系统日志中的所有报错是否都已经被修复。你的伪代码可能是这样的:
def check_system_safe(error_logs):
# 默认系统是安全的
is_safe = True
for error in error_logs:
if error.is_fixed == False:
is_safe = False # 找到了未修复的错误,警报!
break
return is_safe
现在,想象一个刚刚启动、运行完美、没有任何报错的系统。此时 error_logs 是一个空数组 []。
- 如果对空集做全称检查返回
False:你的程序会认为“并不是所有的错误都被修复了”,系统会疯狂拉响警报,但实际上系统健康得很,根本没有错误! - 如果对空集做全称检查返回
True:for循环直接跳过,程序返回is_safe = True。系统判断:“很好,现存的所有 0 个错误都处于已修复状态”,一切正常。
在编程和数学中,“所有的 X 都是 Y” 并不意味着“X 存在”。它的确切含义是:“ 只要你找不出一个不是 Y 的 X,这句话就算对。 ” 既然没有 X,你当然找不出,所以算对。
对于任意的 \(x\),如果 \(x\) 满足条件 P,那么 \(x\) 就满足条件 Q。数学符号表示为:\(\forall x. P(x) \rightarrow Q(x)\)。这里的箭头 \(\rightarrow\) 就是“蕴含”符号。理解空泛为真的终极秘诀,就藏在 \(P \rightarrow Q\) 的真值表里。在逻辑学中,一个条件语句 \(P \rightarrow Q\) 只有在一种情况下是假的: 前提 P 为真,但结论 Q 为假 。其他所有情况,它都被定义为真。
| 前提 P | 结论 Q | P→Q (如果 P 那么 Q) | 说明 |
|---|---|---|---|
| True(真) | True(真) | True (真) | 顺理成章:下雨了 (\(P\)),地湿了 (\(Q\))。没毛病。 |
| True(真) | False(假) | False (假) | 唯一的反例 :下雨了 (\(P\)),地没湿 (\(Q\))。这是撒谎! |
| False (假) | True(真) | True (真) | 没下雨 (\(P\)),但地湿了 (\(Q\),可能是洒水车)。原话“如果下雨地就湿”没算错。 |
| False (假) | False(假) | True (真) | 没下雨 (\(P\)),地也没湿 (\(Q\))。原话没算错。 |
在逻辑学中,如果前提(P)本身就是假的/不存在的,那么基于这个前提做出的任何推论(Q),在逻辑上都被认为是“不假”的,即算作 True。
这就是为什么在计算机和离散数学中,对一个空集进行 \(\forall\) (全称)判断,结果永远是 True。因为你永远无法触发真值表里唯一能让它变成 False 的第二行(\(P\) 为真,但 \(Q\) 为假)。
Combining Quantifiers
量词的德摩根定律 (DeMorgan's Law for Quantifiers)
核心法则 :当否定符号(\(\neg\))穿过量词时,量词必须翻转(\(\forall\) 变成 \(\exists\),\(\exists\) 变成 \(\forall\)),同时后面的谓词也需要取反。
1、否定“全称量词” (Not All \(\rightarrow\) Exists Not)
- 公式 :\(\neg \forall x. P(x) \equiv \exists x. \neg P(x)\)
- 逻辑理解 :要推翻“所有事物都满足 \(P\)”,只需“找到至少一个不满足 \(P\) 的反例”。
- 语义示例 :
- 原句:\(\neg\) (所有的人都是好人)
- 等价:\(\exists\) (存在一个人不是好人)
2、否定“存在量词” (Not Exists \(\rightarrow\) All Not)
- 公式 :\(\neg \exists x. P(x) \equiv \forall x. \neg P(x)\)
- 逻辑理解 :要推翻“存在事物满足 \(P\)”,必须证明“所有事物都不满足 \(P\)”。
- 语义示例 :
- 原句:\(\neg\) (存在一个好人)
- 等价:\(\forall\) (所有人都不是好人)
多重量词的嵌套与顺序 (Ordering Quantifiers)
核心法则 :同类量词可随意交换位置,异类量词交换会彻底改变命题含义。
1、相同量词:顺序可交换 (Same Quantifiers)
连续出现的同种量词,位置先后不影响逻辑真值。
- 全称量词嵌套 :\(\forall x \forall y: P(x,y) \equiv \forall y \forall x: P(x,y)\)
- 存在量词嵌套 :\(\exists x \exists y: P(x,y) \equiv \exists y \exists x: P(x,y)\)
2、不同量词:顺序不可交换 (Different Quantifiers)
当 \(\forall\) 和 \(\exists\) 交替出现时,排在后面的量词依赖于排在前面的量词(具有局部作用域)。
- 公式 :\(\forall x \exists y: \text{Formula} \not\equiv \exists y \forall x: \text{Formula}\)
- 经典辨析 (设 \(P(x,y)\) 为 “\(x\) 喜欢 \(y\)”):
- 情况 A (\(\forall x \exists y\)) :对于每一个人 \(x\),都存在一个他喜欢的人 \(y\)。
- 特点 :这里的 \(y\) 依赖于 \(x\)(每个人喜欢的人可以各不相同)。
- 情况 B (\(\exists y \forall x\)) :存在某一个特定的人 \(y\),所有的人 \(x\) 都喜欢他。
- 特点 :这里的 \(y\) 是全局独立且唯一的(所有人都喜欢同一个“万人迷”)。
FOL翻译
黄金法则
在将自然语言转化为逻辑公式时,掌握两种最基础的模式是关键。所有的复杂长句几乎都是由它们构建而成的:
- “存在/一些...是...” (Some A are B)
- “所有/凡是...都是...” (All A are B)
对于第一种“存在/一些...是...” (Some A are B)的情况,我们使用\(\exists\)配 \(\land\),逻辑公式示例:\(\exists x. mushroom(x) \land purple(x)\),即存在一个事物 \(x\),它既是蘑菇,并且是紫色的。
对于第二种“所有/凡是...都是...” (All A are B)的情况,我们使用\(\forall\)配 \(\rightarrow\),逻辑公式示例:\(\forall x \forall y. [gardener(x) \land mushroom(y) \land purple(y)] \rightarrow allergicTo(x, y)\),即对于任意 \(x\) 和 \(y\),如果满足前提条件,那么得出后续结论。
利用逻辑等价公式,可以对多条件的嵌套蕴含式进行变形以简化阅读:
- 核心法则 :\(A \rightarrow (B \rightarrow C) \equiv (A \land B) \rightarrow C\)
- 应用实例 :将上述“所有园丁...”的公式转换为两层蕴含形式:
这里要注意一个非常容易遇到的坑:防范Vacuous Truth。
在存在量词 (\(\exists\)) 的大前提下,绝不能轻易使用蕴含 (\(\rightarrow\))。
案例分析 :“有些园丁对所有的蘑菇都过敏” (Some gardeners are allergic to every mushroom)
❌ 错误翻译示范
错误原因解析 (Ziggy 效应) :
- 在形式逻辑中,蕴含式 \(False \rightarrow \text{任何结论}\) 的结果永远为 True 。
- 如果代入一个非园丁实体(例如知识库里的一只狗 Ziggy),则前提 \(gardener(Ziggy)\) 为 False。
- 这会导致 \((False \land mushroom(y))\) 整体变为 False。
- 最终导致 \(False \rightarrow allergicTo(x, y)\) 强行输出 True。这荒谬地使得“只要世界里存在一条狗”,这句关于“园丁”的论断就成了真理。
✅ 正确修复版本
正确原因解析 :
- 使用逻辑与 (\(\land\)) 严格“锁定”主体身份。
- 句法结构变为:存在一个事物 \(x\),它必须是园丁,并且满足后续过敏条件。
- 若再次代入非园丁实体(如狗 Ziggy),\(gardener(Ziggy)\) 为 False,则 \(False \land \text{后续条件}\) 会直接得出 False ,成功拦截了逻辑漏洞。
黄金法则总结:
- 表达“所有”时:\(\forall\) 永远配 \(\rightarrow\),即“只要是...,就必定是...”
- 表达“存在”时:\(\exists\) 永远配 \(\land\),即“真的有这么个东西,它既是...又是...”
这是因为表达所有时,我们是在立规矩。当你说“所有园丁都过敏”时,你不是在说全世界所有的东西都是园丁(如果用 \(\land\) 就变成这个荒谬的意思了:所有的东西既是园丁又过敏)。你其实是在加一个 过滤器 :“在这茫茫宇宙中,如果我抓到了一个园丁,那么他必定过敏。”蕴含号 (\(\rightarrow\)) 完美表达了这种“如果...那么...”的条件关系。
而在表达存在时,我们实则是在找证据 (抓现行)。当你说“有些(存在)蘑菇是紫色的”时,你需要实实在在地找出一个具体的东西来证明。这个东西必须 同时满足两个条件 :它必须是个蘑菇,并且 (\(\land\)) 它必须是紫色的。绝对不能用 \(\rightarrow\)(如果...那么...),因为就像前面笔记里的“狗 (Ziggy)”一样,如果你用“存在一个东西,如果是蘑菇,那么是紫色的”,随便拉一条狗过来,因为它不是蘑菇,前提为假,整个句子反而变成真理了,这显然是在钻逻辑的空子。
再次总结:
- \(\forall\) + \(\rightarrow\)* = *“只要...” (设前提)
- \(\exists\) + \(\land\)* = *“既...又...” (抓现行)
案例1
“There is a country that borders both Iraq and Pakistan.” (存在一个国家,它既与伊拉克接壤,又与巴基斯坦接壤。)
我们看一下以下四个不同的FOL表达式:
- \((\exists c\ Country(c) \land Border(c, Iraq) \land Border(c, Pakistan))\)
- \((\exists c\ Country(c) \Rightarrow [Border(c, Iraq) \land Border(c, Pakistan)])\)
- \((\exists c\ Country(c)) \Rightarrow [Border(c, Iraq) \land Border(c, Pakistan)]\)
- \((\exists c\ Border(Country(c), Iraq \land Pakistan))\)
我们对每一个表达式进行“体检”,并把它归类到以下 3 种情况之一:
- 这个表达式完美且正确地翻译了英文原句。(选这个就不需要额外解释了)。
- 这个表达式在 语法上是无效的(Syntactically invalid) ,因此是一句毫无意义的废话。如果选这个,你需要解释 为什么语法错了 。
- 这个表达式在 语法上是有效的(Syntactically valid) ,但是它表达的 意思和英文原句不一样 。如果选这个,你需要解释 它犯了什么逻辑错误/实际表达了什么意思 。
在逻辑雪中,Syntactically Valid(语法有效 / 语法正确)的意思是符号的拼写、括号的闭合、连接词的用法完全符合一阶逻辑的“语法规则”。逻辑系统或计算机能读懂这句话。哪怕这句话在现实中是一句彻头彻尾的谎话,或者犯了逻辑谬误(比如“所有的猪都会飞”),只要格式对,它就是 Valid 的。能够计算出结果(True 或 False)的公式,就是语法有效的。
Syntactically Invalid(语法无效 / 语法错误)的意思是违反了基本的书写规则。比如乱加括号、把不该放在一起的符号强行拼凑。逻辑系统直接 报错死机 ,根本读不懂,更别提去判断真假了。就好比中文里的“我吃饭个被”,字都认识,但拼在一起毫无意义(Meaningless)。
我们一个一个来看:
表达式 1: (∃c Country(c) ∧ Border(c, Iraq) ∧ Border(c, Pakistan))
- 这个表达式表达的意思: 存在一个实体 \(c\),这个 \(c\) 是一个国家,并且 \(c\) 与伊拉克接壤,并且 \(c\) 与巴基斯坦接壤。
- 所属类别: 1. The expression correctly expresses the English sentence. (正确表达了英文原意)
- 原因解释: 它完美且毫无语法错误地应用了存在量词的“固定搭配”。当我们要表达“存在某物满足多个条件”时,必须使用存在量词 (\(\exists\)) 搭配逻辑与 (\(\land\)) 将所有限制条件串联起来。
表达式 2: (∃c Country(c) ⇒ [Border(c, Iraq) ∧ Border(c, Pakistan)])
- 这个表达式表达的意思: 存在一个实体 \(c\),如果这个 \(c\) 是一个国家,那么它与伊拉克和巴基斯坦接壤。
- 所属类别: 3. The expression is syntactically valid but does not express the meaning of the English sentence. (语法有效,但未表达原意)
- 原因解释:
这个表达式在符号拼写和连接上没有违反规则(所以语法 Valid),但它掉进了“空虚真 (Vacuous Truth)”的逻辑陷阱。因为使用了蕴含符号 (\(\Rightarrow\)),只要我们在这个世界里找到任何一个不是国家的实体(例如一块石头),那么前提
Country(石头)就是 False。在逻辑学中,“False 蕴含任何事物”的结果都是 True。因此,仅仅因为世界上存在一块石头,这句话就被判定为真了,这根本无法保证真的存在一个符合条件的“国家”。
表达式 3: (∃c Country(c)) ⇒ [Border(c, Iraq) ∧ Border(c, Pakistan)]
- 这个表达式表达的意思: 如果 (存在一个实体 \(c\),它是一个国家), 那么 (某个不知名的 \(c\) 与伊拉克和巴基斯坦接壤)。
- 所属类别: 2. The expression is syntactically invalid and therefore meaningless. (语法无效,因此无意义)
- 原因解释:
问题出在括号的位置上。左边的
(∃c Country(c))形成了一个完全闭合的作用域(Scope)。这意味着量词 \(\exists c\) 的管辖范围到这个括号就结束了。因此,右边中括号[Border(c...)]里面的 \(c\) 失去了量词的绑定,变成了一个“游离变量 (Free Variable)”。在一阶逻辑命题中,包含游离变量的句子是无法被计算真假的,属于严重的语法错误。 - 这句话如果强行翻译成人话,听起来会非常割裂,像是两个人各说各的: “如果(这个世界上存在某个国家),那么(一个来路不明的神秘物体 \(c\) 挨着伊拉克,并且这个神秘物体 \(c\) 挨着巴基斯坦)。”你会发现,后半句里的那个 \(c\) 显得极其突兀——我们根本不知道这个 \(c\) 是什么东西!
这个表达式3的致命错误在于 括号包裹的位置 ,导致了“变量未绑定(游离变量)”的语法错误。
- 第一步:看量词的管辖范围(作用域)
在一阶逻辑中,量词(比如 \(\exists c\))就像是一个“声明”,它只对紧紧跟在它后面的、被括号包起来的那部分起作用。
你看前半部分:
(∃c Country(c))。这里的右括号)直接把 \(\exists c\) 的管辖范围给“封死”了。在这个括号里面,\(c\) 代表一个国家,逻辑是自洽的。 - 第二步:看蕴含号(\(\Rightarrow\))后面的世界
过了蕴含号之后,进入了后半部分的方括号:
[Border(c, Iraq) ∧ Border(c, Pakistan)]。 这里面又出现了一个变量 \(c\)。但是! 因为前面的 \(\exists c\) 的作用域已经在那个右括号处结束了,所以后半部分的这个 \(c\) 和前面的 \(\exists c\) 没有任何关系 。 - 第三步:为什么判定为语法无效(无意义)? 在逻辑学中,后半部分的这个 \(c\) 被称为“游离变量(Free Variable)”或“自由变量”。 就好比你在解数学题,突然蹦出来一个公式 \(x + 2 = 5\),但整道题从头到尾都没告诉你 \(x\) 是什么。逻辑系统(或者计算机)读到后半句时会直接懵掉:“这个 \(c\) 到底是个常量?是个地名?还是个人名?” 因为无法确定它的身份,整个命题就无法判断真假,因此被判定为语法上无意义(Meaningless)。
表达式 4: (∃c Border(Country(c), Iraq ∧ Pakistan))
- 这个表达式表达的意思: (这句话翻译成人类语言是纯粹的胡言乱语):存在一个实体 \(c\),它是不是国家这件事,与“伊拉克并且巴基斯坦”这个东西接壤。
- 所属类别: 2. The expression is syntactically invalid and therefore meaningless. (语法无效,因此无意义)
- 原因解释:
这个表达式犯了严重的“类型不匹配 (Type Mismatch)”的语法错误。
- 谓词
Border(x, y)括号里要求填入的是具体的对象实体(比如变量或地名)。但Country(c)是一个会输出 True 或 False 的判断命题,不能作为实体参数塞进另一个谓词里。 - 逻辑与 (\(\land\)) 只能用来连接两个布尔类型的逻辑命题(比如 A 且 B)。
Iraq和Pakistan是对象常量,不能用逻辑符号直接把它们连起来。
- 谓词
案例2
目标句子 :“No region in South America borders any region in Europe.”(南美的任何地区都不与欧洲的任何地区接壤。)
表达式 1: (¬∃c, d In(c, SouthAmerica) ∧ In(d, Europe) ∧ Borders(c, d))
- 这个表达式表达的意思: 不存在(\(\neg\exists\))这样两个实体 \(c\) 和 \(d\):\(c\) 在南美,并且 \(d\) 在欧洲,并且 \(c\) 与 \(d\) 接壤。
- 所属类别: 1. The expression correctly expresses the English sentence. (正确表达了英文原意)
- 原因解释: 这是一个非常标准且聪明的“反向翻译法”。原句说“没有任何南美地区接壤欧洲地区”,在逻辑上完全等价于“我们 抓不到任何一个现行 (既在南美,又在欧洲,还互相接壤)”。使用否定符号(\(\neg\))搭配存在量词(\(\exists\))和逻辑与(\(\land\)),在语法合法的同时,精准且直接地表达了原句的互斥关系。
表达式 2: (∀c, d [In(c, SouthAmerica) ∧ In(d, Europe)] ⇒ ¬Borders(c, d))
- 这个表达式表达的意思: 对于任意两个实体 \(c\) 和 \(d\),如果 \(c\) 在南美并且 \(d\) 在欧洲,那么它们必然不接壤。
- 所属类别: 1. The expression correctly expresses the English sentence. (正确表达了英文原意)
- 原因解释: 这是表达“所有都不...”的另一种标准形式,也就是我们的口诀“立规矩(\(\forall\) 搭配 \(\Rightarrow\))”。它设立了一个全局的规则条件(前提):只要满足“一个在南美且另一个在欧洲”,就必然得出结论(\(\neg Borders\))。语法完全有效,逻辑严密贴合原意。 (注:在一阶逻辑翻译中,一句话可以有多种逻辑等价的正确翻译,所以选项1和2都是 Category 1) 。
表达式 3: (¬∀c In(c, SouthAmerica) ⇒ (∃d In(d, Europe) ∧ ¬Borders(c, d)))
- 这个需要确认一下c的作用域到底包不包括右边。经过搜查,一般认为这个表达式中c的作用域是包括右边的。因此语法是正确的。
- 错误含义:“如果 不是所有东西都在南美 (也就是存在某个东西不在南美),那么存在一个欧洲地区 d 使得它不与某个 c 接壤。”
表达式 4: (∀c In(c, SouthAmerica) ⇒ (∀d In(d, Europe) ⇒ ¬Borders(c, d)))
- 这个表达式表达的意思: 对于任意实体 \(c\),如果它在南美, 那么 (对于任意实体 \(d\),如果它在欧洲,那么 \(c\) 和 \(d\) 不接壤)。
- 所属类别: 1. The expression correctly expresses the English sentence. (正确表达了英文原意)
- 原因解释: 还记得我们之前笔记里的那个“进阶技巧”吗?在逻辑学中,两层嵌套的蕴含式 \(A \Rightarrow (B \Rightarrow C)\) 是完全等价于合并条件的 \((A \land B) \Rightarrow C\) 的。 这也就意味着,表达式 4 在数学和逻辑本质上,与我们刚刚判定为正确的表达式 2 是一模一样的!它只是把前提条件拆成了两层“如果...那么...”来写。因此,它语法合法,且同样完美表达了原意。
Unifier
FOL-第二个课件
-
Substitution(θ)只能替换变量 :形式永远是
θ={ v1/t1, v2/t2,… }\theta={\,v_1/t_1,\ v_2/t_2,\dots}θ={v1/t1, v2/t2,…} 其中 viv_ivi 必须是 变量 ,tit_iti 是一个 term(项) 。
- 这个 term 可以是:
- 常量:x/Ax/Ax/A
- 另一个变量:x/yx/yx/y
- 函数项:x/G(A,B)x/G(A,B)x/G(A,B)
- 不能替换常量/谓词/函数符号 :比如 A/xA/xA/x、G(x,x)/yG(x,x)/yG(x,x)/y 都不合法。
- 另外,一个变量在同一个 θ 里 只能对应一个结果 :不能同时有 x/Ax/Ax/A 和 x/Bx/Bx/B(除非 A=BA=BA=B)。