all_lessons/数学的逻辑/18第 19 课 / 共 44 课

第六部分 · 现代地基:连续、大小与计算

图灵机与可计算:从“证不出”到“算不出”

上一课,测度论给"大小"和概率上了锁。三块现代地基还差最后一块——计算。哥德尔刚刚证明了"真却证不出",划清了证明的边界;而在 1936 年,一个 24 岁的年轻人图灵把同一个问题重问了一遍,只不过换成了机器的口吻:一台纯粹机械的装置,究竟能算出什么?为了回答它,他顺手发明了抽象的计算机——整个课程后半程,都要在这台机器上运行。

线性回顾
上一课:测度论用 σ-代数与可数可加性,给"长度/面积/体积"和"概率"上了严格的锁,补齐了积分与概率的地基。
留下的问题:现代地基已经有了两块——拓扑给了邻近第 16 课),测度给了大小第 17 课)。可还有一件贯穿全课、却从没被钉死的东西:什么叫"按规则一步步算出来"?哥德尔(第 15 课)证明"真"盖不满"可证",但"可证""可算"这些词,本身还含糊着。
本课新增:图灵机(把"机械计算"钉死成一个数学模型);丘奇–图灵论题(凡是"能行可计算"的,就等于图灵机可计算);停机问题(用和康托尔、罗素、哥德尔同一个对角线自指,证明有些东西算不出来);通用图灵机(一台机器跑所有程序——存储程序计算机的种子)。
本课路线
(1) 希尔伯特的判定问题:有没有一套机械办法,判定任意数学命题?(2) 图灵机——用纸带、读写头、状态、规则表,把"机械计算"钉死。(3) 丘奇–图灵论题:这就是"计算"本身的定义。(4) 停机问题:没有程序能判定任意程序会不会停——同一个对角线再演一遍。(5) 通用图灵机:程序即数据,一台机器跑所有程序。(6) 从"极限"到"机器":哥德尔与图灵是孪生兄弟,而看清极限之后,数学转身造出了机器本身。

希尔伯特最后的问题:能不能"机械地"判定一切

希尔伯特的野心,我们在第 15 课见识过:他想给数学找一套完备、自洽、能自证清白的地基。哥德尔从"完备"和"自证"两处把这个梦炸开了。但希尔伯特的清单上,还剩一个更具体、更诱人的问题,叫判定问题(德文 Entscheidungsproblem,字面就是"判定的问题"):

判定问题(Entscheidungsproblem)
有没有一套机械的、一步步照做就行的程序,输入任意一句一阶逻辑命题,它能在有限步内输出"这句可证"或"这句不可证"?换句话说:能不能造一台"数学判官",喂给它任何命题,它保证给出是非答案?

这个问题诱人,是因为它听起来像工程而不是哲学——仿佛只要够聪明,总能设计出这样一套流程。可图灵敏锐地意识到:要回答"有没有这样一套机械程序",你首先得说清楚"机械程序"到底是什么。在他之前,"按规则一步步算"是每个人都会、却谁也没有精确定义的东西。你没法证明"某种机械程序不存在",除非你先把"机械程序"这个概念本身钉死。图灵这一钉,钉出了一台机器。

图灵机:把“机械计算”钉死成四样东西

图灵做了一件极朴素的事:他去想象一个人用纸和笔死板地算题,然后把这个过程剥到不能再剥。剥完之后,"机械计算"只剩四样东西——

就这些。没有屏幕,没有鼠标,没有 CPU。一台图灵机就是这样一个四元组:纸带、头、有限状态、规则表。它运行时做的事,简单到近乎笨拙:读当前格 → 查表 → 写、挪、换状态 → 重复,直到进入停机状态就停下。

震撼之处
就这么一台笨机器,图灵论证:它能算出的东西,穷尽了我们说"算法"时所指的一切——加减乘除、判断素数、排序、下棋的每一条规则……凡是能写成"一步步照做"的过程,都能被某台图灵机执行。抽象的计算机,在这里诞生了——比世界上第一台物理计算机还早了将近十年。物理计算机后来只是把这个数学模型,用电路造了出来。

丘奇–图灵论题:这就是“计算”的定义

