未校对,未加习题

8 上下文无关语言

8.1 上下文无关文法

  1. Q: 描述算术表达式文法中,“项”“因子”“表达式”三者以什么顺序“循环”地出现?为什么?
    A: 表达式由项组成,项由因子组成,因子可能是表达式。
    其实“表达式由因子组成,因子由项组成,项可能是表达式”也有可能。实际中可能是看哪种情况更常见,考虑了效率(或许“多项式”一般更常见?)
  2. Q: 接上,为什么不能用正则文法?
    A: 比如左边一来一大堆括号(用泵引理)。
    前缀表达式看,更清晰:比如一来一大堆加号“爆栈”。
    “平衡括号串”同理
  3. Q: 树结构和“上下文无关”有何联系?
    A: 提示:上下文有关语言显然会出现“一子多父”
  4. Q: 歧义和固有歧义有何区别和联系?
    A: 歧义针对CFG,如\(G\). 固有歧义针对CFL,即任意生成它的CFG都有歧义。
    实际应用中,使用非固有歧义的CFL,并相应找非歧义CFG.
  5. Q: 为什么某CFG生成某字符串的最左派生可能不唯一?
    A: 提示:\(3=1+2=2+1\). 最左并不是说必须\(1+2\)不能\(2+1\)了!
  6. Q: \((a+b)^*b(a+b)^*\),正则语言,固有歧义有何联系?
    A: 提示:正则语言一定非固有歧义。因为可以考虑DFA诱导出的正则文法。从右侧开始考察,容易证明语法树唯一性
    具体地,如果有\(A\to aB,C\to aB\)这种,则不断往前“回溯”,最后到\(S\)处,矛盾。

8.2 Chomsky范式

  1. Q: 核(kernel)可计算和什么的有穷有关系?
    A: 上下文无关文法产生式左侧可能出现的总变元个数为有限种。所以不断“迭代”,不断增大“允许产生的次数”,总到某次迭代就不动了。
  2. Q: 核的定义是可能生成(),而不是“一定”。
    既然如此,那么直接把核中的变量从产生式右边删了为啥不会有问题(“少了能产生的串”)?
    A: 空串。
    注意是添加新的产生式,不是把旧的产生式强行变得右边不能有核。所以不会少了原本可以产生的串。
  3. Q: 把(语言不含空串)上下文无关文法变为正上下文无关文法和上一章“正则文法”习题处的做法有区别吗?
    A: 区别很小。都是找核,删核。归纳证明两个语言(不考虑空串)相等。
    实际上上一章是本章该结论的特例。
    注:归纳法可以是\(1+(i-1)\),而不一定是\((i-1)+1\). 此时这样挺方便。
  4. Q: 接上,考察右侧的“字符个数”“不能过多或过少”。“二叉树”思想与范式有何联系?
    A: 字符个数多的话跟上章习题一样引入“中间状态”。最后可以得到“二叉树模拟\(k\)叉树”
    字符个数少:关于空的情况已经讨论过了;1的话和上一章也类似,有点像“路径压缩”。
  5. Q: 讨论Chomsky范式文法是否和原文法等价:考虑()是否含有\(S\)即可。
    A: \(kerG\)
    注意Chomsky范式文法生成语言一定不含空串

8.3 Bar-Hillel泵引理

  1. Q: 此泵引理的“抽屉原理”和正则文法处的有何区别?
    A: 此处是树,之前是链。
    树n层对应了最多\(2^n\)的长度。
  2. Q: 应用此泵引理为什么往往(相比上章的)需要分类讨论?
    A: 不知道\(v_1 uv_2\)在哪个位置。
    (之前是“只在前面”)
  3. Q: 字符串中\(a\)个数和\(b\)个数成指定比例关系如何考察“泵”?
    A: 首先注意每个字符串的“重复段”不一定是相同的。
    实际上相当于想证明:例如:对于\(a:b=7:3\)的字符串,一定存在两个子串(无交,不全为空),使得这两子串拼接起来也是\(a:b=7:3\)
    实际上有更强的结论:存在长度为10的滑窗合题意(请注意\(v_1v_2\ne \epsilon\)即可,并无其它限制)。证明:滑窗,最值定理。
  4. Q: 泵引理只能“拉长”序列嘛?
    A: 还可以缩短一下使得变成\(v_1^0\)这样。

