首页 > 其他分享 >[计算理论] 1. 图灵机、递归函数与丘奇-图灵论题 Turing Machine, Recursive Function & Church-Turing thesis

[计算理论] 1. 图灵机、递归函数与丘奇-图灵论题 Turing Machine, Recursive Function & Church-Turing thesis

时间:2024-03-13 16:44:25浏览次数:16  
标签:Function 函数 递归函数 Turing 纸带 丘奇 图灵机 text ldots

图灵机

在研究一种自动机时,我们有两种视角

  • 语法学 (Syntax),描述一个自动机是什么,如分析自动机的组成、结构。

  • 语义学 (Semantics),描述一个自动机做什么,如分析自动机的语言。

换句话说,前者是自动机的视角,后者是形式语言的视角。

图灵机的语法

图灵机的原始描述如下:

  • 一台含有一条1无限长的纸带的有限状态自动机 (FSM, Finite State Machine)。

  • 纸带从最左端2开始向右无限延伸。纸带被分割为单元,每个单元上有一个字符或空字符 \(\perp\)。纸带拥有一个读写头,指向纸带的某个单元,自动机每次转移时可向左或右移动读写头一个3单元,已经处于最左侧时向左移动将什么都不会发生4

  • 最开始,输入串 \(w\) 写在纸带的前 \(|w|\) 个单元里5,其他单元均为空字符。自动机在一个特殊的开始状态,正如 DFA 那样。读写头在最左侧6

  • 自动机每次读取读写头所在单元的符号,根据当前所在的自动机状态和这个符号,在同位置7覆盖写某个符号,转移到另一个自动机状态,并将读写头向左或向右移动。

  • 有两种特殊的自动机状态 \(\textbf{accept}\) 和 \(\textbf{reject}\),每种各一个8,一旦走到,图灵机停机 (halt)。

上标表示这些地方的描述可以有等价的变种,因此看起来描述得十分随意。

形式化的定义如下。

图灵机的定义(语法部分)

一个图灵机是一个七元组 \((Q, \Sigma, \Gamma, \delta, q_{\textbf{start}}, q_{\textbf{accept}}, q_{\textbf{reject}})\),其中

  • \(Q\) 是自动机的状态。
  • \(\Sigma\) 是输入字符集。
  • \(\Gamma\) 是纸带字符集。\(\Sigma \cup \{\perp\} \in \gamma\)。
  • \(\delta:Q \times \Gamma \to Q \times \Gamma \times \{\text L, \text R\}\) 是转移函数,表示由当前状态和读到的符号转移到另一个状态,在纸带上写一个符号并向一边移动。
  • \(q_{\textbf{start}}, q_{\textbf{accept}}, q_{\textbf{reject}} \in Q\),\(q_{\textbf{accept}} \neq q_{\textbf{reject}}\)。

需要注意的是,根据定义,图灵机是可数无穷多的。我们可以将其与 \(\mathbb N\) 一一对应,记作 \(M \mapsto \langle M \rangle\),在许多时候,通常具体如何映射是不重要的。

图灵机的语义

定义 图灵机一个配置 (configuration) 包含了自动机状态、纸带内容、读写头位置,写作

\[[\text{elements before r/w head}]q[\text{elements on and after r/w head}] \]

e.g.

\[11{\color{blue}q_{\textbf{start}}1}100111 \]

图灵机的定义(语义部分)

  • 如果 \(\delta(q_i, b) = (q_j, c, \text L)\) 那么称 \(\bm u\ a\ q_i\ b\ \bm v\) 生成 \(\bm u\ q_j\ a\ c\ \bm v\)。
  • 如果 \(\delta(q_i, b) = (q_j, c, \text R)\) 那么称 \(\bm u\ a\ q_i\ b\ \bm v\) 生成 \(\bm u\ a\ c\ q_j\ \bm v\)。

其中 \(\bm u, \bm v\) 是两个字符串,表示左边和右边那些没有被改动的字符。

称所有 \(q \in \{q_{\textbf{accept}}, q_{\textbf{reject}}\}\) 的配置为停机配置。

对于输入字符集 \(\Sigma\) 上的图灵机 \(M\),其语言定义为

