§1–2:讲义 PDF p1–33(页脚 1–32);教材 §1.1–1.5(书 p5–20,PDF p18–33) §3:讲义 PDF p34–48(页脚 33–47);教材 §1.5 末(s-m-n、递归定理,书 p19–20)、§1.6(书 p21–24,PDF p32–37) §4–5:讲义 PDF p49–67(页脚 48–66);教材 §1.7–1.8(书 p24–28,PDF p37–41) §6–7:讲义 PDF p68–82(页脚 67–81);教材 §1.12–1.13(书 p37–41,PDF p50–54)
计算复杂性理论按”解决问题需要多少资源”给问题分类。本讲只看一种资源:时间。要谈时间,得先回答三个前置问题:用什么机器算?一步是什么?时间怎么和输入大小挂钩?回答完这些,才能定义复杂性类,并比较”多给一些时间,能不能多解决一些问题”。
本讲的整体逻辑如下:
| 部分 | 要回答的问题 | 核心结论 |
|---|---|---|
| 1. Turing Machine | 用什么模型、怎么计步? | 多带图灵机;时间 = 步数,按输入长度 计 |
| 2. Universal TM | 一台机器能否执行任意程序?代价多大? | 通用机只慢 倍;由此得到对角线方法 |
| 3. Speedup Theorem | 每个问题都有”最快算法”吗? | 否。因此只能给算法定复杂度,复杂性类要允许常数倍 |
| 4. Time Complexity Class | 怎样定义与模型无关的类? | 、 |
| 5. Verification Problem | 能”猜”会怎样? | 非确定图灵机,、 |
| 6. Time Hierarchy | 时间多了,能解的问题一定变多吗? | 对可构造的时间函数:是(用对角线证明) |
| 7. Gap Theorem | 若时间函数不可构造呢? | 可能出现”多给指数倍时间也没用”的空隙 |
第 2 部分的通用图灵机是贯穿全讲的工具:时间谱系定理中的 因子就来自它的模拟开销,对角线方法也依赖它。
1. Turing Machine
要比较”快”与”慢”,先要精确规定”一步”是什么。图灵机把人用纸笔计算的过程抽象出来:有限的规则表(控制器)、无限的草稿纸(带子)、一次只看一个格子(读写头)。它足够简单,便于严格分析;后面也会看到,换成其他合理模型,结论只差多项式倍。
1.1 k-带图灵机
一台 -带图灵机有 条带子,每条带子分成无穷多格,格子地址为 ,每格放一个符号,每条带有一个读写头:
- 第 1 条是输入带,只读,存放输入;
- 其余 条是工作带,可读可写,用作草稿;最后一条(第 条)兼作输出带。

