2 原始递归函数

2.6 Ackermann函数

  1. Q: Ackermann函数的递归相比之前的各种递归有什么本质区别和联系?
    A: 观察\(A(k+1,x+1)=A(k,A(k+1,x))\),相比之前一般的多变量递归表达式\(B(k+1,x+1)=g(k,x,B(k+1,x),B(k,x+1))\),外层是\(B\)而不是固定的可计算的\(g\),则不能套用多变量递归的定义。
    \(A(k,\cdot)\)可看作一元函数\(g(\cdot)\),则显然\(A(k+1,x)\)看成关于\(x\)一元函数为原始递归函数。
    \(A(k+1,x+1)=g(A(k+1,x))\).
    故可以看作Ackermann函数是“不断生成增长越来越快的函数”,每次\(k\)\(k+1\),就使用上一次“生成的函数”作递归的“外层”(即之前的\(g\)记号)
  2. Q: 接上,直观上\(A(k,\cdot):=A_k(\cdot)\)随着\(k\)变大,增长速度越来越快。
    直观上我们希望证明对于任意原始递归函数\(f(x_1,\cdots, x_n)\),存在\(k\)使得()严格大于()。
    上述结论归纳起点是三种初始函数分别别存在\(k\)为()。
    A: \(A_k(max\{x_1,\cdots,x_n\})\)\(f(x_1,\cdots,x_n)\),零函数对应0 投影对应0 后继函数对应1
  3. Q: 接上,既然有了归纳起点,就要开始归纳了。对于复合运算,因为有内外两层,故需要出现\(A_m(A_n(max\{x_i\}))\)结构(此处\(x_i\)\(x_1,\cdots, x_n\)的简化写法)。因此看出\(m\)需要(),而\(n\)处需要()。记一组满足这样条件的\(m,n\)\(m_0,n_0\). 则得到\(A_{m_0}(A_{n_0}(max\{x_i\}))>A_{m_0}(max\{g_j(x_i)\})>h(g_j)\).
    进一步分析:我们需要\(A_k(max\{x_i\})>f(x_i)\),因此只需证明\(A_k(max\{x_i\})\ge A_{m_0}(A_{n_0}(max\{x_i\}))\),则\(k\)只需(),依据是\(A_{k+2}(x)>A_{k+1}(x+1)=A_k(A_{k+1}(x))\).
    A:
    满足\(A_m(max\{x_i\})>h(x_i)\)(其中\(h\)是复合的外层)
    满足\(A_n(max\{x_i\})>max\{g_j(x_i)\}\)(其中\(g_j\)是各个内层分量)
    \(k\ge max\{m_0,n_0\}+2\)
  4. Q: 对于原始递归运算,如何做以上归纳?
    A: \(h(x_i,0)=f(x_i),h(x_i,t+1)=g(t, h(x_i,t),x_i)\)
    \(A_k > f=h(x_i,0)\)
    \(A_k > g, A_k(max\{t,h(x_i, t),x_i\})>g(t,h(x_i,t),x_i)\)
    希望找到\(m\)使得\(A_{k+m}(max\{x_i, t+1\}) > h(x_i, t+1)\),相当于要求\(A_{k+m}(max\{x_i, t+1\}) \ge ? \ge A_k(\max\{t, h(x_i, t),x_i\})> g(t, h(x_i, t),x_i)=h(x_i,t+1)\)
    \(?\)中填什么?直观的想法是\(h(x_i, t)+max\{x_i, t\} \ge max\{t, h(x_i,t), x_i\}\),即出现两项,提示我们采用2个\(A_p\).
    因此只需考虑
    \(A_{k+m}(max\{x_i, t+1\}) > A_{k+m-1}(max\{x_i,t+1\}+1) =A_{k+m-2}(A_{k+m-1}(max\{x_i,t+1\}))\)
    \((核心步骤,得到2A_p结构) > A_{k+m-4}(2A_{k+m-1}(max\{x_i,t+1\}))\)
    \(> A_{k+m-4}(h(x_i, t)+max\{x_i,t\})\ge A_{k+m-4}(max\{t,h(x_i,t),x_i\})\)
    \(>g(t,h(x_i,t),x_i)=h(x_i,t+1)\)
    注:此处相比课本上的证法更加“暴力”。毕竟\(A_k\)\(k\)每增大1,所提升的“增长速度”就非常多。
  5. Q: 栈,递归和配对有何关系?
    A: 用栈书写递归的计算过程(此处用于构造能计算Ackermann函数的\(\mathscr S\)程序)
    用配对函数表示栈,例如栈中有\(1,4,2,3\),则数\(\langle 1\langle 4\langle 2,3\rangle\rangle\rangle\)表示该栈,左边是栈顶,可以通过\(l(\cdot)\)取出。