\[L(M) = \{w \in \Sigma^* \mid \text{starting with } w \text{ on the first } |w| \text{cells of the tape}, M \text{ will eventually enter the accept state}\} \]

其中 \(\text{enter}\) 的过程可以描述为:存在配置 \(C_1, C_2, \ldots, C_k\),使得

  • \(C_1 = q_{\textbf{start}}w\)。
  • \(C_i\) 生成 \(C_{i+1}\)。
  • \(C_k\) 是一个在 \(q_{\textbf{accept}}\) 上的停机配置。

对于一个字符串 \(w\),如果 \(w \in L(M)\),则图灵机一定会在 \(q_{\textbf{accept}}\) 上停机。但 \(w \notin L(M)\) 时,图灵机要么在 \(q_{\textbf{reject}}\) 上停机,要么不停机(永远循环下去)。

也就是说,除非能够证明其一定停机,我们无法通过将 \(w\) 送入图灵机,等待其输出结果来得知其是否属于 \(L(M)\)。这与 DFA 或者 DPDA 的行为不一致。

对于那些总是会停机的图灵机 \(M\),我们称 \(M \textbf{ decides } L(M)\),这样的语言是可判定的 (decidable),称为递归 (recursive) 语言。

否则称 \(M \textbf{ recognizes } L(M)\),这样的语言是可识别 (recognizable) 的,称为递归可枚举 (recursively enumerable) 语言。

递归是说其与一般递归函数的能力等价,后文会证明这一点。递归可枚举是说我们可以通过某种方式枚举语言中所有的字符串,后文也会提到这一点。

如果 \(\overline L\) 是 recognizable 的,则称 \(L\) 是 co-recongnizable 的,也就是,对 \(L\) 来说,\(\textbf{reject}\) 总是能停机,而 \(\textbf{accept}\) 和不停机无法区分。

\(L\) 是 decidable 的当且仅当 \(L\) 是 recognizable 且 co-recognizable 的。

需要注意的是,与 DPDA 与 PDA 的区别不同的是,这里我们只能在语义层面来描述两种语言的区别,而不能够以自动机视角来描述。如果我们能用操作性的语言直接地描述这两种语言的区别(比如,\(\{0^n1^n \mid n \in \mathbb N\}, \{0^{n^2} \mid n \in \mathbb N\}\)),那就违背了停机问题的不可判定性,从而违背了可计算性理论的基本论题,即丘奇-图灵论题。我们之后会回到对这个重要的论题的讨论。

图灵机的变种

图灵机有许多等价变种。这些变种都是在原先图灵机的原始定义上增加一些操作的便捷性。但这些便捷性并不会增强图灵机的能力。图灵机也不可能通过语法学上的努力增强能力。

由于我们考虑的是可计算性,而不是计算复杂性,使用原始图灵机对这些图灵机变种的模拟并不需要高效,有些时候我们甚至不知道是否存在一种高效的模拟(e.g. \(\mathrm P \text{ v.s. } \mathrm{NP}\))。

多带图灵机

多带图灵机拥有 \(k\) 条纸带。转移函数的定义变为

\[\delta:Q \times \Gamma^k \to Q \times \Gamma^k \times \{\text L, \text R, \text S\}^k \]

其中 \(\text S\) 是为方便引入的记号,表示不移动读写头,这可以通过修改 FSM 的状态做到。

使用原始图灵机可以按照如下方式模拟多带图灵机:

  • 从左向右顺序地写下每一条纸带上的内容,用一个特殊字符 # 分隔。
  • 当多带图灵机的某条纸带向右扩展其长度时(即覆盖某个 \(\perp\) 时),原图灵机的读写头指向了一个 #,此时命令其走到 FSM 的一个特殊子模组上,将右侧的所有内容向右移一位。
  • 为了记录每条纸带的位置信息,将纸带字符集 \(\Gamma\) 扩充为 \((\Gamma, \{0, 1\})\),第二维的 \(1\) 表示读写头正在这个位置上。每两个 # 之间有且仅有一个状态的第二维是 \(1\)。
  • 模拟时,从左向右读那些第二维状态为 \(1\) 的位置,将他们写到一个特殊的纸带位置上,比如最左侧,对当前读到第几个纸带可以使用 FSM 的状态记忆。读取到全部内容之后,做出决策并修改纸带。