定义: -带图灵机
一台 -带图灵机是三元组 :
- :有限符号集(字母表),至少含 。 是空白符号,表示”这里没有有用信息”; 是左端标记,固定放在每条带的第 格。
- :有限状态集,含起始状态 和停机状态 。
- :迁移函数(transition function) 输入为当前状态和 个读写头读到的符号;输出为新状态、写到 条工作带上的符号,以及 个读写头的动作(左移 、不动 、右移 )。
读 个符号、只写 个,是因为输入带只读。一条指令
的含义是:当机器处于状态 、各读写头下的符号为 时,把工作带上的 改写为 ,各读写头按 移动,进入状态 。执行一条指令就是一步计算。指令只有有限条,机器的全部”智慧”都在这张有限的表里;带子提供的是无限的存储。
运行前带子要初始化:每条带第 格放 (机器不改写它,也不在别处写它);工作带全为 ;输入带除输入串外全为 。计算从 开始,进入 后不再变化。
1.2 格局与计算
状态只记录”程序执行到哪一行”,不足以描述机器此刻的全部情况:同一状态下,带上内容和读写头位置可以完全不同。要能”暂停后原样继续”,需要记下所有会影响后续计算的信息,这就是格局。
定义:格局(configuration)
运行中的图灵机 在某时刻的格局由三部分组成:
- 当前状态 ;
- 各工作带上的内容(非 部分);
- 个读写头的位置。
初始格局唯一:状态为 ,工作带为空,读写头都在第 格。状态为 的格局称为终止格局。
输入带的内容固定不变,所以不必写进格局。确定型机器在每个格局下只有一条指令可用,所以一步计算是格局之间的一次迁移 ,而 在输入 上的计算是一串格局
用 表示”输入带预置 后运行 “。若计算终止,记 ,终止前走过的步数就是计算时间;若永不终止,记 。
格局是之后反复使用的对象:空间复杂性中的”格局图”、Cook-Levin 定理中”把计算写成公式”,都是把一串格局整体拿来分析。
1.3 问题、判定问题与语言
有了机器,还要说清它在”解决什么”。任何有限对象(图、整数、公式、程序)都能编码成 0-1 串,所以问题可以统一看成串到串的函数。 表示全体有限 0-1 串。
定义:问题、判定问题、语言
- 问题:函数 。记 表示 且停机时输出带上是 。若对所有 有 ,称 计算(解决)。
- 判定问题:值域为 的问题 ,即只回答”是/否”。 计算 时称 判定 。
- 语言:子集 。其特征函数为 若 判定 ,称 接受 , 是可判定的。
- 补问题:。
判定问题与语言是同一件事的两种说法:语言就是全体”是”实例组成的集合。以后常把二者混用,例如""既指”判断公式是否可满足”这个问题,也指全体可满足公式的集合。复杂性理论主要研究判定问题,因为它们形式最简单,而难度通常和对应的计算问题相当。
例:判定回文的双带图灵机
回文是正读反读相同的串,如 。双带图灵机分三个阶段:
上图为输入 在比较阶段(状态 )的某一时刻:工作带末尾的 已比较完并擦去。
- 复制:两个读写头同步右移,把输入逐位抄到工作带;
- 回位:输入带读写头退回最左端,工作带读写头停在最右端;
- 比较:两个读写头相向移动,逐位比较。全部相同就输出 ,否则输出 。
每个阶段 步,共 步。若只允许一条读写带,读写头就要在串的两端来回奔波,需要 步。可见”线性时间能做什么”依赖于模型,这是 §1.6 要讨论的问题。
练习:设计图灵机计算下列函数(数用二进制表示,非整数结果向上取整)
- (据此可实现计数器)。
- ,即 个 (常在输入后附上 ,用来限制机器最多运行 步)。
- 。
- 。
答案要点
- 从最低位起,把末尾连续的 改成 ,再把遇到的第一个 改成 。单次最坏 步;但从 开始连加 次,第 位只翻转约 次,总共不超过 次翻转,所以是线性时间(摊还分析)。
- 把 当倒计数器,每减一就写一个 。共写 个 ,用时 ,相对输入长度 是指数级,但输出本身就这么长,无法更快。
- 输出 后跟 个 ,即串 。
- 设 ,则 。若 恰为 (形如 ),则 ,否则为 。所以只需数出输入长度并检查是否形如 。
最后一个基本事实:串到串的函数有不可数多个,图灵机却只有可数多个(§2.1 会给每台机器一个有限编码),所以绝大多数函数不可计算。§2.6 会给出具体的不可计算函数。
1.4 时间函数
衡量快慢时,要把步数表示成输入长度的函数,而不是输入数值的函数。
定义:时间函数
时间函数是 ,自变量为输入长度 。若 计算 ,且对每个输入 , 至多走 步就停机,称 在 时间内计算 。
是串的长度,不是数值。例如 的二进制是 个 ,数值是天文数字,长度却只有 。所以输入整数 时,” 步”的算法相对长度 是指数时间。练习中的 就是这种情况。
通常约定 :机器至少要把输入读一遍。
1.5 时间可构造函数与时钟
很多构造需要机器”自觉”地在预算 步内停下,例如时间谱系定理中,一台机器要模拟别的机器恰好 步然后收手。这要求 本身能被高效算出来。否则机器连自己的预算是多少都算不出来,第 7 部分的间隙定理会展示这类怪异的时间函数。可构造性就是用来排除它们的。
定义:时间可构造函数
设 ,。
- 若存在图灵机在 时间内计算 ,称 时间可构造(time constructible)。这里 表示 的二进制表示。
- 若存在图灵机在输入 上恰好运行 步后停机,称 完全时间可构造(fully time constructible)。
输入写成 ( 个 ),是因为只关心长度,不关心内容。定义 1 说”算出预算不超支”,定义 2 说”能精确地数出 步”。两者不等价,但大多数场合都可用。常用函数 、、、()都是完全时间可构造的;本课程只关心可构造的时间函数。
可构造性的直接用途是给机器装时钟。设 是 -带机器,运行时间可能很不规则; 是 -带机器,在 步内停机。把两者并联成一台 -带机器:
- 状态 ,且只要任一分量是停机状态,整体就停机:;
- 符号 ;
- 迁移 ,即两台机器同步各走一步。
复制输入后,两台机器并行运行,谁先停整体就停,所以运行时间是二者的较小者。 起到闹钟的作用,强迫 在 步内结束。这称为把 硬连接(hard-wire)到 。以后说”让 运行 步”,指的就是这种做法,前提是 可构造。
1.6 模型无关性与健忘图灵机
回文的例子说明,带数不同,“线性时间”能做的事就不同。若理论结论依赖于这类细节,就缺乏普遍意义。好在图灵机的各种变体(单带、多带、双向无限带、更大字母表……)之间都能以多项式开销互相模拟(§2.5 给出多带到双带、单带的模拟)。所以只要研究对象对多项式倍不敏感,例如”多项式时间可解”,结论就与模型无关。这是第 4 部分把 定义为 的原因。
还有一种变体在后面很有用:
定义:健忘图灵机(oblivious TM)
若图灵机在第 步时各读写头的位置只依赖于输入长度 和 ,与输入内容无关,称其为健忘的。
直观上,健忘机器的读写头按一张固定的时刻表移动,只有写下的内容随输入变化。时刻表事先已知,计算的”连线方式”就固定了。Cook-Levin 定理把计算翻译成公式、电路复杂性把计算翻译成电路时,都会用到这一点。任何机器都能改造成健忘的,代价只是多一个 因子(§2.5)。
1.7 Church-Turing 论题
为什么相信图灵机刻画了”计算”?证据有两类:一是从未找到直觉上可计算、但图灵机不可计算的例子;二是 λ-演算、递归函数、寄存器机等独立提出的模型,能计算的函数都恰好与图灵机相同。
Church-Turing 论题
任何物理上可实现的计算设备都能被图灵机模拟。
它不是数学定理,因为”直觉上可计算""物理可实现”不是形式概念;它更像一条关于自然的定律(Law of Nature),而不是人推导出来的结论。实际使用时,它允许我们用伪代码描述算法,而不必写出图灵机的指令表:只要过程直觉上可以机械执行,就默认存在实现它的图灵机。第 4 部分会把它加强为”多项式开销下的模拟”,即强 Church-Turing 论题。
2. Universal Turing Machine
到目前为止,每台图灵机都是专用的,一台机器只解一个问题。现实中的计算机却是通用的:同一台硬件读入不同程序,就做不同的事。对应的理论问题有两个:能否造一台图灵机,读入”另一台图灵机的描述”和输入,模拟它的运行?模拟要慢多少?
答案”能,而且只慢 倍”有两重意义:它在理论上对应现代计算机”程序即数据”的思想;它也是本课程大多数否定性结论(不可判定性、时间谱系、Ladner 定理……)的技术基础,因为对角线方法要求一台机器能运行并”反驳”其他所有机器。
2.1 把图灵机编码成串
要让机器读入另一台机器,先要把机器写成 0-1 串。图灵机是有限对象:有限个状态、有限个符号、有限条指令。给状态和符号编号后,一条指令如 可写成
整张指令表写成 (每个 是一条指令),再按 转成二进制。
记 为 的二进制编码, 为编码为 的机器。编码系统再做两条约定:
- 每个串都是某台机器的编码。 不合语法的串一律视为某台固定的平凡机器。这样”把任意串 当成程序 来运行”总是有意义的,对角线构造不必额外处理”不是程序”的情况。
- 每台机器有无穷多个编码。 例如 是 的编码,则 也是(或添加无用的冗余状态和指令)。这一点在时间谱系定理中至关重要:那里需要找到某台机器的一个足够长的编码,使”渐近成立”的不等式在这个编码的长度上已经成立。
2.2 有效枚举
固定一个从 到 的可计算双射,就把所有图灵机排成一列:
定义:有效枚举与下标
称 为 的下标(index,或哥德尔编码)。 计算的函数记为 :
一般是偏函数,即在某些输入上没有定义(机器不停机)。由于每台机器有无穷多个编码,每个可计算函数在 中出现无穷多次。“所有算法排成一列”是对角线方法的出发点。
2.3 通用图灵机与模拟效率
定理(枚举定理)
存在通用图灵机 ,对任意 , 其中 表示:一边有定义当且仅当另一边有定义,有定义时两边相等。
用程序语言类比:图灵机是程序,通用图灵机就是这门语言的解释器。复杂性理论还要求解释器足够快:
定理(Hennie-Stearns, 1966)
存在通用图灵机 和多项式 :若 在 步内停机,则 在 步内停机。
系数 只依赖于被模拟的程序(状态数、符号数、带数都不超过 ),与输入 无关。对固定的 它是常数,所以模拟的代价本质上只是多一个 因子。1965 年 Hartmanis 与 Stearns 最早给出的模拟需要 时间;他们的这篇论文创造了”计算复杂性”一词,二人因此获 1993 年图灵奖。
2.4 Hennie-Stearns 构造
目标与困难。 的带数固定,被模拟的 却可以有任意多条( 条)工作带。 只能把 条带挤在少数几条带上,于是有两个问题:
- 怎么放下 条带? 把 的主工作带分成 层(track),每层存 的一条带。每格存一个 元组,用 自己的符号编码。另用一条草稿带记录当前状态、辅助搬运数据。
- 怎么模拟 个读写头各自移动? 的主带只有一个读写头。办法是让读写头不动、让带子动:把 层在第 格对齐,第 格永远放着每条虚拟带”读写头下的那个符号”。某条虚拟带的读写头右移,就把那一层整体左移一格。
第 2 点的朴素做法是整层平移,每步代价 ,总时间 。Hennie-Stearns 的改进是在每层中预留空位,让大多数平移只在局部完成。
数据结构。 用特殊符号 表示”空位”(缓冲格,不是被模拟带上的内容),把主带以第 格为中心分区:
其中 各有 格,区间越往外越长,按 2 倍增长。

