图灵·停机问题的不可判定性

停机问题的不可判定性:

不存在一个图灵机可以判定任意图灵机在所有输入上是不是停机。

在现代编程语言(这个语言是图灵完备的)的表现就是,没有一个程序可以判断所有程序是否能在有限时间结束。


图灵机和图灵可计算

计算就是依据一定规则,对符号串变换的过程。计算的目的由算法实现,算法的执行由计算完成。

对算法的兴趣主要基于这样一个事实:人类做一件事的过程总是可以被视为一个计算,而人类的行为似乎都可以被算法描述。这样一来算法似乎可以描述人类的行为限度,也就是说人类的能力究竟能够做到什么。

直观上看,算法的这种描述能力并不令人惊讶。因为人的思维总是一步步的,或者即使是并行的思考,那也可以通过一定的手段变成串行思考。并且,人的思维总是花费有限时间,这与算法的有限性相一致。

但是这种直观的说明,并没有实际说明能力,算法的能力不在于操作的步骤和时间的有限性,而在于原子操作的能力,比如,对于很多人来说,‘看’基本上就是一个原子操作,对于人类行为的描述中,如果还要把看分解成几个步骤,那并不是算法的焦点,可是也有人或者生物无法完成‘看’,算法并没有给出这种差异的说明。

与此相关的有个笑话: 介绍一个现今最流行的一个解决问题的算法,它因著名量子物理学家理查德·费曼(Richard Feynman )最早使用而得名。这个算法不仅功能强大,而且包含了解决问题所需的全部因素。费曼利用此算法解决了量子力学方面的诸多难题。 下面是费曼算法的详解。 1.把问题写到黑板上; 2.冥思苦想; 3.把答案写到黑板上。 由此可以看出原子操作有多重要!

算法预设了原子操作的简单性,或者从某种角度上看,算法的全部能力来源于原子操作究竟有多强大,可以设想一种机器(这被图灵称为神谕机器),它有一种原子操作:给出一个问题,他会给出答案。如此一来它的能力是无限大的。

那么对于人来说,原子操作究竟定义成什么程度比较好?在这一点上算法有点无能为力。但图灵认为,就数学计算而言,图灵机抓住了全部,图灵意义上的算法就是一个图灵机的停机计算。

“图灵机”是一种理想中的计算模型,它的基本思想是用机械操作来模拟人们用纸笔进行数学运算的过程。通俗地讲,图灵把“计算”这一件日常的行为抽象概括出来,看作是下列两种简单动作的不断重复(值得注意,这两种操作就是图灵认为的原子操作)。

  • 1)在纸上写上或擦除某个符号。

  • 2)把注意力从纸的一个位置移动到另一个位置。

在每个动作完成后,人要决定下一步的动作是什么,这个决定依赖于此人当前所关注的纸上某个位置的符号和此人当前思维的状态。为了模拟人的这种运算过程,图灵构造出一台假想的机器,该机器由以下几个部分组成。

  • 一条无限长的纸带TAPE。纸带被划分为一个接一个的小格子,每个格子上包含一个来自有限字母表的符号,字母表中有一个特殊的符号“_”表示空白。纸带上的格子从左到右依次编号为0,1,2, …,纸带的右端可以无限伸展。

  • 一个读写头HEAD。该读写头可以在纸带上左右移动,它能读出当前所指的格子上的符号,并能改变当前格子上的符号。

  • 一套控制规则TABLE。它根据当前机器所处的状态以及当前读写头所指的格子上的符号来确定读写头下一步的动作,并改变状态寄存器的值,令机器进入一个新的状态。

  • 一个状态寄存器。它用来保存图灵机当前所处的状态。因为寄存器数量是有限的,所以图灵机的所有可能状态的数目是有限的,并且规定有一个特殊的状态,称为停机状态,代表计算完成。

当一个新的计算模型出现时,人们会判定它是否能解决所有图灵可计算的问题,如果是,它就被称为是图灵等价或者图灵完备的。今天,我们称某种程序设计语言是图灵完备的,意思也是所有图灵可计算的算法都能够用这种语言来实现(如今天常见的C、C++、Java、JavaScript等都是图灵完备的,而HTML/CSS这些语言则不是图灵完备的)。

分析

在图灵看来,状态和指令都是由有限符号组成的有限集合(这意味着图灵机的个数是可数的,图灵机被自然数编码),输入和输出也是由有限字符组成的(这意味着输入和输出可以由自然数编码),这一点看似很直观,如果一个机器的状态和指令是无限的,这究竟是什么意思?即使状态数量是无限的,那么机器如何在有限步内到达无限的状态?机器也不能在有限步操作执行无穷的指令。

但是这种定义说明,图灵机简单说来,就是从自然数到自然数的一个函数的计算。由于图灵机的数目是可数的,但是自然数到自然数的函数是不可数的,这意味着图灵机在被定义之后,就意味存在自然数到自然数的函数,他不是图灵可计算的。

[可数和不可数的简单讨论可见 fjql:哥德尔不完全定理 ]

自然,停机问题并不让人惊讶,因为可数和不可数差距太大,相比较而言,大部分问题都不是图灵可计算的(可以参考有理数比较于无理数)。