非确定性图灵机 (NTM, Nondeterministic TM)

同 NFA 之于 DFA 一样,NTM 将其转移的输出改为了原来的幂集。

\[\delta:Q \times \Gamma \to 2^{Q \times \Gamma \times \{\text L, \text R\}} \]

NTM 接受一个串的过程与 TM 一致,只需要修改生成过程为

  • 如果 \((q_j, c, \text L) \in \delta(q_i, b)\) 那么 \(\bm u\ a\ q_i\ b\ \bm v\) 生成 \(\bm u\ q_j\ a\ c\ \bm v\)。
  • 如果 \((q_j, c, \text R) \in \delta(q_i, b)\) 那么 \(\bm u\ a\ q_i\ b\ \bm v\) 生成 \(\bm u\ a\ c\ q_j\ \bm v\)。

也即,NTM \(M\) 接受 \(w\) 当且仅当以 \(w\) 作为纸带的输入,存在一条在 \(q_{\textbf{accept}}\) 上停机的合法路径。

此时,\(M\text{ decide } L(M)\) 当且仅当其所有分支都会停机。也即,对那些 \(w \notin L(M)\),\(M\) 以 \(w\) 为输入时,所有分支都到达了 \(\textbf{reject}\)。

Nondeterminism 与 Verification 是一组相抵的概念。对于语言 \(A\),如果有 NTM \(M \text{ decide } A\),则存在一个 deterministic TM \(V\) 使得 \(V(w) = [w \in A]\);如果有 DTM \(V\) 使得 \(V(w) = [w \in A]\),则存在 NTM \(M \text{ decide } A\)。两者的相互转化是多项式级别的,因此 \(\text{NP}\) 问题有两种等价的定义

  • 复杂度类 \(\text{NP}\) 包含了那些能够在多项式时间内由一个 NTM 解决的判定问题。
  • 复杂度类 \(\text{NP}\) 包含了那些能够在多项式时间内有一个 DTM 验证的判定问题。

当我们有 \(M\) 时,若对任意 \(w\),以 \(w\) 为输入时 \(M\) 进行的决策数有上限 \(T\),则 \(V\) 可以为读入一个长度为 \(T\) 的字符串,按照其内容在 NTM 上做决策,看最终是否走到了 \(q_{\textbf{accept}}\) 的 DTM。当我们有 \(V\) 时,可以在 \(q_{\textbf{start}}\) 前先使用与输入长度相同的状态个数来枚举所有输入的可能得到一个 NTM。

我们可以使用 \(3\) 条纸带的图灵机模拟一个 NTM。

我们尝试枚举每一种输入。由于我们要支持仅是 recognizable 的语言,DFS 是不可取的,因为有可能会一些有停机的实例包含不停机的分支。

我们将纸带 \(1\) 作为只读的,用于保留原始输入,纸带 \(2\) 用于模拟 DTM,纸带 \(3\) 记录所有做过的决策。我们按照字典序枚举决策,将其写入纸带 \(3\)。注意字典序是优先按照长度从小往大排序的。确定了决策之后,将输入从纸带 \(1\) 拷贝到纸带 \(2\) 上,用纸带 \(2\) 模拟。如果每个决策都合法,且最终恰好走到了 \(q_{\textbf{accept}}\),返回 \(\textbf{accept}\)。按字典序枚举决策可以通过由当前决策的编码推导出下一个决策的编码来实现。

需要注意的是,在一个 NTM 中,即使有一部分转移不存在 nondeterministic 的情况,这些状态和转移也可能可以造成无限循环,因此枚举决策需要在所有的步骤都进行,即使某些步骤是 deterministic 的。

另一个需要注意的点是,这种模拟的模式所有的负例都是不停机的。如果 NTM \(M \text{ decide } L(M)\),我们称 \(M\) 是一个 decider。如果想要模拟一个 decider,使得那些负例也总是停机,那我们需要不再枚举那些某个前缀已经走到了 \(q_{\textbf{accept}}\) 或 \(q_{\textbf{reject}}\) 的决策。决策的枚举过程会在我们发现对某个 \(L\),长度不小于 \(L\) 的所有的决策都被停机状态覆盖了时停止。

枚举器 (Enumerator)

一个枚举器是一个具有只写的纸带,即“打印机”的图灵机。

