12. 邮政对应问题 (PCP) 的谜题描述
📜 [原文2]
我们可以很容易地将这个问题描述为一种谜题。我们从一堆多米诺骨牌开始,每张多米诺骨牌两面各有一个字符串。一张多米诺骨牌看起来像
$$
\left[\frac{a}{a b}\right]
$$
一堆多米诺骨牌看起来像
$$
\left\{\left[\frac{\mathrm{b}}{\mathrm{ca}}\right],\left[\frac{\mathrm{a}}{\mathrm{ab}}\right],\left[\frac{\mathrm{ca}}{\mathrm{a}}\right],\left[\frac{\mathrm{abc}}{\mathrm{c}}\right]\right\} .
$$
任务是列出这些多米诺骨牌(允许重复),使得从上方读出的字符串与从下方读出的字符串相同。这个列表称为一个匹配。例如,以下列表是这个谜题的一个匹配。
$$
\left[\frac{\mathrm{a}}{\mathrm{ab}}\right]\left[\frac{\mathrm{b}}{\mathrm{ca}}\right]\left[\frac{\mathrm{ca}}{\mathrm{a}}\right]\left[\frac{\mathrm{a}}{\mathrm{ab}}\right]\left[\frac{\mathrm{abc}}{\mathrm{c}}\right]
$$
从上方读出字符串得到abcaaabc,这与从下方读出的相同。我们也可以通过将多米诺骨牌变形,使上方和下方对应的符号对齐来描绘这个匹配。
$$
\left|\begin{array}{l|l|ll|l|lll}
a & b & c & a & a & a & b & c \\
a & b & c & a & a & a & b & c
\end{array}\right|
$$
📖 [逐步解释]
这一段用一个非常生动的“多米诺骨牌”比喻来解释PCP到底是什么。
- 基本元素:多米诺骨牌。这里的多米诺骨牌不是我们平时玩的那种带点数的,而是特制的。它被分成上下两部分,每一部分上都写着一个字符串。例如,一个骨牌上面是 "a",下面是 "ab"。你可以把它想象成一个键值对,或者一个翻译规则,"a" 翻译成 "ab"。
- 问题实例:一堆多米诺骨牌。一个PCP问题就是给你一套这样的骨牌。比如,给你四张牌:
- 牌1: 上 "b", 下 "ca"
- 牌2: 上 "a", 下 "ab"
- 牌3: 上 "ca", 下 "a"
- 牌4: 上 "abc", 下 "c"
- 目标:寻找一个匹配。任务是,从这堆牌里选出一个序列(注意:牌可以重复使用,这是关键!),然后把它们挨个排列起来。当你这样做的时候,所有牌的上半部分会拼接成一个长字符串,下半部分也会拼接成另一个长字符串。如果这两个长字符串完全相同,那么你选出的这个骨牌序列就叫做一个“匹配”。
- 一个匹配的例子。书中给出了一个例子,序列是:
[牌2], [牌1], [牌3], [牌2], [牌4]
我们来看看这个序列是如何形成匹配的:
- 上方字符串拼接:牌2上("a") + 牌1上("b") + 牌3上("ca") + 牌2上("a") + 牌4上("abc") = "abcaaabc"
- 下方字符串拼接:牌2下("ab") + 牌1下("ca") + 牌3下("a") + 牌2下("ab") + 牌4下("c") = "abcaaabc"
看,上下两个拼接出来的长字符串都是 "abcaaabc",它们完全一样!所以,这个序列是一个匹配。
- 可视化匹配。为了更直观地理解,书里画了一个图。这个图就像把上下两个长字符串对齐,然后用竖线把每个骨牌贡献的部分隔开。这清晰地显示了每一步拼接后,上下字符串是如何保持同步增长,并最终完全一致的。
💡 [数值示例]
- 示例1 (来自原文):
- 牌堆: { [b/ca], [a/ab], [ca/a], [abc/c] }
- 一个匹配: [a/ab], [b/ca], [ca/a], [a/ab], [abc/c]
- 上方: a + b + ca + a + abc = abcaaabc
- 下方: ab + ca + a + ab + c = abcaaabc
- 结论: 存在匹配。
- 示例2 (一个新的简单例子):
- 牌堆: { 牌1:[a/baa], 牌2:[ab/a], 牌3:[b/b] }
- 尝试寻找匹配:
- 从牌2开始:[ab/a]。上方是"ab",下方是"a"。下方需要追赶。
- 接一个牌1:[ab/a][a/baa]。上方是"aba",下方是"abaa"。下方超出了。
- 让我们试试别的组合。从牌1开始:[a/baa]。上方"a",下方"baa"。下方太长了。
- 尝试 [ab/a][b/b][a/baa]:
- 上方: ab + b + a = "abba"
- 下方: a + b + baa = "abbaa"
- 不匹配。
- 实际上,我们可以找到一个匹配:[a/baa][b/b][ab/a]。
- 上方: a + b + ab = "abab"
- 下方: baa + b + a = "baaba"
- 还是不匹配。
- 正确的匹配是:[b/b], [a/baa], [ab/a]。
- 上方: b + a + ab = "baab"
- 下方: b + baa + a = "bbaaa"
- 还是不对。
- 让我们重新思考。是否存在一个匹配?这个问题本身就不简单。这正是PCP的难点所在。实际上,对于这个例子,一个解是 [a/baa] 和 [ab/a] 交替使用吗?比如 [a/baa][ab/a] -> 上方aab, 下方baaa。看来很难。这恰好说明了,即使对于简单的牌堆,找到匹配(或证明没有匹配)也非易事。
⚠️ [易错点]
- 易错点1: 牌的使用次数。题目明确指出“允许重复”,这意味着你可以无限次地使用同一张牌。在上面的例子中,[a/ab] 就被用了两次。
- 易错点2: 字符串拼接顺序。字符串是严格按照骨牌排列的顺序从左到右拼接的,不能交换顺序。
- 易错点3: 匹配的定义。必须是上方的总字符串和下方的总字符串完全相等。在中间步骤中,一个长一个短是正常的,只要最终能相等就行。
📝 [总结]
本段通过“多米诺骨牌”谜题的形式,生动形象地定义了邮政对应问题(PCP)。核心任务是从给定的一组(上下有字符串的)牌中,找出一个可以重复使用牌的排列顺序,使得所有牌上方的字符串拼接起来,与所有牌下方的字符串拼接起来,结果完全相同。
🎯 [存在目的]
此段的目的是将PCP这个抽象的计算问题,用一个具体、易于理解的谜题来呈现。这种形象化的描述降低了入门门槛,让读者能快速抓住问题的核心规则,为后续讨论其不可判定性做好铺垫。它展示了深刻的计算难题可以隐藏在简单的游戏规则之下。
🧠 [直觉心智模型]
PCP就像一个“双声道”的录音带拼接任务。你有几段录音带片段(多米诺骨牌),每段片段都有两个声道(上方和下方),录着不同的声音(字符串)。你的任务是用这些片段(可重复)拼接出一条新的长录音带,使得播放时,第一声道的声音序列和第二声道的声音序列完全一样。
💭 [直观想象]
想象你有两种颜色的乐高积木,红色和蓝色。你有一堆预先组合好的“积木对”(多米诺骨牌),比如“一个红块”对应“一个蓝块接一个红块”,或者“一个红块接一个蓝块”对应“一个蓝块”。你的任务是,从这堆“积木对”中挑选,排成一长条,使得你最终得到的红色积木序列,和蓝色积木序列,看起来一模一样。
21. 问题的形式化与语言表示
📜 [原文4]
邮政对应问题是确定一组多米诺骨牌是否具有匹配。这个问题是算法无法解决的。
在正式阐述这个定理及其证明之前,让我们精确地说明这个问题,然后将其表示为一种语言。PCP 的实例是一组多米诺骨牌 $P$
$$
P=\left\{\left[\frac{t_{1}}{b_{1}}\right],\left[\frac{t_{2}}{b_{2}}\right], \ldots,\left[\frac{t_{k}}{b_{k}}\right]\right\},
$$
而匹配是序列 $i_{1}, i_{2}, \ldots, i_{l}$,其中 $t_{i_{1}} t_{i_{2}} \cdots t_{i_{l}}=b_{i_{1}} b_{i_{2}} \cdots b_{i_{l}}$。问题是确定 $P$ 是否具有匹配。令
$$
\begin{gathered}
P C P=\{\langle P\rangle \mid P \text { 是一个具有**匹配**的**邮政对应问题**的**实例** } \\
\end{gathered}
$$
📖 [逐步解释]
这一段的目的是从前面生动的谜题描述,过渡到计算理论中标准的、严谨的数学语言。这是证明一个问题不可判定的必要步骤。
- 核心论断:开门见山地抛出本节最重要的结论:“邮政对应问题是确定一组多米诺骨牌是否具有匹配。这个问题是算法无法解决的。” 这里的“算法无法解决”就是不可判定的同义词。这意味着不存在一个图灵机(即算法),对于任何你给它的PCP实例,它都能停机并正确回答“有匹配”或“无匹配”。
- 转向形式化:在证明这个惊人结论之前,必须先把问题本身用数学符号精确地定义清楚,不能再依赖“多米诺骨牌”这样的比喻。
- 形式化定义 - 实例 (Instance):一个PCP问题的“实例”被定义为一个集合 $P$。这个集合 $P$ 包含 $k$ 个元素。每个元素是一个“骨牌”,表示为 $[\frac{t_j}{b_j}]$,其中 $j$ 从1到 $k$。$t_j$ (top) 是第 $j$ 张牌上方的字符串,而 $b_j$ (bottom) 是下方的字符串。
- 形式化定义 - 匹配 (Match):一个“匹配”不再是一列骨牌图,而被定义为一个下标序列 $i_1, i_2, \ldots, i_l$。这个序列里的每个下标 $i_j$ 都必须是 $1$ 到 $k$ 之间的整数,代表你选择的是牌堆 $P$ 中的第 $i_j$ 张牌。这个序列之所以被称为“匹配”,需要满足一个核心条件:
- $t_{i_{1}} t_{i_{2}} \cdots t_{i_{l}} = b_{i_{1}} b_{i_{2}} \cdots b_{i_{l}}$
- 这个等式说的是:将序列中所有选定骨牌的上方字符串按顺序拼接起来,得到的结果必须和将它们的下方字符串按顺序拼接起来的结果完全相同。
- 形式化定义 - 语言 (Language):在计算理论中,我们习惯于将“问题”等同于“语言”。一个判定问题对应一个语言,这个语言包含了所有答案为“是”的实例的编码。
- $PCP$ 被定义为一个语言。这个语言是一个集合。
- 集合中的元素是 $\langle P \rangle$。这里的尖括号 $\langle \cdot \rangle$ 表示对实例 $P$ 的一种标准编码(比如,一个描述所有骨牌上下字符串的字符串)。
- 一个编码 $\langle P \rangle$ 属于语言 $PCP$ 的充要条件是:实例 $P$ 具有一个匹配。
- 因此,“确定实例 $P$ 是否有匹配”这个问题,就等价于“判断字符串 $\langle P \rangle$ 是否属于语言 $PCP$”这个问题。
💡 [数值示例]
- 示例1:
- 实例 $P = \left\{ \left[\frac{\mathrm{a}}{\mathrm{ab}}\right]_1, \left[\frac{\mathrm{b}}{\mathrm{ca}}\right]_2, \left[\frac{\mathrm{ca}}{\mathrm{a}}\right]_3 \right\}$ (为了清晰,我给牌加了下标1, 2, 3)
- 一个匹配 (下标序列): $1, 2, 3$
- 验证:
- 顶部拼接: $t_1 t_2 t_3 = \mathrm{a} + \mathrm{b} + \mathrm{ca} = \mathrm{abca}$
- 底部拼接: $b_1 b_2 b_3 = \mathrm{ab} + \mathrm{ca} + \mathrm{a} = \mathrm{abcaa}$
- 结果: "abca" != "abcaa",所以 $1, 2, 3$ 不是一个匹配。
- 另一个匹配 (下标序列): 让我们试试 $2, 3$
- 顶部: $t_2 t_3 = \mathrm{b} + \mathrm{ca} = \mathrm{bca}$
- 底部: $b_2 b_3 = \mathrm{ca} + \mathrm{a} = \mathrm{caa}$
- 也不是匹配。
- 结论: "判断这个 $P$ 是否有匹配" 就是PCP问题。如果它有匹配,那么它的编码 $\langle P \rangle$ 就在语言 $PCP$ 中。
⚠️ [易错点]
- 易错点: 实例 vs. 语言。$P$ 是一个具体的问题实例(一堆牌),而 $PCP$ 是一个抽象的集合,包含了所有有解实例的编码。这是计算理论中一个基础但关键的区别。我们证明的是语言 $PCP$ 是不可判定的,这意味着没有算法能可靠地判断一个给定的 $\langle P \rangle$ 是否在该集合中。
- 易错点: 下标序列的含义。序列 $i_1, \ldots, i_l$ 只是“配方”,它告诉我们按什么顺序用哪些牌。它本身不是解,满足拼接等式的序列才是。
📝 [总结]
本段将PCP问题从谜题形式转化为严谨的数学定义。它定义了PCP的实例(一组带字符串的牌)、匹配(一个让上下拼接字符串相等的牌的下标序列),并最终将PCP问题定义为一个形式语言,即所有有解的PCP实例编码的集合。这是后续进行不可判定性证明的理论基础。
🎯 [存在目的]
在计算机科学中,尤其是计算理论,任何严格的证明都必须建立在形式化定义之上。此段的目的就是完成这个“翻译”工作,将直观的PCP概念,转化为图灵机和算法理论可以处理的、由集合和字符串构成的数学对象(即语言 $PCP$)。没有这一步,就无法在 $A_{TM}$ 和 $PCP$ 之间建立归约,也就无法证明PCP的不可判定性。
🧠 [直觉心智模型]
想象一个巨大的图书馆,书架上放满了各种各样的“PCP牌堆盒子”(实例 $P$)。有些盒子上贴了绿色标签(表示有解),有些贴了红色标签(表示无解)。这个图书馆里所有贴着绿色标签的盒子的“馆藏编号”(编码 $\langle P \rangle$)集合起来,就构成了一本名为《PCP语言》的目录。PCP的不可判定性意味着:你不可能写出一个计算机程序,让它随便扫描一个盒子的编号,就能百分之百正确地判断出这个编号是否记录在《PCP语言》这本目录里。
💭 [直观想象]
你是一名侦探,PCP问题就是一个案件。实例 $P$ 是你收到的案件卷宗,里面有一堆证据卡片(多米诺骨牌)。你的任务是判断这个案子能否“告破”(找到匹配)。如果你能找到一个证据序列(下标序列)能完美地串联起来形成一个完整的证据链(上下字符串相等),案子就告破了。语言 $PCP$ 就是所有“已告破”案件的卷宗编号列表。而不可判定性意味着,不存在一个万能的“推理手册”(算法),能指导你对任何新接手的案件,都能判断出它最终能否告破。
3. PCP 不可判定性定理与证明
33. 证明的技术性处理和修改版PCP (MPCP)
📜 [原文7]
在进行构造之前,我们处理三个小的技术点。(在您初次阅读此构造时,不必过于担心它们。)首先,为了方便构造 $P$,我们假设 $M$ 在 $w$ 上从不试图将其磁头移出纸带的左端。这需要首先修改 $M$ 以防止这种行为。其次,如果 $w=\varepsilon$,我们在构造中使用符号 $\sqcup$ 代替 $w$。第三,我们修改 PCP 以要求匹配从第一张多米诺骨牌开始,
$$
\left[\frac{t_{1}}{b_{1}}\right] .
$$
稍后我们将展示如何消除此要求。我们将此问题称为修改的邮政对应问题(MPCP)。令
$$
\begin{gathered}
M P C P=\{\langle P\rangle \mid P \text { 是一个**邮政对应问题**的**实例** } \\
\text { 且其**匹配**以第一张**多米诺骨牌**开始 }\} .
\end{gathered}
$$
📖 [逐步解释]
在进入核心构造前,作者先提出并解决了三个“小”的技术性问题。这些问题就像是在盖大楼前平整土地,虽然不是主体结构,但能让后续施工更简单、更规范。
- 第一个技术点:磁头不能左移越界
- 问题: 标准的图灵机模型允许磁头在纸带上向左或向右移动。如果磁头在最左边的格子,然后收到一个向左移动的指令,它会停留在原地。但这种“撞墙”行为在我们的构造中会引入不必要的复杂性。
- 解决方案: 我们先对要模拟的图灵机 $M$ 做一个简单的预处理,得到一个等价的图灵机 $M'$。$M'$ 的行为和 $M$ 完全一样,只是它永远不会尝试移出纸带的左边界。这很容易做到:修改 $M$ 的转移函数,让它在开始时在纸带最左边写一个特殊的标记,比如 $`。然后规定,只要磁头读到 `$,它就必须向右移动。这样一来,$M'$ 就和 $M$ 计算能力等价,但行为更规范。所以,后面我们可以安全地假设我们模拟的 $M$ 就有这个好性质。
- 第二个技术点:空输入字符串 $w=\varepsilon$
- 问题: 我们的构造需要将输入 $w$ 放在初始的多米诺骨牌上。如果 $w$ 是空字符串 $\varepsilon$,那么初始格局中就没有输入部分,这会使构造稍微有点不同。
- 解决方案: 为了统一处理,我们规定,如果 $w$ 是空的,我们就用一个空格符号 $\sqcup$ 来代替它。因为图灵机在空输入上运行时,纸带上本来就全是空格,所以这只是让初始格局的表示更加明确。
- 第三个技术点:强制从第一张骨牌开始
- 问题: PCP的规则是,你可以从牌堆里任意选一张牌作为起点。但在我们的构造中,我们希望匹配必须从一个非常特殊的骨牌开始——这张骨牌负责设定图灵机的初始格局。如果玩家可以随便从中间的“计算步骤”骨牌开始,整个模拟就乱套了。
- 解决方案: 作者这里用了一个两步走的策略:
- 步骤一:引入一个更强的变种问题。我们先定义一个PCP的修改版,叫做修改的邮政对应问题 (MPCP)。MPCP的规则和PCP一样,但增加了一条额外的限制:任何合法的匹配都必须以牌堆中的第一张牌 $[\frac{t_1}{b_1}]$ 开始。
- 步骤二:先解决简单版本。我们接下来的证明,将首先证明 $A_{TM}$ 可以归约到 MPCP。也就是说,我们将构造一个MPCP实例,它的解对应于图灵机的计算历史。
- 步骤三:再把MPCP归约回PCP。在证明的最后,我们会展示一个通用的方法,能把任何一个MPCP实例转换成一个PCP实例,并且保证新PCP实例的解法和原MPCP实例的解法等价。这样,整个证明链条就完整了:$A_{TM} \le_m MPCP \le_m PCP$。根据归约的传递性,就证明了 $A_{TM} \le_m PCP$。
💡 [数值示例]
- MPCP 示例:
- 实例 $P' = \left\{ \left[\frac{\mathrm{a}}{\mathrm{ab}}\right]_1, \left[\frac{\mathrm{b}}{\mathrm{ca}}\right]_2, \left[\frac{\mathrm{ca}}{\mathrm{a}}\right]_3 \right\}$.
- 问题: $\langle P' \rangle$ 是否属于语言 $MPCP$?
- 分析: 我们需要寻找一个以牌1开头的匹配。
- 尝试序列 1, ...:
- [a/ab] -> 上方 "a", 下方 "ab"。下方需要一个前缀为 "b" 的上方字符串来追赶。牌2 [b/ca] 正好是。
- 尝试序列 1, 2, ...:
- [a/ab][b/ca] -> 上方 "ab", 下方 "abca"。上方需要一个前缀为 "ca" 的下方字符串来追赶。牌3 [ca/a] 正好是。
- 尝试序列 1, 2, 3:
- [a/ab][b/ca][ca/a] -> 上方 "abca", 下方 "abcaa"。非常接近!上方需要一个 "a" 来结尾。牌1 [a/ab] 或牌3 [ca/a] 的上方都有 "a"。
- 这是一个复杂的过程,但重点是,我们只考虑从 1 开始的序列。如果我们找到了一个解,比如 1, 2, 3, ...,那么 $\langle P' \rangle \in MPCP$。如果所有从 1 开始的序列都无法形成匹配,则 $\langle P' \rangle \notin MPCP$。
⚠️ [易错点]
- 易错点: MPCP不是一个全新的问题类型,它只是PCP的一个带有额外约束的子问题。证明MPCP是不可判定的,是证明PCP不可判定的一个中间步骤。不要把两者混淆。
- 逻辑关系: 证明的逻辑是:(1) 我们先证明MPCP是不可判定的(通过从$A_{TM}$归约)。(2) 然后我们证明,如果PCP是可判定的,那么MPCP也一定是可判定的(因为我们可以把MPCP实例转成PCP实例来解)。(3) 由于(1)和(2)矛盾,所以PCP必须是不可判定的。
📝 [总结]
本段为后续的复杂构造扫清了三个技术障碍:图灵机磁头不越左边界、处理空输入、以及将PCP暂时强化为MPCP(修改的邮政对应问题),该问题强制匹配必须从第一张牌开始。这个“先易后难”的策略大大简化了证明的核心部分。
🎯 [存在目的]
本段的目的是“简化问题”和“分解难题”。通过对被模拟的图灵机行为做一些无伤大雅的规范化,以及暂时引入一个更严格但更容易处理的MPCP问题,作者可以将证明的主要精力集中在最核心的“模拟计算历史”这一构造上,避免在主证明中被各种边界情况和特殊处理分散注意力。
🧠 [直觉心智模型]
这就像在准备一场复杂的戏剧表演。在正式排练(核心构造)之前,导演(作者)先做了几项准备工作:
- 规范演员走位: 告诉演员“永远不要走出舞台左侧”(磁头不越界)。
- 准备特殊道具: 如果剧本里某个角色没台词(空输入),就给他一个面具($\sqcup$符号),让他有存在感。
- 固定开场: 规定第一幕必须是主角登场(强制从第一张骨牌开始),不能让配角先上场把剧情搞乱。
这些准备工作让整个排练过程会顺畅很多。
💭 [直观想象]
想象你在搭建一个极其精密的、由多米诺骨牌组成的大型连锁反应装置,目标是用它来模拟一个计算机的运算。为了让设计更简单,你首先定下几条规则:
- 骨牌倒下的路径永远不会超出桌子的左边缘。
- 如果计算机没有输入,你就在起点放一个特殊的“空输入”骨牌。
- 你规定整个连锁反应必须由你亲手推倒的第一块“起始”骨牌触发。
这就是引入MPCP等技术处理的直观感受——为了最终那个宏伟而复杂的设计能够成功,先做好一切简化和准备工作。
34. 证明主体:从 ATM 归约到 MPCP
📜 [原文8]
现在让我们深入到证明的细节,并设计 $P$ 来模拟 $M$ 在 $w$ 上的行为。
证明 我们让图灵机 $R$ 判定 PCP,并构造图灵机 $S$ 来判定 $A_{\text {TM }}$。令
$$
M=\left(Q, \Sigma, \Gamma, \delta, q_{0}, q_{\text {accept }}, q_{\text {reject }}\right)
$$
其中 $Q, \Sigma, \Gamma$ 和 $\delta$ 分别是 $M$ 的状态集、输入字母表、纸带字母表和转移函数。
在这种情况下,$S$ 构造 PCP 的一个实例 $P$,当且仅当 $M$ 接受 $w$ 时,该实例才具有匹配。为此,$S$ 首先构造 MPCP 的一个实例 $P^{\prime}$。我们将构造过程分为七个部分,每个部分都完成模拟 $M$ 在 $w$ 上的一个特定方面。为了解释我们正在做的事情,我们穿插了构造过程和一个构造实例。
📖 [逐步解释]
这是证明核心部分的正式开始。
- 深入细节: 作者明确表示,前面的铺垫结束,现在要进入构造的“深水区”。目标是设计一个PCP实例 $P$(实际上是MPCP实例 $P'$),其行为能模拟图灵机 $M$ 在输入 $w$ 上的计算。
- 归约法的标准开场白: “我们让图灵机 $R$ 判定 PCP,并构造图灵机 $S$ 来判定 $A_{TM}$。”
- 这是一个典型的反证法和归约法结合的表述。
- 假设存在一个图灵机 $R$ 能够判定 PCP。也就是说,我们假设 PCP 是可判定的。$R$ 就是我们假想的那个 PCP_Solver。
- 目标是基于这个假设,构造出另一个图灵机 $S$,而这个 $S$ 竟然能够判定 $A_{TM}$。
- 由于我们已知 $A_{TM}$ 是不可判定的,所以能判定 $A_{TM}$ 的图灵机 $S$ 是不可能存在的。
- 这个矛盾的出现,说明我们最初的假设——“存在一个图灵机 $R$ 能判定 PCP”——是错误的。因此,PCP 必定是不可判定的。
- 接下来的所有内容,都是在描述如何构造这个图灵机 $S$。
- 定义被模拟的图灵机 M:
- 为了清晰,作者重申了图灵机 $M$ 的七元组形式化定义:$M = (Q, \Sigma, \Gamma, \delta, q_0, q_{accept}, q_{reject})$。
- $Q$: 状态的有限集合。
- $\Sigma$: 输入字母表,即输入字符串 $w$ 中可能出现的字符集合。
- $\Gamma$: 纸带字母表,包含 $\Sigma$ 以及空格符号 $\sqcup$ 和其他可能的辅助符号。
- $\delta$: 转移函数,是图灵机的核心规则,形如 $\delta(q, a) = (r, b, D)$,表示在状态 $q$ 读到符号 $a$ 时,会转移到状态 $r$,将 $a$ 改写为 $b$,并向方向 $D$ (左或右) 移动。
- $q_0$: 初始状态。
- $q_{accept}$: 接受状态。
- $q_{reject}$: 拒绝状态。
- 构造器 S 的功能:
- $S$ 是一个算法(一个图灵机),它接收 $\langle M, w \rangle$ 作为输入。
- $S$ 的工作是输出一个 MPCP 的实例 $P'$。
- 这个 $P'$ 的设计必须满足那个黄金法则:“$M$ 接受 $w$ 当且仅当 $P'$ 有一个(MPCP)匹配”。
- 分步构造: 作者将整个复杂的构造过程拆分成了七个部分。这是一种非常好的教学和论证方法,将一个大问题分解成若干个小侧面,逐一击破。每个部分都旨在模拟图灵机计算的一个特定方面(例如,磁头右移、左移、纸带复制、计算开始、计算结束等)。
- 穿插解释与实例: 为了避免这七个步骤过于抽象,作者承诺会在描述构造规则的同时,给出一个具体的例子,展示这些规则是如何工作的。
💡 [数值示例]
- 输入给S: $\langle M, w \rangle$,其中 $M$ 是一个特定的图灵机, $w = \text{"01"}$。
- S开始工作: $S$ 读取 $M$ 的定义(它的状态集 $Q$,转移函数 $\delta$ 等)和输入 $w$。
- S执行构造: $S$ 根据 $M$ 和 $w$ 的具体内容,按部就班地执行后面将要介绍的七个构造步骤,生成一系列多米诺骨牌。比如,它会生成一张类似 [# / #q001#] 的起始牌,还会根据 $\delta$ 的每一条规则生成对应的“计算牌”。
- S输出: $S$ 将所有生成的骨牌打包成一个MPCP实例 $P'$ 并输出。
- 后续(在归约逻辑中): 假想的PCP_Solver会接收这个 $P'$,并告诉我们它是否有解。$S$ 根据这个答案来判断 $M$ 是否接受 $w$。
⚠️ [易错点]
- S 和 M 的角色: 要分清 $S$ 和 $M$ 的区别。$M$ 是被我们“分析”和“模拟”的对象,它是任意一个图灵机。$S$ 是我们正在“设计”和“构造”的图灵机,它的工作是把关于 $M$ 的问题,转换成关于PCP的问题。$S$ 本身是一个算法,一个“转换器”。
📝 [总结]
本段是证明的正式起点,它清晰地设定了证明策略(通过构造图灵机 $S$ 将 $A_{TM}$ 归约到 PCP)、明确了被模拟对象 $M$ 的形式,并预告了将采用分七步构造 MPCP 实例 $P'$ 的方法,且会辅以实例来解释。
🎯 [存在目的]
本段的目的是建立证明的框架。它在逻辑上连接了“不可判定的 $A_{TM}$”和“待证明的 PCP”,并声明了两者之间的桥梁——一个构造性的归约算法 $S$。它为读者提供了一个清晰的上下文,让读者明白接下来七个部分的构造都是为了实现 $S$ 的功能。
🧠 [直觉心智模型]
我们是工程师(设计者 $S$),接到了一个任务:为任意给定的计算机程序 $M$ 和输入 $w$,设计一套定制的“自动演化拼图” $P'$。这套拼图的规则(骨牌)必须被设计得如此精巧,以至于任何能成功完成拼图(找到匹配)的人,都实际上是在手工模拟了一遍 $M$ 在 $w$ 上的成功运行过程。
💭 [直观想象]
想象你是一个电影导演 $S$。给你一个剧本(图灵机 $M$)和主角的初始状态(输入 $w$)。你的任务不是去“演”这部电影,而是要去设计一套“电影制作规则集” $P'$。这个规则集里包含了很多卡片,比如“如果上一帧是主角在门口,下一帧必须是主角进屋”、“如果角色A说话,镜头必须给A特写”等等。你设计的这套规则必须保证,任何遵循它来制作电影的人,最终拍出的成片(匹配)必然是原剧本的一次成功演绎(接受计算历史)。
35. 构造第一部分:起始
📜 [原文9]
第 1 部分。构造以以下方式开始。
$$
\text { 将 }\left[\frac{\#}{\# q_{0} w_{1} w_{2} \cdots w_{n} \#}\right] \text { 作为第一张**多米诺骨牌** }\left[\frac{t_{1}}{b_{1}}\right] \text { 放入 } P^{\prime} \text { 中。 }
$$
因为 $P^{\prime}$ 是 MPCP 的一个实例,匹配必须以这张多米诺骨牌开始。因此,底部字符串正确地以 $C_{1}=q_{0} w_{1} w_{2} \cdots w_{n}$ 开始,这是 $M$ 在 $w$ 上的接受计算历史中的第一个格局,如下图所示。

图 5.16
MPCP 匹配的开始
在此部分匹配的描绘中,底部字符串由 $\# q_{0} w_{1} w_{2} \cdots w_{n} \#$ 组成,而顶部字符串仅由 $\#$ 组成。为了获得匹配,我们需要扩展顶部字符串以匹配底部字符串。我们提供额外的多米诺骨牌以允许这种扩展。这些额外的多米诺骨牌通过强制 $M$ 的单步模拟,使得 $M$ 的下一个格局出现在底部字符串的扩展中。
📖 [逐步解释]
这是七个构造部分中的第一个,也是最关键的一步:设置计算的起点。
- 构造规则: 规则非常明确,就是创建一张特定的多米诺骨牌,并把它放在牌堆 $P'$ 的第一个位置。
- 这张牌的上方是 #。# 是一个特殊的分隔符,用来标记计算历史中格局的开始和结束。
- 这张牌的下方是 # + 初始格局 + #。
- 初始格局的表示法是 $q_0 w_1 w_2 \cdots w_n$。这是一种标准的图灵机格局表示:$q_0$ 是初始状态,它紧跟在磁头当前指向的符号 $w_1$ 的左边。$w_1 w_2 \cdots w_n$ 是纸带上的输入字符串 $w$。
- 所以下方的整个字符串是 #q_0w_1...w_n#。
- 强制性起点: 因为我们构造的是一个 MPCP 实例,而 MPCP 要求匹配必须从第一张牌开始。所以,任何一个合法的匹配,都必然是以这张牌开头的。
- 产生的效果: 当我们把这张起始牌放下时,匹配的初始状态就形成了:
- 上方字符串 (Top): #
- 下方字符串 (Bottom): #q_0w_1...w_n#
- 此时,上方和下方字符串的第一个字符 # 是匹配的,但下方多出了一大串 q_0w_1...w_n#。这就产生了一个“债务”:上方的字符串必须想办法“追赶”上并匹配掉下方的这串字符。
- 后续策略: 这段解释了整个证明的核心机制。我们如何让上方的字符串“追赶”上来?答案不是随便添加字符,而是通过一系列精心设计的多米诺骨牌。这些骨牌的作用是:
- 当你为了匹配掉下方的第一个格局 $C_1$ 而在上方添加字符时,你被迫在下方添加了第二个格局 $C_2$。
- 这个过程会一直持续下去。你为了匹配 $C_k$,被迫在下方生成 $C_{k+1}$。
- 这就形成了一个“上方追赶,下方延伸”的链条反应,而这个链条反应恰好就是图灵机的计算过程。
💡 [数值示例]
- 示例:
- 图灵机 $M$ 和输入 $w = \text{"ab"}$。
- 初始状态: $q_0$。
- 构造Part 1: 构造器 $S$ 会生成第一张多米诺骨牌,并将其设为 $[\frac{t_1}{b_1}]$。
- $t_1 = \#$
- $b_1 = \#q_0ab\#$
- 所以第一张牌是: $\left[\frac{\#}{\#q_0ab\#}\right]$
- 匹配的开始: 任何一个匹配都必须以这张牌开始。
- 当前上方总字符串: #
- 当前下方总字符串: #q_0ab#
- 目标: 接下来的任务是找到其他骨牌,拼接在后面,使得上方的字符串能变成 #q_0ab#...,从而与下方匹配。
⚠️ [易错点]
- 格局的表示: 理解 $uqav$ 这种格局表示法至关重要。它表示纸带内容是 $uav...$,机器状态是 $q$,磁头指向 $a$。在这个构造中,状态符号被“插入”到纸带字符串中来表示磁头位置。
- # 的作用: # 符号是这个构造的“脚手架”。它不参与图灵机的实际计算,但它强制了计算历史的边界,确保了格局与格局之间被清晰地分开。
📝 [总结]
第一部分构造了MPCP实例的“引擎启动器”——一张特殊的起始多米诺骨牌。这张牌的作用是:1) 确立它作为所有匹配的唯一合法起点;2) 在匹配的底部字符串中放置好图灵机的初始格局;3) 制造一个“不平衡”,驱动后续的骨牌选择必须模拟图灵机的计算步骤,以求“追平”这个不平衡。
🎯 [存在目的]
任何模拟都需要一个起点。这部分构造的目的就是为了精确地、无歧义地建立这个起点。通过MPCP的特性,将图灵机的初始状态 $C_1$ 硬编码到任何可能解的开端,为整个基于计算历史的模拟奠定了坚实的基础。
🧠 [直觉心智模型]
这就像是在一条长长的纸带的底部,我们首先写下了初始任务:#q0w#。而在纸带的顶部,我们只写下了一个开始符号 #。现在,你的任务是使用一些“复印规则”(其他的多米诺骨牌),在顶部把 q0w# 这部分抄写下来。但这些复印规则被设计得很刁钻:当你抄顶部的 q0 时,你被迫在底部写下 q0 变成的下一个状态和字符。这样,你为了完成抄写任务,不得不把整个计算过程在底部演算出来。
💭 [直观想象]
想象你在参加一个奇怪的打字比赛。裁判给你两行纸,下面一行已经预先打好了第一句话:“[开始] 程序的初始状态 [结束]”。上面一行只打了一个“[开始]”。你的任务是让上下两行变得一样长,内容也一样。裁判给你一堆“快捷键”(多米诺骨牌),比如有一个快捷键,你按一下,可以在上面一行打出“程序”,但同时,它会自动在下面一行打出“程序计算了一步之后的状态”。你为了让上面一行追上下面的内容,就不停地使用快捷键,结果不知不觉中,下面一行就把整个程序的运行过程给打印出来了。这就是Part 1设置的“陷阱”。
36. 构造第二、三、四部分:模拟计算步骤
📜 [原文10]
在第 2、3 和 4 部分中,我们向 $P^{\prime}$ 添加执行模拟主要部分的多米诺骨牌。第 2 部分处理磁头向右移动,第 3 部分处理磁头向左移动,第 4 部分处理不与磁头相邻的纸带单元格。
第 2 部分。对于每个 $a, b \in \Gamma$ 和每个 $q, r \in Q$ 且 $q \neq q_{\text {reject}}$,
$$
\text { 如果 } \delta(q, a)=(r, b, \mathrm{R}) \text {,将 }\left[\frac{q a}{b r}\right] \text { 放入 } P^{\prime} \text {。 }
$$
第 3 部分。对于每个 $a, b, c \in \Gamma$ 和每个 $q, r \in Q$ 且 $q \neq q_{\text {reject}}$,
$$
\text { 如果 } \delta(q, a)=(r, b, \mathrm{~L}) \text {,将 }\left[\frac{c q a}{r c b}\right] \text { 放入 } P^{\prime} \text。 }
$$
第 4 部分。对于每个 $a \in \Gamma$,
$$
\text { 将 }\left[\frac{a}{a}\right] \text { 放入 } P^{\prime} \text。 }
$$
📖 [逐步解释]
这三部分是构造的核心,它们负责将图灵机的每一步转移函数规则,都翻译成对应的多米诺骨牌。这些骨牌是模拟得以进行下去的“齿轮”。
第4部分:复制(不变的部分)
我们先看最简单的第4部分。
- 规则: 对于纸带字母表 $\Gamma$ 中的每一个符号 $a$,我们都添加一张形如 $[\frac{a}{a}]$ 的骨牌。
- 作用: 图灵机在一步计算中,只会改变磁头及其所在位置的符号,纸带上其他地方的符号是不变的。这些 $[\frac{a}{a}]$ 骨牌就是“复印机”,它们的作用就是将上一个格局中那些没有被磁头扫过的部分,原封不动地“复制”到下一个格局中。在我们的匹配构造中,这意味着当你需要在上方匹配一个符号 a 时,你可以用这张牌,它同时会在下方也添加一个 a,保持了纸带这部分的稳定。
第2部分:磁头右移
- 规则: 这条规则对应图灵机的右移动作。如果转移函数说 $\delta(q, a) = (r, b, R)$(在状态q读到a,变成状态r,把a写成b,然后磁头向右R移),我们就添加一张骨牌 $[\frac{qa}{br}]$。
- 作用: 让我们看看这张骨牌如何模拟计算。
- 在旧格局中,磁头在a上,表示为 ...qa...。
- 在我们的PCP匹配中,底部有 ...qa... 这部分。上方的字符串需要追赶并匹配掉 qa。
- 这时,我们正好可以使用我们构造的这张 $[\frac{qa}{br}]$ 骨牌。
- 使用后:上方添加了 qa,成功匹配。下方则添加了 br。
- 我们看看格局发生了什么变化:
- 旧格局片段: ... q a ...
- 新格局片段: ... b r ...
- 这恰好是磁头右移的正确表示!原来磁头在a左边,现在状态q消失,a变成b,新的状态r出现在了b的右边(也就是原a的下一个位置)。这张骨牌完美地实现了状态转移、字符改写和磁头右移的模拟。
第3部分:磁头左移
- 规则: 这条规则对应左移动作,稍微复杂一点。如果 $\delta(q, a) = (r, b, L)$(在状态q读到a,变成状态r,把a写成b,然后磁头向左L移),那么对于纸带字母表中的任意一个符号c,我们都添加一张骨牌 $[\frac{cqa}{rcb}]$。
- 作用:
- 在旧格局中,磁头在a上,它左边有一个符号c,表示为 ...cqa...。
- 我们的PCP匹配的底部有 ...cqa... 这部分,上方需要追赶匹配。
- 我们使用对应的骨牌 $[\frac{cqa}{rcb}]$。
- 使用后:上方添加 cqa,成功匹配。下方添加了 rcb。
- 格局变化:
- 旧格局片段: ... c q a ...
- 新格局片段: ... r c b ...
- 这正是磁头左移的正确表示!a被改写为b,而新的状态r出现在了c的前面。
- 为什么需要c? 因为左移时,新的状态r会跑到前一个符号c的左边。为了正确放置r,我们的骨牌必须“看到”磁头左边是什么符号。因为c可以是纸带上的任何符号,所以对于每一个可能的c,我们都要准备一张对应的骨á牌。
💡 [数值示例]
- 假设一个图灵机 $M$ 有:
- $\Gamma = \{0, 1, \sqcup\}$
- $\delta(q_1, 0) = (q_2, 1, R)$ (规则A: 右移)
- $\delta(q_2, 1) = (q_3, 0, L)$ (规则B: 左移)
- 根据Part 2和规则A,我们添加骨牌:
- $[\frac{q_1 0}{1 q_2}]$
- 根据Part 3和规则B,我们添加骨牌 (c可以是0, 1,sqcup):
- $[\frac{0 q_2 1}{q_3 0 0}]$ (如果磁头左边是0)
- $[\frac{1 q_2 1}{q_3 1 0}]$ (如果磁头左边是1)
- $[\frac{\sqcup q_2 1}{q_3 \sqcup 0}]$ (如果磁头左边是sqcup)
- 根据Part 4,我们添加骨牌:
- $[\frac{0}{0}]$, $[\frac{1}{1}]$, $[\frac{\sqcup}{\sqcup}]$
- 模拟过程示例:
- 假设当前格局是 ...0q_101...,在PCP匹配底部是 ...0q_101...。
- 上方需要匹配 0q_101。
- 我们先用 $[\frac{0}{0}]$,上方匹配了0,下方也添加0。匹配变成:上...0,下...0。
- 接着匹配 q_10,我们用右移骨牌 $[\frac{q_1 0}{1 q_2}]$。上方匹配了 q_10,下方添加 1q_2。
- 接着匹配 1,我们用复制骨牌 $[\frac{1}{1}]$。
- 这样一步走完,我们看看底部发生了什么:...0 + 1q_2 + 1... -> ...01q_21...。
- 旧格局: ...0q_101... -> 新格局 ...01q_21...。模拟完全正确!
⚠️ [易错点]
- 左移的复杂性: 必须理解为什么左移需要考虑前一个字符c。因为新状态r的位置依赖于c,所以骨牌的“视野”必须包含c。这是一个关键细节。
- 非拒绝状态: 注意规则里都写着 $q \neq q_{reject}$。这意味着我们只为计算过程中的状态生成骨牌。当图灵机进入拒绝状态时,模拟会因为没有对应的骨牌而“卡住”,无法形成匹配,这正是我们想要的效果。接受状态将有特殊的处理方式。
📝 [总结]
第2、3、4部分是模拟图灵机单步计算的核心。它们将图灵机的三种基本行为——磁头右移、磁头左移、以及纸带部分保持不变——分别翻译成了三种类型的多米诺骨牌。这些骨牌的设计确保了在PCP匹配的构造过程中,下方字符串的演化严格遵循图灵机的转移函数。
🎯 [存在目的]
这三部分是实现“匹配 = 计算历史”这一核心思想的技术手段。它们是“转换器”$S$的主要逻辑,负责将抽象的转移函数规则,具象化为一组可以操作和拼接的PCP骨牌。没有这三部分,模拟就无从谈起。
🧠 [直觉心智模型]
这就像是为一本“自动翻译词典”添加词条。
- Part 4的 $[\frac{a}{a}]$ 是最基础的词条:“单词X”翻译成“单词X”。
- Part 2的 $[\frac{qa}{br}]$ 是一个复合词条:“状态q下的单词a”翻译成“单词b后的状态r”。这是一个上下文相关的翻译规则。
- Part 3的 $[\frac{cqa}{rcb}]$ 是一个更复杂的上下文相关词条:“在单词c之后,处于状态q的单词a”翻译成“状态r下的单词c和单词b”。
当你试图用这本词典去“翻译”(匹配)一个句子时,你被迫遵循它定义的语法(图灵机规则)。
💭 [直观想象]
想象一个DNA复制的过程。
- Part 4的骨牌就像是标准的碱基配对规则(A对T,G对C),它负责复制DNA链中稳定不变的部分。
- Part 2和Part 3的骨牌则像是由一个复杂的“分子机器”(如RNA聚合酶)执行的特殊操作。这个机器在DNA链上移动,当它遇到一个特定的序列(如qa),它会剪切并替换它,然后移动到下一个位置(br)。左移和右移就是这个分子机器的两种移动方式。整个PCP匹配的过程,就像是在观察一条DNA链如何通过这些规则,一步步地“转录”成它的下一个状态。
37. 构造过程的示例
📜 [原文11]
现在我们举一个假设的例子来说明我们目前所构建的内容。令 $\Gamma=\{0,1,2, \sqcup\}$。假设 $w$ 是字符串 $0100$,并且 $M$ 的起始状态是 $q_{0}$。在状态 $q_{0}$ 中,读取一个 $0$ 后,假设转移函数规定 $M$ 进入状态 $q_{7}$,在纸带上写入一个 $2$,并将磁头向右移动。换句话说,$\delta\left(q_{0}, 0\right)=\left(q_{7}, 2, \mathrm{R}\right)$。
第 1 部分将多米诺骨牌
$$
\left[\frac{\#}{\# q_{0} 0100 \#}\right]=\left[\frac{t_{1}}{b_{1}}\right]
$$
放入 $P^{\prime}$ 中,匹配开始

此外,第 2 部分将多米诺骨牌
$$
\left[\frac{q_{0} 0}{2 q_{7}}\right]
$$
放入 $P^{\prime}$,因为 $\delta\left(q_{0}, 0\right)=\left(q_{7}, 2, \mathrm{R}\right)$,第 4 部分将多米诺骨牌
$$
\left[\frac{0}{0}\right],\left[\frac{1}{1}\right],\left[\frac{2}{2}\right], \text { 和 }\left[\frac{\sqcup}{\sqcup}\right]
$$
放入 $P^{\prime}$,因为 $0,1,2$ 和 $\sqcup$ 是 $\Gamma$ 的成员。结合第 5 部分,这使我们能够将匹配扩展到

因此,第 2、3 和 4 部分的多米诺骨牌允许我们通过在第一个格局之后添加第二个格局来扩展匹配。我们希望这个过程继续下去,添加第三个格局,然后是第四个,依此类推。为此,我们需要再添加一张多米诺骨牌来复制符号 $\#$。
📖 [逐步解释]
这一段通过一个具体的例子,串联起了前面 Part 1, 2, 4 的构造规则,展示了模拟是如何真实发生的。
- 设定示例场景:
- 纸带字母表 $\Gamma = \{0, 1, 2, \sqcup\}$
- 输入字符串 $w = 0100$
- 起始状态 $q_0$
- 一个转移规则: $\delta(q_0, 0) = (q_7, 2, R)$。这条规则的意思是:在状态 $q_0$ 读到 0,则状态变为 $q_7$,将 0 改写为 2,然后磁头右移。
- 初始格局: $C_1 = q_00100$
- 应用 Part 1 规则:
- 构造起始骨牌:$[\frac{\#}{\#q_00100\#}]$。
- 匹配从这张牌开始,形成初始状态:
- 上方: #
- 下方: #q_00100#
- 如图所示,下方比上方多出一截 q_00100#,需要被匹配掉。
- 应用 Part 2 和 Part 4 规则:
- 根据 $\delta(q_0, 0) = (q_7, 2, R)$,Part 2 规则生成了核心的“计算骨牌”:$[\frac{q_0 0}{2 q_7}]$。
- 根据 $\Gamma$ 的内容,Part 4 规则生成了“复制骨牌”:$[\frac{0}{0}], [\frac{1}{1}], [\frac{2}{2}], [\frac{\sqcup}{\sqcup}]$。
- 演示匹配过程 (如何匹配掉 q_00100#):
- 目标: 上方需要生成 q_00100# 来匹配下方。
- 第一步: 匹配 q_00。我们看到有张计算骨牌 $[\frac{q_0 0}{2 q_7}]$。它的上方是 q_00,正好是我们需要的!
- 我们使用这张牌。上方成功添加 q_00。下方则被迫添加 2q_7。
- 第二步: 匹配 1。我们用复制骨牌 $[\frac{1}{1}]$。上方添加 1,下方也添加 1。
- 第三步: 匹配 0。我们用复制骨牌 $[\frac{0}{0}]$。上方添加 0,下方也添加 0。
- 第四步: 匹配 0。再次使用复制骨牌 $[\frac{0}{0}]$。上方添加 0,下方也添加 0。
- (这里原文跳过了一步,就是匹配最后的 #,我们将在Part 5看到这张牌)
- 展示匹配结果:
- 我们使用的骨牌序列是:$[\frac{q_0 0}{2 q_7}], [\frac{1}{1}], [\frac{0}{0}], [\frac{0}{0}]$ (暂时忽略最后的 #)。
- 上方字符串 拼接起来是 q_00 + 1 + 0 + 0 = q_00100。
- 下方字符串 拼接起来是 2q_7 + 1 + 0 + 0 = 2q_7100。
- 现在我们把起始牌和这串序列连起来看:
- 总上方: # (来自起始牌) + q_00100 = #q_00100
- 总下方: #q_00100# (来自起始牌) + 2q_7100 = #q_00100#2q_7100
- 观察:我们为了匹配掉下方的第一个格局 $C_1 = q_00100$,在上方成功地构造了它。但作为代价,我们在下方被迫构造出了第二个格局 $C_2 = 2q_7100$!
- $C_1$ 到 $C_2$ 的演化 q_00100 -> 2q_7100 正是应用了 $\delta(q_0, 0)=(q_7, 2, R)$ 规则的结果。模拟成功!
- 引出下一步: 作者指出,这个过程需要能持续下去。目前,格局之间没有分隔。为了从 $C_2$ 模拟到 $C_3$,我们需要一个方法来处理格局之间的分隔符 #。这就引出了 Part 5。
💡 [数值示例]
- 示例延续:
- 当前匹配状态:
- 上方: #q_00100
- 下方: #q_00100#2q_7100
- 新的不平衡: 下方现在多出了一段 #2q_7100 需要被匹配。
- 下一个目标: 上方需要生成 #2q_7100。这将通过 Part 5 提供的 # 骨牌和更多应用 Part 2,3,4 规则的骨牌来完成,从而在下方生成第三个格局 $C_3$。
⚠️ [易错点]
- 图示的理解: 书中的图示非常关键。它清晰地展示了上方字符串是如何“追赶”下方字符串,以及这个追赶过程如何在下方“被迫”产生新的格局。要仔细对齐图示中上下两行的内容,理解其对应关系。
- 原文的跳跃: 原文在这里说“结合第 5 部分”,但第 5 部分还没讲。这是一个写作上的前后呼应。它暗示了要完成这个匹配的扩展,我们还需要第5部分(处理#的骨牌)。
📝 [总结]
本段通过一个翔实的例子,演示了Part 1, 2, 4中构造的多米诺骨牌是如何协同工作,从而成功地将图灵机的一步计算(从 $C_1$ 到 $C_2$)转化为PCP匹配的一个扩展步骤。它生动地展示了“上方追赶,下方延伸”这一核心模拟机制。
🎯 [存在目的]
抽象的规则难以理解,一个好的例子胜过千言万语。本段的目的就是通过一个具体的、可追踪的数值例子,将前面几部分抽象的构造规则“盘活”,让读者亲眼看到模拟是如何发生的,从而对整个证明的机制建立起坚实的、形象的理解。
[直觉心-智模型]
这就像多米诺骨牌效应。第一张起始牌倒下,产生了“不平衡”(下方比上方长)。为了扶正这个不平衡,你必须按照预设的规则(计算骨牌和复制骨牌)去摆放后面的一系列骨牌。而这些规则被设计成,当你完成一个“扶正”动作(匹配掉一个格局)时,必然会触发下一个“不平衡”(在下方产生新格局)。这个连锁反应会一直持续下去,直到计算结束。
💭 [直观想象]
想象一个双人合作的打字员,A和B。A的目标是抄写B打出的内容。
- 开始: B 先打出 #q_00100#。A 只打了 #。
- A开始抄写: A想打出 q_00,他按下一个快捷键(骨牌 $[\frac{q_0 0}{2 q_7}]$)。这个键很怪,它在A的屏幕上打出了 q_00,但同时在B的屏幕末尾追加了 2q_7。
- A继续抄写: A想打出 100,他连续按了三次普通的复制键(骨牌 $[\frac{1}{1}], [\frac{0}{0}], [\frac{0}{0}]$)。这些键在A和B的屏幕末尾都追加了相同的内容 100。
- 第一轮抄写结束:
- A的屏幕: #q_00100
- B的屏幕: #q_00100#2q_7100
- A完成了对第一句话的抄写,但B的屏幕上又多出了第二句话。A不得不继续抄写下去。这个过程就是图灵机的模拟。
38. 构造第五部分:格局分隔与纸带延伸
📜 [原文12]
第 5 部分。
$$
\text { 将 }\left[\frac{\#}{\#}\right] \text { 和 }\left[\frac{\#}{\sqcup \#}\right] \text { 放入 } P^{\prime} \text{。 }
$$
第一张多米诺骨牌允许我们复制标记格局之间分隔的符号 $\#$。此外,第二张多米诺骨牌允许我们在格局末尾添加一个空白符号 $\sqcup$,以模拟当我们写入格局时被抑制的无限多个右侧空白。
📖 [逐步解释]
这一部分解决了两个在模拟过程中出现的“边界”问题:如何分隔格局,以及如何处理图灵机无限长的纸带。
- 第一张骨牌: $[\frac{\#}{\#}]$
- 规则: 添加一张上方是 #,下方也是 # 的骨牌。
- 作用: 这是一张简单的“复制”骨牌,专门用来处理格局分隔符 #。
- 必要性: 回到上一个例子,当上方字符串成功匹配掉 $C_1 = q_00100$ 后,下方字符串变成了 #q_00100#C_2...。此时,上方需要匹配的下一个符号就是 #。这张 $[\frac{\#}{\#}]$ 骨牌正好能完成这个任务:上方添加一个 # 完成了匹配,同时下方也添加一个 #,这个下方新加的 # 正好成为新格局 $C_2$ 和未来可能出现的 $C_3$ 之间的分隔符。它确保了计算历史 ...#C_1#C_2#C_3... 的结构能够被正确地维护。
- 第二张骨牌: $[\frac{\#}{\sqcup \#}]$
- 规则: 添加一张上方是 #,下方是 sqcup# 的骨牌。
- 作用: 这张骨牌用来模拟图灵机纸带的无限性。
- 必要性: 在图灵机的计算中,磁头可能会移动到之前从未访问过的、布满空格符号 $\sqcup$ 的区域。例如,一个格局可能是 uqv,但下一步磁头右移,格局可能变成 ubrv',其中 $v'$ 是 $v$ 的一部分。如果 $v$ 是空的,磁头移到 $v$ 的右边,它实际上是移到了一个原来是隐式的 $\sqcup$ 上。我们的格局表示是有限字符串,无法表示无限的空格。这张骨牌提供了一个机制来“按需生成”这些空格。
- 如何工作: 这张骨牌和上一张 $[\frac{\#}{\#}]$ 骨牌在使用时机上是相同的,都是在匹配完一个格局后,去匹配下一个分隔符 # 时使用。但它提供了一个选择:
- 选择1 (用 $[\frac{\#}{\#}]$): 上下都加 #。新旧格局长度可能不变(或因计算而改变)。
- 选择2 (用 $[\frac{\#}{\sqcup \#}]$): 上方加 #,下方加 sqcup#。这相当于在下一个格局的末尾(#的前面)人为地增加了一个空格符 $\sqcup$。这模拟了纸带向右“延伸”了一格。当图灵机需要用到更多纸带空间时,匹配过程就可以通过选择这张骨牌来提供。
💡 [数值示例]
- 示例1 (使用 $[\frac{\#}{\#}]$):
- 匹配前:
- 上方: ...C_1
- 下方: ...C_1#C_2
- 任务: 匹配下方的 #。
- 使用骨牌: $[\frac{\#}{\#}]$。
- 匹配后:
- 上方: ...C_1#
- 下方: ...C_1#C_2#
- 效果: 上方成功匹配 #。下方则在 $C_2$ 之后也添加了 #,为 $C_3$ 的出现做好了准备。
- 示例2 (使用 $[\frac{\#}{\sqcup \#}]$):
- 场景: 假设格局 $C_k = uaq$ (磁头在最右边),且转移规则是 $\delta(q, \sqcup) = (r, b, R)$。这意味着下一步磁头需要移到当前格局表示的范围之外。
- 匹配前:
- 上方: ...C_{k-1}
- 下方: ...C_{k-1}\#uaq
- 匹配 $C_{k-1}$ 之后,轮到匹配 #: 我们需要延伸纸带,所以选择 $[\frac{\#}{\sqcup \#}]$。
- 匹配后:
- 上方: ...C_{k-1}\#
- 下方: ...C_{k-1}\#uaq\sqcup\# (注意下方多了一个 $\sqcup$)
- 效果: 下一个要匹配的格局变成了 uaqsqcup。现在,当模拟到状态 q 时,它右边有一个 sqcup 可供读取,从而可以应用规则 $\delta(q, \sqcup)$。这张骨牌成功地按需扩展了纸带。
⚠️ [易错点]
- 两张#骨牌的选择: 在每个格局的末尾,构造者在寻找匹配时都有一个选择:是用 $[\frac{\#}{\#}]$ 还是 $[\frac{\#}{\sqcup \#}]$?这个选择不是任意的,而是由图灵机的计算需求决定的。如果下一步计算不需要新的纸带空间,选择哪一个可能都可以(或者只能选第一个)。但如果需要,就必须选择第二个。这种由“未来需求”决定的选择,是PCP匹配寻找过程的一部分。
📝 [总结]
第5部分提供了两张处理格局分隔符 # 的特殊骨牌。第一张 $[\frac{\#}{\#}]$ 用于在格局之间建立清晰的边界。第二张 $[\frac{\#}{\sqcup \#}]$ 在此基础上,还提供了一个巧妙的机制来模拟图灵机无限纸带的按需延伸,即在格局末尾添加空格。
🎯 [存在目的]
这部分是为了处理模拟过程中的结构性和边界性问题。没有 $[\frac{\#}{\#}]$,计算历史的格局链就会断裂。没有 $[\frac{\#}{\sqcup \#}]$,对图灵机纸带的模拟就是不完整的,无法处理磁头移动到新区域的情况。这部分使得整个模拟框架更加健壮和完整。
[直觉心-智模型]
这就像在写一本书,每个格局是一个章节。
- $[\frac{\#}{\#}]$ 骨牌就像是按下“新章节”按钮。你在目录(上方)里标记了“第2章结束”,这本书的正文(下方)也自动翻到了新的一页,打上了“第3章”的标题。
- $[\frac{\#}{\sqcup \#}]$ 骨牌则是一个更高级的“新章节”按钮。它不仅开启了新的一章,还在正文新章节的末尾自动加了一行空白。这行为之后的写作(计算)留出了更多的空间。
💭 [直观想象]
想象你在用一卷无限长的收银条(下方字符串)记录一个过程。每个格局是一次交易记录。
- 用 $[\frac{\#}{\#}]$ 就像是每次打完一笔交易,你就按一下“打印分隔线”的按钮,打出一行***。
- 用 $[\frac{\#}{\sqcup \#}]$ 则更像是,你不仅打印了分隔线,还顺便把收银纸往前多送了一段空白出来,以防下一笔交易的商品名太长写不下。
39. 构造过程的进一步示例
📜 [原文13]
继续举例,假设在状态 $q_{7}$ 中,读取一个 $1$ 后,$M$ 进入状态 $q_{5}$,写入一个 $0$,并将磁头向右移动。也就是说,$\delta\left(q_{7}, 1\right)= \left(q_{5}, 0, \mathrm{R}\right)$。那么我们有多米诺骨牌
$$
\left[\frac{q_{7} 1}{0 q_{5}}\right] \text { 在 } P^{\prime} \text{ 中。 }
$$
所以最新的部分匹配扩展到

然后,假设在状态 $q_{5}$ 中,读取一个 $0$ 后,$M$ 进入状态 $q_{9}$,写入一个 $2$,并将磁头向左移动。所以 $\delta\left(q_{5}, 0\right)=\left(q_{9}, 2, \mathrm{~L}\right)$。那么我们有多米诺骨牌
$$
\left[\frac{0 q_{5} 0}{q_{9} 02}\right],\left[\frac{1 q_{5} 0}{q_{9} 12}\right],\left[\frac{2 q_{5} 0}{q_{9} 22}\right], \text { 和 }\left[\frac{\sqcup q_{5} 0}{q_{9} \sqcup 2}\right] \text{。 }
$$
第一个是相关的,因为磁头左侧的符号是 $0$。前面的部分匹配扩展到

📖 [逐步解释]
这一段继续使用之前的例子,连续演示了图灵机的第二步和第三步计算是如何在PCP匹配中被模拟的,分别展示了一个右移和一个左移操作。
模拟第二步计算(右移)
- 新的转移规则: 假设 $\delta(q_7, 1) = (q_5, 0, R)$。这是第二步计算的规则。
- 生成对应骨牌 (Part 2): 根据此规则,构造器会生成一张右移骨牌 $[\frac{q_7 1}{0 q_5}]$。
- 延续匹配:
- 当前状态: 上方是 #q_00100,下方是 #q_00100#2q_7100。
- 下一个任务: 上方需要匹配掉下方的 #2q_7100。
- 步骤 3.1: 匹配 #。使用 Part 5 的 $[\frac{\#}{\#}]$ 骨牌。上方添加 #,下方也添加 #。
- 上方: #q_00100#
- 下方: #q_00100#2q_7100#
- 步骤 3.2: 匹配 2。使用 Part 4 的复制骨牌 $[\frac{2}{2}]$。
- 上方: #q_00100#2
- 下方: #q_00100#2q_7100#2
- 步骤 3.3: 匹配 q_71。使用我们刚生成的右移骨牌 $[\frac{q_7 1}{0 q_5}]$。
- 上方: #q_00100#2q_71
- 下方: #q_00100#2q_7100#20q_5
- 步骤 3.4: 匹配剩下的 00。使用两次 $[\frac{0}{0}]$。
- 第二步模拟完成:
- 最终上方: #q_00100#2q_7100
- 最终下方: #q_00100#2q_7100#20q_500
- 观察: 我们成功在上方匹配了第二个格局 $C_2 = 2q_7100$ (注意这里的 $C_2$ 表示法有些出入,应该是 $2q_7100$)。作为代价,在下方生成了第三个格局 $C_3 = 20q_500$。
- 我们检查一下这个格局演化 2q_7100 -> 20q_500 是否正确。确实是应用 $\delta(q_7, 1)=(q_5, 0, R)$ 的结果。
模拟第三步计算(左移)
- 新的转移规则: 假设 $\delta(q_5, 0) = (q_9, 2, L)$。这是第三步计算规则。
- 生成对应骨牌 (Part 3):
- 这是一个左移动作。我们需要考虑磁头左边的符号。在格局 $C_3 = 20q_500$ 中,磁头在第二个0上,它左边的符号是第一个0。所以,我们需要一个 c=0 的左移骨牌。
- Part 3 的规则会生成一系列骨牌,包括我们需要的那个:
- 当 c=0: $[\frac{0q_50}{q_902}]$
- 当 c=1: $[\frac{1q_50}{q_912}]$ (虽然当前用不上,但构造时会生成)
- ...等等。
- 延续匹配:
- 当前状态: 上方是 #...#C_2,下方是 #...#C_2#C_3。
- 任务: 上方需要匹配 #C_3,即 #20q_500。
- 过程: 类似于上一步,用 $[\frac{\#}{\#}], [\frac{2}{2}], [\frac{0}{0}]$ 匹配掉 #20。
- 关键步骤: 匹配 q_50。不对,左移骨牌是三个字符的,它需要匹配 0q_50。
- 让我们回看格局 $C_3 = 20q_500$。磁头 q_5 左边是 0,当前读的是 0。所以要匹配的部分是 0q_50。
- 我们使用左移骨牌 $[\frac{0q_50}{q_902}]$。
- 上方添加 0q_50,成功匹配。下方被迫添加 q_902。
- 第三步模拟完成:
- 我们看看下方发生了什么:在格局 C_3=...20q_500... 之后,我们通过一系列骨牌,在底部生成了第四个格局 $C_4$。
- $C_3$ 中片段 ...20q_50... 对应生成了 $C_4$ 的片段 ...2q_902...。
- 格局演化 ...20q_500... -> ...2q_9020... (忽略其他部分)。这正是应用 $\delta(q_5, 0) = (q_9, 2, L)$ 的结果。模拟再次成功!
💡 [数值示例]
- 计算历史链:
- $C_1 = q_00100$
- $C_2 = 2q_7100$ (应用 $\delta(q_0, 0)=(q_7, 2, R)$)
- $C_3 = 20q_500$ (应用 $\delta(q_7, 1)=(q_5, 0, R)$)
- $C_4 = 2q_9020$ (应用 $\delta(q_5, 0)=(q_9, 2, L)$)
- PCP匹配链 (底部):
- 开始: #q_00100#
- 一步后: #q_00100#2q_7100#
- 两步后: #q_00100#2q_7100#20q_500#
- 三步后: #q_00100#2q_7100#20q_500#2q_9020#
- PCP匹配链 (顶部):
- 开始: #
- 一步后: #q_00100
- 两步后: #q_00100#2q_7100
- 三步后: #q_00100#2q_7100#20q_500
- 这个过程清晰地展示了,顶部字符串总是精确地比底部字符串“落后”一个格局。
⚠️ [易错点]
- 图示的对齐: 书中的图示是理解的关键。务必仔细观察每次扩展后,上下字符串是如何对齐的,以及新的“尾巴”是如何产生的。
- 左移骨牌的选择: 再次强调,对于左移,我们需要从一组骨牌中选择正确的那一个。这个选择是根据当前格局中磁头左边的符号来决定的,不是任意的。
📝 [总结]
本段通过连续模拟两步计算(一次右移,一次左移),进一步强化了读者对PCP构造如何模拟图灵机计算的理解。它具体展示了Part 2(右移)和Part 3(左移)的骨牌是如何在匹配过程中被选中并发挥作用的。
🎯 [存在目的]
这段的目的是为了让模拟过程“动起来”。前面的例子只展示了第一步,这里展示了第二步和第三步,特别是引入了更复杂的左移情况。这让读者相信,这个构造机制是通用的,足以处理任何图灵机的任何计算步骤,从而对整个证明的有效性建立信心。
🧠 [直觉心智模型]
这就像一个“你追我赶”的游戏。上方字符串的任务是“追赶”并复制下方字符串的内容。但每当它成功复制了一段(一个格局),下方字符串就会利用这个机会“逃跑”并延伸出新的一段(下一个格局)。这个追逐游戏会一直持续,直到图灵机停机。
💭 [直观想象]
想象你在编织一条长长的挂毯(PCP匹配)。挂毯有上下两层。你按照一个模式(下方已有的格局)在上面一层编织。但你使用的线很特殊(计算骨牌):每当你用一种颜色的线在上面织出一个图案,这种线会自动在下面一层织出下一个图案。你的编织过程被迫推动了整个故事(计算历史)的发展。
310. 构造第六部分:处理接受状态
📜 [原文14]
请注意,当我们构造一个匹配时,我们被迫模拟 $M$ 在输入 $w$ 上的行为。这个过程一直持续到 $M$ 达到停机状态。如果出现接受状态,我们希望部分匹配的顶部与底部“赶上”,以便匹配完成。我们可以通过添加额外的多米诺骨牌来安排这种情况。
第 6 部分。对于每个 $a \in \Gamma$,
$$
\text { 将 }\left[\frac{a q_{\mathrm{accept}}}{q_{\mathrm{accept}}}\right] \text { 和 }\left[\frac{q_{\mathrm{accept}} a}{q_{\mathrm{accept}}}\right] \text { 放入 } P^{\prime} \text{。 }
$$
此步骤的效果是在图灵机停机状态后添加“伪步骤”,其中磁头“吃掉”相邻符号直到没有剩余。继续举例,如果机器在接受状态停机状态时的部分匹配是

我们刚刚添加的多米诺骨牌允许匹配继续:

📖 [逐步解释]
这部分处理的是模拟的“终局”:当图灵机进入接受状态 $q_{accept}$ 时,如何让PCP匹配得以成功完成。
- 终局问题: 目前为止,我们的构造中,上方字符串总是比下方字符串短一个格局。如果图灵机进入 $q_{accept}$ 并停机,这个“债务”就永远还不清了,PCP匹配也就无法完成。这是不行的,因为我们要求“$M$接受$w$” 当且仅当 “$P'$有匹配”。所以,当$M$接受时,我们必须提供一种方法让匹配完成。
- 解决方案:“吃豆人”模式: 当图灵机进入 $q_{accept}$ 状态后,我们引入一套新的“伪计算”规则。这些规则不再模拟图灵机的真实计算,而是进入一个“清场”或“收尾”阶段。这个阶段的目标就是让上方字符串能快速“吃掉”下方剩余的字符,最终追平下方。
- 构造规则 (Part 6):
- 对于纸带字母表 $\Gamma$ 中的每一个符号 a,我们添加两类骨牌:
- $[\frac{a q_{accept}}{q_{accept}}]$: 对应 $q_{accept}$ 状态“吃掉”其右侧的符号 a。
- $[\frac{q_{accept} a}{q_{accept}}]$: 对应 $q_{accept}$ 状态“吃掉”其左侧的符号 a。
- 工作机制:
- 假设在某个格局中,出现了 $q_{accept}$,比如 ...b q_{accept} a...。
- 上方需要匹配这段 ...b q_{accept} a...。
- 吃掉右边的 a: 上方需要匹配 q_{accept}a。我们可以用骨牌 $[\frac{q_{accept} a}{q_{accept}}]$。
- 使用后: 上方添加 q_{accept}a,下方只添加 q_{accept}。
- 效果: 上方字符串比下方多“追赶”了一个字符 a 的长度。格局从 ...b q_{accept} a... 变成了 ...b q_{accept}...。
- 吃掉左边的 b: 接下来上方可能需要匹配 b q_{accept}。我们可以用骨牌 $[\frac{b q_{accept}}{q_{accept}}]$。
- 使用后: 上方添加 b q_{accept},下方只添加 q_{accept}。
- 效果: 上方又多追赶了一个字符 b 的长度。格局从 ...b q_{accept}... 变成了 ...q_{accept}...。
- 这个过程可以不断重复, $q_{accept}$ 就像一个“吃豆人”,不断地将左右两边的纸带符号“吃掉”(在上方匹配掉,但在下方不再产生它们),从而迅速缩短下方字符串,让上方字符串有机会追上。
- 图示解释:
- 图中展示了,当最后一个真实格局包含 $q_{accept}$ 后,比如下方是 ...#...q_{accept}01#。
- 上方匹配掉 #... 后,开始匹配 q_{accept}01。
- 它会先用 $[\frac{q_{accept}0}{q_{accept}}]$,再用 $[\frac{q_{accept}1}{q_{accept}}]$ (假设 $q_{accept}$ 在0左边)。
- 这个过程最终会让下方只剩下 ...#q_{accept}#,而上方则匹配了完整的最后一个格局。
💡 [数值示例]
- 示例:
- 假设图灵机停机前的最后一个格局是 $C_{final} = 10q_{accept}1$。
- PCP匹配状态:
- 上方: ...#C_{final-1}
- 下方: ...#C_{final-1}\#10q_{accept}1\#
- 收尾阶段开始: 上方需要匹配 #10q_{accept}1#。
- 1. 匹配 #: 使用 $[\frac{\#}{\#}]$。
- 上: ...#
- 下: ...#10q_{accept}1##
- 2. 匹配 10: 使用 $[\frac{1}{1}], [\frac{0}{0}]$。
- 上: ...#10
- 下: ...#10q_{accept}1##10
- 3. 匹配 q_{accept}1 (吃掉右边的1): 使用 $[\frac{q_{accept}1}{q_{accept}}]$。
- 上: ...#10q_{accept}1
- 下: ...#10q_{accept}1##10q_{accept}
- 4. 匹配 0q_{accept} (吃掉左边的0): 此时下方的 q_{accept} 左边是0。上方需要匹配 0q_{accept}。我们用 $[\frac{0q_{accept}}{q_{accept}}]$。
- 上: ...#10q_{accept}1#10q_{accept} (这里有点复杂,我们简化一下思路)
- 更清晰的思路: 当上方需要匹配 10q_{accept}1 时:
- 用 $[\frac{1}{1}], [\frac{0}{0}]$ 匹配 10。
- 用 $[\frac{q_{accept}1}{q_{accept}}]$ 匹配 q_{accept}1。此时,下方只生成了 q_{accept}。
- 接着用 $[\frac{0q_{accept}}{q_{accept}}]$ (假设现在格局是 0q_{accept}) 匹配 0q_{accept},下方又只生成 q_{accept}。
- 这个过程持续,直到纸带上的符号都被“吃光”,只剩下 $q_{accept}$。
⚠️ [易错点]
- 为何不需要为 $q_{reject}$ 设计?: 如果图灵机进入拒绝状态 $q_{reject}$,我们不提供任何类似的“收尾”骨牌。因此,模拟会“卡住”,上方永远无法追平下方,匹配永远无法完成。这正是我们想要的结果,因为我们只关心接受计算。
- “吃”的顺序: 是从内向外吃,还是从左到右?这取决于 $q_{accept}$ 两边符号的匹配顺序。PCP匹配的寻找过程会自动探索正确的“吃”法。
📝 [总结]
第6部分为模拟的成功终结提供了机制。当且仅当图リング机进入接受状态 $q_{accept}$ 时,一组特殊的“吃豆人”多米诺骨牌会被激活。这些骨牌允许上方字符串在匹配格局的同时,比下方字符串“赚”取字符,从而逐步消除不平衡,为最终完成匹配创造了条件。
🎯 [存在目的]
这部分是连接“图灵机接受”和“PCP有解”这两个概念的关键桥梁。没有这个收尾机制,即使图灵机接受了,PCP匹配也完不成,归约就会失败。这部分确保了逻辑链条的“当且仅当”关系中的“正向”部分($M$接受$w$ => $P'$有匹配)能够成立。
🧠 [直觉心智模型]
这就像游戏结束时的“奖励关卡”。在整个游戏(模拟)过程中,你一直处于“债务”状态(上方比下方短)。当你成功到达终点(进入$q_{accept}$)时,游戏会解锁一个特殊的“清债模式”。在这个模式下,你每做一个动作(匹配一个符号),你的债务就减少一点。最终,你可以还清所有债务,成功通关(完成匹配)。
💭 [直观想象]
想象你在用积木搭一个两层的塔,要求上下两层最终要一样高。你有一堆普通的积木(计算骨牌),它们的效果是“上层加1块,下层也加1块”,所以下层因为有个初始高度,总是比上层高。但你还有一种金色的“奖励积木”($q_{accept}$骨牌),只有当你搭到某个特定阶段才能使用。这种金色积木的效果是“上层加1块,下层不加”。一旦你可以使用金色积木,你就能不断地只给上层增加高度,最终让它和下层一样高,完成任务。
313. 最终构造:* 编码
📜 [原文17]
令 $u=u_{1} u_{2} \cdots u_{n}$ 为任意长度为 $n$ 的字符串。将 $\star u, u \star$ 和 $\star u \star$ 定义为三个字符串
$$
\begin{aligned}
& \star u \quad=\quad * u_{1} * u_{2} * u_{3} * \quad \cdots \quad * u_{n} \\
& u \star=u_{1} * u_{2} * u_{3} * \cdots \quad * u_{n} * \\
& \star u \star=* u_{1} * u_{2} * u_{3} * \cdots \quad * u_{n} * \text{。 }
\end{aligned}
$$
这里,$\star u$ 在 $u$ 中的每个字符前添加符号 ,$u \star$ 在 $u$ 中的每个字符后添加一个 ,而 $\star u \star$ 则在 $u$ 中的每个字符前和后都添加一个 *。
要将 $P^{\prime}$ 转换为 PCP 的实例 $P$,我们执行以下操作。如果 $P^{\prime}$ 是集合
$$
\left\{\left[\frac{t_{1}}{b_{1}}\right],\left[\frac{t_{2}}{b_{2}}\right],\left[\frac{t_{3}}{b_{3}}\right], \ldots,\left[\frac{t_{k}}{b_{k}}\right]\right\}
$$
我们令 $P$ 为集合
$$
\left\{\left[\frac{\star t_{1}}{\star b_{1} \star}\right],\left[\frac{\star t_{1}}{b_{1} \star}\right],\left[\frac{\star t_{2}}{b_{2} \star}\right],\left[\frac{\star t_{3}}{b_{3} \star}\right], \ldots,\left[\frac{\star t_{k}}{b_{k} \star}\right],\left[\frac{* \diamond}{\diamond}\right]\right\} .
$$
将 $P$ 视为 PCP 的实例,我们看到唯一可能开始匹配的多米诺骨牌是第一张,
$$
\left[\frac{\star t_{1}}{\star b_{1} \star}\right]
$$
因为它是在上方和下方都以相同符号(即 )开始的唯一一张。除了强制匹配从第一张多米诺骨牌开始之外, 的存在不会影响可能的匹配,因为它们只是与原始符号交错。原始符号现在出现在匹配的偶数位置。多米诺骨牌
$$
\left[\frac{* \diamond}{\diamond}\right]
$$
的存在是为了让上方在匹配的末尾添加额外的 *。
📖 [逐步解释]
这是实现从 MPCP 到 PCP 转换的具体技术,即 * 编码技巧。
- 定义 * 编码:
- 首先定义了三种在字符串中插入 * 的操作:
- star u: 在 u 的每个字符前加 。例: u="abc" -> star u="abc"。
- u star: 在 u 的每个字符后加 。例: u="abc" -> u star="abc"。
- star u star: 在 u 的每个字符前后都加 。例: u="abc" -> star u star="abc*"。
- 注意,书中的 star u star 的例子 u1u2...un 和 u star 的例子 u1u2...un* 都和 u star 的定义更吻合。我们以文字描述为准:star u star 是前后都加。这里的核心思想是:star u 和 u star 的交错模式不同。
- 构造新的PCP实例 P:
- 假设我们已经有了 MPCP 实例 $P' = \{[\frac{t_1}{b_1}], [\frac{t_2}{b_2}], ..., [\frac{t_k}{b_k}]\}$。
- 我们基于 $P'$ 构造新的 PCP 实例 $P$。$P$ 中的骨牌是对 $P'$ 中骨牌的改造:
- 改造起始牌 (第1张): $P'$ 的第一张牌 $[\frac{t_1}{b_1}]$ 被改造成 $P$ 中的第一张牌 $[\frac{\star t_1}{\star b_1 \star}]$。
- 改造其他牌 (第2到k张): $P'$ 的其他牌 $[\frac{t_i}{b_i}]$ ($i>1$) 被改造成 $P$ 中的 $[\frac{\star t_i}{b_i \star}]$。
- 添加一张特殊牌: $P$ 中还额外增加了一张全新的牌 $[\frac{*\diamond}{\diamond}]$。这里 diamond 是另一个新符号。
- 分析新实例 P 的性质:
- 强制起点: 让我们看看 $P$ 中的牌,哪一张可以作为 PCP 匹配的起点。
- 第一张牌: $[\frac{\star t_1}{\star b_1 \star}]$。上方以 开始,下方也以 开始。它可以作为起点。
- 其他改造牌: $[\frac{\star t_i}{b_i \star}]$ ($i>1$)。上方以 开始,但下方以 $b_i$ 的第一个字符开始(它不是 )。所以它们不能作为起点。
- 特殊牌: $[\frac{*\diamond}{\diamond}]$。上方以 * 开始,下方以 diamond 开始。也不能作为起点。
- 结论: 唯一能启动匹配的只有第一张改造牌。这样,我们就用骨牌自身的设计,强制了匹配必须从对应于原 MPCP 起始牌的那张牌开始。
- * 的交错作用:
- 一旦匹配从 $[\frac{\star t_1}{\star b_1 \star}]$ 开始,我们看看字符串的样子:
- 上: t_1_1t_1_2...
- 下: b_1_1b_1_2...*
- 下方比上方多一个结尾的 *。现在,如果我们选择一张改造牌 $[\frac{\star t_i}{b_i \star}]$ 接在后面:
- 上: ...t_1_n + t_i_1t_i_2... -> ...t_1_nt_i_1t_i_2...
- 下: ...b_1_m + b_i_1b_i_2... -> ...b_1_mb_i_1b_i_2...
- 你会发现, 和原始符号始终保持着 a b c ... 和 a b c ... 这种交错模式。上方总是在奇数位是 ,偶数位是原符号。下方总是在偶数位是 *,奇数位是原符号。
- 这个精巧的设计保证了,只要下方比上方多一个 ,这个状态就会一直维持下去。 只是一个“骨架”,它不影响原始符号的匹配逻辑,原始符号的匹配完全由 $t_i$ 和 $b_i$ 决定。
- 所以,如果 $P'$ 有一个 MPCP 匹配,那么 $P$ 也会有一个对应的 PCP 匹配。
- 特殊牌 $[\frac{*\diamond}{\diamond}]$ 的作用:
- 这个在原文中的牌应该是 $[\frac{*}{\diamond}]$ 或类似的,原文 $[\frac{*\diamond}{\diamond}]$ 有点令人困惑。我们假设它的作用是处理最后的尾巴。在匹配的最后,上方可能需要一个 来匹配下方多出的最后一个 。但如果用 $[\frac{*}{*}]$,下方又会多一个 。这张特殊牌(可能应该是 $[\frac{*}{\empty}]$,上方 ,下方空)允许上方添加一个 * 而下方不添加任何东西,从而完成最终的闭合。书中的 $[\frac{*\diamond}{\diamond}]$ 可能是一个更复杂的机制,但其核心思想是完成最后的对齐。
⚠️ [易错点]
- 编码的精确性: star u 和 u star 的区别非常关键。正是这个 位置的微小差异,导致了下方字符串总是比上方多一个“悬挂”在末尾的 *,从而驱动了整个交错匹配过程。
- 收尾牌的困惑: 书中对最后一张特殊牌的描述比较简略,可能会引起困惑。重点是理解它的功能需求:在匹配末尾,上方需要一种方法来添加一个 以匹配下方的最后一个 ,并且这个过程不能在下方再产生新的字符。
📝 [总结]
本段给出了从 MPCP 到 PCP 归约的具体实现方法——编码。通过在字符串中巧妙地交错插入 符号,我们改造了 MPCP 实例 $P'$ 中的所有骨牌,生成了新的 PCP 实例 $P$。这个改造达到了两个目的:1) 只有对应于原起始牌的改造牌才能作为新匹配的起点;2) * 的交错模式确保了原始的匹配逻辑不受干扰。这样,就将在 MPCP 中的外部规则(强制起点)成功地内化为了 PCP 实例自身的结构性约束,完成了整个不可判定性的证明链条。
🎯 [存在目的]
这是整个证明的收官阶段。它解决了从 MPCP 到 PCP 的“最后一公里”问题,弥补了证明链条上最后一个缺口。这个精巧的编码技巧,是计算理论中归约证明魅力的一个极好范例,展示了如何用符号操作来强制实现某种计算行为。
🧠 [直觉心智模型]
这就像是给一套多米诺骨牌加上磁性。我们给起始牌的底部和顶部都装上N极磁铁。给其他牌的顶部装上N极,底部装上S极。这样,当你把它们放在金属桌面上时,只有起始牌能稳稳地吸住。其他的牌,因为底部是S极,会被桌面排斥,无法作为起点。而一旦你放下了起始牌,其他牌就能因为异极相吸而正确地接在后面。我们用物理属性(磁性)强制了正确的顺序。
💭 [直观想象]
想象你在设计一个拼图游戏。为了确保玩家从中间的“天空”部分(起始牌)开始拼,你把所有“天空”碎片的边缘做成独特的波浪形。而所有“地面”碎片的边缘是直线。这样,玩家自然会发现,只有波浪形的碎片能互相拼接,从而被迫从“天空”开始。* 编码就扮演了这个“独特边缘”的角色。
4行间公式索引
- 单张多米诺骨牌示例:
$$
\left[\frac{a}{a b}\right]
$$
- 一个多米诺骨牌集合(PCP实例)的示例:
$$
\left\{\left[\frac{\mathrm{b}}{\mathrm{ca}}\right],\left[\frac{\mathrm{a}}{\mathrm{ab}}\right],\left[\frac{\mathrm{ca}}{\mathrm{a}}\right],\left[\frac{\mathrm{abc}}{\mathrm{c}}\right]\right\} .
$$
- 一个成功的匹配(骨牌序列):
$$
\left[\frac{\mathrm{a}}{\mathrm{ab}}\right]\left[\frac{\mathrm{b}}{\mathrm{ca}}\right]\left[\frac{\mathrm{ca}}{\mathrm{a}}\right]\left[\frac{\mathrm{a}}{\mathrm{ab}}\right]\left[\frac{\mathrm{abc}}{\mathrm{c}}\right]
$$
- 匹配的可视化表示:
$$
\left|\begin{array}{l|l|ll|l|lll}
a & b & c & a & a & a & b & c \\
a & b & c & a & a & a & b & c
\end{array}\right|
$$
- 一个不可能有匹配的PCP实例:
$$
\left\{\left[\frac{\mathrm{abc}}{\mathrm{ab}}\right],\left[\frac{\mathrm{ca}}{\mathrm{a}}\right],\left[\frac{\mathrm{acc}}{\mathrm{ba}}\right]\right\}
$$
- PCP实例的形式化定义:
$$
P=\left\{\left[\frac{t_{1}}{b_{1}}\right],\left[\frac{t_{2}}{b_{2}}\right], \ldots,\left[\frac{t_{k}}{b_{k}}\right]\right\},
$$
- PCP问题的语言形式化定义:
$$
\begin{gathered}
P C P=\{\langle P\rangle \mid P \text { 是一个具有**匹配**的**邮政对应问题**的**实例** } \\
\end{gathered}
$$
- MPCP问题中被指定的起始多米诺骨牌:
$$
\left[\frac{t_{1}}{b_{1}}\right] .
$$
- 修改版PCP(MPCP)的语言形式化定义:
$$
\begin{gathered}
M P C P=\{\langle P\rangle \mid P \text { 是一个**邮政对应问题**的**实例** } \\
\text { 且其**匹配**以第一张**多米诺骨牌**开始 }\} .
\end{gathered}
$$
- 被模拟的图灵机M的形式化定义:
$$
M=\left(Q, \Sigma, \Gamma, \delta, q_{0}, q_{\text {accept }}, q_{\text {reject }}\right)
$$
- 构造Part 1:创建起始骨牌:
$$
\text { 将 }\left[\frac{\#}{\# q_{0} w_{1} w_{2} \cdots w_{n} \#}\right] \text { 作为第一张**多米诺骨牌** }\left[\frac{t_{1}}{b_{1}}\right] \text { 放入 } P^{\prime} \text { 中。 }
$$
- 构造Part 2:创建模拟磁头右移的骨牌:
$$
\text { 如果 } \delta(q, a)=(r, b, \mathrm{R}) \text {,将 }\left[\frac{q a}{b r}\right] \text { 放入 } P^{\prime} \text {。 }
$$
- 构造Part 3:创建模拟磁头左移的骨牌:
$$
\text { 如果 } \delta(q, a)=(r, b, \mathrm{~L}) \text {,将 }\left[\frac{c q a}{r c b}\right] \text { 放入 } P^{\prime} \text。 }
$$
- 构造Part 4:创建复制纸带不变部分的骨牌:
$$
\text { 将 }\left[\frac{a}{a}\right] \text { 放入 } P^{\prime} \text。 }
$$
- 构造示例中的起始骨牌:
$$
\left[\frac{\#}{\# q_{0} 0100 \#}\right]=\left[\frac{t_{1}}{b_{1}}\right]
$$
- 构造示例中由右移规则产生的骨牌:
$$
\left[\frac{q_{0} 0}{2 q_{7}}\right]
$$
- 构造示例中由纸带字母表产生的复制骨牌:
$$
\left[\frac{0}{0}\right],\left[\frac{1}{1}\right],\left[\frac{2}{2}\right], \text { 和 }\left[\frac{\sqcup}{\sqcup}\right]
$$
- 构造Part 5:创建处理格局分隔和纸带延伸的骨牌:
$$
\text { 将 }\left[\frac{\#}{\#}\right] \text { 和 }\left[\frac{\#}{\sqcup \#}\right] \text { 放入 } P^{\prime} \text{。 }
$$
- 构造示例中第二步计算(右移)的骨牌:
$$
\left[\frac{q_{7} 1}{0 q_{5}}\right] \text { 在 } P^{\prime} \text{ 中。 }
$$
- 构造示例中第三步计算(左移)的一系列骨牌:
$$
\left[\frac{0 q_{5} 0}{q_{9} 02}\right],\left[\frac{1 q_{5} 0}{q_{9} 12}\right],\left[\frac{2 q_{5} 0}{q_{9} 22}\right], \text { 和 }\left[\frac{\sqcup q_{5} 0}{q_{9} \sqcup 2}\right] \text{。 }
$$
- 构造Part 6:为接受状态创建“吃豆人”骨牌:
$$
\text { 将 }\left[\frac{a q_{\mathrm{accept}}}{q_{\mathrm{accept}}}\right] \text { 和 }\left[\frac{q_{\mathrm{accept}} a}{q_{\mathrm{accept}}}\right] \text { 放入 } P^{\prime} \text{。 }
$$
- 构造Part 7:创建最终闭合匹配的骨牌:
$$
\left[\frac{q_{\text {accept }} \# \#}{\#}\right]
$$
- 星号(*)编码的定义:
$$
\begin{aligned}
& \star u \quad=\quad * u_{1} * u_{2} * u_{3} * \quad \cdots \quad * u_{n} \\
& u \star=u_{1} * u_{2} * u_{3} * \cdots \quad * u_{n} * \\
& \star u \star=* u_{1} * u_{2} * u_{3} * \cdots \quad * u_{n} * \text{。 }
\end{aligned}
$$
- MPCP 实例 P' 的通用形式:
$$
\left\{\left[\frac{t_{1}}{b_{1}}\right],\left[\frac{t_{2}}{b_{2}}\right],\left[\frac{t_{3}}{b_{3}}\right], \ldots,\left[\frac{t_{k}}{b_{k}}\right]\right\}
$$
- 从 P' 转换到 PCP 实例 P 的最终构造:
$$
\left\{\left[\frac{\star t_{1}}{\star b_{1} \star}\right],\left[\frac{\star t_{1}}{b_{1} \star}\right],\left[\frac{\star t_{2}}{b_{2} \star}\right],\left[\frac{\star t_{3}}{b_{3} \star}\right], \ldots,\left[\frac{\star t_{k}}{b_{k} \star}\right],\left[\frac{* \diamond}{\diamond}\right]\right\} .
$$
- 新构造 P 中唯一能启动匹配的骨牌:
$$
\left[\frac{\star t_{1}}{\star b_{1} \star}\right]
$$
- 新构造 P 中用于收尾的特殊骨牌:
$$
\left[\frac{* \diamond}{\diamond}\right]
$$