图灵机把"机械可算"钉死了。可你也许会怀疑:会不会有某种更聪明的计算方式,图灵机做不到,别的模型却能做到?历史给出了一个惊人的巧合。几乎同时,逻辑学家丘奇(Alonzo Church)用一套完全不同的语言——λ-演算(把一切都看成"函数作用在函数上")——也定义了一遍"可计算"。还有人用"递归函数"定义了第三遍。

结果三者被证明完全等价:凡图灵机能算的,λ-演算能算,递归函数也能算,反之亦然。此后人们又试了无数种计算模型(各种编程语言、各种理想机器),没有一个能超出图灵机的能力范围。于是有了这条论断:

丘奇–图灵论题
一切"能行可计算"(凭一套明确规则、一步步机械照做就能完成)的东西,恰好就是"图灵机可计算"的东西。
不是一条定理("能行可计算"是个直觉概念,无法在纸上被证明);它是一个关于"计算"这个词该怎么定义的约定。我们等于是说:"计算",就定义为图灵机能做的事。之所以敢这么大胆,是因为几十年来所有尝试都撞到同一堵墙——你今天手机里的任何 App,能算的也绝不会超出一台图灵机。

停机问题:有些东西,算不出来

钉死了"计算",图灵就能回答希尔伯特了——而回答的方式,正是这门课反复出现的那记杀招。先看一个具体又致命的问题,叫停机问题

停机问题
能不能造一个"万能检查器" H——它本身也是个程序——输入任意一个程序 P 和它的输入,H 保证在有限步内正确回答:"P 跑这个输入,最终会停下来,还是永远死循环?"

这需求太合理了——谁不想有个工具,提前告诉你代码会不会卡死?可图灵证明:这样的 H 根本不存在。证明用的,是康托尔(第 13 课)对付实数、罗素与哥德尔(第 14 课第 15 课)对付集合与证明的同一把钥匙——对角线自指

第一步,假设它存在。假设真有这么个万能检查器 H(P, 输入),它总能正确答"停"或"不停"。既然程序可以把另一个程序当数据读进来(这一点下一节的通用机会兑现),我们就能拿 H 当零件,拼一个专门捣乱的新程序 D

第二步,造一个反叛者 D。D 只接收一个程序 P(把 P 自己的代码也当作它的输入喂进去),行为故意拧着来:

D(P):先问 H —— “P 喂给自己会不会停?”
  若 H 说“会停” → D 就故意进入死循环(不停);
  若 H 说“不停” → D 就立刻停机

(读作"D 拿到程序 P,先用检查器问'P 喂自己会不会停',然后反着做:说会停我就不停,说不停我就停。")注意 D 完全是用现成的 H 拼出来的,所以只要 H 存在,D 就是一个货真价实、能跑的程序。

第三步,把 D 喂给它自己。现在问一句要命的话:D(D) 会停,还是不停?——这就是对角线上那一格,让机器去评判"它自己"。两条路,都撞墙:

撞墙:D 停 ⇔ D 不停
假如 D(D) 会停。D 内部调用的 H 一定回答了"会停"。可按 D 的规矩,H 说"会停"时 D故意死循环——即 D(D) 不停。矛盾。
假如 D(D) 不停。H 一定回答了"不停"。可 H 说"不停"时 D立刻停机——即 D(D) 会停。又矛盾。
于是 D(D) "停"也不是、"不停"也不是。唯一的漏洞,是最开始那个假设——万能检查器 H 根本不存在。停机问题不可判定

请把这条脉络看清楚,它是这门课思想史半程真正的主心骨:

同一记杀招,演了四遍
康托尔第 13 课):沿清单对角线造一个"每一位都不同"的新实数 → 它不在清单里 → 实数不可数
罗素第 14 课):问"不含自己的集合"的集合含不含自己 → 朴素集合论崩塌。
哥德尔第 15 课):造一句"我不可证"的命题 G → 系统必不完备
图灵(本课):造一个"和 H 的判断反着来"的程序 D,把它喂给自己 → 停机问题不可判定
四个人,四个领域,同一个动作:让一个系统去评判"它自己",构造一个恰好违反自身判断的对角线个案,逼出矛盾。康托尔限制"大小",罗素限制"集合",哥德尔限制"证明",图灵限制"计算"——一条自指的引擎,从头贯穿到尾。