为什么被图灵机识别的语言被称为递归可枚举语言?这是因为一个语言是递归可枚举语言当且仅当我们可以用一个枚举器枚举出其所有字符串并依次打印在只写纸带上(或许有重复)。

考虑这样的过程

  • 将合法的输入与自然数一一对应。
  • 对 \(i=1, 2, 3, \ldots\)
    • 对 \(j = 1, \ldots, i\)
      • 将 \(j\) 作为 \(M\) 的输入,运行 \(i\) 步。
      • 如果 \(\textbf{accept}\),输出 \(j\)。

不难看出,每一个 \(\textbf{accept}\) 的字符串都会被输出至少一次。

通用图灵机

通用图灵机是这样一个图灵机,输入 \(\langle M, w \rangle\),其中 \(M\) 是一个图灵机(需要先进行编码),运行结果与 \(w\) 在 \(M\) 上运行的结果一致。

我们可以用 \(3\) 条纸带的图灵机来模拟通用图灵机,纸带 \(1\) 只读,提供 \(M\) 的信息,纸带 \(2\) 模拟 \(M\) 的纸带,纸带 \(3\) 记录当前在 FSM 的哪个状态。

递归函数

递归函数是可计算性的另一种刻画方式。这种刻画方式并不显式地给出计算模型(自动机、纸带),而是从一个基础出发,规定所有可行的计算过程,将所有可达的部分视作可计算的。这个动机源自于数理逻辑中的形式主义 (formalism),即所有的数学都可以归结为操纵公式的规则,而那些数学命题是形而下的,只需要被当作字符串接受操作,而不需要理解其含义。我们通过对命题操作规则得到其他命题,称之为定理。

原始递归函数

原始递归函数是一类函数,这类函数是由最基本的函数和一些允许的推导法则得到的。这些法则将会替代图灵机中的“计算功能”。因为对一个函数在一个点的取值,我们可以通过反向调用这些推导过程,回到最基本的函数,并回溯得到函数值。而“递归”一词来源于其中一条推导法则“原始递归”,允许让 \(f(x + 1)\) 的取值取决于 \(f(0), f(1), \ldots, f(x)\) 与之前已经定义的函数。

原始定义如下

原始递归函数 (primitive recursive function) 是通过对以下基本函数进行有限次推导法则得到的函数族。

基本函数:

  • 零函数:\(f(n) = 0\)。
  • 后继函数:\(f(n) = n + 1\)。
  • 映射函数:\(p^k_i(n_1, n_2, \ldots, n_k) = n_i\)。

推导法则:

  • 复合:若 \(g(n_1, \ldots, n_j), h_i(n_1, \ldots, n_k)\) 是原始递归函数,则

    \[f(n_1, \ldots, n_k) = g(h_1(n_1, \ldots, n_k), \ldots, h_j(n_1, \ldots, n_k)) \]

    也是。

  • 原始递归:若 \(g(n_2, \ldots, n_k), h(n_1, \ldots, n_k, n_{k+1})\) 是原始递归函数,则

    \[\begin{cases}f(0, n_2, \ldots, n_k) = g(n_2, \ldots, n_k) \\ f(n_1 + 1, n_2, \ldots, n_k) = h(n_1, n_2, \ldots, n_k, f(n_1, \ldots, n_k)) \end{cases} \]

    也是。

\(m + n\) 是原始递归函数,一个推导过程如下。

\[\begin{aligned} & f_1(n) = n + 1 & \text{(successor function)} \\ & f_2(n) = n & \text{(projection function)} \\ & f_3(m, n, p) = p & \text{(projection function)}\\ & f_4(m, n, p) = f_1(f_3(m, n, p)) = p + 1 & \text{(composition rule)} \\ & \begin{cases} f_5(0, n) = f_2(n) \\ f_5(m + 1, n) = f_4(m, n, f_5(m, n)) \\ \end{cases} & \text{(recursion rule)}\\ \end{aligned}\]

则 \(f_5(m, n) = m + n\)。同理 \(m \cdot n\) 也是,推导过程几乎相同

