图灵机是阿兰图灵在解决可计算数判定性问题时,提出的一种解决方法,图灵在论文中使用到了该计算机器。
刨去图灵机的分类和形式化的定义,图灵机执行一系列的状态变化。把只包含0和1的字符串输入到图灵机中,图灵机依次根据字符串的每个字符,来决定下一个的状态,当然需要有一个初始状态,机器从初始状态开始运行,把初始状态称为状态0,图灵机依次处理每个输入的字符,例如遇到字符0,跳转到状态1,遇到字符1,跳转到状态2,而在状态1和状态2,同样对输入的字符执行规定的状态变化。
可以想象,图灵机处在某个状态时,可能会遇到字符0,也可能遇到字符1。遇到字符后,可以到另外的某个状态,也可以停留在当前状态。例如,在状态23,遇到1,则转移到状态18,遇到0,则转移到状态23。
图灵机好比一个处在队列训练中的士兵,听从命令作出动作。当士兵处在立正状态时,教官喊口令:稍息,士兵从立正状态到稍息状态。把将官的口令当做输入给士兵的,包含0和1的字符串,士兵根据当前是0还是1,作出动作。
图灵机处在当前状态,会遇到0和1,它有两种选择,当然这两种选择可以是一样的。比如,无论是遇到1还是0,均停留在当前状态,或者均改变到同样的另一个状态。那有多少种可能,从别的状态,转变到现在的状态呢?很明显,是不确定的,这要取决于图灵机的定义,而这种定义,完全可以人为地控制。
把输入的0和1放到传送带上,依次输入到图灵机。例如传送带上放着01001,图灵机是可以人为定义的,也就是“确定”的,这种确定指的是,同样的字符串,输入到图灵机中,每次得到的结果是相同的。图灵机可以在状态转换时,进行操作,例如打印字符0或1,比如,定义这样一个图灵机,它只有一个状态A,在状态A,接收到符号0,则打印符号0,并进入状态A,接收到符号1,同样进入状态A,例如将01001从右往左输入到图灵机,那么输出的结果是10010,这里面还有一个操作,就是在打印符号后,传送带要进行移动,进行左移或者右移,也就是完整的操作是,打印符号,移动或者不移动。在图灵机中,不是传送带移动,而是读写头的移动,把读写头当做人的眼睛,当有一排0和1的字符串时,眼睛一次看到一个符号,眼睛的视线可以向左,亦可以向右移动,当然也可以不移动,这是图灵机所规定的。
总结下图灵机的组成。它有状态,在每个状态遇到0和1时,有规定的操作,以及要进入的下一个状态。把当前的状态,操作(包括打印,左移或者右移,或者不移动),以及要进入的一个状态,看成一个指令,图灵机可以包括很多的指令,图灵机的确定性,在面对同样的输入字符串时,会得到相同的结果。无论该计算机器在何时、何处运行,只要输入的字符串相同,那么打印的结果是相同的。
如何实现一个图灵机?
丢掉现在所学的计算机理论知识,假如有一个人为定义的图灵机,如何创造这样一个图灵机实物?我想不到任何的机械方法,只能人为地去一步步的计算。把人看做一台实现图灵机器的实物,再合适不过。当然,现在大家都知道,现代计算机经过了电子管计算机,晶体管计算机,集成电路计算机。
继续思考和想象,该怎样实现图灵机,或者需要怎样的条件实现图灵机。我在这里想象一台非正常的图灵机,也就是这台机器和图灵机很像,但可能是定义的图灵机,也可能和定义的图灵机不同。以模块进行划分,需要一个存储模块,用来记录当前的状态:某个状态;一系列操作,例如在当前状态下,做哪些操作(打印字符,左移或右移);输入的字符串,这个也可以不存储,可以一个一个将字符输入给图灵机,图灵机需要读取当前输入的字符;存储模块还需要记录打印的字符,也就是输出的字符串。整体把这些都使用一个假想的存储模块实现。有了存储还不够,例如打印,左移和右移,读取输入字符,这些假设使用一个功能模块实现,实现这些功能的名称就叫功能模块吧,随意一些。其中对于读取字符、左移和右移,给实现这些操作的工具取个名称:读写头。有了存储模块和功能模块,就可以实现一个图灵机了。把这个机器叫做T机器吧,存储模块叫做Memory,功能模块叫做Functions。
对操作命令的存储。一条完整的操作命令,应该包括哪些内容呢?T机器的当前状态,输入的字符,操作(打印,读写头的左移或右移,或者不移动),下一个状态。那这样就不需要存储图灵机的状态了,但是需要存储T机器当前的状态(或者初始状态),这样遇到一个输入的0或1字符时,就Memory中寻找唯一的操作命令,操作命令中的当前状态和输入的字符,唯一确定一条应该执行的操作命令。当两条操作命令的当前状态和输入字符相同时,T机器就不能称为T机器了,为什么会这样呢?或者说为什么T机器中存在两条或超过两条的操作命令,当前状态和输入字符均相同,T机器就失效了呢?前文提到了图灵机的“确定性”,这个确定性是人为规定的,而上述的两条命令,使得T机器不知道该怎么办。就像爸爸让你吃馒头,妈妈让你吃米饭,就会陷入迷惑的状态。而我们创造出来的T机器不能存在这样的情况。
有了对操作命令的存储,其实就解决了很多很关键的问题。把T机器的操作命令,做成一个表格,写到纸上。在T机器的组成中,有个模块叫做功能模块,对于我们想要的功能,它均可以实现,存在悖论的地方是,它不能实现一个图灵机。在Memory模块,有单独的地方存放初始状态。然后,我们就“造”出了这样一台T机器。
让T机器开始运行。将一串要输入的01字符,写到一条横着的纸带上,这个纸带左右是没有边界的,T机器只需要使用其中的一段,这一段有字符0或1。将T机器拨回到它的初始状态,也许它已经运行了一次呢。Functions模块使用读写头读取一个字符,同时在Memory模块中,搜索匹配的操作命令,匹配是指当前状态和读取到的字符,与操作命令的当前状态和字符匹配,然后Functions模块执行操作命令中的操作部分,打印或不打印,左移、右移或不移动,根据操作命令修改当前状态。什么时候T机器会停止?一种情况是在Memory模块中,搜索不到匹配的操作命令,这是不太可能的,T机器如此笨拙,它会在Memory模块中,保存着这样的两条操作命令,当前状态相同,而输入字符是0和1,因此,T机器总会搜索到匹配的操作命令。更可能的情况是,在某次执行操作命令后,左移或右移后,读取不到字符了,刚才说到纸带向左和向右是无限延伸的,而T机器只处理了一部分,这一部分存在字符,也有可能存在没有处理的字符,例如,从左到右开始读取后,在初始状态,搜索到的操作命令中的操作是左移,而有字符的最左边的左边是空白,T机器就搜索不到匹配的命令,这时候T机器运行终止。
这样一台理想化的T机器能做些什么呢?因为我们还没有用实物创造出来,不知道用什么材料能制作这样一台理想化的T机器。那就接着想象下,它可以用来做些什么?例如,最简单的例子,T机器仅用来打印输入的字符,称它为P_T吧,P_T机器该如何定义呢?只要有一个状态就可以了,例如Q0,有两条操作命令就足够了,第一条是在Q0状态,读到0,打印0,左移,进入Q0状态;第二条命令,在Q0状态,读到1,打印1,右移,进入Q0状态。这样的机器似乎没有什么新奇的。对机器P_T进行升级,这次叫做P1_T,机器P1_T的作用是打印输入字符的相反字符。它和机器P_T的不同在于操作命令的不同,P1_T在读到字符0时,打印1,在读到字符1时,打印0,同样都进行右移。
我们把图灵机的功能,进行了模糊的描述。这种描述和实现与定义的图灵机是不符的,在图灵的论文《论可计算数及其在判定性问题上的应用》中,图灵是从最简单的计算机器开始描述,定义了符号、格局等概念。第一个计算例子是打印010101...的机器。随后又举了几个计算机器的例子。
图灵机的神奇之处在哪里。似乎,人人都可以想到这样一台机器,在那个年代,机械的机器已经存在,在能量的驱动下做机械运动,完成特定的生产需求。在中国,那是算盘也是存在的,也有可能是算盘的存在,导致人们没有去创造更精巧、功能强大的计算工具。图灵机是抽象的计算“可计算数”的机器,这种抽象才是图灵机被想象出来的神奇之处,而最神奇的是,图灵机按照特定的指令进行运行。可能有人心里会想象到这样的一台机器,但没有写下来,或者认为不可能有材料会实现这样的神奇机器。
理解图灵机对理解现代计算机运行原理有着很大的帮助。比如计算机中的寄存器,寄存器用来临时存储数据,主存用来存储指令和数据,CPU中的ALU部件进行计算。
这节介绍了一个模糊的图灵机,并没有做精确的定义。下节介绍关于汇编语言的概念。