《computational complexity》笔记:基本复杂度类
《computational complexity》作为理论计算的基础,对我这种初学者来说,值得精读并做一些笔记。笔记主要用于整理和记录自己的理解。
the computational model
最初的目标是构造一个计算的模型。这个模型可以看作一个集合,这个集合中的每个元素相当于某一个具体问题的解决方案,也就是一个“程序”;这个集合整体就是一个计算模型,也就是一个可以运行任何“程序”的“计算机”。所以构造一个计算模型的目标,分别从程序和计算机的角度就是要规定程序如何表达和程序如何运行。
直观上来说“计算”就是已有一些“数据”和一些的“草稿纸”,按照“解题思路”每次在数据和稿纸中拿出一些数据进行计算,将结果写在稿纸上或写在“答题纸”上。构造的计算模型应该符合这一直觉。
我们还希望这个模型具有“通用性”,也就是研究“计算”可以建立在这个模型基础上,而非将计算这个本质的概念特殊化,将“可计算”等问题的研究限定在当今世界中。这样,理论计算才能成为一门永恒的科学,而非日新月异的技术。
turing machine
图灵机的一些细节
一个图灵机可以看作一个程序。
纸带和针头(数据草稿纸):多个纸带,纸带上面每个位置可以写单个字符,每条纸带有一个针头,每次可以向左或向右移动一个单位,也可不动。有一个输入纸带,表示给定的数据;一个输出纸带,在运行结束时输出纸带上的值就代表输出结果;其他纸带均用于存储中间运算的结果。设有\(k\)个纸带,纸带上字符集大小为\(\Gamma\)
状态(临时记忆):状态只是一个抽象的数,但作为一个临时的记忆,可以存储的东西种类很多,例如“程序进行到第几步了”,“上一秒从纸带读入的数据是哪些”等等,但因为只是一个数,可以认为记录的信息量是关于读入\(O(1)\)的。状态是集合\(Q\)的一个元素。
计算一步的过程:从每个纸带的针头处读取一个元素,再根据读取的元素和目前的状态决定下一个状态,这些针头处的值如何修改,以及每个针头分别如何移动,或者选择结束计算(达到了终止状态\(q_{halt}\))。那么整个计算的运行时间就可以看作这样的计算的步数。
转移函数(解题思路):由于修改和移动完全取决于针头处的值和目前的状态,因此可以将每次计算看作一个函数\(\delta:Q\times \Gamma^k \rightarrow Q\times \Gamma^{k-1}\times \{L,S,R\}^k\)。
值得注意的是,“状态”这个数不是可有可无的,比如说我想将纸带的某个位置的值\(x\)移到纸带末尾,那么我在移动的每一步“必须要记住\(x\)的值”,这个值是无法在纸带的读入中得到的,所以必须要将\(x\)的值作为一个临时记忆放在状态里以便转移。
定义的普遍性
先定义一个图灵机的运行时间:如果对于所有长度为\(n\)的输入,运行时间不超过\(T(n)\),则称运行时间为\(T(n)\)。
可以从以下几点中感受图灵机模型定义的普遍性:字符集大小的任意性,纸带条数的任意性,纸带可以是双向延伸也可以是单向延伸。这里的任意性说的是在一种模型下的任一程序,可以对应到另一模型下的一个程序使得输出相同,且运行时间不慢太多。
对于任意\(k+2\)个纸带的图灵机,运行时间\(T(n)\),存在三个纸带的图灵机得到相同的结果,运行时间\(kT(n)\log T(n)\)。
证明:将用于草稿的\(k\)个纸带变成一个纸带,字符集\(\Gamma\)变成\(\Gamma^k\),然后\(k\)个针头的移动转化成\(k\)条纸带分别平移,直接暴力平移是\(kT(n)^2\)的。优化每条纸带的平移可以优化到\(T(n)\log T(n)\),算法如下:类似倍增的方法,以针头为中间点,左右从中间向两边按\(2,4,8,...,2^k,...\)依次分块,保证\(2^k\)的块内有效元素个数为\(2^k\)或\(2^{k-1}\)或\(0\),其他元素用空字符填充,且对称(块大小相同的两个块)内有效元素个数之和为\(2^k\)。以左移距离,先找到右侧第一个有效元素数不为\(0\)的块\(2^t\),那么右侧\(2,4,8,...,2^{t-1}\)这些块为空。将\(2^t\)块内的\(2^{t-1}\)个元素取出,依次放到针头处,\(2,4,8,...,2^{t-1}\)这些块各填满一半,对于左侧,进行相反的操作,将针头处,\(2,4,8,...,2^{t-1}\)这些块的元素各拿出一半,放到\(2^t\)处。例如|oooo|aa|i|oo|bcdd|变为|ooaa|oi|b|co|ddoo|。注意到如果访问到\(2^k\)块,单次复杂度为\(O(2^k)\),但此后至少\(2^{k-1}\)内不会再访问到\(2^{k-1}\)块,因此每块均摊复杂度\(O(T(n))\)。
图灵机对现代计算机程序的模拟:将现代计算机程序编译为机器语言后,大致只有三种操作:(a)将内存中的信息写入有限大小的寄存器 (b)将寄存器中的信息写入内存 (c)将寄存器中两个数取出运算得到第三个数。可以将内存和寄存器分别设计为两个纸带,而加法乘法等运算也可以通过图灵机实现。这样一个现代程序就转变成了一个图灵机。
至此我们可以感受到,将可解决的问题定义为在有限时间内可解,或是在多项式时间内可解,那么在图灵机模型上可以解决的问题(存在一种图灵机可解决)都不比任何计算机少。除了加入随机化,或考虑量子计算模型,计算的研究都可以基于图灵机模型进行。
oblivious turing machine 对于相同的输入长度,每个时刻针头的位置相同,也就是针头位置的移动只与读入的长度有关,与读入的数据无关。一种简单的实现方式是针头所在的位置用特殊字符标记,每次针头都从纸带最左端移到最右端再移回来,复杂度是\(O(T(n)^2)\)。oblivious turing machine性质更好,在之后NP问题的规约中有一些应用。如果某问题存在一个图灵机可解,那么一定存在oblivious turing machine可解,但为什么不直接用oblivious turing machine作为计算模型,我的理解是由于判定一个图灵机是否是oblivious turing machine似乎非平凡,因此会导致转移函数对应到计算模型时会有困难,影响之后的二进制表示等。
图灵机的二进制表示 一个很重要的观察是,如果我们规定字符集大小和纸带数量,那么转移函数可以映射到图灵机(只不过有的图灵机会runtime error,可以定义RE为直接输出0),而转移函数也可由二进制来编码,规定编码方式后二进制串可以映射到转移函数(不合法编码要求的可以定义为直接输出0的图灵机)。那么一个图灵机也可以作为另一个图灵机的输入和输出。将图灵机\(M\)的二进制表示记做\(M_{(2)}\),二进制串\(s\)对应的图灵机为\(M_s\)。另外,一个二进制串可以映射到一个图灵机,但任何一个图灵机的转移函数可以有无穷种,因此可以对应到无穷个二进制串,这个细节在以后的证明中会带来很多方便。
universal turing machine 利用图灵机的二进制表示,可以将图灵机作为输入1, 图灵机的输入作为输入2,设计一个图灵机计算其他图灵机的运算结果。这个图灵机也相当于一个程序,但可以运行其他程序,似乎有点像操作系统的概念。具体实现就是用三个工作纸带,分别表示需要需要模拟的程序的二进制表示,模拟的程序的纸带,和目前的状态,再利用\(O(T(n)\log T(n))\)的合并纸带的算法,就可以得到\(O(T(n)\log T(n))\)的结果。
可解问题
不可计算问题
存在图灵机上不可解问题。即存在一个函数\(L:\{0,1\}^{*} \rightarrow \{0,1\}^{*}\),不存在任何图灵机\(M\)使得\(M(\alpha)=L(\alpha)\)对所有\(\alpha\)成立。
证明:利用图灵机的二进制表示。令\(UC(\alpha)\)为\(M_{\alpha}(\alpha)\)结果的第一位的逆,如果\(M_{\alpha}(\alpha)\)运行中发生错误,或者死循环,则\(UC(\alpha)=0\)。那么假设\(UC\)可解,即\(UC(\alpha)=T(\alpha)\),而\(UC(T_{(2)})\ne T(T_{(2)})\),因此矛盾。
我有一个证明存在不可计算问题的想法,因为可能存在多个图灵机解决同一判定问题,但不存在一个图灵机解决多个判定问题,因此可以从基数的角度来思考。\(\{0,1\}^*\)是所有长度有限的二进制串,可以对应到自然数,因此是可数集,基数与\(N\)相同,那么\(L:\{0,1\}^{*}\rightarrow \{0,1\}\)的总数就是\(2^N\);而单纸带字符集大小为\(2\)的图灵机算法由\(\delta:Q\times \{0,1\}^2\rightarrow Q\times \{0,1\} \times \{L,S,R\}^2\)决定,\(Q\)是有限集,对于大小为\(|Q|=n\),图灵机的个数是\(c(18n)^{4n}\),是有限集,可数个有限集的并生然是可数集,基数与\(N\)相同,因此我们知道可解决的问题(或者说算法个数)是可数的。由于\(2^N=R\)和\(N\)的基数不同,因此一定存在不可解问题。在第三章就可以看到,上述不可计算问题的构造本质是“对角化”,最初就是一个证明实数不可数的方法。(另外,线性可解的问题也是无穷个,因为输出读入串的第\(n\)位显然存在线性算法,那么线性可解的问题和可解的问题基数相等,存在一一映射,那么这个映射的本质是什么呢?)
停机问题不可解。停机问题定义为:给定一个程序和输入,判断程序是否终止。
证明:假设停机问题可解。那么存在图灵机\(T\)可解\(UC\)问题,\(T\)的执行过程为,先利用停机问题的图灵机判定\(M_{\alpha}(\alpha)\)是否停机,如果不停机直接输出\(0\),否则利用universal turing machine来模拟并将结果的第一位取反,这样得到\(UC\)的解,与上一定理矛盾。
值得一提的是,不可解问题的研究受到哥德尔不完备定理的启发很大。希尔伯特提出的猜想是构建一个公理系统,任何可以形式化的命题都可以通过推导证真或证伪(complete,完备性),且不存在某个命题既真又伪(sound,一致性),且这个公理系统可以证明自己complete and sound。哥德尔不完备定理否定了这一猜想。哥德尔定理有两条:包含皮亚诺公理的系统如果是一致的,那么不是完备的;包含皮亚诺公理的系统不能自证一致性。
如果反过来用停机问题来证明哥德尔不完备定理也是可行的。包含皮亚诺公理的系统中一定存在\(+,\times,=,>,\vee,\wedge,\neg,\forall,\exists\),那么图灵机的运行过程可以用这些符号形式化地写出,令\(\phi(\alpha,x,t)\)表示\(M_{\alpha}(x)\)是否在\(t\)步以内停机,停机问题可以被表示为\(\exists t:\phi(\alpha,x,t)=1\),由于任何命题可以在有限步内证真或真伪,那么可以按照长度枚举所有证明过程(假设证明过程也可以写成一个数字串),这个算法一定可以在有限步内得到停机问题的解。
P复杂度类
复杂度类就是不同计算资源可解决问题的集合,例如可解问题的类,就是图灵机可以解决的问题集合;多项式时间可解问题的类,就是多项式运行时间的图灵机可解的问题集。
语言(language)\(L\)定义为\(f_L:\{0,1\}^*\rightarrow \{0,1\}\),\(f_L(x)=1\Leftrightarrow x\in L\)。之后对复杂度类的讨论基本都建立在language这样的判定性问题上。
DTIME复杂度类和P复杂度类:\(L\in DTIME(T(n))\)定义为存在一个图灵机和常数\(c\)运行时间不超过为\(cT(n)\)可以求解\(f_L\)。\(P=\bigcup_{c\ge 1}DTIME(n^c)\)
之前已经说明了,P复杂度类不受计算模型的影响,利用图灵机定义出的P的集合大小不小于任何确定性的计算模型。P复杂度类可以被看作实践中可解的问题集合,我认为P复杂度类之所以用多项式\(n^c\)定义,是因为在实际程序设计中,“for循环”往往是程序实现的主体,尤其是在非指数级的问题中(指数级的问题可以认为是难解的),所以用\(n^c\)作为基准更方便判断一个问题是否存在高效算法。实际上这个基准具体是什么并不重要,因为只是作为一个增长趋势的大体区间,如果能找到一个函数列\(f_c\),使得\(\lim_{n\to +\infty}f_c(n)/n^c=t\)常数,那么\(P=\bigcup_{c\ge 1}DTIME(f_c(n))\)。例如\((1+\sin n)^n\)就不在P内,因为在一些\(n\)处会达到指数级,因此P类的核心是,对任意\(n\)(等价于除了有限个正数以外的任意数),对任意长度为\(n\)的输入,效率都很高,正所谓“最坏情况”。
我认为这个复杂度类依然有其局限性,因为其定义的“可高效计算”,只是人为地用多项式增长趋势作为标准,是否有可能在未来会存在一些应用广泛的算法复杂度为\(T(n)=O(n^{10})\),虽然现在来看多项式算法的复杂度主要源于循环嵌套,但存在可能,\(T(n)\)是一类特殊但简洁的函数,其增长的趋势通过计算以后发现介于\(O(n^9)\)到\(O(n^{10})\)之间,那么这类函数实际也是难以计算的。因此对于“易于计算”计算的概念,可能还需要更为本质的定义。
NP and NP completeness
这一章的内容部分在《算法导论》上有介绍,这里就简单概括一下。
NP复杂度类:\(L\in NP\)当且仅当存在多项式运行时间的图灵机\(M\),存在多项式\(p\)使得\(x\in L\Leftrightarrow \exists u\in \{0,1\}^{p|x|} s.t. M(x,u)=1\),此时\(u\)被称为证书(certificate)
非确定性图灵机(NDTM):有两个转移函数\(\delta_0,\delta_1\),和特殊状态\(q_{accept}\in Q\),每一步可以任选转移函数进行转移,设\(M\)为NDTM,\(M(x)=1\)当且仅当存在一种转移函数的选择情况,使得最终可以达到状态\(q_{accept}\)。NDTM的运行时间为\(T(n)\)当且仅当对任意输入\(x\in \{0,1\}^*\)和任意转移函数的选择,在\(T(n)\)步内,要么达到终止状态,要么达到\(q_{halt}\)要么达到\(q_{accept}\)。
NTIME复杂度类:\(L\in NTIME(T(n))\)定义为存在一个NDTM和常数\(c\)运行时间不超过为\(cT(n)\)可解\(L\)
定理:\(NP=\bigcup_{c\ge 1}NTIME(n^c)\)
证明:对于\(L\in NTIME(n^c)\),可以将每次转移函数的选择作为certificate,那么certificate长度也是多项式级别的,因此\(L\in NP\);对于\(L\in NP\),直接用NDTM来写一串certificate,之后就当成TM运行即可。
EXP复杂度类:\(EXP=\bigcup_{c\ge 1}DTIME(2^{n^c})\)。易得\(P\subseteq NP\subseteq EXP\)。
NEXP复杂度类:\(NEXP=\bigcup_{c\ge 1}NTIME(2^{n^c})\),易得\(EXP\subseteq NEXP\)。
定理:若\(P=NP\),则\(EXP=NEXP\)
证明:这里用到了"padding technique",即通过添加无意义的0延长读入的长度来降低算法复杂度。若\(L\in NEXP\),\(L\in NTIME(2^{n^c})\),令\(L_{pad}=\{<x,'0'^{2^{n^c}}>:x\in L\}\),则\(L_{pad}\in NP\),\(L_{pad}\in P\),那么解决\(L\)问题只需用一个多项式时间的TM来解决\(L_{pad}\),因此\(L\in EXP\)。
coNP复杂度类:\(coNP:=\{L:\bar{L}\in NP\}\)
另外一个等价定义是:\(L\in coNP\)当且仅当存在图灵机\(M\),多项式\(p\),对所有\(x\notin L\)都有\(\exists u\in \{0,1\}^{p|x|},M(x,u)=0\)。多项式时间的NDTM无法解决所有coNP问题,coNP和NP的定义也本质不同,因此NP和coNP是不同的复杂度类。直觉上NP和coNP可以互相“规约”是错误的,因为这里所谓的“规约”是在假定\(P=NP\),即NP问题存在高效算法的基础上的。
对比可以发现NP复杂度类中的问题\(L\),别人很容易向你证明\(x\in L\)(只需要给出certificate即可),而很难让人相信\(x\notin L\);而coNP复杂度类中的问题相反,容易证明\(x\notin L\)而难证\(x\in L\)。
可以同样使用Cook-Levin Theorem的证明过程,将\(L\in coNP\)转化为是否对所有取值都不满足CNF表达式,即SAT问题的补属于coNP-complete。
规约和NP-Completeness
规约就是用较小运算资源(比如说研究NP时使用P的资源等)实现问题的转化,规约大概有两个作用:对不同复杂度类而言,考虑其他资源是否可解决complete问题即可在不同复杂度类中更方便地讨论包含关系,例如若\(TQBF\in NP\),则\(PSPACE=NP\);对不同问题而言,规约会使得在复杂度类的层面上问题的“难度”可以比较,例如若\(L\le_p SAT\),则\(L\in NP\)。这两个作用分别需要用到两个定理的证明:如果\(L\le_a L'\),\(L'\in P'\),则\(L\in P'\);如果\(L\le_a L'\),\(L'\le_a L''\),则\(L\le_a L''\)
规约(reductions):称language \(L\subseteq \{0,1\}^*\)多项式时间Karp reducible到language \(L'\subseteq \{0,1\}^*\),记做\(L\le_p L'\),当且仅当存在多项式时间内可计算的函数\(f:\{0,1\}^*\rightarrow \{0,1\}^*\)使得\(x\in L \Leftrightarrow f(x)\in L'\)
可以证明这个规约满足上述两个性质。
NP-hardness and NP-completeness:称\(L'\)为NP-hard当且仅当\(\forall L\in NP:L\le_p L'\),称\(L'\)为NP-complete当且仅当\(L\in NP\)且\(L\)为NP-hard。
我们可以看到,如下问题就是NP-completeness:\(\{<\alpha,x,n,t>:\exists u\in \{0,1\}^n,M_{\alpha}(x)=1 in t steps\}\),传入\(n\)和\(t\)是为了方便输出0的情况的终止。对任意问题,令\(\alpha=M_{(2)}\),\(n=p(|x|)\),\(t=T(|x|)\)即可归约到该问题。
Cook-Levin Theorem:SAT和3SAT是NP-complete问题
证明:首先对于任意\(f:\{0,1\}^n\rightarrow \{0,1\}\)(\(n\)个01变量对应的函数),存在一个CNF表达式长度不超过\(n2^n\)(长度定义为运算个数),即对每个\(f(x_1,...,x_n)=\bigwedge_{f(y_1,...,y_n)=0}\bigvee_{1\le i\le n}(x_i\ne y_i)\)。那么对每个NP问题,存在对应的图灵机\(M\),找到\(M\)对应的双纸带、二进制的oblivious图灵机\(M'\),尝试将\(M'\)的运行过程用CNF表达式写出。具体地,对于长度为\(n\)的读入,可以先用任意certificate运行一遍\(M'\)得到每一步图灵机两个针头的位置。对于任意certificate,第\(i\)步的“输入”可以表示为\(z_i=(q_i,tape_{1,a_i},tape_{2,b_i})\),即状态和两个针头的读入,状态由第\(i-1\)步决定,而\(a_i\)和\(b_i\)已知,对应的值分别由读入和上次在\(q_i\)处写值的第\(prev_{i}\)步决定,因此可以写成\(z_i=f(z_{i-1},z_{prev_i},tape_{1,a_i})\)。把\(tape_1\)的certificate部分以及每个\(z_i\)作为变量,构造CNF表达式。\(z_i\)的二进制表示位数是\(O(1)\)的,因此利用\(f(x_1,...,x_n)=\bigwedge_{f(y_1,...,y_n)=0}\bigvee_{1\le i\le n}(x_i\ne y_i)\),\(z_i=f(z_{i-1},z_{prev_i},tape_{1,a_i})\)的表达式长度也是\(O(1)\)的,最终CNF的大小是多项式级别的。证明了任意NP问题都可以规约到SAT,SAT是NP-complete。
要证明3SAT也是NP-complete,只要证明SAT可规约到3SAT。对于长度超过3的表达式\(\bigvee_{1\le i\le n}{y_i}\),可加入新的变量\(z\),将其写成\((y_1 \vee y_2 \vee z) \wedge (\bar{z} \vee \bigvee_{3\le i\le n}{y_i})\),不断进行下去就可以写成3CNF的形式。
另外可以发现,Cook-Levin Theorem的证明过程的规约,实际上可以建立language\(L\)中元素的certificate和对应的SAT问题的certificate的关系,也就是如果能够找到\(x\in L\)的certificate,也可以在多项式时间内找到\(f(x)\in SAT\)的certificate,反之亦然,满足这一性质的规约称为Levin reduction。利用这个性质,我们可以得到如下定理,说明了NP问题虽然定义在判定性问题上,但如果所有NP问题的判定性版本存在高效算法,那么需要输出certificate的查找版本也存在高效算法。
如果\(P=NP\),那么对于任何\(L\in NP\),存在一个图灵机\(T\),使得对所有\(x\in L\),\(T(x)\)均可输出一个\(x\)的certificate。
证明:如果\(P=NP\),那么SAT问题可解。将\(L\)转化为SAT问题,而SAT问题可以通过依次对\(x_i\)找到\(t=0,1\)使得\(x_i=t\)后有解,令\(x_i=t\)并更新CNF表达式,进而找到SAT问题的certificate,再利用Levin reduction的性质还原出\(x\)的certificate。(由于给定\(x\)和certificate前几位判断之后certificate是否有解仍然是NP问题,因此也可以用这个问题的多项式运行时间的解来按位确定\(x\)的certificate)。
diagnalization
证明实数不可数有一个著名的证明:将实数写成无限二进制小数,如果实数可数,那么可以将实数排成一列\(a_1,a_2,...\),那么翻转(将\(x\)变为\(1-x\))\(a_i\)的小数点后第\(i\)位作为新实数的第\(i\)位,那么这个实数与任何\(a_k\)在第\(k\)位都不同,因此矛盾。在证明存在不可解问题中提到,图灵机是可数的,问题基数与实数相同,因此可以用上述对角化证明。而这个对角化有了实际含义,假设所有language均可解,将这些language按照图灵机二进制表示的大小顺序排成一列\(a_1,a_2,...\),其中\(a_i\)可被\(M_{i}\)解决(如果\(M_{i}\)不能解决任何问题,即\(M_{i}\)会在一些输入中不停机,可以跳过这个\(a_i\),不影响所有问题在\(a\)中出现),那么令\(L=\{i:1-M_{i,i}=1\}\),这个language不能被任何\(M_{k}\)解决,至少在\(k\)处错误。实际上第一章的\(UC\)就是这里的\(L\)。
Time Hierarchy Theorem:若\(f(n)\log f(n)=o(g(n))\),则\(DTIME(f(n))\subsetneq DTIME(g(n))\)
证明:这个非常重要的定理说的是更多的时间资源一定可以解决更多的问题。对于上述对角化有个很直观的想法,就是假设允许运行时间为“无限”,那么“运行时间无限的图灵机”可以解决停机问题,即直接模拟任何图灵机“无穷步”(这个其实容易想象,比如说数学归纳法对任意\(n\in N\)可以在有限步内证明成立,但证明所有\(n\in N\)都成立则需要“无穷”步),那么就证明了“无限时间”可以比“有限时间”解决更多的问题。从对角化来看,如果强调\(x\in UC\)当且仅当\(M_{x}(x)\)在“有限”步内输出\(0\),假设存在一个可以在“无穷”步后输出结果的图灵机也可以写成二进制的形式\(\alpha\),那么此时的对角化无法导出矛盾,因为如果\(M_{\alpha}(\alpha)\)在无穷步后输出0,但由于不能在有限步内输出,因此\(\alpha\notin UC\),答案并没有错误,因此解决UC问题的无穷时间图灵机可以逃过对角化的矛盾,但有限步不行。
那么尝试修改上述的说明。令\(f(n)=o(h(n))\),\(h(n)\log h(n)=O(g(n))\),\(h(n)=g(n)/\log g(n)\)即可。我们令运行时间不超过\(x\in L\)当且仅当\(M_{x}(x)\)在\(h(n)\)步内输出0。那么\(L\notin DTIME(f(n))\),因为对任意\(cf(n)\)运行时间的图灵机,会导出对角化的矛盾,在自己的二进制位处的输出与\(L\)不符;而可用universal turing machine模拟\(M_{x}(x)\)运行前\(h(n)\)步的情况,从而得到\(L\in DTIME(h(n)\log h(n))\)。
另外,这里的\(f(n)\)和\(g(n)\)需要是短时间可构造函数(time-constructible function),即\(g(n)\)需要在关于\(g(n)\)的多项式时间内计算出来,否则\(h(n)\)无法显式地计算就无法确定模拟时步数上限。
Nondeterministic Time Hierachy Theroem:若\(f(n+1)\log f(n+1)=o(g(n))\),则\(NTIME(f(n))\subsetneq NTIME(g(n))\)
证明:这个定理不同的一点在于NP问题的补不是NP问题(不能用NDTM解决),所以要用到lazy diagonalization技巧。再次回顾最初的对角化,其实我们不一定要翻转对角线上的元素,我们只要能构造一个函数,每一行都有一个元素与之不同即可,可以把对角化的过程想象成这样:我们从短到长确定每个\(x\in L\)是否满足,依次对于阶段\(i\),要让\(M_{i}\)不能计算\(L\),因此只需要在有限的区间(可以是\(x\)的区间也可以是\(|x|\)的区间)内确定一个\(M(i)(x)\)与\(x\in L\)结果不统一的,然后用剩下的\(x\)进入\(i+1\)的阶段。
注意到\(\neg NTIME(f(n))\subseteq DTIME(2^f(n))\),那么我们在用universal turing machine模仿时,如果允许用指数级的时间就可以取反。令\(h(n)=g(n)/\log g(n)\),\(h(s(i+1))=2^{h(s(i))}\),令\(L\)只考虑全为\(1\)的情况(即只需要对每个\(n\)判断长度为\(n\)的全1串是否在\(L\)内,其他串均不在\(L\)内),利用\((s(i),s(i+1)]\)来拒绝\(M_{i}\)。令全1串\(x\)的长度在\((s(i),s(i+1))\)时\(x\in L\)当且仅当\(M(i)(x+'1')\)在\(h(x)\)步内输出1或不停机,而\('1'^{s(i+1)}\in L\)当且仅当\(M(i)('1'^{s(i)}+'1')\)在\(h(s(i+1))=2^{h(s(i))}\)步内输出0。由于\(M_{i}\)的答案,是\(L\)在\((s(i),s(i+1))\)上的答案右移一位,而\(M_{i}\)在\(s(i)+1\)的答案与\(L\)在\(s(i+1)\)的答案不同(如果运行时间低于\(h\)),因此\(M_{i}\in NTIME(f(n))\)是无法解决该区间的问题;相反,如下图灵机属于\(NTIME(g(n))\),对于\((s(i),s(i+1))\)区间的问题直接用类似的universal nonderministic turing machine来模拟,在\(s(i+1)\)处则爆搜\(h(s(i))\)的每一步,再将结果取反,由于\(h(s(i+1))=2^{h(s(i))}\),可以解决问题。
Ladner's Theroem(NP intermediate languages):如果\(P\ne NP\),则存在\(L\in NP\setminus P\)且\(L\)不为NP-complete。
证明1:以下是Ladner本人用lazy diagonalization的证明。\(L\)不为NP-complete当且仅当不存在任何一个多项式时间可计算的函数\(f\)使得\(x\in SAT\)当且仅当\(f(x)\in L\)(这也说明所有NP-complete问题可以通过图灵机来枚举)。延续上一个定理证明的思路,利用SAT来构造\(L\),阶段\(2i-1\)来使得多项式时间图灵机\(M_i\)不可解决\(L\),阶段\(2i\)使得多项式时间图灵机\(M_i\)对应的可计算函数不能将SAT规约为\(L\),另外还需要保证\(L\in NP\)。那么对于奇数阶段,我们直接令长度区间\([l,r]\)内的所有\(L\)就是对应长度的SAT,要求\(M_i\)不能解决这个区间内的问题,那么\(r\)有界,否则\(M_i\)可解决SAT;对于偶数阶段,令\(L\)不包括长度\([l,r]\)内的串,那么\(r\)有界,否则任意长的SAT问题可多项式时间归约到长度有限的串,SAT可被解决。具体而言,令\(L=\{x:x\in SAT,g(|x|)\mod 2=1\}\),\(g(|x|)\)就对应阶段\(2i-1\)或\(2i\),要是\(L\in NP\)需使得\(g(n)\)可在多项式时间内计算,那么当存在长度不超过\(\log n\)的SAT可以解决该阶段时,就令\(g(n+1)=g(n)+1\),否则\(g(n+1)=g(n)\),那么只需要求出所有长度不超过\(\log |x|\)的SAT问题,就可以求出\(g(1)...g(|x|)\)。最后一个细节是求\(g\)的时候需要用\(M_i\)运行长度不超过\(\log |x|\)的SAT问题,因此必须要保证\(M_i\)的复杂度不能太大,解决方案是重排\(M_i\),令\(M_i'\)在\(x\)上的的运行时间不超过\(i|x|^i\),具体构造就是考虑将原本\(M_i\)运行时间超过\(i|x|^i\)加入一个“队列”,算\(g\)的复杂度不超过\((\log n)^{g(n)}\),在\((\log n)^{g(n)}\)接近\(n\)时令\(g(n+1)=g(n)\)即可。
证明2:以下是书上给出的对SAT做padding的证明。思路是如果对SAT问题padding上过长的0,那么就属于P;如果padding的过短,那么就属于NP-complete。令\(L=\{x+'1'+'0'^{f(|x|)-|x|-1}:x\in SAT\}\)(即把长度\(n\)的SATpad到\(f(n)\)),令\(f(n)=n^{g(n)}\),\(g(n)\)对应阶段\(i\),即要让多项式时间\(M_i\)与\(L\)矛盾。当\(M_i\)与长度不超过\(\log n\)(类似上一证明,为保证\(f\)可计算不能直接用\(n\))的二进制串矛盾时令\(g(n+1)=g(n)+1\),否则\(g(n+1)=g(n)\)。那么阶段\(i\)对应\(n\)的区间不可能有界,否则可将SAT直接pad到多项式长度后用\(M_i\)解决SAT问题。另外,\(L\)不可能是NP-complete,否则由SAT归约到\(L\),再去掉padding部分规约回SAT,规模减小很多,递归下去即可解决SAT问题。具体地,设长度为\(n\)的SAT问题归约到\(O(n^c)\)的\(L\),则令\(g(k)=2c\),若先规约再去掉pad之后的长度超过\(k\),则\(n\)被转化到至多\(n^{1/2}\)的问题,最终归约到有界的SAT问题中。为了快速计算\(f\),也需要用上一证明中的\(M_i'\)来重排。书上等价的描述是令\(g(n)\)为最小的\(i<\log \log n\),使得\(M_i\)运行时间不超过\(i|x|^i\)(此处用到任何一个图灵机有无穷种二进制表达方式这一细节)且可解决所有长度不超过\(\log n\)的问题,如果不存在则令\(g(n)=\log \log n\),这样的定义更清楚,但似乎构造的本质是分阶段让\(M_i\)不可计算\(L\)的本质被掩盖了。
对角化的局限性
本章的最后,阐述了对角化的局限性,即对角化无法证明\(P\ne NP\)。对角化其实只使用了图灵机的两个性质:存在universal turing machine和可便捷地实现图灵机与二进制串的互相转化,而图灵机还有许多其他性质,例如Cook-Levin Theorem用到的存在oblivious turing machine,即每一步只取决于极少的步数,并影响极少的步数。而只用到这两个性质的模型不止图灵机一个,不同的模型就对应不同的P和NP,例如接下来定义的oracle turing machine,一些oracle turing machine会导致\(P=NP\),一些则导致\(P\ne NP\),这也就意味着只使用这两个性质不可能证出\(P\)是否与\(NP\)相等,否则oracle turing machine也只会出现一种情况。
令\(O\subseteq \{0,1\}^*\)为oracle,定义oracle turing machine\(M^O\)表示一类图灵机,增加一个新纸带和三种状态\(q_{yes},q_{no},q_{query}\),每次进入\(q_{query}\)时,就会根据新增的纸带中的串是否属于\(O\)直接跳转到\(q_{yes}\)或\(q_{no}\)。直观理解就是可以多次询问language\(O\)在一些位置的值,例如任何\(coNP\subseteq P^{SAT}\)内。oracle turing machine满足上述两个性质,\(P^O\)和\(NP^O\)是把\(O\)作为oracle时定义的复杂度类。令\(O=\{<M,x,'1'^n>:M(x)=1\ computes\ in\ 2^n\ steps\}\),那么\(P^O=EXP=NP^O\);要让\(P^O\ne NP^O\),对于\(S\),令\(L=\{'1'^n:\exists s\in\{0,1\}^n,s\in S\}\),那么对所有\(S\)都有\(L\in NP^S\),用之前的思路按照多项式运行时间的\(M_i\)划分阶段,令\(M_i\)运行时间\(T(n)\),存在\(2^n>T(n)\),且\(n\)大于之前其他\(M\)取的\(n\),那么\(M_{i}^S\)无法查出长度为\(n\)的所有串,那么对所有查询都返回no,并根据\(M_{i}^S('1'^n)\)来决定未查的串的实际情况,得到\(L\notin P^S\)。
只使用图灵机的这两个性质证明出的结论称为relativizing results。简而言之就是对角化只能够证明出relativizing results,而\(P\ne NP\)并非这样的结果。
Space complexity
SPACE and NSPACE:令language \(L\)满足\(L\in SPACE(s(n))\),当且仅当存在常数\(c\)和一个图灵机\(M\),使得\(M\)解决所有长度为\(n\)的问题除读入纸带外至多访问过不超过\(cs(n)\)个纸带的位置。\(L\in NSPACE(s(n))\),当且仅当存在\(c\)和NDTM\(M\),使用的纸带位置不超过\(cs(n)\)。
\(SAT\in PSPACE\),因此可以得到\(NP\subseteq PSPACE\)。
图灵机的转移函数的定义域,即图灵机每步“可见”的数值可以作为这一步的一种“状态”,但这种状态是可以循环的,只要纸带其他处的值或纸带针头位置不同。我们可以用更直观的方式定义一种“状态”,这样的状态能够包含图灵机在某一步的全部信息。定义图灵机\(M\)在某一固定输入的configuration graphs,图的每个节点对应图灵机的某一步,其中的信息包括纸带所有位置的值,针头的位置,当前的状态\(q\),根据转移函数可得下一步,下一步对应的节点作为该步对应节点的后继。停机的TM和任意选择转移函数的情况下都停机的NDTM对应的图都无环。若在长度为\(n\)上的输入,除了读入纸带外使用了\(S(n)\)的空间,configuration graph的节点数不超过\(O(n2^{S(n)})\),如果\(S(n)\ge \log n\),则直接对图搜索可得\(NSPACE(S(n))\subseteq DTIME(2^{O(S(n))})\)。
Space Hierarchy Theorem:若\(f(n)=o(g(n))\),\(SPACE(f(n))\subsetneq SPACE(g(n))\)
证明与DTIME Hierarchy相同,而且universal turing machine消耗的空间是常数倍的。
\(PSPACE=\bigcup_{c\ge 1}SPACE(n^c)\),\(NPSPACE=\bigcup_{c\ge 1}NSPACE(n^c)\),\(L=SPACE(\log n)\),\(NL=NSPACE(\log n)\)
我们很少讨论sublogarithmic space,主要原因是低于对数的空间无法进行计数运算,例如目前读入纸带针头的位置都无法记录,连\(L=\{'1'^m+'0'+'1'^m\}\)都无法解决,也不存在universal turing machine。不过也可能解决一些非平凡的language,例如\(L=\{1_{(2)}+'\#'+2_{(2)}+'\#'+...+'\#'+n_{(2)}\}\),只计数只需要至多记到\(n_{(2)}\)的长度,即\(\log n\),因此可在\(O(\log \log n)\)内解决。
PSPACE完全问题
这里涉及到了更复杂的规约,由于\(NL\subseteq P\subseteq NP\subseteq PSPACE\),我们定义PSPACE上的规约可以使用不同的计算资源来定义,取决于我们想研究\(P\ne PSPACE\)还是\(NP\ne PSPACE\)。这里仍然使用Karp reduce,类似NP-complete地定义出PSPACE-complete。一般最容易找到地complete问题就是NDTM的运行结果:\(\{<M,w,n>:NDTM\ M\ accepts\ w\ in\ space n \}\)。language TQBF定义为所有由\(\vee,\wedge,\neg,\forall,\exists\)构成的存在解的布尔表达式,这种表达式也一定可以写成\(Q_1x_1...Q_nx_n\phi(x_1,...,x_n)\),\(Q_i\)是\(\forall\)或\(\exists\),\(\phi\)是CNF表达式(如果不是CNF表达式也可以在多项式时间内转化为多项式长度的CNF表达式,至少可以将表达式写成图灵机,再用cook-levin定理)。
TQBF是PSPACE-complete
证明:设有\(n\)个变量,\(\phi\)的长度为\(m\),直接爆搜所有变量的取值即可在空间\(O(n+m)\)内解决。对于任意PSPACE问题,利用configuration graph来构造TQBF:令\(G(C,C')\)表示若读入纸带给定,\(C\)的下一步是否为\(C'\),\(G\)可以用以\(C\)和\(C'\)为变量的多项式长度的CNF表达式写出,那么设\(G(C,C)=1\),可以写成\(\exists C_0,...,C_T, \forall i<T, G(C_i,C_{i+1})=1\),但\(T\)可能是指数级;用倍增,令\(\psi_i(C,C')\)表示至多\(2^i\)步\(C\)是否可以走到\(C'\),\(\psi_i(C,C')=\exists C'',\psi_{i-1}(C,C'')\wedge \psi_{i-1}(C'',C')\),这个表达式又会达到指数级;再用一些技巧,将表达式写成\(\psi_i(C,C')=\exists C''\forall D_1\forall D_2,((D_1=C\wedge D_2=C'')\vee (D_1=C''\wedge D_2=C'))\Rightarrow \psi_{i-1}(D_1,D_2)\),设原空间复杂度\(T(n)\),每次增加\(O(T(n))\)个变量描述\(C'',D_1,D_2\),空间复杂度变为\(O(T(n)^2)\)。
由于总可以把\(Q_1,...,Q_n\)写成\(\exists,\forall,...\)交替的形式,那么TQBF问题的一个现实场景就是棋类的对弈,即是否存在一个先手必胜的策略。对于\(NP\ne PSPACE\)的直觉,也就来自于"games harder than puzzles"。
Savitch's Theorem:对任何space-constructible function \(S(n)\ge \log n\),\(NSPACE(S(n))\subseteq SPACE(S(n)^2)\)
证明:注意到上一命题的证明过程,对NPSPACE也成立,因此可以直接得到\(PSPACE=NPSPACE\)。直接用上一个证明的方法,设\(M=\log |G|=O(S(n))\),求\(\psi_M(S,T)\)可直接爆搜每一个\(i\)对应的\(C'\),递归的深度是\(O(M)\),且每次记录\(i\)只需\(O(M)\)个bit。
NL完全问题
要讨论\(L\ne NL\)就会自然地引出\(NL\)完全问题,那么这时的规约必须只能使用对数空间。然而对数空间会导致连多项式大小的输出都无法完成,因此有了隐式对数空间可计算(implicitly logspace computable)的概念。
implicitly logspace computable:\(f:\{0,1\}^*\rightarrow \{0,1\}^*\)是隐式对数空间可计算的,定义为存在\(c\)使得对所有\(x\)有\(|f(x)|\le |x|^c\),并且\(L_{f}=\{(x,i):f(x)_i=1\}\in L\),\(L'_{f}=\{(x,i):i\le |f(x)|\}\)。\(B\le_l C\)定义为存在这样的\(f\)使得\(x\in B\)当且仅当\(f(x)\in C\),\(C\)是NL-complete定义为\(C\in NL\)且所有\(B\in NL\)满足\(B\le_l C\)。
两个隐式对数计算的函数复合还是隐式对数计算的,只需要在外层的函数访问读入纸带时开一个新的纸带来模仿内层函数计算该位即可。利用这个性质可以说明规约满足我们的两个要求。很容易说明\(PATH=\{<G,s,t>:t\ can\ be\ reached\ from\ s\ in\ directed\ graph\ G\}\)是NL-complete,只记录目前节点编号,一次考虑每条出边,两个转移函数分别考虑走或不走,可以得到\(PATH\in NL\);对于其他\(A\in NL\),\(A\)的configuration graph的邻接矩阵是implicitly logspace computable的,节点数是关于输入长度的多项式,可以归约到多项式长度的\(PATH\)问题。
接下来我们希望找到利用certificate的NL等价定义。注意到NDTM每步的选择本身就与一个从左往右每个位置只能读一次的certificate一一对应,certificate是否只能读一次不影响NP复杂度类,为了让certificate的含义更加直观我们没有要求只读一次。但如果在定义NL时也不要求只读一次,定义出的复杂度类就是NP:首先,如果由多项式时间规约换成对数空间规约,SAT问题仍然是NP-complete,只需要在对数空间求出oblivious turing machine某一步的\(z_i\)对应的布尔表达式,那么只需要在第一遍模拟时用计数器存针头位置,第二遍模拟时算出\(prev_i\)即可;之后,SAT属于这样新定义出的复杂度类,因为在给定变量取值的情况下,仅需要对数空间就可以检验表达式是否合法。为了避免这种情况,我们必须要求对数空间的certificate作为新的纸带,针头只能向右移动,即每个位置只能被读入一次。仍然要求certificate的长度是关于输入多项式级的。
NL等价定义:language\(L\in NL\)当且仅当存在TM\(M\)和多项式\(p\),使得对所有\(x\in \{0,1\}^*\),\(x\in L\Leftrightarrow \exists u\in \{0,1\}^{p(|x|)},M(x,u)=1\)。
最后研究一下coNL复杂度类。\(\overline {PATH}\in coNL\),但实际上有\(\overline{PATH}\in NL\),因此\(coNL=NL\)。
Immerman-Szelepcsényi Theorem:\(\overline{PATH}\in NL\)
证明:构造certificate的思路就是确定从起点开始走至多\(i\)步能到达的点集\(C_i\),又因为内存限制和certificate每位只能访问一次,不过可以只利用集合大小\(|C_i|\)归纳构造。假设已经证明了\(|C_{i-1}|=k\),接下来证明\(|C_i|\)。对每个点\(u\in C_i\),直接给出一条从\(s\)到\(u\)长度不超过\(i\)的路径;对每个点\(u\notin C_i\),按从小到大的顺序利用路径证明\(v\in C_{i-1}\),程序只需要检查\(u\ne v\),\(v\)没有到\(u\)的边,这些\(v\)的个数是\(k\)即可。
那么对所有\(S(n)\ge \log n\),都可以证出\(NSPACE(S(n))=coNSPACE(S(n))\)。只需要对用padding techinique,设\(L\in coNSPACE(S(n))\),\(\bar{L}\in NSPACE(S(n))\),\((\bar{L})_{pad}\in NL\),\(\overline{(\bar{L})_{pad}}\in NL\),\(L_{pad}\in NL\),\(L\in NSPACE(S(n))\)。
Polynomial Hierarchy
Time space tradeoff for SAT: 定义\(TISP(T(n),S(n))\)为\(O(T(n))\)运行时间和\(O(S(n))\)运行空间的图灵机可计算的language。\(SAT\notin TISP(n^{1.1},n^{0.1})\)。
证明:只需证\(NTIME(n)\subseteq TISP(n^{1.2},n^{0.2})\)。分别说明\(TISP(n^{12},n^2)\subseteq \Sigma_2TIME(n^8)\)和若\(NTIME(n)\subseteq DTIME(n^{1.2})\)则\(\Sigma_2TIME(n^8)\subseteq NTIME(n^{9.6})\),第一部分可以按\(n^6\)将configure graph分块证明,第二部分将\(\forall\)转化为\(\neg \exists\)再用NDTM即可。
Boolean circuits
布尔电路和图灵机一样,都是计算模型。研究不同计算模型的原因是各种模型对应不同现实应用场景,且不同问题问题在这些模型中研究的难度也不一样。图灵机似乎是一个相对复杂的计算模型,例如一个图灵机是否停机甚至是不可解问题,但布尔电路看起来要直观很多。
布尔电路(boolean circuits):\(n\)个输入的布尔电路是一个有向无环图,有\(n\)个入度为0的点(sources)表示\(n\)个01变量,其他节点(gates)上写有\(\wedge,\vee,\neg\),入度分别为\(2,2,1\),所有点出度任意,存在一个出度为0的点作为输出节点(sink)。每个节点的出边传递的数是入边的数进行节点上的运算得到的结果,对于\(x\in \{0,1\}^n\),输出结果\(C(x)\)是输出节点的运算结果。电路的大小(size)为图上的节点数,电路的深度(depth)为sources到sink的最长路长度。
circuit families:\(T(n)\)size circuit families定义为布尔电路的序列\({C_n}_{n\in N}\),且存在常数\(c\),使得对所有\(n\)有\(|C_n|\le cT(n)\)
复杂度类\(P_{/poly}\):令\(SIZE(T(n))\)为language\(L\)满足存在\(T(n)\)size circuit families\({C_n}_{n\in N}\),使得\(x\in L\Leftrightarrow C_{|x|}(x)=1\)。\(P_{/poly}=\bigcup_{c\ge 1}SIZE(n^c)\)。