\[\begin{aligned} & f_6(n) = 0 & \text{(zero function)} \\ & f_7(m, n, p) = m \\ & f_8(m, n, p) = f_5(f_3(m, n, p), f_7(m, n, p)) = p + m\\ & \begin{cases} f_9(0, n) = f_6(n) \\ f_9(m + 1, n) = f_8(m, n, f_9(m, n)) \\ \end{cases} & \text{(recursion rule)}\\ \end{aligned}\]

则 \(f_9(m, n) = m \cdot n\)。

这样的过程不断堆叠,\(m^n, \underbrace{m^{m^{\cdots^m}}}_{n}\) 等等函数也可以被做出来。但是这样的累加只能做常数轮。如果要做 \(m\) 轮,则这个函数不属于原始递归函数。

这个函数叫做阿克曼函数,定义如下

\[A(m, n) = \begin{cases}n + 1 & m = 0 \\ A(m - 1, 1) & m > 0, n = 0 \\ A(m - 1, A(m, n - 1)) & \text{else}\end{cases} \]

其之所以不是原始递归的,是因为原始递归要求一次性给出 \(f\) 的定义,因此 \(h\) 需要是与 \(f\) 无关的已经被定义好的函数。而阿克曼函数并不满足这一点。

以下几个函数对后续的证明起到了重要的作用。

命题

  • \(x\operatorname{∸} y = \begin{cases} x - y & x \geq y \\ 0 & x < y \end{cases}\) 是原始递归的。

  • 一元关系 \(R = \{x \mid x \text{ is prime}\}\) 是原始递归的。

  • 令 \((x)_i\) 表示 \(x\) 的第 \(i\) 个素数的阶数,即

    \[(x)_i = \text{the exponent }x_i \text{ of } p_i \text{ in factorization } x = p_0^{x_0} p_1^{x_1} \ldots p_{n}^{x_n} \]

    则 \(f(x, i) = (x)_i\) 是原始递归的。

证明

为证明 \(x\operatorname{∸} y\) 是原始递归的,我们先证明 \(\operatorname{pred}(m) = m - 1\) 是原始递归的。令

\[f(n_1 + 1) = h(n_1, f(n_1)) = n_1 \]

即可。再用 \(y\operatorname{∸} S(x) = \operatorname{pred}(y\operatorname{∸} x)\) 即可。

用同样的想法,我们可以说明 \(\operatorname{If}(x, y, z) = \begin{cases} z & x = 0 \\ y & x \neq 0 \end{cases}\) 是原始递归的。

为说明 \(\{x \mid x \text{ is prime}\}\) 是原始递归的,我们只需要证明 \([a \mid b] = \begin{cases} 1 & b = ka, k \in \mathbb N \\ 0 & \text{else}\end{cases}\) 是,而这可以用减法和 \(\operatorname{IsZero}(x) = \operatorname{If}(x, 1, 0)\) 做到。

为说明 \((x)_i\) 是原始递归的,我们只需要证明 \(p(i) = i+1\text{-th prime}\) 是原始递归的,而我们知道 \(p(i) \leq i! + 1\),因此可以直接枚举这些数,并调用 \([a\mid b]\)。

因此,对每一个有限的序列 \(\{a_0, \ldots, a_n\}\),都存在一对原始递归函数 $f(\underbrace{\cdot, \cdot, \ldots, \cdot}_{n}) $ 和 \(\{f_0(\cdot), f_1(\cdot), \ldots f_n(\cdot)\}\) 使其可以与

\[a = p_0^{a_0 + 1} p_1^{a_1 + 1} \ldots p_n^{a_n + 1} \]

相互转换,也即,两者之间存在原始递归的双射。

原始递归函数 [1931, Gödel] 是早于图灵机 [1937] 的。此时 Gödel 也有想要定义所有的“可计算的”函数的想法。但原始递归函数并不包含所有“可计算的”函数。

我们通过对角化证明的方式来找出一个可计算但不是原始递归函数的例子。

对角化证明

对角化证明用于说明可数无穷多个 \(\mathbb N\) 上的函数构成的的特性,通过将这个集合列成一张 \(\mathbb N \times \mathbb N\) 的二维表格,并取对角线上的元素,构造一个新的函数,并通过判断其是否在这个集合中得到结论。

一个经典的例子是

命题

实数(无限小数)是不可数的。

证明

