OpenDSA 全教程

Chapter 28 Limits to Computing

| 关于   «  21. 不可解问题   ::   目录   ::   1. 术语表  »

22. 图灵机

22.1. 图灵机

22.1.1. 通用计算模型

在本模块中,我们寻求定义一个尽可能简单的通用计算模型。 原因是我们希望能够理解计算可能性的极限,而这 在一个对"计算机"的复杂定义下相当难做到。 但是,我们也需要确信,无论我们选择哪个模型,它 确实代表了"计算机"的所有基本能力。 特别是,我们希望这个模型能够计算我们的"普通"计算机 所能计算的任何函数。

"状态机"很容易理解。 有若干种不同的状态机,能力各不相同。 我们将讨论其中特别的一种,称为 图灵机。 在讨论"能力"时,关键是 能力,而不是 效率。

任何此类"机器"的必要能力如下:

  • 读

  • 写

  • 计算

图灵机的定义如下。 它有一条被划分为方格的纸带,有一个固定的左端, 并向右无限延伸。 每个方格能存储一个字符。 机器有一个 I/O 头,在任一时刻它"停在" 其中一个方格上。 机器的控制单元由一组抽象 状态 定义。 在任何给定时刻,机器被认为 "处于"某个状态,并且在该状态下有一组可以执行的动作。 从当前状态出发,机器读取 当前方格上的符号,然后可以执行下面之一:

  • 改变当前符号。

  • 把 I/O 头向左或向右移动一个方格。

按照惯例,如果头移出 纸带的左端,或者控制单元把机器送入一个 特别指定的 停机状态,机器就停止运行。

