// 注:本文仅为作者最近学习了解集合论的大致总结,若想深入了解强烈建议找本数理逻辑的教材系统学习,维基百科也不错。
大家知道,数学有别于其它学科最重要就是严谨,比如上篇文章介绍了超越无穷的序数与基数,稍不小心就容易出错误。随着数学理论与证明过程越来越复杂,数学家急需一种能机械化规范证明的系统,使得可方便机器对其验证。在计算机发明之前就有人提出了它——形式系统。本文将从简单的形式系统开始,介绍命题逻辑、一阶逻辑,皮亚诺算数系统直到ZFC集合论这一主流数学中出镜最多的形式系统。
抱着边做边学的目的,我还慢慢搓出了一个能在网页上运行的形式系统模拟器“Deductrium”,后来又把它改造成了游戏。
引子:pq形式系统
简单来说,形式系统是一个字符串收集游戏。首先你手上有一些初始的字符串,系统会提供一些机械的规则,将这些规则作用在你手上的串上,你将得到新的串,下次便可以用这些新串运用规则再生出串。《GEB》这本书中提到了一个最简单的“pq”形式系统:
- 本系统所有合法的字符串只允许这三个字符出现:“s”、“p”、“q”;
- 你手上有这些初始字符串:“pq”、若X代表只包含“s”的字符串,则“XpqX”是初始字符串,比如“spqs”、“sssspqssss”;
- 规则:设X、Y、Z都是串,如果你手上有“XpYqZ”,则你能得到“XpYsqZs”。
举个例子:首先有初始串(X是“s”)“spqs”,运用规则(X是“s”、Y是“”、Z是“s”)得到“spsqss”,继续运用规则(X是“s”、Y是“s”、Z是“ss”)得到“spssqsss”。
下面你能说出哪些串是能够在有限步骤中得到、哪些又是永远得不到的呢?
- sspq
- spspq
- sspsqsss
- sspssqssss
或许你已经看出来了,“XpYqZ”正好代表$X+Y=Z$,其中的数字则是由“s”的个数表示的。注意形式系统本身是没意义的,给它赋予含义后才能讨论这些字符串的意义。形式系统本身只有符号与规则,任何附加在上面的含义都不属于形式系统,是一种我们外在赋予的东西。
命题逻辑形式系统
虽然形式系统本身没有意义,但我们肯定希望它能干有意义的事情,比如用于数学证明。下面我们构造不包含否定的命题逻辑的推演形式系统:
- 本系统所有合法的字符串为:
- 设$n$是自然数,则命题符号$A_n$都是合法的字符串;
- 若X、Y是合法的字符串,则“(X → Y)”也是合法的字符串。
- 设X、Y、Z是任意合法的字符串,本系统初始字符串有这些:
- “(X → (Y → X))”都是初始字符串;
- “((X → (Y → Z)) → ((X → Y) → (X → Z)))”都是初始字符串。
- 规则:
若你手上同时有串“(X → Y)”与“X”,则能得到串“Y”。
目前为止,那些箭头、字母没有任何实际含义。下面我们外在地赋予系统确切的逻辑的意义,则以上可翻译为:
- 术语翻译:合法字符串对应命题、你手上的串对应定理、初始字符串对应公理。
- 符号翻译:
- 命题符号$A_n$代表具体的真命题或假命题,其内容我们暂不关心。
- “(X → Y)”表示命题“命题X能够推出命题Y”,即“→”代表逻辑蕴含。
- 公理模式:对任意命题X、Y、Z,有
- 命题“(X → (Y → X))”是公理 (a1)
- 命题“((X → (Y → Z)) → ((X → Y) → (X → Z)))”是公理 (a2)
- 推理规则(mp):
若命题“(X → Y)”与命题“X”都是定理,则命题“Y”也是定理。
我们来看一个形式化证明的例子,证明对任意的命题“A”,“(A → A)”都是定理:
- “(A → (A → A))” (a1公理)
- “(A → ((A → A) → A))” (a1公理)
- “((A → ((A → A) → A)) → ((A → (A → A)) → (A → A)))” (a2公理)
- “((A → (A → A)) → (A → A))” (mp规则作用于3与2)
- “(A → A)” (mp规则作用于4与1)
很明显这里面每个步骤都可以机械地检验(比如计算机验证),可以说完美满足严谨的数学家们的愿望了。
下面给读者留一道思考题:
证明对任意的命题“A”、“B”、“C”,若“(A → B)”与“(B → C)”是定理,则“(A → C)”也是定理。
提示:从这个(a3)公理出发似乎是个不错的选择:“((A → (B → C)) → ((A → B) → (A → C)))”。
a1至a3公理其实规定了“如何引入逻辑蕴含符号”“如何使用逻辑蕴含符号”“如何消去逻辑蕴含符号”这三件事,使得我们可以表达并处理“能推出什么”的逻辑,但目前暂时还不能表达“不能推出什么”。为了让系统能处理否定命题,我们引入否定符号“¬”,并向形式系统添加以下内容:
- 若X是命题,则“¬X”也是命题。
- 添加公理模式:若X、Y是任意命题,则“((¬X → ¬Y) → (Y → X))”是公理 (a3)
加入否定词的形式系统就是完整的命题逻辑系统了。可以证明:设A、B是任意的命题,则在这个系统中下面的命题都是定理:
- (¬¬A → A) (双重否定消去)
- (A → ¬¬A) (双重否定介入)
- (A → (¬A → B)) (矛盾爆炸原理)
- ((¬A → B) → ((¬A → ¬B) → A)) (反证法原理)
证明方式就是写出推导步骤,独立想出这些推导有点难度,如果读者不想再做这样烧脑的推理习题,则可以直接参见维基百科上面有答案。
或许你注意到这个系统连最基本的“与”、“或”逻辑连词都没有,但其实“A或B”可以通过“(¬A → B)”表达、“A与B”则可通过“¬(A → ¬B)”表达。我们也可以引入新的公理来把“与”、“或”符号加入系统,点击展开/收起如何引入新符号与新公理。
或者你可能觉得两个符号“→”、“¬”都多了,走向另一种极端主义:其实用与非逻辑(NAND)就能表示所有命题逻辑,比如这个谢费尔竖线形式系统,但它也有代价,那就是推理规则太多了。
只看语言叙述很难理解这些形式系统,计算机本来就最擅长做这些机械判定的事情,因此我强烈建议可以尝试着在Deductrium的形式系统中去体验一下。如果你觉得从头开始玩Deductrium太难了,根本玩不到当且仅当与逻辑符号那里,我留了一个Deductrium创造模式,可以直接使用所有公理、符号定义以及元定理等。
命题逻辑的形式系统定义方式很多,更常见的是直接包含“与”、“或”、“非”的系统。我们介绍的形式系统叫做希尔伯特式的,特点是很多公理,但只有一条推理规则(mp)。这条推理规则结合公理能得到很重要的演绎元定理,它告诉了我们为何这一条规则就够用了:
如果假设已知A是定理的条件下能在形式系统中推出B是定理,则该系统能够无假设条件下推出(A → B)是定理。
证明见维基百科。它的逆定理更简单,直接就是mp规则:
如果该系统能够无假设条件下推出(A → B)是定理,则假设已知A是定理的条件下能在形式系统中推出B是定理
演绎元定理与mp规则告诉了我们符号“→”的外在行为确实与逻辑蕴含相同。
那些同时包含“与”、“或”的系统往往推理规则更多,但它们在某种程度上是等价的,即从相同的假设出发,能推出来的东西都一样,虽然中间步骤可能差异很大。
可靠性与完备性、内外定理
不知读者会不会怀疑,刚才有三个公理模式和一个推理规则的形式系统真的就能胜任命题逻辑推理吗?这个问题其实可分成两方面:一是(可靠性)它推出的命题都是真命题吗?二是(完备性)对于所有真命题,是否都能够从这个形式系统中推出来呢?对于命题逻辑来说这两个答案都是肯定的。可靠性证明仅需列出所有公理与推理步骤涉及的命题的真值表,检验其正确性即可;而完备性的证明就有点复杂了,游戏Deductrium中后期会解锁一个“自动证明”的元定理能力,只要是系统穷举所有原子命题都成立的真值表命题都成立,就有方法在系统内写出推理步骤。
注意形式系统内外命题之间的关系其实很微妙,比如我们证明了:
在命题逻辑形式系统中,对任何命题A,“(A → A)”都是定理。
被证明了的命题就叫做定理,上面这句话本身也是定理,准确说它是关于(命题逻辑形式系统里的)定理的定理。注意这两个“定理”是两个层级,并不相同:
- 形式系统推出来的东西,我们只是称呼它们“定理”,或叫系统的“内定理”,它们只是某个形式系统中的概念,跟平时数学定理虽然有点像,但不是一个东西。验证内定理的方式就是给出系统中的推理步骤。
- 我们证明的那条定理,是关于形式系统的理论中的定理,为方便区分,也叫“元定理”或“外定理”。外定理才是真正的数学定理,它跟平时算数中的加法交换律、高等数学里面的泰勒展开定理一样,都是在我们学过的数学体系下推导而来的。
终级问题:先有鸡还是先有蛋?
有些人会困惑,为了机械化验证数学定理的证明无误,我们又需要将整个数学体系定义为一个更复杂的元形式系统来描述、判定,而为了验证更大的元形式系统的正确性,又需要构建元元系统、机械化验证元元定理……(ps.对套娃感兴趣的话可参考这个阿拉丁神灯造物神的故事)具体来说,形式系统可以用集合论的语言准确定义,但后面将看到,集合论又是由形式系统定义出来的!我们跌入了先有鸡还是先有蛋的困境之中。
为了避免无限套娃,我们不再使用形式系统等机械方式验证数学定理的证明的正确性,阅读元定理的证明只能凭我们的数学阅历进行。即我们不能一直刨根问底,必须在某一层级停止选择直接相信它们。这就好比当我们学习外语(形式系统)时需要一门母语(我们的数学阅历)来进行教学,而源头母语的习得能力是与生俱来的本能,不再依赖任何语言了。
但是,我们的目的不就是为了形式化整个数学理论吗?数学理论当然也应该包含形式系统和数理逻辑自身。目前人们是这样做的:定义一个形式系统,这个系统强大到几乎可以表达任意数学理论中的命题,然后我们手动证明该系统是可靠的,只要我们相信该系统是可靠的证明过程无误(这部分确实没法机械检验),我们就敢愉快地使用该系统去检验任何数学证明了,甚至包括该系统可靠性的证明过程。下面引用《GEB》中的一段话:
一个人永远也不能给出一个最终的、绝对的证明,去阐明在某个系统中的一个证明是正确的。当然,一个人可以给出一个关于证明的证明,或者关于一个证明的证明的证明——但是,最外层的系统有效性总还是一个未经证明的假设,是凭我们的信仰来接收的。
这也很像计算机中的编译器的自举——C++语言的编译器是由C++编写的!这里面看似也是鸡与蛋的困境,实则不然:首先人工编写一段将汇编语言翻译成机器码的程序,这段程序只能用机器码写,而且机器码能否正确运行取决于我们是否相信CPU芯片中的电子按物理规律运动。该程序写好后我们就能用汇编语言来写更高级的C语言编译器了,然后再用C语言写更高级的C++编译器,等有了C++编译器,我们就可以放弃原来C语言版的C++编译器,完全改为C++语言编译C++编译器了。
一阶逻辑
命题逻辑中,我们仅用字母表示“原子命题”,并没涉及如何具体描述它们的“内部结构”,下面就来看看一阶逻辑。首先介绍语法方面:
一阶逻辑中除了命题这一概念,还引入了“项”与“谓词”的概念:变量与常量符号是“原子项”,n个项被n元函数作用得到项,被n元谓词作用得到“原子命题”。注意一阶逻辑是一类系统,选择不同的常数符号或谓词就得到不同的形式系统,比如下面举两个一阶逻辑形式系统的例子:
- 若项代表整数,则“0”、“1”、“-2”这些就是常量符号、“x”就是变量符号;加法是个二元函数,因此“add(1,1)”也是项;“>”、“<”、“=”都是二元谓词符号,因此“2>1”、“add(1,1)=2”都是原子命题,原子命题可以继续按命题逻辑的构建方法构造更复杂的命题,比如:“¬(add(x,0)=0 → x=1)”。
- 若项代表集合,则空集“$\phi$”就是常量符号、“x”就是变量符号,花括号是给定元素构造新集合的n元函数;交集$\cap$、并集$\cup$则是二元函数,“$\in$”、“=”、“$\subset$”则是谓词。比如$\left\{x,y\right\}\cap\phi$是项、$\phi\in\left\{\phi\right\}$是原子命题。
引入变量的目的是为了表达任意($\forall$)、存在($\exists$)等带有量词的命题,这也是一阶逻辑与命题逻辑最大的区别。我们继续加入下面的规则:
- 若A是任意命题,x是任意变量,则($\forall$ x : A)也是命题
添加了新符号$\forall$后,同时需要加入能处理它的公理,设大写字母是任意命题,小写字母是任意变量,希腊字母是任意项:
- (a4) (($\forall$ x : A) → A[x/$\alpha$]),其中A[x/$\alpha$]表示将A中所有自由出现的x都替换为项$\alpha$,且A必须满足能被替换,后面选读里会详细说这些概念。
- (a5) (($\forall$ x : (A → B)) → (($\forall$ x : A) → ($\forall$ x : B)))
- (a6) (A → ($\forall$ x : A)) 若x不在A中自由出现
- (a7) 对于任意的公理K,($\forall$ x : K) 也是公理
这四条公理分别对应量词的消去(a4),使用(a5)与介入(a6与a7)。
我们不再单独引入关于存在符号“$\exists$”的公理,而是把它当成是“¬$\forall$¬”的简写。
最后再说说谓词。一般我们会默认形式系统都有等词“=”,并且加入两条公理模式:
- (eq1) $\alpha$=$\alpha$
- (eq2) ($\alpha$=$\beta$ → (A → A’))
其中命题 A’是将命题 A中全部或部分的自由的$\alpha$替换成$\beta$的结果。
利用(eq1)和(eq2)不难证明等词具有自反性与传递性,即:
- $\alpha$=$\beta$ → $\beta$=$\alpha$
- $\alpha$=$\beta$ → ($\beta$=$\gamma$ → $\alpha$=$\gamma$)
再次强调一下:虽然一阶逻辑中有“任意”、“存在”等词语出现,但形式系统只有这些机械化的公理模式,它无法理解这些量词背后的含义。仅靠机械化就能实现正确的逻辑,虽然这些公理模式略微复杂。点击这里可以展开/收起关于公理中替换/自由出现等的具体细节定义。
最后说说“一阶逻辑”是什么意思。命题逻辑也叫“零阶逻辑”,它只谈论命题之间的关系,而一阶逻辑深入到命题内部,可以谈论任意的项,高阶逻辑则可以谈论项之间的任意函数、任意谓词、任意命题等等关系。然而一般来说一阶逻辑已经够用了,所以二阶及以上的逻辑很少提及。
著名的描述关于自然数性质的皮亚诺公理体系就是在一阶逻辑基础上构造的。点击这里展开/收起细节。
ZFC集合论
ZFC集合论认为包括集合的元素在内的所有东西都是集合。它在一阶逻辑基础上仅多加入了加入了谓词“属于”符号“$\in$”,以及关于集合的9个公理:
- 外延公理(定义了集合相等的条件)
- 配对公理(定义了通过元素构造集合的方法)
- 并集公理(定义了并集的存在)
- 幂集公理(定义了幂集的存在)
- 无穷公理(定义了包含自然数的集合的存在)
- 分离公理(让我们能按条件从大集合中筛出元素构成子集,相当于数组的filter函数)
- 替换公理(提供了从已知的集合和关系构造其它的集合的方式,而不局限于子集,相当于数组的map函数)
- 正则公理(剔除了像这样“{ { {…} } } ”无穷嵌套的集合,消除了理发师悖论)
- 选择公理(让我们能够从无穷个任意的集合中每个选出一个元素来构成新集合)
这些公理具体的样子有些复杂不再列出,网上都可以找到(游戏Deductrium里面也有)。
注意上面9条公理完全由一阶逻辑描述,并且不包含除属于符号外(例如空集符号、交并补等)一切其余符号,然而数学家实际上肯定不会只使用寥寥这些符号,点击这里展开/收起关于如何定义新符号的规范型问题
ZFC公理体系不仅可以模拟出皮亚诺公理,证明质数有无穷个这样的较复杂的命题,还可以通过引入更多符号概念定义,证明出关于分析,拓扑几何等几乎一切领域的数学理论。
关于集合论本身也有些细节须注意,比如所有集合并不构成一个集合、所有序数也不能构成一个集合。按序数的定义,所有序数构成的集合也该是一个更大的序数,那么我们就可以在这基础上继续向上堆叠更大的序数,这就与最大序数自相矛盾了。其实ZFC集合论的正则公理将所有序数构成的东西排除在了集合之外从而避免矛盾。将集合论这个形式系统继续扩展,引入类(Class)的概念才能描述所有序数:它们构成的东西叫做“真类”,真类和集合很像,唯一区别是它不能再作为元素出现在其它集合或类中了。
集合论跟序数有着非常紧密的联系。点击这里展开/收起如何用序数描述ZFC集合论的强度。
结语
由于集合论网上资料众多,我也是最近才学习了解这些内容,集合论精彩的地方也远不止这些,比如本文完全没提到最著名的哥德尔不完备性定理。若想深入探索请参考任何数理逻辑教材。虽然ZFC集合论是数学界最广泛承认并使用的形式化公理体系,但在Deductrium中玩到后期你会发现这种希尔伯特式的形式系统的推导真啰嗦,如果要从选择公理证明良序性以及数学归纳法,虽然网上能找到证明思路,但真要形式化地在游戏系统内操作最终推导出来的工作量却太大了。除了Metamath,现在主流的数学家们用的证明辅助工具则完全用的另一套体系——类型论。这便是下一篇文章要填的坑。