但为什么突然会出现这种情况,以至于大部分问题都不是图灵可计算的?到目前为止,定义在人看来是如此的合理,人类直观上理解的可计算也是有限步骤的,看起来图灵似乎抓住了要点。突破这一点的关键在于说明,图灵认为的原子操作并不包含所有的计算原子操作,这一点在之后讨论。

【实际上有一点很关键,人类使用有限符号描述数学,数学中却出现了‘不可数’这样的表达,这是怎么做到的?这是因为人类把一个未完成的集合作为一个已完成的整体,这种作为的合理性基于划分集合的规则的可靠性,只要做到加入新的元素不会扰动之前的分类就(至少到目前为止)不会产生矛盾,而贝里悖论的分类就会产生扰动,庞加莱在《最后的沉思》中区分了两种分类方式。

人类可以使用‘所有图灵机’这样的句子,图灵机能够这样操作吗?从判定的角度来说,图灵机可以判定一个字符串是不是图灵机,但这和‘所有图灵机’的用法似乎并不一样,人类在表达图灵机整体的性质,他必须是可数无限的,然而人类却用可数符号描述出不可数的函数集合和不可计算的函数,这是两种视角的切换,有可能和斯科伦悖论很像。

一方面人类产生的所有句子确实是可数的,而且还是有限的,但是人类语言就像是元数学语言,在描述一个数学世界,这个数学世界相对自己,句子是不可数的,这种层次的错乱似乎依旧有待阐明,虽然很可能这只是一场智力游戏。

应当注意,人类说的无限只是具有不断加入的能力,这是一种动态的无限,它可以被规则表达,但是仅仅是一个分类的、属性的规则并不能说明无穷集合本身,还需要一些公理约束,比方说‘这些规则总是有效的’、‘0不是任何数字的后继’。所有的判断最终基于直觉,但是直觉却难以被阐述,这又把一切引向 操作和功能。】

对角函数不是图灵可计算

假设图灵机编码为 M_1,...,M_n,对应于计算f_1,..,f_n ,这些函数都是N\rightarrow N ,注意图灵机在一个输入(被编码为自然数)不停机,那么图灵机计算的函数在这个自然数上就没有定义,所以这些函数可能是部分函数。

定义对角函数d(n):

  • 如果 f_n(n)有定义且 f_n(n)=1,那么d(n)=2。

  • 其它情况,d(n)=1。

这意味着d(n)不等于任何一个 f_n(n),从而对角函数不是图灵可计算的。

停机函数不是图灵可计算

停机函数h(m,n)判断图灵机M_m在输入n后是不是停机,如果不停机h(m,n)=0,如果停机h(m,n)=1。

假设图灵机H计算停机函数,那么可以构造图灵机D,如果H(n,n)输出0,那么D输出1;如果H(n,n)输出1,再计算 f_n(n),看他是不是等于1(这个时候由于是停机的,那么必然有限步结束),如果等于1,D输出2,不等于1,D输出1。

这样D计算了对角函数,但这是不可能的,从而停机问题不是图灵可计算。

讨论

看起来对角函数是直观可计算的,因为定义似乎给出了算法,但是如果真要计算对角函数,必须计算 f_n(n),即图灵机 M_n输入n后的输出,但问题在于这个图灵机可能不停机,这样无论等多久都不会计算成功。

但这种说法真的有说服力吗?因为现在的情况是一个特定的图灵机,而不是全部图灵机,没有什么理由可以说明人类不能使用一种算法判断这个特定的图灵机是不是会停机,如果人类能够分析图灵机的结构,那么实际上人类能够计算出 f_n(n) 或者说明它没有定义。

这样一来实际上对角函数是可以被计算的!因为对于任何一个特定的图灵机,都可以找到一个一个算法判定它是否停机,对角函数也就被算出来了。当然这个程序如果要被图灵机计算,需要无限的状态,但这不影响对角函数是可以被计算的。

实际上可列无限带来了实际的能力增强,因为把可列个函数的可列个值都按照一张表排列出来,那么一个图灵机就可以在这个纸带上查找任何函数的值,停机问题也就解决了。

这里的讨论说明了

  1. 要么有一个特定的图灵机,它的停机就是不可被人类判定的,这意味着人类永远不知道它在某些输入是不是会停机(实际上有很多简单的程序现在还不能找到一种算法进行分析,比如3x+1问题)。

  2. 要么图灵机对于状态和指令的有限限制是不合理的,虽然直观上看是合理的,但是由于这里是对于数学的证明,数学中并不在意无穷是不是能被完成,数学默认了(无穷多个)自然数的存在,为什么不能默认这种无穷的机器的存在?

  3. 要么,图灵可计算不是人类的能行可计算。

实际上还有一点,那就是人类知道了对角函数的存在,它不被图灵机计算,如果人类是图灵机,这又怎么实现?这一点和哥德尔定理不同,哥德尔定理判断的系统可以不断扩充,但是图灵机是一个确定的系统,如果要说明人类只是图灵机,那么必须说明如何从图灵机的角度‘知道’这个对角函数。