机器的输入是纸带的初始内容,通过从左到右 列出从最左到最右非空带上的所有方格来描述。 自然,纸带上非空符号的个数必须有限。 机器的 字母表 由一些字母组成, 包括特殊符号 \(\#\),它表示给定方格上的空 符号。

图灵机形式化地定义为一个四元组 (\(K\), \(\Sigma\), $delta$, $s$),其中

  • \(K\) 是有限状态集(不包括 \(h\),即 停机状态)。

  • \(\Sigma\) 是一个字母表(包含 \(\#\),不包含 \(L\) 或 \(R\))。

  • \(s \in K\) 是 初始状态。

  • \(\delta\) 是从 \(K \times \Sigma\) 到 \((K \cup \{h\}) \times (\Sigma \cup \{L, R\})\) 的函数。

注意,把 \(\#\) 包含进这个语言只是为了 方便。 我们希望在阅读我们规格说明时不会混淆。

如果 \(q \in K\)、\(a \in \Sigma\) 并且 \(\delta(q, a) = (p, b)\), 那么在状态 \(q\) 下扫描 \(a\) 时, 进入状态 \(p\) 并

  1. 如果 \(b \in \Sigma\),则把 \(a\) 替换为 \(b\)。

  2. 否则(\(b\) 是 \(L\) 或 \(R\)):移动头。

22.1.2. 解释图灵机

图灵机的一个 格局 看起来像这样:

\[(q, aaba\#\underline{\#}a)\]

当 \(q\) 是 \(h\) (停机状态)时, 就会发生 停机格局。

当 I/O 头从纸上最左边的方格向左 移动时,就会发生 挂起格局。

计算 是某一长度 \(n \geq 0\) 的格局序列。 第一个机器例子从起始格局开始的执行如下所示:

\[\begin{split}\begin{eqnarray*} (q_0, \underline{a}aaa) &\vdash_M&(q_1, \underline{\#}aaa)\\ &\vdash_M&(q_0, \#\underline{a}aa)\\ &\vdash_M&(q_1, \#\underline{\#}aa)\\ &\vdash_M&(q_0, \#\#\underline{a}a)\\ &\vdash_M&(q_1, \#\#\underline{\#}a)\\ &\vdash_M&(q_0, \#\#\#\underline{a})\\ &\vdash_M&(q_1, \#\#\#\underline{\#})\\ &\vdash_M&(q_0, \#\#\#\#\underline{\#})\\ &\vdash_M&(h, \#\#\#\#\underline{\#})\\ \end{eqnarray*}\end{split}\]

我们说 \(M\) 在输入 :math:`w` 上停机,当且仅当 \((s, \#w\underline{\#})\) 推出某个停机格局。

如果 \((s, \#w\underline{\#})\) 推出某个挂起格局, 则称 \(M\) 在输入 :math:`w` 上挂起。 这意味着 要么 从左端向左移动 要么 进入无限循环。

图灵机计算从字符串到字符串的函数。 形式化地:设 \(f\) 是从 \(\Sigma^*_0\) 到 \(\Sigma^*_1\) 的函数。 当且仅当对任何 \(w \in \Sigma^*_0\),如果 \(f(w) = u\), 那么图灵机 \(M\) 计算 \(f\):

\[(s, \#w\underline{\#}) \vdash^*_M (h, \#u\underline{\#}).\]

这样的函数 \(f\) 被称为 图灵可计算函数。

下面是我们表达多个参数的方式: 对于 \(f(w_1, ..., w_k) = u\),

\[(s, \#w_1\#w_2\#...\#w_k\underline{\#}) \vdash^*_M (h, \#u\underline{\#}).\]

表达自然数上函数的一种方式是用 一元记法 表示一个数。 (记住,我们不关心是否高效,我们关心 是否可能。) 在这种情况下,我们把值 0 表示为空字符串。 我们说如果 \(M\) 计算 \(f': \{I\}^* \rightarrow \{I\}^*\), 其中对每个 \(n \in \mathbb{N}\) 有 \(f'(I^n) = I^{f(n)}\),则 \(M\) 计算 \(f: \mathbb{N} \rightarrow \mathbb{N}\)。

22.1.3. 图灵可判定与图灵可接受语言

图灵可判定 的语言 \(L \subset \Sigma_0^*\) 当且仅当函数 \(\chi_L: \Sigma^*_0 \rightarrow \{\fbox{Y}, \fbox{N}\}\) 是图灵可计算的,其中对每个 \(w \in \Sigma^*_0\),

\[\begin{split}\chi_L(w) = \left\{ \begin{array}{ll} \fbox{Y} & \mbox{if $w \in L$}\\ \fbox{N} & \mbox{otherwise} \end{array} \right.\end{split}\]

例子:设 \(\Sigma_0 = \{a\}\),设 \(L = \{w \in \Sigma^*_0: |w|\ \mbox{is even}\}\)。

\(M\) 从右到左擦除标记,当前奇偶性 用状态编码。 一旦到达左侧的空白,就标记 \(\fbox{Y}\) 或 \(\fbox{N}\),视情况而定。

对计算的看法有很多。 一种是把函数看作输入到输出的映射 (例如 \(N \rightarrow N\),或 字符串到字符串)。 另一种是判断一个字符串是否属于某种语言。

如果 \(M\) 在输入 \(w\) 上停机,则 \(M\) 接受 字符串 \(w\)。

  • \(M\) 接受一个语言当且仅当 :math:M ` 在 :math:` w ` 上停机,当且仅当 :math:` w in L ` 。

  • 如果存在某台图灵机接受某个语言,则该语言是 \(Turing-acceptable\) 。

例子:\(\Sigma_0 = \{a, b\}\), \(L = \{w \in \Sigma^*_0: w\ \mbox{contains at least one}\ a\}\)。

\[\begin{split}\begin{array}{lll} \hline q&\sigma&\delta(q, \sigma)\\ \hline q_0&a&(h, a)\\ q_0&b&(q_0, L)\\ q_0&\#&(q_0, L)\\ \hline \end{array}\end{split}\]

这种语言图灵可判定吗? 当然。不必只是向左运行,而是调用另一个表示 "见过一个 \(a\)"的状态,如果在该状态下到达 \(\#\) 就打印 \(\fbox{Y}\),否则打印 \(\fbox{N}\)。

每个图灵可判定的语言都是图灵可接受的, 因为如果机器本可以打印 \(\fbox{Y}\),那么 这台机器可以改为停机, 或者如果机器本可以打印 \(\fbox{N}\), 那么它可以向左挂起。

每个图灵可接受的语言都图灵可判定吗? 这就是停机问题。

当然,如果图灵可接受的语言会停机, 我们就写 \(\fbox{Y}\)。 但如果图灵可接受的语言会挂起, 我们是否 总是 能用改为写 \(\fbox{N}\) 的逻辑 替换它? 例子:考拉兹函数。

22.1.4. 构造更复杂的机器

引理:如果

\[(q_1, w_1\underline{a_1}u_1) \vdash_M^* (q_2, ww_2\underline{a_2}u_2)\]

对某个字符串 \(w\) 成立,并且

\[(q_2, w_2\underline{a_2}u_2) \vdash^*_M (q_3, w_3\underline{a_3}u_3),\]

那么

\[(q_1, w_1\underline{a_1}u_1) \vdash^*_M (q_3, ww_3\underline{a_3}u_3).\]

洞察:因为 \((q_2, w_2\underline{a_2}u_2) \vdash^*_M (q_3, w_3\underline{a_3}u_3)\), 这个计算必定在不把磁头移到 \(w_2\) 左方的情况下进行。 机器无法"感知"纸带的左端。 (如果它移到了左边,它就会挂起。) 因此,即使磁头不在纸带的左端,它也不会移到 \(w_2\) 的 左方。

这意味着图灵机的计算可以组合成 更大的机器:

  • \(M_2\) 准备字符串作为 \(M_1\) 的输入。

  • \(M_2\) 在输入末尾把控制交给 \(M_1\) 的 I/O 头。

  • 当 \(M_1\) 完成时,\(M_2\) 收回控制。

下面是一些基本的机器和记法:

  • \(|\Sigma|\) 台写符号机(每个符号一台): 任意给定的字母 \(\sigma\) 都有一台名为 \(\sigma\) 的写符号机。

  • 移动磁头的机器,命名为 \(R\) 和 \(L\),适当地移动 磁头。

  • 起始状态用 \(>\) 表示。

  • 在(例如):math:# 之外的东西上的转移被标记 为 \(\overline{\#}\)。

  • 机器的多份副本用上标表示:\(R^2\) 指 向右移动两次。





22.1.5. 图灵机的扩展

当我们给计算系统添加扩展或新功能时, 有时它们改变了系统能力的一些根本性东西。 例如,当我们向算法添加非确定性时,我们 可能 把底层问题的代价从指数时间变为 多项式时间。 但是,其他改变不会带来根本性的不同。 就图灵机而言,我们关心的是机器能做什么, 而不是做这件事要花多长时间。 非确定性会帮助我们解决停机问题吗? 不会。 同样,下面的扩展也不会增加图灵机的 能力。

  • 提供双向无限纸带

    这不会给图灵机带来新的能力。 为了弄清这一点,我们可以用标准的单向无限纸带 来模拟双向无限纸带的行为。 只需把无限纸带在中间折一下,把纸带的两个方向 都存进单个单元格。 这需要一个大大扩充的字母表,因为我们现在需要能够 表示两个字符的任何组合。 这将需要更多的状态,可能也需要更多的时间。 但在能力方面它不允许任何新的东西。

  • 多条纸带(每条都有自己的头)

    同样,我们可以通过把多个符号编码进单个 表格单元格来模拟它。 例如,要模拟两条纸带(每条都有一个头),我们在每个 单元格中编码相应的两个符号,以及两个二进制标记 来指示纸带头当前是否位于两条纸带中对应 的单元格。

  • 单条纸带上的多个头

    这比编码多条纸带更容易。 我们只需把磁头编码到纸带上,并模拟它们来回 移动。

  • 二维 tape

    我们只需要找到一个从 2D 到 1D 的映射,这 相当容易。 一种方法是以对角线的顺序工作,顺序为 (0, 0)、(0, 1)、 (1, 0)、(0, 2)、(1, 1)、(2, 0),依此类推。

  • 非确定性

    我们可以按顺序模拟非确定性行为,先做所有 长度 1 的计算,然后长度 2 的,依此类推,直到我们 到达其中一个非确定性选择的停机状态。 所以我们看到,虽然非确定性可以节省大量时间,但它 不会改变(最终)能完成什么。

   «  21. 不可解问题   ::   目录   ::   1. 术语表  »

关闭窗口