多次提到彭罗斯将哥德尔不完备性定理(Gödel's incompleteness theorems)作为核心论点之一,下面谈一下全本理解的这个定理及其意义。全本未必能用最严格的数学/逻辑定义来说明,同时全本也对一些问题存有疑问,但这里不影响对该定理框架的描述。证明和论述的来源:http://plato.stanford.edu/entries/goedel-incompleteness/。
首先长话短说,这个定理的基础是面向一组可数(通常是无限的,原因下面会简述)的命题和推演的罗列(本来是集合,但因为有限/可数,所以就可以编序,这也是哥德尔定理的必需的基础)。最能够想象的也是这个定理本身所依靠的最小系统即皮亚诺算术公理系统(Peano axioms)。不清楚的话,只要想想可以不断加一往上长的自然数和数学归纳法就是这个系统的最重要组成部分。对于命题和推演的集合在逻辑学上有一个比较牛逼的名称叫形式系统(Formal System)。
在形式系统中大致可以有以下这些内容条目,
需要注意的是,我们这里的系统,通常是无限的。原因是我们考虑系统的完备性,所以各种符号组合的可能性都需要考虑。所以任何一个能够给出的合法的符号组合,尤其是命题,它必须必然需要被包括在内。同理含参命题也一样。
这个有点像什么?打个比方,我们在学校里学数学,做证明题,有的证明题那个难啊,还有什么奥数什么的。但在这里,我们可以设想有一部机器不断依照一定顺序地制造基本符号组合,从短的到长的,按照字典序什么的,这样对于任意固定长度的符号序列,它总能被触及到,只是早晚问题,而我们这里是逻辑/理论数学上讨论的,这是理想机器,只要序列有限,都是“秒完成”(只有可行/不可行的问题,不存在什么运算复杂性之类的问题)。当然有一个“算法”可以检查并确保生成的是合法的序列。然后这么一条条地生成,那么很显然任何一个证明,无论多艰深,只要是有限的(废话,证明当然是有限的),都无一例外能最终被罗列到!(但,这个系统本身不一定能确认之,有的能,有的不能,这是后面要说明的中心问题)
所以,虽然条目可以是无限的,但是可数的。所以我们能将这些条目编号。这个编号很有讲究,编法当然不是唯一的,就像证明“自然数和有理数一样多”,编法不对是出不了结果的。一个合法的编号就是能够罗列出所有合法的符号组合。比方讲,如果我们知道有一个东西是可数但无限的,比如自然数(虽然自然数作为简单符号不编也没关系),你就不能盯着它编,这样你就编不了别的东西了。至少要夹花编。
其实我们会发现,无论从逻辑讨论还是对于哥德尔定理的讨论,很多条目逻辑上不必关心,当然真要编进去,只要编号合理也无伤大雅。我们比较关心的包括以下这些:
其中一元含参命题A(x)需要讲一下。它不同于返回真假值的逻辑函数,它只是一个对参数的断言,比如A(x):=x如何如何。当参数代入后,它退化为无参命题,则是有一个真假,这个由系统(论证链)来决定。它和逻辑函数的关系是:
既然有了编号,我们对这个系统中任意一个条目m, 我们有它的一个编号[m](别处用上方括号,这里简便起见用一般方括号),我中文里称它为m门,当然这是一个自然数。
接下来我们来看几个比较有趣的函数和命题。注意这里的函数未必编号在系统中,只是对命题起到一个辅助(例如4和5)。
至此,我们需要的基础设施有了。接下来要导出哥德尔定理,主要靠对角线引理。这个方法就是康托(Georg Cantor)在论证无理数多于有理数中使用的著名的方法。只是在这里不是那么直观而已。
这个引理结论很简单:
【对角线引理】
对任意上述“自称完备”的系统(有一定的基本限定条件,例如纳入编号函数相关条目;不自称完备则不用证明,因为已经不完备),对于任意合法编号,对其中任意一个一元命题A(x)(简称A逻辑),都存在一个(依赖于编号函数的)D条款,使得D<=>A([D])。
根据这个引理,那么如果将A设为证明不存在函数NoProv(),就会出现D<=>NoProv([D]),即:
这显然是一个矛盾,也是哥德尔定理揭示的问题。
要分析理解这个现象,我们先看这个引理是怎么来的。以下是这个对角线引理的证明。
【对角线引理证明】
首先我们看跳代检查声明S([a],b,c),所有参数显然都是自然数,虽然第一个参数的含义是对函数的引用,故而这里一开始用[a]标出作为提示。所以跳代检查函数本身实际是S(x,y,z)。我们可以设想其一个特殊的实例S(x,x,y),即对每一个一元函数(编号为x),跳代检查声明这个函数编号代入函数本身产生的无参命题的编号是y。这里实际做的是subst(x,x),这称作自跳代。
然后我们构造一个一元命题B(x):=存在y使得A(y)^S(x,x,y),简称B逻辑。容易看出,这个命题含义是对一个一元函数(编号为x)进行声明,其自跳代(编号)代入一元逻辑函数A()得到的不含参命题为真。
由于B(x)本身也是一个一元函数,我们考虑将其代入B(x)自身(参数x设为B(x)本身的编号),即自跳代subst([B(x)],[B(x)]),亦即B([B(x)])。自然这是一个不含参命题,可将其记作D。从B(x)的定义看,这个自跳代D=B([B(x)])考察了(等价于)B(x)的B逻辑值,亦即B(x)的自跳代(编号)(亦即[D])代入A()得到的命题。从而有D<=>A([D])。证毕。
接下来我们看为什么它是对角线,从而能看出这个引理的“几何特征”。
首先我们列一个表,每一行的行号和每一列的列号对应于相应的哥德尔编号,均向着无限伸展。对于m行n列元素,假设m是一元逻辑命题M(x)的哥德尔编号(即[M(x)]=m),则这个元素为M(n)(对于不是一元命题的行,我们忽略,或标记一个负数之类即可)。于是上述(将NoProv()作为A()代入后的)B(x)就在[B(x)]=b行。然后我们再来看对角线,它实际上都是上述的自跳代 。最后我们看b行b列的元素。这个元素值,作为对角线上元素,它代表B(x)的自跳代命题;作为b行的元素,它代表(作为NoProv()的参数的)“B(x)的自跳代命题”不可证明这一命题。所以说这两者是同一个条目。(即D==A([D]),这和上面的D<=>A([D])表述并不矛盾,实际上是一致的。“D<=>A([D])”本身是基于逻辑推演的真命题)
接下来我们再用更通俗的语言来看看B([B(x)])是怎么回事。B(x)是声明:自己(x)对自己的声明(自己说自己如何如何)是不可证明的(和其他一元命题一样,对每个具体的x,其真假与否由系统决定)。问题就是,B(x)自己说自己呢?(这个直接导致矛盾,系统也爱莫能助)这个其实有点像“我在撒谎”或罗素悖论。
这里需要注意的是,B(x)本身,对于不同x的实例,既有可能是真(可证明),也有可能假(可否证)。比如,在一个编号系统中,如果第2条是含参命题:x是偶数;而第四条是含参命题:x是奇数。那么B(2)就是假的,B(4)就是真的。
那么B([B(x)])到底是真是假呢?我们这里的观点是:
它是真的(因为出了系统我们知道系统给不出它的证明,因为如果系统给出它的证明,系统就不一致了)。但是系统不能给出证明(或者等价地,否证)(但是系统连这个结论也无法作出),也就是在系统的观点上无法知道其真假。
系统本身要是一致的,那么它至少其中会有一条如是的命题,它是真的,但是系统本身无法证明。所以系统是不完备的。
哥德尔定理给出的这种真的,但系统无法证明的命题,是利用了“证明”断言构筑的命题。但这构筑是合法的。
但这不是系统中唯一的这类命题(真却无法证明)。其他的这类命题(也是关于皮亚诺算术系统的)著名的如古德斯坦定理(Goodstein's Theorem)。
但是问题还没完。正如某逻辑学家(名字忘了)说的,哥德尔定理有一难,一容易。一难是很难理解,一容易是很容易,其实极其容易误解。
(未完待续)