MIT-18-404J-计算理论笔记-全-
MIT 18.404J 计算理论笔记(全)
001:课程介绍与有限自动机

概述
在本节课中,我们将学习计算理论的基础知识,特别是有限自动机(Finite Automata)和正则表达式(Regular Expressions)。我们将探讨计算机算法的能力和局限性,并介绍用于描述计算过程的抽象模型。
课程介绍
欢迎来到2020年秋季学期的计算理论导论课程。我是Mike Sipser,本学期将担任你们的讲师。
这门课程主要分为两部分。第一部分是可计算性理论,它研究在原则上算法能计算什么。这是20世纪早期的一个活跃研究领域,如今已基本成为一个封闭的研究课题,因为其主要问题都已得到解答。第二部分是复杂性理论,它关注在实际中,在合理时间内可以计算什么。这部分将讨论计算的时间和空间复杂度,并涉及著名的P与NP问题。
学习本课程需要一定的数学基础,特别是关于数学定理和证明的经验。课程作业和考试将要求你能够构建证明。
理论计算机科学在计算机科学领域中扮演着重要角色。尽管计算机科学已经成熟,但在理解计算的本质方面,我们仍处于非常初级的阶段。例如,我们尚不清楚如何快速分解大数,也不完全理解大脑如何进行创造性计算。本课程涵盖的理论优雅且实用,是理解计算的良好起点。
有限自动机
上一节我们介绍了课程的整体框架,本节中我们来看看第一个计算模型:有限自动机。这是一种非常简单的模型,可以看作是具有少量有限内存的计算机。
有限自动机示例
我们通过一个称为状态图的图表来展示有限自动机。下图展示了一个名为 M1 的有限自动机。

图表中的圆圈称为状态。在本例中,有三个状态:q1, q2, q3。连接状态的箭头称为转移,它们指示了设备如何进行计算。有一个特别指定的起始状态,带有一个从外部指向它的箭头。还有特别指定的接受状态,用双圆圈表示。
如何计算
计算过程很简单。输入是一个由0和1组成的有限字符串(对于其他自动机,可能允许其他符号)。计算步骤如下:
- 将指针放在起始状态(即带有从外部指向箭头的状态)。
- 开始逐个读取输入符号。
- 根据当前状态和读取的符号,沿着对应的转移箭头移动到下一个状态。
- 重复步骤2和3,直到读完所有输入符号。
- 如果最终状态是接受状态,则接受该输入字符串;否则拒绝。
示例1:输入字符串 01101
- 从 q1 开始。
- 读
0:保持在 q1。 - 读
1:转移到 q2。 - 读
1:转移到 q3。 - 读
0:保持在 q3。 - 读
1:保持在 q3。 - 结束于接受状态 q3,因此该字符串被接受。
示例2:输入字符串 00101
- 从 q1 开始。
- 读
0:保持在 q1。 - 读
0:保持在 q1。 - 读
1:转移到 q2。 - 读
0:转移到 q1。 - 读
1:转移到 q2。 - 结束于非接受状态 q2,因此该字符串被拒绝。
通过分析可以发现,该自动机 M1 接受的字符串是那些包含连续两个1(即子串“11”)的字符串。我们称这个字符串集合为该自动机的语言。
形式化定义
为了使讨论更精确,我们需要有限自动机的形式化数学定义。一个有限自动机是一个五元组 (Q, Σ, δ, q₀, F),其中:
- Q 是一个有限的状态集合。
- Σ 是一个有限的输入字母表。
- δ 是转移函数,它接收一个状态和一个输入符号,并返回下一个状态。形式为:δ: Q × Σ → Q。
- q₀ ∈ Q 是起始状态。
- F ⊆ Q 是接受状态集合。
以自动机 M1 为例,其形式化描述如下:
- Q = {q1, q2, q3}
- Σ = {0, 1}
- δ 用下表描述:
| 状态 | 输入 0 | 输入 1 |
|---|---|---|
| q1 | q1 | q2 |
| q2 | q1 | q3 |
| q3 | q3 | q3 |
- q₀ = q1
- F = {q3}
字符串与语言
- 字符串 是字母表中符号的有限序列。空字符串(长度为0)记为 ε。
- 语言 是字符串的集合。例如,自动机 M1 的语言是 A = { w | w 包含子串 “11” }。
我们说一个自动机 M 识别(或接受)一个语言 A,如果 A 恰好是 M 接受的所有字符串的集合。记作 A = L(M)。
如果一个语言可以被某个有限自动机识别,则称该语言为正则语言。
示例:
- 语言 B = { w | w 中 1 的个数为偶数 } 是正则语言。可以用一个只有两个状态的自动机来识别,分别记录当前看到奇数个1还是偶数个1。
- 语言 C = { w | w 中 0 和 1 的个数相等 } 不是正则语言。我们将在后续证明,有限自动机无法识别这个语言。
正则表达式
上一节我们介绍了用有限自动机描述语言,本节中我们来看看另一种描述方式:正则表达式。它通过一系列操作来构建描述语言的表达式。
正则运算
以下是三种基本的正则运算,它们对语言进行操作:
- 并集 (Union):A ∪ B = { w | w ∈ A 或 w ∈ B }
- 连接 (Concatenation):A ∘ B = { xy | x ∈ A 且 y ∈ B }(通常简写为 AB)
- 星号 (Kleene Star):A* = { w₁w₂...wₖ | k ≥ 0 且每个 wᵢ ∈ A }。注意,k=0 时对应空字符串 ε,因此 ε ∈ A* 总是成立。
示例:
设 A = {good, bad}, B = {boy, girl}
- A ∪ B = {good, bad, boy, girl}
- A ∘ B = {goodboy, goodgirl, badboy, badgirl}
- A* = { ε, good, bad, goodgood, goodbad, badgood, badbad, goodgoodgood, ... }(一个无限集合)
正则表达式
正则表达式使用正则运算和基本元素(如字母表符号、空字符串 ε、空集 ∅)来构建。
示例:
- Σ = {0, 1}
- Σ* 表示所有由0和1组成的字符串的集合。
- Σ*1 表示所有以1结尾的字符串。
- Σ*11Σ* 表示所有包含子串“11”的字符串。这正是我们之前自动机 M1 的语言。
一个关键结论是:正则表达式描述的语言类与有限自动机识别的语言类(即正则语言)是完全相同的。我们将在后续证明这种等价性。
正则语言的封闭性
现在我们来探讨正则语言的一个重要性质:封闭性。如果一个运算应用于某个语言类中的语言,产生的结果仍然属于该类,则称该类语言在该运算下是封闭的。
定理:正则语言在并运算下封闭
定理:如果 A₁ 和 A₂ 是正则语言,那么 A₁ ∪ A₂ 也是正则语言。
证明思路:
- 因为 A₁ 和 A₂ 是正则的,所以存在有限自动机 M₁ 和 M₂ 分别识别它们。
- 我们的目标是构造一个新的有限自动机 M 来识别 A₁ ∪ A₂。
- M 应该接受输入字符串 w,当且仅当 M₁ 接受 w 或 M₂ 接受 w。
- 直接先运行 M₁ 再运行 M₂ 不可行,因为自动机不能“倒带”输入。
- 解决方案是并行模拟 M₁ 和 M₂。即,M 同时跟踪 M₁ 和 M₂ 的状态。
- 因此,M 的状态是状态对 (r₁, r₂),其中 r₁ 是 M₁ 的当前状态,r₂ 是 M₂ 的当前状态。
- M 的起始状态是 (q₁, q₂),其中 q₁ 和 q₂ 分别是 M₁ 和 M₂ 的起始状态。
- M 的转移函数定义为:δ((r₁, r₂), a) = (δ₁(r₁, a), δ₂(r₂, a))。
- M 的接受状态集合是 { (r₁, r₂) | r₁ ∈ F₁ 或 r₂ ∈ F₂ },即只要状态对中有一个分量是原自动机的接受状态即可。
- 这样构造的 M 恰好识别 A₁ ∪ A₂。
如果 M₁ 有 k₁ 个状态,M₂ 有 k₂ 个状态,那么 M 有 k₁ × k₂ 个状态。
关于连接运算封闭性的初步讨论
正则语言在连接运算下也是封闭的,但证明更为复杂。直观想法是:给定识别 A₁ 和 A₂ 的自动机 M₁ 和 M₂,要构造识别 A₁ ∘ A₂ 的自动机 M。
M 的任务是:接受字符串 w,当且仅当存在一种方式将 w 切分为 w = xy,使得 M₁ 接受 x 且 M₂ 接受 y。
一个天真的(但有缺陷的)想法是:将 M₁ 的每个接受状态都连接到 M₂ 的起始状态。这样,当 M₁ 在读取 w 的某个前缀后进入接受状态时,就“猜测”这是切分点,并跳转到 M₂ 继续处理剩余部分。
这个方法行不通,因为对于同一个输入 w,可能存在多个可能的切分点。自动机在第一次到达 M₁ 的接受状态时,无法确定这是否是正确的切分点。如果此时跳转到 M₂ 但剩余部分不被 M₂ 接受,自动机就会错误地拒绝,即使存在更靠后的正确切分点。我们将在下节课介绍更强大的工具(非确定性有限自动机)来正确证明这个封闭性。
总结
本节课中我们一起学习了计算理论的入门知识。我们首先了解了课程的两大主题:可计算性理论和复杂性理论。然后,我们深入探讨了第一个计算模型——有限自动机,学习了它的图形表示和形式化定义,并理解了它识别的语言称为正则语言。接着,我们介绍了描述正则语言的另一种等价方式——正则表达式及其运算。最后,我们证明了正则语言在并运算下是封闭的,并开始探讨在连接运算下封闭性的证明思路,这为我们下一节课的内容做好了铺垫。




002:非确定性、闭包属性与正则表达式到NFA的转换

在本节课中,我们将学习计算理论中的一个核心概念:非确定性。我们将介绍非确定性有限自动机(NFA),并利用它来证明正则语言在连接和星号运算下的闭包性质。最后,我们将展示如何将任何正则表达式转换为等价的NFA,从而证明正则表达式描述的语言都是正则语言。
回顾与目标
上一节我们介绍了有限自动机(DFA)和正则语言,并讨论了正则运算。我们的目标是证明两种描述语言的方式——有限自动机和正则表达式——是等价的。为了向这个目标迈进,我们首先需要证明正则语言类在正则运算(并、连接、星号)下是封闭的。我们已经证明了并集运算下的封闭性,本节课我们将利用新引入的非确定性概念来完成连接和星号运算下的封闭性证明。
非确定性有限自动机(NFA)
为了克服在证明连接运算封闭性时遇到的困难(即DFA需要“预知未来”才能确定分割点),我们引入一种新的计算模型:非确定性有限自动机(NFA)。
NFA的核心特性
NFA与DFA外观相似,但有三个关键区别:
- 多值转移:对于一个状态和一个输入符号,可以有零个、一个或多个可能的下一个状态。
- 空转移(ε-转移):允许不消耗任何输入符号就从一个状态转移到另一个状态。
- 接受规则:只要存在至少一条计算路径在读完整个输入后到达接受状态,NFA就接受该输入。只有当所有可能的路径都拒绝时,NFA才拒绝输入。
NFA形式化定义
一个NFA是一个五元组 \((Q, \Sigma, \delta, q_0, F)\):
- \(Q\):有限状态集。
- \(\Sigma\):有限字母表。
- \(\delta\):转移函数,形式为 \(\delta: Q \times (\Sigma \cup \{\epsilon\}) \to \mathcal{P}(Q)\)。这里 \(\mathcal{P}(Q)\) 是 \(Q\) 的幂集(所有子集的集合)。这意味着对于每个状态和输入符号(或空串),函数给出一个可能的下一个状态集合。
- \(q_0 \in Q\):起始状态。
- \(F \subseteq Q\):接受状态集。
理解非确定性的方式
理解NFA的计算方式有多种直观角度:
- 并行计算:每当面临非确定性选择时,机器“分裂”出多个并行线程,每个线程独立处理剩余的输入。只要任一线程接受,整体就接受。
- 计算树:将整个计算过程视为一棵树。根节点是起始状态,每次非确定性选择产生新的分支。如果树中至少有一条从根到叶的路径以接受状态结束,则输入被接受。
- “幸运猜测”:想象机器在每次面临选择时,都能“幸运地”猜中那条最终能导向接受状态的路径(如果这样的路径存在的话)。
NFA与DFA的等价性
尽管NFA看起来更强大,但事实上,NFA和DFA识别的语言类是相同的,即正则语言。我们可以通过一个构造性证明将任何NFA转换为一个识别相同语言的DFA。
子集构造法
给定一个NFA \(M = (Q, \Sigma, \delta, q_0, F)\),我们构造一个等价的DFA \(M' = (Q', \Sigma, \delta', q_0', F')\)。
构造思路:DFA \(M'\) 的状态用于记录NFA \(M\) 在读取输入前缀后所有可能处于的状态集合。
以下是具体构造步骤:
- 状态集:\(Q' = \mathcal{P}(Q)\)。DFA的每个状态对应NFA状态的一个子集。
- 字母表:与NFA相同,为 \(\Sigma\)。
- 转移函数:对于 \(R \in Q'\)(即 \(R \subseteq Q\))和 \(a \in \Sigma\),定义 \(\delta'(R, a) = \bigcup_{r \in R} E(\delta(r, a))\)。这里 \(E(S)\) 表示从集合 \(S\) 中的状态出发,经过任意条(包括零条)ε-转移所能到达的所有状态的集合(即ε-闭包)。简单说,就是先看NFA中 \(R\) 里每个状态读 \(a\) 能到哪些状态,再考虑从这些状态能通过ε-转移自由到达哪些状态,所有这些状态的并集就是DFA的新状态。
- 起始状态:\(q_0' = E(\{q_0\})\),即从NFA起始状态通过ε-转移能到达的所有状态的集合。
- 接受状态集:\(F' = \{ R \in Q' \mid R \cap F \neq \emptyset \}\)。只要DFA的当前状态集合中包含至少一个NFA的接受状态,DFA就处于接受状态。
复杂度:如果NFA有 \(n\) 个状态,那么通过子集构造法得到的DFA最多可能有 \(2^n\) 个状态。这表明非确定性可以指数级地节省状态数,但也意味着模拟NFA的DFA可能非常庞大。
利用NFA证明闭包性质
拥有了NFA这个工具后,我们可以优雅地证明正则语言在连接和星号运算下的封闭性。
闭包性质:连接
定理:如果 \(A_1\) 和 \(A_2\) 是正则语言,那么它们的连接 \(A_1 \circ A_2 = \{ xy \mid x \in A_1, y \in A_2 \}\) 也是正则语言。
证明思路(使用NFA):
假设有DFA \(M_1\) 识别 \(A_1\),\(M_2\) 识别 \(A_2\)。我们构造一个NFA \(M\) 来识别 \(A_1 \circ A_2\)。
- 将 \(M_1\) 和 \(M_2\) 的状态合并。
- \(M\) 的起始状态是 \(M_1\) 的起始状态。
- 对于 \(M_1\) 中的每一个接受状态,添加一个ε-转移,使其指向 \(M_2\) 的起始状态。
- \(M_1\) 中原有的接受状态在 \(M\) 中变为非接受状态。\(M\) 的接受状态集是 \(M_2\) 的接受状态集。
工作原理:NFA \(M\) 在 \(M_1\) 中运行。每当 \(M_1\) 到达一个接受状态(意味着找到了一个可能的前缀 \(x \in A_1\)),\(M\) 就面临一个非确定性选择:可以继续在 \(M_1\) 中读取更多输入,也可以(通过ε-转移)“猜测”这里就是正确的分割点,并跳转到 \(M_2\) 开始处理剩余部分 \(y\)。如果存在一种分割方式使得 \(x \in A_1\) 且 \(y \in A_2\),那么至少有一条计算路径(即做出了正确“猜测”的路径)会最终到达 \(M_2\) 的接受状态,从而使 \(M\) 接受整个字符串。
闭包性质:星号
定理:如果 \(A\) 是正则语言,那么它的星号闭包 \(A^* = \{ x_1 x_2 ... x_k \mid k \geq 0 \text{ 且每个 } x_i \in A \}\) 也是正则语言。
证明思路(使用NFA):
假设有DFA \(M_1\) 识别 \(A\)。我们构造一个NFA \(M\) 来识别 \(A^*\)。
- 保留 \(M_1\) 的所有状态和转移。
- 添加一个新的起始状态 \(q_{start}\),它也是一个接受状态(以确保空串 \(\epsilon \in A^*\) 被接受)。
- 从新的起始状态 \(q_{start}\) 添加一个ε-转移到 \(M_1\) 的原始起始状态。
- 对于 \(M_1\) 中的每一个接受状态,添加一个ε-转移,使其指回 \(M_1\) 的原始起始状态。
工作原理:从 \(q_{start}\) 开始,NFA \(M\) 可以自由跳转到 \(M_1\) 开始运行。每当 \(M_1\) 到达一个接受状态(意味着识别出了一个“片段” \(x_i \in A\)),\(M\) 就面临非确定性选择:可以结束计算(如果当前已是输入末尾),或者通过ε-转移跳回 \(M_1\) 的起始状态,开始尝试识别下一个片段。通过这种方式,\(M\) 非确定性地“猜测”如何将输入字符串分割成多个属于 \(A\) 的片段。
从正则表达式到NFA的转换
现在,我们可以利用闭包性质来证明:任何正则表达式描述的语言都是正则语言。证明方法是给出一个将正则表达式 \(R\) 转换为等价NFA \(N\) 的算法。
转换算法(归纳构造)
正则表达式是通过基础表达式应用并、连接、星号运算递归定义的。我们的转换算法也遵循这个递归结构。
基础情况(原子表达式):
- 表达式
a(\(a \in \Sigma\)):构造一个NFA,它只接受单个字符串a。NFA: (start) --a--> ((accept)) - 表达式
ε:构造一个NFA,它只接受空串。NFA: ((start/accept)) - 表达式
∅:构造一个没有接受状态的NFA(即不接受任何字符串)。NFA: (start)
归纳步骤(复合表达式):
假设我们已经为子表达式 \(R_1\) 和 \(R_2\) 构造了等价的NFA \(N_1\) 和 \(N_2\)。
- 表达式 \(R_1 \cup R_2\):应用并集闭包构造,将 \(N_1\) 和 \(N_2\) 组合成一个新的NFA。
- 表达式 \(R_1 \circ R_2\):应用连接闭包构造,将 \(N_1\) 和 \(N_2\) 组合成一个新的NFA。
- 表达式 \(R_1^*\):应用星号闭包构造,将 \(N_1\) 转换成一个新的NFA。
通过递归地应用这些构造,我们可以为任何复杂的正则表达式构建出一个等价的NFA。由于NFA等价于DFA,这就证明了正则表达式定义的语言属于正则语言类。
转换示例
考虑正则表达式 (a ∪ ab)*。
- 为原子表达式
a和b构建NFA。 - 为表达式
ab应用连接构造,组合a和b的NFA。 - 为表达式
(a ∪ ab)应用并集构造,组合a和ab的NFA。 - 最后,为整个表达式
(a ∪ ab)*应用星号构造,处理上一步得到的NFA。
最终得到的NFA可能不是最简的,但它确实正确地识别了语言 (a ∪ ab)*。
总结



本节课我们一起学习了计算理论中一个极其重要的概念——非确定性。我们介绍了非确定性有限自动机(NFA),并证明了它与确定性有限自动机(DFA)在识别语言的能力上是等价的。利用NFA,我们轻松证明了正则语言在连接和星号运算下的闭包性质。最后,我们展示了一个递归算法,可以将任何正则表达式转换为等价的NFA,从而完成了“正则表达式描述的语言都是正则语言”这一方向的证明。在下一讲中,我们将完成等价性证明的另一半:如何将有限自动机转换为正则表达式。
003:正则泵引理,FA到正则表达式的转换

在本节课中,我们将要学习如何将有限自动机(FA)转换为等价的正则表达式,从而完成两者等价性的证明。我们还将学习一个强大的工具——泵引理,用于证明某些语言不是正则语言。最后,我们将初步接触一种更强大的计算模型——上下文无关文法。
回顾与目标
上一节我们介绍了如何将正则表达式转换为有限自动机。本节中,我们来看看如何反向操作,将有限自动机转换为正则表达式。这两部分构造共同证明了正则表达式和有限自动机在描述语言的能力上是等价的。
从FA到正则表达式
为了完成从有限自动机到正则表达式的转换,我们需要引入一个中间模型——广义非确定性有限自动机。
广义非确定性有限自动机
GNFA与NFA类似,但其转移边上的标签可以是完整的正则表达式,而不仅仅是单个符号或空串。
工作原理:当GNFA处理输入字符串时,它可以从当前状态沿着一条转移边“读取”一个子串,只要该子串属于该转移边标签所描述的正则表达式语言。它在一个步骤中读取整个子串,然后移动到目标状态。接受条件与非确定性有限自动机相同:如果存在一条路径,使得在消耗完整个输入字符串后到达接受状态,则该字符串被接受。
为了简化后续的转换构造,我们假设GNFA具有以下特殊形式:
- 只有一个接受状态,且该状态不是起始状态。
- 除了起始状态(只有出边)和接受状态(只有入边)外,其他任意两个状态之间(包括自循环)都存在转移边。缺失的边可以用空语言
∅作为标签来添加,这不会改变机器识别的语言。
可以证明,任何GNFA都可以被修改为满足这种特殊形式。
转换构造:归纳法
我们将通过归纳法(或递归过程)证明:每个GNFA都有一个等价的正则表达式。
归纳基础:考虑一个只有两个状态的GNFA(根据特殊形式,这是最小的可能)。它必须有一个起始状态 q_start 和一个接受状态 q_accept,且仅有一条从 q_start 到 q_accept 的转移边,其标签为正则表达式 R。显然,这个GNFA等价于正则表达式 R。
归纳步骤:假设我们知道如何将任何具有 k-1 个状态的GNFA转换为正则表达式。现在,我们需要转换一个具有 k 个状态的GNFA G。
- 移除一个状态:从
G中任意选择一个既非起始也非接受的状态,记为q_rip,将其移除。 - 修复损伤:移除
q_rip会破坏所有经过它的路径。对于原始GNFA中的每一对状态q_i和q_j(q_i可以是q_rip的前驱,q_j可以是q_rip的后继),我们需要确保新机器中从q_i到q_j的转移能够补偿所有曾经通过q_rip的路径。- 设从
q_i到q_rip的转移标签为R1。 - 设从
q_rip到自身的转移标签为R2。 - 设从
q_rip到q_j的转移标签为R3。 - 设从
q_i直接到q_j的转移标签为R4。 - 那么,在新GNFA中,从
q_i到q_j的新转移标签应更新为:R4 ∪ (R1)(R2)*(R3)。这个新标签涵盖了直接从q_i到q_j的路径(R4)以及所有从q_i经过q_rip(可循环任意次)再到q_j的路径(R1)(R2)*(R3)。
- 设从
- 对每一对
(q_i, q_j)执行上述操作后,我们得到了一个具有k-1个状态的GNFAG‘,并且L(G’) = L(G)。 - 根据归纳假设,我们可以将
G‘转换为等价的正则表达式。
通过不断移除状态,我们最终会得到一个2状态的GNFA,然后直接得到最终的正则表达式。
由于DFA是GNFA的一种特例(其转移标签是单符号的正则表达式),因此上述构造也完成了从DFA到正则表达式的转换。至此,我们证明了正则表达式、DFA、NFA和GNFA在描述语言的能力上是等价的。
证明语言非正则:泵引理
现在我们已经了解了正则语言能做什么。接下来,我们看看如何证明某些语言超出了有限自动机的能力范围。核心工具是泵引理。
泵引理陈述

泵引理:若 A 是一个正则语言,则存在一个数 p(泵长度),使得对于 A 中任何长度不小于 p 的字符串 s,都可以将其分为三段 s = xyz,满足以下条件:
- 对于每个
i ≥ 0,字符串xy^iz ∈ A(即y可以被“泵”送,重复任意次,包括零次)。 |y| > 0(y非空)。|xy| ≤ p(前两段x和y的总长度不超过p)。
直观理解:任何足够长的正则语言字符串,都包含一个非空的、靠近开头的子串 y,这个子串可以重复任意多次,生成的新字符串仍然属于该语言。
泵引理证明思路
设 M 是识别正则语言 A 的一个DFA,其状态数为 p。考虑 A 中一个长度至少为 p 的字符串 s。当 M 处理 s 时,它需要经过 p+1 个步骤(p+1 个状态,包括起始状态)。根据鸽巢原理,在 p+1 个步骤中访问 p 个状态,必然有某个状态被重复访问。设第一次到达该重复状态时的字符串前缀为 x,两次访问之间读取的字符串为 y(y 非空,因为状态重复意味着有循环),剩余部分为 z。显然,M 也能接受 xy^iz(i≥0),因为可以沿着循环走 i 圈。并且,由于第一次重复发生在 p 步之内,所以 |xy| ≤ p。
应用泵引理证明非正则性
泵引理给出了所有正则语言都必须满足的必要条件。因此,要证明一个语言 B 不是正则的,我们可以:
- 假设
B是正则的,则泵引理成立,存在泵长度p。 - 精心选择一个长度至少为
p的、属于B的字符串s。 - 证明对于
s任何满足泵引理条件(s=xyz,|y|>0,|xy|≤p)的划分,都存在某个i(通常是i=0或i=2)使得xy^iz不属于B。 - 这与泵引理矛盾,故假设错误,
B不是正则语言。
以下是应用示例:
例1:证明语言 D = {0^k 1^k | k ≥ 0} 不是正则的。
- 假设
D正则,泵长度为p。 - 选择字符串
s = 0^p 1^p ∈ D,其长度2p ≥ p。 - 根据泵引理条件3,
|xy| ≤ p,且y非空,因此y必然全部由0组成。 - 考虑
i=2,则xy^2z中0的数量将大于p,而1的数量仍为p,故xy^2z ∉ D。 - 矛盾。因此
D不是正则语言。
例2:证明语言 F = {ww | w ∈ {0,1}*} 不是正则的。
- 假设
F正则,泵长度为p。 - 选择字符串
s = 0^p1 0^p1 ∈ F(它是w=0^p1重复两次)。 - 根据条件3,
|xy| ≤ p,所以y全部由0组成。 - 考虑
i=2,则xy^2z将具有0...0[更多0]...0 1 0^p 1的形式,这不再是两个相同字符串的连接,故xy^2z ∉ F。 - 矛盾。因此
F不是正则语言。
有时,结合正则语言的闭包性质和已知的非正则语言,可以更简洁地证明一个语言非正则。
例3:证明语言 B = {w | w中0和1的数量相等} 不是正则的。
- 假设
B正则。 - 正则语言在交集下封闭。
0*1*是正则语言(正则表达式描述)。 - 如果
B正则,则B ∩ 0*1*也正则。 - 但
B ∩ 0*1* = {0^k 1^k | k ≥ 0} = D,我们已证D非正则。 - 矛盾。因此
B不是正则语言。
引入上下文无关文法
有限自动机无法识别像 {0^n1^n} 这样的语言。本节最后,我们简要介绍一种更强大的模型——上下文无关文法,它可以描述这类语言。
一个CFG G 由四部分组成:
- 变元(非终结符):出现在规则左侧的符号,表示可被替换的语法范畴。
- 终结符:构成最终字符串的基本符号,不出现在规则左侧。
- 规则(产生式):形式为
变元 -> 字符串,其中字符串由变元和终结符组成。 - 起始变元:推导开始的变元。
字符串生成过程:从起始变元开始,反复将当前字符串中的某个变元替换为其某个规则的右侧字符串,直到字符串中不再包含任何变元(即全部是终结符)。此时得到的终结符串就是由该文法生成的语言中的一个字符串。
示例:考虑文法 G1:
S -> 0S1 | R
R -> ε
变元:S, R。终结符:0, 1。起始变元:S。
它可以生成字符串 0011,推导过程如下(也可用派生树表示):
S => 0S1 => 00S11 => 00R11 => 0011。
实际上,L(G1) = {0^n1^n | n ≥ 0},这正是我们之前用泵引理证明为非正则的语言。这表明CFG比有限自动机更强大。
总结
本节课中我们一起学习了:
- FA与正则表达式的等价性完成:通过引入广义非确定性有限自动机(GNFA)并使用归纳构造,证明了可以从有限自动机构造出等价的正则表达式。结合上节课的内容,正则表达式、DFA、NFA、GNFA在描述语言的能力上完全等价。
- 泵引理:学习了用于证明语言不是正则语言的核心工具——泵引理。我们理解了其原理(基于DFA状态数的鸽巢原理),并掌握了如何使用反证法应用它来证明特定语言的非正则性。
- 上下文无关文法初探:为了突破正则语言的限制,我们引入了上下文无关文法(CFG)的基本概念,包括其组成部分(变元、终结符、规则、起始变元)和字符串的生成过程,并通过例子看到CFG可以描述某些非正则语言。



下节课我们将更深入地研究上下文无关文法及其对应的自动机模型。
004:下推自动机,CFG到PDA的转换和反向转换 🧠

在本节课中,我们将继续探索上下文无关文法,并学习其对应的自动机模型——下推自动机。我们将看到这两种模型在表达能力上是等价的,并学习如何将上下文无关文法转换为下推自动机。
上下文无关文法回顾
上一节我们介绍了正则语言及其模型。本节中,我们来看看更强大的模型——上下文无关文法。
一个上下文无关文法由四个部分组成:
- 变量:出现在规则左侧的符号。
- 终结符:构成生成字符串的符号。
- 规则:形式为
变量 -> 变量和终结符组成的字符串。 - 起始变量:推导过程的起点。
文法的语言是所有可以从起始变量推导出的、仅由终结符组成的字符串的集合,称为上下文无关语言。
以下是使用文法生成字符串 0011 的例子:
S -> 0S1 | R
R -> ε
推导过程为:S => 0S1 => 00S11 => 00R11 => 0011。
下推自动机介绍
有限自动机的内存有限。为了增强其能力,我们引入下推自动机。它在有限自动机的基础上增加了一个栈作为辅助存储。
栈是一种后进先出的存储结构。操作包括:
- 压入:向栈顶写入一个新符号。
- 弹出:从栈顶读取并移除一个符号。
下推自动机可以非确定性地运行,并且能够利用栈来记忆信息,从而识别一些有限自动机无法识别的语言,例如语言 {0^k 1^k | k ≥ 0}。
形式化定义与示例
下推自动机是一个六元组 (Q, Σ, Γ, δ, q0, F):
Q:状态集合Σ:输入字母表Γ:栈字母表δ:转移函数Q × (Σ∪{ε}) × (Γ∪{ε}) → P(Q × (Γ∪{ε}))q0:起始状态F:接受状态集合
转移函数决定了在特定状态、读取特定输入符号(或ε)和栈顶符号(或ε)时,机器可以进入的新状态以及在栈顶写入的新符号(或ε)。
考虑语言 {ww^R | w ∈ {0,1}*},即一个字符串后接其反转。识别它的下推自动机策略如下:
- 非确定性地猜测字符串的中点。
- 中点之前:读取输入符号并将其压入栈中。
- 中点之后:读取输入符号,并与从栈中弹出的符号进行比较。
- 如果所有符号都匹配且栈最终为空,则接受。
非确定性在这里至关重要,因为机器在读取时无法预先知道中点位置。
从CFG到PDA的转换
上下文无关文法和下推自动机在表达能力上是等价的。我们现在学习如何将上下文无关文法转换为等价的下推自动机。
核心思想是:让PDA模拟文法的最左推导。PDA将使用栈来存储当前的派生字符串(即一系列变量和终结符)。
转换规则如下:
- 将文法的起始符号压入栈。
- 重复以下步骤:
- 如果栈顶是一个变量,则非确定性地选择该变量的一条规则,用其右侧的字符串替换栈顶的变量。
- 如果栈顶是一个终结符,则从输入中读取下一个符号。如果两者匹配,则弹出栈顶的终结符;否则,该计算路径拒绝。
- 如果栈顶是ε,则直接弹出它。
- 当输入被完全读取,且栈为空时,接受。
这种策略确保了PDA总是在栈顶进行替换操作,符合栈的访问特性。
总结与关系
本节课中我们一起学习了:
- 回顾了上下文无关文法的形式化定义。
- 引入了下推自动机,这是一种拥有栈内存的、更强大的自动机模型。
- 学习了如何将上下文无关文法转换为等价的下推自动机,通过让PDA模拟文法的推导过程。
我们目前了解的模型及其关系可以总结如下:
- 正则语言:由有限自动机识别,由正则表达式描述。
- 上下文无关语言:由下推自动机识别,由上下文无关文法描述。
- 正则语言是上下文无关语言的一个真子集。这意味着所有正则语言都是上下文无关的,但存在是上下文无关而非正则的语言(例如
{0^k 1^k})。


在接下来的课程中,我们将介绍更强大的图灵机模型。
005:上下文无关泵引理与图灵机

在本节课中,我们将学习如何证明某些语言不是上下文无关的,并正式引入图灵机这一核心计算模型。我们将从回顾上下文无关语言开始,然后介绍上下文无关泵引理,最后详细定义图灵机及其相关概念。
回顾:上下文无关语言
上一节我们介绍了上下文无关文法与下推自动机,它们是描述上下文无关语言的两种等价方式。上下文无关语言比正则语言(有限自动机描述的语言)能力更强,因为下推自动机增加了栈这一存储结构。
上下文无关语言在正则运算(并、连接、星号)下是封闭的。然而,它们不在交运算下封闭。一个重要的推论是:上下文无关语言与正则语言的交集仍是上下文无关的。这是因为下推自动机可以在其有限控制中模拟一个有限自动机。但两个上下文无关语言的交集则不一定,因为单个栈难以同时模拟两个栈的行为。
上下文无关泵引理
为了证明某些语言不是上下文无关的,我们需要一个类似于正则语言泵引理的工具。这就是上下文无关泵引理。
上下文无关泵引理:若语言 A 是上下文无关的,则存在一个泵长度 p,使得 A 中任何长度不小于 p 的字符串 s 都可以被划分为五部分:s = uvxyz,并满足以下三个条件:
- 对于每一个 i ≥ 0,有 uvⁱxyⁱz ∈ A。
- |vy| > 0(即 v 和 y 不同时为空串)。
- |vxy| ≤ p。
这个引理的核心思想是:在上下文无关文法生成的长字符串的语法分析树中,必然存在一条从根节点到叶子的长路径。由于文法中变量数量有限,这条路径上必然有某个变量重复出现。利用这个重复出现的变量,我们可以对字符串进行“切割与粘贴”,从而得到可泵的性质。
应用泵引理证明语言非上下文无关
证明思路与正则泵引理类似,采用反证法:
- 假设语言 L 是上下文无关的,则泵引理成立,存在泵长度 p。
- 精心选择一个属于 L 且长度 ≥ p 的字符串 s。
- 根据泵引理,s 可被划分为 uvxyz 并满足三个条件。
- 证明无论怎样划分,只要满足条件2和3,总存在某个 i(通常是 i=0 或 i=2)使得 uvⁱxyⁱz 不属于 L,从而产生矛盾。
- 因此,最初的假设错误,L 不是上下文无关语言。
示例1:证明 B = {0ⁿ1ⁿ2ⁿ | n ≥ 0} 不是上下文无关语言。
假设 B 是上下文无关的,泵长度为 p。选择字符串 s = 0ᵖ1ᵖ2ᵖ。根据泵引理条件3,子串 vxy 的长度不超过 p,因此它不可能同时包含0、1和2三种符号。
- 如果 vxy 只包含0和1,那么当我们将 v 和 y 泵入(例如令 i=2),字符串中0或1的数量会增加,但2的数量不变,导致三者数量不等,新字符串不在 B 中。
- 如果 vxy 只包含1和2,情况类似,泵操作会破坏1和2的数量相等性。
- 如果 vxy 只包含单一符号,泵操作同样会破坏数量相等关系。
因此,无论如何划分,泵操作都会使新字符串脱离语言 B,产生矛盾。故 B 不是上下文无关语言。
示例2:证明 F = {ww | w ∈ {0,1}*} 不是上下文无关语言。
假设 F 是上下文无关的,泵长度为 p。一个错误的选择是 s = 0ᵖ10ᵖ1,因为它可能被划分为 vxy 仅包含中间区域,泵操作后仍能保持 ww 的形式。正确的选择是 s = 0ᵖ1ᵖ0ᵖ1ᵖ。由于 |vxy| ≤ p,它无法横跨两个0的区块或两个1的区块。
- 如果 vxy 完全位于前半段(如0的区块中),泵操作会使前半段0的数量变化,而后半段不变,破坏 ww 形式。
- 如果 vxy 横跨前半段0区块和1区块,泵操作会使符号顺序混乱(如出现0101),同样破坏 ww 形式。
对于其他划分情况,分析类似,总能找到泵操作后不在 F 中的情况。因此 F 不是上下文无关语言。
引入图灵机
上下文无关语言和下推自动机的能力仍然有限,无法完成许多我们认为是计算机常规任务的操作(如判断 0ⁿ1ⁿ2ⁿ)。现在,我们引入图灵机作为本课程后续的核心计算模型,它更接近我们对通用计算机的直观理解。
图灵机直观描述
图灵机由以下几个部分组成:
- 无限长的磁带:被划分为方格,每个方格可存放一个符号。磁带右端无限延伸,初始时输入字符串存放在磁带左端,其余部分为空白符号(记为
␣)。 - 读写头:可以读取当前所指方格内的符号,也可以写入新符号来替换旧符号,并且可以根据指令向左或向右移动一格。
- 有限状态控制器:包含有限的状态集合,以及一个控制机器运行的规则(转移函数)。
图灵机的运行:从起始状态和读写头指向输入最左端开始,根据当前状态和读写头读到的符号,查找转移函数,决定:1) 下一个状态;2) 写入当前方格的符号;3) 将读写头向左(L)或向右(R)移动一格。这一过程不断重复。
图灵机通过进入特定的接受状态或拒绝状态来停机,并相应地表征对输入的“接受”或“拒绝”。如果机器永远无法进入这两个状态,则称它不停机或循环。
图灵机形式化定义
一个图灵机 M 是一个七元组:(Q, Σ, Γ, δ, q₀, q_accept, q_reject)
- Q:有限状态集。
- Σ:输入字母表,不包括空白符号
␣。 - Γ:磁带字母表,满足 Σ ⊆ Γ 且
␣ ∈ Γ。它包含所有可以出现在磁带上的符号。 - δ:转移函数,δ: Q × Γ → Q × Γ × {L, R}。例如,δ(q, a) = (r, b, R) 表示在当前状态 q 读到符号 a 时,转移到状态 r,在当前方格写入符号 b,然后将读写头右移一格。
- q₀ ∈ Q:起始状态。
- q_accept ∈ Q:接受状态。
- q_reject ∈ Q:拒绝状态,且 q_accept ≠ q_reject。
图灵机示例:识别 B =
以下是该图灵机的一种非最优但直观的工作流程描述:
- 从左向右扫描,检查输入格式是否为
a*b*c*(即所有a在前,接着是所有b,最后是所有c)。若发现符号顺序错误,则进入拒绝状态。 - 将读写头移回最左端。
- 执行一次“扫描-标记”循环:
a. 向右扫描,找到第一个未被标记的a,将其标记(如改写为X)。
b. 继续向右扫描,找到第一个未被标记的b,将其标记。
c. 继续向右扫描,找到第一个未被标记的c,将其标记。
d. 将读写头移回最左端。 - 检查标记情况:
- 如果在上一次循环中,恰好标记了最后一个
a、最后一个b和最后一个c,则说明最初数量相等,进入接受状态。 - 如果还有未被标记的
a、b或c,则返回步骤3继续循环。 - 如果某种符号已被标记完,但其他符号还有剩余(例如,找不到未被标记的
a,但还有未标记的b),则说明最初数量不等,进入拒绝状态。
- 如果在上一次循环中,恰好标记了最后一个
这个例子展示了图灵机如何利用读写能力和双向移动来执行比下推自动机更复杂的计数和匹配任务。
图灵可识别语言与图灵可判定语言
- 图灵可识别语言:如果存在一台图灵机 M,使得对于语言 L 中的每个字符串,M 都接受;对于不在 L 中的字符串,M 要么拒绝(停机拒绝),要么永不停机。则称 M 识别 L,L 是图灵可识别的。
- 图灵可判定语言:如果存在一台图灵机 M,它对于任何输入字符串都会在有限步内停机(即进入接受或拒绝状态),并且它接受的语言恰好是 L。则称 M 判定 L,L 是图灵可判定的。
显然,每台判定器也是一台识别器,因此所有图灵可判定语言都是图灵可识别的。反之则不然,存在一些语言可以被图灵机识别,但没有任何图灵机可以判定它(即对某些输入,识别它的图灵机可能永不停机)。我们将在后续课程中看到这样的例子。
至此,我们得到了计算模型的语言层次结构:正则语言 ⊆ 上下文无关语言 ⊆ 图灵可判定语言 ⊆ 图灵可识别语言。
总结