2.7 字函数的可计算性

  1. Q: 本节中的\(n\)进制表示为什么每一位是\(1\sim n\),而不是\(0\sim {n-1}\)?为什么这样的\(n\)进制表示可以不重不漏地对应所有自然数?
    A:
    否则在整个字符串前面加任意多个0不影响结果(数和字符串不一一对应)且不能使用一进制。
    证明:空串对应0.
    长度为1字符串对应\(1\sim n\)自然数(含)。
    接下来归纳:若长度小于等于\(k\)字符串恰好一一对应\(0\sim \sum_{i=0}^{k-1} n\cdot n^i\)的自然数(注意最大指数为\(k-1\)),则长度等于\(k+1\)的字符串对应的自然数一定是\(\alpha_k n^{k} + b\),其中\(b\)对应某个长度为\(k\)的字符串,即范围\(\sum_{i=0}^{k-1}\alpha_i n^i,\alpha_i\in \{1,\cdots,n\}\),接着容易证明长度小于等于\(k+1\)的字符串恰好一一对应\(1\sim \sum_{i=0}^{k} \alpha_in^i\)的自然数。
  2. Q: 改变字母表顺序保持部分可计算、可计算、原始递归的证明思路是什么?
    A:
    首先注意:部分可计算和原始递归,合起来是部分可计算。可计算和原始递归,合起来是可计算。原始递归和原始递归,合起来是原始递归。直观上,原因是原始递归“最强”,增加一些原始递归的操作能维持部分可计算、可计算、原始递归等各种性质。
    所以,设两个不同的字母表顺序下“本质相同”的两个函数分别为\(f\)\(g\),我们只需通过\(f\)某些原始递归函数得到\(g\),根据对称性就反过来也能用\(g\)和某些原始递归函数得到\(f\).
    此处\(f\)如果是部分可计算、可计算、原始递归,则相对应得到\(g\)也是部分可计算、可计算、原始递归。(“保持”)
    更具体地,这里的“某些原始递归函数”就是依次取出某自然数的\(n\)进制表示的每一位,然后“查表”把该位映射成“新的”。这样一来形如\(\eta(f(\eta^{-1}()))\)结构可以表示\(g\).

2 原始递归函数 习题

  1. Q: Cantor编码,双变量递归和“查表”的多步递归(回忆上一篇中2.5题2.)有何联系?哥德尔编码能建立此联系吗?
    A:
    回忆:Cantor编码是每次用“斜线”排列一列数,从而建立自然数集与自然数有序对的一一映射。
    我们希望\(h(x,t_1,t_2)=H(x,\pi(t_1,t_2))\),则只需考察\(H\)是否原始递归。
    容易发现对于非边界情况,因为Cantor编码的特殊性,所谓的“查表”的索引就是简单的\(x-\sigma_1(x)-\sigma_2(x)-1\)\(x-\sigma_1(x)-\sigma_2(x)\)
    即:需要考察\(H(x,\omega_1(y))=H(x,y-\sigma_1(y)-\sigma_2(y)-1)\)以及\(H(x,\omega_2(y))=\cdots\).
    哥德尔编码与此大同小异(\(\omega_i\)不同)
  2. Q: 联立递归在表达\(0,1,0,1,2,0,1,2,3\)时为何比较方便?
    A: 多一个变量作为“内存”来“储存中间量”。(例如:“轮到第几次单调递增了”)
  3. Q: 如何理解“\(A(k,x)\)原始递归,\(A(x,k)\)不原始递归”、“\(A(x,k)\)关于\(x\)增长比\(A(k,x)\)快”?
    A: 提示:已知\(A(k,x)\)原始递归。
    并已知\(\forall a,b\exists x_0,s.t.A(x_0,a)>A(b,x_0)\)(“增长快”)
    以上两事实可以证明出\(A(x,k)\)不原始递归。