8.4 下推自动机

  1. Q: 下推自动机的“状态空间”和FA有何不同?
    A: 用栈表示,是无穷的。
    更新方式不是直接打表而是入栈出栈。
  2. Q: 为什么入栈可以入一个字符串而不是规定只能入栈字母表中字符?
    (上述问题相当于:)为什么动作函数考虑\(\cdots\)\(Q\times \Omega^*\)的二元关系而不是()的?
    A: 人为引入一些“中间状态”和\(\epsilon\)转移则显然两者等价。所以就没必要给自己找麻烦了。
    \(\cdots\)\(Q\times A\)(其中\(A\)\(\Omega^*\)的某个子集,具体略。且千万看清楚定义,当这个字符串长度为1时是“改写”栈顶,长度为2才能“入栈”)
  3. Q: 对于用空栈方式模拟接受状态方式,如果猜错了“倒空”的时机,会怎么办?
    A: 回忆定义,没有对空栈做出任何指令定义,即空栈了一定停机。如果猜错,那么猜错的那个“分支”就相当于没有接受。
  4. Q: 用接受状态方式模拟空栈方式的“栈底符号”和前面图灵机相关证明中什么东西类似?
    A: “划定一块空间,在这块空间中模拟,方便之后退出模拟”,有点类似单向带图灵机相关证明中用到的\(\$\)符号
  5. Q: PDA的状态转移图绘制中有什么和图灵机不同的点?
    A: 每条边上写\(a,X/w\)或者\(\epsilon, X/w\)这类标记。相比图灵机多了一个输入。
    还有一种特殊记号:\(a,\epsilon/w\),相当于某种缩写,即不管栈顶是什么,都拿出来读了塞回去,再加上\(w\).