本节课我们一起学习了两个主要内容。首先,我们介绍了上下文无关泵引理,这是一个用于证明特定语言不属于上下文无关语言类的有力工具,其证明基于对长字符串语法分析树中变量重复出现的“切割与粘贴”论证。其次,我们正式引入了图灵机模型,定义了其基本组件和工作原理,并区分了图灵可识别语言与图灵可判定语言。图灵机以其无限的存储能力和灵活的读写访问,成为了我们研究计算理论的基础模型。在接下来的课程中,我们将深入探索图灵机的能力与极限。
006:TM变体,丘奇-图灵论题 🧠

在本节课中,我们将深入学习图灵机模型。我们将探讨图灵机的几种变体,并证明它们在计算能力上是等价的。这一等价性将引导我们理解丘奇-图灵论题——一个关于算法本质的核心思想。我们还将介绍如何将复杂对象编码为字符串,以便作为图灵机的输入。
图灵机回顾 🔄
上一节我们介绍了图灵机模型。图灵机由一个有限状态控制器、一个无限长的纸带和一个读写头组成。对于任意输入,图灵机有三种可能的结果:接受、拒绝或循环(永不停止)。
- 图灵可识别语言:如果存在一个图灵机接受该语言中的所有字符串,则该语言是图灵可识别的。记作 T-recognizable。
- 图灵可判定语言:如果存在一个图灵机(称为判定器)在所有输入上都停机(接受或拒绝),则该语言是图灵可判定的。记作 T-decidable。
图灵机将成为我们通用计算的标准模型。本课将论证,所有“合理”的计算模型在能力上都是等价的,因此选择图灵机作为基础模型是合理的。
图灵机变体及其等价性 ⚖️
现在,我们来看看图灵机的几种变体,并证明它们与基本单带图灵机是等价的。
多带图灵机
多带图灵机拥有多条纸带,每条纸带都有自己的读写头。输入通常呈现在一条专门的输入带上,其他工作带初始为空白。在每一步,机器可以读取所有带头下的符号,根据当前状态和这些符号决定如何写入新符号并移动每个头。
定理:一个语言是(单带)图灵可识别的,当且仅当它被某个多带图灵机识别。
证明思路:
- 正向:单带图灵机本身就是只拥有一条带的多带图灵机,因此显然成立。
- 反向:我们需要将多带图灵机
M模拟为单带图灵机S。S在其单条纸带上为M的每一条带分配一个“块”。- 每个块存储对应纸带的内容。
- 为了记录
M每个读写头的位置,S使用带点的符号(例如Ȧ)来标记头的位置。 - 为了分隔不同的块,
S使用特殊的分隔符(如#)。 S通过扩大其带字母表来包含这些新符号(带点符号和分隔符)。- 模拟
M的一步时,S需要扫描整个纸带来收集所有带头下的信息,然后更新状态和各块内容,并移动“点”来模拟头的移动。 - 如果某个块的空间不足,
S会执行“移位”操作来腾出空间。 - 如果
S模拟到M进入接受或拒绝状态,则S也做同样操作。
通过这种构造,单带机 S 可以完全模拟多带机 M 的行为。
非确定性图灵机
非确定性图灵机的转移函数允许多种可能的下一个步骤。它接受一个输入,只要存在一条计算路径最终进入接受状态。
定理:一个语言是图灵可识别的,当且仅当它被某个非确定性图灵机识别。
证明思路:
- 正向:确定性图灵机是非确定性图灵机的一种特例(从不分支),因此成立。
- 反向:我们需要将非确定性图灵机
N模拟为确定性图灵机D。- 将
N的非确定性计算想象成一棵树。 D的任务是系统地搜索这棵树,寻找接受路径。D使用其纸带来存储和管理N的不同计算“线程”。- 它将纸带划分为多个块,每个块代表一个线程在某个时刻的完整快照:纸带内容、带头位置(用点符号标记)以及当前状态(通过扩大字母表,用特殊符号写在块上)。
D以广度优先的方式模拟所有线程。当一个线程非确定性地分支时,D复制对应的块以创建新的线程。D逐步执行所有活跃的线程。如果任何线程进入接受状态,D就接受输入。- 如果所有可能的线程都拒绝或永不停止,
D可能永远运行(拒绝循环)。
- 将
枚举器
枚举器是一种特殊的图灵机变体,它没有输入带,而是连接了一个“打印机”。它从完全空白的纸带开始运行,并在程序控制下周期性地打印字符串。枚举器生成的语言就是它打印出的所有字符串的集合。
定理:一个语言是图灵可识别的,当且仅当它是某个枚举器的语言。
证明思路:
- 从枚举器
E到识别器M:M以输入字符串w启动。M模拟E的运行。- 每当
E打印出一个字符串x时,M就检查x是否等于w。 - 如果相等,
M接受。 - 如果
E停止且从未打印w,则M拒绝。 - 如果
E永不停止且从未打印w,则M也永不停止(拒绝循环)。
- 从识别器
M到枚举器E:E需要打印出所有被M接受的字符串。- 关键是不能简单地让
E按顺序对每个字符串w_i运行M直到完成,因为M可能在某个w_i上循环,导致E卡住。 - 正确的做法是采用“分时”技术:
E系统地模拟M在所有可能字符串w_1, w_2, w_3, ...上的运行,但以交错的方式进行(例如,第i轮模拟所有字符串的前i步)。 - 每当
E发现M在某个字符串w上进入接受状态,它就打印出w。 - 注意:这样生成的字符串顺序不一定是字符串的自然顺序(短字符串在前),因为接受得快的字符串可能先被打印出来。对于可判定语言,可以构造出按顺序打印的枚举器。
丘奇-图灵论题 📜
上一节我们证明了多种图灵机变体的等价性。历史上,在20世纪30年代,图灵、丘奇等人提出了多种形式化“算法”或“有效过程”的数学模型(如图灵机、λ演算、递归函数等)。一个重大的发现是,所有这些看似不同的模型都被证明在计算能力上是等价的。
这一现象促使丘奇-图灵论题的提出:
任何直观上“可计算”的函数(或可判定的问题),都可以被图灵机计算。
这是一个论题,而非可被数学证明的定理,因为它连接了形式化的数学概念(图灵机)和直观的、哲学性的概念(算法)。然而,由于所有已知的合理计算模型都与图灵机等价,该论题被广泛接受,并成为计算理论的基石。
意义:丘奇-图灵论题使得我们可以用图灵机来精确地讨论“什么问题是可计算的”。例如,希尔伯特第十问题(寻找整数解的多项式方程)在有了图灵机模型后,才得以被证明是不可判定的(即不存在解决该问题的通用算法)。
编码与高级描述 🖥️
既然图灵机只接受字符串输入,当我们需要处理更复杂的对象(如自动机、图、多项式等)时,必须先将它们编码为字符串。
编码表示:我们用 <O> 表示对象 O 的字符串编码。多个对象可以编码为 <O1, O2>。
字符串对编码:简单地将两个字符串拼接 (xy) 不是好的编码方式,因为无法唯一地解码。需要引入分隔符或其他机制。
图灵机的高级描述:得益于丘奇-图灵论题,在描述算法时,我们不再需要写出图灵机详细的状态和转移函数。我们可以使用高级的、非形式的英文描述,只要描述清楚、每一步是有限的操作、并且显然可以在图灵机上实现即可。
例如,识别语言 {a^k b^k c^k | k ≥ 0} 的图灵机可以描述为:
- 检查输入格式是否为
a*b*c*,否则拒绝。 - 从左到右扫描,依次将每个
a、b、c标记为已读(或删除)。 - 如果所有
a、b、c的数量都匹配,则接受;否则拒绝。
总结 🎯
本节课我们一起学习了:
- 图灵机变体的等价性:证明了多带图灵机、非确定性图灵机、枚举器都与基本的单带确定性图灵机在语言识别能力上等价。
- 丘奇-图灵论题:基于各种模型的等价性,理解了这一核心论题——图灵机抓住了“算法”或“有效计算”的本质。
- 编码与描述:学习了如何将复杂对象编码为字符串输入,并开始使用高级描述来指定图灵机(算法),这将在后续课程中成为我们主要的讨论方式。



这些概念奠定了我们研究计算理论的基础:现在我们有了一个坚实、统一且强大的模型(图灵机)来探讨计算的极限。
007:自动机和语法的决策问题 🧠

在本节课中,我们将学习如何为各种自动机和语法相关的决策问题设计图灵机算法。我们将从简单的确定性有限自动机(DFA)问题开始,逐步深入到更复杂的上下文无关文法(CFG)问题,并最终触及图灵机本身的问题。我们将看到,许多关于正则语言和上下文无关语言的问题是可判定的,但某些问题(如文法的等价性)则不是。
回顾:图灵机与可判定性
上一节我们介绍了图灵机作为通用计算模型。本节中,我们来看看如何利用图灵机解决具体的决策问题。
图灵机在输入字符串 W 上运行时,有三种可能结果:
- 接受
W(停机并接受)。 - 拒绝
W(停机并拒绝)。 - 在
W上永远运行(通过循环拒绝)。
如果一台图灵机在所有输入上都保证停机,我们称它为判定器,它所识别的语言是可判定的。
为了将复杂对象(如自动机、文法)作为图灵机的输入,我们使用编码。我们用尖括号 <...> 表示一个对象的字符串编码。例如,<B, w> 表示将 DFA B 和字符串 w 编码成一个字符串。
DFA 的接受问题 ✅
我们首先看一个简单的问题:给定一个 DFA B 和一个字符串 w,B 是否接受 w?我们将此问题表述为语言 A_DFA。
A_DFA = { <B, w> | B 是一个 DFA,且 B 接受 w }
我们可以构造一个图灵机 D_DFA 来判定 A_DFA。以下是 D_DFA 的描述:
- 输入检查:检查输入字符串
S是否为<B, w>的有效编码形式。如果不是,则拒绝。 - 模拟计算:在输入
w上模拟 DFAB的计算。 - 输出结果:
- 如果模拟结束时
B处于接受状态,则接受。 - 如果模拟结束时
B处于非接受状态,则拒绝。
- 如果模拟结束时
由于 DFA 对任何输入都会在恰好 |w| 步后停止,因此 D_DFA 总是会停机,它是一个判定器。
NFA 的接受问题 🔄
现在考虑 NFA 的接受问题:给定一个 NFA B 和一个字符串 w,B 是否接受 w?语言 A_NFA 定义类似。
A_NFA = { <B, w> | B 是一个 NFA,且 B 接受 w }
我们可以构造判定器 D_NFA。这里的关键是,我们可以利用已知的等价性转换,而不是直接模拟可能带有 ε 转移的 NFA。
D_NFA 的算法如下:
- 输入检查:检查输入是否为
<B, w>的有效编码,其中B是 NFA。 - 转换:使用子程序(或构造)将 NFA
B转换为等价的 DFAB'。 - 调用判定器:在输入
<B', w>上运行我们已有的 DFA 判定器D_DFA。 - 输出结果:
D_DFA接受则接受,D_DFA拒绝则拒绝。
这个例子展示了“归约”的思想:将一个未知问题(A_NFA)转化为一个已解决问题(A_DFA)。
DFA 的空性问题 🚫
接下来,我们考虑一个关于 DFA 本身性质的问题:给定一个 DFA B,它的语言是否为空集?即,L(B) = ∅ 吗?
E_DFA = { <B> | B 是一个 DFA,且 L(B) = ∅ }
判定器 D_E_DFA 可以通过检查从起始状态是否能到达任何接受状态来判断。
算法描述(标记法):
- 标记起始状态:标记 DFA
B的起始状态。 - 迭代标记:重复以下步骤,直到没有新状态被标记:
- 对于每一个已标记的状态,标记所有从该状态通过一条边能到达的未标记状态。
- 检查结果:
- 如果没有接受状态被标记,则接受(语言为空)。
- 如果有接受状态被标记,则拒绝(语言非空)。
这个算法本质上是图搜索(如广度优先搜索),它总是会终止。
DFA 的等价性问题 ⚖️
更复杂一些:给定两个 DFA A 和 B,它们是否识别相同的语言?
EQ_DFA = { <A, B> | A 和 B 都是 DFA,且 L(A) = L(B) }
我们可以巧妙地利用对称差和空性测试来解决。思路是:构造一个新的 DFA C,使其语言恰好是 L(A) 和 L(B) 的对称差(即在 A 中但不在 B 中,或在 B 中但不在 A 中的字符串集合)。如果这个对称差是空的,那么两个语言就相等。
判定器 D_EQ_DFA 的算法:
- 输入:
<A, B>。 - 构造 DFA
C:利用 DFA 对补集、交集和并集的封闭性,构造 DFAC,使得L(C) = (L(A) ∩ L(B)的补集) ∪ (L(B) ∩ L(A)的补集)。 - 测试空性:在输入
<C>上运行 DFA 空性判定器D_E_DFA。 - 输出结果:
- 如果
D_E_DFA接受(即L(C)为空),则接受(L(A) = L(B))。 - 如果
D_E_DFA拒绝(即L(C)非空),则拒绝(L(A) ≠ L(B))。
- 如果
正则表达式的等价性问题 ➡️
基于 DFA 等价性可判定的结论,我们可以立即推断出正则表达式的等价性也是可判定的。
EQ_REX = { <R1, R2> | R1 和 R2 是正则表达式,且 L(R1) = L(R2) }
判定算法非常简单:
- 使用已知算法将正则表达式
R1和R2分别转换为等价的 DFAA1和A2。 - 在
<A1, A2>上运行 DFA 等价性判定器D_EQ_DFA。
这展示了模型等价性的力量:一旦我们在一个模型(如 DFA)中解决了问题,通过可计算的转换,该解决方案就自动适用于所有等价模型(如 NFA、正则表达式)。
CFG 的接受问题 📝
现在我们将注意力转向上下文无关文法(CFG)。第一个问题是:给定一个 CFG G 和一个字符串 w,G 是否能生成 w?
A_CFG = { <G, w> | G 是一个 CFG,且 w ∈ L(G) }
直接尝试所有推导是不可行的,因为可能有无穷多推导。解决的关键是乔姆斯基范式(CNF)。任何 CFG 都可以转化为 CNF,在 CNF 中,所有规则只有两种形式:
A -> BC(变量生成两个变量)A -> a(变量生成一个终结符)
CNF 的一个重要性质是:任何长度为 n 的字符串 w,如果它能被生成,那么存在一个恰好使用 2n - 1 步的推导。
基于此,判定器 D_A_CFG 的算法如下:
- 转换:将输入文法
G转换为等价的 CNF 文法G'。 - 有限搜索:系统地枚举
G'中所有长度不超过2|w| - 1步的推导。 - 检查:如果任何一个推导生成了
w,则接受;如果所有可能的推导都检查完毕仍未生成w,则拒绝。
由于搜索空间是有限的(步数有上限),该算法总会停机。
推论:每个上下文无关语言都是可判定的。因为对于任意 CFL L,存在生成它的文法 G。我们可以构造一个图灵机,将 G 硬编码到机器中,对于输入 w,它只需运行 D_A_CFG 在 <G, w> 上即可。虽然我们可能不知道具体的 G,但它的存在性保证了判定器的存在性。
CFG 的空性问题 🚫
给定一个 CFG G,它的语言是否为空?
E_CFG = { <G> | G 是一个 CFG,且 L(G) = ∅ }
我们可以使用一种从终结符反向标记的算法。
判定器算法(标记法):
- 标记终结符:标记文法中所有出现的终结符。
- 迭代标记变量:重复以下步骤,直到没有新变量被标记:
- 对于每条规则
A -> X1 X2 ... Xk,如果右侧的每一个符号X1, X2, ..., Xk都已经被标记(即每个符号都能推导出纯终结符串),则标记变量A。
- 对于每条规则
- 检查起始变量:
- 如果起始变量
S被标记了,则拒绝(语言非空)。 - 如果起始变量
S未被标记,则接受(语言为空)。
- 如果起始变量
CFG 的等价性与歧义性 ⚠️
现在,我们遇到两个不可判定的问题。
-
CFG 等价性问题:
EQ_CFG= {<G, H>|G和H是 CFG,且L(G) = L(H)}
这个问题是不可判定的。我们不能像处理 DFA 那样使用对称差构造,因为上下文无关语言对补运算和交集不封闭。 -
CFG 歧义性问题:
AMB_CFG= {<G>|G是一个歧义的 CFG }
这个问题也是不可判定的。不存在一个算法能判定任意给定的 CFG 是否是歧义的。
图灵机的接受问题 🤖
最后,我们来到图灵机本身的核心问题:给定一个图灵机 M 和一个输入字符串 w,M 会接受 w 吗?
A_TM = { <M, w> | M 是一个图灵机,且 M 接受 w }
我们将证明(在下节课)A_TM 是不可判定的。这是计算理论中第一个,也是最重要的一个不可判定性问题。
然而,A_TM 是图灵可识别的。我们可以构造一个识别器 U,称为通用图灵机。
U 的算法非常直接:
- 输入:
<M, w>。 - 模拟:在输入
w上模拟图灵机M的运行。 - 输出:
- 如果在模拟过程中观察到
M进入了接受状态,则U接受。 - 如果在模拟过程中观察到
M进入了拒绝状态,则U拒绝。 - 如果
M永不停机(在w上循环),那么U也将永不停机。
- 如果在模拟过程中观察到
注意,U 无法主动检测 M 是否“永不”停机并据此拒绝。它只能通过模拟来观察 M 的行为。因此,U 是一个识别器,而不是判定器。
通用图灵机 U 在历史上意义重大,它体现了“存储程序”的概念,即数据和指令以相同形式存储和处理,这为现代计算机的冯·诺依曼架构奠定了基础。
总结 📚
本节课中我们一起学习了多种关于自动机和文法的决策问题,并为其设计了图灵机算法:
-
可判定的问题:
- DFA/NFA 的接受问题 (
A_DFA,A_NFA) - DFA 的空性问题 (
E_DFA) - DFA 的等价性问题 (
EQ_DFA) - 正则表达式的等价性问题 (
EQ_REX) - CFG 的接受问题 (
A_CFG) - CFG 的空性问题 (
E_CFG) - (推论)所有上下文无关语言都是可判定的。
- DFA/NFA 的接受问题 (
-
不可判定的问题(我们了解到其结论,证明将在后续课程进行):
- CFG 的等价性问题 (
EQ_CFG) - CFG 的歧义性问题 (
AMB_CFG) - 图灵机的接受问题 (
A_TM) —— 它是图灵可识别的,但不可判定。
- CFG 的等价性问题 (


我们还学习了重要的解题技巧,如模型转换(NFA 转 DFA)、利用封闭性构造新自动机、归约到已解决问题,以及使用乔姆斯基范式来限定搜索空间。这些方法是我们分析计算问题可判定性的基础工具。
008:不可判定性


在本节课中,我们将学习不可判定性的概念。我们将首先回顾之前讨论过的自动机和文法的性质测试过程,然后介绍对角线法,并利用它证明图灵机接受问题(ATM)是不可判定的。接着,我们将探讨ATM的补集是不可识别的,并引入归约法来证明其他问题(如停机问题)的不可判定性。
对角线法与集合大小比较
上一节我们介绍了测试各种自动机和文法性质的过程。本节中,我们来看看一种证明问题不可判定的核心方法——对角线法。为了引入这个方法,我们需要先了解如何比较无限集合的大小。
对于有限集合,我们可以通过计数来比较大小。但对于无限集合,我们需要一个更一般的概念。数学家格奥尔格·康托尔提出了一个想法:如果存在一个函数能将一个集合A的元素一一对应地映射到另一个集合B的所有元素上,那么这两个集合就被认为是大小相同的。这里的“一一对应”意味着函数是单射(没有两个不同的A元素映射到同一个B元素)和满射(B中的每个元素都被映射到)。
另一种理解方式是,如果两个集合的元素可以完美地配对起来,那么它们大小相同。
可数集
如果一个无限集合可以与自然数集N建立一一对应关系,则称该集合为可数集。这意味着我们可以将集合中的元素列成一个列表(第一个、第二个、第三个……)。
以下是一些可数集的例子:
- 整数集Z:可以通过序列 0, -1, 1, -2, 2, -3, 3, ... 与自然数建立一一对应。
- 正有理数集Q+:可以通过一种“对角线”遍历的方式,将所有正有理数排列成一个无限网格,然后按特定顺序(如螺旋形)列出,跳过重复值,从而与自然数建立一一对应。
你可能会认为所有无限集都是可数的,但事实并非如此。
实数集是不可数的
定理:实数集R是不可数的。
证明:(反证法)假设R是可数的。那么存在一个从自然数到实数的一一对应函数f。我们可以据此列出一个包含所有实数的列表:f(1), f(2), f(3), ...
现在,我们构造一个新的实数x,其小数表示如下:
- x的第1位小数不同于f(1)的第1位小数。
- x的第2位小数不同于f(2)的第2位小数。
- x的第3位小数不同于f(3)的第3位小数。
- … 以此类推。
按照这个规则构造的实数x,不可能出现在我们假设的列表中,因为它与列表中的第n个数至少在第n位小数上不同。这与“列表包含所有实数”的假设矛盾。因此,这样的列表(一一对应)不可能存在,R是不可数的。
这种方法被称为对角线法,因为我们沿着列表的对角线进行构造。
图灵机与语言的基数
从实数不可数可以推导出一些重要结论。
首先,考虑所有语言的集合(即字母表Σ上所有子集的集合)。每个语言可以对应一个介于0和1之间的二进制实数(用1表示字符串在语言中,0表示不在)。因此,所有语言的集合与实数集存在一一对应,是不可数的。
其次,所有图灵机的集合是可数的。因为每台图灵机都有一个有限的描述(一个字符串),而所有有限字符串的集合是可数的。
由此得出一个关键推论:存在某些语言,没有任何图灵机能够识别(或判定)它们。因为语言有不可数多个,而图灵机只有可数多个。
ATM是不可判定的
现在,我们运用对角线法来证明一个具体的、非常重要的问题是不可判定的:图灵机接受问题(ATM)。
ATM定义:
ATM = { <M, w> | M是一台图灵机,且M接受输入w }
我们已经知道ATM是图灵可识别的(通用图灵机可以识别它)。现在证明它是不可判定的。
证明:(反证法)假设存在一台图灵机H能够判定ATM。即,对于任意输入<M, w>,H总是停机,并且:
- 若M接受w,则H接受。
- 若M不接受w(拒绝或循环),则H拒绝。
现在,我们利用H来构造一台新的图灵机D,其行为如下:
输入:一台图灵机M的描述
。
- 在输入<M,
>上运行判定器H(即询问H:M是否接受它自己的描述?)。 - 输出与H相反的结果:
- 如果H拒绝,则D接受。
- 如果H接受,则D拒绝。
换句话说,D接受
现在,考虑当我们将D自己的描述
- 根据D的定义,D接受
当且仅当D不接受 。
这是一个逻辑矛盾。因此,我们最初的假设(判定器H存在)是错误的。所以,ATM是不可判定的。
与对角线法的联系:可以想象一个表格,行是所有图灵机M1, M2, ...(包括D),列是所有图灵机的描述。表格第i行第j列的条目表示“Mi是否接受
ATM的补集是不可识别的
我们已经知道ATM是图灵可识别但不可判定的。现在考察其补集:
ATM补 = { <M, w> | M是一台图灵机,且M不接受输入w }
定理:ATM的补集不是图灵可识别的。
这个结论基于一个更一般的定理:
定理:如果一个语言A及其补集A补都是图灵可识别的,那么A是图灵可判定的。
证明:设M1是A的识别器,M2是A补的识别器。我们可以构造A的判定器T如下:
输入:w
- 并行地运行M1(w)和M2(w)。
- 由于w要么属于A,要么属于A补,因此M1和M2中必有一个最终会接受。
- 如果M1接受,则T接受。如果M2接受,则T拒绝。
因为M1和M2中总有一个会接受,T总能停机并给出正确答案,所以T是A的判定器。
现在回到ATM。我们知道ATM是图灵可识别的。如果ATM的补集也是图灵可识别的,那么根据上述定理,ATM就应该是图灵可判定的。但我们刚刚证明了ATM是不可判定的。因此,ATM的补集不可能是图灵可识别的。
这揭示了图灵可识别语言类的一个性质:它对补运算不封闭。ATM是可识别的,但其补集不可识别。
归约法证明不可判定性
对角线法是证明不可判定性的根本方法。一旦我们有了一个“种子”不可判定问题(如ATM),就可以通过归约法来证明其他问题的不可判定性,而无需每次都进行复杂的对角线构造。
归约法的思想:如果问题A可以“归约”到问题B,意味着我们可以利用解决B的方法来解决问题A。那么,如果A是不可判定的,B也一定是不可判定的(因为如果B可判定,A也就可判定了,矛盾)。
示例:停机问题(HALTTM)
HALTTM定义:
HALTTM = { <M, w> | M是一台图灵机,且M在输入w上停机 }
我们将通过归约ATM到HALTTM来证明HALTTM是不可判定的。
证明:(反证法)假设存在判定器R可以判定HALTTM。我们将利用R来构造一个ATM的判定器S,从而与“ATM不可判定”的事实矛盾。
构造S如下:
输入:<M, w>
- 在输入<M, w>上运行判定器R(即询问R:M在w上是否停机?)。
- 如果R拒绝(即M在w上永不停机),那么M肯定不接受w。因此S拒绝。
- 如果R接受(即M在w上停机),那么S可以安全地模拟M在w上的运行直到其停机(因为R保证了它会停)。
- 如果模拟中M接受,则S接受。
- 如果模拟中M拒绝,则S拒绝。
这样,S就正确地判定了ATM。但我们已经知道ATM是不可判定的,这样的S不可能存在。因此,我们最初的假设(判定器R存在)是错误的。所以,HALTTM是不可判定的。
总结
本节课中我们一起学习了:
- 对角线法:通过比较无限集合的大小(可数与不可数),并利用对角线构造法证明实数集是不可数的。
- ATM的不可判定性:运用对角线法,我们证明了图灵机接受问题(ATM)是图灵不可判定的。这是计算理论中一个里程碑式的结论。
- 不可识别语言:基于一个连接可识别性与可判定性的定理,我们推导出ATM的补集甚至不是图灵可识别的。
- 归约法:我们引入了归约法作为证明其他问题不可判定性的强大工具,并以停机问题(HALTTM)为例,展示了如何将ATM归约到HALTTM来证明后者的不可判定性。


这些概念构成了理解计算极限的基础,并为我们后续研究更复杂的不可判定问题做好了准备。
009:可还原性

在本节课中,我们将学习如何使用可还原性方法来证明问题是不可判定的或非图灵可识别的。我们将介绍可还原性的一般概念,并重点讨论一种特定的可还原性——映射可还原性。通过这种方法,我们可以利用已知的不可判定问题来证明其他问题的不可判定性。
概述与回顾
上一节我们介绍了图灵机的局限性,并证明了语言 ATM(图灵机接受性问题)是不可判定的。我们使用了对角化方法来证明这一点。
本节中,我们来看看一种新的证明方法——可还原性方法。这是证明其他问题不可判定的典型方式。我们将继续讨论不可判定性,并引入可还原性的一般概念。
可还原性方法简介
可还原性的核心思想是:如果问题 A 可以归约到问题 B,那么意味着我们可以利用 B 的解决方案来解决 A。
换句话说,如果 A 可还原到 B,那么解决 B 就为解决 A 提供了一条途径。
以下是理解可还原性的几个简单例子:
- 测量面积:测量矩形面积的问题,可以归约到测量其长和宽的问题。我们通过测量长和宽来计算面积,而不是直接测量整个区域。
- NFA接受性问题:非确定性有限自动机的接受性问题 ANFA,可以归约到确定性有限自动机的接受性问题 ADFA。我们通过将NFA转换为等价的DFA,然后利用DFA的解决方案来解决NFA的问题。
- 下推自动机“压栈”问题:判断一个下推自动机是否会对任何输入进行压栈操作的问题,可以归约到上下文无关文法的空性问题 ECFG(等价于PDA的空性问题)。
从这些例子中,我们可以得出两个关键推论:
- 如果 A 可还原到 B,且 B 是“简单”(例如可判定)的,那么 A 也一定是简单的。
- 如果 A 可还原到 B,且 A 是“困难”(例如不可判定)的,那么 B 也一定是困难的。因为如果 B 是简单的,根据推论1,A 也会是简单的,这与已知矛盾。
在本课程中,由于我们关注计算的局限性,我们将更多地使用第二个推论来证明问题的困难性。
示例:证明 Halt_TM 不可判定
首先,我们通过一个例子来演示如何使用可还原性。回顾一下,Halt_TM 问题是判断一个给定的图灵机在给定输入上是否会停机(无论接受还是拒绝)。
我们已经知道 ATM 是不可判定的。现在,我们通过将 ATM 归约到 Halt_TM 来证明 Halt_TM 也是不可判定的。
证明思路(反证法):
- 假设 Halt_TM 是可判定的,即存在一个判定器 R 可以解决它。
- 利用 R,我们可以构造一个判定 ATM 的图灵机 S。这将与 ATM 不可判定的事实矛盾。
- 因此,假设不成立,Halt_TM 不可判定。
图灵机 S 的设计:
- 输入:
<M, w>,其中 M 是一个图灵机,w 是一个字符串。 - 操作:
- 在输入
<M, w>上运行判定器 R,判断 M 在 w 上是否停机。 - 如果 R 输出“否”(即 M 在 w 上不停机),则 S 直接拒绝(因为永不停机的机器不可能接受 w)。
- 如果 R 输出“是”(即 M 在 w 上停机),则 S 可以安全地模拟运行 M 在 w 上直到结束。
- 根据模拟结果:若 M 接受 w,则 S 接受;若 M 拒绝 w,则 S 拒绝。
- 在输入
这样,我们就用假设的 Halt_TM 判定器 R 构造出了一个 ATM 的判定器 S。由于 ATM 已知不可判定,所以最初的假设(Halt_TM 可判定)是错误的。因此,Halt_TM 是不可判定的。
这个证明展示了如何将一个已知的不可判定问题(ATM)归约到目标问题(Halt_TM),从而证明目标问题也是不可判定的。
映射可还原性
现在,我们介绍一种更具体、更有用的可还原性形式——映射可还原性。它基于可计算函数的概念。
一个可计算函数是一个可以由算法(如图灵机)计算的函数,它接收一个字符串输入,并总是停机且输出另一个字符串结果。
我们定义:如果存在一个可计算函数 f,使得对于所有字符串 w,满足:
w ∈ A ⇔ f(w) ∈ B
那么称语言 A 是映射可还原到语言 B 的,记作 A ≤ₘ B。
直观理解是,函数 f 像一个“问题转换器”,它将关于 A 的成员资格问题,转换成关于 B 的成员资格问题,并且保持了成员关系(在A中的映射到在B中的,不在A中的映射到不在B中的)。
映射可还原性的性质
映射可还原性具有几个重要性质,使其非常有用:
-
可判定性的保持:如果 A ≤ₘ B 且 B 是可判定的,那么 A 也是可判定的。
- 证明:要判定
w ∈ A?,只需计算f(w),然后用 B 的判定器判定f(w) ∈ B?,输出相同答案即可。
- 证明:要判定
-
可识别性的保持:如果 A ≤ₘ B 且 B 是图灵可识别的,那么 A 也是图灵可识别的。
- 证明:与上述类似,用 B 的识别器即可。
由此可以导出我们更常用的推论:
- 推论1(用于证明不可判定):如果 A ≤ₘ B 且 A 是不可判定的,那么 B 也是不可判定的。
- 推论2(用于证明不可识别):如果 A ≤ₘ B 且 A 不是图灵可识别的,那么 B 也不是图灵可识别的。
示例:ATM 到 ETM 补集的映射归约
回顾 ETM 是图灵机的空性问题:{ <M> | L(M) = ∅ }。我们之前用一般归约证明了它不可判定。现在,我们可以展示一个从 ATM 到 ETM 补集(即非空语言问题)的映射归约。
我们定义可计算函数 f 如下:
- 输入:
<M, w> - 输出: 一个图灵机 M_w 的描述。M_w 的行为是:
- 对于输入 x,首先检查
x == w。 - 如果
x != w,则立即拒绝。 - 如果
x == w,则模拟原始图灵机 M 在输入 w 上的运行,并输出相同结果。
- 对于输入 x,首先检查
关键点:语言 L(M_w) 要么是空集(如果 M 拒绝 w),要么是单元素集合 {w}(如果 M 接受 w)。因此:
<M, w> ∈ ATM ⇔ M 接受 w ⇔ L(M_w) 非空 ⇔ <M_w> ∈ ETM的补集
这就构成了一个从 ATM 到 ETM补集 的映射归约(ATM ≤ₘ ETM补集)。由于 ATM 不可判定,根据推论1,ETM 的补集也不可判定,从而 ETM 本身也不可判定。
映射可还原性与一般可还原性的对比
- 一般可还原性:更宽泛的概念。只要求能使用 B 的求解器作为子程序来构造 A 的求解器。我们证明 Halt_TM 不可判定的方法就是一般归约。
- 映射可还原性:更严格、更结构化的概念。要求存在一个可计算函数 f 来转换问题实例。它是一般可还原性的一个特例。
一个重要区别在于处理补集时:
- 在一般归约下,语言 A 总是可以归约到其补集 A̅(只需将求解器的答案取反)。但 A 可能无法映射归约到 A̅。
- 例如,ATM的补集 可以用一般归约到 ATM,但不能映射归约到 ATM。因为如果存在这样的映射归约,由于 ATM 是可识别的,将导致 ATM的补集 也是可识别的,这与事实矛盾。
证明不可识别性
映射可还原性特别适合用于证明语言是非图灵可识别的。
证明模板:要证明语言 B 不是图灵可识别的,可以找到一个已知的非图灵可识别语言 A(例如 ATM的补集),并展示一个从 A 到 B 的映射归约(A ≤ₘ B)。根据推论2,B 就不是图灵可识别的。
示例:证明 ETM 不可识别
我们已经知道 ATM的补集 不是图灵可识别的。我们可以使用之前相同的归约函数 f(将 <M, w> 映射到 M_w),但这次关注成员关系:
<M, w> ∈ ATM的补集 ⇔ M 拒绝 w ⇔ L(M_w) 为空 ⇔ <M_w> ∈ ETM
这构成了一个从 ATM的补集 到 ETM 的映射归约(ATM的补集 ≤ₘ ETM)。由于 ATM的补集 不可识别,因此 ETM 也不可识别。
示例:证明 EQ_TM 及其补集都不可识别
EQ_TM 问题是判断两个图灵机是否等价(识别相同语言):{ <M1, M2> | L(M1) = L(M2) }。这是一个更强的结论:EQ_TM 和它的补集都不是图灵可识别的。
证明思路:
我们需要构造两个映射归约。
-
证明 EQ_TM 不可识别:将 ATM的补集 映射归约到 EQ_TM。
- 定义函数 f1,输入
<M, w>,输出一对图灵机<T_w, T_reject>。- T_w:是一个忽略自身输入,总是模拟 M 在 w 上运行的图灵机。因此,如果 M 接受 w,则
L(T_w) = Σ*(接受所有字符串);如果 M 拒绝 w,则L(T_w) = ∅(拒绝所有字符串)。 - T_reject:是一个拒绝所有输入的图灵机(
L(T_reject) = ∅)。
- T_w:是一个忽略自身输入,总是模拟 M 在 w 上运行的图灵机。因此,如果 M 接受 w,则
- 分析:
- 若 M 拒绝 w(即
<M, w>在 ATM的补集 中),则L(T_w) = ∅ = L(T_reject),因此<T_w, T_reject>在 EQ_TM 中。 - 若 M 接受 w,则
L(T_w) = Σ*,与L(T_reject) = ∅不同,因此不在 EQ_TM 中。
- 若 M 拒绝 w(即
- 这实现了 ATM的补集 ≤ₘ EQ_TM,故 EQ_TM 不可识别。
- 定义函数 f1,输入
-
证明 EQ_TM 的补集不可识别:将 ATM的补集 映射归约到 EQ_TM的补集。
- 定义函数 f2,输入
<M, w>,输出一对图灵机<T_w, T_accept>。- T_w:同上。
- T_accept:是一个接受所有输入的图灵机(
L(T_accept) = Σ*)。
- 分析:
- 若 M 拒绝 w(即
<M, w>在 ATM的补集 中),则L(T_w) = ∅,与L(T_accept) = Σ*不同,因此<T_w, T_accept>在 EQ_TM的补集 中。 - 若 M 接受 w,则
L(T_w) = Σ* = L(T_accept),因此不在 EQ_TM的补集 中。
- 若 M 拒绝 w(即
- 这实现了 ATM的补集 ≤ₘ EQ_TM的补集,故 EQ_TM的补集 也不可识别。
- 定义函数 f2,输入
总结
本节课中我们一起学习了:
- 可还原性方法:一种通过将已知的困难问题(如 ATM)归约到目标问题,来证明目标问题同样困难(不可判定或不可识别)的强大技术。
- 映射可还原性:一种特定形式的可还原性,基于可计算函数。它不仅能用于证明不可判定性,还能有效地证明非图灵可识别性。
- 关键性质:
- 若 A ≤ₘ B 且 B 可判定/可识别,则 A 也可判定/可识别。
- 若 A ≤ₘ B 且 A 不可判定/不可识别,则 B 也不可判定/不可识别。
- 应用示例:我们使用这些方法证明了:
- Halt_TM 是不可判定的(通过一般归约)。
- ETM 不仅是不可判定的,而且是不可识别的(通过映射归约)。
- EQ_TM 及其补集都是不可识别的(通过两个映射归约)。


可还原性是计算理论中的一个核心概念,它帮助我们理解不同计算问题之间的相对难度,并划定了可计算性的边界。在接下来的课程中,我们还将看到可还原性在计算复杂性理论中的重要作用。
010:计算历史方法

在本节课中,我们将学习一种更复杂的、用于证明问题不可判定的方法——计算历史方法。我们将通过几个例子来理解这种方法,包括证明波斯特对应问题和某些上下文无关文法问题的不可判定性。
概述
上一节我们介绍了归约和映射归约,用于证明各种问题是不可判定的。本节中,我们将引入一种更复杂的方法,即计算历史方法。这是一种广泛使用的、用于证明问题不可判定的技术,尤其在证明更复杂的问题时非常有效。
核心概念回顾
要证明一个语言是不可判定的,通常需要展示一个已知的不可判定语言(如 ATM)可以归约到目标语言 B。公式化表示为:若 ATM ≤ₘ B,则 B 不可判定。
波斯特对应问题
首先,我们来看一个称为波斯特对应问题的组合问题。以下是该问题的定义:
- 输入:一组“多米诺骨牌”,每张牌是一个字符串对 (Tᵢ, Bᵢ),其中 Tᵢ 是顶部字符串,Bᵢ 是底部字符串。
- 问题:是否存在一个序列(允许重复使用骨牌),使得将所有顶部字符串按顺序连接起来的结果,与将所有底部字符串连接起来的结果完全相同?这样的序列称为一个“匹配”。
例如,给定骨牌集合:
- (AB, ABA)
- (AA, ABA)
- (BA, AA)
- (ABA, A)
一个可能的匹配序列是:骨牌1, 骨牌2, 骨牌3, 骨牌2, 骨牌4。验证如下:
- 顶部连接:
AB+AA+BA+AA+ABA=AB AAB AAA BA - 底部连接:
ABA+ABA+AA+ABA+A=AB AAB AAA BA - 两者相等。
我们将证明,判断给定的 PCP 实例是否存在匹配的问题是不可判定的。
计算历史方法基础
为了证明 PCP 不可判定,我们将使用计算历史方法。首先需要理解几个基础概念。
图灵机格局
图灵机的一个格局是其在计算过程中某一时刻的快照,它包含了确定后续计算所需的所有信息:
- 当前状态
- 读写头位置
- 磁带内容
为了方便,我们通常将格局编码为一个字符串。编码方式为:将磁带内容分为读写头左侧部分(T1)和读写头及其右侧部分(T2),并将当前状态符号插入到 T1 和 T2 之间。例如,若状态为 q,读写头正指向符号 a,格局可表示为 T1 q a T2。
接受计算历史
图灵机 M 在输入 W 上的一个接受计算历史,是 M 从起始格局开始,经过一系列步骤,最终到达接受格局的完整格局序列。
我们可以将整个计算历史编码为一个字符串:将每个格局的字符串编码用分隔符(如 #)连接起来。例如:
# C1 # C2 # C3 # ... # Ck #
其中 C1 是起始格局,Ck 是包含接受状态的格局。
线性有界自动机与可判定性
在深入 PCP 证明前,我们先通过一个更简单的例子——线性有界自动机来体会计算历史方法。
线性有界自动机
LBA 是一种特殊的图灵机,其磁带长度仅与输入长度成线性关系,不能超出初始输入占用的区域。
LBA 的接受问题
对于 LBA,判断“给定 LBA B 和输入 W,B 是否接受 W?”这个问题是可判定的。原因是 LBA 的格局总数是有限的(状态数 × 头位置数 × 磁带内容可能性),因此模拟其运行一定步数后,若未接受则必然进入循环,可以安全拒绝。
LBA 的空语言问题
然而,判断“给定 LBA B,其语言 L(B) 是否为空集?”这个问题是不可判定的。我们将通过计算历史方法来证明这一点。
证明思路(归约 ATM ≤ₘ ELBA):
- 假设存在判定 ELBA 的判定器 R。
- 要判定 ATM(即输入
<M, w>),我们构造一个与 M 和 w 相关的 LBA,记为 B_{M,w}。 - 设计 B_{M,w},使其专门检查输入字符串是否为 M 在 w 上的一个接受计算历史。如果是,则接受;否则拒绝。
- 将 B_{M,w} 输入给判定器 R。
- 分析:
- 如果 R 说
L(B_{M,w})非空,意味着存在至少一个被 B_{M,w} 接受的字符串。根据设计,这个字符串只能是 M 在 w 上的一个接受计算历史。因此,M 接受 w。 - 如果 R 说
L(B_{M,w})为空,意味着不存在这样的接受计算历史。因此,M 不接受 w。
- 如果 R 说
- 这样,我们就利用 R 判定了 ATM,与 ATM 不可判定矛盾。故 ELBA 不可判定。
关键:构造 B_{M,w} 是可行的,因为它可以利用内置的 M 和 w 信息,在有限的磁带空间内,通过前后移动来验证输入字符串的格式是否正确(以起始格局开始、以接受格局结束),以及每个格局是否根据 M 的规则合法地转移到下一个格局。
证明 PCP 不可判定
现在,我们运用计算历史方法来证明波斯特对应问题是不可判定的。思路是进行归约:ATM ≤ₘ PCP。
证明概述:
- 假设存在判定 PCP 的判定器 R。
- 要判定 ATM(输入
<M, w>),我们构造一个与 M 和 w 相关的 PCP 实例 P_{M,w}(一组特定的多米诺骨牌)。 - 设计 P_{M,w},使得该实例存在匹配,当且仅当 M 接受 w。匹配将“编码”一个 M 在 w 上的接受计算历史。
- 用 R 判断 P_{M,w} 是否有匹配。若有,则 M 接受 w;若无,则 M 不接受 w。
- 这构成了对 ATM 的判定,矛盾。故 PCP 不可判定。
构造 P_{M,w} 的骨牌(简化版):
为了使匹配强制模拟计算历史,我们精心设计骨牌。以下是核心骨牌类型(假设匹配必须从第一张特定骨牌开始):
- 起始骨牌:
(#, #q₀w₁w₂...wₙ#)。这迫使匹配底部以起始格局开始。 - 转移骨牌(向右移动):对于 M 的每条转移规则
δ(q, a) = (r, b, R),创建骨牌(q a, b r)。这用于在匹配中模拟读写头处的状态和符号更新。 - 复制骨牌:对于每个磁带符号 a,创建骨牌
(a, a)。这用于复制计算历史中不被读写头改变的部分。 - 分隔符骨牌:
(#, #)。用于在匹配中分隔连续的格局。 - “收尾”骨牌:当计算历史到达接受状态后,需要额外的骨牌让顶部字符串“追上”底部字符串。例如,创建形如
(a q_accept, q_accept)和(q_accept a, q_accept)的骨牌,让接受状态“吞噬”其旁边的磁带符号,最终得到骨牌(q_accept #, #)来完成匹配。
通过这种构造,任何成功的匹配都必须严格按照 M 在 w 上的接受计算历史来排列骨牌,反之,一个接受计算历史也能指导我们生成一个匹配。这就建立了等价关系。
应用于上下文无关文法
计算历史方法还可用于证明其他问题的不可判定性。例如,对于上下文无关文法:
- 空性问题(ECFG):判断 CFG G 的语言是否为空。这是可判定的。
- 全性问题(AllCFG):判断 CFG G 的语言是否包含所有字符串(即 L(G) = Σ*)。这是不可判定的。
我们可以通过归约 ATM ≤ₘ AllCFG 来证明后者。思路是:
- 给定
<M, w>,构造一个 PDA P_{M,w}(等价于 CFG)。 - 设计 P_{M,w},使其接受所有“不是” M 在 w 上接受计算历史的字符串。它利用栈和非确定性,来猜测输入字符串在何处违反了计算历史的规则(例如,起始格局错误、相邻格局转移非法、未以接受格局结束等)。
- 那么,
L(P_{M,w}) = Σ*当且仅当不存在 M 在 w 上的接受计算历史(即 M 不接受 w)。 - 利用假设的 AllCFG 判定器来判断
L(P_{M,w})是否为 Σ*,从而判定 ATM。
这里的关键区别在于,PDA 很难验证一个字符串是合法的计算历史(这需要检查所有部分),但可以很容易地证伪它(只需找到一个错误点)。因此我们构造的 PDA 接受“坏”的字符串,而唯一的“好”字符串(接受计算历史)会被拒绝。所以,当且仅当没有“好”字符串时,PDA 才接受所有字符串。
总结
本节课我们一起学习了计算历史方法。这种方法的核心是利用图灵机的计算历史作为“桥梁”,将不可判定的 ATM 问题归约到目标问题。我们看到了它在三个不同场景下的应用:
- 证明线性有界自动机的空语言问题(ELBA)不可判定。
- 证明波斯特对应问题(PCP)不可判定。
- 证明上下文无关文法的全性问题(AllCFG)不可判定。


这种方法通常适用于那些涉及“是否存在某种结构或对象”的判定问题。通过精心构造,使得目标问题中“存在解”等价于图灵机“存在接受计算历史”,从而建立起归约关系,证明目标问题的不可判定性。
011:递归定理和逻辑

在本节课中,我们将学习计算理论中的一个重要概念——递归定理。递归定理揭示了图灵机(或任何程序)如何能够获取自身的描述,从而实现自引用。我们还将探讨递归定理的一个经典应用:哥德尔不完备性定理,它展示了在形式数学系统中存在无法被证明的真命题。

自复制悖论与可能性
上一节我们介绍了使用计算历史方法证明问题不可判定。本节中,我们来看看一个看似矛盾的概念:自复制机器。
想象一个制造汽车的工厂。通常,工厂的复杂度会高于它制造的汽车,因为它不仅包含制造汽车所需的所有指令和部件,还包含制造工具和机器人等额外部分。因此,一个能制造自身的工厂似乎是不可能的,因为它需要包含自身的完整描述以及制造所需的额外部件,这会导致无限循环。
然而,在现实世界中,生物体确实可以自我复制。这表明自复制机器在理论上是可能的。冯·诺依曼曾对此进行过著名论述。接下来,我们将展示如何构造一个能打印自身描述的图灵机。
构造自复制图灵机
首先,我们需要一个引理:存在一个可计算函数 Q,它可以将任何字符串 W 转换为一个图灵机 P_W,该图灵机在启动时会打印出字符串 W 并停机。
用公式表示:
P_W = Q(W),其中 P_W 是一个图灵机,满足当运行 P_W 时,输出为 W。
基于此,我们可以构造自复制图灵机 SELF。SELF 由两部分组成:A 和 B。
以下是 SELF 的工作流程:
- A 部分运行。A 本身是图灵机 P_B,即一个会打印出 B 部分描述(字符串形式)的机器。运行后,B 的描述出现在纸带上。
- 控制权传递给 B 部分。B 读取纸带上的内容(即 B 的描述),并计算 Q(纸带内容)。根据引理,Q(纸带内容) 的结果正是机器 A(因为 A 就是打印该内容的机器)。
- B 将得到的 A 的描述与纸带上原有的 B 的描述组合起来,形成完整的 SELF 的描述,并将其打印到纸带上。
关键点在于:B 不需要在自身代码中内嵌 A 的描述,而是通过计算 Q 函数动态获得。这就避免了循环引用和无限增长的问题。
递归定理
自复制是递归定理的一个特例。递归定理更一般地指出:任何图灵机都可以获得自身的描述。
递归定理的正式表述如下:
对于任意一个图灵机 T(它期望的输入中包含一个图灵机描述),存在另一个图灵机 R,使得对于所有输入 w,R 在 w 上的行为与 T 在输入 <R, w> 上的行为完全相同。
用公式表示:
∀T ∃R ∀w: R(w) 的行为等价于 T(<R, w>)。
这意味着,在编写图灵机 R 时,你可以假设它能以某种方式“拿到”自己的描述
递归定理的应用
证明 A_TM 不可判定
之前我们用对角化法证明了 A_TM(接受性问题)不可判定。使用递归定理,我们可以得到一个更简洁的证明:
- 假设存在判定器 H 可以判定 A_TM。
- 利用递归定理构造图灵机 R,R 在输入 w 上执行以下操作:
- 获取自身的描述
。 - 运行判定器 H 来检查 <R, w> 是否属于 A_TM(即询问 H:“R 会接受 w 吗?”)。
- 如果 H 说“是”(R 接受 w),则 R 拒绝 w。
- 如果 H 说“否”(R 不接受 w),则 R 接受 w。
- 获取自身的描述
- 这就产生了矛盾:H 对 <R, w> 的预测总是错的。因此,这样的判定器 H 不可能存在。
极小图灵机的集合不可识别
一个图灵机是极小的,如果没有更短的图灵机与其语言完全相同。可以证明,所有极小图灵机构成的集合不是图灵可识别的。证明思路如下:
- 假设存在一个枚举器 E 能枚举所有极小图灵机(或其无限子集)。
- 利用递归定理构造图灵机 R,R 获取自身描述
后,启动枚举器 E,并等待直到 E 输出一个描述长度比 长的图灵机 B。 - R 随后模拟 B 在所有输入上的行为,因此 L(R) = L(B)。
- 但 R 的描述比 B 短,这与 B 是极小图灵机的假设矛盾。因此,这样的枚举器 E 不存在,说明极小图灵机的集合不可识别。
递归定理与数学逻辑
递归定理的一个深刻应用在数学逻辑领域,即哥德尔第一不完备性定理。该定理指出:在任何足够强大且一致的形式数学系统中,都存在一些真命题,无法在该系统内被证明。
以下是证明思路的简化概述:
- 前提:假设我们的形式系统满足:
- 可靠性:系统内可证明的命题都是真的。
- 可检验性:给定一个命题和一个候选证明,可以在有限步内机械地检验该证明是否正确。这意味着“(证明,命题)”对构成的集合是可判定的。
- 推论:所有在该系统内可证明的命题构成的集合是图灵可识别的(只需系统性地生成所有可能的字符串,检验每个是否是某个命题的有效证明即可)。
- 构造:考虑所有形如“图灵机 M 不接受输入 w”的命题。这些命题的集合本质上就是 A_TM 的补集。
- 矛盾:如果系统中能证明所有这样的真命题,那么 A_TM 的补集就成为可识别的。但我们已知 A_TM 的补集不可识别。因此,系统中必然存在一些这样的真命题,是无法被证明的。
- 具体化:利用递归定理,可以构造出一个具体的“哥德尔语句”G,其含义等价于“G 在本系统内不可证明”。通过逻辑分析可以得出,G 必然是一个真但不可证的命题。
这展示了递归定理如何帮助我们在数学系统中精确地构造出自指语句,从而揭示形式化推理的局限性。
总结
本节课我们一起学习了递归定理及其应用。
- 我们首先探讨了自复制机器的可能性,并构造了一个能打印自身代码的图灵机。
- 接着,我们介绍了更一般的递归定理,它允许程序在运行时获取自身的描述。
- 然后,我们看到了递归定理的应用:给出了 A_TM 不可判定的新证明,并证明了极小图灵机集合的不可识别性。
- 最后,我们简要探讨了递归定理在数学逻辑中的革命性应用,即哥德尔不完备性定理,它表明了形式数学系统固有的局限性。



递归定理是计算理论中一个连接程序自指、不可判定性和数理逻辑的优美而强大的工具。
012:时间复杂度 🕒

在本节课中,我们将要学习计算复杂性理论的基础,特别是时间复杂度的概念。我们将从可计算性理论转向复杂性理论,探讨如何衡量算法所需的资源(如时间),并定义重要的复杂性类,如P类。
课程概述
在上一节中,我们介绍了递归定理及其应用。本节中,我们将完全转变方向,开始学习计算复杂性理论。复杂性理论关注的是可判定语言,但核心问题是“需要多少资源(如时间)来判定一个语言”。这与可计算性理论中“是否可判定”的问题形成了对比。
我们将首先通过一个例子来建立直觉,然后正式定义时间复杂度类,并介绍一个核心概念:P类,即多项式时间内可判定的语言集合。
从例子出发:分析一个语言的时间需求
考虑语言 A = {a^k b^k | k ≥ 0}。这是一个可判定语言。现在,我们关心的是:判定这个语言需要多少时间?
分析时间复杂度时,我们通常关注最坏情况复杂度。即,对于每个输入长度 n,我们考虑解决该长度下所有可能输入所需的最大步骤数。我们使用 大O记号 来描述运行时间的上界,忽略常数因子。
大O记号定义:
对于函数 f(n) 和 g(n),我们说 f(n) = O(g(n)),如果存在正常数 c 和 n0,使得对所有 n ≥ n0,都有 f(n) ≤ c * g(n)。
单带图灵机上的算法
首先,我们证明一个定理:在单带图灵机上,语言A可以在 O(n²) 时间内判定。
算法描述:
- 扫描整个输入,检查其形式是否为
a*b*。如果不是,则立即拒绝。 - 进入一个循环,在每次循环中:
- 扫描整个磁带,划掉一个
a和一个b。 - 如果在划掉过程中,一种符号先用尽而另一种还有剩余,则拒绝。
- 扫描整个磁带,划掉一个
- 如果所有
a和b都被成对划掉,则接受。
时间复杂度分析:
- 第一阶段扫描需要 O(n) 步。
- 循环需要 O(n) 次迭代(因为每次划掉一对符号)。
- 每次迭代需要扫描整个磁带,即 O(n) 步。
- 总时间为 O(n) + O(n) * O(n) = O(n²)。
这个算法直观但并非最优。一个自然的问题是:我们能否做得比 O(n²) 更好?
改进算法与模型依赖性
以下是针对语言A的改进算法,它展示了模型选择如何影响时间复杂度。
更优的单带图灵机算法
我们可以设计一个在单带图灵机上以 O(n log n) 时间运行的新算法。
算法核心思想:
不再每次划掉一个 a 和一个 b,而是每次扫描时,划掉每隔一个的 a 和 b。同时,在有限状态控制中跟踪剩余 a 和 b 数量的奇偶性。如果任何一次扫描中,a 和 b 的奇偶性不匹配,则拒绝。如果所有符号都被划掉且奇偶性始终匹配,则接受。
时间复杂度分析:
- 初始检查:O(n)。
- 循环次数:O(log n)(因为每次划掉一半的符号)。
- 每次扫描:O(n)。
- 总时间:O(n log n)。
可以证明,对于单带图灵机,O(n log n) 是解决此问题的最佳可能时间。任何运行时间低于 o(n log n) 的算法,其判定的语言都将是正则语言,而A不是正则语言。
多带图灵机带来的优势
如果我们使用多带图灵机,可以显著提高效率。
算法描述(双带图灵机):
- 将输入带上的所有
a复制到第二个工作带上。 - 输入带头部继续读取
b,同时工作带头部回到起始位置。 - 每读一个
b,就在工作带上匹配划掉一个a。 - 如果
a和b同时匹配完毕,则接受;否则拒绝。
时间复杂度分析:
此算法只需对输入进行常数次扫描,总时间为 O(n)。
这个例子揭示了复杂性理论中的一个关键点:模型依赖性。在可计算性理论中,图灵机、RAM等模型在“可判定性”上是等价的。但在复杂性理论中,不同模型所需的时间资源可能不同(例如,从 O(n log n) 到 O(n))。
定义时间复杂度类
为了建立独立于具体模型的稳健理论,我们做出以下观察:所有“合理的”确定性计算模型(如单带/多带图灵机、RAM模型)在多项式时间内是相互可模拟的。即,一个模型上时间为 T(n) 的算法,在另一个模型上模拟最多需要 T(n)^k 的时间(k 为某个常数)。
这意味着,如果我们只关心多项式时间与指数时间这样的本质区别,而忽略 n² 与 n³ 之间的差异,那么模型的选择就不再是关键。这使我们能够专注于一类重要的问题。
我们选择单带图灵机作为定义时间复杂度的基础模型。
时间可构造函数定义:
如果函数 T: N → N 满足 T(n) ≥ n 且存在一台图灵机能在 O(T(n)) 时间内计算出 1^n → 1^{T(n)} 的映射,则 T(n) 是一个时间可构造函数。常见的 n、n log n、n²、2^n 都是。
时间复杂度类 TIME 定义:
设 T(n) 是一个时间可构造函数。TIME(T(n)) 是所有能被一台确定性单带图灵机在 O(T(n)) 时间内判定的语言的集合。
这些复杂度类形成一个层次结构:TIME(n) ⊆ TIME(n log n) ⊆ TIME(n²) ⊆ ...
多项式时间与 P 类 🏁
基于时间层次,我们定义理论计算机科学中最重要的复杂性类之一:P 类。
P 类定义:
P = ∪_{k} TIME(n^k)
即,P 是所有能在多项式时间内被确定性单带图灵机判定的语言的集合。
为什么 P 类如此重要?
- 模型无关性:由于所有合理模型都是多项式相关的,使用多带图灵机、RAM等模型定义的 P 类与单带图灵机定义的 P 类是相同的。这恢复了我们在可计算性理论中享有的模型独立性。
- 实践相关性:尽管
n¹⁰⁰这样的多项式时间在实际中可能也很慢,但 P 类在理论上通常被视为“高效可解”问题的标志。它排除了需要指数级搜索的暴力算法,是密码学、算法设计等领域的一个关键分界线。
示例:PATH 问题属于 P
让我们看一个属于 P 的具体问题。
PATH 问题定义:
给定一个有向图 G 以及两个节点 s 和 t,判断 G 中是否存在一条从 s 到 t 的路径。
证明 PATH ∈ P:
我们可以使用广度优先搜索(BFS)算法。
- 标记起点
s。 - 重复以下步骤直到没有新节点被标记:将所有从已标记节点通过一条边直接到达的未标记节点进行标记。
- 检查终点
t是否被标记。若是,则接受;否则拒绝。
(高级别)时间复杂度分析:
- 最多有
n个节点需要标记,所以外层循环最多n次迭代。 - 每次迭代需要检查所有边,最多有
n²条边。 - 在单带图灵机上实现这些操作,每一步都可以在多项式时间内完成。
- 因此,总运行时间是输入规模
n的某个多项式。故 PATH ∈ P。
在分析属于 P 类的问题时,我们通常只需说明算法的每个阶段都是多项式时间,且阶段数是多项式,而无需给出精确的多项式次数。
一个未知的领域:HAMPATH 问题
现在考虑一个与 PATH 类似但更难的问题。
HAMPATH 问题定义:
给定一个有向图 G 以及两个节点 s 和 t,判断 G 中是否存在一条从 s 到 t 的哈密顿路径,即一条经过 G 中每个节点恰好一次的路径。
一个指数时间算法:
一个简单的算法是枚举所有可能的节点排列(共 m! 种,m 为节点数),检查每个排列是否构成一条从 s 到 t 的有效路径。这需要 Ω(m!) 时间,是超多项式(指数级)的。
核心问题:HAMPATH ∈ P 吗?
目前没有人知道这个问题的答案。寻找 HAMPATH 的多项式时间算法,或者证明这样的算法不存在,是计算机科学中最著名的开放问题之一——P 与 NP 问题的核心。我们将在后续课程中深入探讨这个问题。
课程总结
本节课中,我们一起学习了计算复杂性理论的入门知识:
- 我们引入了时间复杂度的概念,使用最坏情况分析和大O记号。
- 通过语言
{a^k b^k}的例子,我们看到了算法分析以及计算模型的选择(单带 vs 多带图灵机)如何影响时间复杂度。 - 我们定义了时间复杂度类
TIME(T(n)),并基于单带图灵机模型定义了核心的 P 类(多项式时间可判定语言)。 - 我们理解了 P 类的重要性在于其模型无关性和实践意义。
- 我们分析了 PATH 问题属于 P,并对比了看似相似但复杂度未知的 HAMPATH 问题,引出了 P 与 NP 这个未解之谜。


从下一讲开始,我们将以 P 类为基石,进一步探索更广阔的复杂性世界。
013:P和NP,SAT,多项式时间可归约性

概述
在本节课中,我们将学习计算复杂性理论的核心概念。我们将回顾确定性多项式时间类P,并引入非确定性多项式时间类NP。我们将探讨P与NP的关系这一著名未解问题,并通过哈密顿路径问题和合数问题等例子来理解NP类。我们还将介绍动态规划这一基本多项式时间算法,并开始接触多项式时间归约的概念,为理解NP完全性打下基础。
回顾:P类与时间复杂性
上一节我们介绍了时间复杂性类。时间复杂性类是在特定时间界限内可解决的语言集合。例如,TIME(n²)包含所有能在n²时间内解决的问题。我们将问题等同于语言。
类P是所有能在多项式时间内解决的问题的集合。它是所有多项式时间界限(如n², n³, n⁵等)对应语言集合的并集。我们证明了P类在合理的确定性模型选择下是不变的,这论证了其自然性。
我们以PATH问题为例,给出了一个多项式时间算法。接着,我们引入了哈密顿路径问题(HAMPATH)。
哈密顿路径问题(HAMPATH)
哈密顿路径问题是指:给定一个图以及起点s和终点t,是否存在一条从s到t的简单路径,该路径恰好访问图中每个节点一次。
目前尚不清楚HAMPATH问题是否在P类中。我们可以通过尝试所有可能的路径来得到一个指数时间的正确算法,但这无法给出多项式时间算法。这是一个尚未解决的难题。
有趣的是,如果能找到HAMPATH的多项式时间算法,将产生惊人的后果。例如,它将立即为分解大整数等许多其他我们尚不知如何多项式求解的问题提供多项式时间解法。尽管分解问题与哈密顿路径问题看似无关,但我们将在后续课程中建立这种联系。
非确定性时间复杂性
现在,我们开始讨论非确定性复杂性,作为确定性复杂性的一个变体。
首先,在本课程这部分,所有机器都是判定器,所有语言都是可判定的。非确定性机器作为判定器,意味着在每一个输入上,它的所有计算分支都必须在有限步内停机。
非确定性机器所用时间的定义是:我们单独查看每个分支。一台非确定性图灵机在T(n)时间内运行,如果它的所有分支都在T(n)步内停机。这是获得有用概念的正确方式。
定义:NTIME与NP类
我们定义非确定性时间复杂性类NTIME。NTIME(T(n))是所有能被一台在O(T(n))时间内运行的非确定性图灵机判定的语言集合。
可以将其与确定性时间类TIME(或DTIME)类比。NTIME中的计算可以想象为一棵计算树,所有分支都必须在T(n)步内停机。
类比P类,我们定义NP类为所有能在非确定性多项式时间内解决的语言集合。它是所有多项式时间界限对应的NTIME类的并集。
NP类同样不依赖于合理的非确定性模型选择,因此从数学角度看是一个非常自然的类。从实践角度看,它捕捉了那些成员资格可以快速验证的问题。
NP类与可验证性
NP类中的问题有一个关键特征:当你有一个属于该语言的实例时,存在一种方法可以快速验证这一点。这种验证方法通常被称为一个证书或简短证明。
- 对于HAMPATH问题,证书就是那条哈密顿路径本身。
- 对于合数问题(COMPOSITES),证书就是一个非平凡因子。
相比之下,证明一个数是素数(没有非平凡因子)则不那么显然。能够快速验证成员资格是理解NP类的核心直觉。
P与NP的关系
P类显然是NP的子集,因为确定性机器是非确定性机器的特例。从可验证性角度看,如果你能快速测试成员资格(P),那么你当然也能快速验证它(NP),此时证书甚至无关紧要。
核心问题是:P类是否等于NP类? 即,能够快速验证成员资格(使用证书)是否意味着你也能在不依赖证书的情况下,自己快速测试成员资格?
对于像HAMPATH这样的问题,我们是否需要确定性地搜索答案,还是能找到某种不需要搜索的直接多项式解法?大多数人相信P ≠ NP,但至今无人能证明。证明某个问题(如HAMPATH)没有多项式时间算法非常困难,因为多项式时间算法构成的类别非常丰富和强大。
动态规划:一个关键的多项式时间算法
为了展示多项式时间算法的能力,我们介绍动态规划。这是一种通过记住已解决的子问题来避免重复计算,从而将可能是指数级的递归算法转化为多项式时间算法的技术。
我们以上下文无关文法成员资格问题(ACFG)为例。给定一个上下文无关文法G和一个字符串w,判断w是否在L(G)中。
一个简单的递归思路是:对于文法中的每个变量A和w的每个子串,检查A是否能推导出该子串。但朴素的递归会导致指数级重复计算。
关键观察是:不同的子问题数量是有限的。子串的数量是O(n²),变量的数量也是有限的。因此,总的不同子问题数量是多项式级别的。
动态规划算法(带记忆化的递归)会维护一个表格,记录已解决的子问题及其答案。在每次递归调用前,先检查表格。这样,总计算量就被限制在多项式范围内,从而得到一个多项式时间算法。
动态规划还有另一种“自底向上”的视角:先解决所有最小的子问题(如长度为1的子串),然后利用它们的结果逐步构建更大子问题的解。这两种视角是等价的。
布尔可满足性问题(SAT)
现在,我们转向理解P和NP的另一个核心:布尔可满足性问题(SAT)。
布尔公式由布尔变量(取真/假值)通过逻辑运算符与(∧)、或(∨)、非(¬)连接而成。一个布尔公式是可满足的,如果存在对其变量的某种真值赋值,使得整个公式计算结果为真。
例如,公式 φ = (x ∨ y) ∧ (¬x ∨ ¬y) 是可满足的。赋值 x=真, y=假 可使公式为真。
SAT语言就是所有可满足的布尔公式的集合。判断一个公式是否属于SAT,即判断它是否可满足。
SAT问题在NP类中,因为如果公式可满足,一个满足赋值就是其成员资格的简短证书。
库克-列文定理与多项式时间归约
有一个非凡的定理(由Cook和Levin独立发现)将SAT问题与整个NP类联系起来:如果SAT ∈ P,那么 NP = P。
证明这一点的关键工具是多项式时间归约。它类似于我们之前学过的映射归约,但要求归约函数本身必须在多项式时间内计算。
多项式时间归约的意义在于:如果问题A可以多项式时间归约到问题B(记作 A ≤ₚ B),并且B ∈ P,那么A ∈ P。
库克-列文定理的惊人之处在于,它证明了 NP中的每一个问题都可以多项式时间归约到SAT问题。因此,如果你能把SAT“拉进”P类(即证明SAT ∈ P),那么通过归约,NP中的所有问题都会被一起拉进P类,从而证明P = NP。
这类似于可计算性理论中,我们证明了所有图灵可识别语言都可以映射归约到A_TM。这里存在许多类比。


总结
本节课我们一起学习了计算复杂性理论的基础。我们回顾了P类,正式定义了NP类和非确定性时间复杂性。我们通过哈密顿路径、合数等例子理解了NP类对应“容易验证”的问题。我们探讨了P与NP关系这一核心未解问题。接着,我们介绍了动态规划这一强大的多项式时间算法设计技术,并以ACFG问题为例展示了其应用。最后,我们引入了布尔可满足性问题(SAT)和多项式时间归约的概念,并概述了库克-列文定理的核心思想:SAT在NP中具有特殊地位,所有NP问题都可归约到它。这为下一讲深入探讨NP完全性奠定了基础。
014:NP-完全性

在本节课中,我们将学习NP-完全性这一核心概念。我们将回顾多项式时间归约,并介绍两个重要问题:3SAT和团问题。我们将展示如何将3SAT问题多项式时间归约到团问题,从而理解NP-完全问题的“难度”是如何传递的。最后,我们将正式定义NP-完全性,并探讨其重要性。
多项式时间归约与NP问题回顾
上一节我们介绍了多项式时间归约的概念。本节中,我们来看看这个概念如何帮助我们理解问题的计算难度。
多项式时间归约遵循我们之前讨论的归约模式:如果问题A可归约到问题B,且问题B是容易解决的,那么问题A也变得容易解决。具体来说,我们关注的是映射归约,但要求归约函数本身可以在多项式时间内计算。
我们有一个关键结论:如果A可多项式时间归约到B,且B属于P类,那么A也属于P类。这个结论对于后续的整个讨论至关重要。
关于P和NP的直观理解是:P类问题是那些可以快速判定成员资格的问题,而NP类问题是那些可以快速验证成员资格的问题。验证通常需要一个“证书”来证明输入属于该语言。
该领域的核心未解问题是P是否等于NP,即P与NP问题。我们尚不知道答案。如果P等于NP,意味着所有涉及搜索的NP问题都可以在不进行穷举搜索的情况下快速解决;如果P不等于NP,则存在一些本质上需要搜索的问题。
为了探索这个问题及其影响,我们引入了可满足性问题。我们提到(将在下一讲证明)一个非常卓越的定理:如果可满足性问题可以在多项式时间内解决,那么所有NP问题都可以在多项式时间内解决。也就是说,如果SAT属于P,则P等于NP。从这个意义上说,SAT是NP问题中最“难”的问题,所有NP问题的难度都蕴含在SAT之中。
证明这个定理的关键工具就是多项式时间归约。我们将展示NP中的每一个问题都可以多项式时间归约到SAT。为了建立这种归约的直觉,我们今天将看一些具体的多项式时间归约例子,首先介绍两个新问题:3SAT和团问题。
引入3SAT与团问题
以下是两个我们将要讨论的问题。
3SAT问题
首先,我们考虑一种特殊形式的布尔公式,称为合取范式。
合取范式公式按特定方式组织:它包含由“与”操作连接起来的组,这些组称为子句;在每个子句内部,元素由“或”操作连接。这些元素要么是变量,要么是变量的否定(即文字)。
- 文字:一个变量或其否定。
- 子句:多个文字的“或”运算。
- 合取范式公式:多个子句的“与”运算。
一个3CNF公式是每个子句恰好包含三个文字的CNF公式。例如,公式 (x1 ∨ ¬x2 ∨ x3) ∧ (¬x1 ∨ x4 ∨ ¬x5) ∧ (x2 ∨ x5 ∨ x6) 就是一个3CNF公式。
3SAT问题就是可满足性问题限制在3CNF公式上。它是所有可满足的3CNF公式的集合。你可能会认为这个特例比一般的SAT问题更容易,但事实证明并非如此,解决这个特例与解决一般情况同样困难。
团问题
现在,我们转向第二个问题:团问题。这涉及到图论。我们考虑由点和连接线组成的图。
- 团:图中一个节点子集,其中每对节点之间都有边直接相连。
- K-团:一个包含K个节点的团。
团问题是:给定一个图和一个目标大小K,判断图中是否存在一个大小为K的团。显然,团问题是可判定的,你可以尝试所有可能的K个节点的子集,检查它是否构成一个团。但这通常是指数级算法。同时,团问题也属于NP,因为如果你有一个团作为证书,可以很容易地验证一个图是否包含一个K-团。
我们将要展示的是,3SAT问题和团问题是相关的,你可以将3SAT多项式时间归约到团问题。这看起来有些令人惊讶,因为这两个问题表面上非常不同。但我们将给出这个归约,这意味着如果你能找到快速解决团问题的方法,那么你也能快速解决3SAT问题。这正是本节的核心要点。
从3SAT到团问题的归约
我们将展示如何将3SAT问题多项式时间归约到团问题。这是你需要理解的一种典型归约,因为你可能会在作业或考试中遇到类似题目。
从高层次看,我们正在展示如何将布尔公式的可满足性问题重新编码为测试图是否包含团的问题。
根据定义,我们需要给出一种方法,将公式φ转换为一个图G和一个数K,使得公式φ是可满足的,当且仅当图G有一个K-团。
我们通过一个例子来演示。首先,我们需要理解像φ这样的公式可满足意味着什么,因为这有助于进行归约。由于公式是合取范式,使其为真对应于使每个子句为真。而要使一个子句为真,必须使其中的至少一个文字为真。因此,满足赋值就是在每个子句中至少使一个文字为真。这是进行归约的基础。
现在,我们进行归约。我们将这个公式转换为一个图和一个数K。我将分两步进行:首先说明图的节点是什么,然后说明边是什么,最后说明数K是什么。我们还需要确保构建这个图的程序可以在多项式时间内完成,这一点在完成后会很明显。
第一步:定义节点
图G的节点对应于公式中的每一个文字。每个文字都成为图中的一个节点,并用该文字的名称标记。因此,对于公式中的每个文字,我们都有一个对应的标记节点。
第二步:定义边
我将通过首先说明哪些边是“禁止”的来定义边,然后包含所有其他边。
禁止的边有两种类型:
- 来自同一子句的节点之间的边。即,子句内部没有边。
- 连接具有不一致标签的节点之间的边。例如,连接
a和¬a的边是被禁止的。
在列出所有禁止边之后,我们将在所有未被禁止的节点对之间添加边。也就是说,如果两个节点既不在同一个子句中,标签也不矛盾,那么它们之间就有一条边。
第三步:定义K
K等于公式中子句的数量。这就是我们要在图G中寻找的团的大小。
我声称,这样构造出来的图G将有一个K-团,当且仅当φ是可满足的。这很巧妙:如果φ可满足,那么图中会有一个K-团;如果φ不可满足,则没有。
接下来,我们需要论证为什么这个构造是有效的。这是一个“当且仅当”的证明,需要从两个方向进行。
证明方向一:如果φ可满足,则G有K-团
假设φ可满足,则存在一个满足赋值。在一个CNF公式的满足赋值中,每个子句至少有一个文字为真。从每个子句中任意选取一个为真的文字。现在,查看G中对应的节点。我们声称这些节点一起构成了一个K-团。
- 节点数量:因为我们从每个子句选一个节点,而K是子句数,所以我们恰好有K个节点。
- 连通性:我们需要证明这些节点之间两两相连。根据构造,只要两个节点之间没有禁止边,它们就有边相连。我们选取的节点之间会有禁止边吗?
- 它们不可能来自同一个子句,因为我们每个子句只选了一个节点。
- 它们不可能具有不一致的标签,因为它们都来自同一个赋值,都是为真的文字。不可能在一个子句中a为真,而在另一个子句中¬a为真,因为如果a为真,那么¬a必然为假,不可能成为那个子句中的真文字。
因此,我们选取的节点对之间都没有禁止边,所以它们之间都有边相连。这就构成了一个K-团。
证明方向二:如果G有K-团,则φ可满足
假设G有一个K-团。首先,观察这个团中每个子句恰好有一个节点。
- 它不可能在一个子句中有两个节点,因为根据构造,同一子句中的节点之间没有边,所以它们不能同时出现在一个团中(团要求所有节点对之间都有边)。
- 它也不可能缺少某个子句的节点。因为总共有K个子句,而团有K个节点。如果某个子句没有节点,那么必然有另一个子句有两个节点,这已经排除了。
因此,这个K-团在每个子句中恰好有一个节点。
现在,我们从这个团得到一个满足赋值:取团中每个节点对应的文字,将这些文字设置为真(如果文字是¬a,则将变量a设置为假)。这样,我们在每个子句中设置了一个文字为真,因此得到了一个满足赋值。需要仔细检查的是,我们不会试图同时将a和¬a都设为真。但根据构造,a和¬a之间没有边,所以它们不可能同时出现在同一个团中。因此,赋值是一致的。
最后,这个归约可以在多项式时间内完成,因为从公式构造图的过程是直接的:为每个文字创建节点,根据简单规则添加边,并计算子句数量。
这个证明表明,如果我能快速解决团问题,那么我就能快速解决3SAT问题。因为我刚刚展示了如何将这些公式转换为图。
NP-完全性的定义与重要性
现在,让我们来讨论NP-完全性。我们虽然还不会证明SAT是NP-完全的,但至少可以给出定义。
一个语言B被称为NP-完全的,如果它满足两个性质:
- B属于NP。
- NP中的每一个语言都可以多项式时间归约到B。
简单来说,它既是NP的成员,又是NP中最“难”的问题(所有NP问题都可以归约到它)。这就是我们声称SAT所具有的神奇性质:SAT显然在NP中,而Cook-Levin定理将表明NP中的所有问题都可以归约到SAT。因此,SAT将是我们的第一个NP-完全问题。
由此我们得到一个重要推论:如果SAT(或任何其他NP-完全问题)被证明可以在多项式时间内解决,那么每一个NP问题都可以在多项式时间内解决。这是直接的,因为所有问题都可以多项式时间归约到这个NP-完全问题,如果你能轻松解决它,通过归约就能轻松解决一切。
Cook-Levin定理指出SAT是NP-完全的。我们将在下一讲证明它。但为了本讲后续的讨论,我们假设我们知道它是真的。
基于SAT是NP-完全的假设,并且我们展示了3SAT可以多项式时间归约到团问题,再加上SAT本身可以归约到3SAT(我们稍后会看到),那么通过归约的传递性,3SAT和团问题也都是NP-完全的。因为任何NP问题都可以先归约到SAT,再归约到3SAT,再归约到团问题。
一般来说,要证明某个语言是NP-完全的,一个典型方法是证明某个已知的NP-完全问题(如3SAT)可以多项式时间归约到它。
为什么NP-完全性这个概念重要? 有两个主要原因:
- 实践指导:如果你在研究一个新的计算问题(例如机器人运动规划),并试图为其寻找多项式时间算法,但随后证明该问题是NP-完全的,这提供了强有力的证据表明该问题可能不在P中。因为如果它在P中,将意味着P=NP,这将是一个惊天动地的发现。因此,NP-完全性证明通常被视为放弃寻找精确多项式时间算法、转而寻求近似算法或启发式方法的理由。
- 理论意义:对于试图证明P≠NP的理论学家来说,NP-完全性保证了你不会“选错问题”。如果你选择研究一个NP-完全问题,并成功证明它不在P中,那么你就直接证明了P≠NP。反之,如果你选择了一个实际上是P的问题(比如质数判定,在多年前曾被认为是NP的候选),那么你的努力可能会白费。NP-完全问题则没有这个风险:如果P≠NP,那么NP-完全问题肯定不在P中。
总结


本节课中,我们一起学习了NP-完全性的核心概念。我们回顾了多项式时间归约,并介绍了3SAT和团问题。我们详细演示了如何将3SAT问题多项式时间归约到团问题,理解了这种归约如何将计算难度从一个问题传递到另一个问题。最后,我们正式定义了NP-完全性,并讨论了它在理论计算机科学和实际问题中的重要性。这为我们后续深入理解Cook-Levin定理以及更多NP-完全问题奠定了基础。
015:库克-莱文定理

在本节课中,我们将学习NP完全性理论的核心定理——库克-莱文定理。我们将证明布尔可满足性问题(SAT)是NP完全的,并介绍如何将SAT归约到3-SAT。理解这些证明是掌握NP完全性概念的关键。
概述
我们首先回顾NP完全性的定义。一个语言是NP完全的,如果它属于NP类,并且NP类中的每一个其他问题都可以在多项式时间内归约到它。如果任何一个NP完全问题被证明存在多项式时间算法,那么P就等于NP。反之,如果P不等于NP,那么所有NP完全问题都是难解的。
上一节我们介绍了NP完全性的概念,本节中我们将深入证明库克-莱文定理,即SAT是NP完全的。
证明SAT是NP完全的
证明分为两部分:
- SAT属于NP类。
- NP中的任何语言A都可以在多项式时间内归约到SAT。
第一部分很简单:对于一个布尔公式,其可满足性的“证据”就是一个令其值为真的变量赋值。我们可以在多项式时间内验证这个赋值。
第二部分是证明的核心。我们需要为任意一个NP语言A构造一个归约。设A由某个非确定性图灵机M在n^k时间内判定。我们的目标是,给定输入字符串w,在多项式时间内构造一个布尔公式φ_M,w,使得w ∈ A当且仅当φ_M,w是可满足的。
这个公式的核心思想是模拟图灵机M在输入w上的计算。如果M接受w,那么存在一条接受的计算分支。我们将这条分支的计算历史编码成一个表格,称为格局表。然后,我们构造一个布尔公式来描述一个合法的、接受的计算格局表的存在性。
构造格局表
格局表是一个n^k行 n^k列的表格。
- 每一行代表计算历史中的一个格局(即机器在某个时刻的完整快照)。
- 第一行是起始格局。
- 最后一行包含接受状态。
- 表格的尺寸
n^k × n^k确保了即使机器在n^k步内尽可能向右移动,其读写头也不会超出表格范围。
如果M接受w,则存在至少一个这样的合法格局表。如果M不接受w,则不存在任何合法的格局表。
编码为布尔变量
为了用布尔公式描述这个表格,我们为表格中的每一个单元格(i, j)和每一个可能的符号σ(属于机器的带字母表Γ或状态集Q)创建一个布尔变量x_{i,j,σ}。
- 如果
x_{i,j,σ} = TRUE,则表示单元格(i, j)中包含符号σ。 - 这可以看作是一种“独热编码”:每个单元格中,有且仅有一个对应的变量为真。
构造布尔公式 φ_M,w
整个公式φ_M,w由四个子公式合取而成,分别确保格局表的四个关键属性:
1. φ_cell:每个单元格有且仅有一个符号
这个子公式确保每个单元格的变量设置是合理的。对于每个单元格(i, j),它包含两部分:
- 至少有一个符号:
⋁_{σ ∈ Γ ∪ Q} x_{i,j,σ} - 至多有一个符号:对于所有不同的符号对
σ, τ,¬(x_{i,j,σ} ∧ x_{i,j,τ})
然后将这两个条件对所有的i, j进行合取。
2. φ_start:第一行是起始格局
这个子公式硬性规定表格第一行的内容必须与输入w的起始格局完全一致。例如:
x_{1,1,q0} = TRUE(起始状态在第一个单元格)x_{1,2,w1} = TRUE(输入的第一个符号)- ... 以此类推,直到
x_{1,n+1,w_n},后面的单元格则规定为空白符。
3. φ_accept:最后一行包含接受状态
这个子公式要求在接受格局(最后一行)中,至少有一个单元格包含接受状态q_accept:
⋁_{1 ≤ j ≤ n^k} x_{n^k, j, q_accept}
4. φ_move:相邻行之间的转移是合法的
这是最复杂的部分,它确保表格中每一行都是根据M的转移函数从前一行合法得到的。我们利用图灵机操作的局部性:一个格子下一时刻的内容,只取决于当前时刻它自身及其左右邻居格子的内容。
我们检查所有2×3的“窗口”(覆盖两行、三列)。一个窗口是合法的,如果它的内容不违反M的转移规则(例如,读写头的移动、符号的改写都符合规则)。非法窗口的例子包括:符号无端变化、状态凭空出现或消失、同一行出现两个状态等。
φ_move子公式断言:表格中每一个2×3窗口都是合法的。对于每个窗口位置,我们列出所有可能的合法窗口配置(这是一个只依赖于M的固定集合),然后断言当前窗口的变量设置必须匹配其中一种合法配置。这通过一个析取式来实现,然后对所有可能的窗口位置进行合取。
关键引理:如果表格的每一个2×3窗口都合法,并且φ_start和φ_cell成立,那么整个表格就构成一个从起始格局到接受格局的合法计算历史。
归约的正确性与多项式时间
- 正确性:如果
w ∈ A,则存在一条接受计算分支,我们可以根据它填充格局表,并设置相应的变量为真,这将满足整个公式φ_M,w。反之,如果φ_M,w可满足,则满足的变量赋值定义了一个所有窗口合法、起始正确、结束于接受的格局表,这正好对应了M接受w的一个计算历史。 - 多项式时间:公式
φ_M,w的大小是多项式级别的。变量总数约为O((n^k)^2) = O(n^{2k})。每个子公式(φ_cell,φ_start,φ_accept,φ_move)的构造都可以在关于n的多项式时间内完成。因此,从w到φ_M,w的映射是一个多项式时间归约。
至此,我们完成了库克-莱文定理的证明:SAT是NP完全的。
从SAT归约到3-SAT
上一节我们证明了SAT是NP完全的,本节中我们来看看如何将一般的布尔公式可满足性问题(SAT)归约到其特殊形式——3合取范式可满足性问题(3-SAT)。这巩固了3-SAT的NP完全性。
我们需要一个多项式时间算法,将任意布尔公式φ转换为一个3-CNF公式φ‘,并保持可满足性等价(注意,不是逻辑等价,因为会引入新变量)。
归约思路
- 将公式
φ解析成一个二叉树结构,其中内部节点是逻辑操作(∧,∨),叶节点是变量或其否定。 - 为树中每一个内部节点(代表一个子表达式)引入一个新的辅助变量(例如
z_i)。 - 对于每个内部节点,例如
z_i = A ∧ B,构造一组子句来强制z_i与A ∧ B的值一致。这利用了逻辑等价关系,如(A ∧ B) → z_i等价于子句(¬A ∨ ¬B ∨ z_i)。 - 类似地,对于
z_j = A ∨ B,也可以构造一组强制其值的子句。 - 最后,添加一个子句确保根节点对应的变量(代表整个公式的输出)为真。
示例与复杂度
假设原公式φ有k个逻辑运算符。通过上述过程:
- 我们会引入大约
k个新变量。 - 每个运算符(如
∧或∨)会产生固定数量(例如4个)的3元子句来约束其对应的新变量。 - 最后再加一个子句要求输出为真。
因此,最终产生的3-CNF公式φ‘的子句数量是O(k),构造过程是多项式时间的。
关键点:φ‘包含了原变量和新变量。φ是可满足的,当且仅当φ‘是可满足的。如果φ可满足,我们可以先得到原变量的赋值,然后根据运算结果依次确定每个新变量z_i的赋值,从而满足φ‘。如果φ‘可满足,则将其赋值中原变量的部分提取出来,必然满足φ。
总结
本节课中我们一起学习了计算理论的两个核心证明:
- 库克-莱文定理:我们通过模拟非确定性图灵机的计算,构造了从任意NP语言到布尔可满足性问题(SAT)的多项式时间归约,从而证明了SAT是NP完全的。
- SAT到3-SAT的归约:我们通过为公式的每个子表达式引入辅助变量,并构造约束子句,展示了如何在多项式时间内将任何布尔公式转换为一个可满足性等价的3-CNF公式,从而证明了3-SAT也是NP完全的。



这些定理为NP完全性理论奠定了基础,使我们能够通过归约技术,证明成千上万的实际问题是NP完全的,从而理解它们的内在计算难度。
016:空间复杂度,PSPACE,萨维奇定理


在本节课中,我们将要学习计算复杂度的另一个基本度量:空间复杂度。我们将定义空间复杂度类,探讨多项式空间(PSPACE)和非确定性多项式空间(NPSPACE),并了解它们与之前学过的时间复杂度类(如P和NP)之间的关系。我们还将通过两个重要例子——真量化布尔公式(TQBF)问题和词梯(Ladder)问题——来加深理解。
空间复杂度定义
上一节我们介绍了时间复杂度,本节中我们来看看空间复杂度。空间复杂度衡量的是图灵机在计算过程中所使用的存储空间(即磁带单元)数量。
对于一个确定性图灵机,如果它在所有长度为 n 的输入上都能停机,并且扫描的磁带单元数不超过 f(n),我们就说它在空间 f(n) 内运行。对于非确定性图灵机,要求其每一个计算分支所使用的空间都不超过 f(n)。
基于此,我们可以定义空间复杂度类:
- SPACE(f(n)):所有能被确定性单带图灵机在
O(f(n))空间内判定的语言集合。 - NSPACE(f(n)):所有能被非确定性单带图灵机在
O(f(n))空间内判定的语言集合。
多项式空间类则是这些类的并集:
- PSPACE = ∪k SPACE(nk)
- NPSPACE = ∪k NSPACE(nk)
关于多带图灵机,一个重要的结论是:将其转换为单带图灵机模拟时,空间开销仅是线性的。因此,基于多带图灵机定义的PSPACE类与基于单带图灵机定义的PSPACE类是相同的。
时间与空间复杂度的关系
理解了空间复杂度的定义后,我们来看看它与时间复杂度的基本关系。
首先,时间可以“转换”为空间。如果一个图灵机在 T(n) 时间内运行,那么它最多只能访问 T(n) 个不同的磁带单元。因此,我们有:
TIME(T(n)) ⊆ SPACE(T(n))
一个直接的推论是:P ⊆ PSPACE,以及 NP ⊆ NPSPACE。
其次,空间可以“转换”为时间,但代价可能很高。如果一个图灵机只使用 S(n) 空间,那么它可能运行的最大时间受限于其可能的不同配置总数。一个配置由磁带内容、读写头位置和状态组成。在 S(n) 空间内,可能的磁带内容数最多为 |Γ|^{S(n)}(Γ为磁带字母表),加上有限的状态和读写头位置,总配置数最多为 c^{S(n)}(c为常数)。由于作为判定器的图灵机不能重复配置(否则会无限循环),其运行时间最多为配置总数。因此,我们有:
SPACE(S(n)) ⊆ TIME(c^{S(n)})
这意味着,多项式空间可能对应指数时间。
PSPACE 包含 NP 与 coNP
基于上述关系,我们已知 P ⊆ PSPACE。但一个更强的结论是:NP ⊆ PSPACE。
以下是证明思路:
- SAT(布尔可满足性问题)是NP完全问题。
- 我们可以设计一个确定性算法在多项式空间内判定SAT:尝试所有可能的变量赋值(像里程表一样逐个生成),对每个赋值检查公式是否可满足。每次只存储一个赋值,空间复杂度为
O(n)。因此,SAT ∈ PSPACE。 - 由于SAT是NP完全的,任何NP中的语言
A都可以在多项式时间内归约到SAT。 - 多项式时间归约也可以在多项式空间内完成(因为时间限制隐含了空间限制)。
- 因此,任何NP语言
A都可以先归约到SAT,再用PSPACE算法解决,整个过程仍在多项式空间内。故 NP ⊆ PSPACE。
此外,由于PSPACE类对补运算封闭(只需将判定机的接受与拒绝状态互换),我们同样有 coNP ⊆ PSPACE。
目前我们了解的复杂度类关系可以总结为:P ⊆ NP ⊆ PSPACE 且 P ⊆ coNP ⊆ PSPACE。P是否等于NP,以及NP是否等于PSPACE,都是未解之谜。
例子一:真量化布尔公式(TQBF)
为了更具体地理解PSPACE,我们来看一个属于PSPACE的典型问题:真量化布尔公式问题。
量化布尔公式是在普通布尔公式(变量、与、或、非)前加上存在量词(∃)和全称量词(∀)构成的公式,且每个变量都必须被量词绑定。例如:
- P1 = ∀x ∃y (x ∨ y) ∧ (¬x ∨ ¬y)
- P2 = ∃y ∀x (x ∨ y) ∧ (¬x ∨ ¬y)
TQBF问题就是判定一个给定的量化布尔公式是否为真。
为什么TQBF在PSPACE中?
我们可以给出一个递归的确定性算法:
- 如果公式没有量词(也就没有变量),直接计算其布尔值。
- 如果公式形如 ∃x φ,则递归计算 φ(x=真) 和 φ(x=假)。如果任一结果为真,则接受。
- 如果公式形如 ∀x φ,则递归计算 φ(x=真) 和 φ(x=假)。如果两者结果都为真,则接受。
关键在于,在递归调用后,我们可以重用空间来计算另一个分支。递归深度最多为变量数 n,每层只需常数空间记录当前变量赋值,因此总空间复杂度为 O(n)。所以 TQBF ∈ PSPACE。值得注意的是,该算法的时间复杂度是指数级的。
例子二:词梯(Ladder)问题
接下来,我们通过一个更生动的问题来探讨非确定性空间计算。
词梯问题定义如下:给定一个确定性有限自动机(DFA)B(其定义的语言视为“合法单词”集合),以及两个合法字符串 u 和 v。问是否存在一个从 u 到 v 的“梯子”?梯子是一个字符串序列,其中相邻字符串仅在一个符号上不同,且序列中所有字符串都必须被 B 接受(即都是合法单词)。
为什么词梯问题在NPSPACE中?
我们可以设计一个非确定性多项式空间算法:
- 设当前字符串
y为起始串u。 - 重复以下步骤最多
T次(T是长度为m的字符串总数上界,即|Σ|^m):- 非确定性地将
y修改一个符号,得到新字符串y‘。 - 检查
y‘是否被B接受。如果不是,则拒绝此分支。 - 如果
y‘等于目标串v,则接受。 - 否则,令
y = y‘继续。
- 非确定性地将
- 如果循环
T次仍未到达v,则拒绝。
该算法只需存储当前字符串 y 和计数器,空间复杂度为 O(m)。因此,词梯问题属于 NSPACE(n)(这里 n 与输入规模相关)。
一个更惊人的结论是萨维奇定理的体现:词梯问题实际上也可以在确定性多项式空间(具体是平方级空间)内解决。这暗示了非确定性空间和确定性空间之间可能存在更紧密的联系,我们将在下节课深入探讨。
总结


本节课中我们一起学习了空间复杂度的基本概念。我们定义了SPACE和NSPACE复杂度类,以及PSPACE和NPSPACE。我们分析了时间与空间复杂度的基本包含关系,并证明了NP和coNP都是PSPACE的子集。最后,我们通过TQBF和词梯两个具体问题,加深了对多项式空间算法及其特点的理解。关键要点在于,空间可以被重用,这使得一些在时间上代价高昂(指数级)的问题,在空间上可能变得可行(多项式级)。下一节,我们将进一步探讨萨维奇定理及其揭示的非确定性与确定性空间复杂度之间的深刻关系。
017:PSPACE完全性


在本节课中,我们将学习空间复杂度、萨维奇定理以及PSPACE完全问题。我们将重点分析一个具体问题——阶梯问题,并以此为基础,理解如何将非确定性空间计算转换为确定性空间计算,以及如何证明一个问题是PSPACE完全的。
空间复杂度回顾
上一节我们介绍了空间复杂度的基本概念。空间复杂度衡量算法或问题所需的内存大小。我们定义了空间复杂度类 SPACE(f(n)) 和非确定性空间复杂度类 NSPACE(f(n)),以及多项式空间类 PSPACE 和非确定性多项式空间类 NPSPACE。
我们相信这些类之间存在包含关系,但许多问题尚未解决。例如,P、NP、coNP 与 PSPACE 的确切关系仍是开放性问题。
阶梯问题:一个关键示例
本节中,我们来看一个关键示例——有界阶梯问题。这个问题将帮助我们理解后续更抽象的定理。
阶梯 是指一个字符串序列,其中相邻字符串仅有一个符号不同。有界阶梯问题 是:给定一个确定有限自动机(DFA)、两个字符串 u 和 v,以及一个步数界限 B,判断是否存在一个长度不超过 B 的阶梯,从 u 连接到 v,且阶梯上的每个字符串都被该DFA接受。
我们用符号 u →_B v 表示在最多 B 步内可以从 u 到达 v。
解决有界阶梯问题的算法
我们设计一个递归算法 BL 来解决此问题。算法的输入是 (M, u, v, B),其中 M 是DFA。
以下是算法的核心步骤:
- 基础情况(B = 1):检查
u和v是否都被M接受,并且它们是否恰好在一个符号位置上不同。如果是,则接受;否则,拒绝。 - 递归情况(B > 1):尝试所有可能的中间字符串
w。对于每个w,递归地检查:- 能否在
B/2步内从u到达w(即调用BL(M, u, w, B/2))。 - 能否在
B/2步内从w到达v(即调用BL(M, w, v, B/2))。 - 如果对某个
w,两次递归调用都返回接受,则算法接受。 - 如果尝试了所有
w后仍未找到成功的路径,则算法拒绝。
- 能否在
要解决原始的无界阶梯问题,只需将界限 B 设置为可能的最大阶梯长度 T,即所有长度为 m(u 和 v 的长度)的字符串总数 |Σ|^m,然后调用 BL(M, u, v, T)。
空间复杂度分析
理解该算法的空间使用至关重要。
- 每次递归调用需要存储一个候选中间字符串
w,其长度与输入字符串相同,因此需要O(m)空间。 - 递归深度是多少?初始界限
T = |Σ|^m是指数级的。每次递归我们将步数界限B减半,因此递归深度为O(log T) = O(m)。 - 关键点在于,当从一层递归返回时,其使用的空间(用于存储
w)可以被后续递归调用重用。
因此,总空间复杂度是 O(m) * O(m) = O(m^2),即 O(n^2),其中 n 是输入的总大小。
这个算法展示了如何通过递归和空间重用来解决一个看似需要指数空间的问题,而只使用了多项式空间。
萨维奇定理:NPSPACE = PSPACE
上一节我们通过阶梯问题看到了空间重用的威力。本节中,我们来看看萨维奇定理,它指出非确定性多项式空间和确定性多项式空间是等价的。
萨维奇定理表明,任何在 f(n) 空间内运行的非确定性图灵机(NTM),都可以被一台在 f(n)^2 空间内运行的确定性图灵机(DTM)模拟。特别地,这意味着 PSPACE = NPSPACE。
定理证明思路
证明方法与解决阶梯问题的算法高度相似,但更抽象。我们不再考虑字符串和DFA,而是考虑图灵机的配置(即瞬时描述,包含状态、带内容和读写头位置)。
我们定义一个新问题:给定NTM N 的两个配置 C1 和 C2,以及一个步数界限 B,判断 N 能否在 B 步内从 C1 到达 C2。记作 C1 →_B C2。
我们构造一个确定性图灵机 M 来解决这个问题,算法同样是递归的:
- 基础情况(B = 1):
M直接检查根据N的转移函数,能否在一步内从C1变为C2。 - 递归情况(B > 1):
M枚举所有可能的中间配置C_mid。对于每个C_mid,递归地检查:C1 →_{B/2} C_mid是否成立。C_mid →_{B/2} C2是否成立。- 如果对某个
C_mid两者都成立,则接受。 - 如果所有
C_mid都不满足,则拒绝。
空间复杂度分析
- 存储一个配置需要
O(f(n))空间,因为N最多使用f(n)个带单元。 - 递归深度:初始界限
B是N在f(n)空间内可能的不同配置总数上限,即T = (状态数) * f(n) * (|Γ|^{f(n)}),其中Γ是带字母表。T是指数级O(c^{f(n)})。递归深度为O(log T) = O(f(n))。 - 空间在递归调用间被重用。
因此,模拟 N 的确定性机器 M 的总空间复杂度为 O(f(n)) * O(f(n)) = O(f(n)^2)。
阶梯问题的解法本质上是萨维奇定理在该具体问题上的应用。
PSPACE完全性
在学习了空间复杂度和萨维奇定理之后,我们现在转向PSPACE完全性的概念,这与NP完全性类似。
一个问题是 PSPACE完全的,如果:
- 它属于
PSPACE。 PSPACE中的每一个问题都可以在多项式时间内归约到它。
我们选择多项式时间归约而非多项式空间归约,是因为归约本身应该比所讨论的复杂性类(PSPACE)“更容易”。如果归约能力太强(如多项式空间归约),那么 PSPACE 内的任何两个问题都可以相互归约,导致所有 PSPACE 问题都是完全的,从而失去分类的意义。
如果某个PSPACE完全问题被发现属于 P,那么将导致 P = PSPACE。如果它属于 NP,则将导致 NP = PSPACE = coNP。
TQBF是PSPACE完全的
本节我们将证明,真量化布尔公式问题 是PSPACE完全的。TQBF是指所有为真的量化布尔公式的集合。
例如,公式 ∃x ∀y [(x ∨ y) ∧ (¬x ∨ ¬y)] 为真,而 ∀x ∃y [(x ∨ y) ∧ (¬x ∨ ¬y)] 为假。
证明思路:构造归约
我们需要证明,对于任意语言 A ∈ PSPACE,存在多项式时间归约 f,将 A 的实例 w 映射为一个量化布尔公式 φ,使得 w ∈ A 当且仅当 φ ∈ TQBF(即 φ 为真)。
设 M 是判定 A 的确定性多项式空间图灵机。归约 f 将构造一个公式 φ,其含义是“M 接受输入 w”。
尝试一:直接模拟(失败)
我们可以模仿证明SAT是NP完全的库克-列文定理,为 M 在 w 上的计算构造一个计算表格。表格的宽度是 M 的空间界限 n^k,高度是其最大运行步数,这可能是 O(c^{n^k})(指数级)。直接为每个表格单元创建变量并描述其正确性,得到的公式大小与表格相同,即指数级大,无法在多项式时间内构造出来。
尝试二:递归构造(仍需改进)
我们采用与萨维奇定理和阶梯问题相似的递归思想。定义公式 φ_{C_i, C_j, B},表示“M 能从配置 C_i 在 B 步内到达配置 C_j”。
对于 B > 1,我们尝试写成:
φ_{C_i, C_j, B} = ∃C_mid [φ_{C_i, C_mid, B/2} ∧ φ_{C_mid, C_j, B/2}]
这表示:存在一个中间配置 C_mid,使得从 C_i 到 C_mid 和从 C_mid 到 C_j 都能在 B/2 步内完成。
问题:这种递归会导致公式大小爆炸。因为每一层递归,一个公式会变成两个子公式的合取,子公式数量呈指数增长(1 -> 2 -> 4 -> 8 ...)。递归深度是 O(log(初始B)) = O(n^k),最终公式大小是指数级的。
解决方案:缩写技巧
关键改进在于利用全称量词 ∀ 来“压缩”合取 ∧。我们可以等价地重写上面的公式:
φ_{C_i, C_j, B} = ∃C_mid ∀(C_g, C_h) ∈ {(C_i, C_mid), (C_mid, C_j)} [φ_{C_g, C_h, B/2}]
这个公式的意思是:存在一个中间配置 C_mid,使得对于有序对 (C_g, C_h) 取值为 (C_i, C_mid) 或 (C_mid, C_j) 的两种情况,公式 φ_{C_g, C_h, B/2} 都成立。
这里,∀(C_g, C_h) ∈ S [P(C_g, C_h)] 可以通过 ∀C_g ∀C_h [ ( (C_g = C_i ∧ C_h = C_mid) ∨ (C_g = C_mid ∧ C_h = C_j) ) ⇒ P(C_g, C_h) ] 来实现,而蕴含关系 ⇒ 可以用 ∧ 和 ∨ 表达。
优势:现在,每一层递归,我们只是在现有公式前添加一些量词和布尔连接词(描述 C_g, C_h 的取值条件),而不是将公式复制成两份。添加的内容大小是 O(n^k)。
- 递归基础(B = 1):此时可以直接构造一个大小固定的公式来描述一步转移是否合法(类似于库克-列文定理中对局部窗口的约束)。
- 递归过程:从
B = T(最大运行时间)开始,应用上述规则不断递归,直到B = 1。 - 最终公式:
φ_{start, accept, T}即为我们所需的φ,它表达了“M从起始配置能在T步内到达接受配置”。
公式大小分析
- 递归深度:
O(log T) = O(n^k)。 - 每层递归添加
O(n^k)大小的量词和连接词。 - 因此,最终公式
φ的总大小为O(n^k) * O(n^k) = O(n^{2k}),即多项式大小。归约函数f可以在多项式时间内构造出这个公式。
这就证明了从任意 PSPACE 问题到 TQBF 的多项式时间归约的存在性。由于 TQBF 本身显然在 PSPACE 内(可以用类似本证明的递归算法在多项式空间内求值),因此 TQBF 是 PSPACE 完全的。
总结
本节课中我们一起学习了:
- 空间复杂度 的基本概念和类别(
PSPACE,NPSPACE)。 - 通过有界阶梯问题,我们看到了一个利用递归和空间重用,在平方空间内解决复杂问题的具体算法。
- 萨维奇定理 指出
NPSPACE = PSPACE,其证明思想与阶梯问题算法一脉相承,展示了如何将非确定性空间计算平方后转换为确定性计算。 - PSPACE完全性 的定义及其意义。
- 证明了 TQBF(真量化布尔公式)问题是PSPACE完全的。证明的关键在于巧妙地使用递归构造量化布尔公式,并利用全称量词避免公式大小的指数爆炸,最终在多项式时间内完成归约。


这些内容揭示了空间复杂度理论与完全性理论之间的深刻联系,并为理解更高级的复杂性类别奠定了基础。
018:游戏与广义地理学 🎮

在本节课中,我们将学习空间复杂度的相关内容,特别是如何将量化布尔公式(TQBF)问题与一种称为“广义地理学”的游戏联系起来,并证明后者是PSPACE完全问题。我们还将初步探讨对数空间复杂度类L和NL。
回顾与概述 📝
上一讲我们介绍了几个定理,它们的证明思路基本相同。其中一个涉及“梯子问题”,即判断能否通过每次改变一个符号,从一个字符串变换到另一个字符串,且所有中间字符串都符合某个有限自动机的语言或特定规则。基于这个思想,我们证明了萨维奇定理:任何非确定性图灵机都可以用确定性图灵机模拟,所需空间仅需平方。最后,我们证明了TQBF(判断量化布尔公式是否为真)问题是PSPACE完全的。
本节我们将以此为基础,讨论另一个PSPACE完全问题,并展示PSPACE与某些游戏中判断哪一方必胜之间的联系。课程后半部分,我们将深入探讨空间复杂度,特别是研究对数空间复杂度类。
广义地理学游戏 🗺️
首先,我们介绍一个名为“地理学”的游戏。游戏规则如下:两名玩家轮流说出地名,每个新地名必须以上一地名的最后一个字母开头,且地名不能重复。无法说出新地名的玩家判负。
我们将这个游戏抽象化,得到“广义地理学”游戏。游戏在一个有向图上进行,指定一个起始节点。两名玩家轮流沿着图中的边移动,访问过的节点不能再次访问,从而共同构建一条简单路径。首先无法移动的玩家判负。
我们定义问题GG:给定一个有向图和一个起始节点,判断在双方都采取最优策略的情况下,先手玩家(玩家一)是否拥有必胜策略(即“强制获胜”)。
核心概念:判断图G和起始节点s是否属于语言GG,即玩家一是否有强制获胜策略。
游戏与必胜策略 🏆
理解“强制获胜”或“必胜策略”的概念至关重要。它意味着,无论对手如何应对,拥有该策略的玩家总有一系列应对方法,能确保自己最终获胜。对于广义地理学这类游戏,双方中必有一方拥有必胜策略。
让我们通过一个简单例子来理解。考虑下图,起始节点为a,玩家一先手。
a -> b
a -> c
b -> d
c -> e
d -> f
e -> f
玩家一从a开始。如果玩家二选择走到b,则玩家一只能走到d,然后玩家二无路可走,玩家一获胜。然而,如果玩家二选择走到c,则玩家一走到e,玩家二可以走到f,此时玩家一无路可走,玩家二获胜。因此,玩家二拥有必胜策略(选择走到c)。所以,对于这个图实例,(G, a) 不属于语言GG。
公式游戏与TQBF 🔢
为了建立游戏与复杂度的联系,我们引入“公式游戏”。游戏基于一个量化布尔公式,例如:∃x1 ∀x2 ∃x3 ... ψ(x1, x2, x3, ...)。
游戏有两名玩家:玩家∃ 和 玩家∀。玩家按量词顺序轮流为变量赋值:玩家∃ 为存在量词(∃)变量赋值,玩家∀ 为全称量词(∀)变量赋值。所有变量赋值完成后,计算公式中无量词部分ψ的真值。若ψ为真,则玩家∃获胜;否则玩家∀获胜。
核心洞察:玩家∃在公式游戏中拥有必胜策略,当且仅当原量化布尔公式为真。这是因为“存在必胜策略”的语义恰好对应了量词的逻辑含义:存在一种对x1的赋值,使得对于x2的所有赋值,都存在对x3的赋值……最终使ψ为真。
因此,判断公式游戏中哪一方必胜的问题,等价于TQBF问题。
从TQBF归约到广义地理学 ⛓️
我们的目标是证明广义地理学(GG)是PSPACE完全的。已知TQBF是PSPACE完全的,因此我们只需将TQBF多项式时间归约到GG。
给定一个TQBF公式(假设已转化为合取范式CNF),我们构造一个广义地理学游戏图,使得在该图上的游戏模拟原公式游戏。构造的核心思想是:图中的路径选择对应变量的赋值,并最终通过子句结构来判定公式ψ是否被满足。
构造简述:
- 变量赋值部分:为每个变量xi创建一个菱形结构。玩家在菱形中走左侧或右侧,分别对应将xi赋值为真或假。通过精心设计节点和边的连接,可以确保
玩家∃(对应玩家一)和玩家∀(对应玩家二)在各自变量上做出选择。 - 子句验证部分:在所有变量赋值完成后,路径进入子句验证模块。这里包含代表每个子句的节点,以及代表子句中每个文字的节点。文字节点连接回变量赋值部分对应的真值分支。
- 游戏流程:在赋值阶段,双方通过在图中的移动完成对公式变量的赋值。进入验证阶段后,
玩家∀可以选择一个声称未被满足的子句节点。然后玩家∃必须从该子句中选一个文字节点。如果该文字在之前的赋值中为真,则玩家∀将无路可走(因为对应的图节点已被访问),玩家∃获胜。如果该文字为假,则玩家∀可以移动到该文字节点,导致玩家∃无路可走,玩家∀获胜。
通过这种构造,玩家∃在广义地理学游戏中获胜,当且仅当其在原公式游戏中有必胜策略,即原TQBF公式为真。这就完成了从TQBF到GG的归约,证明了GG是PSPACE完全的。
对数空间复杂度初探 💾
现在,我们转换话题,探讨空间复杂度的另一个重要领域:对数空间。
由于标准单带图灵机在读取长度为n的输入时就会使用n的空间,为了定义亚线性空间(如对数空间)复杂度类,我们需要新的模型。
只读输入图灵机模型:
- 机器有一条只读输入带,存放输入,其空间不计入复杂度。
- 机器有一条可读写的工作带,其使用的空间才计入空间复杂度。
- 空间复杂度
S(n)定义为工作带上使用的格子数。
我们定义:
- L =
SPACE(log n):确定性对数空间可判定的语言类。 - NL =
NSPACE(log n):非确定性对数空间可判定的语言类。
对数空间仅够存储固定数量的指针或索引,功能相对较弱。
例子:
- 回文语言(形如ww^R)属于L。我们可以用工作带存储两个指针,分别从输入首尾向中间移动比较字符。
- 有向图路径问题(PATH)属于NL。非确定性算法可以猜测路径,但只在工作带上存储当前节点位置,并配合一个计数器防止循环。
对数空间的基本性质 📊
关于L和NL,有以下基本事实:
- L ⊆ NL:确定性类自然包含于非确定性类。
- L ⊆ P,NL ⊆ NP:任何对数空间(无论确定性与否)算法,其运行时间都是多项式级的。原因在于,对于固定输入,机器的格局(状态、工作带内容、读写头位置)总数是多项式级的(因为工作带内容有
c^(log n) = n^k种可能)。机器不可能运行超过多项式步而不进入循环,因此它必然在多项式时间内停机。 - 萨维奇定理对对数空间成立:
NSPACE(log n) ⊆ SPACE(log^2 n)。即任何非确定性对数空间算法,都可以用确定性log^2 n空间来模拟。
一个重要构造:格局图
对于非确定性图灵机M和输入w,可以构造其格局图。图的节点是M在w上的所有可能格局。如果格局Cj可以在M的一步内从格局Ci到达,则存在从Ci到Cj的边。那么,M接受w当且仅当在格局图中,从起始格局存在一条路径到达某个接受格局。
由于格局数是多项式级的,构造此图并检查路径存在性(例如使用图可达性算法)可以在多项式时间内完成。这给出了NL ⊆ P的另一种证明。
总结 🎯
本节课我们一起学习了以下内容:
- 我们介绍了广义地理学游戏,并将其形式化为一个计算问题GG。
- 我们探讨了公式游戏,并建立了其必胜策略问题与TQBF问题的等价性。
- 通过精巧的图构造,我们展示了如何将TQBF问题归约到广义地理学问题,从而证明GG是PSPACE完全问题。这建立了PSPACE与特定游戏必胜策略判定之间的深刻联系。
- 课程后半部分,我们转向了对数空间复杂度,介绍了只读输入图灵机模型,并定义了复杂度类L和NL。
- 我们了解了L和NL的基本性质,包括它们与P和NP的包含关系,以及萨维奇定理在对数空间下的应用。我们还介绍了格局图的概念,它是分析空间有界计算的有力工具。


下节课我们将更深入地探索对数空间复杂度,特别是NL完全问题以及相关的复杂性类关系。
019:L和NL,NL = coNL

在本节课中,我们将继续讨论空间复杂度,特别是对数空间复杂度类L和NL。我们将回顾L和NL的定义与示例,介绍对数空间归约和NL完全问题的概念,并最终证明一个重要的定理:NL类在补集运算下是封闭的,即NL = coNL。
回顾:L和NL类
上一节我们介绍了时间复杂度的概念,并转向了空间复杂度。我们首先讨论了多项式空间(PSPACE),并证明了存在PSPACE完全问题,如TQBF语言和广义地理游戏。随后,我们将注意力转向更小的空间复杂度类:对数空间。
为了讨论小于线性空间(n)的复杂度类,我们引入了一个新的计算模型:双带图灵机。该模型包含一个只读输入带(存储可能非常大的输入)和一个读写工作带(作为本地内存)。在讨论对数空间时,我们限定工作带最多使用 O(log n) 个存储单元,这足以存储指向输入位置的指针或计数器。
我们定义了以下两个重要的复杂度类:
- L:由确定性图灵机在对数空间内判定的语言集合。
- NL:由非确定性图灵机在对数空间内判定的语言集合。
以下是两个示例语言:
- 语言 A = {ww^R | w ∈ {0,1}*}(回文串)。这个语言属于 L。一个对数空间的确定性图灵机可以通过使用工作带上的指针(记录当前比较的字符位置)来检查输入是否为这种形式。
- PATH语言:给定一个有向图G和起点s、终点t,判断是否存在从s到t的路径。这个语言属于 NL。一个非确定性对数空间图灵机可以猜测一条从s到t的路径,并在工作带上记录当前所在的节点。
L与NL的关系类似于P与NP的关系,是一个尚未解决的开放性问题。然而,与NP和coNP的关系不同,我们将证明NL等于coNL。
L、NL与P的关系
上一节我们快速提到了L和NL与P类的关系,本节我们来详细看看。
首先,任何在L中的语言也一定在P中。证明的关键在于理解对数空间图灵机的格局。
一个机器在输入w上的格局包含了其动态部分:状态、两个读写头的位置以及工作带的内容。输入带的内容是固定的,因此不计入格局。
对于一个运行在O(log n)空间上的机器,其可能的格局总数是多项式级别的。因为工作带内容有 c^(O(log n)) = n^(O(1)) 种可能(c是带字母表大小),状态数和读写头位置数也是多项式级别。
因此,一台总是停机的对数空间机器,其运行步数不可能超过其格局总数(否则会进入循环)。所以,它的运行时间是多项式的。这直接证明了 L ⊆ P。
类似地,萨维奇定理在对数空间层级也成立。它表明,任何非确定性对数空间(NL)机器都可以被一台确定性机器在对数平方空间(O(log² n))内模拟。证明思路与之前相同:构造计算表,并递归地检查是否存在接受路径,递归深度为多项式,每层需要O(log n)空间存储一个格局。
更重要的是,我们可以证明 NL ⊆ P。我们通过构造一个确定性多项式时间算法来模拟非确定性对数空间机器M。
核心思想是构建M在输入w上的格局图 G_{M,w}。
- 节点:M在w上所有可能的格局。
- 边:如果格局C_i可以在M的一步非确定性转移中变为格局C_j,则存在一条从C_i到C_j的边。
由于M是对数空间的,其格局总数是多项式级别的,因此这个格局图的大小也是多项式的。
M接受输入w,当且仅当在格局图 G_{M,w} 中,存在一条从起始格局 C_start 到唯一接受格局 C_accept 的路径(我们约定接受前机器会清空工作带并归位读写头,从而保证接受格局唯一)。
因此,我们的多项式时间模拟算法如下:
- 在输入w上,构造格局图
G_{M,w}。 - 使用图搜索算法(如BFS或DFS)检查图中是否存在从
C_start到C_accept的路径。 - 如果存在路径,则接受;否则拒绝。
这就证明了NL ⊆ P。结合L ⊆ NL,我们得到包含关系:L ⊆ NL ⊆ P。
对数空间归约与NL完全性
类似于NP完全性,为了研究L与NL的关系,我们需要定义NL完全问题。但这里不能使用多项式时间归约,因为NL ⊆ P,任何两个P中的语言都可以多项式时间相互归约,这会使归约概念失去意义。我们需要一个更弱的归约概念:对数空间归约。
为了定义可对数空间计算的函数,我们引入对数空间转换器模型。这是一个三带确定性图灵机:
- 只读输入带:存放输入w。
- 读写工作带:最多使用O(log |w|)空间。
- 只写输出带:用于输出结果f(w),机器只能向右移动并写入,不能回读。
我们说一个函数f是对数空间可计算的,如果存在一个对数空间转换器,对于任何输入w,它停机时输出带上正好是f(w)。
现在我们可以定义归约:语言A 对数空间可归约到语言B(记作 A ≤_L B),如果存在一个对数空间可计算的函数f,使得对于所有输入w,有 w ∈ A ⇔ f(w) ∈ B。
这里有一个技术细节需要注意。假设 A ≤_L B 且 B ∈ L,我们想证明 A ∈ L。自然的想法是:对于输入w,先计算 f(w),然后用B的对数空间判定器判断 f(w) 是否属于B。但问题在于,f(w) 的长度可能是多项式的,我们无法将其整个存储在对数空间的工作带上。
解决方案是:B的判定器在运行时,一次只需要查看 f(w) 的一个符号。因此,我们不需要预先计算并存储整个 f(w),而是在B的判定器需要某个符号时,临时启动转换器重新计算该符号。每次需要新符号时,我们都从头运行转换器,并忽略直到目标位置之前的所有输出。这个过程虽然耗时(多项式时间),但只使用了对数空间的工作内存。这就证明了如果 A ≤_L B 且 B ∈ L,则 A ∈ L。
现在我们定义NL完全性:一个语言B是NL完全的,如果:
B ∈ NL。- 对于NL中的每一个语言A,都有
A ≤_L B。
PATH问题是NL完全的
我们将证明之前提到的PATH问题是NL完全的。
首先,PATH ∈ NL 我们已经知道。现在需要证明,对于任意语言 A ∈ NL,都有 A ≤_L PATH。
设非确定性图灵机M在O(log n)空间内判定语言A。我们构造一个对数空间归约函数f,将输入w映射为PATH问题的一个实例 (G, s, t)。
这个归约的核心思想与我们证明NL ⊆ P时类似:令 G 为M在输入w上的格局图 G_{M,w}。令 s 为起始格局 C_start,t 为唯一接受格局 C_accept。
那么,w ∈ A(即M接受w)当且仅当在格局图G中存在从s到t的路径。因此,f(w) = (G, s, t) 就是一个正确的归约。
现在需要证明函数f是对数空间可计算的。我们的对数空间转换器需要输出图G(边列表)以及起点s和终点t。由于格局总数是多项式N,我们可以通过枚举所有可能的格局对 (C_i, C_j) 来生成边列表:
- 在工作带上,依次生成所有可能的格局对(每个格局大小为O(log n),因此一对格局可在O(log n)空间内表示)。
- 对于每一对
(C_i, C_j),根据M的转移函数,判断C_i能否在一步内转移到C_j。如果可以,则将这条边(C_i, C_j)输出到输出带。 - 最后,输出起始格局
C_start和接受格局C_accept作为s和t。
整个过程只需要在工作带上存储至多两个格局,因此空间复杂度为O(log n)。这就证明了PATH是NL完全的。
如果PATH能在确定性对数空间(L)内解决,那么所有NL问题都能在L内解决,即L = NL。这正是该问题重要性的体现。
NL = coNL 的证明
本节我们将证明一个令人惊讶的定理:NL类在补集运算下封闭,即 NL = coNL。这与我们对NP的认知(相信NP ≠ coNP)形成对比。
证明思路是:由于PATH是NL完全的,那么PATH的补集(¬PATH,即判断图中是否不存在从s到t的路径)就是coNL完全的。如果我们能证明 ¬PATH ∈ NL,那么任何coNL中的语言都可以通过对数空间归约到 ¬PATH,从而也在NL中,这就证明了 coNL ⊆ NL。反过来,NL ⊆ coNL 是显然的(交换接受和拒绝状态),因此两者相等。
所以,核心任务是构造一个非确定性对数空间图灵机N,使其能够判定 ¬PATH。即,当图G中没有从s到t的路径时,N的某些计算分支接受;当存在路径时,N的所有分支都拒绝。
直接“反转”PATH的非确定性算法是行不通的,因为非确定性接受要求至少有一条路径接受,而反转后需要确保所有路径都不存在,这很难用非确定性直接验证。
我们需要一个更巧妙的方法。首先引入一个概念:非确定性对数空间计算函数。我们允许非确定性图灵机的某些分支输出一个函数值,其他分支可以“拒绝”(不输出)。要求是:至少有一个分支输出值,并且所有输出值的分支必须输出相同的正确结果。
假设我们有一个非确定性对数空间机器可以计算以下函数:给定图G和起点s,输出从s可到达的节点数量 c = |R|,其中R是从s出发可达的节点集合。
如果我们能计算这个计数函数,那么我们就可以用它来判定 ¬PATH。思路如下:
设已知从s可达的节点数为c。非确定性地,我们尝试“猜出”所有c个可达节点。
- 我们依次考虑图中的每个节点u。
- 对于每个u,我们非确定性地猜测它是否可达(P)或不可达(N)。
- 如果猜测u可达(P),那么我们同时非确定性地猜测一条从s到u的路径来验证。如果找不到这样的路径,当前分支“拒绝”(失败)。
- 在验证过程中,如果发现当前正在检查的节点t(我们想知道s到t是否有路径)被验证为可达,那么我们就知道存在s到t的路径,当前分支可以输出“是”(对于PATH问题)或在此处“拒绝”(对于
¬PATH问题,因为此时不应接受)。 - 我们统计所有被成功验证为可达的节点数量k。
- 在检查完所有节点后,如果统计的数量k等于已知的计数c,并且节点t不在这k个已验证的可达节点之中,那么我们就可以确信t是不可达的。此时,对于
¬PATH问题,我们可以接受(输出“否”)。
关键在于,至少会有一个非确定性分支正确地猜出了所有c个可达节点及其验证路径。如果t不可达,这个分支最终会发现k=c且t不在列表中,从而接受。如果t可达,那么任何正确的分支在验证过程中都会提前遇到t,并根据算法设计不会到达最终的接受步骤。
因此,问题的核心就转化为:如何非确定性地在对数空间内计算从s出发的可达节点数c?
计算c的过程运用了类似的“逐步逼近”技巧,其本身就是一个巧妙的迭代算法(称为“自我归约”)。由于时间关系,其具体细节将在下节课展开。但基本思想是:从计数0开始,通过多次利用“验证可达节点集合”的子程序,逐步确定可达节点的数量。这个算法可以非确定性地在对数空间内完成。
综上所述,我们能够非确定性地在对数空间内判定 ¬PATH,从而证明了 coNL ⊆ NL,结合 NL ⊆ coNL,得到 NL = coNL。
总结


本节课我们一起深入探讨了对数空间复杂度类L和NL。
- 我们回顾了L和NL的定义,以及它们与P类的关系(L ⊆ NL ⊆ P)。
- 我们引入了对数空间归约和NL完全性的概念,并证明了PATH问题是NL完全的。
- 最后,我们证明了一个关键定理:NL类在补集运算下是封闭的,即 NL = coNL。这个证明通过展示如何非确定性地在对数空间内计算图中从某点出发的可达节点数,并利用该计数来判定PATH的补集问题。这个结果揭示了非确定性对数空间的一个深刻性质,与NP类形成了有趣的对
020:层次定理 👨🏫

在本节课中,我们将要学习两个核心主题:首先,我们将完成关于 NL = coNL 的证明,这是一个令人惊讶的结果,表明非确定性对数空间类在补集运算下是封闭的。其次,我们将探讨层次定理,该定理表明,为图灵机提供更多的资源(时间或空间)确实能让它解决更多的问题。
回顾:NL = coNL 的证明思路
上一节我们介绍了 Immerman–Szelepcsényi 定理,即 NL = coNL。为了证明这一点,我们只需要证明 PATH 问题的补集(即判断图中从起点 s 到终点 t 不存在路径的问题)可以在 NL 中解决。
我们采取的策略是:构造一个非确定性对数空间图灵机来计算一个特殊的 PATH 函数。这个函数对于输入 (G, s, t),当存在从 s 到 t 的路径时输出“是”,否则输出“否”。如果我们能非确定性地计算这个函数,那么通过接受所有输出“否”的分支,我们就能在 NL 内解决 PATH 的补集问题。
核心概念:可到达节点计数
证明的关键在于引入一个中间量:从起点 s 可到达的节点数量。我们定义:
R: 从s出发可到达的节点集合。c: 集合R的大小,即c = |R|。
我们将证明,如果我们能非确定性地计算出 c,那么我们就能利用它来测试任意节点 t 是否可达,从而计算出 PATH 函数。
从计数到路径判定 🔄
以下是证明的核心步骤,展示了如何利用可到达节点计数 c 来判定路径是否存在。
步骤一:已知 PATH 函数,计算计数 c
如果我们有一个非确定性图灵机 M 可以计算 PATH 函数(即对每个节点 u 判定 s -> u 是否可达),那么计算 c 是简单的。算法如下:
- 初始化计数器
count = 0。 - 遍历图中的每一个节点
u。 - 在节点
u上运行机器M来判定s -> u是否可达。 - 如果
M的输出是“是”,则将count加 1。 - 遍历完所有节点后,输出
count作为c。
由于 M 在 NL 中,且我们只需额外存储一个计数器(对数空间),因此整个计算过程也在 NL 中。
步骤二:已知计数 c,判定 PATH 函数(核心算法)
这是证明中最巧妙的部分。假设我们神奇地知道了从 s 出发恰好有 c 个节点可达。我们可以利用这个信息来判定任意目标节点 t 是否可达。
算法思路:非确定性地“猜测”出所有 c 个可达节点。如果我们的猜测正确(即恰好找到了所有可达节点),并且 t 不在其中,那么我们就知道 t 是不可达的。
以下是算法的非确定性过程:
- 初始化
k = 0,用于记录已发现的可达节点数。 - 遍历图中的每一个节点
u:- 非确定性选择:猜测
u是否可达。 - 如果猜测“可达”:
- 非确定性地猜测一条从
s到u的长度不超过n(节点总数)的路径。 - 如果未能找到这样一条路径(即猜测错误),则拒绝(此分支失败)。
- 如果成功找到路径,则:
- 如果
u == t,则接受(因为找到了到t的路径)。 - 否则,
k = k + 1。
- 如果
- 非确定性地猜测一条从
- 如果猜测“不可达”:继续处理下一个节点。
- 非确定性选择:猜测
- 遍历完所有节点后,检查
k == c。- 如果
k != c,说明我们的猜测集合没有包含所有可达节点,此分支拒绝。 - 如果
k == c,说明我们正确找到了所有c个可达节点。既然在步骤2中未因找到t而接受,那么t肯定不在此集合中,因此输出“否”(即t不可达)。
- 如果
这个算法只需要存储当前节点 u、计数器 k 和已知的常数 c,所有这些都是对数空间,因此它在 NL 中。
步骤三:计算计数 c 本身
现在的问题是如何获得那个关键的计数 c。我们通过一个递推过程来计算它。定义:
R_d: 从s出发,在d步内(路径长度 ≤d)可到达的节点集合。c_d: 集合R_d的大小,即c_d = |R_d|。
显然,c_n = c(其中 n 是节点总数)。我们可以从 c_0 = 1(只有 s 自身在0步内可达)开始计算。
如果我们已知 c_d,我们可以利用与步骤二类似的算法(但将路径长度限制为 d)来判定“在 d 步内是否可达”这个问题。一旦我们能判定每个节点在 d 步内是否可达,我们就可以像步骤一那样数出它们的数量,从而得到 c_{d+1}。
通过这种递推,我们可以从 c_0 开始,逐步计算出 c_1, c_2, ..., c_n = c。每一步都只需要对数空间。最终,我们得到了计算 PATH 函数所需的关键值 c。
结合以上三个步骤,我们构造出了一个在 NL 中计算 PATH 函数的非确定性图灵机。因此,PATH 的补集也在 NL 中,从而证明了 NL = coNL。
空间与时间层次定理 🏔️
上一节我们证明了复杂性类之间有趣的相等关系。现在,我们来看看它们之间的不等关系。层次定理告诉我们,提供更多的计算资源确实能解决更多的问题。
空间层次定理
定理:对于空间可构造函数 f(n)(例如 f(n) = n^2, n^3 等),存在一个语言 A,使得:
A ∈ SPACE(f(n))(A可以在O(f(n))空间内判定)。A ∉ SPACE(o(f(n)))(A不能在o(f(n))空间内判定)。
其中 o(f(n)) 表示比 f(n) 增长严格更慢的函数集合。
通俗解释:对于任意一个“足够好”的空间界限 f(n),总存在一些问题,恰好需要大约 f(n) 的空间才能解决,用更少的空间是无法解决的。这意味着空间复杂性类形成了一个真包含的无穷层次结构:
SPACE(n) ⊂ SPACE(n^2) ⊂ SPACE(n^3) ⊂ ...
证明思路(对角化法):
我们通过构造一个图灵机 D 来定义语言 A(即 A = L(D))。D 的设计确保它自己的语言 A 无法被任何运行在 o(f(n)) 空间内的图灵机所识别。
D在O(f(n))空间内运行:D在输入w(长度为n)上启动时,首先在磁带上标记出f(n)个单元格。如果计算过程中需要超过这个空间,D就拒绝。D试图与所有“小空间”机器不同:D将输入w解释为另一个图灵机M_w的编码(如果w编码非法,则直接拒绝)。然后,D尝试在分配的空间限制内模拟M_w在输入w上的运行。- 如果模拟成功完成,且
M_w接受w,则D拒绝w。 - 如果模拟成功完成,且
M_w拒绝w,则D接受w。 - 如果模拟因空间不足或超过时间限制(为避免无限循环,需设置一个步数上限)而无法完成,
D也拒绝w。
- 如果模拟成功完成,且
为什么这行得通? 对于任何运行在 o(f(n)) 空间内的图灵机 M,当输入 w 足够长(且 w 是 M 的编码加上足够多的填充字符)时,D 将拥有足够的空间来成功模拟 M 在 w 上的运行。根据构造,D 在 w 上的行为与 M 相反,因此 L(D) ≠ L(M)。这就证明了 L(D)(即 A)不在 SPACE(o(f(n))) 中。
时间层次定理
时间层次定理与空间层次定理类似,但有一个技术性的对数因子差距。
定理:对于时间可构造函数 f(n)(例如 f(n) = n^2, n^3 等),存在一个语言 A,使得:
A ∈ TIME(f(n))。A ∉ TIME(o(f(n) / log f(n)))。
通俗解释:给予更多的计算时间,也能解决更多的问题。但是,证明要求的时间差距比空间定理稍大一点(多了一个 log f(n) 因子),这主要源于模拟开销。
证明思路:与空间层次定理的证明非常相似,也是通过对角化法构造一个图灵机 D。主要区别在于:
D使用f(n)作为步数计数器(时钟),以防止模拟无限循环。- 在模拟另一个机器
M时,为了高效查找M的转移函数,D需要将M的描述随身携带在磁头上。管理这个步数计数器会引入额外的log f(n)因子开销,因此D只能与运行时间比f(n)/log f(n)更短的机器区分开来。
层次定理的推论与应用 💡
层次定理为我们提供了第一批确定的、严格的复杂性类包含关系。
- 已知的分离结果:根据空间层次定理,我们知道
SPACE(n) ⊂ SPACE(n^2)。由于NL ⊆ SPACE(log^2 n),且PSPACE包含所有多项式空间,因此我们可以得出NL ⊂ PSPACE。这是一个被严格证明的不相等关系。 - 对未解问题的启示:虽然我们不知道
P是否等于NP,也不知道L是否等于P,但层次定理告诉我们,L ≠ PSPACE。因此,L = P和P = PSPACE这两个等式中至少有一个不成立(事实上,普遍认为两者都不成立)。
总结 🎯
本节课中我们一起学习了:
- NL = coNL 的证明:通过巧妙地非确定性地计算从起点可达的节点数量,并将其用于判定任意节点是否可达,我们证明了非确定性对数空间类在补集运算下封闭。这是一个深刻且起初令人意外的结果。
- 空间与时间层次定理:通过对角化方法,我们证明了为图灵机提供更多的空间或时间资源,确实能够扩大其所能解决问题的范围。这确立了复杂性类之间严格的无穷层次结构,并为我们提供了一些像
NL ⊂ PSPACE这样的确定分离关系。


这些定理勾勒出了计算复杂性理论的基本格局:既有像 NL = coNL 这样的优美对称性,也有像层次定理所揭示的、资源增加必然带来能力提升的严格层次性。
021:可证明的棘手问题与神谕


在本节课中,我们将学习如何证明一个问题是“天然”棘手的,即它无法在多项式时间内解决。我们将通过证明一个具体问题是“指数空间完全”的来展示这一点。此外,我们还将探讨“神谕”的概念,并了解它为何能揭示解决P与NP问题的方法局限性。
回顾:时间与空间层次定理
上一节我们介绍了时间与空间层次定理。简单来说,这些定理表明,如果允许计算模型使用稍多一些的资源(时间或空间),那么它就能解决更多的问题。证明的核心思想是对角化。
这些定理意味着,复杂度类形成了一个层次结构。例如,随着空间界限从 n^2 增加到 n^3、n^4,我们能解决的问题类会变得越来越大。对于时间复杂性也是如此。
一个重要的推论是:NL(非确定性对数空间)是 PSPACE(多项式空间)的真子集。这意味着存在一些问题在PSPACE中,但不在NL中。我们之前学过的 TQBF(全量词化布尔公式可满足性)问题就是一个例子,它是PSPACE完全的,因此肯定不在NL中。
引入指数复杂度类
为了找到天然棘手的问题,我们首先需要引入两个新的复杂度类:
- EXPTIME:能在
2^(n^k)时间内解决的问题集合。 - EXPSPACE:能在
2^(n^k)空间内解决的问题集合。
这些类比多项式时间(P)和多项式空间(PSPACE)要大得多。根据层次定理,我们可以证明一些分离关系:
- P ≠ EXPTIME
- PSPACE ≠ EXPSPACE
接下来,我们定义这两个新类的“完全问题”:
- 一个问题是 EXPTIME完全的,如果它属于EXPTIME,并且EXPTIME中的每一个问题都能在多项式时间内归约到它。
- 一个问题是 EXPSPACE完全的,如果它属于EXPSPACE,并且EXPSPACE中的每一个问题都能在多项式时间内归约到它。
关键点:如果一个问题是EXPTIME完全的,那么它不可能在P中。因为如果它在P中,通过归约,整个EXPTIME类都会坍缩到P,这与P ≠ EXPTIME矛盾。同理,一个EXPSPACE完全的问题不可能在PSPACE或P中。
因此,我们的策略是:找到一个天然的、易于描述的问题,并证明它是EXPSPACE完全的。这样我们就证明了一个天然问题是棘手的。
一个天然棘手的问题:带乘方的正则表达式等价性
我们即将展示的问题是:带乘方的正则表达式等价性问题。
首先,回顾一下普通的正则表达式等价性问题(判断两个正则表达式是否描述相同的语言)。这个问题实际上在PSPACE中,并不棘手。
现在,我们增强正则表达式的语法,允许乘方操作。例如,R^k 表示将正则表达式 R 重复连接 k 次。如果 k 以二进制书写,这个操作可以极大地压缩表达式的长度。
带乘方的正则表达式等价性问题就是:给定两个允许使用乘方操作的正则表达式,判断它们是否等价。
定理:带乘方的正则表达式等价性问题是 EXPSPACE完全的。
由于EXPSPACE完全问题不在P中,这便是一个被证明的、天然的棘手问题。
证明概述(第一部分:属于EXPSPACE)
证明分为两部分。首先,需要证明该问题属于EXPSPACE。
- 给定两个带乘方的正则表达式,首先通过展开所有乘方操作,将它们转换为普通的(但可能指数级大的)正则表达式。
- 然后,对这两个展开后的巨型表达式运行已知的PSPACE等价性测试算法。
- 由于输入(展开后的表达式)大小是指数级的,而算法是PSPACE的,因此总空间消耗是原始输入大小的指数级,即该问题在EXPSPACE中。
证明概述(第二部分:EXPSPACE难度,即归约)
第二部分更有趣:证明EXPSPACE中的任何问题都能归约到这个问题上。这意味着它是EXPSPACE中最难的问题之一。
设语言 A ∈ EXPSPACE,由一台在 2^(n^k) 空间内运行的图灵机 M 判定。对于任意输入 w,我们需要构造两个带乘方的正则表达式 R1 和 R2,使得:
R1等价于R2当且仅当M接受w。
构造思路:
- 令
R2为生成所有字符串的正则表达式(即Σ*)。 - 构造
R1,使其生成除了M在w上的拒绝计算历史之外的所有字符串。
什么是拒绝计算历史? 它是 M 在输入 w 上,从起始格局开始,一步步运行,直到到达拒绝格局的整个格局序列。由于 M 是判定器,对于不接受 w 的情况,必然存在这样一个唯一的拒绝历史。
关键观察:
- 如果
M接受w,则不存在拒绝计算历史。此时R1将生成所有字符串(因为要避开一个不存在的字符串),所以R1 ≡ R2。 - 如果
M拒绝w,则存在一个唯一的拒绝计算历史。此时R1会生成除这个特定字符串外的所有字符串,所以R1不等于R2。
因此,测试 R1 与 R2 的等价性,就等价于测试 M 是否接受 w。
如何构造 R1?
R1 被构造为所有“坏”字符串的并集,即那些不是合法拒绝计算历史的字符串。它分为三部分:
- 坏起始:描述所有不以正确的起始格局开始的字符串。
- 坏转移:描述所有在某个相邻格局间违反
M转移规则的字符串(通过检查非法的2x3邻域)。 - 坏拒绝:描述所有不包含拒绝状态的字符串(即没有正确结束的字符串)。
如果字符串是那个唯一的拒绝计算历史,它必须同时满足:起始正确、每一步转移正确、最终以拒绝结束。因此,它不会被 R1 的任何一部分描述。而任何其他字符串,至少会违反其中一条,从而被 R1 捕获。
在构造中,我们巧妙地使用了乘方操作和填充(使所有格局长度相同)来在多项式时间内写出 R1,尽管它要描述的“坏字符串”集合和那个唯一的“好字符串”(拒绝历史)本身是双指数级长度的。这是整个归约的核心技巧。
通过这个归约,我们证明了任何EXPSPACE问题都能转化为带乘方的正则表达式等价性问题,因此后者是EXPSPACE完全的。
神谕计算
现在,我们转向一个不同但相关的话题:神谕。
什么是神谕? 神谕是一个“黑盒子”,图灵机可以免费地询问某个特定语言 A 的成员资格问题。拥有神谕 A 的图灵机记作 M^A。
例如,如果拥有一个SAT(布尔可满足性问题)的神谕,那么就能瞬间解决SAT,也能通过归约快速解决任何NP问题。
我们可以定义相对于神谕的复杂度类,例如:
- P^A:拥有神谕
A时,多项式时间内可判定的语言集合。 - NP^A:拥有神谕
A时,非确定性多项式时间内可判定的语言集合。
一个有趣的发现:存在神谕 A,使得 P^A = NP^A。一个具体的例子就是 A = TQBF(PSPACE完全问题)。
- 证明思路:
NP^TQBF中的任何计算,其非确定性分支都可以询问TQBF神谕。由于TQBF是PSPACE完全的,我们可以用一台非确定性多项式空间机器来模拟这个过程:用自身的空间来计算TQBF问题的答案,而不是询问神谕。根据萨维奇定理,NPSPACE = PSPACE。而P^TQBF显然包含PSPACE(因为可以解TQBF,从而解所有PSPACE问题)。因此NP^TQBF ⊆ PSPACE ⊆ P^TQBF,两者相等。
神谕与P vs NP问题的启示
这个关于神谕的现象对解决 P vs NP 问题有深刻的启示。
我们刚刚证明“带乘方的正则表达式等价性”是棘手的方法,本质依赖于层次定理的证明,而后者是一种对角化方法。对角化证明有一个特点:如果证明过程仅依赖于“模拟”其他图灵机,那么当给所有机器都加上同一个神谕时,模拟依然成立。
这意味着:如果一个证明仅使用对角化方法证明了 P ≠ NP,那么同样的证明将能证明对于所有神谕 A,都有 P^A ≠ NP^A。
然而,我们刚刚找到了一个神谕 A = TQBF,使得 P^A = NP^A。
因此,我们得出一个关键结论:纯粹的、相对化的对角化方法不足以解决 P vs NP 问题。任何声称证明 P ≠ NP 的方法,如果其核心论证在引入神谕后依然成立(即“可相对化”),那么该方法必定有误,因为它会与 P^TQBF = NP^TQBF 这一事实矛盾。
这告诉我们,解决P vs NP可能需要更复杂、非相对化的新技巧。
总结


本节课我们一起学习了:
- 如何证明天然棘手问题:通过证明“带乘方的正则表达式等价性”问题是 EXPSPACE完全的,我们展示了一个易于描述但被证明无法在多项式时间内解决的问题。
- 神谕的概念:神谕是提供免费信息查询的黑盒子,允许我们定义相对化的复杂度类。
- 神谕的深刻含义:我们发现了存在神谕
A使得P^A = NP^A。这一事实表明,任何纯粹基于对角化(即可相对化)的证明方法,都无法用来证明P ≠ NP。这为这个著名开放问题的解决指明了某种技术上的障碍和所需新方法的方向。
022:概率计算,BPP

在本节课中,我们将学习概率计算模型,并定义相关的复杂度类 BPP。我们将通过一个关于“只读一次分支程序”等价性判定的具体例子,来理解 BPP 算法的设计思路。
概率图灵机
上一节我们介绍了时间与空间层次定理,并讨论了证明 P 与 NP 问题可能面临的困难。本节中,我们来看看一种新的计算模型:概率图灵机。
概率图灵机与非确定性图灵机类似,其计算过程可以产生多个分支。关键区别在于,我们将为每个分支赋予一个概率。为了简化,我们规定每次选择只有两个可能的分支,并且每个分支被选中的概率均为 50%。这可以理解为机器在每次需要选择时“抛一枚硬币”。
计算树中某个特定分支出现的概率,等于 1 除以 2 的“该分支上抛硬币次数”次方。机器接受输入的概率,就是所有到达接受状态的分支的概率之和。机器拒绝的概率则是 1 减去接受的概率。
错误概率与 BPP 类
对于概率图灵机试图判定的语言,其某些分支可能会给出错误答案。我们定义机器的错误概率 ε:对于语言中的任何字符串,机器拒绝的概率至多为 ε;对于不在语言中的任何字符串,机器接受的概率至多为 ε。
现在,我们可以定义复杂度类 BPP。BPP 是所有能被多项式时间概率图灵机判定的语言的集合,且该机器的错误概率至多为 1/3。这意味着:
- 对于语言中的字符串,机器至少以 2/3 的概率接受。
- 对于不在语言中的字符串,机器至少以 2/3 的概率拒绝。
定义中使用常数 1/3 看似随意,但实际上,通过“放大引理”,我们可以将任何小于 1/2 的错误概率降低到任意小的程度。方法很简单:将原始机器独立运行多次,然后根据多数结果输出答案。通过足够多次的运行,可以将正确率提升到极高。
BPP 与 NP 的对比
理解 BPP 的一种方式是与 NP 对比:
- 在 NP 中,对于语言中的字符串,只需存在至少一条接受路径;对于不在语言中的字符串,则所有路径都必须拒绝。
- 在 BPP 中,对于语言中的字符串,绝大多数路径必须接受;对于不在语言中的字符串,绝大多数路径必须拒绝。BPP 要求计算结果有明显的倾向性(远离 50%),这样才能通过多次运行进行放大。
分支程序与等价性问题
为了具体说明 BPP 算法,我们引入“分支程序”这一计算模型。分支程序是一个有向无环图,包含两种节点:
- 查询节点:标有变量名(如 x1),有两个出边,分别标记为 0 和 1。
- 输出节点:标有输出值 0 或 1。
其中一个节点被指定为起始节点。
给定一组对变量的赋值(输入),从起始节点开始,根据当前查询节点的变量值选择相应的出边,直至到达某个输出节点,该节点的值即为计算结果。
两个分支程序是等价的,当且仅当它们对所有可能的输入赋值都给出相同的输出。分支程序的等价性判定问题是 co-NP 完全的,因此不太可能存在于 BPP 中(否则将导致 NP ⊆ BPP,这是一个未被相信的结论)。
只读一次分支程序
我们考虑一个受限版本:“只读一次”分支程序。在这种程序中,任何计算路径上,每个变量最多被查询一次。虽然任何布尔函数都可以用(可能很大的)只读一次分支程序表示,但将通用分支程序转化为等价的只读一次形式可能需要指数级增长。
有趣的是,只读一次分支程序的等价性判定问题是可以在 BPP 内解决的。我们接下来概述这个算法背后的核心思想。
算法思路与算术化
一个朴素的想法是:随机生成许多输入赋值,运行两个分支程序,看输出是否总是一致。如果不一致,则可立即断定它们不等价。但如果它们几乎处处相等,仅在一个输入上不同,那么随机采样发现这个差异的概率极低,需要指数次尝试。
我们需要一个更聪明的方法。核心思想是“算术化”:将分支程序的布尔逻辑计算,转化为在更大域(如实数或某个有限域)上的多项式计算。
首先,我们为分支程序的每个节点和边关联一个“执行值”:如果计算路径经过它,则值为1;否则为0。可以归纳地定义这些值:
- 起始节点的执行值为 1。
- 从执行值为
a的查询节点(变量为xi)出发,其标记为1的出边的执行值为 a ∧ xi,标记为0的出边的执行值为 a ∧ ¬xi。 - 一个节点的执行值是其所有入边执行值的 或。
由于分支程序是无环的,任何节点最多只有一个入边的执行值可能为 1,因此“或”操作可以简单地替换为“加和”。
现在进行算术化:用算术运算模拟布尔运算。
- 与 操作
a ∧ b模拟为乘法:a * b。 - 非 操作
¬a模拟为:1 - a。 - 或 操作
a ∨ b在一般情况下可模拟为:a + b - a*b。但在我们的分支程序场景中,由于至多一个入边为 1,“或”可直接模拟为加法:a + b。
应用这些规则,我们可以为任何分支程序定义一个多项式 P(x1, x2, ..., xn)。关键性质是:当变量 xi 被赋予布尔值(0 或 1)时,多项式 P 的值与原始分支程序的输出完全相同。
扩展到非布尔赋值
算术化的强大之处在于,我们现在可以将非布尔值(如实数)代入变量 xi,并计算多项式 P 的值。对于两个只读一次分支程序,它们分别对应多项式 P1 和 P2。
算法思路如下:
- 随机选择变量
x1, ..., xn的一组非布尔赋值(例如,从某个足够大的有限域中随机选取)。 - 分别计算
P1和P2在这组赋值下的值。 - 如果
P1 ≠ P2,则两个分支程序一定不等价(因为如果等价,则对所有布尔赋值结果相同,从而推导出它们的多项式在形式上完全一致,对任何赋值结果都相同)。 - 如果
P1 = P2,则我们推测两个分支程序是等价的。
这个算法的正确性依赖于一个关键事实:如果两个不同的多项式(来自只读一次分支程序)在随机选取的点上取值相等的概率非常低(由 Schwartz-Zippel 引理保证)。因此,如果它们等价,算法总是接受;如果它们不等价,算法以极低的概率错误接受。通过多次独立运行,可以将错误概率降至任意小。




本节课中我们一起学习了概率计算模型和 BPP 类的定义,并通过只读一次分支程序等价性判定问题,初步了解了设计 BPP 算法的核心技巧——算术化。下一节,我们将完成这个算法的正确性证明。
023:概率计算(续)🎲

在本节课中,我们将继续学习概率计算,并完成关于“一次读取分支程序等价性判定”的BPP算法证明。我们将回顾算术化的方法,并利用多项式根的性质来分析算法的正确性。
回顾:概率图灵机与BPP类
上一节我们介绍了概率图灵机和BPP类的定义。本节中,我们来看看如何利用这些概念解决一个具体问题。
概率图灵机在计算步骤中可以“抛硬币”进行随机选择。机器接受输入的概率是所有接受分支的概率之和。BPP类包含那些存在多项式时间概率图灵机可以判定的语言,且该机器的错误概率被有界地远离1/2(例如,错误概率 ≤ 1/3)。
一个关键引理是错误概率放大引理:通过多次独立运行算法并取多数结果,可以将错误概率降至任意小。
问题:一次读取分支程序的等价性判定
我们关注的问题是:给定两个一次读取分支程序,判断它们是否计算相同的布尔函数。对于一般的分支程序,此问题是coNP完全的。但对于一次读取分支程序,我们可以在BPP类内解决它。
以下是核心思路:
- 如果只是随机选取布尔赋值(0/1)来测试,若两个程序仅在一个输入上不同,则发现差异的概率极低。
- 因此,我们扩展输入域,使用算术化方法让分支程序在非布尔值(如整数)上运行。
- 我们将证明,如果两个程序不等价,那么它们在绝大多数非布尔赋值上也会输出不同的值。通过随机选取一个非布尔赋值进行测试,我们就能以高概率得到正确答案。
算术化方法
为了在非布尔值上运行分支程序,我们需要一种将布尔逻辑运算(AND, OR, NOT)用算术运算(+, ×)模拟的方法。
定义以下转换,其中真值1对应布尔True,0对应False:
- 逻辑与 (AND) 模拟为乘法:
A AND B→A × B - 逻辑非 (NOT) 模拟为:
NOT A→1 - A - 逻辑或 (OR) 模拟为:
A OR B→A + B - A×B
对于一次读取分支程序,由于其无环且每个变量在每条路径上最多被查询一次,从节点汇聚的“或”运算可以简化为求和,因为至多有一条入边可能被激活。
从路径执行到代数标记
考虑一个分支程序。传统执行方式是沿着输入赋值决定的路径走。另一种等价的视角是标记:
- 将路径上的所有节点和边标记为
1。 - 将不在路径上的所有节点和边标记为
0。 - 输出节点的标记值就是输出。
我们可以用递归规则定义这个标记,而无需显式追踪路径:
- 边标记规则:从标记为
a的查询节点(查询变量x_i)出发:- 标记为
1的边:a × x_i - 标记为
0的边:a × (1 - x_i)
- 标记为
- 节点标记规则:节点的标记是其所有入边标记的和。
在布尔赋值下,这个标记系统与路径执行完全一致。其优势在于,标记规则中的运算(+, ×, -)在非布尔值上也有定义,从而自然地将计算扩展到了更广的域上。
核心代数事实:多项式根的数量限制
算法的分析依赖于关于多项式的两个基本事实。
事实一:单变量多项式
一个非零的 d 次单变量多项式,在其系数所属的域中,最多有 d 个根。
推论:多项式的一致性
如果两个不同的 d 次多项式 P1 和 P2 在域中超过 d 个点上取值相同,那么它们的差 P1 - P2 就是一个有超过 d 个根的非零 d 次多项式,这与事实一矛盾。因此,两个不同的 d 次多项式在域中最多在 d 个点上取值相同。
事实二:多变量多项式(Schwartz-Zippel引理)
设 P(x1, ..., xm) 是一个 m 元非零多项式,每个变量 xi 的次数最多为 d。如果从大小为 q 的有限域中随机均匀地选取赋值 (a1, ..., am),那么 P(a1, ..., am) = 0 的概率最多为 (m * d) / q。
分支程序的输出多项式
当我们对一次读取分支程序进行算术化,并将输入变量视为符号时,程序的输出可以表示为一个多项式 P(x1, ..., xm)。
这个多项式具有特殊形式:它是许多项的和,每一项是某些 xi 和 (1 - xi) 的乘积。由于程序是“一次读取”的,每个变量在每个项中至多出现一次(要么是 xi,要么是 (1 - xi)),因此每个变量在每个项中的次数最多为1。
关键观察:在布尔赋值(xi ∈ {0, 1})下,这样的一个项只有在所有因子都为1时才等于1,这对应一个使原布尔函数输出1的特定赋值。因此,整个多项式 P 在布尔域上的取值,正好列出了使原分支程序输出1的所有输入赋值。也就是说,多项式 P 编码了分支程序所计算的布尔函数的真值表。
等价性判定算法与分析
基于以上准备,我们给出判定两个一次读取分支程序 B1 和 B2 是否等价的BPP算法:
- 参数设置:设变量个数为
m。选取一个素数q > 3m。所有运算将在模q的有限域F_q上进行。 - 随机赋值:从域
F_q中均匀随机地选取赋值(a1, ..., am)给变量(x1, ..., xm)。 - 算术化求值:使用算术化规则,分别在赋值
(a1, ..., am)上计算B1和B2的输出值v1和v2。 - 判断:若
v1 = v2,则接受(判定为等价);否则拒绝(判定为不等价)。
现在分析该算法的正确性:
-
情况一:
B1与B2等价。
由于它们计算相同的布尔函数,它们的输出多项式P1和P2在所有的布尔赋值上取值相同。而P1和P2都是前述特殊形式的多项式。可以论证,在这种情况下P1和P2是完全相同的多项式。因此,对于任何赋值(包括我们随机选取的非布尔赋值),P1和P2的输出都必然相等。算法总是接受,错误概率为0。 -
情况二:
B1与B2不等价。
则P1和P2是不同的多项式。每个变量在P1和P2中的次数最多为1。根据Schwartz-Zippel引理,对于随机赋值,P1与P2输出值相等的概率最多为:
(变量个数 m * 次数上界 1) / 域大小 q < m / (3m) = 1/3
因此,算法以至少2/3的概率拒绝(得到正确答案)。
综上所述,该算法以大于 2/3 的正确概率判定一次读取分支程序的等价性,属于BPP类。
总结
本节课中,我们一起学习了:
- 回顾了BPP类和概率计算的基本概念。
- 引入了算术化技术,将逻辑运算转化为算术运算,从而将分支程序的计算扩展到非布尔域。
- 利用了多项式根的性质(Schwartz-Zippel引理),分析了随机测试在扩展域上的有效性。
- 完成了一个巧妙的证明:展示了一次读取分支程序等价性判定问题属于BPP类。该证明的核心在于,通过算术化,将程序等价性问题转化为多项式恒等性问题,并利用随机采样来检测多项式是否相同。


这个结果不仅本身有趣,其使用的算术化方法也是后续学习交互式证明系统等高级主题的重要基础。
024:交互式证明系统,IP

在本节课中,我们将要学习交互式证明系统(Interactive Proof Systems)及其对应的复杂性类 IP。这是一个结合了概率计算和交互通信的模型,可以看作是 NP 概念的概率版本。我们将通过图非同构问题的例子来理解这个模型,并探讨 IP 与 NP、BPP、PSPACE 等复杂性类之间的关系。
图同构问题与 NP
上一节我们介绍了交互式证明系统的概念。本节中,我们来看看一个具体的例子:图同构问题。
图同构问题(ISO)是指判断两个图是否同构。两个图同构意味着它们本质上是同一个图,只是节点的标签或排列顺序不同。判断两个图是否同构的问题属于 NP 类,因为我们可以提供一个同构映射作为证书,验证者可以在多项式时间内检查这个映射是否正确。
然而,判断两个图是否不同构(即非 ISO 问题)是否也属于 NP 类,目前尚不清楚。也就是说,我们可能无法提供一个简短的证书来证明两个图不同构。
交互式证明模型
尽管非 ISO 问题可能不属于 NP,但我们可以通过交互式证明系统,让一个拥有无限计算能力的证明者(Prover)说服一个只有多项式时间计算能力的验证者(Verifier)相信两个图确实不同构。
以下是交互式证明系统的基本模型:
- 验证者(Verifier):计算能力有限,只能在多项式时间内运行,并且可以是概率性的(即可以使用随机数)。
- 证明者(Prover):计算能力无限,可以解决任何计算问题。
- 交互过程:双方可以交换多项式数量的信息。
- 目标:对于属于某个语言的输入字符串,存在一个诚实的证明者能以高概率说服验证者接受。对于不属于该语言的输入字符串,任何(即使是恶意的)证明者都只能以低概率让验证者接受。
图非同构的交互式证明协议
现在,我们来看一个具体的协议,它能让证明者说服验证者两个图 G 和 H 是不同构的。
协议的核心思想是,验证者通过随机挑战来测试证明者是否真的能区分两个图。
以下是协议步骤:
- 验证者随机选择图 G 或图 H(例如,抛硬币决定)。
- 验证者随机打乱所选图的节点顺序,得到一个新图 K,然后将 K 发送给证明者。
- 验证者询问证明者:“K 是由 G 还是由 H 打乱得到的?”
- 证明者利用其无限的计算能力,检查 K 与 G 和 H 哪个同构,并给出答案(“G”或“H”)。
- 验证者检查证明者的答案是否正确。
- 重复上述步骤多次(例如,100次)。
协议分析:
- 如果 G 和 H 确实不同构,那么 K 只可能与 G 或 H 中的一个同构。诚实的证明者每次都能给出正确答案,因此验证者最终会以概率1接受。
- 如果 G 和 H 实际上同构,那么 K 既可能与 G 同构,也可能与 H 同构。证明者无法区分,最多只能随机猜测。假设重复 n 次,证明者猜对所有 n 次的概率仅为 (1/2)^n,这是一个极低的概率。因此,任何证明者都无法以高概率欺骗验证者接受。
通过这个协议,我们展示了非 ISO 问题属于 IP 类。
IP 与其他复杂性类的关系
了解了 IP 的基本定义和例子后,我们来看看它与其他复杂性类的关系。
以下是几个重要的包含关系:
- NP ⊆ IP:任何 NP 问题都可以转化为一个交互式证明,其中证明者直接发送证书,验证者确定性验证。
- BPP ⊆ IP:BPP 类中的问题可以由概率多项式时间的验证者自行解决,无需与证明者交互(或让证明者保持沉默)。
- IP ⊆ PSPACE:任何交互式证明系统都可以在多项式空间内通过遍历所有可能的交互历史和随机选择来模拟。
- PSPACE ⊆ IP:这是一个非常重要的结果(IP = PSPACE),表明 IP 类的能力非常强大,包含了所有多项式空间可解的问题。我们将在后续课程中证明一个稍弱但核心思想相同的结果:coNP ⊆ IP。
迈向 coNP ⊆ IP:#SAT 问题
为了证明 coNP ⊆ IP,我们将聚焦于一个 coNP 难的问题:#SAT 问题(或称 Number SAT)。
#SAT 问题的定义如下:
给定一个布尔公式 φ 和一个数字 k,判断公式 φ 的满足赋值(satisfying assignments)的确切数量是否等于 k。我们用 #φ 表示公式 φ 的满足赋值数量。
#SAT 是 coNP 难的,因为 coNP 完全问题(如公式不可满足性)可以多项式时间归约到它:一个公式 φ 不可满足当且仅当 #φ = 0。
因此,如果我们能证明 #SAT ∈ IP,就意味着 coNP ⊆ IP。
一个低效但直观的交互协议思路
我们首先描述一个直观但计算上不可行的协议思路,以理解证明的核心挑战。
假设公式 φ 有 m 个变量 x₁, …, x_m。协议过程如下:
- 证明者声称 #φ = k(与输入一致)。
- 为了证明这个声称,证明者进一步声称当 x₁ = 0 时的满足赋值数 A₀ 和当 x₁ = 1 时的满足赋值数 A₁,并且满足 A₀ + A₁ = k。
- 验证者检查 A₀ + A₁ 是否等于 k。
- 接着,证明者对 A₀ 和 A₁ 分别进行同样的展开(例如,对于 A₀,进一步声称 x₁=0, x₂=0 和 x₁=0, x₂=1 时的数量),并逐层递进。
- 最终,在最后一层(预设了所有 m 个变量的值),证明者给出了 2^m 个值,每个值(0或1)表示对应完全赋值是否满足公式。
- 验证者做两件事:
- 检查每一层中,兄弟节点的值之和是否等于父节点的值。
- 在最后一层,直接计算每个完全赋值是否满足 φ,并与证明者提供的值比对。
问题:
这个协议需要证明者在最后一层发送 2^m 个值,这是指数级的,违反了多项式时间交互的要求。因此,这不是一个有效的 IP 协议。
关键洞察:
这个思路的缺陷在于“分支爆炸”。我们需要一种方法,使得验证者只需检查一个或少数几个子节点,就能高置信度地推断父节点的正确性,同时又能防止恶意证明者通过精心构造的单一错误路径进行欺骗。下一节课,我们将通过引入“算术化”技术,在更大的域(而非仅布尔值)上进行计算,来解决这个问题,从而构造出一个真正高效的协议。
总结
本节课中我们一起学习了:
- 交互式证明系统(IP) 的基本模型,包括能力有限的概率验证者和能力无限的证明者。
- 通过图非同构问题,我们看到了一个具体的 IP 协议,它解决了可能不属于 NP 的问题。
- 探讨了 IP 与 NP、BPP、PSPACE 等复杂性类之间的关系,特别是 IP = PSPACE 这一深刻结论。
- 为了证明 coNP ⊆ IP,我们引入了 #SAT 问题,并分析了一个直观但低效的协议思路,指出了其中的核心困难在于避免指数级信息交换。


下一节课,我们将完成 #SAT ∈ IP 的证明,从而最终建立 coNP ⊆ IP 这一重要结果。
025:coNP是IP的子集 👨🏫


在本节课中,我们将要学习交互式证明系统(IP)的最后一个重要结论:coNP是IP的子集。我们将通过分析一个具体问题——#SAT(计数可满足性问题)——来展示这一点。首先,我们会回顾交互式证明系统的定义和基本设置,然后介绍一个指数级的、有缺陷的验证协议。接着,我们将通过算术化技术,将这个指数级协议改进为一个多项式级的、有效的交互式证明协议。本节课的核心在于理解如何利用算术化和随机性来高效地验证一个公式的不可满足性(即属于coNP的问题)。
交互式证明系统回顾 🔄
上一节我们介绍了交互式证明系统的基本概念。本节中我们来看看其正式定义和关键思想。
交互式证明系统涉及两个参与方:
- 证明者(Prover):拥有无限的计算能力,目标是说服验证者接受某个陈述。
- 验证者(Verifier):计算能力受限(通常是多项式时间),负责与证明者交互并最终决定是否接受输入。
两者都看到输入,并交换多项式数量的消息。最终,验证者以一定的概率接受或拒绝输入。对于一个语言L,要求:
- 完备性:如果输入x在L中,那么存在一个诚实的证明者,能使验证者以高概率(例如 ≥ 2/3)接受。
- 可靠性:如果输入x不在L中,那么对于任何(即使是恶意的)证明者,验证者都只能以低概率(例如 ≤ 1/3)接受。
这个概率间隙允许我们使用概率放大引理,使得接受概率在“是”实例中趋近于1,在“否”实例中趋近于0。
一个令人惊奇的定理是 IP = PSPACE。本节课我们将证明一个稍弱但核心思想相同的结论:coNP ⊆ IP。
从#SAT问题入手 🔢
为了证明coNP ⊆ IP,我们聚焦于一个coNP难的问题:#SAT(计数可满足性问题)。
#SAT问题的定义:
- 输入:一个布尔公式φ(在变量x₁, ..., xₘ上)和一个数字k。
- 问题:判断公式φ的可满足赋值的数量是否恰好等于k。
特别地,如果φ是不可满足的,那么它的可满足赋值数就是0。因此,将不可满足性问题归约到#SAT是容易的,而不可满足性问题是coNP完全的。所以,如果我们能证明#SAT ∈ IP,就能推出coNP ⊆ IP。
预设变量与计数恒等式 📝
在深入协议之前,我们需要建立一些符号和关键恒等式。
给定公式φ,我们可以预设其前i个变量的值(设为a₁, ..., aᵢ,每个aⱼ ∈ {0,1})。记作:
- φ|a₁...aᵢ:将x₁, ..., xᵢ分别设为a₁, ..., aᵢ后得到的新公式。
- #φ|a₁...aᵢ:新公式φ|a₁...aᵢ的可满足赋值数量(即对剩余m-i个变量的所有2^(m-i)种赋值进行计数)。
基于此,我们有两个核心计数恒等式:
- 加法恒等式:对于i < m,有
#φ|a₁...aᵢ = #φ|a₁...aᵢ0 + #φ|a₁...aᵢ1。这表示,在预设前i位后,总可满足数等于将下一位设为0和设为1两种情况的可满足数之和。 - 终结恒等式:当所有变量都被预设(i = m)时,
#φ|a₁...aₘ的值要么是0(该赋值不满足φ),要么是1(该赋值满足φ)。即#φ|a₁...aₘ = φ(a₁, ..., aₘ)。
一个指数级的朴素协议(及其缺陷) 🐌
基于上述恒等式,我们可以构思一个直观的交互协议:
协议流程(指数级):
- 证明者发送声称的总可满足赋值数
#φ。 - 验证者检查收到的值是否等于输入中的k。若不等于,则拒绝。
- 为了证明
#φ正确,证明者必须证明它等于#φ|0 + #φ|1。因此,证明者发送这两个数。 - 验证者检查
#φ是否等于收到的两个数之和。若不等于,则拒绝。 - 验证者现在需要确信
#φ|0和#φ|1的正确性。协议递归进行:为了证明#φ|a₁,证明者需要发送#φ|a₁0和#φ|a₁1,验证者检查它们的和,如此往复。 - 最终,在递归了m层之后,证明者需要为所有2^m种完整的变量赋值(即
φ|a₁...aₘ对于所有a₁...aₘ)发送一个值(0或1)。 - 验证者最后检查:对于每一种完整赋值,收到的值(0或1)是否等于直接计算
φ(a₁, ..., aₘ)得到的结果(也是0或1)。同时,它也要检查最后一层的加法恒等式是否成立。
协议分析:
- 如果输入正确(k = #φ)且证明者诚实:验证者所有检查都会通过,最终以概率1接受。
- 如果输入错误(k ≠ #φ):诚实的证明者会发送正确的
#φ,导致第一步检查失败,验证者拒绝。那么,一个恶意的证明者如果想欺骗验证者接受,就必须在第一步说谎,发送一个错误的#φ'(令#φ' = k)。然而,根据加法恒等式,一个错误的上层值必然导致至少一个下层值也是错误的(因为两个正确的下层值之和不可能等于一个错误的上层值)。这个“谎言”会沿着递归树向下传播,直到最后层。验证者最终会在检查某个终结值(0或1)或某层加法时发现不一致,从而拒绝。 - 致命缺陷:这个协议中,证明者在每一层都需要发送指数级数量(2^(m-i))的值。整个协议的消息长度是指数级的,违反了交互式证明系统对多项式时间验证者的要求(验证者必须能在多项式时间内处理消息)。
因此,我们需要一个更高效的协议。
算术化:从布尔值到多项式 🧮
上一节我们看到了朴素协议的指数级缺陷。本节中我们来看看如何通过算术化技术来克服它。
算术化的目标是将布尔公式φ转换成一个多项式 p_φ,使得对于任何布尔赋值(变量取0或1),多项式的值等于原布尔公式的值(0或1)。转换规则如下:
- 布尔变量 x:映射为多项式变量
x。 - 逻辑非 (¬x):映射为
(1 - x)。 - 逻辑与 (x ∧ y):映射为
x * y。 - 逻辑或 (x ∨ y):映射为
x + y - x*y。
通过递归应用这些规则,任何布尔公式φ都可以被算术化为一个多元多项式 p_φ(x₁, ..., xₘ)。关键性质是:对于所有 (a₁, ..., aₘ) ∈ {0,1}^m,有 p_φ(a₁, ..., aₘ) = φ(a₁, ..., aₘ)。此外,p_φ 的次数最多是公式φ的长度。
现在,我们扩展“可满足赋值计数”的概念。对于预设值 a₁, ..., aᵢ(现在允许 aⱼ 取自一个足够大的有限域 F,而不仅仅是{0,1}),我们定义:
- #φ|a₁...aᵢ = Σ_{(bᵢ₊₁, ..., bₘ) ∈ {0,1}^(m-i)} p_φ(a₁, ..., aᵢ, bᵢ₊₁, ..., bₘ)
注意,即使预设值 aⱼ 不是0或1,我们仍然只对剩余变量进行布尔赋值(0或1)并求和。当所有预设值 aⱼ 都是布尔值时,这个定义与原始的计数定义一致。我们之前的两条计数恒等式在这个扩展定义下依然成立。
多项式级IP协议:核心思想 🚀
算术化如何帮助我们?关键在于一个深刻的观察:对于固定的 a₁, ..., aᵢ,将 #φ|a₁...aᵢ 视为第 i+1 个预设值(记作变量 z)的函数时,它是一个单变量多项式 hᵢ(z)!这是因为求和是在剩余变量上进行的,而 p_φ 本身是多项式。
核心协议思想(多项式级):
- 证明者不再像指数协议那样,为下一层所有可能的布尔预设发送两个数字(如
#φ|...0和#φ|...1),而是发送整个多项式hᵢ(z)(通过发送其系数)。 - 验证者收到这个多项式
hᵢ(z)后,可以做两件事:- 检查加法恒等式:计算
hᵢ(0) + hᵢ(1),并验证其是否等于上一轮声称的值。 - 随机抽查:为了相信
hᵢ(z)是正确的多项式(而不是证明者伪造的),验证者随机从域F中选取一个点r,然后要求证明者证明hᵢ(r)的值是正确的。
- 检查加法恒等式:计算
- 如何证明
hᵢ(r)正确呢?这恰好变成了一个形式相同但“深度”增加了1的子问题:我们需要验证#φ|a₁...aᵢ, r。于是,协议可以递归地进行。 - 递归到最后,当所有变量都被预设时(即需要验证
#φ|a₁...aₘ),验证者可以直接计算p_φ(a₁, ..., aₘ)来检查证明者声称的值是否正确。
为什么随机抽查有效?
如果证明者是诚实的,他发送的就是正确的多项式 hᵢ(z),那么无论验证者选哪个点 r,检查都会通过。
如果证明者是恶意的,他发送了一个错误的多项式 hᵢ'(z)。由于两个不同的低次多项式在域 F 中相同的点很少(至多 deg 个),而 F 很大(我们选择其大小远大于多项式次数),因此验证者随机选择的 r 恰好撞上这两个多项式值相等的概率极低。如果 hᵢ'(r) ≠ hᵢ(r),那么在后续递归验证 hᵢ'(r) 的过程中,这个谎言最终会被发现(因为最后一层验证者可以独立计算)。
完整的多项式级IP协议 📜
以下是#SAT问题的多项式级交互式证明协议详细步骤:
协议步骤:
- 第0轮:
- 证明者P发送数值
C₀ = #φ(声称的总可满足数)。 - 验证者V检查
C₀ == k。若不成立,则拒绝。
- 证明者P发送数值
- 第i轮 (i = 1 到 m):
- P发送一个单变量多项式
gᵢ(z),并声称gᵢ(z) = #φ|r₁, r₂, ..., r_{i-1}, z,其中r₁, ..., r_{i-1}是前几轮V选择的随机数。 - V进行两项检查:
- 和检查:验证
gᵢ(0) + gᵢ(1) == C_{i-1}。这里C_{i-1}是上一轮确定要验证的值(初始C₀,后续为g_{i-1}(r_{i-1}))。 - 若检查失败,则拒绝。
- 和检查:验证
- V从域
F中随机选取rᵢ。 - V计算
Cᵢ = gᵢ(rᵢ),作为下一轮需要验证的值。
- P发送一个单变量多项式
- 最终轮 (i = m+1):
- 此时,所有m个变量都已被预设值
(r₁, ..., rₘ)指定。 - V独立计算
value = p_φ(r₁, ..., rₘ)(使用算术化公式直接计算多项式值)。 - V检查
value == Cₘ(即最后一轮证明者声称的值)。 - 若相等,则接受;否则拒绝。
- 此时,所有m个变量都已被预设值
协议分析:
- 完备性:如果
k = #φ且证明者诚实(始终发送正确的多项式),那么所有检查都会通过,验证者以概率1接受。 - 可靠性:如果
k ≠ #φ,那么任何证明者要想让V接受,必须在第一轮说谎C₀' = k。为了通过第一轮的和检查,他必须发送一个错误的多项式g₁'(z)。根据Schwartz-Zippel引理,V随机选择的r₁使得g₁'(r₁) = g₁(r₁)(正确值)的概率至多为d/|F|(d是多项式次数)。如果侥幸通过,谎言延续到下一轮。最终,证明者需要在整个链条上都侥幸逃过随机检查,其总概率上界约为m * d / |F|。通过选择足够大的域F,我们可以使这个错误概率小于1/3。 - 效率:证明者每轮发送一个低次多项式(系数个数为多项式级)。验证者每轮只进行多项式次数的计算(求值、加法)和一个随机选取。因此,验证者在多项式时间内运行。
由于我们为#SAT问题构造了一个多项式轮的交互式证明协议,因此 #SAT ∈ IP。又因为#SAT是coNP难的,所以 coNP ⊆ IP。
总结 🎓


本节课中我们一起学习了如何证明 coNP是IP的子集 这一重要结论。我们首先定义了#SAT问题,并展示了其与coNP的联系。然后,我们构思了一个基于计数恒等式的指数级验证协议,并指出了其效率缺陷。接着,我们引入了算术化技术,将布尔公式转化为多项式,从而将“计数”概念扩展到有限域上。利用“扩展的计数函数是低次多项式”这一关键性质,我们将指数级协议改进为多项式级的交互式证明协议。该协议的核心是证明者发送整个多项式,而验证者通过随机抽查一点的值来高效地检验整个多项式的正确性。最终,我们严格描述了协议步骤,并分析了其完备性和可靠性。这个协议精巧地结合了代数、概率和计算复杂性理论的思想,是理解IP = PSPACE定理的重要阶梯。

浙公网安备 33010602011771号