P、NP、NPC问题

来源:互联网 发布:表达亲亲的网络用语 编辑:程序博客网 时间:2024/04/28 16:09

转自:http://blog.csdn.net/wwy851/article/details/6082007

最近看了很多关于P、NP和NPC问题的文章,但是都不是很系统全面,很多叙述的也不太清楚,有的易理解但却显得罗里啰嗦,因此,本人结合自己的理解整理成下面的文章,以飨感兴趣的读者,希望可以一起交流探讨。

(一)   非确定性问题

那么究竟什么是非确定性问题呢?有些计算问题是确定性的,比如加减乘除之类,你只要按照公式推导,按部就班一步步来,就可以得到结果。但是,有些问题是无法按部就班直接地计算出来的。比如,找大质数的问题,大的合数分解质因数的问题,就没有一个确定的公式,把数代进去,就直接可以算出结果。这种问题的答案,是无法直接计算得到的,只能通过间接的“猜算”来得到结果。这也就是非确定性问题。而这些问题通常有个算法,它不能直接告诉你答案是什么,但可以告诉你,某个可能的结果是正确的答案还是错误的。这个可以告诉你“猜算”的答案正确与否的算法,假如可以在多项式时间内算出来,就叫做多项式非确定性问题。而如果这个问题的所有可能答案,都是可以在多项式时间内进行正确与否的验算的话,就叫完全多项式非确定问题。完全多项式非确定性问题可以用穷举法得到答案,一个个检验下去,最终便能得到结果。但是这样算法的复杂程度是指数关系,因此计算的时间随问题的复杂程度成指数的增长,很快便变得不可计算了。了解了这个问题,为便于以后的 理解,我们再来看看算法和问题的复杂性。

(二)  算法和问题的复杂性

算法的复杂性是指解决某个问题的一个具体算法的执行时间(这里不考虑空间复杂度)时间复杂度并不是表示一个程序解决问题需要花多少时间,而是当问题规模扩大后,程序需要的时间长度增长得有多快。也就是说,对于高速处理数据的计算机来说,处理某一个特定数据的效率不能衡量一个程序的好坏,而应该看当这个数据的规模变大到数百倍后,程序运行时间是否还是一样,或者也跟着慢了数百倍,或者变慢了数万倍。不管数据有多大,程序处理花的时间始终是那么多的,我们就说这个程序很好,具有O(1)的时间复杂度,也称常数级复杂度;数据规模变得有多大,花的时间也跟着变得有多长,这个程序的时间复杂度就是O(n),比如找n个数中的最大值;而像冒泡排序、插入排序等,数据扩大2倍,时间变慢4倍的,属于O(n^2)的复杂度。还有一些穷举类的算法,所需时间长度成几何阶数上涨,这就是O(a^n)的指数级复杂度,甚至O(n!)的阶乘级复杂度。不会存在O(2*n^2)的复杂度,因为前面的那个“2”是系数,根本不会影响到整个程序的时间增长。同样地,O (n^3+n^2)的复杂度也就是O(n^3)的复杂度。因此,我们会说,一个O(0.01*n^3)的程序的效率比O(100*n^2)的效率低,尽管在n很小的时候,前者优于后者,但后者时间随数据规模增长得慢,最终O(n^3)的复杂度将远远超过O(n^2)。我们也说,O(n^100)的复杂度小于O(1.01^n)的复杂度。 容易看出,前面的几类复杂度被分为两种级别,其中后者的复杂度无论如何都远远大于前者:一种是O(1),O(log(n)),O(n^a)等,我们把它叫做多项式级的复杂度,因为它的规模n出现在底数的位置;另一种是O(a^n)和O(n!)型复杂度,它是非多项式级的,其复杂度计算机往往不能承受。当我们在解决一个问题时,我们选择的算法通常都需要是多项式级的复杂度,非多项式级的复杂度需要的时间太多,往往会超时,除非是数据规模非常小。