上图三层分别存着 “first work tape”、“second work tape”、“third work tape”。每一层按从左到右的顺序跳过 读出来,就是那条虚拟带的内容;第 格是各读写头当前所指的符号。上下两图是第一层读写头右移一格前后的样子,第二、三层不变。下面先给出约束,再解释这次移动是怎样完成的。
定义:分区不变式
对每一层和每个 ,区间 (或 )在这一层上只能是:满(不含 )、半满(恰好一半是 )或空(全是 )。并且左右互补:
- 满 空;
- 半满 半满;
- 空 满。
第 格永远放非 的符号。
互补条件保证每一对 在这一层上合计恰好存了 个真符号,缓冲在两侧分布均匀,不会出现一侧挤满、另一侧全空而被迫大搬家的情况。
一次平移(某层读写头右移,即该层左移一格):
- 从 向右找该层第一个非空区间 。
- 从 取出最左的 个真符号,依次填入第 格和 ,使它们都变成半满。容量核对:。
- 左侧: 原来都是空的,由不变式 原来都是满的。把 的全部内容并入 , 并入 ……原第 格的符号并入 。于是 都变成半满, 恰好多了 个符号,与 少掉的 个互补,不变式保持。
借助草稿带”边抄边搬”,这次平移只涉及 共 格,耗时 。
回到上图第一层:移动前中心是 k,=o r、=r s t w 都满,、 都空,第一个非空区间是 (半满,存着 t a p e),所以 。右侧:t a p e 依次填入中心(t)、(a)、(p e)。左侧: 的 r s t w 并入 , 的 o r 并入 ,旧中心 k 进入 。移动后,第一层的 都是半满, 变空、 变满,读出顺序 …first wor k t ape… 不变,只是读写头从 k 移到了 t。
例:单层上的两次平移(展示步骤 1–3)
只看一层,取区间 。虚拟带内容为 ,读写头在 上:
时刻 0 读出 初始 × × a b× cde ×f g × ×abcdefg 右移一次() × × a bc de× ×f g × ×abcdefg 再右移() a b c d× efg ×× × × ×abcdefg
- 第一次: 非空,,只需把 移到中心、 移进 。代价很小,但 满、 空,下次就得动用更外层。
- 第二次: 已空,找到 ()。取出 填中心和 ; 的 整体并入 ,原中心 进 。此后 又都半满,接下来至少一步内不必再动 。
每次动用第 层后,内层全部恢复半满,“缓冲”被重新补满,所以越外层的大搬家越少发生。
代价分析。 一次涉及第 级区间的平移之后, 与 都是半满,它们合计还能吸收约 次同方向的移动。所以同一层上,相邻两次第 级平移之间至少隔 步, 步内第 级平移至多 次。由于读写头至多走 格,只需用到 。
证明(时间界)
每步模拟先读出第 格的 元组,查 的指令表,写回,再对各层做平移。查表与编码开销是 的多项式。平移的总代价为
由于 ,总时间为 。
证明思路(通俗版)
- 要证什么:一台带数固定的 ,能以 的代价模拟带数任意的机器。
- 难点: 条带只能叠在一条带上,而一条带只有一个读写头。于是让读写头固定、让带子滑动;但带子整体滑动一次要 步。
- 核心想法:像在书架上留空位。书架上处处留一点空隙,插入一本书只需挪动附近几本,偶尔空隙用光才大挪一次。这里的空隙按 的规模分级布置:小搬家很便宜、经常发生;大搬家很贵(),但每次大搬家都会把内层空隙重新补满,所以要再过 步左右才会再发生。
- 为什么是 :每一级的总花费都是”次数 × 单价 “,一共 级,加起来 。这与二进制计数器”第 位每 次才翻一次”的摊还分析是同一个道理。
2.5 两个推论:健忘模拟与少带模拟
上面的 何时进行大搬家依赖于读写头怎么动,因此依赖于输入。若把搬家改成按固定日程进行,就得到健忘机器。
推论(健忘化)
设 时间可构造, 能被某图灵机在 时间内判定,则存在健忘图灵机在 时间内判定 。
证明
修改 :
- 先把 全部置为半满(各区间的边界用 和 标好,输入与 交错抄入)。这一步需要事先算出 ,用到可构造性。
- 维护一个模拟步数计数器。每模拟一步就加一;若第 位刚从 变成 ,就按固定方式来回扫描 常数遍,把内层重新整理为半满。
何时整理、扫哪些区间只取决于步数,与输入内容无关,所以读写头轨迹只依赖 与步数。第 级整理每 步一次、每次 ,总代价仍为 。
推论(Hennie-Stearns, 1966)
若 能被某 -读写带图灵机在 时间内计算,则 能被双读写带图灵机在 时间内计算,也能被单读写带图灵机在 时间内计算。
双带对应主带加草稿带。只有一条读写带时,没有草稿带协助搬运,每次平移代价变大,总时间为 。两种代价都是多项式,这正是 §1.6 所说”模型变体只差多项式倍”的一个具体实例。
2.6 对角线方法:不可判定性
有了通用机,一台机器就能运行任何别的机器,包括”把某台机器的编码喂给它自己”。对角线方法利用这一点:构造一台机器,让它在每台机器的”自身编码”这个输入上,与那台机器的输出唱反调,于是它不可能等于任何一台机器。
把所有运行结果排成一张无限表:第 行是机器 ,第 列是输入 ,表项为 。对角线上是 。取对角线并逐项取反,得到的这一行与表中每一行都至少在对角线位置上不同。
定义:对角函数
等价地,把 换成 。
定理
不能被任何图灵机计算。
证明
设某台机器 计算 。把 自己的编码 作为输入:由定义, 当且仅当 ,矛盾。
是一个处处有定义的全函数,难点在”否则”那一支:要输出 ,必须确认 不会输出 ,包括它永远不停的情况,而模拟时永远无法确定”它再走几步会不会停”。这自然引向停机问题。
定义:停机问题
定理
不能被任何图灵机计算。
证明
设机器 计算 ,构造
先问 ;只有确认 会停机时,才用通用机把它跑完,所以 总会停机,并且计算的正是 ,与上一定理矛盾。
这个证明的方法叫归约:假设 可解,把它当子程序来解已知不可解的 ,从而推出矛盾。方向要分清:要证明”新问题 难”,应当把已知难的问题 归约到 (“若 可解,则 可解”),而不是反过来。之后的 NP-完全性证明也都是这种模式。
Remark:对角线方法的一般模式
递归论与复杂性理论中几乎所有否定性结论都由对角线方法得到。一般模式是:构造一台机器 ,让它(借助通用机)模拟机器列表中的机器,并在某些输入上故意与它们的输出相反,从而保证 不同于列表中的每一台;同时控制 自身使用的资源,再由此推出矛盾或分离结果。本讲的时间谱系定理正是”只模拟 步再取反”的资源受限版本,通用机的 开销也因此出现在定理条件中。
3. Speedup Theorem
有了”时间 = 步数”,似乎可以这样定义问题的难度:一个问题的时间复杂度 = 解它的最快算法的运行时间。这要求每个问题都有一个最快的算法。本部分说明这个想法行不通,而且失败得很彻底:
- Blum 加速定理:存在一个(人为构造的)可计算函数,它的任何算法都能被另一个算法大幅加速,比如快到指数倍,并且可以无限加速下去,根本没有最快的算法。
- 线性加速定理:对每个问题,任何算法都能快任意常数倍。
两者合起来决定了第 4 部分的做法:不给问题定一个精确的时间,而是问”它有没有一个运行时间不超过 的算法”。
3.1 Blum 复杂性度量
Blum 的结论不依赖于”时间”的具体定义。他先抽象出一个”资源度量”至少应满足什么条件,再对所有满足条件的度量统一证明。
定义:Blum 复杂性度量
设 是 §2.2 的可计算函数枚举。一族函数 称为 Blum 复杂性度量,如果:
- 有定义 有定义;
- 对任意 ,""是可判定的。
理解为程序 在输入 上消耗的资源量。
两条公理的含义:(1) 程序停机当且仅当资源消耗有限;(2) 给定预算 ,总能判断”程序是否在预算内完成”,哪怕程序本身不停机。时间显然满足:
定义:Blum 时间函数
其中 表示使 成立的最小 (不存在则无定义)。 是 Blum 复杂性度量。
第 2 条成立,是因为判断 只需用通用机把 模拟 步。
本部分沿用递归论的习惯,把输入 看作自然数(串与自然数一一对应),并且逐个输入比较步数,而不是像 §1.4 那样按输入长度取最坏情况。
3.2 主引理:几乎处处的加速
先引入一个用语:一个关于 的性质几乎处处(almost everywhere,a.e.)成立,指它只在有限个 上不成立。只在有限个输入上出错的算法很容易修补(查表),所以”几乎处处”是讨论加速时合适的标准。
主引理
设 是可计算全函数。存在可计算全函数 ,使得对任一计算 的图灵机 ,都能有效地构造出图灵机 ,满足:
- 是全函数,且 a.e.;
- a.e.
逐句解读:
- 对任意加速比 ,比如 ;
- 存在一个问题 ;
- 对解 的任何算法 ;
- 能构造出算法 ,它几乎处处解 ,而且快到连 都比 小。取 时,就是 ,指数级的加速。
3.3 主引理的证明
预备工具:s-m-n 定理与递归定理。 证明中要定义一族程序,而这族程序的定义要引用它们自己的编号。下面两个递归论定理保证这种”自我引用”是合法的。记 为第 个 元可计算函数。
定理(s-m-n 定理)
设 。存在单射原始递归函数 ,使得对所有 和 ,,有
直观:把多元程序 的前几个参数”焊死”成常数,就得到一个新程序;新程序的编码可以从 和这些常数算出来。证明就是写出新程序”先把 写到带上,再用通用机运行 “,然后算出它的编码。这相当于函数式编程里的柯里化(currying)。本节用的是 的情形:存在 使
定理(Kleene 递归定理)
设 是可计算全函数。存在 使 。
直观:任何”程序变换” 都有一个”不动点”程序,变换前后行为相同。它的一个推论正是这里要用的:
推论(用自身编号定义程序)
设 是可计算函数。存在 ,使 \phi^{(2)}_e(u,x)\simeq g(e,u,x).\tag{2}
也就是说,在描述程序 时,可以把 自己的编号当作已知参数来用,就像程序能读到自己的源代码。由 s-m-n 定理,存在可计算全函数 使 ;再对 用递归定理取不动点 ,即得 。
构造的整体思路。 由 (1)(2),一个编号 确定一族单参数程序
目标函数取 。程序 的行为是:对编号 的机器视而不见,只对编号 的机器做对角线。机器 的”加速版”将是 ,即 。
对角线的规则是”太快就注销”:在输入 上,若机器 比 快得不够多,即
就注销(cancel),并让 的输出与 不同。于是:凡是真正计算 的机器 都不会被注销,因而必然满足 。加速比不需要事后分析,而是被注销规则直接”强制”出来的。
形式定义。 对固定的 ,按 依次定义注销集 。假设 ()都已定义,且对所有 , 都有定义,令
否则 无定义。再令
(约定 。)
几点说明:
- 第 阶段只考虑编号 的机器,所以每阶段只需检查有限台机器;机器 从阶段 起才”入场”。
- 减去 ,使每台机器至多被注销一次。注销一次就足以保证它不等于 。
- 判断 只需把 运行有限步(Blum 公理 2),因此即使 不停机, 也可计算;而对 , 一定有定义, 能算出来。
- 输出 比所有被注销机器的输出都大,因此与每一台都不同,这就是对角线取反。
再由 (2) 取定 ,使 恰好就是 。下面验证三条性质。
证明(三条性质)
(i) 每个 都是全函数。 对 归纳,设所有 ()都有定义。固定 ,对 从大到小归纳:
- 若 ,则 ,。
- 若 ,且 已有定义,由 (1)(2), 都停机,于是 对 都有定义, 有定义, 有定义。
(ii) 每个 与 几乎处处相同。 机器 是否在阶段 被注销,只取决于 、 以及 此前是否被注销,与其他机器无关。所以对 ,它在” 系列”与” 系列”里于同一阶段被注销,从而 编号 的机器只有 台,各至多注销一次。设 是它们最后一次被注销的阶段,则当 时 ,从而 。
(iii) 加速。 设 。若 对某个 成立,则 会在第一个这样的阶段(于” 系列”中)被注销,使 ,矛盾。所以对所有 ,
取 :由 (i)(ii), 是全函数且 a.e. 等于 ;由 (iii), a.e.。 由 直接算出,构造是有效的。
证明思路(通俗版)
- 要造什么:一个函数 ,以及每个 的程序 的一个”快 倍”的替身。
- 替身从哪来:一次性造出一整族程序 ,,程序 的替身就是 。 与 规则相同,只是”不管前 台机器”。前 台机器总共只影响有限个输入,所以 与 只差有限处。
- 为什么替身一定更快:规则规定,谁比自己的替身快得不够多(),就在那个输入上故意给出与它不同的答案。所以正确计算 的程序都”不敢”太快,它们一定比替身慢 倍以上。
- 为什么需要递归定理: 判断是否注销机器 时,要知道替身 跑多少步,也就要运行这族程序里的另一个成员。程序的定义引用了自己所在家族的编号 ,递归定理保证这样的 存在。
- 为什么不会无穷递归: 只调用 ,编号越来越大,而 不用管任何机器,直接输出 。所以从 往回算,每一级都能算完,这就是 (i) 中”从大到小归纳”。
3.4 Blum 加速定理
主引理的替身只是几乎处处正确。修补有限个输入,就能得到真正计算 的程序,代价是加速的构造不再是有效的。
定理(Blum 加速定理,1967)
设 是可计算全函数。存在可计算全函数 ,使得对任一计算 的图灵机 ,存在计算 的图灵机 ,满足 a.e.
证明
不妨设 单调递增。把主引理中注销条件改为 ,同样的论证给出 : 全, a.e.,且 a.e.。
设 对所有 成立。给 加一段”查表”:输入 时直接输出 ,否则照常运行 。记新机器为 ,它处处计算 。查表的额外开销主要是比较 与 ,不超过 步,所以对足够大的 ,,从而
注销条件里多出的 "" 是预先留出的余量,专门用来抵消查表的开销。 取决于 与 在哪些输入上不同,无法从 算出,所以这里只能说”存在”。
它说明了什么。 对这个 ,任取一个算法 ,就有更快的 ,又有更快的 ……
这条链永远走不到头,所以 没有”最快算法”,“问题的时间复杂度 = 最快算法的时间”这个定义对它没有意义。这个 是对角线构造出来的人造函数,但它足以说明:一般地,我们只能谈论解(算法)的复杂度,再通过”问题有什么样的解”来给问题分类。
3.5 线性加速定理
Blum 定理的反例是人造的。另一个更早、更温和的结论对所有问题都成立:常数倍的加速总是做得到。
定理(线性加速定理,Hartmanis-Stearns 1965)
若 能在 时间内判定,则对任意 , 能在 时间内判定。
想法:换更大的字母表,一步干 步的活。 设 在 步内判定 。构造 ,它的一个符号代表 的 个连续格子(字母表含 )。
证明
按如下方式运行:
- 用 步把输入每 个符号压成一个,抄到工作带上;
- 用 步把读写头移回开头;
- 每轮用 5 步模拟 的 步: 在 步内读写头最多移动 格,只会碰到当前块和左右相邻两块。 把这三块都看一遍、记进状态(状态集足够大,可以记下这些内容),就能算出 步后三块的新内容和读写头的新位置,再写回去。
总时间不超过 取 即得。
推论
若 (增长严格快于线性),且 能在 时间内判定,则对任意 , 能在 时间内判定。
此时 被 吸收。留下的 是读一遍输入并压缩所需的时间,无论怎么加速都省不掉。
两个加速定理带来的结论。 常数因子没有意义: 与 时间能解的问题一样多,只是机器的字母表和状态集更大。所以下一部分定义 时,规定”存在常数 使运行时间 “,这正是大 记号的来历。再结合 Blum 定理,复杂性类刻画的是”问题有什么样的解”,而不是”问题的最优解有多快”。
4. Time Complexity Class
第 3 部分说明,问题没有”最快算法”可言,常数倍也总能省掉。所以给问题分类时,只能问”它有没有一个足够快的算法”,并且忽略常数因子。本部分据此定义时间类,再从中挑出与模型无关的那些,得到真正的复杂性类 和 。
4.1 TIME(T(n))
定义:
设 是时间函数。判定问题 属于 ,当且仅当存在常数 和接受 的图灵机 ,使 在每个长度为 的输入上至多运行 步。
是一个问题的集合。定义中的”存在算法”回应了 Blum 定理:刻画的是问题有什么样的解;“存在常数 “回应了线性加速定理:常数倍本来就能省掉。
4.2 复杂性类:要求与模型无关
依赖于所用的机器模型。双带图灵机能在线性时间判定回文,单带图灵机却需要平方时间,所以”回文 “是否成立取决于允许几条带。这样的类反映的是模型细节,而不是问题本身的性质。
定义:复杂性类(complexity class)
直观上,复杂性类是一类问题,它们都具有某种与模型无关的性质的解。
按这个要求, 不是复杂性类。要得到与模型无关的类,就要把”差一个多项式倍”的时间界合并在一起,因为各种合理模型之间正好能以多项式开销互相模拟(§1.6、§2.5)。
4.3 P 与强 Church-Turing 论题
定义:多项式时间类
把所有多项式合并后,换模型只会让多项式的次数改变,问题仍留在 中。这一点依赖于下面的信念:
强 Church-Turing 论题(Strong Church-Turing Thesis)
任何物理上可实现的计算设备都能被图灵机模拟,且模拟时间不超过被模拟设备运行时间的某个多项式。
§1.7 的论题只说”能算什么”,强论题进一步说”算得多快也只差多项式倍”。在它之下, 与模型无关。量子计算是对它的潜在挑战:目前既不能确定量子计算机是否物理可实现,也没有被证明的例子表明某个问题量子多项式时间可解而图灵机不可。
计算机科学通常把 等同于”有高效(可行)算法的问题”,这称为 Cobham-Edmonds 论题。选多项式的另一个好处是封闭性:多项式时间算法的复合、以及调用多项式次多项式时间子程序,结果仍是多项式时间的。所以 作为”高效”的定义,在组合算法时不会失效。
把 当作”可行”仍有争议,常见的质疑有两个:
- 真的刻画了可行问题吗? 是多项式,却远不可行; 是指数,但在中等规模下也许仍可处理。
- 中的问题都能被证明属于 吗? 可能存在多项式时间算法,我们却无法证明它的运行时间是多项式。
教材对此的态度是:怀疑 与相信强 Church-Turing 论题是不一致的。
4.4 EXP 与补类
用同样的方式定义指数时间类:
定义:指数时间类
指数上必须是 ,不能只取 。原因仍是封闭性:先用多项式时间算法把输入变形,再在结果上运行指数算法,得到的算法应当仍算”指数时间”。
例:为什么不能用
设算法 在 时间内把长度 的输入变成长度 的串,算法 在长度 的输入上用 时间。复合算法 的时间是 ,无论 多大都不在 中,却在 中。所以 对”先做多项式预处理”不封闭,而 封闭。
后面经常要谈”一类问题的补”,例如 与 。
定义:补类
设 是复杂性类,其补类为 。
引理
。
(若 ,则对 有 ,于是 。)确定型类都满足 :把机器的输出 对调,就判定了补语言,时间不变,所以 ,。下一部分的非确定型类就没有这么简单了。
5. Verification Problem
把""看成一个命题,判定 就是在找它的证明。 是”能在多项式时间内找到证明”的问题。还有很多问题,证明很短、检查起来很快,但没人知道怎么快速找到证明。
例如顶点覆盖:给定图 和整数 ,问是否存在至多 个顶点,使每条边至少有一个端点被选中。若有人递来一个顶点集合,检查它是否满足要求只要多项式时间;可是自己去找,看起来只能在 个子集里搜索。
穷举所有可能的短证明再逐个检查,说明这类问题都在 中,但这个刻画太粗,抹掉了”可以快速检查”这个特征。为了专门刻画可高效验证的问题,引入一个理论模型:非确定图灵机。
5.1 非确定图灵机
定义:非确定图灵机(NDTM)
非确定图灵机 与图灵机的区别只在于它有两个迁移函数 。每一步, 可以任意选用其中一个。若对每个输入 和每一种选择序列, 都在 步内进入 ,称 在 时间内运行。
“非确定”指没有规定使用 还是 的策略。把所有可能的选择画出来, 在输入 上的计算是一棵二叉树:根是初始格局,每个格局有两个后继(分别用 ),每一条从根出发的路径是一种可能的计算。“在 时间内运行”就是这棵树的深度不超过 。
非确定图灵机不是(人们相信不是)物理可实现的,引入它纯粹出于理论需要:它让”存在一个短证明”这件事有了机器的说法。
5.2 接受:存在一条成功路径
定义:NDTM 接受的语言
若计算树中存在一条路径停机并输出 ,称 接受 ,记 ;否则(所有路径都输出 或不停机)称 拒绝 ,记 。若 ,称 接受 。
接受与拒绝是不对称的:接受只需一条成功路径,拒绝却要求所有路径都失败。这与”存在性命题”的结构一致:要说明存在顶点覆盖,举出一个就够了;要说明不存在,必须排除所有候选。这种不对称是” 是否等于 “这一问题的根源,非确定型类不能像 §4.4 那样对调输出来求补。
5.3 猜测与验证
非确定性提供的能力是猜测。以顶点覆盖 为例,一台 NDTM 可以这样工作:
- 猜测:用 步,每步非确定地写下一位 或 ,得到一个 位的串,它代表 的一个子集 。
- 验证:确定地检查 ,并检查每条边都至少有一个端点在 中;通过就输出 ,否则输出 。
所有子集都会在某条路径上被猜到。若存在大小不超过 的覆盖,就有一条路径恰好猜中它并接受;若不存在,每条路径的验证都失败。整台机器运行多项式时间。
一般地,NDTM 的计算可以看作”先猜一个证据,再确定地验证”。成功路径上做出的非确定选择本身就是证据:它说明 ,而且检查它很快。第 3 讲会把这个看法写成 的等价定义: 当且仅当存在多项式长的证书 ,使多项式时间验证器 。
5.4 NTIME、NP 与 NEXP
定义:非确定时间类
,当且仅当存在常数 和在 时间内运行、接受 的 NDTM。
就是非确定多项式时间类,即可在多项式时间内验证的问题。""问的是:能快速验证的问题,是否都能快速求解?
命题
证明
第一、三个包含:确定型图灵机是不用第二个迁移函数()的 NDTM。 第二个包含:设 NDTM 在 时间内运行,其计算树深度至多 ,至多 条路径。确定型机器逐条枚举选择序列、用通用机模拟每一条,任一条接受就接受,总时间 。
四个包含中哪些是严格的,目前只知道一部分:第 6 部分的时间谱系定理会给出 与 ,所以 中至少有一个包含是严格的,但不知道是哪一个。
5.5 “通用”非确定图灵机
NDTM 也是有限对象,可以照搬 §2.1–2.2 编码并有效枚举:
每台 NDTM 出现无穷多次。下一个自然的问题是:有没有通用的 NDTM?
照搬 Hennie-Stearns 的构造即可:每模拟一步前,非确定地选用被模拟机器的 或 ,开销仍是 。但非确定性允许一种几乎没有开销的模拟。关键是不去维护整条带,而只记录读写头”看到”的东西:
定义:快照(snapshot)
-带机器 在输入 上第 步的快照是 其中 是第 步的状态, 是第 步各读写头所指格中的符号。
与格局不同,快照的大小只依赖于机器 ,与输入长度无关;一条计算路径对应一串快照。“通用”NDTM 的工作方式如下:
- 猜测:输入 。 只在输入带上真实地运行 ,同时非确定地猜出每一步的选择( 或 ),以及每一步各工作带读写头下的符号,即猜出一串快照,最后一个快照是接受状态。
- 验证:对每一条工作带分别检查。 用一条额外的带,按照快照序列和迁移函数规定的写入与移动,把这条工作带的实际变化过程重放一遍,核对每一步”读写头下的符号”是否与所猜的一致。
- 所有检查都通过就接受,否则拒绝。
若所有检查都通过,所猜的快照序列就确实是 的一条接受路径;反过来,任何一条接受路径都会在某个分支上被猜中。每条带的重放是线性时间,所以模拟一条长度为 的接受路径只需 时间(常数依赖于 )。
思路:为什么能省掉
确定型通用机慢,是因为它必须真实地维护 条带,读写头的移动导致大量数据搬运。非确定机可以”先猜后验”:先大胆猜出每一步读写头下的符号,算出整条计算路径,再逐条带回头检查猜得对不对。检查一条带时只需跟踪这一条带的变化,用一条额外的带顺序重放即可,没有搬运开销。
的缺陷是不一定停机:猜测阶段没有任何东西阻止它一直猜下去。实际使用时,被模拟的总是时间函数可构造的 NDTM,可以给 装上时钟(§1.5),超时即拒绝。第 6 部分的非确定时间谱系定理就要用到这种廉价模拟。
5.6 TIME 与 NTIME
确定型与非确定型时间类之间,几乎没有已证明的非平凡关系。下面是一个罕见的例子。
定理(Paul-Pippenger-Szemerédi-Trotter, 1983)
- 它没有回答 与 的关系: 与 都依赖模型,按 §4.2 都不是复杂性类,这个分离无法推广到多项式时间。
- 它是一个非相对化的结果:第 3 讲会说明,大多数基于模拟与对角线的证明都”相对化”,因而无法解决 ;这个定理的证明不属于此类。
- 证明的灵感来自 Hopcroft-Paul-Valiant 的结果 (第 2 讲)。
6. Time Hierarchy Theorem
显然推出 。真正的问题是:时间多给一些,能解的问题是否严格变多?若答案是否定的,复杂性类的整个层级就可能塌成一团。时间谱系定理给出肯定的回答,工具是 §2.6 的对角线方法加上”只模拟有限步”的时间限制。证明需要的两样东西前面都已备好:通用机的模拟开销(§2.4,带来 因子),以及给机器装时钟(§1.5,要求时间函数可构造)。
6.1 确定时间谱系定理
定理(时间谱系定理,Hartmanis-Stearns 1965)
若 时间可构造,且 ,则
表示严格低阶: 即 。
证明目标:造一个语言 ,它能在 时间内判定,但不能在 时间内判定。做法是让判定 的机器 在每台机器 的”自身编码”上与它唱反调,而且只花 步。
证明
定义机器 :
输入 ,用通用机 模拟 至多 步(把 -时钟硬连接到 上)。若模拟在 步内完成,输出 ();否则输出 。
设 为 判定的语言。因为 可构造、时钟保证 在 步内停机,。
假设 ,由某台机器 在 时间内判定。由 Hennie-Stearns 定理, 模拟 在长度 的输入上至多需要 步,常数 只依赖于 本身。因为 ,存在 使 时 。 有无穷多个编码(§2.1),取其中一个长度 的编码 ,即 。于是 在输入 上能完成模拟:
- ,因为二者判定同一个语言 ;
- ,因为 完成模拟后把结果取反。
矛盾。所以 。
两个前提各有用处:
- 因子来自通用机的模拟开销。 要在 步内模拟完一台 时间的机器,而模拟本身要 步,所以需要 比 大。
- **“每台机器有无穷多个编码”**让我们能挑一个足够长的 ,使”渐近成立”的不等式 在 处已经成立。
6.2 指数谱系
谱系定理的直接推论是 :
中间一步成立是因为 。同理可以一层层往上:
定义:指数谱系
由谱系定理,。 中的问题能在高度为常数的指数塔 时间内解决;高度随 增长的塔函数比所有这些都快。有些验证问题(例如某些程序验证问题)的复杂度甚至远超塔函数。
6.3 非确定时间谱系定理
非确定型也有谱系定理,但 §6.1 的证明不能照搬。问题出在”取反”: 要输出 ,就得确认 的所有路径都拒绝(§5.2 的不对称)。非确定机器做不到这一点;确定型地枚举所有路径又要指数时间,远超 。
定理(非确定时间谱系定理,Seiferas-Fischer-Meyer 1978;Žák 1983 简化证明)
若 时间可构造,且 ,则
历史上,Cook(1973)先证明了 时 。这里没有 因子,因为 §5.5 的”通用”NDTM 只有常数倍开销;取而代之的是奇怪的 ,下面会看到它的来源。
核心想法:懒惰对角线(lazy diagonalization)。既然取反很贵,就只在极少数输入上取反,并且只在取反负担得起时才做:
- 只考虑一元输入 。把输入长度切成很长的区间 ,第 个区间专门对付第 台机器 。
- 区间内部(不取反,只”错位抄写”):对 ,令 。这只需非确定地模拟,无需取反,用 §5.5 的 在线性时间内完成。
- 区间右端点(取反一次):令 。这里要取反的输入 比当前输入短得多(区间极长),所以可以用确定型暴力法枚举所有路径算出结果,时间仍不超过 。
若 与 接受同一语言,错位抄写会把 在左端点 上的答案一路传到右端点 ,而右端点又规定了相反的答案,于是矛盾。
| 输入 | |||||
|---|---|---|---|---|---|
| 的定义 |
机器 的定义。 设 是所有 NDTM 与 -时钟硬连接后的有效枚举,所以每个 都在 时间内运行。
构造:Žák 的机器
- 输入带读写头与第一条工作带读写头同步向右全速扫描。若输入长度为 或含 ,拒绝。第一条工作带上在第 格写 ,此后大多写 ,偶尔写 ;写 的位置依次记为 ,由第 2 步决定。
- 扫描的同时, 在第二条工作带上依次枚举 。枚举出 后, 用暴力法计算 ;算完时,把结果记在第二条工作带上,并在第一条工作带读写头此刻所在的格子写 ,这个位置就是 。
- 输入为 ()时,扫描完输入后:
- (a) 若 ,接受当且仅当 ;
- (b) 若 ,用 非确定地模拟 至多 步。
的取法保证了暴力计算”刚好赶上”: 就是扫描头在暴力计算结束时走到的位置,所以暴力计算的时间不超过 。输入长度恰为 时,答案在扫描结束时已经备好。
构造细节:第 2 步如何在线性时间内完成
枚举出 后, 暂停两条扫描头,做三件事:
- 利用第一条工作带上的标记,在第三条工作带上造出 (只需在上次造好的 后补 个 );
- 把 的编码从第二条工作带复制到第三条工作带;
- 把读写头移回暂停前的位置,恢复扫描,同时在第三条工作带上暴力计算 。
每次暂停只往回看常数次,累计开销与扫描长度成线性。所以第 1、2 步总共 ;第 3(a) 步只需读出已备好的结果;第 3(b) 步由 完成,。
证明
:由上, 的总时间为 。
:假设某 NDTM 在 时间内接受 。由线性加速,可设其时间为 ,所以它出现在枚举 中,而且出现无穷多次。取足够大的 ,使 接受 ,且对所有 , 模拟 所需的 步不超过 (由 )。于是
矛盾。
条件 的来源:在长度 的输入上, 模拟的是 在长度 的输入上的计算,需要约 步,必须塞进 的预算。错位一格换来了”把答案沿区间传下去”,代价就是这个 。对 这样的多项式,,条件就是通常的 。
7. Gap Theorem
由时间谱系定理,。自然会猜:对任意可计算全函数 ,是否都有
间隙定理说:不一定。若对时间函数不加限制,可以找到 ,使得多给指数倍的时间也解决不了任何新问题。这正是 §1.5 引入可构造性的原因。
7.1 间隙定理
定理(间隙定理,Trakhtenbrot 1964;Borodin 1972)
设 是可计算全函数,。存在可计算全函数 ,使
取 ,就得到 :在 与 之间是一段”空白地带”。
思路:找一段没有机器在其中停机的时间区间。 对每个输入长度 ,只关心前 台机器 在长度为 的输入上的运行时间。这些运行时间只有有限个。只要找到一个 ,使区间 内没有任何一个运行时间落入,就令 。这样,任何在 步内停机的机器,其实在 步内就已停机。
证明
构造互不相交的区间:,,得到区间 。
记 为性质:
对任意 和任意长度为 的输入 ,要么 在 步内停机,要么 在 步内不停机。
可判定:把这有限多个计算各运行 步即可。设 在长度 的输入上共有 个”(机器,输入)“组合,它们的停机时间至多 个。每个停机时间至多落在一个区间里,所以在 个区间 中至少有一个不含任何停机时间(鸽巢原理)。于是存在最小的 使 成立,令 。 可计算,且对所有 , 成立。
设 由某台 在 步内判定。对 , 属于 ,由 : 要么在 步内停机,要么 步内不停机。后者与假设矛盾,所以 在 步内停机。长度 的有限个输入用查表处理。因此 。
( 还允许常数倍 。处理常数是技术细节,可以在构造 时把 适当加大来吸收,这里从略。)
证明思路(通俗版)
- 想要什么:一个预算 ,使得把预算放大到 也没用。
- 为什么可能:机器的运行时间只有有限个值,就像数轴上有限个点。把数轴切成一段段越来越长的区间 ,有限个点不可能占满无穷多段,必有一段是空的。
- 怎么用:在长度 上,把 定在一段空区间的左端。任何在 步内停机的机器,停机时间不会落在空区间里,所以必然 。
- 为什么只看前 台机器:要让每个长度都只检查有限个计算, 才可计算。代价是每台机器只在长度足够大时才”被照顾到”,前面的有限个输入用查表补上。
7.2 与谱系定理的关系
间隙定理与时间谱系定理并不矛盾,它说明的是谱系定理里的可构造性条件不能去掉:
- 若 是时间可构造的,且 增长得比 快(例如 ),则 ,谱系定理给出 ,与间隙定理矛盾。所以间隙定理造出的 不是时间可构造的。
- 直观上, 是”刻意避开所有机器停机时间”挑出来的,算出 本身就要运行很多机器很多步,根本无法在 时间内完成,所以不能用它来给机器装时钟。
这就是本讲反复强调”只关心可构造的时间函数”的原因:对可构造函数,时间越多、能力越强(谱系定理);去掉这个限制,时间与能力之间的关系可以变得很怪异(间隙定理)。
上图为输入