顺带,希尔伯特的判定问题也就此有了答案:如果存在那台"数学判官",就能用它去判定"某程序是否停机"这类命题——可停机问题不可判定,所以判定问题的答案是"不存在"。数学没有万能判官。

通用图灵机:一台机器,跑所有程序

如果本课只有坏消息,那就辜负图灵了。他最深远的贡献,恰恰是一个建设性的想法,而且它就藏在刚才那句"程序可以被当作数据读进来"里。

到目前为止,每台图灵机都专机专用:一张规则表只会干一件事(比如"给数加一")。图灵却问:能不能造一台通用机器 U,它不为任何特定任务而造,而是——你把另一台机器 M 的规则表,当成符号写在 U 的纸带上(这叫 M 的"描述"),再在旁边写上 M 的输入,然后 U照着这份描述,一步步模拟出 M 的运行

图灵证明:能。这台机器叫通用图灵机。它带来的观念转变,怎么强调都不过分:

程序 = 数据
在通用机眼里,"程序"和"数据"是同一种东西——都是纸带上的符号串。一台机器(U 的硬件是固定的),却能通过读取不同的"程序描述",变成任意一台机器。这正是你手上这台笔记本的秘密:CPU(硬件)一次造好、永不改变,可它读入不同的程序,就能当浏览器、当播放器、当游戏机。这就是"存储程序计算机"的数学种子——冯·诺依曼架构、乃至你眼前这块屏幕背后的一切,都发芽于图灵 1936 年的这张纸带。

下面这台微型图灵机,不模拟别人,而是老老实实亲自跑一个程序,让你亲眼看它一格一格地计算,然后准时停下来——一个"会停机"的活标本。

微型图灵机:亲手跑一台会停机的机器
这是著名的 3 状态 2 符号「勤劳海狸」(BB-3)。纸带符号 {0,1},状态 {A,B,C} 外加停机。规则表(当前状态,读到 → 写,移动,下一状态):A,0→1,右,BA,1→1,左,CB,0→1,左,AB,1→1,右,BC,0→1,左,BC,1→1,右,停机。起点:全 0 的空带、头在第 0 格、状态 A。点"步进"看它一步步算;它会在第 13 步准时停机,纸带上留下六个 1——看它先算、再停,正是一台图灵机最朴素的一生。三角标是读写头,指着当前格。
当前状态
A
已走步数
0
磁带上 1 的个数
0

从“极限”到“机器”:转身造物

把哥德尔和图灵并排放,你会看到一对孪生兄弟。哥德尔说的是证明的极限——有真命题,永远证不出来(真却证不出)。图灵说的是计算的极限——有明确的问题,永远算不出来(问却算不出)。它们不是各说各话,而是同一件事的两张面孔:都用对角线自指,都得出"机械的确定性有一道逃不掉的边界"。哥德尔从"证"的一侧撞见这堵墙,图灵从"算"的一侧撞见同一堵墙。

可图灵这一侧,还带回了一份哥德尔那侧没有的正面大礼。看清"算不出什么"的同一套思考里,他造出了通用图灵机——那台能读程序、能模拟一切的机器。数学在这里完成了一次漂亮的转身:看清了极限,转过身,把机器本身造了出来。

一句话带走
图灵把"机械计算"钉成一台数学机器(纸带 + 读写头 + 有限状态 + 规则表),并借丘奇–图灵论题把它立为"计算"的定义。用和康托尔、哥德尔同一个对角线自指,他证明停机问题不可判定——哥德尔限制"证明",图灵限制"计算",二者是孪生兄弟。但他还造出了通用图灵机:程序即数据,一台机器跑所有程序——这正是你手上这台计算机的数学种子。看清了极限的数学,转身造出了机器本身。

常见误解

下一步
三块现代地基——连续(拓扑)、大小(测度)、计算(图灵)——齐了,能跑程序的机器也有了。而哥德尔与图灵联手告诉我们一件事:别指望从系统内部把一切都证明干净、算尽算绝。那就换个思路——不再追求先验的、板上钉钉的确定性,而是让机器从数据里"学":给它一堆例子,让它自己找出规律。这个"从数据中学习"的念头,要先被翻译成一道精确的数学题,才谈得上求解。后半程,就从这里开始。→ 第 19 课《学习问题:把"从数据中学习"变成一道数学题》。