而问题的复杂性是指问题本身的复杂程度,是问题的性质。例如,对于排序问题,如果我们只能通过元素间的相互比较来确定元素间的相互位置,则排序问题的复杂性是O(nlgn),但是排序算法有很多,冒泡法的时间复杂度是O(n^2),快速排序平均情况下时间复杂度是O(nlgn)等等,而排序问题的复杂性是指在所有的解决该问题的算法中最好算法的复杂性。问题的复杂性不可能通过枚举各种可能算法来得到,一般都是预先估计一个值,然后从理论上证明。为了研究问题的复杂性,必须将问题抽象,为了简化问题,我们只考虑一类简单的问题,判定性问题,即提出一个问题,只需要回答yes或者no的问题。任何一般的最优化问题都可以转化为一系列判定性问题,比如求图中从A到B的最短路径,可以转化成:从A到B是否有长度为1的路径?从A到B是否有长度为2的路径?…从A到B是否有长度为k的路径?如果问到了k的时候回答了yes,则停止发问,我们可以说从A到B的最短路径就是k。接下来再来看两个概念:

(1)确定性算法

设A是求解问题B的一个算法,如果在展示问题B的一个实例时,在整个执行过程中每一步都只有一个选择,则称A是确定性算法.因此如果对于同样的输入,实例一遍又一遍地执行,它的输出从不改变.通常我们在写程序时,用到的都是一些确定性算法,比如说排序算法,查找算法等.

(2)不确定性算法

一个不确定性算法由下列两个阶段组成:猜测阶段和验证阶段。

猜测阶段:

在这个阶段产生一个任意解串Y,它可能对应于输入实例的一个解,也可以不对应解.事实上,它甚至可能不是所求解的合适形式,它可能在算法的不同次运行中不同.它仅仅要求在多项式步数内产生这个解.

验证阶段:

在这个阶段,主要做两件事.首先,检查产生的解串Y是否是合适的形式,如果不是,则算法停下并回答NO;其次,如果Y是合适形式,那么算法继续检查它是否是问题实例X的解,如果它确实是实例X的解,那么它停下并且回答YES,否则它停下并回答NO.我们也要求这个阶段在多项式步数内完成.

(三)P问题、NP问题与NPC问题

(1)P问题

如果一个问题可以找到一个能在多项式的时间内解决它的算法,那么这个问题就属于P问题。P是英文单词多项式的第一个字母。我们通常在编程中求解的问题大多都是P类问题.比如说排序,找最短路径等。P是所有可在多项式时间内用确定算法求解的判定问题的集合。例如,查找、排序等。

(2)NP问题

如果一个问题可以找到能在多项式时间内验证它的一个解是否正确的算法,那么这个问题称为NP问题。显然,所有的P类问题都是属于NP问题。NP问题是所有可用多项式时间算法验证其猜测准确性的问题的集合。例如,哈米尔顿回路,TSP(Travelling Salesman Problem,旅行商问题)。

NP问题不是非P类问题。NP问题是指可以在多项式的时间里验证一个解的问题。NP问题的另一个定义是,可以在多项式的时间里猜出一个解的问题。比方说,我RP很好,在程序中需要枚举时,我可以一猜一个准。现在某人拿到了一个求最短路径的问题,问从起点到终点是否有一条小于100个单位长度的路线。它根据数据画好了图,但怎么也算不出来,于是来问我:你看怎么选条路走得最少?我说,我RP很好,肯定能随便给你指条很短的路出来。然后我就胡乱画了几条线,说就这条吧。那人按我指的这条把权值加起来一看,嘿,神了,路径长度98,比100小。于是答案出来了,存在比100小的路径。别人会问他这题怎么做出来的,他就可以说,因为我找到了一个比100 小的解。在这个题中,找一个解很困难,但验证一个解很容易。验证一个解只需要O(n)的时间复杂度,也就是说我可以花O(n)的时间把我猜的路径的长度加出来。那么,只要我RP好,猜得准,我一定能在多项式的时间里解决这个问题。我猜到的方案总是最优的,不满足题意的方案也不会来骗我去选它。这就是NP问题。当然有不是NP问题的问题,即你猜到了解但是没用,因为你不能在多项式的时间里去验证它。下面我要举的例子是一个经典的例子,它指出了一个目前还没有办法在多项式的时间里验证一个解的问题。很显然,前面所说的Hamilton回路是NP问题,因为验证一条路是否恰好经过了每一个顶点非常容易。但我要把问题换成这样:试问一个图中是否不存在Hamilton回路。这样问题就没法在多项式的时间里进行验证了,因为除非你试过所有的路,否则你不敢断定它“没有Hamilton回路”。

    之所以要定义NP问题,是因为通常只有NP问题才可能找到多项式的算法。我们不会指望一个连多项式地验证一个解都不行的问题存在一个解决它的多项式级的算法。相信读者很快明白,信息学中的号称最困难的问题——“NP问题”,实际上是在探讨NP问题与P类问题的关系。

    很显然,所有的P类问题都是NP问题。也就是说,能多项式地解决一个问题,必然能多项式地验证一个问题的解——既然正解都出来了,验证任意给定的解也只需要比较一下就可以了。关键是,人们想知道,是否所有的NP问题都是P类问题。我们可以再用集合的观点来说明。如果把所有P类问题归为一个集合P中,把所有 NP问题划进另一个集合NP中,那么,显然有P属于NP。现在,所有对NP问题的研究都集中在一个问题上,即究竟是否有P=NP?通常所谓的“NP问题”,其实就一句话:证明或推翻P=NP。

    NP问题一直都是信息学的巅峰。巅峰,意即很引人注目但难以解决。在信息学研究中,这是一个耗费了很多时间和精力也没有解决的终极问题,好比物理学中的大统一和数学中的歌德巴赫猜想等。

    目前为止这个问题还“啃不动”。但是,一个总的趋势、一个大方向是有的。