另外,这种命题的实际应用是很难说的,实际中存在无限吗?如果没有无限,那么谈论的就没有什么效益了,看起来这和之前对于集合的讨论是一样的,虽然‘所有的集合’在人看起来很直觉,它可以被视为一个集合,但实际上这和人类的思维冲突,蕴涵集合包含自身这一荒谬的结论,停机问题有可能也是如此。

再回到之前的讨论,人类如何找到一种有限的算法,判断一个特定的图灵机是否停机(实际上这个图灵机确实在某些输入是要运行无限的时间)?这种分析能力似乎就不是图灵机刻画的,分析能力代表的原子操作就不只是改写纸带和转移注意力能够做到的,还有被一些人称为直觉的一种东西,直觉似乎也不是图灵机能实现的。

总之,这是康托尔以来一直未能被讨论清楚的东西,人类如何处理可数和不可数,以及这意味着什么,这依旧有待于未来的认识。

图灵机如何判定自己

停机问题要求图灵机不能判断所有图灵机,这一点本身让人困惑,毕竟这样一来图灵机要判断自己。不过判断自己并不是不可能的,为了形象化,图灵机可以视为一个程序。

一个程序A可以通过被存储的程序文本来访问自己,这样看来任意对于A来说,他不认识这个文本是不是自己,实际上任何一个(正确的)程序文本对于A来说都一样。所以从这个角度看A可以判定自己,当然这里A实际上也不算真的判定自己,这里区分了运行的A和被作为数据的A。

那么是不是意味着有一个特殊的图灵机,它可以判定很多(甚至除了自己以外的所有图灵机)图灵机是否停机?这一点比较麻烦,确实可以说,有一个图灵机可以判定更有意义那部分的程序是不是停机,似乎并不能否决这种可能。

所以停机问题的不可判定并没有人们想的那么强大,在很多领域中,人类确实可以期望,存在一个程序可以对这个领域的全部程序进行判定(比如限制最大长度的程序,即超过1GB的程序会被判为非法)。

彭罗斯:如何超越算法

假定我们有某一个算法,它有时有效地告诉我们什么时候一台图灵机将不停止。我们用H来标志这个算法(图灵机),但是现在允许该算法有时不能告诉我们一台图灵机在实际上将不停止:

图灵·停机问题的不可判定性_第1张图片

□表示不停机

当Tn(m)=□时H(n;m)=□是一种可能性。实际上存在许多这种算法H(n;m)。[例如,只要Tn(m)一停止,H(n;m)就能简单地产生1,尽管几乎没有什么实际的用处!]

除了不把所有的□用0来取代而留下一些以外,我们可以仔细地顺着图灵的步骤,对角线过程提供了对角线上的第n个元素1+Tn(n)×H(n;n)。只要H(n;m)=□,我们就将得到一个□。注意□×□=□,1+□=□。

把计算H(n;m)放在Tn对m作用之前;然后只有如果H(n;m)=1时(也就是说,只有如果计算Tn(m)实际上给出一个答案时),我们才允许Tn作用到m上,而如果H(n;m)=0(也就是如果Tn(m)=□),则简单地写为0。

这是一个完好的计算,所以它是由某一台,譬如讲第k台图灵机得到的,而且现在有: 1+Tn(n)×H(n;m)=Tk(n)。

我们看第k个对角元素,也就是n=k,就会得到:1+Tk(k)×H(k;k)=Tk(k)。

停机问题的不可判定性也可以如此证明,不过对于不停机的情况H会确定的输出0,由此这个式子无法满足。 因为如果Tk(k)停止,我们就得到了不可能的关系式:1+Tk(k)=Tk(k),[由于H(k;k)=1],而如果Tk(k)不停止[这样H(k;k)=0],我们有同样不协调的结果:1+0=□,

如果计算Tk(k)停止,我们就有了一个矛盾[由于假定只要Tk(k)停止H(k, k)就为1,则方程导致不协调性:1+Tk(k)=Tk(k)。所以Tk(k)不能停止,也就是:Tk(k)=□。

但是,算法不能“知道”这个。因为如果该算法给出H(k, k)=0,则我们应该又导致矛盾(我们得到了在符号上不成立的关系:1+0=□)。这样,如果我们能找到k,就将知道如何去建造击败我们知道其答案的算法的特别计算!

我们怎么找到k呢?这是一项艰巨的工作。我们需要做的是仔细考察H(n;m)和Tn(m)的构造,然后仔细弄清1+Tn(n)×H(n;n)作为一台图灵机是如何动作的。我们发现这台图灵机的号码为k。要把这一切弄透彻肯定是复杂的。但它是可以办得到的。由于这种复杂性,若不是因为我们为了击败H而特地制造Tk(k)的这个事实,我们对计算Tk(k)毫无兴趣!重要的是,我们有了定义很好的步骤,不管我们的H是哪一个,该步骤都能找到合适的k,使得Tk(k)击败H,因此这样我们可以比该算法做得更好。如果我们认为自己仅仅比算法更好些,也许会给我们带来一些小安慰!

你可能感兴趣的:(思想,算法,学习)