若可数,我们可以将所有实数列在一张二维表格里,每一行表示一个数,每一列表示一个数位,每一个格子中有一个数字 \(0 \sim 9\),现在考虑构造一个新的数 \(\beta\),\(\beta\) 的第 \(i\) 位是第 \(i\) 行第 \(i\) 列的数字向后移位一次的结果(即 \(+1\) 模 \(10\)),则 \(\beta\) 是一个无限小数,但是若他是表的第 \(k\) 个数,则第 \(k\) 行第 \(k\) 列的元素等于其自身的移位,矛盾。

这说明,\(\beta\) 不在表里。这样一张表格是不存在的。

通过类似的想法,我们可以说明原始递归函数的一个问题:其是一个在所有取值上都定义的函数。这样的函数称作 (total) 的。在一些取值上可能没有定义的函数称为部分 (partial) 的。

很明显,原始递归函数是可数无穷多的,因此我们将其列出,第 \(n\) 个函数为 \(\psi_n\)。现在考虑 \(\varphi(n) = \psi_n(n) + 1\),则任何 \(\varphi(n)\) 都是可计算的,因为可以直接调用 \(\psi_n(n)\),但 \(\forall n, \varphi \neq \psi_n\),因此 \(\varphi\) 不可能在这张表里,因此不是原始递归函数。

如果我们放松限制,考虑不一定是全的的函数,则令 \(\varphi(n) = \begin{cases}\psi_n(n) + 1 & \psi_n(n) \text{ is defined} \\ \text{undefined} & \psi_n(n) \text{ is undefined}\end{cases}\) 时,我们无法导出 \(\forall n, \varphi \neq \psi_n\)。这说明所有可计算的函数有可能可以是可数无穷多的。

此时,或许一些人会说,我们考虑了一个更大的集合,却得出了可数无穷多,那我们只列举出那些全的并且可计算的函数,岂不是还是可以使用对角化证明导出矛盾?这就涉及到停机问题的不可计算性了。简单来说,在下一节对可计算函数的定义(\(\mu\)-递归函数)下,判断一个一般的可计算函数是否是全函数这个任务是不可计算的,因此我们构造出的反例不是可计算的函数。

一般递归函数

原始递归函数有一个等价的描述:其推导过程中,每次递归在其进入之前便可确定递归层数,也即上文提到的,\(f\) 需要一次性被给出,\(f(x + 1)\) 依赖于 \(f(0), f(1), \ldots, f(x)\) 与之前已经被定义好的函数。有一些地方会将其形容为所有的循环都是 \(\texttt{for}\) 循环。

但问题在于,递归的形态是不一定可以在计算之前就确定的,而是在计算过程之中才被不断确定。阿克曼函数就是一个例子,其递归层数来自于自己在更小的 case 中的计算结果。更一般地,这个动机可被形式化为

  • 无界搜索:若 \(\theta(x_1, x_2, \ldots, x_n, y)\) 是递归函数,则

    \[f(x_1, x_2, \ldots, x_n) = \operatorname{argmin}_{y \in \mathbb N}[(\theta(x_1, x_2, \ldots, x_n, y) \text{ is defined and} = 0) \wedge ((\forall z \leq y)[\theta(x_1, x_2, \ldots, x_n, z) \text{ is defined}])] \]

    也是。

在古老的记号中,\(\operatorname{argmin}_{y \in \mathbb N}\) 写作 \(\mu y\),因此包含原始递归的所有基本函数和法则与无界搜索法则的函数叫做 \(\mu\)-递归函数,也可以叫做一般递归函数 (general recursive function)。

这样,一个递归过程可以以一个可计算函数作为停止条件。并且这个操作的可计算性是符合直观的,如同一个 \(\texttt{while}\) 循环。

如果不存在这样的 \(y\),那么 \(f(x_1, x_2, \ldots, x_n)\) 无定义。因此存在不是全函数的 \(\mu\)-递归函数。

一般递归函数与图灵可计算函数的等价性

我们可以将图灵机停机时纸带最终的结果作为图灵机的输出。这样一个图灵机可以被视作一个函数的定义。这样的函数叫做图灵可计算函数。

定理 一般递归函数与图灵可计算函数等价。

一般来说,我们更信任图灵机的计算能力是完全的,因此这里只说明一般递归函数是如何模拟图灵机的。

