MIT-6-045-自动机-可计算与复杂性笔记-全-
MIT 6.045 自动机、可计算与复杂性笔记(全)
001:课程介绍与概述
在本节课中,我们将学习MIT 6.045课程“自动机、可计算性与复杂度”的总体介绍。我们将了解课程目标、结构、核心主题,并通过一个在线赌博的案例,初步探索计算理论在现实世界中的应用。
课程概述与结构
欢迎来到6.045课程,即“自动机、可计算性与复杂度”。这门课程也被称为“理论计算机科学中的伟大思想”。我是Scott Aaronson,这是我第七次讲授这门课程。
我们有三名助教:Adam Eidia、Saed Meribon和Kevin Wu。课程网站上有完整的教学大纲。
这门课程今年的注册人数创下了纪录。这可能源于大家对可计算性理论的求知欲,也可能是因为电影《模仿游戏》的影响。无论如何,这门课现在可以作为一门核心课程来选修。
我们为这门课程建立了一个Piazza问答网站。任何关于讲座内容不清楚的地方、作业的澄清问题(不是直接索要答案),都可以在上面提问。问题可以由助教、我或其他同学回答。这是一个极好的资源,我鼓励大家使用它。
在课堂上,请随时打断我进行提问。虽然这个讲堂有点令人生畏,但既然大家早上9:30来到这里,我希望提供一些额外的价值。互动就是价值之一。不过请注意,如果我被一个有趣的问题带偏,可能会花上10分钟深入探讨。
教材与资源
以下是本课程的主要教材和资源。
- 主要教材:Michael Sipser所著的《计算理论导论》。Sipser现在是这里的理学院院长。这本书涵盖了本课程前60%左右的内容,讲解非常直观。对于它所涵盖的基础知识,做得非常出色。
- 补充书籍:课程后半部分的内容,有几本书可供参考。我写的《Quantum Computing Since Democritus》涵盖了部分内容。还有Moran和Mers的书,以及Arora和Barak的书。这些都是可选读物。
- 课程笔记:我们在Stellar网站上提供了2008年首次开设此课程时的课堂笔记。它们并非完美,可能存在一些错误,但仍然是重要的学习资源。
课程要求与评分
以下是关于作业、考试和评分标准的详细信息。
- 作业:本课程将有六次作业。每次作业通常有两周时间完成。具体的截止日期将在本周确定并公布在Stellar网站上。我们鼓励组成学习小组、合作解题,但要求独立撰写最终答案,并列出所有合作者的姓名。作业需要提交纸质版。
- 考试:将有一次期中考试和一次期末考试。期中考试日期待定,期末考试在期末考试周进行。期中考试占总成绩的25%,期末考试占35%,作业占40%。
- 课堂参与:课堂参与是评分的一小部分。积极参与课堂讨论、参加复习课、在Piazza上提问、参加答疑时间等,都会在最终成绩处于边界时起到作用。
我的答疑时间是周二上午11点到12点,就在讲座之后。你也可以通过邮件预约其他时间。我的办公室在32号楼。助教的答疑时间将另行安排,以方便尽可能多的同学。
复习课在周五进行。我们将安排三个复习时间段供大家选择。复习课非常重要,因为我的讲课风格偏向于阐述大思想、历史和意义。复习课则会专注于讲解更多例题和解决作业中类似问题的方法。
课程的意义与目标
你可能会问,为什么要学习这门课程?许多计算机科学课程教你的是在现实工业中有用的技能,但这门课不是其中之一。你可能会偶然学到一些有用的东西,但这并非本意。
这门课程旨在展示计算机科学为何配得上“科学”之名。我们试图展示这个领域的知识深度、历史根源以及未来的可能方向。这门课将通过展示不可判定问题、哥德尔定理、密码学、P与NP问题、量子计算等,来拓展你的思维。
未来,当你听到密码学或物理与计算等领域的新进展时,这门课程将为你提供理解它们的知识背景。好消息是,我们在这里教授的内容不会很快过时。
Edsger Dijkstra有一句名言:“计算机科学并不比天文学更关于望远镜。”他的意思是,计算机科学是一套工具,通常是数学工具,可以用来理解任何受规则支配的系统,无论是细胞、大脑、物理定律、经济市场,还是计算机。
我个人是因为想理解电子游戏的工作原理而进入计算机科学领域的。从某种意义上说,创建电子游戏就像是在表达数学。代码不仅仅是游戏的总结,它们就是游戏本身,改变它们,游戏就会做不同的事情。这门课程的一部分目标,就是重新唤醒对这些思想最初被发现时是多么令人惊讶的认识。
物理学试图从现象出发,向下寻找更好的理论来解释一切。计算机科学在某种意义上则相反:我们从一组规则出发(这些规则可以受物理学启发,但不必是),然后向上构建,探索通过组合这些规则能构建什么、能产生什么行为,以及不能产生什么行为,并尝试从数学上理解这些。
核心案例:在线赌博问题
为了让大家对本课程将要探讨的内容有一个初步印象,我们来看一个具体案例:如何建立一个在线赌博网站。
假设你已经解决了所有法律问题,在开曼群岛设立了服务器,想要运营一个在线轮盘赌游戏。玩家可以押注红色或黑色,猜对了赢钱,猜错了输钱。
这里存在一个明显的困难:由于互联网消息是依次发送的,总有一方要先说话。如果赌徒先下注,网站完全可以总是宣布相反的结果,让赌徒永远输钱。赌徒很快就会发现不对劲并停止使用网站。
对于一次性的高额赌注,赌徒希望有某种保证,确保网站在其下注前就已经决定了轮盘的结果。在实体赌场,你可以在球还在转动时下注,但这在线上行不通。
那么,我们该如何解决这个问题呢?我们需要一种“承诺”机制,就像把赌注封存在信封或保险箱里一样:赌徒先做出决定并“锁定”它,但暂不向赌场透露;然后赌场公布结果;最后赌徒再“打开”承诺,证明自己的下注。关键在于,如何在互联网上实现这种“数字保险箱”。
现代的解决方案基于一个假设:某些问题是“计算上困难”的。我们这里说的不是绝对不可能解决的问题(本课程后面会讲到),而是指解决它们所需的时间可能超过宇宙的年龄,因此在实际中是不可行的。
我们需要找到那些解决时间随问题规模呈“指数级”增长的问题。线性增长是一条直线,平方增长是一条曲线,而指数增长则是一条急速攀升、几乎无法画在黑板上的曲线。
困难问题示例:因数分解
一个著名的、据信是计算困难的问题是“大整数因数分解”问题。我给你一个很大的合数,你需要将它分解为质数的乘积。
一个简单的算法是尝试所有可能的除数。如果n是表示该数字所需的二进制位数,那么可能的除数数量大约是2^n个。一个优化是只需尝试到平方根,但这样仍有大约2^(n/2)种可能,依然是指数级。
目前已知最快的经典算法是“数域筛法”,其运行时间大约是2^(n^(1/3))。虽然比穷举好,但仍然是指数级增长。正是基于“大整数因数分解是困难的”这一信念,我们当前的电子商务安全才得以建立。
现在,假设我们相信因数分解是困难的,如何用它来解决在线赌博问题呢?
赌徒可以这样做:选择两个巨大的随机质数P和Q。约定如果P或Q中至少有一个以数字3结尾,则代表押注黑色;否则代表押注红色。然后,赌徒计算N = P * Q,并将乘积N发送给赌场。此时,赌徒的赌注就像被锁在了N这个数字里。
赌场收到N后,宣布轮盘结果(红或黑)。最后,赌徒进入“解承诺”阶段,向赌场揭示P和Q。赌场验证P * Q是否等于N,并检查P和Q是否都是质数(这很重要,以防赌徒用多个质数乘积作弊,从而事后选择因子),然后根据因子是否以3结尾来判断赌注,并结算。
这里依赖于算术基本定理:每个大于1的自然数都有唯一的质因数分解(不考虑顺序)。同时,赌场不需要一个所有质数的列表,他们可以使用高效的“素数判定算法”来验证P和Q是否为质数。这正是现代密码学的核心:一个问题的某些方面(如判定是否为合数)是容易的,而其他方面(如找出具体因子)则是困难的。
需要指出的是,量子计算机可以高效解决因数分解问题(由Peter Shor发现)。如果赌场拥有量子计算机,这个方案就被破解了。不过,还有其他密码学方法可以实现在线承诺,并且据信能抵抗量子计算机的攻击。
密码学是理论概念最直接、最明显具有现实世界影响的领域之一。在密码学中,你正是试图利用问题的困难实例,并且你必须确信无论对手多么聪明,都无法高效解决它。这正是理论计算机科学的核心:探索计算的终极极限,什么能算,什么不能算。
课程路线图
以上只是一个开胃菜。要严谨地讨论这些问题,我们需要建立很多基础。比如,究竟什么是“高效”算法?如何形式化地描述我们讨论的对象?人们花了一些时间才搞清楚,而且这个定义虽然几十年来非常有效,但它后来被发现没有涵盖量子现象,导致人们一度认为因数分解是困难的,而考虑量子效应后其实不然。我们仍在探索中。
本课程大致分为三个阶段。
第一阶段,我们将学习自动机理论、形式语言、可计算性以及电路。这些都是计算模型,帮助我们习惯形式化地讨论计算,并证明在给定模型下能做什么和不能做什么。这类似于尺规作图:古希腊人痴迷于能用尺规构造什么图形,而真正有趣的是探索这个模型的终极限制——什么图形不能构造。我们将看到许多关于计算模型的“不可能性”定理。
第二阶段,我们将讨论图灵机和可计算性理论,并将其与哥德尔不完备定理联系起来。它们虽然不是同一件事,但密切相关。我们甚至可以用图灵机来证明哥德尔定理。
第三阶段,我们将进入复杂度理论。当我们引入“效率”概念,要求算法在宇宙寿命内结束时,情况就变了。这将引领我们探讨P与NP问题。我们会学习NP完全性,这是我们对P与NP问题所知的最主要成果之一。然后,我们将讨论引入随机性后计算理论的变化,如果有时间还会回到密码学,并涉及一些机器学习的内容。最后,我们会用大约四讲的时间来介绍量子计算。
总结
本节课中,我们一起学习了MIT 6.045课程的总体介绍。我们了解了课程的目标是探索计算的理论基础与极限,而不仅仅是实用技能。我们通过一个在线赌博的案例,看到了如何利用“因数分解是困难的”这一信念来构建安全的承诺协议,并引出了密码学、计算复杂性等核心概念。最后,我们预览了本课程将涵盖的三大板块:计算模型与自动机、可计算性理论以及复杂度理论。下节课,我们将从第一个计算模型——电路开始。
002:计算模型入门
在本节课中,我们将学习两种基本的计算模型:布尔逻辑电路和有限自动机。我们将探讨它们的定义、能力、局限性以及一些核心概念,如通用性和电路复杂性。
电路:组合逻辑模型
上一节我们介绍了课程的基本信息,本节中我们来看看第一个计算模型:布尔逻辑电路。电路是一种由逻辑门组成的网络,用于计算布尔函数。与电子工程中的电路不同,在理论计算机科学中,电路必须是无环的。
一个电路从给定的输入位(例如 X, Y, Z)开始,然后通过逻辑门对它们进行操作。基本的逻辑门包括:
- 非门 (NOT):输出输入位的反。
- 与门 (AND):仅当所有输入为1时输出1。
- 或门 (OR):当至少一个输入为1时输出1。
- 异或门 (XOR):当两个输入不同时输出1,相同时输出0。等价于模2加法。
通过将这些门连接起来,我们可以构建更复杂的逻辑运算。例如,要计算三个比特的多数函数(即判断是否有至少两个比特为1),我们可以构建如下电路:
( X AND Y ) OR ( Y AND Z ) OR ( X AND Z )
这个电路直接检查是否存在任意一对同时为1的比特。
通用性:一组门的力量
我们可能会问,为什么只使用这些特定的门?这引出了一个核心概念:通用性。如果仅通过组合某个门集中的门,就能表示任意一个具有任意数量输入比特的布尔函数,那么我们称这个门集是通用的。
为了理解通用性并非理所当然,我们先看一些非通用的门集例子:
- 仅包含恒等门:只能计算恒等函数。
- 仅包含非门:每个比特独立处理,无法让比特之间产生关联。
- 仅包含与门和或门:它们都是单调函数(将任何输入从0改为1,输出只会从0变为1或保持不变,绝不会从1变为0)。非门不是单调的,因此无法用与门和或门构造非门。
- 仅包含异或门和非门:它们都对应于模2的线性函数。无论怎样组合,得到的总是线性函数,而像与门这样的函数是二次的(
X AND Y对应X * Y mod 2),因此无法构造。
一个有趣的事实是,在允许免费使用常数(0和1)的前提下,单调性和线性几乎是导致一个门集不通用仅有的两种方式。换句话说,通用性是常态而非例外。
证明与门、或门、非门是通用的
现在,我们来证明集合 {AND, OR, NOT} 是通用的。我们需要展示如何用这些门表示任意一个 n 比特布尔函数 f: {0,1}^n -> {0,1}。
我们可以使用真值表构造法。对于任意函数,列出其真值表。对于输出为1的每一行输入组合,我们构造一个子电路:使用与门和非门来检查输入是否精确匹配该组合。例如,对于输入组合 (X=0, Y=1, Z=1),对应的子电路是 (NOT X) AND Y AND Z。最后,将所有这样的子电路的输出用一个(可能多层级的)或门连接起来。这个电路就精确计算了目标函数。
这种构造方法产生的电路大小(门数量)是 O(n * 2^n)。当 n 很大时,2^n 项占主导,导致电路规模呈指数级增长,这在实践中是不可行的。
更精简的通用门集
实际上,我们不需要全部三种门。我们可以证明 {AND, NOT} 已经是通用的。因为我们可以用它们来模拟或门:X OR Y = NOT( (NOT X) AND (NOT Y) )。这被称为德摩根定律。
更进一步,甚至存在单个通用门,例如与非门 (NAND)。X NAND Y = NOT(X AND Y)。我们可以用与非门构造非门:NOT X = X NAND X。然后,利用这个非门,我们可以构造与门:X AND Y = NOT(X NAND Y)。既然 {AND, NOT} 是通用的,那么 {NAND} 也是通用的。
电路复杂性与香农计数论证
一个自然的问题是:表示任意布尔函数真的需要指数级大小的电路吗?是否存在更高效的构造方法?1949年,克劳德·香农通过一个巧妙的计数论证证明,虽然我们很难给出一个具体的需要大电路的函数例子,但几乎所有的布尔函数都需要大约 2^n / n 数量级的门。
论证思路如下:
- 计数函数:具有 n 个输入比特的布尔函数总数为
2^(2^n)(因为真值表有2^n行,每行可独立选择0或1)。 - 计数小电路:大小为 S(门数量)的电路总数有一个上界,大约是
(n+S)^(2S)量级。 - 比较数量:如果每个函数都能用大小不超过 S 的电路表示,那么电路总数必须至少等于函数总数。由此推导出 S 必须满足
S log S = Ω(2^n),从而得出S = Ω(2^n / n)。
这个论证的美妙之处在于,它通过“鸽巢原理”证明了困难函数的存在性,尽管没有明确构造出任何一个。有趣的是,这个下界几乎是紧的,存在构造方法可以用大约 O(2^n / n) 个门实现任意函数。
从非均匀模型到均匀模型:有限自动机
尽管电路在理论上是通用的,但它有一个主要缺点:它是非均匀的。这意味着对于不同的输入长度 n,你需要设计完全不同的电路。我们更希望有一个均匀的计算模型:一个固定的程序能够处理任意长度的输入。
为此,我们引入可能是最简单的均匀计算模型:有限自动机 (Finite Automaton),在现代语境中也称为流算法 (Streaming Algorithm)。
有限自动机可以看作一个功能受限的计算机:
- 它从左到右(或从右到左)单次扫描输入字符串。
- 它只有有限个内部状态,用于记住关于已读前缀的“摘要”信息。
- 它没有额外的存储空间(如磁带或内存数组)。
状态的数量有限是关键限制。如果允许无限状态,那么自动机只需记住整个输入字符串,模型就变得平凡了。有限状态迫使机器必须在有限内存下总结输入。
一个有限自动机由以下部分组成:
- 一个有限状态集
S。 - 一个起始状态
s0 ∈ S。 - 一组接受状态
F ⊆ S(其余为拒绝状态)。 - 一个输入字母表
Σ(例如{0, 1})。 - 一个转移函数
δ: S × Σ -> S,定义了在当前状态和读入符号下,应转移到哪个新状态。
有限自动机示例
让我们构建一个简单的有限自动机,其功能是检查输入字符串中是否包含至少一个‘1’。
- 状态集:
{A, B} - 起始状态:
A - 接受状态:
B(状态A为拒绝状态) - 字母表:
{0, 1}
转移函数定义如下(用箭头表示):
- 在状态
A:- 读
0:保持在状态A(还没看到1)。 - 读
1:转移到状态B(已看到1,可以接受)。
- 读
- 在状态
B:- 读
0:保持在状态B(已经知道可以接受,继续)。 - 读
1:保持在状态B。
- 读
这个自动机从状态 A 开始。只要它没读到1,就停留在 A(拒绝路径)。一旦读到第一个1,就进入状态 B 并永远停留(接受路径)。因此,它接受的字符串正是那些包含至少一个‘1’的字符串。
总结
本节课中我们一起学习了两种基础计算模型。
- 布尔逻辑电路:我们了解了其构成、通用性的概念,并证明了
{AND, OR, NOT}及其子集(如仅{NAND})是通用的。通过香农的计数论证,我们认识到绝大多数布尔函数需要指数级大小的电路,尽管明确构造这样的函数仍然困难。 - 有限自动机:作为最简单的均匀计算模型,它通过有限状态和转移函数来处理任意长度的输入流。我们通过一个检查输入是否包含‘1’的例子,直观理解了其工作原理。
从非均匀的电路模型过渡到均匀的自动机模型,我们开始触及计算理论的核心:探索在不同资源限制(如内存、时间)下,什么是可计算的。在下节课中,我们将更深入地研究有限自动机的能力与局限。
003:有限自动机、非确定性有限自动机与正则表达式
在本节课中,我们将学习有限自动机(DFA)的基本概念,探讨其与非确定性有限自动机(NFA)的关系,并介绍正则表达式。我们将了解这些模型如何定义“正则语言”,并学习如何证明某些语言不是正则的。
有限自动机(DFA)回顾
上一节我们介绍了计算模型的基本概念。本节中,我们来看看一种最简单的计算模型:有限自动机。
有限自动机是一种扫描输入的计算机模型。它从左到右读取输入符号,并根据当前状态和读取的符号转换到新的状态。读取完所有符号后,根据最终所处的状态决定接受或拒绝该字符串。
更正式地,一个有限自动机 M 由以下五部分组成:
- 状态集合 Q:一个有限的状态集合。
- 字母表 Σ:一个有限的输入符号集合(例如 {0, 1})。
- 起始状态 q₀ ∈ Q:开始计算前的状态。
- 接受状态集合 F ⊆ Q:如果计算结束于 F 中的状态,则接受输入。
- 转移函数 δ:
δ: Q × Σ → Q。它定义了在当前状态和输入符号下,应转换到哪个新状态。
如果一个有限自动机 M 接受语言 L 中的所有字符串,并拒绝所有不在 L 中的字符串,则称 M 识别(或接受)语言 L。我们将 M 识别的语言记为 L(M)。
如果一个语言能被某个有限自动机识别,则称该语言为正则语言。
以下是两个有限自动机的例子:
- 识别“包含至少一个1”的字符串。
- 识别“包含奇数个1”的字符串。
正则语言的封闭性
我们已经看到了一些正则语言的例子。现在,我们来看看如何通过已知的正则语言构造新的正则语言。这被称为封闭性。
以下是正则语言的一些封闭性质:
- 交集封闭性:如果 L 和 L' 是正则语言,那么 L ∩ L' 也是正则语言。
- 证明思路:使用乘积构造法。构造一个新的自动机,其状态是原有两个自动机状态的笛卡尔积。新自动机同时模拟两个原自动机的运行,仅当两个原自动机都接受时才接受。
- 补集封闭性:如果 L 是正则语言,那么其补集 L̅(所有不在 L 中的字符串)也是正则语言。
- 证明思路:将原自动机中所有接受状态和非接受状态互换。
- 并集封闭性:如果 L 和 L' 是正则语言,那么 L ∪ L' 也是正则语言。
- 证明思路:可以利用德摩根定律和上述两个性质:
L ∪ L' = complement(complement(L) ∩ complement(L'))。
- 证明思路:可以利用德摩根定律和上述两个性质:
此外,所有有限语言(只包含有限多个字符串的语言)都是正则的。可以通过为语言中的每个字符串构建一条独立的接受路径来实现。
非正则语言示例
并非所有语言都是正则的。一个关键的限制是,有限自动机只有固定的、有限的内存(状态数),因此无法“计数”或记住任意多的信息。
考虑回文语言 P:所有正读反读都一样的二进制字符串(例如 01 10, 0000)。直观上,要判断一个字符串是否是回文,需要记住前半部分,以便与后半部分比较。对于任意长的字符串,这需要无限增长的内存,而有限自动机无法提供。
我们可以用鸽巢原理严格证明 P 不是正则语言:
- 假设存在一个具有 k 个状态的有限自动机 M 识别 P。
- 考虑所有偶数长度回文,它们形如
xx^R(x 是前半部分,x^R 是 x 的反转)。有无限多个这样的 x。 - 当 M 读完某个 x 后,会处于某个状态。由于只有 k 个状态,而 x 有无限多种可能,根据鸽巢原理,必存在两个不同的字符串 x 和 y,使得 M 读完 x 和 y 后处于相同的状态 S。
- 现在考虑字符串
xy^R。由于 x ≠ y,xy^R不是回文。 - 然而,M 在处理
xy^R时,读完 x 后进入状态 S。由于读完 y 后也进入状态 S,且 y^R 会使 M 从状态 S 出发最终接受(因为yy^R是回文,应被接受),因此 M 也会接受xy^R。 - 这就产生了矛盾:M 接受了一个非回文字符串。因此假设错误,P 不是正则语言。
这个论证的核心是:有限自动机无法区分会导致相同状态的、不同的历史信息(如 x 和 y)。这种技术可以形式化为泵引理,用于系统性地证明语言的非正则性。
非确定性有限自动机(NFA)
为了增强表达能力(或至少简化设计),我们引入非确定性有限自动机。NFA 允许在每一步有多个可能的转移,甚至可以有不读输入就发生的 ε-转移。
形式上,NFA 与 DFA 的区别在于转移函数 δ:δ: Q × (Σ ∪ {ε}) → P(Q),其中 P(Q) 是 Q 的幂集(所有子集的集合)。它输出一个可能的状态集合。
NFA 接受一个输入字符串,当且仅当存在至少一条由转移函数定义的路径,从起始状态开始,读取整个输入(可能经过若干 ε-转移)后,到达某个接受状态。
NFA 的优势在于设计通常更简洁。例如,设计一个识别“倒数第三个字符是1”的字符串的 DFA 比较繁琐,但 NFA 可以很简单地设计出来:先随意读任意字符(停留在初始状态),当看到一个1时,“猜测”这就是倒数第三个字符,然后严格检查后续是否恰好还有两个字符。
NFA 与 DFA 的等价性
一个自然的问题是:NFA 是否比 DFA 更强大?答案是否定的。
定理:任何 NFA 都可以转换为一个识别相同语言的 DFA。
- 证明思路(幂集构造法):
- 设 NFA N 有 k 个状态。
- 构造一个 DFA M,其每个状态对应 N 的一个状态子集。因此 M 最多有 2ᵏ 个状态。
- DFA M 的状态
{q1, q2, ...}表示:在读取了部分输入后,NFA N 可能处于的所有状态的集合。 - DFA M 的转移函数定义为:从状态集合 S 出发,读入符号 a,到达状态集合
∪_{q∈S} δ_N(q, a)(即从 S 中每个状态 q 出发,读 a 在 N 中能到达的所有状态的并集)。 - DFA M 的起始状态是 N 的起始状态在 ε-转移下能到达的所有状态的集合。
- DFA M 的接受状态是那些包含 N 的至少一个接受状态的状态集合。
- 这个构造表明,NFA 并没有增加语言的识别能力,它识别的语言类仍然是正则语言。但状态数可能指数级增长,这体现了非确定性作为一种“设计工具”的价值。
正则表达式
正则表达式是描述正则语言的另一种强大且常用的方式。它通过递归组合基本操作来定义字符串集合。
基本操作包括:
- 基本符号:字母表中的字符(如
0,1)。 - 连接:
R₁R₂表示 R₁ 的字符串后紧接 R₂ 的字符串。 - 选择(或):
R₁ | R₂表示属于 R₁ 或 R₂ 的字符串。 - 克林星号:
R*表示重复 R 零次或多次。 - 括号:
(R)用于分组。
例如:
(0|1)*表示所有二进制字符串。(0|1)*000(0|1)*表示所有包含子串“000”的字符串。- 表示“包含偶数个1”的字符串的正则表达式可以是:
0* (10*10*)*。
一个关键结论是(将在后续课程中证明):一个语言是正则的,当且仅当它可以由某个正则表达式描述。因此,正则表达式、DFA 和 NFA 在定义正则语言的能力上是完全等价的。
总结
本节课中我们一起学习了:
- 有限自动机(DFA) 的形式化定义及其识别的正则语言。
- 正则语言在交集、补集、并集运算下的封闭性。
- 存在非正则语言,如回文语言,并学习了如何使用鸽巢原理进行证明。
- 非确定性有限自动机(NFA) 的概念及其更简洁的设计优势。
- NFA 与 DFA 的等价性,通过幂集构造法可以将任何 NFA 转换为 DFA。
- 正则表达式作为描述正则语言的另一种等价且实用的方法。
这些概念构成了形式语言理论的基础,并帮助我们理解不同计算模型的能力与局限。
004:正则表达式与有限自动机的等价性
在本节课中,我们将学习正则表达式与有限自动机之间的等价性证明。我们将看到,任何正则表达式都可以转换为一个非确定性有限自动机,反之亦然。这证明了正则语言(由DFA/NFA定义的语言)和正则表达式描述的语言是同一类语言。
从正则表达式到NFA
上一节我们介绍了正则表达式和有限自动机的基本概念。本节中,我们来看看如何将任意一个正则表达式转换为一个等价的非确定性有限自动机。
证明分为两个方向。首先,我们处理较简单的方向:给定一个正则表达式,构造一个等价的NFA。我们通过归纳法来构造,处理正则表达式的三种基本操作:并、连接和克林星号。
以下是构造NFA的基本构件:
- 基本符号:对于正则表达式
a(a是字母表中的一个符号),其NFA很简单:一个开始状态通过标记为a的边指向一个接受状态。 - 空串:对于正则表达式
ε,其NFA是一个开始状态即接受状态。 - 空语言:对于正则表达式
∅,其NFA没有从开始状态到接受状态的路径。
对于复杂的正则表达式,我们假设已经为其子表达式构造了NFA,然后按以下规则组合:
并操作 (R1 ∪ R2)
假设我们已有NFA M1 接受语言 L(R1),NFA M2 接受语言 L(R2)。要构造接受 L(R1) ∪ L(R2) 的NFA,我们创建一个新的开始状态,并用 ε 转移分别指向 M1 和 M2 的开始状态。M1 和 M2 的接受状态保持不变,作为新NFA的接受状态。
公式描述:NFA(R1 ∪ R2) = 新开始状态 --ε--> NFA(R1) 和 新开始状态 --ε--> NFA(R2)。
连接操作 (R1 ∘ R2)
要构造接受语言 L(R1) ∘ L(R2) 的NFA,我们将 NFA(R1) 的所有接受状态与 NFA(R2) 的开始状态用 ε 转移连接起来,并取消 NFA(R1) 中状态的接受性。
公式描述:NFA(R1 ∘ R2) = 将 NFA(R1) 的所有接受状态通过 ε 转移连接到 NFA(R2) 的开始状态。
克林星号操作 (R*)
要构造接受语言 L(R*) 的NFA,我们创建一个新的开始状态(也是接受状态),并用 ε 转移指向 NFA(R) 的开始状态。同时,将 NFA(R) 的所有接受状态用 ε 转移指回这个新的开始状态。
公式描述:NFA(R*) = 新开始状态(接受) --ε--> NFA(R) 的开始状态,并且 NFA(R) 的所有接受状态 --ε--> 新开始状态。
通过递归地应用这些规则,我们可以为任何正则表达式构造出一个等价的NFA。由于NFA和DFA等价,这也意味着正则表达式可以转换为DFA。
从DFA到正则表达式
上一节我们展示了如何从正则表达式构建NFA。现在,我们来看反方向:如何将一个DFA(或NFA)转换为一个等价的正则表达式。这个方向稍复杂一些。
我们的策略是引入一个中间模型——广义非确定性有限自动机,然后通过它来完成转换。
广义非确定性有限自动机
一个GNFA本质上是一个NFA,但其边上的标签可以是任意正则表达式,而不仅仅是单个符号。此外,为了方便,我们规定GNFA具有以下形式:
- 有唯一的一个开始状态,没有进入该状态的边。
- 有唯一的一个接受状态,没有离开该状态的边。
- 任意两个状态之间最多只有一条有向边(标签为一个正则表达式)。
如果一个GNFA只有两个状态(开始状态和接受状态),且它们之间有一条标签为 R 的边,那么它显然接受语言 L(R)。
状态消减法
我们的目标是将一个多状态的GNFA逐步化简为仅有两个状态的GNFA,从而直接读出正则表达式。具体方法是反复“删除”一个非开始、非接受的状态,并修复因此被破坏的路径。
假设我们要删除状态 q_rip。考虑任意两个其他状态 q_i 和 q_j(可以是同一个状态)。在原GNFA中,从 q_i 到 q_j 的路径可能有:
- 直接通过边
R1。 - 经过
q_rip:即路径q_i -> q_rip -> ... -> q_rip -> q_j。这对应于先走边R2(从q_i到q_rip),然后在q_rip上循环零次或多次(R4*,其中R4是q_rip的自环边),最后走边R3(从q_rip到q_j)。
因此,在删除 q_rip 后,我们需要在 q_i 和 q_j 之间添加一条新的边,其标签为原标签 R1 与新路径标签 (R2)(R4)*(R3) 的并集。
公式描述:新标签 = R1 ∪ (R2)(R4)*(R3)。
我们需要对GNFA中每一对状态 (q_i, q_j) 执行此操作。这样,我们就得到了一个少了一个状态但语言等价的GNFA。
重复此过程,直到GNFA只剩下开始状态和接受状态。此时,连接这两者的边上的正则表达式就是原DFA所对应语言的正则表达式。
等价性的意义与推论
本节课我们一起学习了正则表达式与有限自动机等价的完整证明。这个等价性具有重要的理论和实践意义。
首先,它证明了我们之前定义的正则表达式运算(并、连接、星号)是完备的。在证明的两个方向中,我们恰好用到了这三种核心运算。
其次,它带来了强大的推论。例如,虽然正则表达式本身没有定义补集运算,但我们现在可以证明:如果一个语言 L 是正则的(即存在正则表达式描述),那么它的补集 ¬L 也是正则的。证明思路是:将 L 的正则表达式转换为DFA,交换该DFA中的接受与非接受状态得到接受 ¬L 的DFA,再将此DFA转换回正则表达式。
最后,这个等价性桥梁让我们可以自由选择最合适的工具来描述或处理正则语言:有时用正则表达式更简洁,有时用自动机进行推理更直观。
上下文无关文法导论
在结束了正则语言部分的讨论后,我们转向表达能力更强的语言类——上下文无关语言。正则语言无法描述许多有用的结构,例如匹配的括号或回文。
上下文无关文法是一种用于生成语言的规则系统。它由一组替换规则组成,涉及变量(非终结符)和终结符(字母表符号)。推导从开始变量出发,反复应用规则替换变量,直到得到一个仅由终结符组成的字符串,该字符串即属于文法生成的语言。
例如,以下文法生成所有由 0 和 1 组成的回文串:
S -> 0S0 | 1S1 | 0 | 1 | ε
推导示例:S => 0S0 => 01S10 => 01010。
与正则语言类似,上下文无关语言也有对应的机器模型,即下推自动机。PDA是一个附带了栈的NFA。栈提供了“后进先出”的存储能力,使其能够识别像 {0^n1^n | n ≥ 0} 或匹配括号这类非正则的语言。栈的操作使得PDA可以记住和处理嵌套结构,这是DFA有限的有限状态所无法做到的。
一个有趣的问题是:非确定性下推自动机比确定性下推自动机更强大吗?这与P vs NP问题有相似的精神。对于有限自动机,非确定性并未增加表达能力(NFA与DFA等价)。但对于下推自动机,情况不同。例如,回文语言可以被非确定性PDA接受,但不能被确定性PDA接受。这初步揭示了计算模型中确定性与非确定性关系的复杂性。
上下文无关文法在计算机科学中应用广泛,特别是用于定义编程语言的语法。编译器使用这类文法来解析源代码。自然语言中也存在类似结构,但往往伴随着歧义性——同一个句子可能对应多个不同的语法分析树(即推导方式)。消除歧义是设计和解析上下文无关文法时需要处理的重要问题。
005:图灵机与可计算性
在本节课中,我们将学习计算理论的核心模型——图灵机。我们将了解图灵机如何定义,它为何被认为是通用计算模型,以及它如何帮助我们理解“可计算性”这一概念。
概述
上一节我们介绍了上下文无关语言和下推自动机,它们比正则语言和有限自动机更强大,但仍存在局限性。本节中,我们将引入一个更强大的计算模型——图灵机。图灵机被认为是通用计算模型,能够模拟任何物理上合理的计算设备。我们将探讨图灵机的定义、工作原理,并介绍“可计算性”的正式概念。
从有限自动机到图灵机
有限自动机只能读取输入,并拥有有限的内部状态。为了获得更强的计算能力,我们需要添加新的功能。
以下是有限自动机所缺少的关键能力:
- 无限制的可读写内存:有限自动机只有有限的内部状态,无法存储任意数量的信息。
- 在内存中移动和重读的能力:有限自动机只能从左到右读取输入一次,无法回头或修改输入。
图灵机通过引入一个无限长的纸带和一个读写头来解决这些问题。读写头可以在纸带上左右移动,读取符号,并写入新的符号。
图灵机的定义
图灵机本质上是一个增强版的有限自动机。其核心组成部分包括:
- 无限长的纸带:被划分为方格,每个方格可以包含一个来自有限字母表的符号(例如,0、1、#)。纸带在两端都是无限的,或者至少可以根据需要任意延伸。
- 读写头:指向纸带上的一个方格,可以读取该方格的符号,写入一个新符号,并每次向左或向右移动一格。
- 有限状态控制器:包含有限数量的内部状态,决定机器的行为。
图灵机的转移规则由以下公式描述:
(当前状态, 读取的符号) -> (新状态, 写入的符号, 移动方向)
其中,移动方向可以是 左移(L)、右移(R),或者也可以是 接受(Accept) 或 拒绝(Reject),表示停机。
与有限自动机不同,图灵机可能永远不会停止(即进入无限循环),也可能在某个时刻通过进入“接受”或“拒绝”状态而停止。
一个图灵机示例:判断回文串
让我们设计一个图灵机来判断一个由0和1组成的字符串是否是回文串(正读反读都一样)。
以下是该图灵机的工作思路:
- 读取最左边的符号,记住它(通过状态),并用特殊标记(如#)覆盖它。
- 向右移动,直到遇到输入末尾的标记(#)。
- 向左移动一格,检查此处的符号是否与步骤1记住的符号匹配。如果不匹配,则拒绝。
- 如果匹配,则用#覆盖这个符号,然后向左移动,直到遇到输入起始的标记(#)。
- 向右移动一格,回到剩余未检查字符串的最左端。
- 重复步骤1-5。如果在检查过程中,发现下一个要读取的符号已经是标记(#),这意味着所有符号都已成功匹配,则接受。
这个图灵机虽然效率不高(需要来回移动),但它可以正确地判定回文串语言,而这是有限自动机无法做到的。
图灵机的变体与等价性
你可能会想,如果我们给图灵机增加更多功能(例如,多个纸带、二维纸带、随机访问内存),它是否会变得更强大?
一个核心的发现是:许多看似更强大的图灵机变体,在计算能力上与基本的一带、单向无限图灵机是等价的。这意味着它们所能计算的函数集合是完全相同的。
以下是两个等价性示例:
- 双向无限纸带 vs 单向无限纸带:可以通过“折叠”或“交织”的方式,用单向无限纸带模拟双向无限纸带。只需将双向纸带的左右两部分交错存储在单向纸带上,并修改状态转移逻辑来模拟左右移动。
- 多带图灵机 vs 单带图灵机:可以用一个单带图灵机模拟一个多带图灵机。方法是将所有纸带的内容并排存储在一个纸带上,并用扩展的字母表来标记每个纸带上读写头的位置。模拟器需要在各个“虚拟纸带”的读写头位置之间来回移动以执行一步操作,这虽然低效,但确实可行。
这些模拟论证支持了丘奇-图灵论题。
丘奇-图灵论题与可计算性
丘奇-图灵论题是一个基本假设,而非可被证明的定理。它有两种表述:
- 定义性表述:任何“直观上可计算”的函数,都可以被某个图灵机计算。我们正式定义“可计算”即为“图灵机可计算”。
- 物理性表述:任何物理上可实现的计算机(遵循已知物理定律)的计算能力,都不会超过图灵机。
这个论题得到了广泛的支持,因为所有已知的、被提出的合理计算模型(如λ演算、递归函数、现代编程语言)都已被证明与图灵机等价。
基于图灵机,我们可以正式定义可计算语言:
一个语言 L 是可计算的,当且仅当存在一个图灵机 M,使得:
- 对于所有属于 L 的输入字符串 x,M 在 x 上运行最终会接受。
- 对于所有不属于 L 的输入字符串 x,M 在 x 上运行最终会拒绝。
(注意:M 必须在所有输入上都停机。)
根据这个定义,回文串语言、素数语言等都是可计算的。事实上,任何你能用现代编程语言编写的、对有限输入总能给出是/否答案的程序,所对应的语言都是可计算的。
总结
本节课中我们一起学习了计算理论的核心——图灵机。我们从增强有限自动机的需求出发,定义了图灵机的基本模型,并通过回文判定的例子了解了其工作原理。我们探讨了图灵机各种变体之间的等价性,这引出了强大的丘奇-图灵论题,即图灵机抓住了“有效计算”的本质。最后,我们基于图灵机给出了“可计算语言”的正式定义。在接下来的课程中,我们将看到图灵机一个非凡的特性:它们可以模拟其他图灵机(通用性),同时我们也将探索图灵机无法解决的问题,从而触及计算的极限。
006:通用性与不可计算性
在本节课中,我们将要学习图灵机理论中两个核心且深刻的概念:通用性和不可计算性。我们将看到,存在一个特殊的“通用”图灵机,它可以模拟任何其他图灵机的行为。然后,我们将探讨计算的极限,证明存在图灵机无法解决的问题,其中最著名的例子就是停机问题。
通用图灵机:软件产业的基石
上一节我们介绍了图灵机的基本概念和邱奇-图灵论题。本节中,我们来看看图灵机一个极其重要的能力:通用性。这个概念由图灵在其1936年的论文中提出,它本质上是整个软件产业存在的基础。
定理:存在一个特定的图灵机,记为 U(通用图灵机),使得对于所有图灵机 M 和所有输入字符串 x,都有:
U(<M>, x) = M(x)
这个公式的含义是:通用图灵机 U 以另一台图灵机 M 的描述 <M> 和输入 x 作为输入,其运行结果与 M 直接在输入 x 上运行的结果完全相同。换句话说,U 是一个图灵机语言的“解释器”。
如何描述一台图灵机?
要理解这个定理,首先需要明确如何用有限的信息描述一台图灵机。一台图灵机由其状态转移表完全定义。例如,一个简单的两状态机可以用一个表格来描述在不同状态和读头下应执行的操作(写入什么符号、向哪移动、进入什么状态)。这个表格中的所有信息(状态编号、动作、转移目标)都可以用有限的二进制字符串进行编码。我们将图灵机 M 的这种编码字符串记作 <M>。
关键在于,这个描述字符串 <M> 本身也可以被写在图灵机的输入带上,作为另一台图灵机(比如 U)的输入。这就实现了“程序即数据”的概念,也是现代存储程序计算机的核心思想。
通用机 U 如何工作?
U 的构造本质上是一个编程练习:编写一个用图灵机语言实现的图灵机语言解释器。其基本思路如下:
- U 有两条输入带(或同一带的不同区域):一条存放
<M>,另一条存放原始输入x。 - 为了模拟 M 的一步操作,U 需要在
<M>带上反复扫描,查找 M 当前状态对应的指令。 - U 需要跟踪 M 的当前状态和读头位置。由于 U 本身是固定大小的,它无法将这些信息全部存储在有限状态中,因此必须将这些信息也记录在带上(例如,通过标记或特殊符号)。
- U 根据当前模拟的状态和
x带上读到的符号,在<M>带上找到对应的指令(写入什么、移动方向、下一个状态),然后更新x带和自身的状态记录。
这个过程需要 U 在带上进行大量来回移动和比较操作,模拟 M 的一步可能需要 U 执行很多步。但重要的是,U 是一个固定的机器,却能模拟任意复杂、甚至比自身描述更庞大的图灵机 M。
不可计算问题:停机问题
既然图灵机如此强大,一个自然的问题是:有什么是图灵机不能做的吗?答案是肯定的。最著名的不可计算问题就是停机问题。
停机问题定义为:判断一个给定的图灵机 M 在空白输入(或给定输入 x)上是否会最终停止(即不进入无限循环)。形式化地,我们定义语言 HALT 包含所有那些在空白输入上会停机的图灵机的描述 <M>。
直观上,判断程序是否包含无限循环似乎不难。但考虑以下程序(用高级语言表示):
for n = 4, 6, 8, ... to infinity:
found = False
for p = 2 to n-2:
if (p is prime) and (n-p is prime):
found = True
break
if not found:
HALT
这个程序会检查是否每个大于2的偶数都能表示为两个素数之和(即哥德巴赫猜想)。该程序会停机,当且仅当哥德巴赫猜想是错的。因此,如果我们能解决停机问题,就能立即判定哥德巴赫猜想的真伪。许多其他数学难题也可以类似地编码为停机问题。这暗示了停机问题可能极其困难。
停机问题的不可判定性证明
下面我们通过反证法严格证明,不存在能解决停机问题的图灵机。这是一个经典的自指论证。
-
假设:假设存在一台图灵机 P 能解决停机问题。即,对于任意输入
<M>(M 的描述),P 总能停机,并且:- 若 M 在空白输入上停机,则 P 接受。
- 若 M 在空白输入上永不停机,则 P 拒绝。
-
构造矛盾机 Q:利用 P,我们可以构造一台新的图灵机 Q,其行为如下:
- Q 的输入是某个图灵机
<M>的描述。 - Q 首先运行 P 来判断:当 M 以自己的描述
<M>作为输入时,是否会停机?- 这里需要一个小技巧:P 判断的是 M 在空白输入上是否停机。我们可以先构造一个机器 M',它先将
<M>写到带上,然后模拟 M 的行为。这样 M' 在空白输入上的行为就等价于 M 在输入<M>上的行为。Q 可以调用 P 来判断 M'。
- 这里需要一个小技巧:P 判断的是 M 在空白输入上是否停机。我们可以先构造一个机器 M',它先将
- 根据 P 的输出,Q 采取相反的行动:
- 如果 P 说“M 在
<M>上停机”,那么 Q 就进入无限循环。 - 如果 P 说“M 在
<M>上永不停机”,那么 Q 就立即停机。
- 如果 P 说“M 在
- Q 的输入是某个图灵机
-
引发矛盾:现在,考虑当 Q 以自己的描述
<Q>作为输入时会发生什么?我们分析 Q 在<Q>上的运行:- 根据定义,Q(
<Q>) 首先会调用 P 来判断 Q 在<Q>上是否停机。 - 情况一:假设 Q 在
<Q>上停机。那么根据 Q 的构造逻辑,P 必须报告“Q 在<Q>上永不停机”,Q 才会停机。这与我们的假设(Q 停机)意味着 P 应报告“停机”相矛盾。 - 情况二:假设 Q 在
<Q>上永不停机。那么根据 Q 的构造逻辑,P 必须报告“Q 在<Q>上停机”,Q 才会进入无限循环。这与我们的假设(Q 永不停机)意味着 P 应报告“永不停机”相矛盾。
- 根据定义,Q(
-
得出结论:无论哪种情况都导致矛盾。矛盾的根源在于我们最初假设了 P 的存在。因此,这样的图灵机 P 不可能存在。停机问题是不可计算的。
忙海狸函数:触及无限的增长
为了更具体地感受不可计算性,我们可以看看忙海狸函数。BB(n) 定义为:在所有 n 个状态的图灵机中(在空白带上启动),那些最终会停机的机器所能运行的最大步数。
以下是已知的一些值:
- BB(1) = 1
- BB(2) = 6
- BB(3) = 21
- BB(4) = 107
- BB(5) ≥ 47,176,870(确切值未知,取决于一些尚未证明是否停机的图灵机)
- BB(6) 极其巨大,远超任何通常能想象到的函数(如指数塔、阿克曼函数)。
忙海狸函数增长得如此之快,以至于它本身是不可计算的。我们可以简要说明原因:如果存在图灵机能计算 BB(n),那么我们就可以用它来解决停机问题。方法是对任何 n 状态图灵机 M,只需模拟它运行 BB(n) 步。如果在此过程中它停机了,则回答“停机”;如果超过 BB(n) 步仍未停机,由于 BB(n) 是所有 n 状态停机机器运行步数的上界,那么 M 必定永不停机。这构成了一个判定停机问题的过程,与停机问题的不可判定性矛盾。
可计算与不可计算:谁更普遍?
你可能会认为不可计算问题是罕见的特例。但康托尔在19世纪80年代关于无穷集合的研究揭示了一个惊人的事实:不可计算的语言(问题)实际上占绝大多数。
- 可数无穷:如果一个无限集合的元素能与正整数一一对应,则称其为可数无穷。例如:所有整数、所有有理数、所有有限二进制串、所有图灵机。因为每台图灵机都可以用一个有限的二进制串描述,而有限二进制串是可数的。
- 不可数无穷:存在更大的无穷。康托尔通过著名的对角线法证明,所有二进制串的集合(等价于所有语言,或所有实数的一个子集)是不可数的。其数量级严格大于可数无穷。
论证概要:假设所有语言是可数的,我们可以将它们列表 L1, L2, L3...。每个语言可以表示为一个无限长的二进制序列(第 i 位表示第 i 个字符串是否属于该语言)。现在构造一个新语言 L:对于第 i 个字符串,如果它在 Li 中,则 L 不包含它;如果它不在 Li 中,则 L* 包含它。这样 L* 与列表中的每一个语言都至少在一个字符串上不同,因此不在列表中,矛盾。所以语言是不可数的。
结论:图灵机只有可数无穷多台,而语言有不可数无穷多个。每台图灵机至多决定一种语言,因此几乎所有的语言都是不可计算的。如果你随机选择一个语言,它可计算的概率是0%。
总结
本节课中我们一起学习了:
- 通用图灵机 U 的存在性及其意义:一台固定的机器可以模拟任何其他图灵机,奠定了通用计算的基础。
- 停机问题的不可判定性:通过巧妙的自指论证,我们证明了不存在能判定任意程序是否停机的算法。这是计算理论中第一个也是最重要的不可计算问题。
- 忙海狸函数:一个增长极快且自身不可计算的函数,生动体现了不可计算性的存在。
- 可数与不可数无穷:通过康托尔的对角线法,我们理解了图灵机(可计算对象)只是所有可能问题中极其微小的一部分,绝大多数问题是不可计算的。
这些概念揭示了计算的本质能力和根本限制,是理论计算机科学的基石。在下节课中,我们将学习如何利用“规约”技术,基于停机问题的不可判定性,来证明其他问题的不可计算性。
007:图灵可识别性与归约
在本节课中,我们将学习图灵可识别语言的概念,并深入探讨一个核心工具——归约。我们将了解如何通过归约来证明问题的不可判定性,并探索一些令人惊讶的不可判定问题。
回顾:集合的基数与不可判定性
上一节我们介绍了图灵机与停机问题,并证明了停机问题是不可判定的。我们还讨论了集合的基数,特别是无限集的大小。
我们主要讨论了两种基数:
- 可数无限:自然数集 \(\mathbb{N}\) 的基数,记为 \(\aleph_0\)。例如,自然数对 \(\mathbb{N}^2\) 和有理数集 \(\mathbb{Q}\) 都具有相同的基数。
- 不可数无限:实数集 \(\mathbb{R}\) 的基数,记为 \(2^{\aleph_0}\)。这也是所有语言集合的基数。
一个关键结论是:所有图灵机的集合是可数的(基数为 \(\aleph_0\)),而所有语言的集合是不可数的(基数为 \(2^{\aleph_0}\))。根据康托尔定理,后者严格大于前者。因此,必然存在一些语言(问题)是任何图灵机(算法)都无法判定的。这从基数角度解释了为什么存在不可判定的问题。
图灵可识别语言
现在,我们引入一个比“可判定”稍弱的概念。
可判定语言的定义是:存在一个图灵机 \(M\),使得对于任意输入 \(x\):
- 若 \(x \in L\),则 \(M\) 停机并接受。
- 若 \(x \notin L\),则 \(M\) 停机并拒绝。
我们称 \(M\) 判定 了语言 \(L\)。
图灵可识别语言(或称递归可枚举语言)的定义则是:存在一个图灵机 \(M\),使得对于任意输入 \(x\):
- 若 \(x \in L\),则 \(M\) 停机并接受。
- 若 \(x \notin L\),则 \(M\) 可能停机并拒绝,也可能永远循环。
两者的核心区别在于,对于不属于语言的输入,可识别语言对应的图灵机被允许永不停机。所有可判定语言都是图灵可识别的,但反之则不成立。
示例:停机问题是图灵可识别的
我们已知停机问题 \(HALT = \{ \langle M, x \rangle \mid M \text{ 在输入 } x \text{ 上停机} \}\) 是不可判定的。然而,它是图灵可识别的。
以下是识别 \(HALT\) 的图灵机思路:
- 输入为 \(\langle M, x \rangle\)。
- 在输入 \(x\) 上模拟图灵机 \(M\) 的运行。
- 如果模拟过程中 \(M\) 停机(无论是接受还是拒绝),则接受 \(\langle M, x \rangle\)。
- 如果 \(M\) 永不停机,那么模拟也将永远进行下去,这正是允许的。
这个图灵机识别了 \(HALT\),因为它对所有“是”实例(\(M\) 停机)都会停机并接受,而对所有“否”实例(\(M\) 永不停机)则永远循环。
语言类与补集
目前我们接触的语言类关系如下:
- 正则语言 \(\subseteq\) 上下文无关语言 \(\subseteq\) 可判定语言 \(\subseteq\) 图灵可识别语言 \(\subseteq\) 所有语言。
其中,可判定语言类也称为递归语言,常记为 R。图灵可识别语言类也称为递归可枚举语言,常记为 RE。
现在考虑一个语言 \(L\) 的补集 \(L^C = \{ x \mid x \notin L \}\)。
一个重要的事实是:图灵可识别语言类对补运算不封闭。例如:
- \(HALT \in RE\)(可识别)。
- \(HALT^C \notin RE\)(不可识别)。其证明将在习题中完成。
这引出了补类的概念。对于任意语言类 \(X\),定义其补类 \(coX\) 为:
注意,\(coX\) 不是 \(X\) 的补集(即不是“不在 \(X\) 中的所有语言”),而是“其补集在 \(X\) 中的所有语言”。例如,\(coRE\) 就包含了像 \(HALT^C\) 这样的语言,因为它的补集 \(HALT \in RE\)。
可以证明,\(RE \cap coRE = R\)。也就是说,一个语言及其补集如果都是图灵可识别的,那么这个语言一定是可判定的。
归约
归约是理论计算机科学中一个核心且强大的概念。它是一种证明方法,用于表明:如果能解决某个问题 \(B\),那么就能解决问题 \(A\)。
直观理解
在日常生活中,我们经常使用归约。例如,你想去哈佛广场但不知道路。你的朋友告诉你:“如果你能到中央广场,那么从那里坐红线地铁向北一站就是哈佛广场。” 你朋友并不知道从你家到中央广场的路线,但他提供了从“到中央广场”这个问题到“到哈佛广场”这个问题的归约。你知道如何解决前一个问题,结合这个归约,你就知道了如何解决后一个问题。
形式化定义:图灵归约
我们说问题 \(A\) 图灵可归约到问题 \(B\),记作 \(A \leq_T B\),如果存在一个图灵机 \(M\),在拥有一个能解决 \(B\) 的“神谕”(oracle)的情况下,能够判定 \(A\)。
这意味着,我们假设存在一个黑箱子(神谕),对于任何输入,都能立即给出它是否属于 \(B\) 的答案。我们设计一个算法 \(M\),它可以随时咨询这个神谕,并最终判定输入是否属于 \(A\)。\(M\) 被称为归约机。
关键点:
- 归约关注的是“如果有了解决 \(B\) 的能力,就能解决 \(A\)”。
- 即使 \(B\) 本身是不可判定的,这个归约关系仍然有意义。它说明 \(A\) 的难度不会超过 \(B\)。
- 如果 \(B\) 是可判定的,那么通过归约 \(A \leq_T B\),可以立即得出 \(A\) 也是可判定的(因为我们可以用判定 \(B\) 的真实算法替换掉神谕调用)。
归约的性质
- 自反性:\(A \leq_T A\)。要解决 \(A\),只需调用解决 \(A\) 的神谕即可。
- 传递性:如果 \(A \leq_T B\) 且 \(B \leq_T C\),那么 \(A \leq_T C\)。我们可以将第一个归约中所有对 \(B\) 神谕的调用,替换为执行第二个从 \(B\) 到 \(C\) 的归约过程。
- 可判定语言是“最简单”的:如果 \(L\) 是可判定的,那么对于任何语言 \(S\),都有 \(L \leq_T S\)。因为判定 \(L\) 的图灵机根本不需要调用 \(S\) 的神谕。
示例:两种停机问题的等价性
考虑两个停机问题变种:
- \(HALT = \{ \langle M, x \rangle \mid M \text{ 在输入 } x \text{ 上停机} \}\)
- \(HALT_\epsilon = \{ \langle M \rangle \mid M \text{ 在空输入上停机} \}\)
我们可以证明它们在图灵归约下是等价的,即 \(HALT \equiv_T HALT_\epsilon\)。
- \(HALT_\epsilon \leq_T HALT\):要判断 \(M\) 在空输入上是否停机,只需调用 \(HALT\) 神谕,询问 \(\langle M, \epsilon \rangle\) 即可。
- \(HALT \leq_T HALT_\epsilon\):给定 \(\langle M, x \rangle\),我们构造一个新的图灵机 \(M‘\),它的行为是:首先在磁带写上 \(x\),然后模拟 \(M\) 的运行。显然,\(M‘\) 在空输入上停机当且仅当 \(M\) 在输入 \(x\) 上停机。因此,我们调用 \(HALT_\epsilon\) 神谕询问 \(\langle M‘ \rangle\),就能得到 \(HALT\) 问题的答案。
这个例子展示了如何通过“硬编码”输入来建立归约。
映射归约
映射归约是图灵归约的一种更严格的形式。在映射归约 \(A \leq_m B\) 中,归约机 \(M\) 必须满足:
- \(M\) 在运行中只能调用一次 \(B\) 的神谕。
- \(M\) 必须原样输出神谕给出的答案,不能进行翻转或其他处理。
映射归约是一种更强的结论。例如,虽然 \(HALT \leq_T HALT^C\)(只需调用神谕后翻转答案),但可以证明 \(HALT \nleq_m HALT^C\)。映射归约能更好地保持复杂性类之间的区别(例如 \(RE\) 和 \(coRE\)),因此在某些理论分析中更受青睐。
利用归约证明不可判定性
归约最重要的用途之一是证明新问题的不可判定性。我们有一个现成的、已知不可判定的问题——停机问题 \(HALT\)。
证明策略:要证明语言 \(L\) 是不可判定的,只需证明 \(HALT \leq_T L\)。
推理:如果 \(L\) 是可判定的,那么由于 \(HALT\) 可归约到 \(L\),则 \(HALT\) 也应该是可判定的。但这与 \(HALT\) 不可判定的事实矛盾。因此,\(L\) 必定是不可判定的。
以下是两个著名的、通过归约证明不可判定性的数学问题:
1. 希尔伯特第十问题(丢番图方程)
问题:给定一个具有整数系数的多项式方程组(丢番图方程),判断是否存在整数解。
结论:该问题是不可判定的。
思路:可以构造从停机问题到此问题的归约。这表明,不存在一个通用算法能判定任意丢番图方程是否有整数解。这是数学上一个深刻的结论,因为该问题本身不涉及图灵机或自指,纯粹是一个数论问题。
2. 矩阵 mortality 问题
问题:给定一组 \(k \times k\) 的整数矩阵,判断是否存在一种方式(允许重复使用、任意顺序相乘),使得它们的乘积为零矩阵。
结论:对于 \(k \geq 3\),该问题是不可判定的。甚至对于固定数量的几个 \(3 \times 3\) 矩阵,问题也是不可判定的。
令人惊讶之处:这个问题看起来像是一个线性代数问题,直觉上可能认为存在某种算法(即使效率不高),但事实上它和图灵停机问题一样困难。
图灵度与不可判定问题的层次
所有在图灵归约下等价的问题构成一个等价类,称为图灵度。
- 可判定度:所有可判定问题构成一个图灵度(最易)。
- 停机问题度:\(HALT\)、\(HALT_\epsilon\)、丢番图方程问题、矩阵 mortality 问题等相互等价,构成另一个图灵度。
- 更高阶的度:存在比停机问题更难的问题。例如,“超级停机问题”——判定一个拥有停机问题神谕的图灵机是否停机。可以证明,即使拥有普通停机问题的神谕,也无法判定超级停机问题。通过反复应用此构造,可以得到一个无限的问题层次,其中每个问题都比前一个更难。
- 中间度:是否存在难度严格介于可判定问题和停机问题之间的问题?答案是肯定的,这由 Friedberg-Muchnik 定理解决,表明存在“中间”图灵度。
每个图灵度中包含的语言数量是可数的(\(\aleph_0\)),因为执行归约的图灵机只有可数多个。
总结
本节课我们一起学习了:
- 图灵可识别语言:定义了比可判定性更弱但更广泛的语言类 \(RE\),并理解了其与补类 \(coRE\) 的关系。
- 归约:掌握了计算机科学中这一核心证明工具。我们学习了图灵归约 \(A \leq_T B\) 的直观含义和形式定义,理解了它是比较问题难度的标尺。
- 证明不可判定性的方法:掌握了通过从停机问题归约来证明新问题不可判定的标准技巧。
- 丰富的不可判定问题世界:通过希尔伯特第十问题和矩阵 mortality 问题等例子,我们看到了不可判定性不仅限于自指的停机问题,也出现在许多看似纯粹的数学领域。
- 问题复杂度的层次结构:了解了图灵度的概念,知道存在无限多的、难度各不相同的不可判定问题层次。
归约是贯穿可计算性理论和复杂性理论的强大工具,在后续学习 P、NP、NP完全性 等概念时,它将扮演至关重要的角色。
008:不可判定性与哥德尔不完备性定理
在本节课中,我们将学习可计算性理论中的两个核心概念:Dovetailing(鸽巢式搜索) 技术,以及它与哥德尔不完备性定理的深刻联系。我们将看到如何利用这些工具来理解计算的极限和数学证明系统的局限性。
可计算性理论回顾
上一节我们介绍了图灵归约和图灵度的概念。本节中,我们来看看一些更具体的不可判定问题,并学习一种处理无限搜索的实用技术。
图灵可识别语言是指存在图灵机能在答案为“是”时停机并接受的语言。停机问题(Halting Problem)是这类问题中最著名的例子,但还有许多非显然的例子与之图灵等价。例如,判断一个丢番图方程是否有整数解的问题,就被证明与停机问题一样困难。
Dovetailing(鸽巢式搜索)技术
当我们想判断一个图灵机是否存在某个输入使其停机时,直接逐个尝试所有输入会遇到问题:如果某个输入导致机器永远运行,我们的检查过程就会被卡住。Dovetailing 技术可以巧妙地解决这个问题。
以下是 Dovetailing 的基本步骤:
- 模拟图灵机在第一个输入上运行 1 步。
- 模拟图灵机在第一个和第二个输入上各运行 2 步。
- 模拟图灵机在前三个输入上各运行 3 步。
- 以此类推,不断增加模拟的输入数量和步数。
这个过程类似于证明有理数是可数的对角线方法。通过这种交错执行的方式,如果存在某个输入能使机器停机,我们最终一定能在有限步内发现它,而不会被某个永不停止的模拟分支无限期阻塞。
更复杂的不可判定问题示例
利用 Dovetailing 技术,我们可以分析更复杂的问题。考虑语言 L,它包含所有这样的带预言机的图灵机描述:存在某个预言机设置使得该机器永远运行。
我们断言 L 是不可判定的。原因在于,即使我们有一个判断 L 的预言机,我们也可以利用它来解决普通的停机问题(通过构造一个忽略预言机的机器)。反之,如果我们想用普通停机问题的预言机来判断 L,则需要更精巧的构造。
核心思路是构建一个树形结构来模拟所有可能的预言机设置(0 或 1 的无限序列)。每当机器查询一个新的预言机位时,我们就分支考虑该位为 0 和 1 的两种情况。我们使用广度优先搜索(BFS) 来遍历这棵树,以避免在某个无限分支上卡住。如果此搜索过程最终停止,说明不存在使原机器永远运行的预言机;如果此过程永不停止,则根据König 引理(每个无限、有限分支的树都包含一条无限路径),必然存在一个预言机设置使机器永远运行。
哥德尔不完备性定理
哥德尔不完备性定理在停机问题的不可判定性被证明前五年就已提出,并深深影响了图灵。它的起点不是计算,而是逻辑。
自指与递归定理
像“这句话是假的”这样的句子会导致悖论。人们可能认为禁止自指就能解决问题,但递归定理表明这是不可能的。递归定理指出,任何程序都可以在编写时假定它能访问自己的源代码。这通过一种类似“打印以下内容两次,第二次加上引号”的技巧实现。
这意味着,即使表面上禁止直接自指,我们也能通过谈论引号内的字符串(即代码本身)来构造出本质上自指的语句,从而重新引入悖论。
真理的不可定义性与证明
塔斯基指出,真理在数学系统内是不可形式化定义的。也就是说,不存在一个数学上可定义的函数 F(s),能对每个算术语句 s 输出 1(真)或 0(假)。如果可以定义,我们就能构造出说谎者悖论,导致数学矛盾。
哥德尔的创新在于将焦点从“真理”转向“可证明性”。一个证明系统包括形式语言、推理规则和公理。如果系统能证明的每个语句都是真的,则它是可靠的(Sound)。如果系统永远不会同时证明一个语句及其否定,则它是一致的(Consistent)。如果系统对语言中的每个语句,要么能证明它,要么能证明它的否定,则它是完备的(Complete)。如果存在一个程序能列出系统的所有定理,则它是可计算的(Computable)。
哥德尔第一不完备性定理(非形式化陈述)
设 F 是任何一个足够强大(能表达算术语句)、可靠且可计算的证明系统(例如皮亚诺算术或策梅洛-弗兰克尔集合论)。那么,存在一个在 F 的语言中可表达的算术语句 S,使得 F 既不能证明 S,也不能证明 S 的否定。
换句话说,任何足够强大且一致的形式系统,都必然包含一些它既无法证明也无法证伪的算术真理。这揭示了数学证明系统固有的局限性。
总结
本节课中我们一起学习了:
- Dovetailing 技术:一种处理无限搜索、避免被永不停止的分支卡住的有效方法。
- 复杂不可判定问题的分析:通过构建可能性树和使用广度优先搜索,我们展示了如何判断某些涉及预言机的问题的不可判定性。
- 哥德尔不完备性定理的铺垫:理解了自指悖论、递归定理以及真理在形式系统内的不可定义性。
- 哥德尔第一不完备性定理的核心结论:任何足够强大、可靠且可计算的形式系统,在算术上都是不完备的,存在无法判定的语句。
这些概念深刻揭示了计算和数学推理的边界,将可计算性理论与数理逻辑紧密地联系在了一起。
009:哥德尔不完备性定理与柯尔莫哥洛夫复杂度
在本节课中,我们将要学习哥德尔不完备性定理的深入内容,包括其证明思路、与停机问题的联系,以及罗瑟定理对它的改进。最后,我们将初步接触柯尔莫哥洛夫复杂度,作为从可计算性理论到复杂度理论的过渡。
概述:从可计算性到自指与不完备性
上一节我们介绍了如何通过归约证明问题的不可计算性,以及递归可枚举集等概念。本节中,我们将深入探讨自指现象的核心——哥德尔不完备性定理,并了解其证明和影响。
哥德尔第一不完备性定理
哥德尔第一不完备性定理指出:任何足够强大、可计算且一致(或可靠)的形式系统,都无法同时是完备的。这意味着系统中必然存在一些既不能被证明也不能被证伪的语句。
形式系统的理想属性
在深入定理之前,我们先明确对一个“好”的形式系统(证明系统)的期望。以下是几个核心属性:
- 可靠性:系统证明的所有定理都是真的。
- 一致性:系统永远不会同时证明一个命题及其否定。
- 可计算性:存在一个图灵机可以枚举系统的所有定理。或者说,系统的定理集是递归可枚举的。
- 完备性:对于系统语言中的任何语句,系统要么能证明它,要么能证明它的否定。
- 强大性:系统能够表达足够丰富的数学陈述,例如关于算术的陈述(如“某图灵机停机”)。
定理的陈述与条件必要性
哥德尔定理的正式陈述依赖于上述多个条件。我们可以通过思考如果去掉某个条件会怎样,来理解它们的必要性:
- 放弃可靠性:可以构造一个完备但不可靠的系统。例如,一个宣称所有语句都为真的系统,它显然是完备的,但不可靠。
- 放弃可计算性:可以构造一个可靠且完备的系统。例如,直接以所有真的算术语句作为公理的系统。但这样的系统没有提供任何“可计算”的证明方法。
- 放弃强大性(即放弃对算术的刻画):可以构造可靠、可计算且完备的系统。例如,命题逻辑系统。但它无法表达“图灵机停机”这类算术命题。
因此,定理的条件缺一不可。
定理的证明思路
哥德尔证明的核心是构造一个特殊的语句,即哥德尔语句 G(F),其含义是:“G(F) 在系统 F 中不可证明”。
- 处理自指:通过类似“打印以下内容两次,第二次加引号”的技巧,可以在不直接自指的情况下构造出这样的语句。
- 表达“可证明性”:这是关键创新。哥德尔证明了,在一个足够强大的系统 F 内部,可以形式化地定义“语句 S 在 F 中可证明”这个概念。这是因为“S 可证明”等价于“存在一个枚举 F 所有定理的图灵机,它会在有限步内输出 S”。由于 F 能谈论图灵机停机问题,因此它也能表达这种“可证明性”。
- 逻辑推导:
- 假设
G(F)在 F 中可证。那么根据G(F)的含义,G(F)为假(因为它声称自己不可证)。这意味着 F 证明了一个假命题,从而 F 不可靠。 - 假设
G(F)在 F 中不可证。那么G(F)为真(因为它声称的不可证性成真)。由于 F 可靠,它也不能证明¬G(F)(因为那是假的)。因此,F 无法判定G(F),所以 F 不完备。
- 假设
因此,一个可靠、可计算且足够强大的系统 F 必然是不完备的。
与停机问题的联系
哥德尔定理可以从停机问题的不可解性推导出来,这展示了深刻的联系。
- 思路(反证法):假设存在一个可靠、可计算、完备且足够强大的证明系统 F。
- 构造算法:对于任意图灵机 M,问“M 在空输入上是否停机?”。由于 F 完备,它最终会证明“M 停机”或“M 永不停机”。由于 F 可靠,我们找到的证明就告诉了我们真相。
- 实现:我们可以编写一个程序,并行枚举 F 的所有定理,直到找到关于 M 停机的证明或否证。这便解决了停机问题。
- 矛盾:因为停机问题是不可解的,所以这样的证明系统 F 不可能存在。
这个算法被称为“英国博物馆算法”,因为它像在博物馆中漫无目的地浏览所有展品一样,枚举所有可能的证明。
罗瑟定理:用一致性代替可靠性
哥德尔的证明需要“可靠性”这个较强的元数学假设。罗瑟通过改进哥德尔语句,将假设弱化为系统内部可定义的“一致性”。
罗瑟语句 R(F) 的含义是:“对于 R(F) 在 F 中的每一个证明,都存在一个比它更短的 R(F) 在 F 中的否证”。
通过精巧的逻辑分析(考虑证明和否证的长度,并利用只有有限个更短字符串可检查这一事实),可以证明:如果 F 是一致的,那么 R(F) 在 F 中既不可证也不可否证。因此,任何一致、可计算且足够强大的形式系统都是不完备的。
哥德尔第二不完备性定理
在证明哥德尔/罗瑟语句不可证的过程中,我们实际上用到了“F 是一致的”这个假设。第二不完备性定理指出:一个一致且足够强大的系统 F,无法证明自身的一致性 Con(F)。
- 形式化证明:F 可以证明:“如果 F 一致,则罗瑟语句
R(F)成立”。即F ⊢ Con(F) → R(F)。 - 推导:如果 F 能够证明自身的一致性(即
F ⊢ Con(F)),那么根据上述,F 就能证明R(F)。但根据罗瑟定理,如果 F 一致,R(F)不可证。这就产生了矛盾。 - 结论:因此,一致的系统 F 不能证明
Con(F)。
一个有趣的推论是:我们可以构造一个“自我厌恶”的理论 F' = F + ¬Con(F),即 F 加上“F 不一致”作为新公理。如果 F 是一致的,那么 F‘ 也是一致的(否则 F 就能证明 Con(F),违反第二定理)。这个系统相信自己是矛盾的,却不会在实际推导中产生矛盾。
实践中的形式系统层级
- 皮亚诺算术 无法证明自身的一致性。
- ZF 集合论 可以证明皮亚诺算术的一致性(因为它能构造出 PA 的模型——自然数集),但无法证明 ZF 自身的一致性。
- 更强大的系统(如 ZF + 大基数公理)可以证明 ZF 的一致性,但又无法证明自身的一致性。
这形成了一个无限层级:每个系统都能证明 weaker(较弱)系统的一致性,但无法证明自身或 stronger(更强)系统的一致性。数学真理无法被任何一个形式系统完全捕获。
过渡:柯尔莫哥洛夫复杂度
最后,我们介绍一种使可计算性理论“定量化”的方法——柯尔莫哥洛夫复杂度,它将为我们进入计算复杂度理论铺平道路。
字符串 x 的柯尔莫哥洛夫复杂度 K(x) 定义为:输出 x 的最短计算机程序(例如,图灵机描述)的长度。它衡量了产生 x 所需的最少信息量,或者说 x 的“内在随机性”。
不变性定理
虽然程序长度依赖于编程语言,但不变性定理保证:对于任意两种通用编程语言,其定义的柯尔莫哥洛夫复杂度最多相差一个常数(该常数仅取决于语言本身)。因此,K(x) 在渐近意义下是良定义的。
示例与意义
- 高压缩性字符串:例如,由 n 个 0 组成的字符串。一个打印 n 个 0 的程序长度约为
log n(用于编码 n)。所以K(n个0) ≈ O(log n),远小于 n。 - 随机字符串:一个随机生成的 n 位字符串,其柯尔莫哥洛夫复杂度大约为 n。因为不存在显著短于 n 的程序来描述它。这对应了数据压缩的基本极限:大多数字符串是不可压缩的。
柯尔莫哥洛夫复杂度是算法信息论的基础,它形式化了“随机性”和“信息内容”的概念。在下节课中,我们将看到,判断一个字符串的柯尔莫哥洛夫复杂度是否小于某个值,本身是一个不可计算的问题,并由此开始复杂度理论的正式学习。
总结
本节课中我们一起学习了:
- 哥德尔第一不完备性定理:任何足够强大、可计算且一致的形式系统必然不完备,存在不可判定的命题。
- 证明精髓:通过将“自指”和“可证明性”算术化,构造出断言自身不可证的哥德尔语句。
- 与停机问题的等价:存在完备证明系统的假设会导致停机问题可解。
- 罗瑟定理:将定理中的“可靠性”假设弱化为系统内部的“一致性”。
- 哥德尔第二不完备性定理:一致的系统无法证明自身的一致性。
- 形式系统的层级结构:数学真理需要不断扩展的公理系统来逼近。
- 柯尔莫哥洛夫复杂度:作为可计算性理论的定量延伸,它用最短程序长度定义字符串的复杂性,揭示了数据压缩的理论极限和随机性的本质。
010:从可计算性到复杂度
在本节课中,我们将学习一个连接可计算性与复杂度理论的核心概念——柯尔莫哥洛夫复杂度。我们将了解它如何定义、为何重要,以及它为何是不可计算的。最后,我们将正式进入复杂度理论,介绍时间与空间复杂度的基本定义和层次定理。
柯尔莫哥洛夫复杂度:终极数据压缩极限
上一节我们讨论了哥德尔不完备性定理。本节中,我们来看看柯尔莫哥洛夫复杂度。这个概念由柯尔莫哥洛夫、所罗门诺夫和柴廷在20世纪60年代独立提出,它代表了数据压缩的理论极限。
给定一个比特串 x,其柯尔莫哥洛夫复杂度 K(x) 定义为:在某种选定的编程语言中,能在空白输入上输出 x 然后停机的最短程序的长度。本质上,它是 x 的最短可计算描述的长度。
对于任意 n 比特的串 x,K(x) 永远不会比 n 大太多,因为总可以写一个直接打印 x 的程序。在问题集3中,你将证明一个关键的不变性定理:编程语言的选择最多只会给 K(x) 带来一个与 x 无关的常数偏移。这使得柯尔莫哥洛夫复杂度成为一个定义良好的概念。
大多数字符串是不可压缩的
我们观察到,在所有 n 比特的字符串中,必然存在一些是不可压缩的。事实上,更强的结论也成立:几乎所有的 n 比特串都具有接近最大的柯尔莫哥洛夫复杂度。
以下是论证思路:
考虑长度不超过 n-100 比特的程序。这样的程序数量最多是 2^(n-99) 个(因为长度为 k 的比特串总数是 2^k)。然而,总共有 2^n 个不同的 n 比特字符串。由于 2^(n-99) 远小于 2^n(相差 2^99 倍),根本没有足够多的短程序来描述每一个长字符串。因此,绝大多数 n 比特字符串的柯尔莫哥洛夫复杂度至少是 n-100。
这个结论意味着,可压缩的字符串只占所有字符串中极小的一部分。我们日常处理的文件之所以能被压缩(例如用GZip),恰恰说明它们具有高度的规律性和冗余性,与完全随机的文件截然不同。
柯尔莫哥洛夫复杂度的应用:识别“异常”
柯尔莫哥洛夫复杂度最初是为了解决概率论中的一个古老悖论而发明的:如何判断一枚硬币是否“有问题”?
假设你抛一枚硬币1000次:
- 如果得到1000次正面朝上,你会怀疑硬币有问题。
- 如果得到一个完美的正反交替序列,你同样会怀疑。
- 如果序列是“在质数编号的抛掷中出现反面”,你也会怀疑。
- 但如果得到一个看似无规则的随机序列,你不会怀疑,尽管这个特定序列出现的概率与前几种同样低。
区别在于,前三种序列可以用远短于1000比特的规则(程序)来描述,即它们的柯尔莫哥洛夫复杂度远小于序列长度 n。而第四个随机序列的复杂度大约就是 n。因此,现代观点认为:当你观察到序列的柯尔莫哥洛夫复杂度远小于其长度时,就有理由怀疑其生成过程并非随机(例如硬币有问题)。这为“模式识别”提供了一个形式化的标准。
一个坏消息:柯尔莫哥洛夫复杂度是不可计算的
这听起来是个非常有用的理论工具,但遗憾的是,柯尔莫哥洛夫复杂度是不可计算的。不存在一个程序,输入字符串 x,总能输出 K(x)。
我们可以写一个程序,通过枚举所有图灵机(程序),并模拟运行它们。每当一个长度为 m 的程序停机并输出 x,我们就知道 K(x) ≤ m。随着时间推移,我们会得到越来越好的上界,并最终在某个时刻找到那个最短的程序。但问题在于,我们无法知道何时找到了最短的那个,因为总可能有更短的程序尚未停机。因此,这个程序会永远运行下去,无法在有限时间内确定 K(x) 的精确值。
更严格的证明表明,计算 K(x) 与解决停机问题是图灵等价的。这里我们用一个更简单、更优雅的悖论——贝里悖论——来直观说明其不可计算性。
贝里悖论如下:令 n 为“不能用100个英文单词描述的最小正整数”。这样的 n 必然存在(因为描述有限,整数无限)。但“不能用100个英文单词描述的最小正整数”这个短语本身已经用了少于100个单词描述了 n,构成了矛盾。
我们可以构造一个柯尔莫哥洛夫复杂度的版本。假设 K(x) 是可计算的,考虑以下程序 P:
for each string x in lexicographic order:
if K(x) >= n:
print(x)
halt
这个程序会寻找并输出一个复杂度至少为 n 的字符串。程序 P 的长度大约是 log(n) + c(c 是固定开销)。如果 n 足够大,使得 n > log(n) + c,那么 P 本身就是一个短于 n 比特的程序,却输出了一个据称需要至少 n 比特才能描述的字符串 x。这意味着 K(x) ≤ length(P) < n,与程序寻找的条件 K(x) >= n 矛盾。因此,最初的假设(K(x) 可计算)是错误的。
迈向复杂度理论:时间与空间资源
柯尔莫哥洛夫复杂度不考虑计算所需的时间,这引出了复杂度理论的核心关切:不仅关心是否可计算,更关心是否可用合理资源(时间、空间)进行可行计算。
我们需要一个计算模型,这里我们使用双带图灵机。对于任意函数 f(n),我们可以定义复杂度类:
DTIME(f(n)):所有能被一台双带图灵机判定的语言集合,该机器在长度为n的输入上,总是在O(f(n))步内停机。DSPACE(f(n)):所有能被一台双带图灵机判定的语言集合,该机器在长度为n的输入上,总共只访问O(f(n))个磁带格子(无论运行多久)。
我们关注最坏情况复杂度,并忽略常数因子。通常,我们区分多项式时间(如 n, n^2, n^3)和指数时间(如 2^n),因为前者在实践中通常可行,而后者则不然。
复杂度类的基本关系
了解不同复杂度类之间的关系至关重要。以下是一些基本包含关系:
- 层次结构:如果
f(n) = O(g(n)),那么DTIME(f(n)) ⊆ DTIME(g(n)),DSPACE(f(n)) ⊆ DSPACE(g(n))。给予更多资源,至少能解决同样多的问题。 - 时间与空间:对于任意
f(n),有DTIME(f(n)) ⊆ DSPACE(f(n))。因为图灵机每步只能移动一格,f(n)步内最多访问f(n)个格子。 - 空间与时间:
DSPACE(f(n)) ⊆ DTIME(2^(O(f(n))))。一台使用f(n)空间的机器,其可能的不同配置(磁带内容、读写头位置、内部状态)总数是2^(O(f(n)))量级。如果它要判定一个语言,则必须在重复进入同一配置前停机,否则将陷入无限循环。因此,其运行时间最多是指数于f(n)。
时间层次定理
一个核心问题是:给予更多时间,是否真能解决更多问题?时间层次定理给出了肯定的答案。例如,存在在 O(n^3) 时间内可判定,但在 O(n^2) 时间内不可判定的语言。
证明思路是构造一个“时间有界停机问题”的变体。考虑语言:
L = { <M, 0^k> | 图灵机 M 在空白输入上在 k^2.5 步内停机 }
我们可以证明:
L ∈ DTIME(n^3):只需模拟M运行k^2.5步并检查是否停机,模拟开销在O(n^3)内。L ∉ DTIME(n^2):假设存在O(n^2)时间的判定机,我们可以利用它构造一个程序P,使得P在输入<P, 0^k>上的行为导致矛盾(类似于停机问题或贝里悖论的论证)。因此,这样的判定机不可能存在。
这个定理表明,时间资源是分层的,更多时间确实能带来更强的计算能力。
总结
本节课中我们一起学习了:
- 柯尔莫哥洛夫复杂度
K(x)的定义:字符串的最短可计算描述的长度,是数据压缩的理论极限。 - 绝大多数字符串是不可压缩的,这解释了为何可压缩的数据具有特殊结构。
- 柯尔莫哥洛夫复杂度可用于形式化地定义“随机性”或“模式”,但遗憾的是,它是不可计算的,其证明与贝里悖论密切相关。
- 我们正式进入了复杂度理论,定义了时间复杂度
DTIME(f(n))和空间复杂度DSPACE(f(n))类。 - 我们探讨了不同复杂度类之间的基本包含关系,并介绍了时间层次定理,它证明了给予更多计算时间确实能解决更多问题。
下一讲,我们将继续深入探讨时间与空间复杂度,并开始接触计算理论中最重要的课题之一:P与NP问题。
011:时间与空间复杂度进阶
在本节课中,我们将继续深入探讨时间与空间复杂度。我们将回顾时间层次定理,并探讨其局限性和一些反直觉的结果,例如“加速定理”。接着,我们将正式定义几个核心的复杂度类,如P、PSPACE和EXP,并讨论它们之间的关系。最后,我们会引入“扩展的丘奇-图灵论题”,探讨计算在物理世界中的极限。
回顾与课程安排
上一节我们介绍了柯氏复杂度和时间/空间复杂度的基本概念。本节中,我们来看看时间层次定理的细节及其深远影响。
首先是一些课程安排提醒:
- PSet3 的截止日期是本周五。
- PSet2 的批改工作基本完成,预计周四前返还。
- 期中考试将在春假后的那个周四进行。
- 我们将在春假后、考试前安排一次复习课,并提供在线练习材料。
时间层次定理的回顾与含义
我们证明了时间层次定理,其核心结论是:拥有更多时间,就能判定更多语言。例如,TIME(n²) 是 TIME(n³) 的真子集。
证明方法本质上是图灵“停机问题不可判定”证明的缩放版。我们构造了一个语言,包含那些在约 n^2.5 步内停机的图灵机描述。这个语言显然可以在 n³ 时间内判定(直接模拟即可),但假设它能在 n² 时间内判定,就会导致一个矛盾:一个机器可以模拟自身并做出相反行为。
这类似于一个思想实验:你无法用一个耗时5秒的程序,准确预测自己10秒后会做什么。因为一旦你知道了预测结果,你就可以选择做相反的事情。时间层次定理正是这个思想的正式类比:如果一个机器能在少于 T(n) 的时间内预测另一个同类机器在 T(n) 时间内的行为,它就可以通过让自己做相反的事情来制造矛盾。这从某种意义上说明,计算的时间无法被普遍地“加速”。
一个自然的问题是:是否存在一些自然的问题,可以被证明需要 n³ 时间,而不能在 n² 时间内解决?这里“自然”指的是输入规模为 n,而非问题本身规模是 n³。
确实存在一些问题,我们不知道如何在线性时间内解决,例如矩阵乘法、最大流、线性规划、最大匹配等。算法课上研究的许多问题都有很快的算法,但并非线性时间。我们能否证明其中某些问题本质上就需要超过线性时间?
在某些情况下,这是可以证明的,方法是通过从时间层次定理进行规约。例如,存在一些基于图的游戏(如使用黑白棋子的游戏),其中计算最佳策略的难度与模拟一个图灵机运行 n³ 步是同等困难的。如果将国际象棋推广到 n×n 的棋盘,并且不限制游戏时长,那么判定给定棋局中白方或黑方是否必胜的难度,就相当于模拟一个图灵机运行指数时间。由此可以证明,不存在解决这个广义国际象棋问题的高效算法。这个结论是确定的,不依赖于 P 是否等于 NP 的假设。
然而,这只是例外而非常态。在大多数情况下,我们根本无法证明计算难度的无条件下界。这可以说是人类文明中最大的开放问题之一。原因之一是,50多年过去了,我们在许多情况下掌握的最强工具仍然是这种自指论证,它似乎不足以告诉我们想知道的大部分事情。
空间层次定理与资源比较
时间层次定理可以推广到其他资源。就像有时间层次定理一样,也有空间层次定理。
空间层次定理指出:拥有更多内存,就能判定更多语言。例如,SPACE(n³) 是 SPACE(n⁴) 的真子集。
证明方式与时间层次定理完全相同,只需将“时间”替换为“空间”。我们定义一个语言,包含所有在不超过 n^3.5 空间内停机并接受的图灵机。这个语言可以在 n⁴ 空间内判定,但如果它能在 n³ 空间内判定,就会产生自指悖论。
一般来说,对于几乎任何资源,我们都能证明某种层次定理。计算复杂性中的真正困难,往往出现在比较不同资源的时候,例如时间 vs. 空间,或者时间 vs. 非确定性时间(这引出了 P vs. NP 问题)。
时间层次定理的正式表述
在表述时间层次定理时,我们需要更严谨一些。最强的希望是:只要 F(n) 比 G(n) 增长得慢,TIME(F(n)) 就严格包含于 TIME(G(n))。但这并不完全正确,原因有二:
- 模拟本身会产生开销。
- 我们必须确保所讨论的增长率是“合理的”。
首先需要一个定义:如果一个函数 F(n) 是时间可构造的,则存在一个图灵机 M,以 0^n 作为输入,精确运行 F(n) 步后停机。这大致意味着,可以用大约 F(n) 的时间来计算 F(n)。在算法和复杂性中出现的几乎所有自然函数都是时间可构造的。
时间层次定理的正式表述是:如果 F 和 G 都是时间可构造的,并且 F(n) = o( G(n) / log G(n) ),那么 TIME(F(n)) ⊂ TIME(G(n))。
在证明中,我们在哪里用到了“F 是时间可构造的”这个假设?在第一步,我们说“显然,我们可以在比 F(n) 稍多一点的时间内判定这个语言”。为了设置“闹钟”(即确定允许图灵机运行多久后将其截断),我们需要能够计算 F(n)。如果 F 是像“忙碌海狸函数”这样不可计算的函数,我们就无法设置这个闹钟。
空间层次定理的表述更紧凑:如果 F 和 G 是空间可构造的,并且 F(n) = o( G(n) ),那么 SPACE(F(n)) ⊂ SPACE(G(n))。
加速定理:没有“最快”算法的问题
一个有趣的问题是:每个问题都必须有一个单一的复杂度吗?或者说,是否存在一些问题,只有越来越快的算法序列,而没有渐近意义上最快的算法?
在实践中,算法研究经常出现类似情况。例如整数乘法:
- 小学算法:O(n²) 时间。
- Karatsuba 算法:约 O(n^log₂3) 时间。
- 基于FFT的算法:约 O(n log n) 时间。
对于较小的数字,小学算法更快;当数字位数达到几十或几百时,Karatsuba 开始占优;位数更大时,FFT 方法更好。那么,是否存在一个无限的、越来越好的算法序列?
另一个著名例子是矩阵乘法:
- 标准算法:O(n³) 时间(输入规模为 n² 时,是 O(m^1.5),其中 m 是输入大小)。
- Strassen 算法:约 O(n^2.81) 时间。
- Coppersmith–Winograd 算法:O(n^2.376) 时间。
- 最新进展 (Vassilevska Williams/Stothers):O(n^2.373) 时间。
同样,存在一个交叉点序列,更复杂的算法在输入规模极大时才开始超越简单算法。是否存在一个无限序列的算法,使得对于任意 ε > 0,都有 O(n^(2+ε)) 时间的算法,但就是没有 O(n²) 的算法?理论上这是可能的。
Blum 加速定理指出,确实可以构造出具有这种行为的人工问题。该定理的一个惊人表述是:存在一个语言 L,使得对于任何在 O(F(n)) 时间内判定 L 的图灵机 M,总存在另一个在 O(log F(n)) 时间内判定 L 的图灵机 M‘。也就是说,对于这个语言,总存在一个指数级更快的算法。
需要注意的是,这里涉及的 F(n) 是极其巨大的函数(例如指数塔),取对数多次后仍然增长极快。同时,随着算法渐近速度加快,其大 O 记号中的常数项也会变得巨大。所以实际图像是:随着 n 增大,一个 O(log F(n)) 的算法会在某个巨大规模后超越 O(F(n)) 的算法,然后又被 O(log log F(n)) 的算法超越,依此类推。
我们几乎从未在实际问题中遇到过这种情况。对于矩阵乘法等实际问题,我们不能排除存在无限算法序列的可能性,但能证明这种情况存在的只有这些特意构造出来的人工问题。
复杂度类 P、PSPACE、EXP 及其关系
现在,我们引入一些重要的复杂度类。
P(多项式时间):所有能在多项式时间内判定的语言的集合。即 P = ∪_k TIME(n^k)。
将多项式时间作为“高效”的标准,主要出于方便和鲁棒性。几乎所有合理的数字计算机模型都会产生相同的 P 类,因为不同模型之间可以用多项式时间开销相互模拟。此外,多项式在加法、乘法和复合下封闭,这个性质在规约和算法组合时非常有用。
扩展的丘奇-图灵论题认为,任何现实物理手段所能高效计算的问题,都与图灵机上的 P 类一致。这是一个关于物理世界的可证伪的 empirical claim。它断言,你无法建造一个能高效解决 P 类之外问题的物理设备。
一些看似能突破此论题的科幻想法(如相对论计算机、芝诺计算机),在综合考虑所有物理定律(如能量需求、量子效应、广义相对论)后,都被认为不可行。然而,量子计算可能是一个例外。如果量子计算机确实能够建造,那么扩展丘奇-图灵论题就需要被修订为“量子多项式时间”是极限。这是一个深刻的物理问题。
PSPACE(多项式空间):所有能在多项式空间内判定的语言的集合。即 PSPACE = ∪_k SPACE(n^k)。
EXP(指数时间):所有能在指数时间内判定的语言的集合。即 EXP = ∪_k TIME(2(nk))。
需要注意它的一个近亲 E = ∪_k TIME(2^(kn)),它只允许 2^(O(n)) 时间,而不允许 2^(n²) 这样的时间。
我们还可以定义 EXPSPACE = ∪_k SPACE(2(nk)) 等类。
以下是这些类之间的已知包含关系:
- P ⊆ PSPACE:因为 TIME(n^k) ⊆ SPACE(n^k),所以 P ⊆ PSPACE。
- PSPACE ⊆ EXP:因为 SPACE(F(n)) 中的机器可能进入的状态数约为 2^O(F(n)),所以 SPACE(F(n)) ⊆ TIME(2^O(F(n)))。因此,多项式空间的问题可以在指数时间内解决,即 PSPACE ⊆ EXP。
- P ⊂ EXP:由时间层次定理可知,P 是 EXP 的真子集。
然而,一些关键问题仍然是开放的:
- P vs. PSPACE:是否 P = PSPACE?我们相信 P ≠ PSPACE,但无人能证明。证明这一点与证明 P ≠ NP 同样困难。
- PSPACE vs. EXP:是否 PSPACE = EXP?同样,我们相信不相等,但无法证明。
我们知道至少有一个包含关系是严格的(因为 P ⊂ EXP),但无法确定是哪一个(或两个都是)。大多数研究者猜想三者互不相同:P ⊂ PSPACE ⊂ EXP。
填充技术
我们可以证明,这些类之间的“塌缩”可以向上传递。例如,如果 P = PSPACE,那么 EXP = EXPSPACE。
证明使用了一种称为填充的技术。假设 L 是一个 EXPSPACE 语言(例如,在 2(nk) 空间内可判定)。我们构造一个新语言 L‘,它将每个 L 中的串 x 填充上 2(|x|k) 个零。那么:
- L‘ 在 PSPACE 中:因为要判定 x000...,我们只需要忽略尾部的零,对 x 运行原来的 2(nk) 空间算法。现在输入长度 N ≈ 2(nk),所以使用的空间是 2(nk) = O(N),即线性空间,故 L‘ ∈ PSPACE。
- 根据假设 P = PSPACE,所以 L‘ ∈ P。
- 那么 L 就在 EXP 中:要判定 x 是否属于 L,我们只需先自己将 x 填充到长度 2(nk),然后运行判定 L‘ 的多项式时间算法。该算法的运行时间是填充后长度 N 的多项式,即 poly(2(nk)),这仍然是指数时间,所以 L ∈ EXP。
因此,从 P = PSPACE 推出了 EXP = EXPSPACE。这个技巧展示了如何将低层次的复杂性结论“放大”到高层次。
总结
本节课中,我们一起学习了:
- 时间层次定理的正式表述及其依赖的“时间可构造性”条件。
- 空间层次定理,以及复杂性中的困难往往源于比较不同资源。
- Blum 加速定理,它展示了存在没有“最快”算法的人工问题。
- 几个核心复杂度类:P(多项式时间)、PSPACE(多项式空间)、EXP(指数时间)的定义和直观含义。
- 扩展的丘奇-图灵论题,及其面临的潜在挑战(如量子计算)。
- 这些复杂度类之间的包含关系(P ⊆ PSPACE ⊆ EXP),以及哪些是已知严格的(P ⊂ EXP),哪些是重大开放问题(P vs. PSPACE, PSPACE vs. EXP)。
- 填充技术,它可以将低层次类的等价性推导到高层次类的等价性(例如,P = PSPACE ⇒ EXP = EXPSPACE)。
下节课,我们将运用填充技术进行更多推导,并开始讨论 P、NP、NP 完全性 以及著名的 P vs. NP 问题。
012:非确定性、NP类与P vs NP问题
在本节课中,我们将学习非确定性图灵机的概念,并由此定义出计算复杂性理论中一个核心的类:NP(非确定性多项式时间)。我们将探讨NP的两种等价定义,并通过大量实例理解其内涵。最后,我们将触及计算机科学中最著名的开放性问题:P是否等于NP。
课程提醒与回顾
上一节我们介绍了复杂性类P、PSPACE和EXPSPACE,以及时间与空间层次定理。我们还讨论了“填充”技术,它能将低层复杂性类的不等式结论推广到更高层。
本节中,我们来看看非确定性如何被引入到复杂性理论中。
以下是本节课开始前的一些课程事务提醒:
- PSet 3的截止日期是明天。
- PSet 2可以在下课时领取。
- 期中考试将在春假后的周四举行。在PSet 3之后,我们会发布一份模拟试题,并安排至少一次由助教主持的复习课。
利用填充技术证明P ≠ LINSPACE
首先,我们展示一个使用填充技术的具体例子,来证明P不等于线性空间(LINSPACE)。这是一个我们可以严格证明的结论,但其结论本身有些奇特。
定理:P ≠ LINSPACE。
证明思路:我们采用反证法。假设P = LINSPACE,然后推导出矛盾。具体步骤如下:
- 假设:P = LINSPACE。
- 推导包含关系:
- 显然,P ⊆ PSPACE(多项式时间使用的空间不超过多项式量级)。
- 关键在于证明PSPACE ⊆ P。我们利用填充技术来实现这一点。
- 取任意一个属于PSPACE的语言L,即L可在多项式空间(比如
n^2空间)内判定。 - 构造一个新的语言L‘,它是L的“二次填充”版本:
L' = { (x, 0^{|x|^2}) | x ∈ L } - 对于L‘,输入长度是
|x| + |x|^2。由于L本身在|x|^2空间内可判定,那么判定L‘只需要空间与|x|成正比,即线性于L‘的输入长度。因此,L‘ ∈ LINSPACE。 - 根据假设P = LINSPACE,可得L‘ ∈ P。即存在多项式时间算法判定L‘。
- 现在,要判定原始输入x是否属于L,我们只需构造填充串
(x, 0^{|x|^2}),然后用判定L‘的多项式时间算法运行它。这个过程的运行时间是输入(x, 0^{|x|^2})长度的多项式,也就是|x|^2的多项式,因此是|x|的多项式。所以,L ∈ P。
- 取任意一个属于PSPACE的语言L,即L可在多项式空间(比如
- 由此,我们证明了如果P = LINSPACE,那么PSPACE ⊆ P。
- 得出矛盾:
- 结合P ⊆ PSPACE和PSPACE ⊆ P,我们得到P = PSPACE。
- 进一步,由于LINSPACE ⊆ PSPACE且假设P = LINSPACE,可推出LINSPACE = PSPACE。
- 但这与空间层次定理矛盾,该定理指出对于空间可构造函数,更小的空间复杂度类严格包含于更大的类中(例如,LINSPACE ⊊ PSPACE)。
- 结论:因此,最初的假设P = LINSPACE不成立,即P ≠ LINSPACE。
这个证明的奇妙之处在于,它并没有告诉我们P中是否存在LINSPACE无法解决的问题,或者反之。它只证明了这两个类不可能相等,至少有一个类不包含于另一个之中。
非确定性图灵机与NP类
现在,我们将非确定性引入场景。首先定义非确定性图灵机。
非确定性图灵机
一台非确定性图灵机在概念上类似于之前课程中学过的非确定性有限自动机,但功能更强大。与确定性图灵机不同,在计算过程中的任何一步,它可能有多个可供选择的下一步动作(包括写入的符号、移动方向、下一状态)。
接受条件:一台非确定性图灵机接受一个输入串,当且仅当存在至少一条由该输入引导的、最终进入“接受状态”的计算路径。即使存在其他导致拒绝的路径,只要有一条接受路径即可。
非确定性时间复杂性类
基于此,我们可以定义非确定性时间复杂性类。
定义:NTIME(f(n)) 是所有能被一台非确定性图灵机在 O(f(n)) 时间内判定的语言的集合。这里要求所有计算路径都在 c * f(n) 步内停机,其中c是常数。
显然,确定性图灵机是非确定性图灵机的特例(只需忽略非确定性选择即可),因此有:
TIME(f(n)) ⊆ NTIME(f(n))
NP类:非确定性多项式时间
最重要的非确定性复杂性类是NP。
定义(基于非确定性图灵机):
NP = ∪_{k} NTIME(n^k)
即,NP是所有能在非确定性多项式时间内判定的语言的集合。
NP的等价定义:可验证性
NP的定义看似抽象,但它有一个极其重要且直观的等价定义,这解释了为何NP类如此核心。
定义(基于验证器):
一个语言L属于NP,如果存在一个多项式时间图灵机V(称为验证器)和一个多项式p,满足以下两个条件:
- 完备性:如果x ∈ L,那么存在一个称为“证据”或“证明”的字符串w,其长度满足
|w| ≤ p(|x|),使得验证器V在输入(x, w)上接受。 - 可靠性:如果x ∉ L,那么对于所有字符串w(
|w| ≤ p(|x|)),验证器V在输入(x, w)上都拒绝。
直观理解:NP是那些“答案是‘是’的问题可以被高效验证”的语言的集合。给定一个问题和一份声称是答案的“证据”(例如,一个解、一个证明),我们可以在多项式时间内检查这个证据是否正确。
两种定义的等价性证明
- 从验证器到非确定性图灵机:如果L有一个多项式时间验证器V,我们可以构造一个非确定性图灵机N来判定L。N首先非确定性地“猜测”一个长度不超过p(|x|)的证据字符串w,然后模拟验证器V在
(x, w)上的运行。根据完备性和可靠性,N接受当且仅当x ∈ L。 - 从非确定性图灵机到验证器:如果L能被一个非确定性多项式时间图灵机N判定,那么我们可以将证据w定义为导致N接受的计算路径的描述。验证器V接收
(x, w),然后模拟N,严格遵循路径w的描述进行每一步操作。如果该路径在多项式步内引导至接受状态,则V接受。由于接受路径长度是多项式的,其描述w也是多项式长度,且验证过程是确定性的多项式时间。
NP问题的例子
理解NP的最好方式是通过例子。以下是众多NP问题中的一部分,它们都共享“容易验证解”的特性。
以下是几个经典的NP问题:
- 整数分解相关:语言
{ (n, d) | n 有一个以7结尾的因子d }。证据就是因子d本身。 - 图同构:语言
{ (G, H) | 图G与图H同构 }。证据是一个从G顶点到H顶点的映射(同构函数)。 - 电路可满足性:语言
{ C | 布尔电路C存在一组输入使其输出为1 }。证据是那组使电路输出1的输入。 - 最小电路规模问题:语言
{ (f, k) | 布尔函数f(由其真值表给出)存在一个规模不超过k的电路 }。证据就是那个规模不超过k的电路。 - 图三着色:语言
{ G | 图G的顶点可以用三种颜色着色,使得任意相邻顶点颜色不同 }。证据是一种具体的着色方案。 - 哈密顿回路:语言
{ G | 图G包含一个经过每个顶点恰好一次并回到起点的回路 }。证据是哈密顿回路本身。 - 子集和问题:语言
{ (a1, a2, ..., an, k) | 存在一个子集,其元素之和等于k }。证据是所选子集。 - 装箱问题:给定一堆盒子和一个行李箱的尺寸,判断是否能将所有盒子装入行李箱。证据是一种具体的装箱方案。
- 数独:给定一个n×n的数独盘面,判断是否可解。证据是一个完整的解。
注意:并非所有难题都在NP中。例如,判断一个国际象棋残局(推广到n×n棋盘)中白方是否有必胜策略,这涉及到交替量词(“存在白方的一步,使得对于黑方的所有应对,存在白方的下一步...”),其证据可能是指数大小的博弈树,因此该问题被认为不属于NP(实际上是PSPACE完全的)。同样,Presburger算术(只允许加法的整数逻辑)的真值判定问题是可判定的,但已知不在NP中。
NP在复杂性类图谱中的位置
我们现在知道P ⊆ NP,因为确定性算法可以直接作为非确定性算法(不利用猜测能力)。那么NP包含于哪些类呢?
- NP ⊆ PSPACE:要判定一个NP语言,我们可以枚举所有可能的多项式长度证据w,对每个w用验证器检查。虽然这需要指数时间(
2^{p(n)}),但每次检查只需多项式空间,并且检查完一个证据后可以重用空间检查下一个。因此,整个算法只需多项式空间。 - 结合之前的知识,我们有:
P ⊆ NP ⊆ PSPACE ⊆ EXPTIME。 - 根据时间层次定理,我们知道
P ⊊ EXPTIME。因此,上述包含链中至少有一个是严格的(我们相信三者都是严格的,但只能证明至少有一个)。
P vs NP 问题
现在,我们来到计算复杂性理论,乃至整个计算机科学中最核心的未解问题:
P是否等于NP?
用通俗的语言说,这个问题问的是:如果一个问题(的正面答案)可以高效地验证,那么它是否也能高效地求解?
- 如果 P = NP,那将意味着所有具有简短可验证证明的问题(包括上述所有例子)都能在多项式时间内找到解。这将彻底改变世界,从破解密码、优化物流,到自动化数学发现和创造性设计。
- 如果 P ≠ NP(这是大多数研究者的信念),则意味着存在这样一类问题,验证其解容易,但找到解本质上是困难的。
这个问题最早由库克(Stephen Cook)在1971年形式化提出,但类似的思想更早出现。值得注意的是,哥德尔(Kurt Gödel)在1956年写给冯·诺依曼(John von Neumann)的一封信中,就已经清晰地阐述了这个问题及其潜在的革命性意义——即机器有可能在多项式时间内找到数学定理的有限长度证明,从而在某种程度上替代数学家的心智劳动。
总结
本节课中我们一起学习了:
- 非确定性图灵机的概念,它允许计算路径在每一步进行“猜测”。
- 复杂性类NP的两种等价定义:基于非确定性多项式时间图灵机,以及基于多项式时间验证器。
- 大量NP问题的实例,它们都具有“解容易验证”的共同特征。
- NP在复杂性类图谱中的基本位置关系:
P ⊆ NP ⊆ PSPACE。 - 计算机科学的标志性开放问题:P vs NP问题,探讨了可验证性与可求解性之间的根本关系。
理解NP是深入学习计算复杂性理论,特别是NP完全性理论的基础。下一讲中,我们将探讨NP完全问题的概念,这是理解P vs NP问题为何如此困难的关键。
013:NP完全性理论
在本节课中,我们将学习NP完全性理论,这是P与NP问题故事中的一个关键环节。我们将首先回顾P与NP问题的背景和重要性,然后深入探讨多项式时间归约的概念,并最终定义和证明NP完全问题的存在。我们将通过一个简单的例子开始,然后逐步构建,最终证明著名的3SAT问题是NP完全的。
P与NP问题回顾
上一节我们定义了P与NP问题。P类包含所有能在多项式时间内被确定性图灵机判定的语言。NP类则包含所有能在多项式时间内被验证的语言,即存在一个多项式时间验证器,对于语言中的每个字符串,都存在一个多项式大小的“证明”(或“见证”),使得验证器接受。
核心问题是:P = NP 是否成立?换句话说,是否每一个能高效验证解的问题,也能被高效地找到解?大多数计算机科学家相信 P ≠ NP,因为如果P等于NP,将意味着存在一种通用、高效的方法来解决大量极其困难的计算问题,这听起来“好得令人难以置信”。
NP完全性简介
本节中,我们将探讨NP完全性理论。这是一个关键概念,它帮助我们理解NP类中哪些问题是最困难的。如果一个NP问题是“NP完全的”,那么从某种意义上说,它至少和NP类中的任何其他问题一样难。证明一个问题是NP完全的,是表明其计算困难性的有力方式。
为了定义NP完全性,我们首先需要“多项式时间归约”的概念。
多项式时间归约
在可计算性理论单元中,我们学习了图灵归约和“多一”归约。现在,我们将这些概念限制在多项式时间内。
- 多项式时间图灵归约:语言A可多项式时间图灵归约到语言B(记作 A ≤ₚᴛ B),如果存在一个带预言机(oracle)B的多项式时间图灵机可以判定A。这意味着,如果我们有一个能高效解决B的子程序,我们就能高效解决A。
- 形式化:若 A ∈ Pᴮ(即在多项式时间内,借助B的预言机可判定A),则 A ≤ₚᴛ B。
- 多项式时间多一归约:语言A可多项式时间多一归约到语言B(记作 A ≤ₚᴍ B),如果存在一个多项式时间可计算的函数f,使得对于所有输入x,有:x ∈ A 当且仅当 f(x) ∈ B。
- 这比图灵归约更强,因为它要求将A的实例直接映射到B的实例。
一个重要性质是:如果 A ≤ₚᴍ B,那么 A ≤ₚᴛ B 也成立。但反过来不一定成立。
NP困难与NP完全的定义
利用归约的概念,我们可以定义问题的“硬度”。
- NP困难(图灵归约下):语言L是NP困难的,如果NP中的每一个语言L‘都可以多项式时间图灵归约到L。即,NP ⊆ Pᴸ。这意味着L至少和NP中的任何问题一样难。
- NP完全:语言L是NP完全的,如果它同时满足:
- L ∈ NP(L本身是NP问题)。
- L是NP困难的(所有NP问题都可归约到它)。
NP完全问题是NP类中“最难”的问题。如果任何一个NP完全问题能在多项式时间内解决(即属于P),那么NP中的所有问题都能在多项式时间内解决,从而证明 P = NP。
第一个NP完全问题:D问题
从定义出发,我们首先需要证明至少存在一个NP完全问题。我们构造一个看似平凡但符合定义的问题,称为D问题。
D问题定义:
输入是一个三元组 <M, 0ⁿ, 0ᵗ>,其中M是一个图灵机的描述,n和t是用一元制(即一串0)表示的数字。
问:是否存在一个长度为n的比特串w,使得图灵机M在输入w上在最多t步内进入接受状态?
- 为什么D ∈ NP? 如果三元组属于D,那么见证w就是那个使M接受的n比特串。验证器只需模拟M运行t步,检查它是否接受。由于t以一元制给出,模拟时间是t的多项式(实际上是线性的),因此验证是多项式时间的。
- 为什么D是NP困难的? 设L是任意一个NP语言。根据NP定义,存在一个多项式时间验证器V和一个多项式p(n),使得对于长度为n的输入x,其见证长度不超过p(n),且验证时间不超过某个多项式q(n)。我们的归约函数f将输入x映射到
<Mₓ, 0ᵖ⁽ⁿ⁾, 0ᵠ⁽ⁿ⁾>,其中Mₓ是将x硬编码(hard-code)进验证器V后得到的图灵机。那么,x ∈ L 当且仅当 存在见证w使得Mₓ在p(n)步内接受w 当且仅当<Mₓ, 0ᵖ⁽ⁿ⁾, 0ᵠ⁽ⁿ⁾> ∈ D。这个归约显然是多项式时间的。
因此,D问题是NP完全的。虽然它不“有趣”,但它作为一个起点至关重要。
证明更多NP完全问题:归约链
一旦我们有了一个NP完全问题(如D),我们就可以通过归约来证明其他问题是NP完全的。关键原理如下:
传递性原理:如果已知语言L是NP完全的,并且我们证明 L ≤ₚᴍ L‘(或 L ≤ₚᴛ L’),且 L‘ ∈ NP,那么L’也是NP完全的。
- 原因:因为L是NP困难的,任何NP问题都可归约到L。又因为L可归约到L‘,根据归约的传递性,任何NP问题都可归约到L’。所以L‘是NP困难的,又已知L’ ∈ NP,故L‘是NP完全的。
这就像邀请制:第一个问题(D)由定义直接获得资格,之后的问题需要由一个已获资格的问题“邀请”进来。
库克-列文定理:3SAT是NP完全的
我们将通过一个归约链来证明著名的布尔可满足性问题(SAT)的变体——3SAT是NP完全的。链式结构如下:
D ≤ₚᴍ CIRCUIT-SAT ≤ₚᴍ 3SAT
第一步:D ≤ₚᴍ CIRCUIT-SAT
CIRCUIT-SAT(电路可满足性问题)定义:
输入是一个布尔电路的编码(由AND、OR、NOT门组成)。
问:是否存在一组对电路输入线的赋值(0或1),使得电路的输出为1?
- 思路:我们需要将图灵机M在时间t内是否有接受计算的问题,转化为一个电路是否有满足赋值的问题。
- 构造:
- 因为M的运行时间和空间都被t多项式限制,我们可以用一张
t × t的“时空表格”来描述整个计算过程。表格的每一行代表一个时间步,每一列代表磁带上的一个格子。 - 我们为表格中的每个位置定义布尔变量:
X[i][t]:在时间t,第i个磁带格子是否为1。H[j][t]:在时间t,读写头是否在第j个格子。Q[s][t]:在时间t,图灵机状态是否为s。
- 根据图灵机的转移函数,时间t+1的变量值可以由时间t的变量值通过一组固定的布尔逻辑公式确定(例如,“如果读写头不在格子i,则
X[i][t+1]的值等于X[i][t];否则,由当前状态和当前符号决定写入0还是1”)。这些逻辑关系可以用AND、OR、NOT门构成的子电路来实现。 - 将所有这些子电路按照时间顺序连接起来,形成一个大的组合电路。电路的初始输入是见证w的各个比特(
X[i][0]),以及初始为0的磁带格子(可简化为常量0)。电路的最终输出是变量Q[accept][t](是否在最终时间进入接受状态)。
- 因为M的运行时间和空间都被t多项式限制,我们可以用一张
- 结论:这样构造的电路是可满足的(存在一组输入w使其输出1),当且仅当原始的图灵机M存在一个长度为n的见证w使其在t步内接受。这个构造过程是多项式时间的。因此,D ≤ₚᴍ CIRCUIT-SAT。又因为CIRCUIT-SAT显然属于NP(见证就是满足赋值),所以CIRCUIT-SAT是NP完全的。
第二步:CIRCUIT-SAT ≤ₚᴍ 3SAT
3SAT定义:
输入是一个由若干子句(clause)构成的合取范式(CNF)布尔公式φ,且每个子句恰好包含三个文字(变量或其否定)。
问:是否存在一组对变量的真值赋值,使得公式φ为真(即所有子句都为真)?
- 思路:将电路“模拟”成一组3SAT子句。电路中的每个逻辑门都对应一个或几个3SAT子句,这些子句共同约束该门的输出与输入之间的关系。
- 构造:
- 为电路中每条线(包括输入、输出和内部门之间的连线)引入一个布尔变量。
- 对于每个逻辑门,添加一组子句来刻画其功能。例如,对于一个AND门
y = x₁ AND x₂,我们需要子句来排除y ≠ (x₁ AND x₂)的所有情况:(¬x₁ ∨ ¬x₂ ∨ y)// 如果x1和x2都是1,y必须是1。(x₁ ∨ ¬y)// 如果y是1,x1不能是0。(x₂ ∨ ¬y)// 如果y是1,x2不能是0。(¬x₁ ∨ ¬x₂ ∨ ¬y)是冗余的,因为前三个子句已足够。实际上,对于AND门,可以用更少的子句精确编码。
- 对于输出线
z(对应整个电路的输出),添加一个单文字子句(z),要求它必须为真。 - 对于NOT门等,也可以用类似方式编码。
- 结论:这样构造出的3SAT公式φ是可满足的,当且仅当原始电路是可满足的。每个门只引入常数个子句,所以整个构造是多项式时间的。因此,CIRCUIT-SAT ≤ₚᴍ 3SAT。由于CIRCUIT-SAT是NP完全的,且3SAT ∈ NP,所以3SAT也是NP完全的。
总结
本节课中,我们一起学习了NP完全性理论的核心内容。
- 我们首先回顾了P与NP问题的意义,并指出大多数研究者相信P ≠ NP。
- 接着,我们引入了多项式时间归约(图灵归约和多一归约)的概念,这是比较问题计算难度的关键工具。
- 利用归约,我们定义了NP困难和NP完全:NP完全问题是NP类中最难的问题,所有NP问题都能归约到它。
- 我们构造了第一个(虽然不实用但符合定义的)NP完全问题——D问题。
- 我们学习了证明新问题是NP完全的核心方法:通过从已知的NP完全问题(如D)进行多项式时间归约。
- 最后,我们沿着 D → CIRCUIT-SAT → 3SAT 的归约链,概述了库克-列文定理的证明思想,从而确立了3SAT作为第一个“有趣的”NP完全问题的地位。
NP完全性理论的重要性在于,它为我们提供了数千个彼此等价的“最难”计算问题的例子。证明一个新问题是NP完全的,通常意味着寻找其精确、高效的通解是极其困难的(除非P=NP)。在接下来的课程中,我们将看到更多NP完全问题的例子,并探索这一理论的应用。
014:NP完全性(续)与应对策略
在本节课中,我们将继续探讨NP完全性这一核心主题。我们将回顾证明问题NP完全性的基本方法,并通过一个具体的例子(三着色问题)来演示如何构造归约。随后,我们将讨论当在实际中遇到NP完全问题时,可以采取哪些策略来应对。
回顾:证明NP完全性的基本路径
上一节我们介绍了NP完全性的概念以及通过归约证明问题NP完全性的思路。本节中,我们来看看证明NP完全性的一个经典路径。
首先,我们从一个“通用”的NP完全问题出发,即通用图灵机接受问题。库克-列文定理的核心贡献在于,它通过模拟图灵机的每一步计算,将这个问题归约到了电路可满足性问题。这意味着,给定任何图灵机,我们都能在多项式时间内构造一个电路,使得该电路可满足当且仅当存在输入使该图灵机在多项式步内接受。
一旦我们证明了电路可满足性是NP完全的,就可以将其作为起点,归约到其他结构更简单、更像组合优化问题的问题上。一个关键的步骤是证明3-SAT问题是NP完全的。
以下是证明3-SAT是NP完全的核心思路:
- 电路扁平化:3-SAT可以看作是电路可满足性的一种特殊、扁平化的形式。电路中的每个逻辑门(与、或、非)都涉及少量输入和输出。
- 引入辅助变量:为了将任意电路“扁平化”为一组三元子句,我们为电路中每个门的输出引入一个新的变量。
- 编码逻辑约束:对于每个逻辑门,我们可以用一组至多包含三个变量(或它们的否定)的子句来编码其输入输出关系。例如,一个“与门”输出
y,输入为x1和x2,我们可以用四个子句来确保y = x1 ∧ x2的关系成立。
通过这种方式,我们得到了一个3-SAT实例,它是可满足的当且仅当原始电路是可满足的。由于3-SAT具有非常规整的结构(仅包含三元子句),它成为了后续证明其他问题NP完全性的一个非常方便的起点。
示例:证明三着色问题是NP完全的
现在,我们来看一个具体的例子:证明三着色问题是NP完全的。三着色问题是指:给定一个图(可以看作地图,顶点代表区域,边代表相邻关系),问是否能用三种颜色为所有顶点着色,使得任意一条边两端的顶点颜色不同。
首先,很容易证明三着色问题属于NP类,因为一个有效的着色方案本身就可以作为验证的证书。
接下来,我们需要证明它是NP难的。为此,我们选择一个已知的NP完全问题,并将其归约到三着色问题。这里我们选择从电路可满足性问题进行归约。我们的目标是:给定一个电路,构造一个图,使得该图是三着色的当且仅当该电路是可满足的。
步骤一:建立颜色“调色板”
三着色问题具有对称性(三种颜色可以任意置换),但电路逻辑没有这种对称性。因此,我们首先需要打破对称性,建立固定的颜色含义。
我们构造三个特殊的顶点,形成一个三角形,迫使它们必须被涂上三种不同的颜色。我们将这三种颜色分别命名为 T(真)、F(假) 和 N(中性)。
T
/ \
N---F
步骤二:创建布尔变量
要模拟电路,我们需要布尔变量。我们可以创建一个顶点,并将其连接到中性顶点 N。由于它不能与 N 同色,这个顶点的颜色只能是 T 或 F。这样,我们就得到了一个可以代表 True 或 False 的变量顶点,例如 x1。
T
/ \
N---F
\
x1 (必须为 T 或 F)
步骤三:构建逻辑门“ gadget ”
这是归约的核心:我们需要用图的连接关系来模拟与、或、非门的逻辑。
-
非门:要得到
¬x1,我们创建一个新顶点,将其同时连接到x1和N。这个新顶点不能与x1同色,也不能与N同色,因此它的颜色必须是x1的相反值。x1 ---- (¬x1) | | N-------N (连接回调色板) -
与门:构造一个模拟
y = x1 ∧ x2的与门更为复杂。我们需要一个结构,使得中心顶点y只有在x1和x2都为T时才为T,其他情况均为F。这需要通过精心设计顶点和边的连接来实现,并可能引入一些辅助顶点来打破对称性,处理x1=T, x2=F等情况。虽然构造细节繁琐,但可以证明这样的结构是存在的。
一旦我们拥有了与非门,根据德摩根定律,我们就可以构造出或门。由于 {与, 非} 是功能完备的,我们可以用它们模拟任何布尔电路。
步骤四:连接电路并指定输出
按照给定电路的逻辑,用上述“ gadget ”将变量顶点和门顶点连接起来。最后,对于电路的输出顶点,我们将其连接到 F 和 N,强制要求输出顶点必须为 T(即可满足)。
通过以上构造,我们得到了一个图。根据构造过程,该图是三着色的,当且仅当存在一组对原始电路输入变量的赋值,使得电路输出为真(即可满足)。这个构造过程显然是多项式时间的。因此,我们成功地将电路可满足性问题归约到了三着色问题,从而证明了三着色是NP完全的。
应对NP完全问题的策略
既然许多实际问题都是NP完全的,那么在实践中遇到它们时,我们该怎么办?以下是一些常见的策略:
1. 接受并采用非精确算法
对于规模不大的实例,直接使用暴力搜索或更智能的回溯搜索(在搜索过程中利用约束进行剪枝)可能是可行的。虽然最坏情况下是指数时间,但对于许多实际实例可能足够快。
2. 使用启发式算法或不完全算法
这类算法不保证找到最优解或证明无解,但旨在有限时间内找到一个“足够好”的解。
- 局部搜索:如模拟退火、遗传算法。从一个随机解开始,不断进行局部改进,有时允许暂时“下山”以避免陷入局部最优。
- 贪心算法:在每一步做出当前看起来最优的选择。
3. 寻找近似算法
放弃寻找最优解,转而寻找在可证明的范围内接近最优的解。不同NP完全问题的可近似性差异很大。
- 正面例子:欧几里得平面上的旅行商问题存在多项式时间近似方案,对于任意小的
ε>0,都可以在多项式时间内找到不超过最优解(1+ε)倍的环游路线。 - 反面例子:对于3-SAT问题,随机赋值平均能满足
7/8的子句。而著名的 PCP定理 表明,任何多项式时间算法想保证满足比7/8更多比例的子句都是不可能的(除非P=NP)。这标志着一个尖锐的阈值。
4. 利用问题的特殊结构
实际遇到的问题实例可能具有特殊结构,使其不再困难。
- 参数化算法:如果问题的“难度”可以被某个参数
k(如树宽)控制,且在实际中k很小,那么可能存在时间复杂度为O(f(k) * n^c)的算法,对于小k是高效的。 - 特殊情况:例如,一般的图三着色是NP完全的,但二分图(2-可着色) 的判定可以在线性时间内解决。确保你的问题没有意外地落在某个容易的特殊情况中。
5. 重新审视问题定义
有时,NP完全性是一个信号,表明你要求解的问题可能过于泛化。是否可以接受一个更弱但可高效求解的问题变体?是否可以利用领域知识增加一些限制条件?
关于其他“捷径”的说明
- 量子计算:目前没有证据表明量子计算机能在多项式时间内解决NP完全问题。它可能提供指数级加速,但并未改变问题的复杂度类别。
- 生物/物理计算:诸如蛋白质折叠可以解决其对应的NP完全模型的说法,通常被解释为自然界巧妙地避开了该问题中最困难的那些实例,而非真正解决了通用的NP完全问题。
总结
本节课中我们一起学习了:
- 证明NP完全性的经典路径:从通用问题归约到电路可满足性,再到3-SAT,最后以3-SAT为起点证明其他问题。
- 一个具体的归约示例:通过构造“调色板”和逻辑门“gadget”,将电路可满足性问题归约到三着色问题,从而证明后者是NP完全的。
- 应对NP完全问题的多种策略:包括使用智能搜索、启发式算法、近似算法、利用问题特殊结构以及重新定义问题。理解这些策略有助于我们在实际中面对计算难题时做出合理的选择。
NP完全性理论不仅告诉我们哪些问题可能是难以高效解决的,也指引我们去探索近似、随机化和参数化等丰富的算法设计领域。
015:NP完全性、coNP与物理系统
在本节课中,我们将继续探讨NP完全性,并引入一个重要的新概念——coNP。我们将看到,并非所有我们感兴趣的难题都是NP完全的,并理解为什么像因数分解这样的问题被认为不属于NP完全类。此外,我们还将探讨NP完全问题与物理系统(如肥皂泡)之间的关系,并简要介绍“相对化”这一概念,它解释了为何P与NP问题如此难以解决。
从肥皂泡实验说起
上一节我们介绍了NP完全性归约,并讨论了如何在实际中应对NP完全问题。本节中,我们来看看一个有趣的历史观点:是否存在能自动解决NP完全问题的物理系统?
有时人们声称,例如蛋白质折叠这样的物理系统可以做到这一点。但我对此表示怀疑,这些系统很可能只是执行了类似局部优化的启发式算法,在实践中效果良好,但我们很容易构造出导致其失败的案例。证明黎曼猜想或破解RSA密码很可能就是这类难题的案例。
这里有一个来自上世纪六七十年代的有趣想法:使用肥皂泡高效解决NP完全问题。其设想是:取两块玻璃板,在其间按任意构型放置一些图钉。然后将这个装置浸入肥皂水中再取出,肥皂泡会以某种方式连接这些图钉。气泡倾向于最小化其表面积。因此,它们会尝试以最小化连接所有图钉所需线段总长度的方式连接。
这引出了一个难题:如果给定欧几里得平面上的一组点,寻找连接所有这些点的线段的最小总长度(允许线段在没有图钉的中间点交汇),这是一个已知的NP难问题,称为最小斯坦纳树问题。如果线段不允许在中间点交汇,那就是最小生成树问题,存在多项式时间算法。然而,将图钉装置浸入肥皂水,大自然似乎解决了最小斯坦纳树问题。这是否意味着肥皂水能做到超级计算机做不到的事?
互联网上对此有过讨论,许多人持怀疑态度,认为它可能只是陷入局部最优解,就像许多其他物理系统一样。例如,一块石头可能位于山腰的裂缝中,它需要先滚上去再滚下来才能达到更低的势能状态,但我们很少观察到这种情况。因此,为什么不能假设这个肥皂泡系统也会陷入局部最优呢?
有人反驳说这只是计算机科学界的固有观点,并质疑是否有人真正做过实验。这促使我进行了一次实验物理探索。我搭建了装置并进行了测试。使用三到五个图钉时,通常能找到最小斯坦纳树,这非常酷。但当你开始添加更多图钉,比如六七个时,就可能得到次优解,甚至可能出现中间循环(气泡圈)。如果出现循环,就证明这不是最优解,因为循环总是可以收缩以减少线段总长度。所以,大自然确实非常善于最小化其存储的势能,但在很多情况下,它也可能陷入势能的局部最优。这几乎是所有试图解决NP完全问题的启发式方法都会遇到的难题。
在课程最后,我们会简要讨论量子计算。早期人们希望量子计算能通过量子隧穿等效应克服陷入局部最优的问题。但现在我们认为,即使对于量子计算机,某些NP完全问题案例可能仍然非常困难。
我们甚至可以设想,NP完全问题的困难性是物理世界的一个基本事实,或许我们应该将其作为一个约束条件来寻找物理理论。但这只是一种推测。归根结底,这是一个实证问题。我每个月左右都会收到一些人声称可以解决NP完全问题,这比声称证明P≠NP的人要多。对于前者,你只需说:太好了,这里有一个3000位的数字,请把它的因数发给我,然后我们再详谈。通常之后你就不会再收到他们的回复了。
引入coNP:NP的“邪恶双胞胎”
但并非所有我们感兴趣的NP难题都被认为是NP完全的。为了解释这一点,我们需要在P和NP的故事上增加一个新的概念:coNP。
coNP是NP的伴侣或“邪恶双胞胎”。它的定义是:包含NP中每一个语言的补集的语言类。语言L的补集(L-complement)是不在L中的字符串集合。因此,对于NP中的每一个语言,其补集在coNP中。
另一种定义方式是:coNP是所有满足“当答案为‘否’时存在短证书”的语言的集合。这个证书可以高效验证。请注意,NP的定义在“是”和“否”答案之间存在根本的不对称性:对于“是”的答案需要有短证书,但对于“否”的答案则不需要。coNP只是颠倒了这个故事,要求“否”的答案需要有证书。
就像我们定义NP难和NP完全问题一样,我们也可以定义coNP难和coNP完全问题。以下是一些coNP完全问题的例子:
- 非可满足性问题:给定一个布尔公式(例如3SAT公式),问这个公式是否不可满足?如果答案是“否”(即可满足),那么短证书就是一个可满足赋值。如果答案是“是”(即不可满足),则短证书并不明显。
- 非三色性问题:给定一个图,问这个图是否不可三着色?
- 子集和问题的补集:给定一组整数和一个目标值,问是否不存在一个子集的和等于该目标值?
coNP在很多方面表现得像NP。特别地,如果P = NP,那么必然也有P = coNP。因为P类在补集下是封闭的(只需交换接受和拒绝状态),没有像NP那样的内置不对称性。因此,如果P = NP,那么P = NP = coNP。
但有趣的是,其逆命题并不明显。假设NP = coNP,这会意味着P = NP吗?至今无人知道这样的蕴含关系。就我们所知,即使P ≠ NP,NP仍可能等于coNP。
如果NP等于coNP,那将意味着什么?那将意味着总是存在布尔公式不可满足性的短证明。这个证明可能仍然很难找到(因为在我们假设的世界里P ≠ NP),但一旦你找到了它,你就可以检查这个证明并同意该公式不可满足。这不像P = NP那么惊人,因为它不是说你能找到这个证明,但它仍然有点令人惊讶,因为它意味着有人可以给你一个证书,你检查后就能同意这个指数级难度的搜索问题没有解。
P、NP、coNP与NP完全的关系图
为了更清晰地理解,让我们画一张关系图。
这是我们之前知道的:我们有P和NP。NP难问题与NP的交集是NP完全问题。
现在,我们说NP也有它的“邪恶双胞胎”coNP。coNP与NP难的交集我们称之为coNP完全问题。
对于每一个NP完全问题,都有一个对应的coNP完全问题,反之亦然。但现在这允许我们提出一个新问题:NP是否等于coNP?或者说,是否总是存在不可满足性的短证明?
如果存在,那么关系图可以简化为这样:P仍然不等于NP,但NP等于coNP,那么NP完全和coNP完全问题就会是同一类问题。
一个很好的问题是:在多项式时间归约下,NP难和coNP难可能是不同的。但在图灵归约下,任何NP难问题也是coNP难问题,反之亦然。为什么?因为如果你有一个能解决NP完全问题的预言机,你也可以用它来解决coNP完全问题——只需翻转答案即可。在图灵归约下,我们恢复了接受和拒绝之间的对称性。因此,在图灵归约下,NP难和coNP难是同一回事。但NP完全和coNP完全不同,因为要成为NP完全,必须在NP中;要成为coNP完全,必须在coNP中。
NP ∩ coNP 与因数分解
这个扩展的关系图让我们关注另一个方面:如果一个语言同时属于NP和coNP(即位于NP ∩ coNP的交集中),这是否意味着它必须在P中?
我们大多数人倾向于认为答案是否定的。不仅仅是因为我这样画了图,而是因为我们有具体的、属于NP ∩ coNP但人们极难将其放入P的问题例子。
让我们看一个这样的语言。定义语言 DIV 为所有整数对 (n, k) 的集合,其中 n 有一个不超过 k 的除数。
首先,能够判定这个语言等价于能够进行因数分解。为什么?如果你有一个DIV的预言机,你可以通过对k进行二分搜索来找到n的最小素因子,然后除以该因子并对得到的更小的数重复此过程。反之,如果你知道n的素因子分解,你当然可以判定DIV,因为你只需要知道n的最小素因子是什么。
我声称DIV在NP中。证书是什么?就是那个不超过k的除数本身。
同时,我声称DIV也在coNP中。为什么“否”的答案(即n没有不超过k的除数)也有短证书?因为每个整数都有唯一的一个素因子分解。证书就是n的素因子分解本身。此外,我们还需要一个事实:素性测试可以在多项式时间内完成(我们在课程开始时提到过)。因此,你可以自己确信这些素因子确实是n的素因子,并且没有更小的除数。一旦你知道了素因子分解,你就有了一个证明,表明n没有任何不超过k的除数。
因此,DIV同时位于NP和coNP中。我们利用了因数分解问题的一个结构性性质,使其不同于任何已知的NP完全问题:每个整数都有且仅有一个素因子分解。而对于图的三着色等问题,情况并非如此;你无法提前预测一个图将有多少种三着色方案。
这意味着,当我们将因数分解适当地表述为像DIV这样的判定问题时,该语言将位于NP ∩ coNP中。如果我们相信RSA是安全的(即因数分解是困难的),那么它就不在P中。因此,这将是NP ∩ coNP但不在P中的一个候选问题。
更广泛地说,我们可以提出另一个猜想:P 不等于 NP ∩ coNP。这是对P ≠ NP猜想的另一个加强。例如,为了拥有密码学,你实际上需要比这更多的东西,但这是最起码的要求。同样,如果P = NP,那么这个猜想也不成立。如果NP = coNP,那么这个猜想就等价于P ≠ NP。但如果NP ≠ coNP,那么我们在这里真的是在提出一个更强的猜想,而我们大多数人也会相信它。
为什么因数分解不是NP完全的?
现在,我想用coNP这个概念来解释我们在课程早期提到过的一点:因数分解几乎肯定不是NP完全问题。我们为什么如此确信?
这里有一个定理:如果存在任何语言同时属于NP ∩ coNP并且是NP完全的(即使在图灵归约下),那么这将意味着NP = coNP。
换句话说,像因数分解这样位于中间区域(楔形区)的问题,不可能是NP完全的,除非导致整个结构发生巨大的坍塌(即NP = coNP)。
为什么?让我们更形式化地看看。假设有一个语言 L 在 NP ∩ coNP 中并且是NP完全的(在图灵归约下)。我们想证明这将导致 NP = coNP。
我们需要证明,任何 NP 中的语言 L‘ 也在 coNP 中。如何证明?我们需要为 L’ 的“否”答案提供短证书。
由于 L 是NP完全的(在图灵归约下),根据定义,L‘ 在 P^L 中(即存在一个多项式时间图灵机,带有 L 的预言机,可以判定 L‘)。
现在,假设 x 不是 L‘ 的实例(即答案为“否”)。我们需要一个证书。我们有一个判定 L‘ 的过程,它在多项式时间内运行,并向 L 预言机进行查询。L 是一个在 NP ∩ coNP 中的语言。
现在,我们需要提供一个证明,表明该过程输出“拒绝”。我们可以这样做:模拟这个判定过程,每当它向 L 预言机提出查询时,我们都需要提供该查询答案的证明。如果答案是“是”,我们需要一个“是”的证书(因为 L 在 NP 中)。如果答案是“否”,我们需要一个“否”的证书(因为 L 在 coNP 中)。由于只有多项式次查询,我们只需要提供多项式数量的“是”和“否”证书,因此总证明大小是多项式的。这个证明将展示带预言机的图灵机的行为,从而证明输入 x 不是 L‘ 的实例。
因此,L‘ 在 coNP 中。这意味着 NP 包含于 coNP。由对称性,coNP 也包含于 NP,所以 NP = coNP。
这就是证明。这就是为什么我们相信因数分解不是NP完全的。换句话说,如果你接受NP不同于coNP,那么因数分解就不可能是NP完全的。
因此,因数分解是一个具体的例子,它肯定在NP中,许多人相信它在经典计算下是困难的,但它几乎肯定不是NP完全的。所以,它是位于P和NP完全之间“ twilight zone ”的一个很好的候选者。
拉德纳定理:中间问题的存在性
但是,如果你只是想知道“中间区域”是否存在问题,你甚至不需要依靠信念。有一个重要的结果叫做拉德纳定理,它指出:
如果 P ≠ NP,那么必然存在既不在P中也不是NP完全的语言。
如果 P = NP,那么一切都坍塌了,NP中的一切都在P中并且也是NP完全的(在图灵归约下)。但拉德纳定理说,只要 P ≠ NP,那么就不仅存在P问题和NP完全问题,还存在介于两者之间的问题。
不幸的是,拉德纳定理的证明并没有给出任何自然的、属于这个中间领域的问题例子(比如我们认为是因数分解的问题)。它只是告诉你这样的问题存在。这类似于可计算性理论中的弗里德伯格-穆克尼克定理,存在既不可判定也不等价于停机问题的中间语言,但它们是非常奇怪的语言。
在这里,构造这种语言的方法是:定义一个在几乎所有输入长度上都是空集的语言,但在少数彼此间隔非常非常远的输入长度上,它是3SAT问题。这就像在漫长的“空”的海洋中散布着小小的3SAT“岛屿”。这些小岛屿足以阻止语言属于P(基于P ≠ NP的假设)。同时,由于它们间隔如此之远,这将扼杀任何可能的NP完全性归约(将普通3SAT归约到此语言)。技术部分在于确保你的语言仍然在NP中。拉德纳展示了如何做到这一点,但这不是一个非常自然的例子。它证明了如果P不同于NP,那么P和NP完全不可能是NP的全部。
相对化:为什么P vs NP如此困难?
最后,我应该谈谈P与NP问题的相对化。这实际上说明了为什么P与NP问题如此难以解决。
在可计算性理论中,我们有可判定语言和可识别语言。你可以证明停机问题是不可判定的。然后,你可以将整个情况“提升”到一个预言机:假设每个人都可以免费拥有一个停机预言机。那么问题就变成了:带有停机预言机的图灵机能否解决带有停机预言机的图灵机的停机问题?答案仍然是否定的,你可以通过重复之前的证明来证明。因此,我们得到了一个越来越难的问题的无限层次结构。
现在,我们也可以想象给P和NP提供预言机。P^A 表示带有语言A预言机的P。NP^A 表示NP验证机也可以访问A预言机。然后我们可以问:对于每个预言机A,P^A 是否等于 NP^A?
在可计算性中,预言机是否存在并不重要。但贝克、吉尔和索洛维在1975年指出,P与NP问题并不具有这种对预言机的不敏感性。他们表明:
- 存在预言机 A,可以证明相对于该预言机,P ≠ NP。
- 存在其他预言机 B,可以证明相对于该预言机,P = NP。
这意味着,P与NP问题的答案取决于现实世界中我们没有这些预言机这一事实。因此,你需要一种对预言机敏感的证明技术,这基本上排除了所有纯粹来自逻辑或可计算性理论的技术。
如何构造使P ≠ NP的预言机?提示是:预言机只需要编码一些非常困难的搜索问题。例如,如果我随机选择一个语言(每个输入以1/2的概率独立地属于或不属于该语言),那么以概率1,相对于该语言,P ≠ NP。这是因为我可以问:“在预言机字符串的前2n位中,是否存在n个连续的1?”这个问题在NPA中是可回答的(证书就是这些1的位置)。但在PA中,你只能在多项式时间内查看多项式个位置,很可能找不到这样的字符串(如果它存在的话)。所以,对于绝大多数随机预言机,PA ≠ NP^A。
如何构造使P = NP的预言机?一个常见的例子是使用PSPACE完全的语言作为预言机。可以证明,P^PSPACE = NP^PSPACE。因为两者实际上都等于PSPACE(你可以用多项式空间来模拟NP机器及其对PSPACE预言机的查询)。因此,相对于一个PSPACE预言机,P和NP会坍缩。
我们得出结论,P与NP问题的答案对存在的预言机敏感。这对证明技术是一个惊人的强大约束,它排除了人们曾经提出的大多数解决P与NP问题的想法,因为如果它们有效,那么即使有预言机存在,它们也应该有效。
在过去的25年左右,复杂性理论中出现了一些对预言机敏感的新技术。我和Avi Wigderson在2008年提出了对Baker-Gill-Solovay论证的推广,表明即使这些新技术也不足以解决P与NP问题。这被称为“代数化障碍”,它概括了预言机的概念以涵盖这些新技术。
多项式层次结构:预言机的“喂养狂潮”
最后,让我们考虑将P和NP作为预言机相互“喂养”,看看会产生什么。
首先考虑 **PNP**:即带有解决某个NP完全问题预言机的P。这显然是一个相当强大的类,它包含NP,也包含coNP(因为P机器可以翻转预言机的答案)。事实上,PNP 甚至可以做一些我们不相信属于NP或coNP本身的事情。
一个很好的例子是:考虑旅行商问题(TSP)。决策问题“是否存在一条访问所有城市且总长度不超过K的路径?”是NP完全的。但现在假设我问一个略有不同的问题:“最短路径的长度是否是素数?”
我声称这个问题在P^NP中。如何解决?你可以使用NP预言机进行二分搜索来找出最短路径的长度。具体步骤是:
- 询问NP预言机:“是否存在长度不超过某个值M的路径?”
- 根据回答,调整M的值,通过二分搜索逐步缩小范围,最终确定最短路径的确切长度L。这需要多项式次数的查询。
- 一旦知道了L,再询问一次NP预言机(或者使用一个在P中的素性测试程序)来判断L是否为素数。
因此,通过多项式次数的NP预言机查询,我们可以在多项式时间内解决“最短路径长度是否为素数”的问题,所以该问题属于PNP。这个问题似乎比单纯的“是否存在路径”更复杂,展示了PNP可能比NP和coNP的并集更强大。
这种通过交替使用存在性和全称性预言机(或量化词)定义复杂性类的过程,引出了所谓的多项式层次结构,这是复杂性理论中一个重要的主题。
总结
在本节课中,我们一起学习了:
- 物理系统与NP完全性:探讨了使用肥皂泡等物理系统解决NP完全问题的历史想法,并指出它们很可能也会陷入局部最优,而非解决全局最难实例。
- coNP:引入了NP的补集类coNP,其特点是“否”答案具有短证书。我们讨论了NP = coNP的可能性及其含义。
- 复杂度类关系图:描绘了P、NP、coNP、NP完全和coNP完全之间更丰富的关系,并提出了P ≠ NP ∩ coNP等更强的猜想。
- 因数分解的地位:利用coNP的概念,严谨地解释了为什么因数分解问题极不可能是NP完全的(除非NP = coNP),从而将其定位在NP ∩ coNP这个可能的“中间区域”。
- 拉德纳定理:知道了如果P ≠ NP,则必然存在既非P也非NP完全的语言,尽管该定理构造的例子不自然。
- 相对化障碍:理解了P与NP问题对预言机的敏感性,这解释了为何许多传统证明方法(如对角化)难以攻克此问题,并介绍了“代数化障碍”作为其现代推广。
- 预言机类的扩展:简要了解了像P^NP这样的类,它可能包含更复杂的问题(如判断最优解是否具有某种属性),并引出了多项式层次结构的概念。
这些概念帮助我们更深入地理解了NP完全性之外的复杂性版图,以及为何某些像因数分解这样的问题在复杂性理论中占据着独特而重要的位置。
016:多项式空间与随机算法入门
在本节课中,我们将要学习两个重要的主题:多项式空间(PSPACE)的完全问题,以及随机算法的基本概念和复杂度类。我们将从回顾多项式层级开始,然后深入探讨PSPACE完全问题,最后介绍随机算法的动机和定义。
多项式层级与PSPACE回顾
上一节我们介绍了多项式层级。让我们从一张图开始回顾。
我们有P类,以及我们之前见过的NP类和coNP类。上次我们看到了多项式层级的第二层,即带NP预言机的NP类(记作 Σ₂ᴾ 或 NPᴺᴾ),以及带NP预言机的coNP类(记作 Π₂ᴾ 或 coNPᴺᴾ)。在这两者之间,还有一个类,即带NP预言机的P类(有时记作 Δ₂ᴾ)。
你可以继续添加预言机,得到 NPᴺᴺᴾ、coNPᴺᴺᴾ 等等。最终,所有这些类的并集构成了多项式层级(Polynomial Hierarchy, PH)。另一种理解方式是,PH是所有 Σₖᴾ 类的并集。所有这些类都包含在多项式空间(PSPACE) 类中。
我们还看到,整数分解问题同时属于NP和coNP。如果分解问题是NP完全的,那么将导致NP等于coNP,而我们认为这不太可能成立,因此分解问题不太可能是NP完全的。
PSPACE完全问题
现在,我们来看看PSPACE的完全问题。PSPACE完全性的定义与NP完全性类似。
一个问题是PSPACE难的(PSPACE-hard),如果所有PSPACE中的问题都可以在多项式时间内归约到它。如果一个问题既是PSPACE难的,又属于PSPACE类,那么它就是PSPACE完全的(PSPACE-complete)。
与NP完全性类似,存在一个“平凡”的PSPACE难问题,即空间版本的停机问题。定义如下:给定一个图灵机M和一个空间界限 0^s(即s个空格),问M是否能在O(s)空间内停机并接受?这个问题显然是PSPACE难的,因为任何PSPACE问题都可以映射到它。
然而,更有趣的是存在自然的PSPACE完全问题,它们并非为构造完全性而刻意设计。
自然PSPACE完全问题示例
一个经典的例子是正则表达式等价性问题。给定两个正则表达式R₁和R₂,问它们描述的语言是否相同(即 L(R₁) = L(R₂))?一个特例是:给定一个正则表达式R,问它是否描述所有二进制串的集合(即 L(R) = {0,1}*)?这个问题是PSPACE完全的。
更一般地,许多双人完全信息博弈问题都是PSPACE完全的。这类问题的直觉是:它们通常涉及两个玩家竞争,你需要判断在双方都采取最优策略的情况下,先手玩家是否能必胜。
- 广义国际象棋:将国际象棋推广到n×n的棋盘。给定一个棋子配置,判断白方是否有必胜策略。这个问题是PSPACE完全的。
- 广义地理游戏:给定一个国家名列表(或一个表示“后继”关系的有向图),两名玩家轮流说出一个国家名,新说出的国家名首字母必须与前一个国家名的尾字母相同,且不能重复。无法继续的玩家输。其广义版本(基于任意有向图)也是PSPACE完全的。
这些例子表明,PSPACE完全性捕获了许多现实世界中看似合理的、有趣的问题。
规范的PSPACE完全问题:TQBF
在证明NP完全性时,3-SAT是一个方便的起点。类似地,存在一个规范的PSPACE完全问题,它是证明PSPACE难性的有力工具。
这个问题是真量化布尔公式问题(True Quantified Boolean Formula, TQBF或QBF)。其形式如下:
给定一个带有交替量词的布尔公式,判断该公式是否为真。
例如:
∃x₁ ∀x₂ ∃x₃ ∀x₄ ... ∃xₙ φ(x₁, x₂, ..., xₙ)
问题是:是否存在对x₁的赋值,使得对于x₂的所有赋值,都存在对x₃的赋值,使得对于x₄的所有赋值……,最终使得公式φ为真?
量词的顺序至关重要。交换量词顺序会改变问题的含义。例如,“∃x ∀y (x > y)”是假的(没有最大的自然数),而“∀y ∃x (x > y)”是真的(每个自然数都有比它大的数)。
TQBF问题之所以强大,是因为它允许量词的数量(即交替次数)随输入规模n增长。相比之下,多项式层级的第k层只允许固定数量k的交替量词。因此,TQBF能够表达比多项式层级任何固定层都更复杂的问题,这对应了PSPACE包含PH的事实。
TQBF问题直观地对应了双人博弈:存在量词(∃)对应玩家一的选择,全称量词(∀)对应玩家二的选择。公式φ根据双方走出的序列判断胜负。因此,问上述公式是否为真,就是在问玩家一是否有必胜策略。
为什么TQBF属于PSPACE?
我们可以设计一个多项式空间的算法来解决TQBF。核心思想是利用递归,并重复使用空间。
考虑一个简化的子问题:对于固定的x₁(例如设为0),我们得到一个关于变量x₂到xₙ的新量化公式。假设我们有一个算法能以S(n-1)的空间解决规模为n-1的问题。
要解决规模为n的问题,我们可以:
- 尝试将x₁设为0,调用解决n-1规模问题的算法,检查结果。
- 清除使用的空间。
- 尝试将x₁设为1,再次调用解决n-1规模问题的算法,检查结果。
- 根据两次调用的结果和第一个量词的类型(∃或∀)决定最终答案。
这个递归过程的空间消耗大约是 S(n) ≈ S(n-1) + O(1),因此总空间是O(n),即多项式空间。关键在于,我们可以重复使用同一块空间来处理不同的分支,而不需要同时存储所有分支的信息。这类似于在隐含的博弈树(公式计算树)上进行深度优先搜索(DFS),其栈深度仅为n。
随机算法的引入与动机
为什么我们需要研究随机算法?尽管我们计算的问题本身是确定性的,但随机性有时能在算法上提供帮助。
以下是几个动机:
- 数值计算与蒙特卡洛方法:例如,计算复杂形状的面积或定积分。可以通过在包围区域内随机采样点,并统计落在目标内的点的比例来近似估计。这种方法在物理、工程等领域有广泛应用。
- 密码学:安全的加密需要随机性。就像“石头剪刀布”游戏,如果你的出招是可预测的,你就会输。密码学中,密钥的随机性对于防止被破解至关重要。
- 算法设计:有些问题没有已知的多项式时间确定性算法,但存在高效的概率算法。
- 示例:生成大素数:给定参数n,需要输出一个n比特长的素数。根据素数定理,一个随机n比特数是素数的概率约为
Θ(1/n)。因此,一个简单的随机算法是:反复随机选取n比特数,并用一个多项式时间的素性测试算法检查它,直到找到一个素数为止。期望尝试次数约为O(n),这构成了一个多项式时间的随机算法。目前我们不知道是否存在多项式时间的确定性算法来完成这个任务。
- 示例:生成大素数:给定参数n,需要输出一个n比特长的素数。根据素数定理,一个随机n比特数是素数的概率约为
随机计算模型与复杂度类
我们如何形式化地描述一个拥有随机性的图灵机?
一种方式是定义概率图灵机,它在执行过程中可以“抛硬币”,即根据概率进行状态转移(例如,以50%的概率进入状态A,50%的概率进入状态B)。
更简便的方式是考虑一个拥有随机带的确定性图灵机。除了输入带和工作带,它还有一条“随机带”,上面预先写满了随机比特(每个比特独立且均匀地为0或1)。当算法需要随机性时,它只需从随机带上读取下一个比特。这两种模型在计算能力上是等价的。
基于这个模型,我们可以定义随机算法的复杂度类。首先定义随机多项式时间(RP)。
我们说一个语言L属于RP,如果存在一个多项式时间图灵机M,满足:
- 如果输入x ∈ L,则至少有一半(> 1/2)的随机串z使得M(x, z)接受。
- 如果输入x ∉ L,则对于所有随机串z,M(x, z)都拒绝。
RP算法的直觉是:当答案应为“否”时,它从不犯错(总是拒绝);当答案应为“是”时,它至少有50%的概率给出正确答案(接受)。这类似于一个几乎没有“假阳性”但允许“假阴性”的测试。
RP与其他类的关系
显然,P ⊆ RP。此外,RP ⊆ NP。为什么呢?如果一个问题在RP中,那么对于“是”实例,存在许多(超过一半)随机串可作为“见证”使机器接受。在NP的定义中,我们只需要至少存在一个见证串即可。因此,RP的要求比NP更强(需要很多见证),所以RP是NP的一个子集。
类似地,我们可以定义补随机多项式时间(coRP),其中机器在“是”实例时总是接受,在“否”实例时以至少一半的概率拒绝。显然,coRP ⊆ coNP。
错误概率放大
在RP的定义中,常数1/2并不是关键。我们可以通过重复运行算法来放大成功概率(或减小错误概率)。
假设原算法对于“是”实例的成功概率仅为p > 0(例如p=1/2)。我们独立随机地选择k个随机串z₁, z₂, ..., zₖ,并运行算法k次。只要有任何一次运行接受,我们就最终接受(因为“否”实例永远不会接受)。
- 对于“否”实例,错误概率仍为0。
- 对于“是”实例,所有k次运行都失败(即都拒绝)的概率至多是
(1-p)^k。当k增大时,这个概率指数级下降。例如,取k=100,即使p=1/2,错误概率也会降到远低于2^{-100}。
因此,只要原始成功概率p是一个大于0的常数,我们就可以通过多项式次数的重复,将成功概率提升到任意接近1(例如0.999)。所以RP的定义对具体的常数概率(只要>0)不敏感。
其他随机复杂度类
- 零错误概率多项式时间(ZPP):定义为 ZPP = RP ∩ coRP。ZPP中的算法对于“是”和“否”实例都有单边错误,并且错误概率可以通过重复运行被指数级降低。这类算法通常被称为拉斯维加斯算法,其特点是它要么给出正确答案,要么以很小的概率不给出答案(但绝不给出错误答案)。
- 有界错误概率多项式时间(BPP):这是更一般的随机算法类。一个语言L属于BPP,如果存在多项式时间图灵机M,满足:
- 如果x ∈ L,则至少2/3的随机串z使得M(x, z)接受。
- 如果x ∉ L,则至少2/3的随机串z使得M(x, z)拒绝。
BPP允许在两个方向上都有错误,但错误概率被限制在1/3以内。同样,常数1/3也可以通过重复运行进行放大。BPP包含了RP和coRP,被认为是代表“高效概率计算”的主要类。
总结
本节课中我们一起学习了:
- 多项式空间(PSPACE)的完全问题:我们回顾了多项式层级包含在PSPACE中。我们看到了自然的PSPACE完全问题,如正则表达式等价性和广义双人博弈(如广义国际象棋)。我们重点介绍了规范的PSPACE完全问题——真量化布尔公式(TQBF),并理解了其直观含义以及它属于PSPACE的原因。
- 随机算法的引入与动机:我们探讨了为什么需要随机算法,包括在数值模拟、密码学和解决特定问题(如素数生成)中的应用。
- 随机计算模型与复杂度类:我们介绍了拥有随机带的图灵机模型。在此基础上定义了重要的随机复杂度类:
- RP:单边错误,无假阳性。
- coRP:单边错误,无假阴性。
- ZPP:RP ∩ coRP,零错误概率(拉斯维加斯算法)。
- BPP:有界双面错误概率,代表通用的高效概率计算。
我们理解了这些类之间的关系(P ⊆ RP ⊆ NP,以及P ⊆ coRP ⊆ coNP),并学习了通过重复运行来放大成功概率的关键技术。
下一讲,我们将更深入地学习概率论基础,以便更严格地分析随机算法。
017:概率复杂性类与随机算法
在本节课中,我们将学习概率复杂性类,如RP、coRP、ZPP和BPP。我们将探讨随机算法的基本概念,并学习如何使用概率论工具(如切尔诺夫界)来分析这些算法的误差放大。最后,我们将通过一个具体的例子——非零电路问题——来展示随机算法的威力。
概率复杂性类回顾
上一节我们介绍了多项式层级和PSPACE。本节中,我们来看看概率复杂性类,这是本周学习的重点。
RP(随机多项式时间)
RP是NP的一个子类。对于一个RP算法,如果答案是“是”,那么存在大量的接受证据。具体来说,如果你随机选择一个字符串,那么它成为接受证据的概率至少为1/2。如果答案是“否”,算法总是拒绝。
核心定义:语言 L 属于 RP,如果存在一个多项式时间随机算法 M,满足:
- 如果 x ∈ L,则 Pr[M(x) 接受] ≥ 1/2。
- 如果 x ∉ L,则 Pr[M(x) 接受] = 0。
coRP
coRP是RP的补类,也是coNP的子类。对于一个coRP算法,如果答案是“否”,你可以完全确定;如果答案是“是”,算法可能以一定概率失败。
核心定义:语言 L 属于 coRP,如果存在一个多项式时间随机算法 M,满足:
- 如果 x ∈ L,则 Pr[M(x) 接受] = 1。
- 如果 x ∉ L,则 Pr[M(x) 接受] ≤ 1/2。
ZPP(零错误概率多项式时间)
ZPP是RP和coRP的交集。一个ZPP算法永远不会给出错误答案,但它有时可能无法给出答案(输出“我不知道”)。通过重复运行,你可以以压倒性概率快速得到正确答案。
核心定义:ZPP = RP ∩ coRP。
另一种等价定义是:ZPP是那些可由期望多项式时间随机算法判定的语言集合,且算法答案总是正确的。
BPP(有界错误概率多项式时间)
BPP是最通用的有界错误概率类。算法允许在“是”和“否”两种情况下都犯错误,但错误概率被一个常数界限隔开。
核心定义:语言 L 属于 BPP,如果存在一个多项式时间随机算法 M 和一个常数 ε > 0,满足:
- 如果 x ∈ L,则 Pr[M(x) 接受] ≥ 2/3。
- 如果 x ∉ L,则 Pr[M(x) 接受] ≤ 1/3。
常数 2/3 和 1/3 并非神圣不可改变,任何两个被常数间隔隔开的概率都可以。
概率论基础工具
为了分析BPP算法的误差放大,我们需要一些概率论的基本工具。
1. 并界(Union Bound)
并界是理论计算机科学中最有用的原理之一。对于任意两个事件A和B,有:
Pr[A ∨ B] ≤ Pr[A] + Pr[B]
这个不等式之所以强大,是因为它不要求事件A和B相互独立。即使坏事之间有关联,其发生的总概率上界也仅仅是各自概率之和。
2. 期望的线性性质(Linearity of Expectation)
对于任意两个随机变量X和Y(无论是否独立),有:
E[X + Y] = E[X] + E[Y]
这个性质同样不要求X和Y独立,使其应用极其广泛。
3. 马尔可夫不等式(Markov‘s Inequality)
对于非负随机变量X和任意k > 0,有:
Pr[X ≥ k * E[X]] ≤ 1/k
这个不等式用于界定随机变量远超其期望值的概率。
误差放大与切尔诺夫界
对于BPP算法,我们可以通过多次独立运行并取多数结果来降低错误概率。切尔诺夫界为我们提供了分析这种策略的数学工具。
假设我们有一个BPP算法,对于不在语言L中的输入x,单次运行接受的概率 p ≤ 1/3。我们独立运行该算法m次。我们犯错的唯一情况是超过半数的运行(即至少 m/2 次)错误地接受了。
我们希望界定这个坏事件发生的概率。直接使用马尔可夫不等式得到的上界 (≤ 2/3) 不够强。我们需要利用运行的独立性。
切尔诺夫界(简化版):设 X1, X2, ..., Xm 是独立的0-1随机变量,Pr[Xi = 1] = p。令 S = X1 + ... + Xm,μ = E[S] = p * m。那么对于任意 δ > 0,有:
Pr[S ≥ (1+δ)μ] ≤ exp(-δ²μ / 3)
在我们的BPP场景中,p = 1/3,μ = m/3。我们关心 S ≥ m/2,即 (1+δ)μ = m/2,解得 δ = 1/2。代入切尔诺夫界:
Pr[错误] ≤ exp(-(1/2)² * (m/3) / 3) = exp(-m / 36)
这个概率随着m增大而指数级下降。因此,只需多项式次重复,就能将错误概率降至可忽略不计的程度。这也证明了BPP的定义不依赖于特定的常数(如2/3和1/3),只要两者被常数间隔隔开即可。
BPP在复杂性层级中的位置
我们已经知道:
- RP ⊆ NP
- coRP ⊆ coNP
- ZPP ⊆ NP ∩ coNP
那么BPP呢?BPP是否包含在NP中?一个NP证据需要能确定性地证明答案是“是”。对于BPP,即使我给你看一万个导致算法接受的随机串,我仍然可能只是“精心挑选”了这些串,这并不能证明大多数随机串都会导致接受。因此,我们不知道BPP ⊆ NP。
一个重要的定理(Sipser–Gács–Lautemann定理)指出:
BPP ⊆ Σ₂^P ∩ Π₂^P
即BPP包含在多项式层级的第二层中。这是目前已知的关于BPP最好的上界之一。
示例:非零电路问题(PIT)
现在,我们来看一个至今未知是否在P中,但已知在RP中的问题:非零电路问题。
问题描述:给定一个算术电路(仅包含加法、减法和乘法门,输入为常数1),判断其输出的数值是否非零。
难点:电路可能通过反复平方产生双指数级大小的数值(例如 2^(2^n)),然后在最后一步相减归零。直接模拟计算需要处理超大规模整数,可能导致指数时间。
随机算法:
- 随机选择一个大小合适的素数
p(例如在[2, 2^(2n)]范围内随机选取)。 - 在模
p的意义下模拟电路计算。 - 如果计算结果模
p不为零,则一定可以断定原电路输出非零。 - 如果计算结果模
p为零,则输出“零”(可能出错)。
算法分析:
设原电路输出值为 A,其绝对值最大为 2^(2^n)。
- 如果
A = 0,那么模任何p都是0,算法总是正确。 - 如果
A ≠ 0,我们需要分析算法出错的概率,即A ≡ 0 (mod p)的概率,这意味着素数p整除A。
由于|A| ≤ 2^(2^n),能整除A的不同素数个数最多为2^n个(因为每个素数至少为2,A最多被2^n个素数乘积表示)。
而在区间[2, 2^(2n)]中,素数总数非常多(由素数定理可知约为Θ(2^(2n) / (2n)))。
因此,随机选到一个能整除非零A的素数p的概率非常小,约为(2^n) / (2^(2n)/ (2n)),这是一个可忽略的概率。
通过重复此过程,可以将错误概率降至任意低。这证明了非零电路问题属于 coRP(等价地,其补问题属于RP)。
总结
本节课中我们一起学习了概率复杂性类。我们从回顾RP、coRP和ZPP开始,理解了它们提供的不同“确定性”保证。然后,我们深入探讨了最通用的有界错误类BPP,并学习了如何使用切尔诺夫界来分析随机算法的误差放大。我们还了解了BPP在复杂性层级中的已知位置(在多项式层级第二层内)。最后,我们通过非零电路问题这一具体实例,看到了随机算法如何巧妙地解决那些直接确定性计算看似困难的问题。这些概念和工具是理解现代计算理论中随机化核心作用的基础。
018:随机算法与密码学入门
在本节课中,我们将完成对随机算法和概率复杂度类的讨论,并开始介绍密码学的基础知识。我们将探讨随机算法的放大性质、多项式恒等式测试,以及从古典密码到一次性密码本的基本概念。
随机算法的放大性质
上一节我们介绍了随机算法,本节我们来看看其核心优势:放大性质。对于任何随机算法,我们可以通过多次运行并取多数结果来显著降低错误概率。具体来说,错误概率会随着重复次数的增加而呈指数级下降。
对于具有双边错误的随机算法(即BPP类算法),证明这一指数放大性质需要一些分析。我们使用理论计算机科学中一个称为切尔诺夫界的工具来完成这一分析。
多项式恒等式测试
以下是多项式恒等式测试问题及其随机算法的一个例子。
问题描述:给定一个算术电路(由加法、减法和乘法门组成,输入可以是常数或变量),判断其输出的多项式是否恒等于零。
挑战:算术电路可能通过重复平方等操作,快速产生需要指数级位数才能写下的巨大数字,因此确定性多项式时间算法可能不可行。
随机算法(RP算法):
- 随机选择一个具有多项式位数的素数 p。
- 将所有算术运算在模 p 下进行。
- 如果原始电路输出非零多项式,那么以高概率,模 p 后的新电路输出也将非零。
关键点:该分析对每一个算术电路都成立。电路可能由对手精心构造,但算法使用的素数是我们自己随机选择的。只要素数选择得当,算法就能以高概率对任何电路给出正确答案。
推广:含变量的情况
当电路输入包含变量(如 x)时,算法需要调整:
- 选择一个足够大的有限域(其大小远大于电路可能产生的多项式次数 d)。
- 为变量 x 随机代入该域中的一个值。
- 根据代数基本定理,一个非零的 d 次多项式最多有 d 个根。因此,在足够大的域中随机选点,该点恰好是根的概率极低。
这个算法非常实用,例如可用于快速验证两个复杂代数表达式是否等价,而无需进行耗时的完全展开。
去随机化的挑战与展望
多项式恒等式测试的去随机化(即寻找确定性多项式时间算法)是理论计算机科学的一个重大开放问题。有趣的是,多数复杂性理论家猜想 P = BPP,即随机性并不能从根本上提供超越多项式时间的计算能力。
为什么这么猜想?
这与伪随机数发生器的概念有关。如果存在这样的PRG:它能用一个对数长度的随机种子,生成一个更长的、“看起来”完全随机的字符串,并且任何多项式时间算法都无法区分其输出与真随机串,那么我们就可以去随机化任何BPP算法。
具体方法是:遍历所有可能的对数长度种子,用PRG扩展每个种子得到“伪随机串”,用这些串运行原随机算法,然后对结果取多数。由于种子只有对数个,可能的种子总数是多项式级别的,因此这个遍历过程是多项式时间的。
一个重要定理(Impagliazzo-Wigderson, 1997):基于一个看似合理的计算复杂性假设(即存在一个指数时间可判定的语言,即使对非均匀算法——如针对不同输入长度的不同电路——也需要指数时间),可以构造出满足上述要求的伪随机数发生器,从而证明 P = BPP。
这强化了随机性可能并非必需的观点。
密码学导论
现在,让我们转向密码学,这是理论计算机科学最具直接应用价值的领域之一。在密码学中,我们通常主动构造计算上困难的问题。
古典密码模型
密码学的基本场景涉及三方:
- Alice:发送方。
- Bob:接收方。
- Eve:窃听者。
Alice想发送一条明文消息 M 给Bob,但传输信道会被Eve窃听。目标是在Eve无法读懂的情况下让Bob能恢复消息。
传统方案:Alice和Bob预先共享一个秘密密钥 K。
- 加密:Alice使用密钥 K 和加密函数 E,将明文 M 转换为密文 C = E_K(M)。
- 解密:Bob收到 C 后,使用密钥 K 和解密函数 D,恢复明文 M = D_K(C)。
历史例子:
- 凯撒密码:将每个字母在字母表中固定移位(如移3位)。极易被破解。
- 字母替换密码:使用一个随机排列作为密钥,将每个字母映射为另一个字母。可通过分析字母频率(如英文中‘e’最常见)来破解。
这些古典密码的弱点在于加密模式固定,一旦被对手知晓或分析出模式,安全性即告失效。
一次性密码本
现代密码学将安全性寄托于密钥的随机性,而非算法的复杂性。一个理论上绝对安全(如果正确使用)的系统是一次性密码本。
方案描述:
- 将明文 M 视为二进制串。
- 密钥 K 是一个与 M 等长的、均匀随机的二进制串。Alice和Bob必须预先安全地共享 K。
- 加密:密文 C = M ⊕ K(逐比特异或)。
- 解密:明文 M = C ⊕ K(异或操作是对合的)。
安全性证明(信息论安全):
对于不知道 K 的Eve来说,无论她拥有多少计算资源(即使计算能力无限),密文 C 在统计上看完全是一个均匀随机串,不包含关于明文 M 的任何信息。观察 C 不会让Eve获得关于 M 的任何新知识。
致命限制:密钥绝不能重复使用
如果同一个密钥 K 被用来加密两条不同的明文 M1 和 M2,Eve获得 C1 = M1 ⊕ K 和 C2 = M2 ⊕ K,她可以计算:
C1 ⊕ C2 = (M1 ⊕ K) ⊕ (M2 ⊕ K) = M1 ⊕ M2
这就泄露了两个明文的异或值。结合对明文格式的已知信息(例如,如果明文是图像),可能足以恢复出关键信息。历史上,苏联间谍因重用一次性密码本密钥而被破解。
香农的结论:香农证明,任何达到信息论安全(即无条件安全,不依赖对手计算能力假设)的密码系统,其密钥长度必须至少与消息长度一样长。因此,一次性密码本在密钥长度效率上已达到最优,无法在保持同等安全性的前提下缩短密钥。
总结
本节课中我们一起学习了:
- 随机算法的放大性质及其在多项式恒等式测试中的应用。
- 复杂性理论中对 P = BPP 的猜想及其与伪随机数发生器的深刻联系。
- 密码学的基本模型与古典密码的弱点。
- 一次性密码本的原理、其强大的信息论安全性,以及密钥不可重复使用的关键限制。
下一讲,我们将深入探讨基于计算复杂性假设的现代密码学,看看如何用短密钥实现安全通信。
019:基于复杂性的密码学
在本节课中,我们将要学习基于计算复杂性假设的密码学。我们将探讨如何利用伪随机生成器来改进一次性密码本,并理解单向函数与密码学安全性之间的核心关系。
上一节我们介绍了信息论密码学,特别是完美安全的一次性密码本。本节中我们来看看,当我们假设对手的计算能力有限时,如何构建更实用的密码系统。
伪随机生成器的定义
为了构建更高效的密码系统,我们需要一个核心工具:密码学安全的伪随机生成器。其核心思想是生成一个看似随机、但任何多项式时间算法都无法将其与真随机字符串区分开的序列。
一个密码学伪随机生成器是一个函数 G,它将一个长度为 n 的真随机种子 s,扩展为一个长度为 n+1 的“伪随机”字符串 G(s)。它必须满足两个条件:
- 高效可计算性:函数 G 可以在多项式时间内计算。
- 不可区分性:对于任何多项式时间算法 A(称为敌手),其区分真随机字符串与伪随机字符串的优势是可忽略的。形式化表示为:
| Pr[ A(r) = 1 ] - Pr[ A(G(s)) = 1 ] | ≤ negl(n)
其中,r是随机的n+1比特字符串,s是随机的n比特种子,negl(n)表示一个比任何1/p(n)(p为任意多项式)衰减都快的函数。
这意味着,任何计算能力有限的敌手都无法有效判断一个字符串是来自真随机源还是来自伪随机生成器。
从短种子生成长密钥
一个只将种子延长1比特的伪随机生成器看似作用有限,但我们可以通过迭代使用它来获得任意多项式长度的输出。
以下是其工作原理:
- 从
n比特种子s0开始。 - 计算
G(s0),得到n+1比特。将前n比特作为新的种子s1,输出剩余的1比特b0。 - 计算
G(s1),得到n+1比特。将前n比特作为新的种子s2,输出剩余的1比特b1。 - 重复此过程。最终,输出的比特序列
b0, b1, b2, ...构成了一个更长的伪随机字符串。
通过这种“反馈-输出”的迭代模式,我们可以从一个短种子生成任意长的伪随机比特流,用于加密长消息。
构建高效密码系统
有了伪随机生成器,我们就可以改进一次性密码本,使其仅需一个短密钥。
假设爱丽丝和鲍勃共享一个短密钥 k(例如 n 比特)。他们想安全地交换一条长消息 m(例如 n^2 比特)。以下是加密和解密过程:
- 加密:爱丽丝使用伪随机生成器 G 将短密钥
k扩展为与消息m等长的伪随机比特流 G(k)。然后,她通过按位异或操作生成密文:c = m ⊕ G(k)。 - 解密:鲍勃同样使用 G 和共享密钥
k生成相同的伪随机比特流 G(k)。然后,他通过再次异或操作恢复明文:m = c ⊕ G(k)。
这个系统的安全性基于一个归约论证:如果存在一个敌手伊芙能够以不可忽略的优势从这个系统中获取关于明文 m 的信息(例如,区分两条可能的明文),那么我们就可以利用伊芙来构造一个算法,以不可忽略的优势区分 G(k) 的输出与真随机字符串,这与 G 是伪随机生成器的假设矛盾。因此,在伪随机生成器安全的假设下,该密码系统是安全的。
单向函数:伪随机性的基础
伪随机生成器的存在性依赖于一个更基础的概念:单向函数。
一个单向函数 F 满足:
- 正向易计算:给定输入
x,计算F(x)是容易的(多项式时间)。 - 逆向难求解:给定输出
y = F(x)(其中x随机选取),对于任何多项式时间算法 A,找到任何一个原像x'使得F(x') = y的概率是可忽略的。即:
Pr[ F( A(F(x)) ) = F(x) ] ≤ negl(n)
单向函数是许多密码学原语的基石。一个重要结论是:如果存在密码学伪随机生成器,则一定存在单向函数(伪随机生成器本身就是一个单向函数,因为从输出反推种子是困难的)。
更令人惊讶的是,反向也(几乎)成立。Håstad, Impagliazzo, Levin 和 Luby 证明的 HILL 定理 指出:如果存在单向函数,则可以构造出密码学伪随机生成器。这意味着,单向函数的存在是构建此类安全密码系统的充分必要条件。
公钥密码学的引入
尽管基于短密钥的私钥密码学很实用,但它仍然要求通信双方事先安全地共享一个密钥。在网络时代,这成为了一个可扩展性瓶颈。
公钥密码学解决了这个问题。它允许完全陌生的双方,在不事先共享任何秘密的情况下,通过公开信道建立安全的通信。其直观类比是“挂锁盒”模型:鲍勃可以将他的打开挂锁(公钥)公开送给爱丽丝,爱丽丝用它锁上盒子(加密消息)后寄回,只有拥有对应钥匙(私钥)的鲍勃才能打开。
下节课我们将深入探讨两个著名的公钥密码系统:Diffie-Hellman 密钥交换和 RSA 加密算法。
总结
本节课中我们一起学习了基于复杂性理论的密码学基础。我们定义了密码学伪随机生成器,它能够生成任何多项式时间敌手都无法与真随机区分的序列。利用它,我们可以用短密钥实现类似一次性密码本的安全加密。我们了解到,这种伪随机生成器的存在性等价于单向函数的存在性,而后者是一个比 P ≠ NP 更强的假设。最后,我们看到了私钥密码学的局限性,并引出了无需预先共享密钥的公钥密码学。
020:公钥密码学与RSA
在本节课中,我们将学习现代密码学的核心——公钥密码学。我们将从Diffie-Hellman密钥交换协议开始,深入探讨其工作原理,然后详细讲解著名的RSA加密系统。最后,我们将看到一个利用RSA解决“安全约会”问题的巧妙应用。
Diffie-Hellman密钥交换协议
上一节我们介绍了基于单向函数的私钥密码学。本节中我们来看看如何在不预先共享密钥的情况下,让通信双方安全地协商出一个共享密钥,这就是Diffie-Hellman协议的目标。
协议设定与目标
Alice想发送一条秘密消息给Bob,而窃听者Eve正在监听信道。我们的目标是让Alice和Bob在不被Eve知晓的情况下,共同协商出一个随机秘密。一旦他们拥有这个共享秘密,就可以将其用作一次性密码本的密钥,或通过伪随机数生成器扩展后用于加密。
协议步骤
以下是Diffie-Hellman密钥交换协议的具体步骤:
-
选择公共参数:首先,选择一个巨大的随机质数 P。这个质数可以公开,Eve也可以知道它。每个质数 P 都对应一个模 P 的乘法群 Z_P^*,它包含从1到 P-1 的所有整数,运算为模 P 乘法。
-
选择生成元:Alice从乘法群 Z_P^* 中随机选择一个元素 G,并将其公开发送给Bob(Eve也会看到)。
-
生成私钥与公钥:
- Alice随机选择一个私有的指数 A(1 ≤ A ≤ P-1),并保密。
- Alice计算 G^A mod P。这里需要使用重复平方法进行高效计算,以避免对指数 A 进行线性次乘法。由于所有计算都是模 P 的,数字长度不会超过 P 的位数,因此整个过程是多项式时间可完成的。
- Alice将计算结果 G^A mod P 发送给Bob。
-
Bob的响应:
- Bob随机选择自己的私有指数 B(1 ≤ B ≤ P-1),并保密。
- Bob计算 G^B mod P,并将其发送给Alice。
-
计算共享密钥:
- Alice收到 G^B mod P 后,利用自己的私钥 A 计算 (GB)A mod P = G^(AB) mod P。
- Bob收到 G^A mod P 后,利用自己的私钥 B 计算 (GA)B mod P = G^(AB) mod P。
至此,Alice和Bob都得到了相同的值 G^(AB) mod P,这个值可以作为他们的共享秘密密钥。
安全性分析
Eve在整个过程中可以看到 P、G、G^A mod P 和 G^B mod P。为了得到共享密钥 G^(AB) mod P,Eve似乎需要从 G 和 G^A mod P 中恢复出 A(即求解 G^A ≡ H (mod P) 中的 A),这被称为离散对数问题。目前没有已知的经典计算机多项式时间算法能解决此问题。Diffie-Hellman协议的安全性基于一个更强的假设——Diffie-Hellman假设,即给定 G、G^A mod P 和 G^B mod P,计算 G^(AB) mod P 是计算上不可行的。
RSA加密系统
Diffie-Hellman协议解决了密钥交换问题。接下来我们看看RSA系统,它能够更直接地实现公钥加密:任何人都可以使用公钥加密消息,但只有持有私钥的接收者才能解密。
密钥生成
RSA的第一步由接收者(例如Bob)完成:
- Bob选择两个巨大的随机质数 P 和 Q。这是他的私钥,必须严格保密。同时,他需要确保 P-1 和 Q-1 都不能被3整除(对于一般化的RSA,是指与加密指数 e 互质)。
- Bob计算 N = P * Q。N 就是他的公钥,可以公开给任何人(包括Alice和Eve)。
此时,系统的安全性依赖于大整数分解问题的困难性,因为一旦Eve分解了 N 得到 P 和 Q,她就掌握了Bob的私钥。
加密过程
当Alice想发送明文消息 X 给Bob时:
- 她需要确保 X 是模 N 乘法群 Z_N^* 中的一个元素。Z_N^* 包含所有小于 N 且与 N 互质的正整数。如果消息太长,可以分块处理;在实际应用中,明文 X 通常会先进行填充(加入随机数据),以防止重复加密相同明文产生相同密文,避免泄露信息。
- 加密操作非常简单:Alice计算 X^3 mod N(这里使用3作为加密指数,实际中可以使用其他合适的值,常记为 e)。
- Alice将密文 X^3 mod N 发送给Bob。
解密过程
Bob收到密文 C = X^3 mod N 后,需要恢复 X。他利用私钥(P 和 Q)进行如下操作:
- 由于Bob知道 P 和 Q,他知道乘法群 Z_N^* 的阶 φ(N) = (P-1)(Q-1)。
- 他需要找到一个整数 K,使得 3K ≡ 1 (mod φ(N))。因为 3 与 φ(N) 互质(由 P-1 和 Q-1 不被3整除保证),这样的 K 一定存在,并且可以使用扩展欧几里得算法高效求出。K 就是解密指数(常记为 d)。
- Bob对密文进行解密运算:计算 C^K mod N。
- 因为 C^K ≡ (X3)K ≡ X^(3K) (mod N)。
- 又因为 3K ≡ 1 (mod φ(N)),所以 3K = t * φ(N) + 1。
- 根据欧拉定理:若 X 与 N 互质,则 X^(φ(N)) ≡ 1 (mod N)。
- 因此,X^(3K) ≡ X^(t * φ(N) + 1) ≡ (X(φ(N)))t * X ≡ 1^t * X ≡ X (mod N)。
- 这样,Bob就成功恢复出了明文 X。
安全性讨论
Eve看到的是公钥 N 和密文 C = X^3 mod N。她面临的RSA问题是从 C 和 N 中恢复 X。这显然不比分解 N 更容易,但反之(即证明破解RSA等价于分解 N)仍未解决,这是一个开放性问题。我们通常假设RSA问题是困难的(RSA假设)。
陷门单向函数
RSA的本质是一个陷门单向函数。函数 f(x) = x^3 mod N 是单向的:已知 N 时容易计算但难以求逆。然而,如果知道一个“陷门”秘密(即 N 的分解 P 和 Q),求逆就变得容易。陷门单向函数是公钥密码学的基础。
一个有趣的应用:RSA约会协议
最后,我们来看一个展示RSA巧妙的“安全约会”协议。Alice和Bob想知道彼此是否愿意约会,但如果不愿意,他们不希望对方知道自己曾有意向。
协议步骤
-
Alice准备:
- Alice生成RSA密钥对:私钥 (P, Q),公钥 N = P * Q。
- 她创建两个消息:
- X:编码为“0”(表示“不感兴趣”),并用随机数填充。
- Y:编码为“1”(表示“感兴趣”),并用随机数填充。
- 她将 N、X^3 mod N 和 Y^3 mod N 发送给Bob。Bob无法解密,因此不知道哪个对应“1”。
-
Bob响应:
- 如果Bob不感兴趣,他随机选择一个 R ∈ Z_N^*,计算 (X^3) * (R^3) mod N 并发回给Alice。
- 如果Bob感兴趣,他随机选择 R,计算 (Y^3) * (R^3) mod N 并发回给Alice。
-
Alice解密:
- Alice利用私钥计算收到消息的立方根,得到 X * R mod N 或 Y * R mod N。由于 R 是随机的,她无法判断这是 X 还是 Y,因此无法确定Bob的意向。
- Alice将这个结果(X*R 或 Y*R)直接发回给Bob。
-
Bob解读:
- Bob收到 X*R 或 Y*R 后,除以自己知道的 R。
- 如果他自己当初选择的是 X(即不感兴趣),那么他得到 X,并知道Alice发送的是“0”(不感兴趣),但他仍然不知道如果自己当初选 Y 会得到什么结果。
- 如果他自己当初选择的是 Y(即感兴趣),那么他得到 Y,并解码出“1”,从而知道Alice也感兴趣。
这个协议保证了只有当双方都表示感兴趣时,双方才会知道对方有意向。如果一方不感兴趣,则无法探知另一方的真实想法。该协议依赖于双方诚实地执行步骤,更高级的协议(如使用零知识证明)可以防止作弊行为。
本节课中我们一起学习了公钥密码学的两大基石:Diffie-Hellman密钥交换协议和RSA加密系统。我们理解了它们如何利用数论难题(离散对数、大整数分解)来实现安全的通信,并看到了RSA在解决特定安全问题上的一个创造性应用。这些概念构成了现代安全通信的基础。
021:零知识证明与量子计算
在本节课中,我们将要学习两个激动人心的主题:零知识证明和量子计算。这两个主题都是对之前所学知识的精彩应用。
上一节我们介绍了更多密码学知识,特别是公钥密码学。本节中,我们来看看零知识证明这个听起来有些反直觉的概念。
零知识证明
传统的证明方式是,如果你想让我相信某件事为真,你会写下证明过程。我阅读并验证后,就被你说服了。但在这个过程中,你将证明本身交给了我,我因此获得了向他人证明的能力。
零知识证明试图捕捉这样一种想法:你能否在不透露任何额外信息的情况下,仅仅说服我某件事是真的?例如,你只想让我相信你拥有某个问题的答案,但不想告诉我答案本身。你希望对方除了“你知道答案”这一事实外,一无所知。
让我们从一个非计算机科学的例子开始。
可乐与百事可乐的例子
假设我认为可乐和百事可乐味道不同。如何在不透露配方等额外信息的情况下,仅仅让你相信“对我来说,它们味道不同”这一事实?
我们可以进行以下互动协议:你随机选择一杯可乐或百事可乐(不告诉我),然后让我品尝并判断是哪一种。如果我们反复进行这个游戏,而我每次都能正确区分,那么你就能确信,对我来说,这两种饮料味道确实不同。
在这个协议中,你没有学到可乐或百事可乐的化学配方,你只学到了“对我来说它们味道不同”这一比特信息。更重要的是,你无法回家向你的室友证明这一点,因为这个协议是我们之间的互动过程。这是一种“最不有用”的证明形式,因为你除了知道陈述为真外,没有学到任何可以用于说服他人的额外信息。这正是零知识证明的核心。
图非同构的零知识证明
现在,让我们看一个更形式化的计算机科学例子:图非同构问题。
首先,我们需要理解图同构的概念。两个图 G 和 H 是同构的,如果可以通过重新标记顶点名称使它们完全相同。图同构问题(GI)是 NP 问题,因为你可以提供一个顶点间的映射关系(同构)作为证书,我可以在多项式时间内验证。
然而,图非同构问题(即判断两个图是否不同构)则不那么直观。如何提供一个简短的证明来说服别人两个图不同构?
我们可以设计一个零知识协议,其思路与可乐-百事可乐测试类似。
以下是协议步骤:
- 验证者随机选择图 G 或图 H。
- 验证者对该图的顶点应用一个随机置换,生成一个新图,并将其发送给证明者。
- 证明者需要判断这个新图是由 G 还是 H 置换而来的,并将答案(G 或 H)告诉验证者。
- 重复此过程多次。
我们来分析这个协议:
- 完备性:如果两个图确实不同构,那么所有与 G 同构的图和所有与 H 同构的图是两个不相交的集合。全能的证明者总能正确判断新图源自哪个原图。因此,在“是”实例(即不同构)中,证明者获胜的概率为 1。
- 可靠性:如果两个图实际上是同构的,那么从 G 或 H 出发,经过随机置换后得到的图的分布是完全相同的。证明者没有任何信息可以判断来源,只能随机猜测,每次猜对的概率是 1/2。如果我们重复协议 k 次,证明者仅在全部 k 轮中都猜对时才能欺骗验证者,这个概率是 1/2^k,当 k 足够大(例如 100)时,这个概率可以忽略不计。
这个协议的关键特性是零知识。验证者在与证明者互动后,除了“图 G 和 H 不同构”这一事实外,没有学到关于这两个图的任何额外信息。
如何形式化“没有学到额外信息”这个概念?思路是:假设存在一个模拟器,它知道验证者所知道的一切,并且额外知道“图 G 和 H 不同构”这一事实。如果这个模拟器能够完美地模拟(预测)验证者与真实证明者之间的整个互动过程(即协议记录),那么就意味着真实的协议互动没有给验证者带来任何超出那一事实的新知识,因为验证者自己(在知道那一事实后)也能生成完全相同的互动记录。
三染色问题的零知识证明
图非同构的证明者被假设为全能的。但在现实中,我们更常遇到的情况是:证明者只是一个知道某个特定问题(如数独)答案的普通人。我们希望对于任何 NP 问题,都能构造零知识证明。
我们可以从 NP 完全问题入手,例如三染色问题:给定一个图,能否用三种颜色给顶点着色,使得任意相邻顶点颜色不同?
假设证明者知道该图的一个有效三染色方案,并希望在不透露具体方案的情况下,让验证者相信这一点。
一个简单的物理协议如下:
- 证明者将有效的染色方案写在图上,然后用贴纸盖住每个顶点的颜色。
- 验证者进入房间,选择一条边(两个相邻顶点)。
- 证明者揭开这两个顶点上的贴纸,验证者检查它们的颜色是否不同。
- 验证者离开,证明者擦除并重新随机化染色(例如,随机置换三种颜色的标签),然后重复步骤1-3多次。
分析这个协议:
- 完备性:如果证明者确实拥有有效染色,并且每次都诚实执行,那么验证者每次检查都会看到不同颜色。因此,完备性为 1。
- 可靠性:如果图不可三染色,那么任何染色方案至少存在一条边连接两个同色顶点。验证者单次检查恰好选中这条“坏边”的概率约为 1/|E|(边数分之一)。通过重复协议多次(例如 |V|^3 次),验证者被欺骗(即始终没选中坏边)的概率会变得极低。
- 零知识:在每一轮中,证明者都重新随机化染色方案。验证者每次只看到两个随机、不同的颜色,这些颜色与之前的轮次无关。因此,验证者没有获得关于特定染色方案的任何信息。如果验证者事先相信图是可三染色的,他完全可以自己模拟出每次会看到一对随机不同颜色的结果。
要将此物理协议转化为可通过互联网执行的数字协议,我们需要用到公钥加密(如 RSA)来实现“比特承诺”:
- 证明者对每个顶点的颜色(附加随机数后)进行加密,然后将密文列表发送给验证者。这相当于用贴纸盖住了颜色。
- 验证者选择一条边(两个顶点),请求证明者解密这两个顶点的密文。
- 证明者提供解密结果,验证者用公钥验证解密正确性,并检查两个颜色是否不同。
- 重复此过程。
这样,我们就实现了对三染色问题(进而对任何 NP 问题)的零知识证明。
零知识证明的应用
零知识证明在密码学中非常有用。例如,在之前提到的“约会协议”中,零知识证明可以确保参与方在遵循协议的同时,不泄露自己的私有信息。更广泛地,它可用于安全多方计算,使得多个互不信任的参与方能够共同计算一个函数,而不会泄露各自的输入信息,例如“百万富翁问题”或联合计算总额而不暴露个人数据。
上一节我们探讨了零知识证明如何让我们在不泄露信息的情况下进行验证。本节中,我们来看看另一个突破性的计算范式——量子计算。
量子计算
什么是量子计算?让我们从计算模型的发展谈起。
我们学习了 P(多项式时间确定性图灵机),将其视为高效计算的模型。后来,我们看到了 BPP(有随机性的多项式时间计算)。关于“宇宙本质上是确定性的还是随机的”的哲学争论,会影响我们将 P 还是 BPP 视为更基础的高效计算模型。
量子计算的出现源于类似的观察:自然界似乎能够高效地模拟量子力学系统,但我们没有已知的经典(确定性或随机)多项式时间算法来做到这一点。例如,预测化学反应中分子的行为需要求解薛定谔方程,这在经典计算机上是极其困难的。
理查德·费曼等人提出了一个革命性的想法:与其试图在经典计算机上模拟量子系统,不如直接利用遵循量子力学规律的物理系统来构建计算机——即量子计算机。这样,我们就能自然获得模拟量子系统的能力。
更令人惊讶的是,这种能力不仅限于模拟物理系统。彼得·肖尔发现,量子计算机能够在多项式时间内分解大整数,而这正是 RSA 等公钥密码系统安全性的基础假设。这表明,量子计算可能提供超越经典计算的根本性新能力。
从经典计算到量子计算
为了理解量子计算,我们首先用新的数学语言重新描述经典(概率)计算。
- 状态:一个概率比特的状态可以表示为一个二维概率向量
(p0, p1),其中p0是比特为 0 的概率,p1是比特为 1 的概率,且p0 + p1 = 1,所有元素非负。 - 操作:对比特的操作(逻辑门)可以表示为矩阵。该矩阵作用于状态向量。为了保持向量的概率性质(即输出仍为一个有效的概率分布),操作矩阵必须是随机矩阵(每列元素之和为 1,且元素非负)。例如,非门(NOT)的矩阵是
[[0, 1], [1, 0]]。 - 测量:当我们“查看”一个比特时,以概率
p0得到 0,以概率p1得到 1。
量子计算是对这个框架的推广,只需改变一个关键点:将概率的 1-范数约束改为振幅的 2-范数约束。
- 状态:一个量子比特(qubit)的状态是一个二维复向量
(α, β)。它满足|α|^2 + |β|^2 = 1。这里|α|^2解释为测量时得到 0 的概率,|β|^2是得到 1 的概率。α 和 β 称为振幅。这种状态通常用狄拉克符号表示为|ψ⟩ = α|0⟩ + β|1⟩,其中|0⟩ = (1, 0)^T,|1⟩ = (0, 1)^T。 - 操作:对量子比特的操作是保持 2-范数为 1 的矩阵,即酉矩阵(U^† U = I)。酉矩阵是复数域上的正交矩阵。例如,量子非门(泡利-X 门)的矩阵与经典非门相同:
[[0, 1], [1, 0]]。 - 测量:当我们测量一个量子比特
|ψ⟩ = α|0⟩ + β|1⟩时,结果以概率|α|^2坍缩为 0,以概率|β|^2坍缩为 1,并且量子比特的状态随之变为对应的|0⟩或|1⟩。
量子计算的威力源于量子比特可以处于叠加态(即 α 和 β 均不为零的状态),以及量子门操作可以产生并利用纠缠等经典世界不存在的现象。这使得量子算法(如肖尔算法)能够以指数级加速解决某些特定问题。
本节课中我们一起学习了零知识证明和量子计算的基本概念。零知识证明允许我们在不泄露任何额外知识的情况下验证陈述的真实性,其核心思想是通过交互式协议和模拟器概念来实现。量子计算则提供了一种基于量子力学原理的新型计算模型,它利用量子比特的叠加和纠缠特性,有望在解决某些问题上超越经典计算机的能力,例如大数分解。这两个领域都是理论计算机科学中深刻而迷人的应用。
022:量子比特基础与纠缠
在本节课中,我们将学习量子计算的基础知识,包括单个量子比特(qubit)的状态、测量和演化,以及两个量子比特的纠缠现象。我们将从最简单的概念开始,逐步深入,确保初学者能够理解这些看似复杂的量子力学原理。
单个量子比特
上一节我们介绍了课程的背景,本节中我们来看看量子计算中最基本的单元:量子比特。
一个量子比特的状态可以表示为0和1状态的叠加。它本质上是一个向量,由两个复数(称为振幅)组成。这个向量必须满足归一化条件,即两个振幅的绝对值的平方和为1。
公式:一个量子比特的状态可以表示为:|ψ⟩ = α|0⟩ + β|1⟩,其中 |α|² + |β|² = 1。
如果α和β是实数(本课程中大多数情况如此),那么所有可能的叠加态就构成了一个单位圆。当α=1,β=0时,是|0⟩态。当α=0,β=1时,是|1⟩态。这两个状态是正交的。
另外两个重要的状态是|+⟩态和|-⟩态:
|+⟩ = (|0⟩ + |1⟩) / √2|-⟩ = (|0⟩ - |1⟩) / √2
对量子比特可以做的两件基本操作是测量它,或者通过酉变换来演化它。
测量是一个破坏性且不可逆的过程。当你测量一个量子比特α|0⟩ + β|1⟩时,你会以|α|²的概率得到结果0,以|β|²的概率得到结果1。测量后,量子比特的状态会坍缩为你所看到的那个经典状态。
酉变换是对振幅向量进行的线性变换,它总是将单位向量映射到另一个单位向量。一个矩阵是酉矩阵,当且仅当其逆矩阵等于其共轭转置。酉矩阵本质上就是旋转和反射。
以下是几个重要的酉矩阵例子:
- 恒等操作:
I = [[1, 0], [0, 1]] - 非门(X门):
X = [[0, 1], [1, 0]] - Z门:
Z = [[1, 0], [0, -1]](对|1⟩态的振幅乘以-1) - 哈达玛门(H):
H = (1/√2) * [[1, 1], [1, -1]]。它在|0⟩/|1⟩基和|+⟩/|-⟩基之间进行转换,并且是其自身的逆。
|+⟩和|-⟩态可以完美区分,因为你可以先应用一个哈达玛门,然后再测量。正交状态之所以能被完美区分,是因为你总可以先通过一个酉变换将它们旋转到|0⟩和|1⟩态。
量子力学描绘的宇宙图景是,整个宇宙的状态就是一个在复向量空间中旋转的单位向量。
一个非常重要的概念是全局相位不可观测。状态|0⟩和-|0⟩在物理上是完全相同的,因为任何测量得到的概率都只取决于振幅的绝对值平方。然而,相对相位是可观测的。叠加态|0⟩+|1⟩和|0⟩-|1⟩可以通过测量完美地区分开。
另一个有用的酉变换是45度旋转门R。它将|0⟩态映射到|+⟩态,将|+⟩态映射到|1⟩态,依此类推。如果对|0⟩态应用R然后测量,会以一半的概率得到0或1,这被认为是本质上不可约的随机性。
有趣的是,如果你从|+⟩态开始,应用R然后测量,你总是会得到1。如果你从|-⟩态开始,应用R然后测量,你总是会得到0。这引出了量子力学的核心现象:振幅干涉。
振幅干涉与双缝实验
上一节我们介绍了单个量子比特的操作,本节中我们通过双缝实验来理解振幅干涉这一核心概念。
当对叠加态进行变换时,最终某个结果的振幅是所有可能路径到达该结果的振幅之和。如果这些振幅有的为正,有的为负,它们可能会相互抵消,导致总振幅为零,这意味着该结果永远不会被观测到。这就是干涉。
著名的双缝实验是展示干涉的经典例子。光子一次一个地射向带有两条狭缝的屏幕,然后观察它们落在第二块屏幕上的位置。实验发现,光子会形成明暗相间的干涉条纹。有些位置光子永远不会出现。
然而,如果你关闭一条狭缝,那些原本光子永远不会出现的位置,现在光子却可以出现了。更奇怪的是,如果你试图监测光子究竟通过了哪条狭缝(例如设置一个测量装置),干涉条纹就会消失,结果变得符合经典概率的叠加规则。
关键在于,任何泄露“光子通过哪条缝”这一信息到外部环境的行为,都会破坏干涉。这也是建造量子计算机如此困难的原因:必须让量子系统与外部环境高度隔离,才能保持其量子特性(如干涉)。宏观物体(如猫)因为包含大量粒子,极易与环境相互作用,所以我们很难看到宏观的量子叠加现象。
两个量子比特与张量积
理解了单个量子比特和干涉后,我们现在可以探讨两个量子比特的系统,这里会出现更多有趣的现象。
两个量子比特的状态需要用一个包含四个振幅的向量来描述,分别对应四个可能的经典状态:00, 01, 10, 11。这些振幅同样需要满足归一化条件。
公式:|ψ⟩ = α|00⟩ + β|01⟩ + γ|10⟩ + δ|11⟩,其中 |α|² + |β|² + |γ|² + |δ|² = 1。
我们可以对这个四维向量进行测量或施加4x4的酉变换。
构造多量子比特状态和操作的一个有用工具是张量积。它表示将两个系统“放在一起”。
- 状态
|0⟩⊗|0⟩就是|00⟩。 - 状态
|0⟩⊗|+⟩等于(|00⟩ + |01⟩)/√2。 - 状态
|+⟩⊗|+⟩等于(|00⟩+|01⟩+|10⟩+|11⟩)/2,即所有四个字符串的均匀叠加。
同样,我们也可以对操作进行张量积。例如,操作I ⊗ H表示对第一个量子比特什么都不做,对第二个量子比特进行哈达玛变换。这对应一个4x4的矩阵。在量子计算中,当我们说“对第8个量子比特进行H操作”时,实际意思是应用操作I ⊗ I ⊗ ... ⊗ H ⊗ ... ⊗ I,其中H只在第8个位置。
并非所有的两量子比特状态都可以写成两个单量子比特状态的张量积。例如,状态(|00⟩ + |11⟩)/√2就无法分解。我们可以通过反证法证明:假设它可以分解为(a|0⟩+b|1⟩) ⊗ (c|0⟩+d|1⟩),那么通过比较系数会导出矛盾abcd=0和abcd=1/2。
定义:
- 一个多量子比特状态如果可以写成各量子比特状态的张量积,则称为可分离态。
- 如果不能,则称为纠缠态。
要产生纠缠,需要量子比特之间的相互作用。仅对各个量子比特单独进行操作无法产生纠缠。一个著名的两量子比特门是受控非门。
受控非门是一个酉变换,其作用是:如果第一个(控制)量子比特是|1⟩,则对第二个(目标)量子比特应用非门;否则什么都不做。
代码/矩阵表示:
CNOT = [[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 0, 1],
[0, 0, 1, 0]]
它不能写成两个单比特操作的张量积。
我们可以使用哈达玛门和受控非门来生成纠缠态:
- 从
|00⟩开始。 - 对第一个量子比特应用H门,得到
(|00⟩+|10⟩)/√2。 - 以第一个量子比特为控制位,第二个为目标位,应用CNOT门。
|00⟩保持不变,|10⟩变为|11⟩。最终得到纠缠态(|00⟩+|11⟩)/√2。
纠缠的含义与测量
现在我们来探讨纠缠的物理含义,这涉及到对复合系统的一部分进行测量。
一个重要规则是,你可以只测量多个量子比特中的一部分。例如,对于两量子比特态α|00⟩+β|01⟩+γ|10⟩+δ|11⟩,如果只测量第一个量子比特,看到0的概率是|α|²+|β|²,看到1的概率是|γ|²+|δ|²。
测量后,整个系统的状态会坍缩。如果测得第一个量子比特为0,那么第二个量子比特的新状态是(α|0⟩+β|1⟩)/√(|α|²+|β|²)(即重新归一化)。如果测得第一个量子比特为1,则第二个量子比特的新状态是(γ|0⟩+δ|1⟩)/√(|γ|²+|δ|²)。
对于可分离态,测量一个量子比特不会影响另一个。但对于纠缠态(|00⟩+|11⟩)/√2,情况则不同:
- 如果测量第一个量子比特得到0,那么你立即知道第二个量子比特也一定是0。
- 如果得到1,那么第二个量子比特也一定是1。
- 无论两个量子比特相距多远(比如一个在地球,一个在月球),这个关联都瞬间成立。
这似乎暗示了“鬼魅般的超距作用”,曾让爱因斯坦深感不安。他认为这应该能用经典的“隐变量”理论来解释,即两个粒子在分离时就约定好了未来的行为。
然而,约翰·贝尔在1964年证明,存在一些基于纠缠态的测量实验,其结果无法用任何经典的、局部的隐变量理论来解释。贝尔不等式表明,量子力学预言的相关性比任何经典理论所允许的都要强。这已被实验反复证实。
尽管如此,不可通信定理保证了我们无法利用纠缠实现超光速通信。该定理指出,无论Alice对她持有的那部分纠缠量子比特做什么操作(酉变换或测量),都无法影响Bob对他那部分量子比特进行测量得到结果的概率分布。因此,量子力学在保持“无法超光速传递信息”这一相对论要求的同时,展现了一种全新的、非经典的关联形式。
不可克隆定理
最后,我们讨论量子信息的一个关键特性:不可克隆。
在经典世界,信息可以随意复制。但在量子世界,你无法完美复制一个未知的量子态。这就是不可克隆定理。
证明非常简单。假设存在一个克隆酉操作U,对于任意单量子比特态|ψ⟩ = α|0⟩+β|1⟩,我们希望它满足:U(|ψ⟩⊗|0⟩) = |ψ⟩⊗|ψ⟩ = α²|00⟩+αβ|01⟩+αβ|10⟩+β²|11⟩。
等号左边是|ψ⟩⊗|0⟩ = α|00⟩+β|10⟩,这是(α, β)的线性函数。而等号右边包含了α², β², αβ等项,这是非线性的。不存在一个线性变换(酉变换是线性的)能够实现从线性到非线性的映射。因此,这样的克隆机不可能存在。
这个定理有深远的影响。它意味着量子信息具有内在的私密性,不能被窃听者在不留痕迹的情况下复制。这为量子密码学(如量子密钥分发)和量子货币等应用奠定了基础。
总结
本节课中我们一起学习了量子计算的基础知识。我们从单个量子比特的叠加态、测量和酉变换开始,理解了振幅干涉这一核心现象。接着,我们探讨了两个量子比特的系统,引入了张量积、纠缠态的概念,并学会了如何使用受控非门产生纠缠。我们分析了纠缠的奇特性质,包括其非经典的关联性以及它如何通过贝尔不等式与经典观念划清界限,同时又受制于不可通信定理。最后,我们了解了不可克隆定理,它揭示了量子信息无法被完美复制的根本特性。这些概念构成了理解更复杂量子算法和协议的基础。
023:量子算法与BQP类
在本节课中,我们将学习量子计算中的核心概念,包括BQP复杂性类的定义,以及两个关键的量子算法:Deutsch-Jozsa算法和Simon算法。我们还将探讨BQP与其他经典复杂性类(如P、NP和PSPACE)的关系,并简要了解Shor的因式分解算法背后的思想。
BQP类与Deutsch-Jozsa算法
上一节我们介绍了通用量子门集和量子电路的概念。本节中,我们来看看如何定义量子计算中的高效复杂性类,即BQP。
BQP(有界误差量子多项式时间)是所有决策问题的集合,这些问题可以通过一个多项式大小的量子电路,在多项式数量的量子比特上,以至少2/3的概率得到正确答案。这可以看作是经典P类或BPP类的量子版本。
现在,我们来看一个具体的量子算法例子:Deutsch-Jozsa算法。这是第一个被发现的量子算法,它展示了量子叠加如何实现经典上不可能的速度提升。
该算法解决的问题是:给定一个函数 f,它接收一个比特并输出一个比特,且承诺 f 要么是常数函数(对所有输入输出相同),要么是平衡函数(对一半输入输出0,另一半输出1)。目标是判断 f 是常数函数还是平衡函数。
经典确定性算法在最坏情况下需要查询函数两次。而Deutsch-Jozsa算法只需查询一次。
以下是该算法的量子电路:
- 初始化两个量子比特为 |0⟩ 和 |1⟩。
- 对第一个量子比特应用哈达玛门(H),得到叠加态 (|0⟩ + |1⟩)/√2。
- 对第二个量子比特应用哈达玛门后得到 (|0⟩ - |1⟩)/√2。
- 应用量子黑盒(Oracle)U_f,它实现变换:|x, a⟩ → |x, a ⊕ f(x)⟩。
- 再次对第一个量子比特应用哈达玛门。
- 测量第一个量子比特。
算法的核心思想是利用量子叠加和干涉。通过将第二个寄存器预置为“减号”态 (|0⟩ - |1⟩)/√2,应用 U_f 后,输入态 |x⟩ 的振幅会乘以 (-1)^(f(x))。当对叠加态 (|0⟩ + |1⟩)/√2 进行此操作后,根据 f 是常数还是平衡,最终测量结果会确定性地不同,从而仅用一次查询就解决了问题。
虽然这个算法只带来了常数倍的加速,但它清晰地展示了量子叠加和干涉的原理。
Simon算法:指数级加速
上一节我们看到了一个常数倍加速的量子算法。本节中,我们来看一个能实现指数级加速的算法:Simon算法。
Simon算法解决的是一个“黑盒”问题。给定一个函数 f: {0,1}^n → {0,1}^n,并承诺存在一个非零的秘密字符串 s ∈ {0,1}^n,使得对于所有 x, y,有:
f(x) = f(y) 当且仅当 y = x ⊕ s
这里 ⊕ 表示按位异或。我们的目标是通过尽可能少的查询来找出这个秘密字符串 s。
首先分析经典情况:
- 确定性算法在最坏情况下可能需要查询 O(2^n) 次。
- 利用“生日悖论”,随机化算法平均需要 O(2^(n/2)) 次查询来找到一个碰撞对 (x, y),使得 f(x) = f(y),然后通过 s = x ⊕ y 得到答案。可以证明,Ω(2^(n/2)) 也是经典随机算法所需的查询下界。
现在,Simon的量子算法仅需 O(n) 次查询就能找到 s,实现了指数级加速。
以下是Simon算法的步骤:
- 创建叠加:初始化两个 n 量子比特寄存器为 |0⟩⊗n。对第一个寄存器应用哈达玛门,创建所有可能输入的等幅叠加态:**(1/√(2n)) Σ_x |x⟩|0⟩**。
- 查询Oracle:应用实现函数 f 的黑盒变换 U_f,得到态:(1/√(2^n)) Σ_x |x⟩|f(x)⟩。
- 测量第二寄存器(可选):测量第二个寄存器会坍缩到一个特定的 f(x) 值。根据量子力学原理,第一个寄存器会坍缩到所有能产生该 f(x) 的 x 的叠加态。由于函数的性质,这将是两个字符串 x 和 x ⊕ s 的等幅叠加态:(|x⟩ + |x ⊕ s⟩)/√2。注意,我们并不关心 f(x) 的具体值,测量它只是为了对第一个寄存器产生所需的效果。
- 再次应用哈达玛门:对第一个寄存器(现在处于 (|x⟩ + |x ⊕ s⟩)/√2 态)再次应用哈达玛门。利用哈达玛门的性质:H^⊗n |x⟩ = (1/√(2^n)) Σ_z (-1)^{x·z} |z⟩,其中 x·z 是点积模2。应用后得到态:(1/√(2^n)) Σ_z [ (-1)^{x·z} + (-1)^{(x⊕s)·z} ] |z⟩。
- 测量第一寄存器:测量第一个寄存器会得到一个 n 比特字符串 z。振幅公式表明,只有当 (-1)^{x·z} 和 (-1)^{(x⊕s)·z} 同号时,z 的出现概率才非零。这等价于条件:s·z = 0 (mod 2)。因此,测量结果 z 是一个满足 s·z = 0 的随机字符串。
- 重复与求解:重复上述过程 m 次(m = O(n)),收集到一系列线性方程:s·z_1 = 0, s·z_2 = 0, ..., s·z_m = 0。这些是模2线性方程。通过经典的高斯消元法,我们可以高效地解出满足所有方程的 s。由于 s 非零,当收集到大约 n 个线性无关的方程时,就能以高概率唯一确定 s。
整个算法对黑盒 f 仅进行了 O(n) 次查询,其余都是经典多项式时间处理,从而实现了相对于经典算法的指数级加速。
从Simon算法到Shor算法
Simon算法解决了一个看似人为的黑盒问题。然而,它的结构直接启发了Peter Shor,在不到一年后提出了著名的量子因式分解算法。
Shor算法的核心是将因式分解问题转化为周期寻找问题。具体思路如下:
- 给定一个合数 N,随机选择一个与 N 互质的整数 x。
- 考虑函数 f(r) = x^r mod N。这是一个周期函数,其周期 s 是 x 在模 N 乘法群中的阶,它整除 φ(N) = (p-1)(q-1)(p, q 是 N 的质因数)。
- 如果能找到周期 s,再利用一些数论知识,就有很高概率推导出 N 的因子。
寻找函数 f(r) 的周期,在结构上与Simon问题非常相似,只不过是在整数加法群 Z 上而非比特串群 Z_2^n 上寻找周期。Shor的突破在于使用了量子傅里叶变换(QFT)来代替Simon算法中的第二次哈达玛变换。
量子傅里叶变换是一种线性变换,它能将时域(或输入域)的周期性,转换到频域(或输出域)的集中性。在对函数 f 进行量子查询并丢弃输出寄存器后,输入寄存器会坍缩到所有相差周期 s 的 r 值的叠加态。对此态应用量子傅里叶变换,测量结果会以高概率给出与周期 s 相关的信息,经过少量重复和经典后处理,即可得到周期 s。
因此,Shor算法本质上是一个更精巧的周期寻找算法,它利用了问题的代数结构,并通过量子傅里叶变换实现了指数加速。
BQP类与其他复杂性类的关系
现在我们已经了解了BQP中的一些具体问题。本节中,我们来看看BQP与我们已经学过的其他经典复杂性类之间的关系。
已知的包含关系如下:
- P ⊆ BQP:任何经典多项式时间算法都可以被量子电路轻易模拟(例如,经典控制器可以直接输出硬编码答案的量子电路)。
- BPP ⊆ BQP:量子计算机可以通过测量处于|0⟩态的量子比特来生成随机比特,从而模拟经典概率算法。
- BQP ⊆ PSPACE:一个量子计算过程可以通过计算指数多条路径的振幅和来经典模拟,而这可以在多项式空间内完成(虽然需要指数时间)。更强的结论是 BQP ⊆ PP ⊆ PSPACE。
- BQP ⊆ EXP:通过直接存储和演化指数大小的态向量,可以在指数时间内经典模拟任何量子计算。
关于BQP与NP的关系,是未解难题:
- NP ⊆ BQP?:即量子计算机能否在多项式时间内解决NP完全问题?目前未知。如果存在这样的算法,它将与Shor或Grover算法都截然不同。已知的是,对于黑盒搜索问题(在N个元素中找一个标记项),经典需要 O(N) 次查询,而Grover量子搜索算法仅需 O(√N) 次查询,这为许多问题提供了平方加速,但不足以将指数时间问题变为多项式时间。
- BQP ⊆ NP?:即量子计算机的答案是否总有一个简短的经典证明?不一定。因式分解问题同时在BQP和NP中。但可能存在一些BQP中的问题,其答案验证需要指数时间,甚至可能不在多项式谱系(PH)中。
总结来说,复杂性类的关系可以大致想象为:P和BPP包含在BQP中;NP完全问题位于NP内部;像因式分解这样的问题在NP内但可能既不在P中也不是NP完全;BQP的范围可能超出NP,延伸至PSPACE的某处,但始终被包含在EXPTIME中,并且远低于不可判定的停机问题。
总结
本节课中我们一起学习了量子计算复杂性理论的核心内容。我们首先定义了量子高效计算类BQP。然后,通过Deutsch-Jozsa算法,我们看到了量子叠加如何实现常数倍加速。接着,深入探讨了Simon算法,它通过对黑盒函数的巧妙查询和干涉,实现了相对于经典算法的指数级加速,并直接启发了Shor的因式分解算法。最后,我们梳理了BQP与P、NP、PSPACE等经典复杂性类之间的已知关系和未解问题。量子计算为特定问题带来了前所未有的速度提升,但其能力范围仍然受到经典计算理论框架的约束。

浙公网安备 33010602011771号