8.5 上下文无关文法与下推自动机的等价性

  1. Q: 为了用PDA模拟Chomsky范式文法(是CFG),对于\(X\to a\)产生式用()模拟,而对于()用()。
    注:为了完整说明等价性还需要考虑()串的特例。
    注:等价的证明方法:对于\(X\to \alpha\),栈中的\(X\)可以\(\epsilon-\)转移地变成()。且终极符在()的同时出栈。这种方法挺简明的,不过栈中的字母表比较大。
    A: 读取a弹出X,\(X\to YZ\),弹出\(X\)放入\(YZ\)

    \(\alpha\),读取纸带上的终极符
  2. Q: 为什么只用考虑最左派生?
    注:可以看到上题模拟过程根据栈的性质对应了最左派生。左边不用完,那右边“压着”。
    A: 画出语法树。发现对于任意一般的派生,都可以构造最左派生得到同样结果。
  3. Q: 反过来模拟,显然终极符对应()。那么必须要用()同时记录()和()
    A: 输入字母表中的字母
    变元,栈字母表中的字母,状态
  4. Q: 为什么\(S\to [q_1,X_0, p],p任取\)
    A: PDA从\(q_1\)转移到任意\(p\)都没关系,只要从\(X_0\)开始,栈顶移除\(X_0\)能读入字符串\(w\)\(w\)就是能被文法接受的。
  5. Q: 接上,类似的想法出现在\([q,X,p_{m+1}]\to a[p_1,Y_1,p_2]\cdots\)中。这里的\(p_2,\cdots\)都可以是任意状态。简要解说该产生式。
    A: 产生式左侧:状态\(q\)时读入\(w\)能对栈弹\(X\)得到\(p_{m+1}\).
    那么如果读入\(a\)时不是直接干脆地弹了\(X\),而是之后还加入了\(Y_1Y_2\cdots\),那么就不马上得到\(p_{m+1}\),而是先得到(\(a\)决定的)中间状态\(p_1\),然后再经过一系列任意的状态转移和弹\(Y_i\)动作,总共来看生成了\(w\).
    注:假设PDA只有一种状态,那么这个文法就退化得和PDA更加直接对应了,这可帮助抓住本质,进行记忆。
  6. Q: 为了证明\([q,X,p]\)派生出\(w\)等价于\((q,w,X)\mathop\vdash\limits^* (p,\epsilon,\epsilon)\),使用归纳。
    如果\([q,X,p]\)派生出\(w\),证明后者,那么先把\([q,X,p]\)派生一步得到()再归纳。
    反之,已知后者证明前者,则初始的\(q,w,X\)第一步先\(\vdash\)(),之后\(\mathop\vdash\limits^*\)(),根据归纳假设()派生()。从而容易归纳
    A: \(a[p_1,Y_1,p_2]\cdots\)(注:归纳要点是先消耗一个字符\(a\)
    \((p_1, u, Y_1Y_2\cdots)\)
    \((p,\epsilon,\epsilon)\)
    \([p_1,Y_1,p_2]\cdots [p_m,Y_m,p]\)
    \(u\)\(w\)去除左侧第一个字符\(a\)得到的)
  7. Q: 上题证明有一个细节:\((p_1,u,Y_1Y_2\cdots)\)\(\mathop\vdash\limits^*(p,\epsilon,\epsilon)\),则一定可以人为划分成有限段(根据“第一次栈高度降低至某某”),且每段都形如()。从而才推出“派生”关系
    A: 去掉一个\(Y\)\(p_i\)转移至\(p_{i+1}\)并读取了一段字符串u_i
  8. Q: 另证:如果考虑接受时栈空且接受状态指定(从而初始状态是\([p_1,p_n]\)给定)
    且每次只会弹出或者加入一个变元的PDA,那么变元只需要\([p,q]\)型即可(为什么?)
    此时,考虑计算过程中栈高度的变化,要么空过则\([p,q]\Rightarrow [p,r][r,q]\),要么()。
    A:
    提示:每个\([p,q]\)这时都“编码”了栈不变,只有状态转移了的过程。具体地,\([p,q]\Rightarrow a[r,s]b\)\([r,s]\)仍然“编码”了栈不变。注意,这里需要联系“是否空过”
    所以括号填:栈没有空过,则\([p,q]\Rightarrow a[r,s]b\)(或者\(p=q\)时也可\(\Rightarrow \epsilon\)

8.6 确定型下推自动机

  1. Q: 为了计算唯一,除了对于所有输入不可能(),还需要()
    A: 大于一种可能动作
    任意一种状态如果能\(\epsilon\)转移就不能一般地读入和转移
  2. Q: DPDA的两种接受方式的关系和非确定PDA有何区别?
    A: 接受状态方式比空栈方式强。接受状态方式模拟空栈和之前比较类似,但是空栈方式由于不能“猜字符串没了”,所以没法模拟接受状态方式。
    实际上对于空栈方式正是因为不能“猜”字符串结束,所以根据确定型,如果\(w\)被接受,那么\(w\)之后添加任何非空字符串都不被接受。总之空栈方式真的很弱。
  3. Q: “补封闭”与“证明真子集”有什么联系?“补封闭”与“确定”又有何联系?
    A: 自身运算封闭,超集运算不封闭,超集一定是真超集。
    因为“确定”,所以只要末尾不接受,那就是“补”(注:其实比这个复杂。但最总体思想是这个)
    但是非确定情况,某个计算分支不接受不能说明问题。
  4. Q: 除了运行到末尾不接受,还有可能(),中途空栈,中途死循环\(\epsilon\)转移。
    对于第一种,直接“自暴自弃状态”即可。第二种直接“模拟”,即栈底有一个特定的符号。
    对于第三种,首先找到一连串不断生成的\(\beta_0,\cdots,\beta_i\)中最()的,设其为\(Z\alpha\). 设对应的循环格局\((p,\epsilon,Z)\),则对DPDA出现无限循环等价于可以\(\mathop\vdash\limits^*\)()
    A: 中途停下(没有动作可做)
    短(或之一)
    \((p,u,Z\alpha),u\ne \epsilon\)
  5. Q: 接上,对于循环格局,我们具体如何处理进行模拟且避免循环?
    A: 既然充要条件是经过某某,那我们就在“必经之路打劫”,直接“劫持走”(即:预先计算好是否接受。接受则劫持到接受状态,否则直接劫持到不接受状态。如果接受状态读了新字符那也不接受)
  6. Q: 末尾的\(\epsilon\)转移给接受补集的DPDA带来什么麻烦?
    A: 如果原机器运行结果末尾在接受和非接受间转移,那么“直接构造”将导致新机器也接受。
    注:解决方法是在状态处引入新分量记录上次读取字符以来有没有接受过。只有从未接受过时,才真正是“补集”中的。

8.7 上下文有关文法

  1. Q: 上下文有关语言递归和只有()个产生式的()递归证明类似。
    A: 1,(无限制)文法生成的语言
  2. Q: 直接背诵从0型语言到3型语言的5个反例。
    A:
  • \(\Phi(x,t)\downarrow\)\(x,t\),递归可枚举但不递归。
  • 对角线方法证明存在递归但不1型(具体地,所有CSG可以被自然数不漏地枚举。而存在某递归语言,对\(1^i\)的结果和\(L_i\)不同)
  • 上下文无关语言可以用泵引理,所以\(a^nb^nc^n\)是1型但不2型
  • \(\{a,b,c\}^* - \{a^nb^nc^n|n\ge 1\}\)是2型但不是确定型CFL
  • \(a^nb^n\)是确定型CFL但不3型
  • 注:\(\Phi(x,t)\uparrow\)\(x,t\)不是递归可枚举
  1. Q: 用LBA模拟CSG最自然的是()条带。可以看到“单调”起了核心作用。
    A: 2
    (一条带上始终不变,另一条生成的所有结果和其比较)
    (注:利用非确定性)

习题

8.3(2)证明不会……
读完字符串 进入接受就行 不需要一定停止(之后加)