此时,图灵机的编码需要被显式地给出,并使用原始递归函数解析。

对一个图灵机,其一条转移的五元组 \((q_i, s_j, q_k, s_l, r_m)\) (下标从 \(0\) 开始)可被编码为

\[p_0^{1 + i} p_1^{1 + j} p_2^{1 + k}p_3^{1 + l}p_4^{1 + m} \]

。而一个图灵机对应一个有限的五元组的序列,因此可被编码为

\[e = p_0^{\#(i_0, j_0, k_0, l_0, m_0)} p_1^{\#(i_1, j_1, k_1, l_1, m_1)}\ldots p_n^{\#(i_n, j_n, k_n, l_n, m_n)} \]

令 \(\varphi_e^{(n)}\) 为接收 \(n\) 个输入变量的标号为 \(e\) 的图灵机计算的部分函数,\(\varphi_e\) 表示 \(\varphi_e^{(1)}\)。

一条纸带 \(s_{0, 1, \ldots, n}\) 可被编码为

\[\prod_{j = 1}^n p_j^{1 + \#(s_j)} \]

一个配置 \((q_i, p, s_{1, 2, \ldots, n})\) 可被编码为

\[2^{1 + i} 3^{1 + \#(p)} 5^{1 + \#(s_{1, 2, \ldots, n})} \]

一个图灵机的一个历史记录 \((c_0, c_1, \ldots, c_n)\) 可以被编码为

\[2^e \prod_{i=0}^n p_{i+1}^{\#(c_i)} \]

定理 (Kleene's normal form theorem) 存在原始递归的判断式 (Kleene T-predicate) \(T(e, x, y)\) 和函数 \(U(y)\),使得

\[\varphi_e(x) = U(\mu y\ T(e, x, y)) \]

证明

我们令 \(T(e, x, y)\) 表示 \(y\) 是否是图灵机 \(e\) 在输入 \(x\) 上的合法的历史记录,则 \(U\) 只需要提取 \(y\) 的最后一步的纸带内容。

我们可以把 \(y\) 还原为历史记录 \(c_0, c_1, \ldots, c_n\),因此我们只需要一个判断式 \(S(c_0, c_1, \ldots, c_n)\) 表示其是否合法,以及一个输出 \(c_n\) 的纸带函数,后者显然是原始递归的。

判断时,我们可以将 \(c_i, c_{i+1}\) 还原为状态、纸带、读写头位置。

状态是有限的,因此检查状态转移是否合法是原始递归的。

两条纸带只应在 \(c_i\) 的读写头位置有区别,我们可以用上述提到的 \(x\operatorname{∸} y\) 来实现判等。读写头位置同理,因为对一个参数加减一个常数是原始递归的。

因此,每个图灵机都可以被一个一般递归函数模拟。

丘奇-图灵论题

“论题” (thesis) 是说那些有些模糊,无法被形式化地声明或者验证的,但是对工作有益的猜想。

丘奇-图灵论题首先基于对可计算性的形式化描述的等价性。

  • (Gödel, Herbrand, 1933) 一般递归函数。
  • (Church, 1936) \(\lambda\)-演算。
  • (Turing, 1936) 图灵机。

这三份工作,都想要使用严格的数学语言刻画所有可计算的过程,而它们被严格证明是等价的。

定理 一个函数是 \(\lambda\)-可计算的当且仅当其是图灵可计算的,也当且仅当其是一般递归的。

之后,他们讨论了不依赖于数学定义的,作为直觉或概念上的可计算性,即能行可计算 (effective computability). 能行方法 (effective method) 的描述如下:“其每一步骤都是精确预定的,并且一定会在有限的步骤中产生答案”。

这个定理给予了当时的人一种信心,于是他们断言,

丘奇-图灵论题 (Church-Turing thesis) 能行可计算与图灵可计算一致。

也就是说,这是一种公认的信念,认为这三种等价的形式化描述准确地描绘 (characterize) 了可计算性的理念或者本性 (nature)。

这件事在图灵机上更容易被看出,图灵在其原论文中也做了一些解释。对于计算机还没有诞生的三十年代,当我们想要描述一个可操作的计算过程时,可以使用的工具是纸和笔。纸和笔对应着纸带,而操作者此时的“心灵”对应着有限自动机,这是因为当操作者严格遵循一个形式化的过程时,其下一步的操作总是取决于他目前的心灵状态与纸带上的内容,而心灵状态是有限的。可计算的函数无外乎可用纸和笔与大脑完成的计算,而其形式化后就是图灵机。

而对于一般递归函数,我们很难直接在直观意义上说明无界搜索可以涵盖全部可计算的函数。而在之后,人们在物理上实现的计算机也更像图灵机。因此在现在,递归函数已太不被人提起。

有了这种信念,我们可以直接用自然语言描述一系列操作,它一定是图灵可计算的,也一定是一般递归的。

标签:Function,函数,递归函数,Turing,纸带,丘奇,图灵机,text,ldots
From: https://www.cnblogs.com/shiys22/p/18070986

相关文章

  • [转]Golang Functional Options Pattern
     原文: https://golang.cafe/blog/golang-functional-options-pattern.html-------------------- GolangFunctionalOptionsPatternTheGo(Golang)FunctionaOptionsPatternisaway,apatternofstructuringyourstructsinGobydesigningaveryexpressivea......
  • 4-3nn.functional和nn.Module
    importtorchimporttorchkerasprint("torch.__version__="+torch.__version__)print("torchkeras.__version__="+torchkeras.__version__)"""torch.__version__=2.1.1+cu118torchkeras.__version__=3.9.4"""1......
  • 关于Flask中View function mapping is overwriting an existing endpoint function
    关于Flask中Viewfunctionmappingisoverwritinganexistingendpointfunction首次编辑:24/3/10/11:03最后编辑:24/3/10/11:57引子背景本来是在写个人网站,以前的代码中,几乎每个视图函数都有类似于:@app.route("/")defindex(): try: returnsend_file("index.html") e......
  • lua5.1 - function env
    注意:只在lua5.1才支持,后面的lua版本做了改动不再兼容 myEnv.lualocalmyEnv={}myEnv.a=1myEnv.b="one"myEnv.log=printreturnmyEnv Test.lualocalmyEnv=require("myEnv")setfenv(1,myEnv)--调用上面的函数后,print将没法使用因为那是在全局env......
  • What does -> mean in Python function definitions?
    Whatdoes->meaninPythonfunctiondefinitions?InPython,the"->"symbolisusedtoindicatethereturntypeofafunction.ItispartofthefunctiondefinitioninaPython3.5orlater.Forexample,thefollowingcodedefinesafunct......
  • [Rust] Using ? operator in the main function
    usestd::num::ParseIntError;fnmain()->Result<(),ParseIntError>{letmuttoken=100;letpretend_user_input="8";letcost=total_cost(pretend_user_input)?;//<--use?inmainfunctionifcost>......
  • RuntimeError: cuda runtime error (8) : invalid device function at /pytorch/aten/
    今天犯了一个很低级的错误。打开服务器使用python命令训练网络报错:Traceback(mostrecentcalllast):File"Train.py",line166,in<module>result=G(input)File"/home/cat/anaconda3/lib/python3.7/site-packages/torch/nn/modules/module.py",line493,......
  • [Rust] Specifying a function argument can be mutated
    Followingcodehascompileerror:#[test]fnmain(){letvec0=vec![22,44,66];letmutvec1=fill_vec(vec0);assert_eq!(vec1,vec![22,44,66,88]);}fnfill_vec(vec:Vec<i32>)->Vec<i32>{vec.push(88);vec}......
  • ../inst/include/Eigen/src/Core/MathFunctions.h:487:16: error: no member named 'R
    Asmentionedin conda-forge/r-base-feedstock#163(comment),IsuccessfullyinstalledsctransforminMacsiliconM1Maxbyfirstrun exportPKG_CPPFLAGS="-DHAVE_WORKING_LOG1P intheterminalandtheninstallthepackageinR.......
  • Semantic Kernel 学习笔记:体验基于 prompt function 实现的 Plugin
    在一个SemanticKernelplugin中可以创建两种类型的function,分别是nativefunction与promptfunction(之前叫semanticfunction)。下面这款plugin中给C#method添加了[KernelFunction]attribute,就是nativefunctionpublicclassLightPlugin{publicboolIsOn......