Undecidability⚓︎
约 5676 个字 1 行代码 预计阅读时间 28 分钟
核心知识
- 邱奇 - 图灵论题
- 通用图灵机
- 停机问题
- 正则表达式
- 上下文无关文法
- 归约
- 不可判定问题
- 图灵机
- 文法
- 上下文无关文法
- 递归语言的性质
- 枚举 == 图灵可枚举的 == 递归可枚举的
- 按词典序枚举 == 按词典序图灵可枚举的 == 递归的
- 莱斯定理
注意
本章笔记的证明是 Gemini 3 Pro 基于教材内容整理得到的(笔者稍微整理了一下排版
The Church-Turing Thesis⚓︎
邱奇 - 图灵论题(Church-Turing thesis):在所有输入上停止的图灵机 ==「算法」(algorithm)。
- 它既非定理,也非数学陈述,因为它只是一种断言,且无法被证明正确与否
Universal Turing Machines⚓︎
编码
来自朋辈复学课件(应该参考的是 xg 的笔记
) 。
编码(encoding) 是指用某一语言中的字符串来表示某一集合中的元素,可以通过字符串还原出原元素。比如 \(O\) 的编码用 \(“O”\) 表示。相关结论有:
- 有限集合可编码
- 有限个有限集合组成的整体可编码
- FA、正则表达式、CFG、PDA、TM 都可编码
就像通用计算机一样,存在一种可以被编程的“通用 (generic)”图灵机,它能解决任何图灵机可以解决的问题。使这台通用机器表现得像特定机器 \(M\) 的「程序」必须是对 \(M\) 的描述,也就是说我们可以把图灵机形式化一种可用来编写程序的编程语言。用这种语言编写的程序可以被一个通用图灵机(universal Turing machine) 解释,也就是另一种用相同语言编写的程序。
我们遇到的第一个问题是:图灵机的状态和纸带符号可能有无穷多种,所以很难用字母表将它们一一穷举出来。于是我们采用以下约定:表示图灵机状态的字符串形式为 \(\{q\}\{0, 1\}^*\),而纸带符号则表示为 \(\{a\}\{0, 1\}^*\)。
- 设 \(M = (K, \Sigma, \delta, s, H)\) 为图灵机
- 令 \(i, j\) 为满足 \(2^i \ge |K|, 2^j \ge |\Sigma| + 2\) 的最小整数,那么它们分别表示状态和符号编号的位串长度
- 固定 4 个特殊符号 \(\sqcup, \triangleright, \leftarrow, \rightarrow\) 为词典序中 4 个最小的符号,所以它们分别被表示为 \(a0^j, a0^{j-1}1, a0^{j-2}10, a0^{j-2}11\)
- 起始状态则始终被表示为词典序中的第一个状态,即 \(q0^i\)
- 注意到所有位串都需要保留前导 0
-
将整个图灵机 \(M\) 记作 \(“M”\),它由转移表 \(\delta\) 构成,即形如 \((q, a, p, b)\) 的字符串序列
- 这些四元组按词典序升序排序,起始于 \(\delta(s, \sqcup)\)
-
停机状态集 \(H\) 由那些不作为上述四元组中的第一个元素的状态间接确定
- 任何字符串 \(w \in \Sigma^*\) 有一个唯一的表示,记作 \(“w”\)
-
通用图灵机 \(U\) 有两个参数,分别是机器 \(M\) 的描述 \(“M”\) 和输入字符串 \(w\) 的描述 \(“w”\);当且仅当 \(M\) 在 \(w\) 上停机时,\(U\) 在输入 \(“M”, “w”\) 上停机,对应的函数记号为:
\[ U(“M”\ “w”) = “M(w)” \] -
实际上,这里描述的不是单纸带机器 \(U\),而是一个与之密切相关的三纸带机器 \(U'\)(而 \(U\) 是模拟 \(U'\) 的单纸带图灵机)
- 第一条纸带作为工作区,存储被模拟机器 \(M\) 的当前纸带内容(包括输入串 \(w\))
- 第二条纸带作为说明书,存储 \(M\) 自身的完整描述,即所有的状态转移规则
- 第三条纸带作为状态寄存器,实时记录 \(M\) 当前的内部状态
- 在每一步模拟中,\(U'\) 会根据第三条纸带上的当前状态和第一条纸带上扫描到的当前字符,去第二条纸带中搜索匹配的指令(四元组
) ,找到后便更新第三条纸带上的状态,并在第一条纸带上执行相应的写入或移动操作,如此循环直至停机
The Halting Problem⚓︎
假设现在有一个程序,输入为用相同语言编写的程序 \(P\) 以及 \(P\) 的输入 \(X\)。它能够正确判断程序 \(P\) 对于输入 \(X\) 能否停机,若能则返回是,否则返回否。我们将它记作 halt(P, X)。
假设有另一个程序 diagonal(X),其代码如下:
于是有了一个无法回答的问题:diagonal(diagonal) 是否能停机?不难发现,当且仅当 halts(diagonal, diagonal) 返回否时才能停机,也就是说当且仅当不停机的时候才能停机,这显然是个矛盾。所以,不存在一种能够判断任意程序是否能停机或(永远)循环的程序或算法(即不存在像 halts 这样的程序
令 \(H = \{“M”\ “w”: \text{Turing Machine } M \text{ halts on input string } w\}\)。首先注意到 \(H\) 是递归可枚举的:它能被前面介绍的通用图灵机 \(U\) 精确半判定,也就是说当输入在 \(H\) 内,\(U\) 始终能停机。这一问题便是图灵机的停机问题(halting problem)。
定理
语言 \(H\) 是不可递归的。因此,递归语言类是递归可枚举语言类的严格子集。
证明
令 \(H_1 = \{“M”: \text{Turing machine } M \text{ halts on input string } “M”\}\)。
- 假设前提:如果 \(H\) 是递归的(可判定的
) ,那么它的特例 \(H_1\)(机器是否在输入自身编码时停机)也必须是递归的,进而 \(H_1\) 的补集 \(\overline{H_1}\) 也必须是递归的。 - 构造矛盾:通过对角线法考察 \(\overline{H_1}\)(即“不接受自身编码的图灵机”的集合
) 。如果存在一个机器 \(M^*\) 能识别 \(\overline{H_1}\),那么当问及“\(M^*\) 是否接受它自己的编码”时,会陷入“接受即不接受,不接受即接受”的逻辑悖论 - 得出结论:由于 \(\overline{H_1}\) 连递归可枚举都做不到,因此初始假设不成立,证明了 \(H\) 不是递归的
定理
递归可枚举语言类在补操作下不封闭。
Undecidable Problems About Turing Machines⚓︎
不存在一种能为所有输入给出解的算法的问题被认为是不可判定的(undecidable) 或不可解的(unsolvable)。前面介绍的停机问题便是不可判定问题。
定义
令 \(L_1, L_2 \subseteq \Sigma^*\) 为语言。\(L_1\) 到 \(L_2\) 的归约(reduction) 是一个递归函数 \(\tau: \Sigma^* \mapsto \Sigma^*\),满足当且仅当 \(\tau(x) \in L_2\) 时 \(x \in L_1\)。
\(L_1\) 到 \(L_2\) 的归约可记作 \(L_1 \le L_2\),表示 \(L_1\) 的判定难度小于 \(L_2\)(来自 xg 笔记
注:reduction 应该就翻译成“归约”,没有“规约”的说法。
定理
若 \(L_1\) 不是递归的,那么存在一种 \(L_1\) 到 \(L_2\) 的归约,使得 \(L_2\) 也不是递归的。
证明
假设 \(L_2\) 是可递归的,即能被图灵机 \(M_2\) 判定。令 \(T\) 为计算归约 \(\tau\) 的图灵机。那么图灵机 \(TM_2\) 就能判定 \(L_1\) 了。但 \(L_1\) 是不可判定的,于是发生矛盾。所以 \(L_2\) 也不是递归的。
定理
以下关于图灵机的问题都是不可判定的:
- 给定图灵机 \(M\) 和输入字符串 \(w\),\(M\) 是否能在 \(w\) 上停机?
- 给定图灵机 \(M\),\(M\) 是否能在空纸带上停机?
- 给定图灵机 \(M\),\(M\) 是否能在某个输入字符串上停机?
- 给定图灵机 \(M\),\(M\) 是否能在每个输入字符串上停机?
- 给定图灵机 \(M_1, M_2\),它们是否能在相同字符串上停机?
- 给定图灵机 \(M\),\(M\) 半判定的语言是否是正则的 / 上下文无关的 / 递归的?
- 存在一个固定机器 \(M\),以下问题是不可判定的:给定 \(w\),\(M\) 能否在 \(w\) 上停机?
证明
- 前面证明过了
- 给定机器 \(M\) 和输入 \(w\),构造一个新机器 \(M_w\)。\(M_w\) 在空纸带上启动时,会先在带子上写上 \(w\),然后开始模拟 \(M\)。因此,\(M_w\) 在空纸带上停机,当且仅当 \(M\) 在输入 \(w\) 上停机。
- (将问题 2 归约到此问题上)给定 \(M\),构造 \(M'\),它会擦除任何给定的输入,然后在空串上模拟 \(M\)。显然,\(M'\) 在“某个”字符串上停机,当且仅当它在“所有”字符串上停机,这也当且仅当 \(M\) 在空串上停机。
- 问题 3 的论证同样适用于此,因为构造出的 \(M'\) 要么接受所有输入(如果 \(M\) 在空串停机
) ,要么不接受任何输入。 - (将问题 4 归约到此问题上)给定 \(M\),构造字符串 \(“M”“y”\),其中 \(y\) 是一台立即接受任何输入的机器。显然,\(M\) 和 \(y\) 接受相同的输入,当且仅当 \(M\) 接受所有输入。
- (将问题 2 归约到此问题上)构造 \(M'\):它先保存输入,然后运行 \(M\) 在空串 \(e\) 上的模拟。
- 如果 \(M\) 在 \(e\) 上停机,\(M'\) 恢复输入并运行通用图灵机 \(U\)(此时 \(M'\) 接受的语言是 \(H\))
- 如果 \(M\) 在 \(e\) 上不停机,\(M'\) 就永远不停(此时 \(M'\) 接受的语言是 \(\emptyset\)
) 。由于无法判断 \(M\) 是否在 \(e\) 上停机,也就无法判断 \(L(M')\) 是 \(\emptyset\)(正则且递归)还是 \(H\)(非递归)
- 这台特定机器正是通用图灵机 \(U\)
证明语言递归 / 递归可枚举的方法
来自朋辈辅学课件。
- 证明 \(A\) 递归
- 构造判定 \(A\) 的图灵机
- 证明 \(\exists\ B\),\(B\) 是递归的且存在 \(A\) 到 \(B\) 的归约
- 证明 \(A, \overline{A}\) 都是递归可枚举的(轮流运行两台半判定的图灵机)
- 证明 \(A\) 不递归
- 对角化构造
- 证明 \(\exists\ B\),\(B\) 是非递归的且存在 \(B\) 到 \(A\) 的归约
=== “递归可枚举 "
- 证明 $A$ 递归可枚举
- 构造半判定 $A$ 的图灵机
- 证明 $\exists\ B$,$B$ 是递归可枚举的且存在 $A$ 到 $B$ 的归约
- 证明 $A$ 并非递归可枚举
- 证明 $\exists\ B$,$B$ 是非递归可枚举的且存在 $B$ 到 $A$ 的归约
- 证明 $A$ 是不递归的,且 $\overline{A}$ 不是递归可枚举的
Unsolvable Problems About Grammars⚓︎
定理
以下问题是不可判定的:
- 对于给定文法 \(G\) 和字符串 \(w\),确定 \(w\) 是否属于 \(L(G)\)
- 对于给定文法 \(G\),确定 \(e\) 是否属于 \(L(G)\)
- 对于给定文法 \(G_1, G_2\),确定 \(L(G_1)\) 是否等于 \(L(G_2)\)
- 对于任意文法 \(G\),确定 \(L(G)\) 是否为空集
- 存在固定文法 \(G_0\),满足以下问题是不可判定的:确定任意字符串 \(w\) 是否属于 \(L(G_0)\)
证明
下面将展示从停机问题到(a)的归约:给定任何图灵机 \(M\) 和字符串 \(w\),我们只需对 \(M\) 应用在「文法」一节的第一个定理的证明中给出的构造,得到一个文法 \(G\),使得 \(L(G)\) 是由 \(M\) 半决定的语言。因此,当且仅当 \(M\) 在输入 \(w\) 时停机,\(w\) 属于 \(L(G)\)。
其他问题的证明也可以采用非常类似的归约,这里就不再赘述了。
由于之前已经证过文法和图灵机是等价的,因此对文法的不可判定性不觉得意外。然而,和上下文无关文法相关的相似问题也是不可判定的。
定理
以下问题是不可判定的:
- 给定上下文无关文法 \(G\),\(L(G)\) 是否等于 \(\Sigma^*\)?
- 给定上下文无关文法 \(G_1, G_2\),\(L(G_1)\) 是否等于 \(L(G_2)\)?
- 给定两个下推自动机 \(M_1, M_2\),它们是否准确接受相同的语言?
- 给定下推自动机 \(M\),找到等价的下推自动机,且保证状态数尽可能少
证明
整个证明的核心策略是归约,难点主要集中在第 1 个问题,一旦 1 被证明,问题 2、3、4 都可以通过简单的逻辑推导得出。以下是分步的清晰解释:问题 1 的证明思路是将一个已知不可判定的问题转化为“判断 \(L(G)\) 是否等于 \(\Sigma^*\)”的问题。
- 我们已知“判断一个广义文法 \(G_1\) 是否生成任何字符串(即是否 \(L(G_1) \neq \emptyset\))”是不可判定的
-
构造“推导历史”集合 \(D_{G'_1}\):
- 我们将 \(G_1\) 转换为标准形式 \(G'_1\)
- 定义集合 \(D_{G'_1}\) 为 \(G'_1\) 中所有合法的推导过程的字符串集合
- 为了方便下推自动机(PDA)进行检查,这里采用了一种「牛耕式
」 (boustrophedon)的写法,即把推导步骤中的奇数项反转( \(S_1 \Rightarrow x_1^R \Rightarrow x_2 \Rightarrow x_3^R \dots\)) ;这样做是因为 PDA 的栈是后进先出的,反转后才能让栈顶元素与后续输入字符一一对应匹配 - 关键逻辑:\(G_1\) 生成空语言(\(L(G_1) = \emptyset\)
) ,当且仅当不存在合法的推导过程,即 \(D_{G'_1} = \emptyset\)
-
转向考察补集 \(\overline{D_{G'_1}}\):
- 与其去描述合法的推导(这需要上下文敏感的能力
) ,不如去描述不合法的推导,即 \(\overline{D_{G'_1}}\) - 如果 \(D_{G'_1}\) 是空的(意味着 \(G_1\) 不生成任何串
) ,那么它的补集 \(\overline{D_{G'_1}}\) 就应该是全集 \(\Sigma^*\) - 只要我们能构造一个上下文无关文法 \(G_2\) 来生成 \(\overline{D_{G'_1}}\),那么判断“\(L(G_2) = \Sigma^*\)”就等同于判断“\(L(G_1) = \emptyset\)”
- 与其去描述合法的推导(这需要上下文敏感的能力
-
证明 \(\overline{D_{G'_1}}\) 是上下文无关的:一个字符串只要满足以下任意一个条件,它就是“非法推导”(属于 \(\overline{D_{G'_1}}\)
) :- 开头不对
- 结尾不对
- 分隔符 \(\Rightarrow\) 数量不对
- 偶数步推导错误(不符合规则)
- 奇数步推导错误(不符合规则)
可以证明这 5 种情况对应的语言都是上下文无关的。前三种和正则语言相关,证明较简单;而后两种可以通过非确定性 PDA 构造出来,利用栈来对比相邻的推导步骤。由于上下文无关语言对并集封闭,所以它们的并集 \(\overline{D_{G'_1}}\) 也是上下文无关的,因此存在一个文法 \(G_2\) 生成它。
如果我们能判定 \(L(G_2) = \Sigma^*\),我们就能判定 \(L(G_1) = \emptyset\),因为后者不可判定,所以前者也不可判定。
基于问题 1 的推论,我们继续完成问题 2, 3, 4 的证明:
- 如果这个问题可解,那我们只需要把 \(G_2\) 设为一个能生成全集 \(\Sigma^*\) 的平凡文法;这样问题就变成了“判断 \(L(G_1) = \Sigma^*\)”,回到了问题 1。既然 1 不可解,2 也就不可解
- 上下文无关文法可以转化为等价的 PDA;如果能判断 PDA 的等价性,也就等于能判断 CFG 的等价性,回到了问题 2,因此不可解
- 如果能求出最小状态 PDA,我们就可以检查它是否是那个“接受 \(\Sigma^*\) 的单状态 PDA”;也就是说,如果能最小化,就能判断一个 PDA 是否接受全集 \(\Sigma^*\),这等同于判断一个 CFG 是否接受全集 \(\Sigma^*\),回到了问题 1,因此不可解
可判定的问题
摘自朋辈复学课件
。 (其实应该也是从 xg 笔记中整理的;具体证明过程请认准 xg 笔记)
- \(A_{\text{DFA}} = \{ \langle D, w \rangle \mid D \text{ is a DFA that accepts } w \}\)
- \(A_{\text{NFA}} = \{ \langle N, w \rangle \mid N \text{ is a NFA that accepts } w \}\)
- \(A_{\text{REX}} = \{ \langle R, w \rangle \mid R \text{ is a regular expression that generates } w \}\)
- \(E_{\text{DFA}} = \{ \langle D \rangle \mid D \text{ is a DFA}, L(D) = \emptyset \}\)
- 搜索是否有可达的接受状态
- \(EQ_{\text{DFA}} = \{ \langle D_1, D_2 \rangle \mid D_1, D_2 \text{ are DFAs}, L(D_1) = L(D_2) \}\)
- 构造 \(D_1 \oplus D_2 = (L(D_1) \cup L(D_2)) - (L(D_1) \cap L(D_2))\)
- \(L(D_1) = L(D_2) \leftrightarrow L(D_1 \oplus D_2) = \emptyset\)
- \(ALL_{\text{DFA}} = \{ \langle D \rangle \mid D \text{ is a DFA that accepts all inputs} \}\)
- 构造 \(\overline{D}\)
- \(A_{\text{CFG}} = \{ \langle G, w \rangle : G \text{ is a CFG that generates } w \}\)
- \(A_{\text{PDA}} = \{ \langle P, w \rangle : P \text{ is a PDA that accepts } w \}\)
- \(E_{\text{CFG}} = \{ \langle G \rangle : G \text{ is a CFG}, L(G) = \emptyset \}\)
- 迭代计算每一非终结符是否能推导出空串
- \(E_{\text{PDA}} = \{ \langle P \rangle : P \text{ is a PDA}, L(P) = \emptyset \}\)
An Unsolvable Tiling Problem⚓︎
略
Properties of Recursive Languages⚓︎
定理
一个语言是递归的,当且仅当它和它的补都是递归可枚举的。
证明
证明的核心在于用并行模拟把两个可能不停机的过程变成一个必然停机的过程。
- 正向(\(\Rightarrow\)
) :若 \(L\) 是递归的,它和它的补集 \(\bar{L}\) 自然都是递归可枚举的(这是定义的直接推论) - 反向(\(\Leftarrow\)
) :- 设机器 \(M_1\) 识别 \(L\),机器 \(M_2\) 识别 \(\bar{L}\),构造新机器 \(M\) 同时并行运行 \(M_1\) 和 \(M_2\)
- 因为任意输入 \(w\) 必在 \(L\) 或 \(\bar{L}\) 中,所以 \(M_1\) 和 \(M_2\) 必有一个会停机
- 一旦其中一个停机,\(M\) 就立即给出最终结果(\(M_1\) 停则接受,\(M_2\) 停则拒绝)
- 既然 \(M\) 总能停机并给出结果,说明 \(L\) 是递归的
定义
我们称图灵机 \(M\) 枚举(enumerates) 语言 \(L\),当且仅当对于 \(M\) 的某些固定状态 \(q\),
一个语言是图灵可枚举的(Turing-enumerable),当且仅当存在能枚举该语言的图灵机。
定理
一个语言是递归可枚举的,当且仅当它是图灵可枚举的。
证明
-
假如 \(L\) 是递归可枚举的 \(\rightarrow\) 它可以被机器枚举
- 难点:如果依次测试字符串 \(s_1, s_2, s_3...\)(看机器是否接受它们
) ,一旦机器在某个字符串上陷入死循环,就永远没机会测试后面的字符串了 - 解法(燕尾法 (dovetailing)
) :采用分阶段并行的策略- 阶段 1:对第 1 个字符串跑 1 步
- 阶段 2:对前 2 个字符串各跑 2 步
- 阶段 \(k\):对前 \(k\) 个字符串各跑 \(k\) 步
- 结果:这样保证了机器 \(M\) 永远不会卡死在某一个输入上,只要一个字符串属于 \(L\),它最终一定会在某个阶段被接受并被打印出来
- 难点:如果依次测试字符串 \(s_1, s_2, s_3...\)(看机器是否接受它们
-
假如 \(L\) 可以被机器枚举 \(\rightarrow\) 它是递归可枚举的
- 思路:这个方向很简单。假设有一台“枚举机器”在不断吐出属于 \(L\) 的字符串
- 构造:我们要判断输入 \(w\) 是否在 \(L\) 中,只需运行这台枚举机器,并盯着它的输出看
- 判定:每当枚举机器吐出一个新串,就拿来和 \(w\) 比对;如果相等,就停机接受;如果不等,就继续等下一个;如果 \(w \in L\),它迟早会被吐出来并被接受
定义
令 \(M\) 为枚举语言 \(L\) 的图灵机。若以下条件为真,我们称 \(M\) 按词典序枚举(lexicographically enumerates) 了 \(L\)(其中 \(q\) 是特别的“显示”状态
一个语言是按词典序图灵可枚举的(lexicographically Turing-enumerable),当且仅当存在能按词典序枚举该语言的图灵机。
定理
一个语言是递归的,当且仅当它是按词典序图灵可枚举的。
证明
-
正向(\(L\) 是递归的 \(\rightarrow\) 可以按字典序枚举)
- 关键点:递归语言的判定机器 \(M\) 总是会停机(不会死循环)
- 做法:构造一个新机器,按字典序(\(s_1, s_2, s_3...\))依次生成所有可能的字符串,并用 \(M\) 去测试每一个
- 结果:因为 \(M\) 对每个串都能快速给出 Yes/No 而不卡死,可以按顺序一个个测下去;测过并通过的就打印出来,输出自然就是严格按字典序排列的
-
反向(可以按字典序枚举 \(\rightarrow\) \(L\) 是递归的)
- 关键点:有序性让我们知道“何时该放弃等待”
-
做法:假设有一个能按顺序吐出字符串的枚举机;要判定输入 \(w\) 是否在 \(L\) 中,就盯着这个枚举机看:
- 如果枚举机吐出了 \(w\),直接接受
- 如果枚举机吐出了一个比 \(w\) 还要大(字典序更靠后)的字符串,说明 \(w\) 肯定已经被跳过去了,以后永远也不会出现了,直接拒绝
-
结论:因为总是能等到上面两种情况之一(不会无休止地等下去
) ,所以判定过程必然停机,证明 \(L\) 是递归的
莱斯定理(Rice's Theorem)
假设 \(\mathcal{C}\) 是所有递归可枚举语言类的非空真子集,那么以下问题是不可判定的:给定图灵机 \(M\),\(L(M)\) 是否属于 \(\mathcal{C}\)。
证明
利用归约法,把停机问题转化为判断一个语言是否属于类 \(\mathcal{C}\) 的问题
- 设定:设 \(\mathcal{C}\) 是递归可枚举语言的一个真子集。不妨假设空集 \(\emptyset \notin \mathcal{C}\),而存在某个特定语言 \(L \in \mathcal{C}\)(由机器 \(M_L\) 识别)
- 构造:对于给定的停机问题实例(机器 \(M\) 和输入 \(w\)
) ,我们构造一个新的机器 \(T_{M,w}\)- \(T_{M,w}\) 在处理任何输入 \(x\) 时,先强制运行 \(M\) 在 \(w\) 上的计算
- 若 \(M\) 死循环:\(T_{M,w}\) 也会永远卡在这里,不接受任何 \(x\),此时它识别的语言是 \(\emptyset\)(不在 \(\mathcal{C}\) 中)
- 若 \(M\) 停机:\(T_{M,w}\) 就会继续去运行 \(M_L(x)\),此时它识别的语言就是 \(L\)(在 \(\mathcal{C}\) 中)
- 结论:这样一来,判断“\(T_{M,w}\) 识别的语言是否属于 \(\mathcal{C}\)” 就完全等价于判断 “\(M\) 是否在 \(w\) 上停机”;因为停机问题不可判定,所以“判断语言是否属于类 \(\mathcal{C}\)” 也是不可判定的
评论区