(3)NPC问题

人们发现还有一系列的特殊NP问题,这类问题的特殊性质使得很多人相信P<>NP,只不过现在还无法证明。这类特殊的NP问题就是NP完全问题,即NPC问题,C代表COMPLETE)。显然,NP完全问题是求NP中判定问题的一个子类。一个NPC问题具有如下性质:它可以在多项式时间内求解,当且仅当所有的其他的NPC问题也可以在多项式时间内求解。

如果判定问题π∈NP,并且对所有其他判定问题π'∈NP,都有π'多项式变换到π(记为π'∞π),则称判定问题π 是NP完全的。

那我们现在来总结一下,P是属于NP的一个子集,那么NPC和NP到底是什么关系呢?从以上对NPC的描述可以推出NPC实际上是一类特殊的NP,另外NPC显然又和P问题没有任何交集,那么也就是说NPC是NP的另个子集。          

对于问题域用一个有限的矩形框来表示是很牵强的,问题域也应该像宇宙一样无穷无尽,否则你可以反问那么问题之外的问题是什么呢?哑然。

人们认为如果一个NPC问题存在多项式时间的算法,则所有的NP问题都可以在多项式时间内求解,即P=NP成立。这是因为,每一个NPC问题可以在多项式时间内转化成任何一个NP问题。

因此,我们可以知道NP问题实际是就是由P问题和非P问题(实际就是NPC问题)组成的。那么我们得出一个结论:在NP域,NPC 问题 ≡ 非P问题,图(一)实际应该为图(二)。

另外,如果每一个NPC问题可以在多项式时间内转化成任何一个NP问题的话,那么一个NPC问题与其它任何NPC问题都是等价的,这又如何证明呢?

比如前面说的哈米尔顿回路问题就是一个NPC问题。NPC问题的历史并不久,cook在1971年找到了第一个NPC问题,此后人们又陆续发现很多NPC问题,现在可能已经有3000多个了。所以,我们一般认为NPC问题是难解的问题,因为他不太可能存在一个多项式时间的算法(如果存在则所有的NP问题都存在多项式时间算法,这太不可思议了,但是也不是不可能)。类似哈米尔顿回路/路径问题,货郎担问题,集团问题,最小边覆盖问题(注意和路径覆盖的区别),等等很多问题都是NPC问题,所以都是难解的问题。

上面的论述好像有点费解,不过你会想明白的。

人们普遍认为,P=NP不成立,也就是说,多数人相信,存在至少一个不可能有多项式级复杂度的算法的NP问题。人们如此坚信P≠NP是有原因的,就是在研究NP问题的过程中找出了这类非常特殊的NP问题-NPC问题。正是NPC问题的存在,使人们相信P≠NP。

为了便于说明,我们先引入一个概念——归约(Reducibility),这里主要指多项式时间规约(Polynomial-time Reducible)。

设A和B是两个判定问题.如果存在一个确定性算法C,它的行为如下:当给C展示问题A的一个实例时,C可以把这个实例变换成问题B的一个实例,使得A的实例跟B的实例有相同的YES/NO应答,并且这个变换在多项式时间内完成.那么我们说A多项式时间归约到B。我们可以将多项式时间归约看作是一个函数的映射,即F(A)=B,并且这个F是多项式时间内可计算的。也就是说问题A实现上可以通过它自身满足的条件,通过一些形式上的改变而变换到问题B。实际上,问题A不比B难,同样问题B也不比A难。

《算法导论》上举了这么一个例子。比如说,现在有两个问题:求解一个一元一次方程和求解一个一元二次方程。那么我们说,前者可以约化为后者,意即知道如何解一个一元二次方程那么一定能解出一元一次方程。我们可以写出两个程序分别对应两个问题,那么我们能找到一个“规则”,按照这个规则把解一元一次方程程序的输入数据变一下,用在解一元二次方程的程序上,两个程序总能得到一样的结果。这个规则即是:两个方程的对应项系数不变,一元二次方程的二次项系数为0。按照这个规则把前一个问题转换成后一个问题,两个问题就等价了。同样地,我们可以说,Hamilton回路可以约化为TSP问题(Travelling Salesman Problem,旅行商问题)。

在Hamilton回路问题中,两点相连即这两点距离为0,两点不直接相连则令其距离为1,于是问题转化为在TSP问题中,是否存在一条长为0的路径。Hamilton回路存在当且仅当TSP问题中存在长为0的回路。

    问题A可约化为问题B”有一个重要的直观意义。B的时间复杂度高于或者等于A的时间复杂度。也就是说,问题A不比问题B难。这很容易理解。既然问题A能用问题B来解决,倘若B的时间复杂度比A的时间复杂度还低了,那A的算法就可以改进为B的算法,两者的时间复杂度还是相同。正如解一元二次方程比解一元一次方程难,因为解决前者的方法可以用来解决后者。

    很显然,归约具有一项重要的性质:归约具有传递性。如果问题A可归约为问题B,问题B可归约为问题C,则问题A一定可归约为问题C。这个道理非常简单,就不必阐述了。

    现在再来说一下归约的标准概念就不难理解了:如果能找到这样一个变化法则,对任意一个程序A的输入,都能按这个法则变换成程序B的输入,使两程序的输出相同,那么我们说,问题A可归约为问题B。

好了,从归约的定义中我们看到,一个问题归约为另一个问题,时间复杂度增加了,问题的应用范围也增大了。通过对某些问题的不断归约,我们能够不断寻找复杂度更高,但应用范围更广的算法来代替复杂度虽然低,但只能用于很小的一类问题的算法。再回想前面讲的P和NP问题,联想起归约的传递性,自然地,我们会想问,如果不断地归约上去,不断找到能“通吃”若干小NP问题的一个稍复杂的大NP问题,那么最后是否有可能找到一个时间复杂度最高,并且能“通吃”所有的 NP问题的这样一个超级NP问题?答案居然是肯定的。也就是说,存在这样一个NP问题,所有的NP问题都可以约化成它。换句话说,只要解决了这个问题,那么所有的NP问题都解决了。这种问题的存在难以置信,并且更加不可思议的是,这种问题不只一个,它有很多个,它是一类问题。这一类问题就是NPC 问题。
      NPC问题的定义非常简单。同时满足下面两个条件的问题就是NPC问题。首先,它得是一个NP问题;然后,所有的NP问题都可以归约到它。证明一个问题是 NPC问题也很简单。先证明它至少是一个NP问题,再证明其中一个已知的NPC问题能归约到它,这样就可以说它是NPC问题了。
    既然所有的NP问题都能约化成NPC问题,那么只要任意一个NPC问题找到了一个多项式的算法,那么所有的NP问题都能用这个算法解决了,NP也就等于P 了。因此,给NPC找一个多项式算法太不可思议了。因此,前文才说,“正是NPC问题的存在,使人们相信P≠NP”。我们可以就此直观地理解,NPC问题目前没有多项式的有效算法,只能用指数级甚至阶乘级复杂度的搜索。

要证明一个判定问题是NP完全的,只要在NP完全类中找到一个问题A,将这个问题归约到待证明问题即可。要证明问题是NP完全是很困难的,因为很多问题之间的转化过程是很难想到的。第一个被证明的NP完全问题是可满足性问题,它是判定一个合取范式的布尔公式F是否存在真值指派的问题(在后面会介绍)。在很多NP完全问题的证明中,我们都可以用这个问题来归约,这里不再详述。

前段时间轰动世界的一个数学成果,是几个印度人提出了一个新算法,可以在多项式时间内,证明某个数是或者不是质数,而在这之前,人们认为质数的证明,是个非多项式问题。可见,有些看来好象是非多项式的问题,其实是多项式问题,只是人们一时还不知道它的多项式解而已

(4)NP困难问题

NP-Hard问题是这样一种问题,它满足NPC问题定义的第二条但不一定要满足第一条(就是说,NP-Hard问题要比 NPC问题的范围广)。NP-Hard问题同样难以找到多项式的算法,但它不列入我们的研究范围,因为它不一定是NP问题。即使NPC问题发现了多项式级的算法,NP-Hard问题有可能仍然无法得到多项式级的算法。事实上,由于NP-Hard放宽了限定条件,它将有可能比所有的NPC问题的时间复杂度更高从而更难以解决

NP困难:一个判定问题A称为是NP困难的,如果对于NP中的每个问题B,B多项式时间归约到A。

NP完全:一个判定问题A称为是NP完全的,如果对于NP中的每个问题B,B多项式时间归约到A,并且A在NP类中.

真的很佩服你的耐性和理解力,居然看到了这里,那就再接再厉继续把它看完吧。

第一个 NP-complete 问题

NP 是 Non-deterministic Polynomial 的缩写,NP 问题通俗来说是其解的正确性能够被很容易检查的问题,这里"很容易检查"指的是存在一个多项式检查算法。
例如,著名的推销员旅行问题(Travel Saleman Problem or TSP):假设一个推销员需要从香港出发,经过广州,北京,上海,…,等 n 个城市, 最后返回香港。 任意两个城市之间都有飞机直达,但票价不等。现在假设公司只给报销 $C 块钱,问是否存在一个行程安排,使得他能遍历所有城市,而且总的路费小于 $C?
推销员旅行问题显然是 NP 的。因为如果你任意给出一个行程安排,可以很容易算出旅行总开销。但是,要想知道一条总路费小于 $C 的行程是否存在,在最坏情况下,必须检查所有可能的旅行安排! 这将是个天文数字。
NP-complete 问题是所有 NP 问题中最难的问题。它的定义是,如果你可以找到一个解决某个 NP-complete 问题的多项式算法,那么所有的 NP 问题都将可以很容易地解决。
通常证明一个问题 A 是 NP-complete 需要两步,第一先证明 A 是 NP 的,即满足容易被检查这个性质; 第二步是构造一个从某个已知的 NP-complete 问题 B 到 A 的多项式变换,使得如果 B 能够被容易地求解,A 也能被容易地解决。这样一来,我们至少需要知道一个 NP-complete 问题。
第一个 NP complete 问题是 SAT 问题,由 COOK 在 1971 年证明。SAT 问题指的是,给定一个包含 n 个布尔变量(只能为真或假) X1,X2,…,Xn 的逻辑析取范式,是否存在它们的一个取值组合,使得该析取范式被满足? 可以用一个具体例子来说明这一问题,假设你要安排一个 1000 人的晚宴,每桌 10 人,共 100 桌。主人给了你一张纸,上面写明其中哪些 人因为江湖恩怨不能坐在同一张桌子上,问是否存在一个满足所有这些约束条件的晚宴安排? 这个问题显然是 NP 的,因为如果有人建议一个安排方式,你可以很容易检查它是否满足所有约束。COOK 证明了这个问题是 NP-complete 的,即如果你有一个好的方法能解决晚宴安排问题,那你就能解决所有的 NP 问题。
这听起来很困难,因为你必须面对所有的 NP 问题,而且现在你并不知道任何的 NP-complete 问题可以利用。COOK 用非确定性图灵机( Non-deterministic Turing Machine ) 巧妙地解决了这一问题。
   正式地,NP 问题是用非确定性图灵机来定义的,即所有可以被非确定性图灵机在多项式时间内解决的问题。非确定性图灵机是一个特殊的图灵机,它的定义抓住了"解容易被检查" 这一特性。非确定性图灵机有一个"具有魔力的"猜想部件,只要问题有一个解,它一定可以猜中。例如,只要存在哪怕一个满足约束的晚宴安排方式,或是一个满足旅行预算的行程安排,都无法逃过它的法眼,它可以在瞬间猜中。在猜出这个解以后,检查确认部分和一台普通的确定性图灵机完全相同,也即是等价于任何一个实际的计算机程序。
   COOK 证明了,任意一个非确定性图灵机的计算过程,即先猜想再验证的过程,都可以被描述成一个 SAT 问题,这个 SAT 问题实际上总结了该非确定性图灵机在计算过程中必须满足的所有约束条件的总和(包括状态转移,数据读写的方式等等),这样,如果你有一个能解决该 SAT 问题的好的算法,你就可以解决相应的那个非确定性图灵机计算问题,因为每个 NP 问题都不过是一个非确定性图灵机计算问题,所以,如果你可以解决 SAT ,你就可以解决所有 NP 问题。因此,SAT 是一个 NP-complete 问题。
    有了一个 NP-complete 问题,剩下的就好办了,我们不用每次都要和非确定性图灵机打交道,而可以用前面介绍的两步走的方法证明其它的 NP-complete 问题。迄今为止,人们已经发现了成千上万的NP-complete 问题,它们都具有容易被检查的性质,包括前面介绍的推销员旅行问题。当然更重要的是,它们是否也容易被求解,这就是著名的 P vs NP 的问题

自从我们来到这个世上,只要我们有需求那么我们就会面临问题,需求越高问题的复杂性也就越大,我们解决了的问题都不再是问题,随着我们认知的更进一步,而我们所未解决的问题就会越来越多,好像永远比我们解决的要多,那我们怎么来解决这个问题呢?…呵呵!这好像是一个无解的问题。

解空间无非就两种,一种无解,另一种有解。有解的情况下又分两种情况,一种是有算法另一种就是没有算法。

1、有解但无算法的问题:
    比如圆周率Pi的小数点后面是否有连续的100万个0。因为Pi是一个客观存在的实数,所以Pi的值是确定的,因此这个问题的解也是存在的。要么是yes,要么是no,虽然我们不知道他到底是什么,但他是客观存在的,不随时间改变,不随人的认识而改变。但是没有算法可以计算这个问题的答案。当然,可以用一种笨办法来解决这个问题,就是不停地计算Pi的小数点后面的值,如果发现了有连续的100万个0,则这个问题的答案就是yes,但是如果没有发现,我们必须一直计算下去,而且永远无法停止~~,所以这种笨办法根本称不上是算法,因为他不满足算法在有限步内终止的条件。所以这个问题是没有算法的(至少目前认为如此,也许以后可以从数论中找到某种方法来求出小数点后面是否有连续的k个0,或从概率的角度计算Pi的小数点后面的值的分布等等等等)。
2、无解也无算法的问题:
    比如给定任意一个命题,是否存在一种算法判断这个命题是真是假?这就是著名的图灵停机问题。如果存在这个算法,那么我们只要找到这个算法就可以一劳永逸了,以后无论拿到什么新的命题,都可以用这个算法来验证一下,立刻就知道该命题是真是假,这样我们就掌握了整个宇宙的终极真理。但是图灵已经证明了这样的算法是不存在的,这个问题也是无解的。(证明中主要利用了康托尔对角线删除法,就是用来证明实数和自然数不等势的那种对角线删除法)
3、可计算与不可计算:
根据图灵-丘奇论题,:
(1)可计算的问题就是能被图灵机计算的问题;(图灵的定义)
(2)可计算的问题就是使用lamda演算系统可以计算的问题;(丘奇的定义)
图灵-丘奇论题与其说是定理,不如说是算法的定义。因为算法本身就是一个不精确的概念,到底什么是算法,以前一直没有确切的定义。而图灵-丘奇论题则从数学上给出了算法的形式定义。
图灵说:所有的图灵机能计算的问题都是有算法的(也就是可计算的),所有有算法的问题都可以用图灵机计算。这个论题本身是无法证明的,它就像物理中的光速不变定律一样,是一条自然定律,不能加以逻辑上的证明,只能用实验来检验。而目前来看,图灵命题也和光速不变一样,经得住历史和时间的检验,现在即使发展到了量子计算机,还是没有摆脱图灵机的约束,量子计算机上可计算的问题也是普通的图灵机上可计算的问题,只不过计算效率不同而已。
不可计算的问题的两个例子前面已经说过了,一个是Pi的例子,另一个是图灵停机问题。
4、可证明性与不可证明性
   在一个公理系统中,有若干条公里,有一些推导规则,在系统中进行定理的证明,就是从公理出发,利用这些规则推导出新的定理。如果最终能得到我们需要证明的命题,则该命题为真;如果最终得到了和我们需要证明的命题相违背的命题,则我们要证明的命题为假。 如果把系统中所有的定理看作图中的节点,假如从定理i1,i2,..ik根据系统的规则可以推导出定理j,则从i1,i2,...ik分别连接一条到j的有向边。这样整个公理系统构造成了一个有向图。定理的证明过程事实上是在公理系统中从公理表示的节点出发,构造一颗到达目标命题节点的“证明树”。因而定理的证明就和图论中的路经搜索类似(BTW,这就是定理自动化证明的基本原理)。 超级天才歌德尔在25岁的时候提出了著名的歌德尔不完备性定理。该定理指出:在任何一个公理化系统中,如果存在着矛盾,这个系统是不完备的。所谓存在着矛盾,就是可以证明命题A成立,也可以证明命题A的否命题成立,这就自相矛盾了。所谓不完备,是指系统中存在着一些命题,无法证明它成立,也无法证明它不成立。这就好像在一个图中存在着某些孤立点,从基本的公理节点出发永远无法访问到这些孤立点。歌德尔在“不完备性定理”的证明过程中构造出了一个无法证明是真是伪的定理。具体说起来比较麻烦,我根据自己的理解将其简化为下述的简单形式:

命题A = “命题A不成立”

现在问命题A是否成立。如果命题A成立,则根据命题A的内容,命题A应该不成立;如果命题A不成立,则根据命题A的内容,命题A又应该成立。   这个例子很不严谨,因为它事实上混淆了语法和语义层次。但我觉得这个例子可以作为歌德尔的例子的一个简化版本。歌德尔的那个例子要比这个严谨和复杂得多,但实质上是差不多的,也是利用了逻辑中的悖论。罗素等人所提倡的解决这种悖论的方法就是给谓词逻辑分层次,从而产生了一阶谓词逻辑、二阶谓词逻辑等。像上面的例子,罗素认为命题A的内容描述了命题A本身的性质,这就超出了命题A所能表达的范围,他认为这样的A不是合法的命题。
   

首先,从目前的科学发展来看,这个世界应该是不确定的。否则的话就会陷入科学决定论的怪圈。20世纪以前的物理学认为自然界存在两种物质:一种是粒子,它的运动状态和运动规律可以用牛顿力学来描述;另一种物质是场,它的运动规律遵循Maxwell方程组。但无论是哪一种,他们的运动方程都由Laplace方程决定。给出系统的初始状态,通过求解运动方程,就可以唯一地确定系统在任意时刻的运动状态。按照经典物理的理论,整个世界是确定的,世界上没有真正的随机。所谓的随机只是因为我们对所需的参数认识不够而造成的。以掷硬币为例,我们如果知道了硬币的一切参数(包括质量、密度等)和外界的一切参数(包括重力,抛掷角度,抛掷力大小等),那么掷硬币的结果是完全可以通过运动方程计算出来的。将这种思想推而广之,我们的宇宙在诞生之初所有的粒子和场的初始状态都是确定的,如果宇宙的运动发展存在着规律,那么整个宇宙的发展过程在宇宙诞生之初就被完全确定了。宇宙中的任何事物,太阳系、地球、人类、甚至人类的思维等等,一切的运动变化结果,都在宇宙诞生之初就完全确定了。1819年,拉普拉斯出版了《关于概率的哲学论文》[Essai philosophique sur lesprobabilites]。拉普拉斯写道:“我们应当把宇宙的现状看作它的先前状况的结果,看作随后状况的原因。假定一位神明能够知晓使得自然生机勃勃的所有的力,和构成自然的所有物体在一瞬间的状况:对于这个神明来说,没有任何事物会是不确定的;未来会和过去一样在它眼前出现。”在1927年前大多数物理学家都同意上述见解。这种拉普拉斯决定论断言,如果给出宇宙在某个瞬间的状况、情境,宇宙在无论未来还是过去的任何瞬间的状况就是完全被决定的。这种观点在西方哲学界被称为“科学决定论”。然而,量子理论的诞生彻底打破了这种确定性!量子理论断言:我们的宇宙中存在着根本意义上的随机,这种随机不是因为参数不够无法计算造成的,而是因为时间、空间和物质之间一种未知的纠缠关系产生的。按照量子理论,人的主观意识甚至会对外界的客观实在产生影响!这就完全违背了经典的唯物主义(事实上经典的唯物主义应该进行修正,但我们的教科书上还是100年前的东西)。对于量子而言,如果人不去观测它,它处于不确定的状态;而一旦观测它,它就会陷入一个确定的状态。量子所处的状态和人的观测方式有关。从这个意义上来说,人的主观决定(选择的观测方式)将会直接影响到客观世界的量子的状态!

    其次,Pi和根号2都是无理数,但是Pi要更特殊一点,它是一个普适常量,它的物理意义显然要比根号2大得多。你恐怕曲解了NP问题的含义,NP问题通常是指没有多项式时间算法的问题,更精确地说,NP问题是指可在多项式时间内验证的问题。从这个定义上说简单的排序问题也是NP问题,因为它可在多项式时间内验证。但我们通常所说的NP问题都是指难解问题(尚未找到多项式时间算法)。Pi的那个例子和这个不同,并不是计算的复杂度太大,而是算法无法终止!哈密尔顿回路问题是NP完全问题,它还没有找到多项式时间的算法,但他是有算法的,而且这个算法可以在有限时间内终止。就算该算法的复杂度是指数级的,对于一个确定的输入这个算法可能需要算到宇宙毁灭,但它总是能终止的。而对Pi的计算,是永远无法终止的,因为它是无限不循环小数!你要搞清楚的是NP问题和不可计算问题是两回事,我们讨论一个问题可不可以计算,并不关心计算该问题的复杂度是多少,而是关心原则上是否存在能够在有限时间内终止的机械算法。而对Pi而言,没有这种算法。

    反证法本身确实存在问题。直觉主义者一直都怀疑反证法,甚至抵制反证法。他们认为形式逻辑中的公理 ~(~A) => A 并不成立。因为A的否不成立,没有理由说明A一定成立。换句话说,他们认为排中律不成立。当然,这种争论未必有结论,究竟信仰那种学派完全是个人自由。事实上这些不同的学派的理论只是在基本概念和基本体系上有差异,最终得到的高层次的定理并不相互矛盾。因为高层次的定理很容易被实践检验,如果和实践相抵触的公理话,那种学派早就不存在了。公理系统是人为规定的。事实上可以有很多不同的公理系统,比如数理逻辑中,欧洲、中国与苏联、美国这三地的学者都喜欢用不同的公理系统。不同的公理系统最终得到的高层次的定理并不会相互矛盾,这些公理系统之间可以相互推导出对方的公理,所以他们是完全等价的。使用何种公理系统也完全是个人的喜好,当然了,最好使用那种和人类直观相符合的公理系统。你也可以用和人类直观相违背的公理系统,照样能得到一些系列和实践并不矛盾的结果。著名的例子就是非欧几何的诞生,它就是违背了人类的直观,但是却开创了新的数学领域。同一个公理系统的各条公理之间是不可能相互推导的,当然更不可能相互矛盾。可以由公理推导出来的命题叫做定理,所谓系统的公理就是不能由系统内其他公理推导,但是却显然正确的命题(如果不正确该系统就会有矛盾)。逻辑究竟怎么划分目前似乎也无定论。

    最后,计算显然是离散的。原来人类以为世界是连续的,量子理论告诉我们世界也是离散的,这个世界上没有真正的连续,都是一种离散的近似(就好像整个世界是Matrix中的计算机模拟出来的一样^o^ )。例如,在本世纪初,按照经典物理的电磁辐射理论,人们无法解释黑体辐射能量密度按照频率分布的实验结果。于是Plank提出光是以离散的形式辐射出来,每一份辐射是一个光量子,它的能量为ε=hv,其中v是辐射频率,h是Plank常数。Einstein通过分析光电效应则意识到:电磁辐射不仅发射和吸收是以量子形式进行的,而且传播也是以量子形式进行的,Einstein认为辐射场本身就是由光量子组成,每个光子的能量就是ε=hv。所以能量具有最小的单位,能量是离散的。现在普遍认为整个世界都是离散化的。离散数学一定要好好学习,这是计算机科学的基础。

程序员到底要走多远,没有一定的标准。事实上不懂相对论,不懂量子理论并不妨碍你成为优秀的程序员。但是我认为作为一个21世纪的现代人,这些常识性的科学知识还是应该了解的,否则怎么能体现出我们和100年前的人的区别?仅仅是为了满足人类的好奇心,也有必要了解一下最新的科学知识。

   程序员有很多种,有的就像盖房子的民工一样,只会砌砖头,就算他再熟练,经验再丰富,也只能砌砖头;有的就像包工头一样,可以搞管理;有的就像建筑设计师一样,可以做设计;还有的就是那些科学家了,他们研究物理、研究材料、研究如何才能盖出更好的房子,他们的研究不是针对如何建造某幢具体的大楼,而是影响全人类的建筑水平。究竟做那种人,取决于你自己的定位。

 

原创粉丝点击