以 3SAT 到 CLIQUE 为例逐项审查归约方向、构造、双向等价与 NP 成员性。
依据本地课程资料 lectures/chap8.pdf、dis10.pdf、dis11.pdf、dis12.pdf 重绘;交互用于解释算法状态与证明不变量,不替代正文中的完整论证。
CS170 · 第 9 讲
本章是全书的转折点:在经历了七章高效算法之后,我们直面那些历经数十年仍未找到多项式时间解法的计算问题。我们将建立 NP 完全性理论,揭示这些看似迥异的难解问题本质上是同一问题的不同伪装,并展示如何通过多项式时间归约将它们串联成一个紧密的网络。
本章的核心研究对象是搜索问题(search problem):给定一个实例 I(输入数据),寻找一个满足特定规格的对象 S(解),或报告不存在这样的解。
本书前七章讨论的最短路径、最小生成树、最大流、最大匹配等问题,虽然候选解空间呈指数级增长——\(n\) 个男孩与 \(n\) 个女孩有 \(n!\) 种匹配方式、\(n\) 个顶点的图有 \(n^{n-2}\) 棵生成树——但都找到了巧妙绕过穷举搜索的高效算法。这些算法的运行时间是输入大小的多项式函数(如 \(n\)、\(n^2\)、\(n^3\))。
然而本章引入的新问题,至今未发现任何显著优于穷举搜索的多项式时间算法。为了理解这种困难性的深远意义,我们先考察指数增长的威力。
指数增长的寓言:根据传说,国际象棋发明者 Sissa 请求国王在棋盘第一格放 1 粒米、第二格 2 粒、第三格 4 粒,依此类推翻倍至第 64 格。总数为
\[2^{64} - 1 = 18\,446\,744\,073\,709\,551\,615\]
足以将印度铺满好几遍。Malthus 由此论证人口的指数增长终将耗尽线性增长的资源;Moore 则观察到芯片晶体管密度每 18 个月翻番,这便是 Moore 定律。
摩尔定律的两面性:表面上看,硬件的指数级进步似乎让指数时间算法变得可接受——只需等待即可。但事实恰恰相反。假设一个 \(O(2^n)\) 的布尔可满足性(SAT)算法运行 1 小时,1975 年可解 25 个变量、1985 年 31 个、1995 年 38 个、如今约 45 个——每增加一个变量需等待约 1.5 年,而应用需求的增速远超于此。相比之下,\(O(n)\) 或 \(O(n\log n)\) 算法每十年可处理的问题规模乘以约 \(100\) 倍;\(O(n^2)\) 算法乘以约 \(10\) 倍;即便是 \(O(n^6)\) 这样不够优雅的多项式算法,每十年也能将可解规模翻倍有余。
这一反转揭示了一个深刻事实:指数算法在摩尔定律下仅能取得多项式级别的进展,而多项式算法则能取得指数级别的进展。要让摩尔定律真正转化为解决问题的能力,我们需要高效的多项式算法。
搜索问题的形式化:
一个搜索问题由以下性质定义:对于实例 I,存在一个验证算法 \(C(I, S)\),当且仅当 S 是 I 的解时输出 \(\text{true}\),且 \(C\) 在 \(|I|\) 的多项式时间内运行。此外,解 S 的长度必须是 \(|I|\) 的多项式(以保证可读性)。
以 SAT 为例:\(I\) 是一个合取范式(CNF)布尔公式,\(S\) 是一个真值赋值,验证算法只需检查 \(S\) 是否使每个子句中至少一个文字为 \(\text{true}\),这显然是多项式时间的。
工作示例:摩尔定律下不同复杂度算法的可解规模对比
假设某固定计算任务耗时 1 小时,比较不同复杂度算法在硬件每 10 年提速约 \(100\) 倍(对应摩尔定律)时可处理的问题规模 \(n\):
\(O(2^n)\) 算法:每 10 年规模仅增加约 \(\log_2(100) \approx 6.6\)。从 1975 年的 \(n=25\) 到 2025 年仅增至约 \(n=25 + 5 \times 6.6 \approx 58\)。进展极其缓慢。
\(O(n)\) 算法:规模乘以 \(100\)。1975 年 \(n=25\),1985 年 \(n=2500\),1995 年 \(n=250\,000\),呈爆炸式增长。
\(O(n^6)\) 算法:规模乘以 \(100^{1/6} \approx 2.15\)。每十年仍能翻倍,远优于指数算法。
这直观展示了为什么指数算法在实际中几乎无用,而多项式算法能充分利用硬件进步。
本节系统介绍一系列重要的搜索问题,其中一些问题我们已在前面章节见过高效算法,而另一些则因微小的结构差异变得极其困难。
布尔可满足性 SAT 与 3SAT
SAT 的实例是合取范式(CNF)公式,即若干子句的合取,每个子句是若干文字的析取(文字 = 变量或其否定)。例如:
\[(x \lor y \lor z) \land (x \lor y) \land (\lnot y \lor z) \land (\lnot z \lor x) \land (x \lor y \lor z)\]
SAT 要求找到使每个子句至少有一个文字为真的赋值。对于 \(n\) 个变量,朴素算法需检查 \(2^n\) 种赋值。
SAT 有两个多项式时间可解的特例:Horn SAT(每个子句至多一个正文字,可用贪心算法求解)和 2SAT(每个子句两个文字,可通过强连通分量在线性时间求解)。然而一旦允许子句包含三个文字,得到的 3SAT 问题就再次变得困难。
旅行商问题 TSP
给定 \(n\) 个城市及其两两之间的距离 \(d_{ij}\),以及预算 \(b\),寻找一条恰好访问每个城市一次并返回起点的回路(tour),使其总长度 \(\leq b\)。TSP 原本是优化问题(求最短回路),但我们将其改写为搜索问题以便统一框架:优化版本可通过二分搜索调用搜索版本来求解(见习题 8.1)。
TSP 与最小生成树(MST)形成鲜明对比:MST 是多项式时间可解的,而 TSP 可视为 MST 的"困难表亲"——TSP 要求树不能分叉(即为一条路径/环),这一结构限制显著增加了复杂度。
Euler 路径与 Rudrata 环
Euler 路径访问每条边恰好一次,其多项式时间可解性由 Euler 刻划:连通且至多两个顶点度数为奇数。
Rudrata 环(Hamilton 环)访问每个顶点恰好一次,与 TSP 惊人地相似,至今未有多项式时间算法。Euler 问题与 Rudrata 问题的复杂度鸿沟源于"边 vs 顶点"的差异,而非"路径 vs 环"的差异(后者可通过简单归约等价化)。
割与平衡割
最小割(Min-Cut)可通过 \(n-1\) 次最大流计算在多项式时间求解。但平衡割(Balanced Cut)要求将顶点分为两个大小均 \(\geq n/3\) 的集合且割边数 \(\leq b\),这是一个困难问题,在图像分割等应用中有重要价值。
整数线性规划 ILP 与零一方程 ZOE
ILP 要求整数向量 \(x\) 满足 \(Ax \leq b\),即使 LP 有多项式时间算法,ILP 仍是困难的。ZOE 是 ILP 的特例:寻找 0-1 向量 \(x\) 使 \(Ax = \mathbf{1}\)(\(A\) 为 0-1 矩阵),其简洁形式在归约理论中极有价值。
3D 匹配
二分匹配(男孩-女孩)可归约为最大流而高效求解。3D 匹配引入第三维度(男孩-女孩-宠物),要求找出 \(n\) 个不相交的三元组覆盖所有成员,这一微小推广使其变为困难问题。
独立集、顶点覆盖、团
独立集(Independent Set)要求 \(g\) 个两两不相邻的顶点;顶点覆盖(Vertex Cover)要求 \(b\) 个覆盖所有边的顶点;团(Clique)要求 \(g\) 个两两相邻的顶点。三者在一般图上均为困难问题,在树上独立集可高效求解。
最长路径与背包问题
最短路径可高效求解,但最长路径(简单路径、总权重 \(\geq g\))是困难的。背包问题(Knapsack)的 \(O(nW)\) 动态规划在输入规模上是指数级的(因涉及 \(W\) 而非 \(\log W\))。子集和(Subset Sum)是背包的特例(价值=权重、目标=容量),同样困难。
下表总结了困难问题(NP 完全)与容易问题(在 P 中)的对比:
| NP 完全(困难) | P(容易) |
|---|---|
| 3SAT | 2SAT, Horn SAT |
| TSP | 最小生成树 |
| 最长路径 | 最短路径 |
| 3D 匹配 | 二分匹配 |
| 背包 | 一元背包 |
| 独立集 | 树上的独立集 |
| ILP | 线性规划 |
| Rudrata 路径 | Euler 路径 |
| 平衡割 | 最小割 |
工作示例:SAT 实例的验证与不可满足性分析
考虑 SAT 实例:\((x \lor y \lor z) \land (x \lor y) \land (\lnot y \lor z) \land (\lnot z \lor x) \land (x \lor y \lor z)\)。
验证算法 \(C(I, S)\) 的执行过程(设赋值 \(x=\text{true}, y=\text{true}, z=\text{true}\)): 1. 子句 \((x \lor y \lor z)\):\(x\) 为真 ✓ 2. 子句 \((x \lor y)\):\(x\) 为真 ✓ 3. 子句 \((\lnot y \lor z)\):\(z\) 为真 ✓ 4. 子句 \((\lnot z \lor x)\):\(x\) 为真 ✓ 5. 子句 \((x \lor y \lor z)\):\(x\) 为真 ✓
该赋值满足前四个子句但最后一个子句要求至少一个变量为真——等等,最后一个子句也是 \((x \lor y \lor z)\),在 \(x=\text{true}\) 时为真。实际上需检查所有赋值:中间三个子句 \((x \lor y)\)、\((\lnot y \lor z)\)、\((\lnot z \lor x)\) 迫使 \(x=y=z\),而结合首末两个子句的约束可证明不存在满足全部五个子句的赋值(提示:分析三个中间子句如何约束三者取相同值)。
此例展示了验证可在多项式时间完成(逐个子句检查),但寻找满足赋值可能需要穷举。
为精确讨论计算复杂性,我们引入两个核心复杂性类。
P 类(Polynomial time)
P 是所有可在多项式时间内求解的搜索问题的集合。即存在算法,输入实例 \(I\),在 \(O(|I|^k)\) 时间内返回一个解 \(S\)(如果存在),或正确报告无解。前一章讨论的最短路径、最小生成树、最大流等问题均属于 P。
NP 类(Nondeterministic Polynomial time)
NP 是所有多项式时间可验证的搜索问题的集合。即存在验证算法 \(C(I, S)\),当且仅当 \(S\) 是 \(I\) 的解时输出 \(\text{true}\),且运行时间为 \(|I|\) 的多项式。
NP 名称源于"非确定性多项式时间":想象一种能在每一步正确猜测的非确定性算法,它能在多项式时间内找到一个解并验证。这等价于"多项式时间可验证"的搜索问题定义。
历史注记:NP 最初定义为判定问题(是/否问题)的类,源于形式语言理论的研究传统。搜索问题版本与其本质相通。
P 与 NP 的关系
显然 \(\text{P} \subseteq \text{NP}\):若一个问题可在多项式时间求解,则给出解后自然可在多项式时间验证(只需求解并比较)。核心问题是反向包含是否成立:\(\text{P} \stackrel{?}{=} \text{NP}\)。
绝大多数研究者相信 \(\text{P} \neq \text{NP}\)。理由包括:数十年来无数聪明头脑未能找到这些困难问题的多项式算法;数学定理的"寻找证明"是一个搜索问题且属于 NP——若 \(\text{P} = \text{NP}\),则将存在高效方法证明任何定理,数学家就不再被需要了。
然而证明 \(\text{P} \neq \text{NP}\) 本身极其困难,是数学和计算机科学中最重要的未解难题之一。
搜索问题的空间结构
假设 \(\text{P} \neq \text{NP}\),搜索问题的空间可想象为一个从易到难的谱系:底部是 P(多项式时间可解),顶部是 NP 完全(NP 中最难的问题),中间可能存在既非 P 也非 NP 完全的问题(如因数分解)。
工作示例:多项式时间验证算法的执行
以 3SAT 为例。验证算法 \(C(I, S)\) 的伪代码:
function VerifySAT(I, S):
// I = CNF 公式, S = 真值赋值
for each clause C in I:
clause_satisfied = false
for each literal l in C:
if l is variable x and S[x] == true:
clause_satisfied = true
if l is negated variable not-x and S[x] == false:
clause_satisfied = true
if clause_satisfied == false:
return false
return true
复杂度分析:设公式有 \(m\) 个子句、\(n\) 个变量,每个子句最多 3 个文字。外层循环 \(m\) 次,内层最多检查 3 个文字,赋值查找为 \(O(1)\)(数组索引)。总时间 \(O(3m) = O(m)\),是输入大小的多项式。
这展示了 NP 定义的核心:验证一个给定解是高效的,但寻找解可能需要穷举 \(2^n\) 种赋值。
要证明某个问题没有高效算法,我们需要比"尚未发现算法"更强有力的证据。归约(reduction) 提供了这种证据。
搜索问题的归约
从搜索问题 A 到搜索问题 B 的归约由两个多项式时间算法组成:
\(f\):将 A 的任意实例 \(I\) 变换为 B 的实例 \(f(I)\);
\(h\):将 B 的任意解 \(S\)(针对 \(f(I)\))回推为 A 的解 \(h(S)\)(针对 \(I\))。
必须满足:\(f(I)\) 有解当且仅当 \(I\) 有解;若 \(f(I)\) 无解,则 \(I\) 也无解。
归约的图示:
I ──f──> f(I)
│ │
│ h │ 算法 for B
│ │
h(S) <── S ──
这意味着:任何求解 B 的算法都可被"夹在" \(f\) 和 \(h\) 之间,转化为求解 A 的算法。
归约的方向
若记归约为 \(A \to B\),则:
困难性沿箭头方向传播:若 A 困难且 \(A \to B\),则 B 也困难。
高效算法逆箭头方向传播:若 B 有多项式算法且 \(A \to B\),则 A 也有多项式算法。
在本章中,我们使用归约的"反常"目的:已知 A 困难,通过 \(A \to B\) 证明 B 也困难。
归约的复合
归约具有传递性:若 \(A \to B\) 且 \(B \to C\),则 \(A \to C\)。复合归约的前处理为 \(f_{BC} \circ f_{AB}\),后处理为 \(h_{AB} \circ h_{BC}\)。这使得归约链可以高效地扩展 NP 完全性的证明范围。
NP 完全的定义
一个搜索问题是 NP 完全的(NP-complete),当且仅当所有其他搜索问题都可归约到它。这是一个极强的要求:NP 完全问题必须能用来解决世界上任何搜索问题!
NP 完全问题的存在令人惊讶,但确实存在。一旦我们证明某个问题是 NP 完全的,就可用它证明新的 NP 完全问题:只需将已知的 NP 完全问题归约到新问题即可。
归约证明困难性的逻辑
所有 NP 问题都归约到 NP 完全问题,因此每个 NP 完全问题都包含了所有搜索问题的复杂性。若任何一个 NP 完全问题属于 P,则 \(\text{P} = \text{NP}\)。既然我们相信 \(\text{P} \neq \text{NP}\),这些搜索问题就都是困难的。
因数分解的不同
因数分解(FACTORING)也是著名的困难问题,但其困难性质与 NP 完全问题不同。因数分解总是有解(任何整数都可分解为素数乘积),且未被相信是 NP 完全的。第 10 章将展示因数分解可被量子计算机高效求解,而 SAT、TSP 等 NP 完全问题似乎不能。
工作示例:归约的结构与正确性验证
以 TSP 优化问题归约为搜索问题为例,展示归约的双向正确性:
前处理 \(f\):给定距离矩阵 \(D\) 和预算 \(b\),搜索版本直接以 \((D, b)\) 为实例。
后处理 \(h\):若搜索版本返回一个 tour \(T\),则 \(h(T) = T\)(直接输出)。
情况 1:若搜索版本有解(存在长度 \(\leq b\) 的 tour),则优化版本取其最短 tour,若其长度 \(\leq b\) 则返回,否则报告无解。
情况 2:若搜索版本无解(不存在长度 \(\leq b\) 的 tour),则优化版本的最短 tour 长度必 \(> b\),故无解。
多项式时间检查:\(f\) 只是复制输入,\(O(n^2)\);\(h\) 是恒等映射,\(O(1)\)。两者均为多项式时间。
这展示了归约的核心:两个方向的正确性(解的存在性对应)和多项式时间约束。
本节展示两个关键归约:3SAT 到独立集、SAT 到 3SAT,以及独立集与顶点覆盖、团之间的简单归约。
3SAT \(\to\) INDEPENDENT SET
这是连接布尔逻辑与图论的关键归约。给定 3SAT 实例 \(I\),构造独立集实例 \((G, g)\):
为什么这样构造?
三角形的最大独立集大小为 1,因此独立集从每个子句至多选一个文字。
\(g\) 等于子句数,迫使独立集恰好从每个子句选一个文字。
相反文字之间的边防止矛盾赋值(不能同时选 \(x\) 和 \(\lnot x\))。
解的回推:若独立集 \(S\) 有 \(g\) 个顶点,则对每个变量 \(x\):若 \(S\) 含标号 \(x\) 的顶点,令 \(x = \text{true}\);若含 \(\lnot x\),令 \(x = \text{false}\);否则任意赋值。此赋值满足所有子句。
反之,若有满足赋值,从每个子句选一个为真的文字加入 \(S\),则 \(S\) 是大小为 \(g\) 的独立集。
SAT \(\to\) 3SAT
这是"问题归约为自身特例"的典范。要将 SAT 归约为 3SAT,只需消除长文字子句。对子句 \((a_1 \lor a_2 \lor \ldots \lor a_k)\)(\(k > 3\)),引入新变量 \(y_1, y_2, \ldots, y_{k-3}\),替换为:
\[(a_1 \lor a_2 \lor y_1) \land (\lnot y_1 \lor a_3 \lor y_2) \land \cdots \land (\lnot y_{k-3} \lor a_{k-1} \lor a_k)\]
等价性证明:
若新子句全满足,则某个 \(a_i\) 必为真(否则 \(y_1\) 真 \(\Rightarrow\) \(y_2\) 真 \(\Rightarrow\) ... \(\Rightarrow\) 最后一子句假)。
若原子句满足(某 \(a_i\) 真),令 \(y_1, \ldots, y_{i-2}\) 为真,其余为假,即可满足所有新子句。
进一步可限制每个文字至多出现两次:将变量 \(x\) 的 \(k\) 次出现替换为 \(x_1, \ldots, x_k\),并添加等价链 \((x_1 \lor x_2) \land (x_2 \lor x_3) \land \cdots \land (x_k \lor x_1)\)。
INDEPENDENT SET \(\to\) VERTEX COVER
基于补集关系:\(S\) 是顶点覆盖 \(\iff\) \(V \setminus S\) 是独立集。
因此,要判断图 \(G\) 是否有大小为 \(g\) 的独立集,只需检查是否存在大小为 \(|V| - g\) 的顶点覆盖。
INDEPENDENT SET \(\to\) CLIQUE
基于补图关系:\(S\) 是 \(G\) 的独立集 \(\iff\) \(S\) 是补图 \(\overline{G}\) 的团。
因此将实例 \((G, g)\) 映射为 \((\overline{G}, g)\),解完全相同。
工作示例:3SAT 到独立集的构造与解的回推
考虑 3SAT 实例(4 个子句):
\[(x \lor y \lor z) \land (x \lor y \lor \lnot z) \land (x \lor \lnot y \lor z) \land (x \lor y \lor \lnot z)\]
步骤 1:创建三角形/边
子句 1 → 三角形 \((x, y, z)\)
子句 2 → 三角形 \((x, y, \lnot z)\)
子句 3 → 三角形 \((x, \lnot y, z)\)
子句 4 → 三角形 \((x, y, \lnot z)\)
步骤 2:添加矛盾边
\((y, \lnot y)\) 之间:子句 1 的 \(y\) 与子句 3 的 \(\lnot y\) 连边,等等。
\((z, \lnot z)\) 之间:子句 1 的 \(z\) 与子句 2 的 \(\lnot z\) 连边,等等。
步骤 3:设 \(g = 4\)(子句数量)
验证:若赋值 \(x=\text{true}, y=\text{false}, z=\text{true}\) 满足公式,则从每个子句选一个为真文字的顶点:
子句 1:选 \(x\)(为真)
子句 2:选 \(x\)(为真)
子句 3:选 \(x\)(为真)或 \(z\)(为真)
子句 4:选 \(x\)(为真)
选子句 1 的 \(x\)、子句 2 的 \(x\)、子句 3 的 \(x\)、子句 4 的 \(x\)——它们都是正文字 \(x\),彼此无边,构成独立集!故 \(S = \{x_1, x_2, x_3, x_4\}\) 是大小为 4 的独立集。
回推:\(S\) 全为正文字 \(x\),故令 \(x=\text{true}\),\(y, z\) 任意,验证满足所有子句。
本节继续沿归约链深入:3SAT 到 3D 匹配、3D 匹配到 ZOE、ZOE 到子集和、ZOE 到 ILP,以及 ZOE 到 Rudrata 环再到 TSP。
3SAT \(\to\) 3D MATCHING
这是归约理论中最精巧的构造之一,需要用三元组模拟布尔变量和逻辑门。
变量 gadget:对每个变量 \(x\),创建两个男孩 \(b_0, b_1\)、两个女孩 \(g_0, g_1\) 和四个宠物 \(p_0, p_1, p_2, p_3\),组成四个三元组构成的"菱形"结构。任何匹配必须选择其中两组:\((b_0, g_1, p_0), (b_1, g_0, p_2)\)(表示 \(x=\text{true}\))或 \((b_0, g_0, p_1), (b_1, g_1, p_3)\)(表示 \(x=\text{false}\))。
子句 gadget:对子句 \(c = (x \lor y \lor z)\),创建新男孩 \(b_c\) 和新女孩 \(g_c\),添加三个三元组对应三种满足方式(\(x=\text{true}\)、\(y=\text{false}\)、\(z=\text{true}\)),每个三元组使用变量 gadget 中特定的宠物。若文字为真,对应宠物空闲可用;若为假,宠物已被占用,无法匹配。
收尾:未匹配的宠物通过"通用动物爱好者"夫妇来匹配。
3D MATCHING \(\to\) ZOE
ZOE 的 0-1 变量天然描述组合选择:对每个三元组 \(i\),设 \(x_i \in \{0,1\}\)(选中为 1)。对每个男孩/女孩/宠物,写方程 \(\sum_{j \in T} x_j = 1\)(\(T\) 是该实体出现的三元组集合),要求恰好一个三元组被选中。这直接得到 \(Ax = \mathbf{1}\) 形式。
ZOE \(\to\) SUBSET SUM
关键观察:0-1 向量可编码为整数。将 \(A\) 的每列视为二进制整数,寻找列的子集使其和为 \(\mathbf{1}\)(全 1 向量)对应子集和问题。
但二进制加法有进位问题!解决方案:将列视为 base \((n+1)\) 整数(\(n\) 为列数)。由于至多 \(n\) 个数相加且每位数字为 0 或 1,base \((n+1)\) 下不会产生进位,向量加法与整数加法等价。
ZOE \(\to\) ILP
ILP 要求整数向量 \(x\) 满足 \(Ax \leq b\)。将 ZOE 的每个方程 \(x_{j_1} + \cdots + x_{j_k} = 1\) 拆为两个不等式 \(\leq 1\) 和 \(\geq 1\),并添加 \(0 \leq x_i \leq 1\),即得 ILP 形式。
ZOE \(\to\) RUDRATA CYCLE
分两步:先归约为带边对 Rudrata 环(Rudrata Cycle with Paired Edges),再消除边对。
ZOE 到带边对 Rudrata 环:构造一个包含 \(m+n\) 组平行边的简单环结构(\(m\) 个方程、\(n\) 个变量)。每组平行边选择一个,对应变量赋值或方程中选择哪个变量。边对约束 \(C\) 确保:若变量 \(x_i=1\)(选择 \(x_i=1\) 边),则方程侧不能选 \(x_i\) 相关边(因与 \(x_i=0\) 边配对),从而保证每个方程恰好一个变量为 1。
消除边对:设计一个 12 顶点 gadget(图 8.12),在 Rudrata 环中只能以两种方式遍历,模拟一对边中恰好选一条的约束。替换所有边对后得到纯 Rudrata 环。
RUDRATA CYCLE \(\to\) TSP
给定图 \(G=(V,E)\),构造 TSP:城市 = \(V\),距离 \(d_{uv} = 1\) 若 \(\{u,v\} \in E\),否则 \(d_{uv} = 1+\epsilon\)(\(\epsilon > 1\)),预算 \(b = |V|\)。
若 \(G\) 有 Rudrata 环,则同一回路是 TSP 中长度 \(= |V| \leq b\) 的 tour。
若 \(G\) 无 Rudrata 环,则任何 TSP tour 至少用一条非边(长度 \(1+\epsilon\)),总长度 \(\geq |V| + \epsilon > b\)。
取 \(\epsilon = 1\) 得满足三角不等式的 TSP(第 9 章可近似);取 \(\epsilon\) 大则产生"间隙"性质:要么有长度 \(\leq n\) 的解,要么所有解长度 \(\geq n + \epsilon\)(间隙),这蕴含不可近似性(除非 \(\text{P} = \text{NP}\))。
工作示例:ZOE 到子集和的进制转换
考虑 ZOE 实例(矩阵列视为向量):
\[A = \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ 0 & 1 & 1 & 0 \\ 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \end{pmatrix}\]
列向量为 \(c_1=(1,0,0,1,0)\), \(c_2=(0,0,1,0,1)\), \(c_3=(0,0,1,0,0)\), \(c_4=(0,1,0,0,0)\)。
若用二进制读:\(c_1=10001_2=17\), \(c_2=10100_2=20\), \(c_3=00100_2=4\), \(c_4=01000_2=8\),目标和 \(= 11111_2 = 31\)。
但 \(c_2 + c_3 = (0,0,1,0,1) + (0,0,1,0,0) = (0,0,2,0,0) \neq\) 任何合法向量,而二进制 \(20+4=24 \neq 31\),此处碰巧不冲突。但考虑若 \(c_2+c_3+c_4 = 20+4+8=32 \neq 31\) 也 OK。
真正的问题:假设有列 \(a=00101_2=5\), \(b=00110_2=6\), \(c=10100_2=20\),则 \(a+b+c=31\) 但向量和为 \((1,0,3,1,1) \neq (1,1,1,1,1)\)。二进制进位破坏了等价性。
解决方案:用 base \((n+1)\),其中 \(n=3\)(列数),即 base 4:
\(a = 00101_4 = 4+1 = 5\)
\(b = 00110_4 = 4+4 = 8\)(注意:base 4 下数字不能 \(\geq 4\),但此处数字为 0/1,合法)
\(c = 10100_4 = 64+4 = 68\)
\(a+b+c = 5+8+68 = 81\),而目标 \((1,1,1,1,1)_4 = 1+4+16+64+256 = 341\),不相等,正确反映了向量和不相等。
由于 base \((n+1)\) 下每位数字 \(\in \{0,1\}\) 且至多 \(n\) 个数相加,每位和 \(\leq n <\) base,无进位,向量加法与整数加法完全等价。归约正确。
本节完成归约链的闭环:证明所有 NP 问题都可归约到 SAT,从而确立 SAT 的 NP 完全性,并简要讨论超越 NP 的不可解问题。
CIRCUIT SAT:SAT 的推广
CIRCUIT SAT 的实例是一个布尔电路(有向无环图),包含五种门:AND(入度 2)、OR(入度 2)、NOT(入度 1)、已知输入(标号 \(\text{true}\)/\(\text{false}\))、未知输入(标号 \(?\))。一个汇点被指定为输出门。
CIRCUIT SAT 要求找到未知输入的赋值使输出门为 \(\text{true}\)。
CIRCUIT SAT 归约为 SAT
对每个门 \(g\) 引入变量,用子句模拟门的行为:
NOT 门 \(g = \lnot h\):子句 \((g \lor h) \land (\lnot g \lor \lnot h)\)(\(g \iff \lnot h\))。
AND 门 \(g = h_1 \land h_2\):子句 \((\lnot g \lor h_1) \land (\lnot g \lor h_2) \land (g \lor \lnot h_1 \lor \lnot h_2)\)。
OR 门类似。
输出门 \(g\):添加子句 \((g)\) 强制其为真。
所得 CNF 公式的满足赋值与电路满足赋值一一对应。
任意 NP 问题归约为 CIRCUIT SAT
这是通用归约:设 \(A\) 是任意 NP 问题,\(C(I, S)\) 是其多项式时间验证算法。
关键论证(第 7.7 节):任何多项式时间算法都可表示为电路——输入门编码输入比特,门的数量是输入规模的多项式。
因此,对 \(A\) 的实例 \(I\),可在多项式时间构造电路:已知输入 = \(I\) 的比特,未知输入 = \(S\) 的比特,输出 = \(\text{true} \iff S\) 是 \(I\) 的解。此电路的满足赋值与 \(I\) 的解一一对应。
归约链闭环:
\[\forall A \in \text{NP}: A \to \text{CIRCUIT SAT} \to \text{SAT} \to \text{3SAT} \to \cdots\]
这证明了 CIRCUIT SAT 和 SAT 是 NP 完全的:所有 NP 问题都可归约到它们。
不可解问题
NP 完全问题至少还有指数时间算法。但存在完全没有算法的合理计算问题!
停机问题(Halting Problem):给定程序 \(p\) 和输入 \(x\),判断 \(p(x)\) 是否停机。
Turing 1936 年的证明:假设存在程序 \(\text{terminates}(p, x)\),构造
function paradox(z):
if terminates(z, z) goto loop // 若 z(z) 停机则循环
otherwise halt // 否则停机
执行 \(\text{paradox}(\text{paradox})\):若它停机 \(\Rightarrow\) \(\text{terminates}(\text{paradox}, \text{paradox}) = \text{true}\) \(\Rightarrow\) 它循环,矛盾;若它循环 \(\Rightarrow\) \(\text{terminates} = \text{false}\) \(\Rightarrow\) 它停机,矛盾。故 \(\text{terminates}\) 不存在。
这展示了计算的极限:有些问题无论多少时间都无法通过算法解决。编程永远需要纪律、创造力和技巧——你无法自动检测程序是否有无限循环。
工作示例:CIRCUIT SAT 到 SAT 的编码
考虑一个简单电路:输出门 \(g\) 是 AND 门,\(g = h_1 \land h_2\),其中 \(h_1\) 是已知输入 \(\text{true}\),\(h_2\) 是未知输入。
门行为子句:
AND 门 \(g = h_1 \land h_2\):
\((\lnot g \lor h_1)\):若 \(g\) 真则 \(h_1\) 必真
\((\lnot g \lor h_2)\):若 \(g\) 真则 \(h_2\) 必真
\((g \lor \lnot h_1 \lor \lnot h_2)\):若 \(h_1, h_2\) 都真则 \(g\) 必真
已知 \(h_1 = \text{true}\):子句 \((h_1)\)
输出门 \(g\) 为真:子句 \((g)\)
化简:由 \((g)\) 得 \(g=\text{true}\);由 \((\lnot g \lor h_2)\) 和 \(g=\text{true}\) 得 \(h_2=\text{true}\)。
因此唯一满足赋值:\(g=\text{true}, h_1=\text{true}, h_2=\text{true}\)。对应电路:未知输入 \(h_2 = \text{true}\) 使输出为 \(\text{true}\)。
验证:代入电路,\(h_1=\text{true}, h_2=\text{true}\),AND 门输出 \(\text{true}\),满足要求。编码正确。
依据本地课程资料 lectures/chap8.pdf、dis10.pdf、dis11.pdf、dis12.pdf 重绘;交互用于解释算法状态与证明不变量,不替代正文中的完整论证。
NP 代表'Nondeterministic Polynomial time'(非确定性多项式时间)。NP 类包含一些极难的问题(如 SAT、TSP),我们尚不知道它们是否有高效算法。NP 不是'No Problem'。
这是 P = NP 的核心问题,但绝大多数研究者相信 P ≠ NP。验证解(NP)比寻找解(P)容易得多——SAT 的验证只需逐子句检查,但寻找满足赋值可能需要穷举 2^n 种可能。可验证性不蕴含可解性。
恰恰相反。归约 A → B 意味着困难性沿箭头方向传播(A 难则 B 难),而高效算法逆箭头方向传播(B 有多项式算法则 A 也有)。要用归约证明 B 困难,需将已知的困难问题 A 归约到 B。
NP 完全问题有算法(如穷举搜索),只是目前只知道指数时间算法。'不可解问题'(如停机问题)是另一类——它们根本没有算法(无论多项式还是指数)。NP 完全 ≠ 不可解。
P = NP 只保证存在多项式时间算法,但这些算法的指数可能非常高(如 O(n^100)),或者我们尚未发现具体算法。理论上的存在性与实际可计算性之间仍有差距。
问题:关于多项式时间算法与摩尔定律的关系,以下哪项最准确?
问题:下列关于 NP 类问题的描述,哪一项最准确?
问题:若存在从搜索问题 A 到搜索问题 B 的多项式时间归约(A → B),则以下哪项成立?
问题:关于顶点覆盖(VERTEX COVER)与独立集(INDEPENDENT SET)的关系,以下哪项正确?
lectures/chap8.pdf · 247-249 · confidence: high · 定义搜索问题由多项式时间算法 C 指定:C(I,S)=true ⟹ S 是 I 的解;摩尔定律下指数算法仅多项式进展而多项式算法指数进展lectures/chap8.pdf · 258-260 · confidence: high · P 是所有多项式时间可解的搜索问题;NP 由验证算法定义;归约图示含 f 和 h 两个多项式时间函数;NP 完全定义:所有其他搜索问题归约到它lectures/chap8.pdf · 263-267 · confidence: high · 3SAT 到独立集:每个子句创建三角形,相反文字连边,目标 g=子句数;SAT 到 3SAT:长子句 (a1∨...∨ak) 用新变量 y1...yk-3 拆分为多个三文字子句lectures/chap8.pdf · 267-274 · confidence: high · 3D 匹配 ZOE 形式化:变量 xi∈{0,1} 表示第 i 个三元组是否选中,每行方程保证每个男孩/女孩/宠物恰好出现一次;ZOE 到子集和用 base n+1 避免进位lectures/chap8.pdf · 274-276 · confidence: high · 通用归约:对 NP 问题 A 的实例 I,构造电路使已知输入编码 I、未知输入编码 S,输出 true ⟺ S 是 I 的解;CIRCUIT SAT 到 SAT 通过门级 CNF 编码实现