## Lec 7 CFG ### PDA 形式化定义:A **pushdown automaton** is a 6-tuple $$ (Q, \Sigma, \Gamma, \delta, q_0, F), where: $$ - $Q$ is the finite set of states; - $\Sigma$ is the finite input alphabet; - $\Gamma$ is the finite stack alphabet; - $\delta : Q \times \Sigma_{\varepsilon} \times \Gamma_{\varepsilon} \rightarrow \mathcal{P}(Q \times \Gamma_{\varepsilon})$ is the transition function; - $q_0 \in Q$ is the initial state; and - $F \subseteq Q$ is the set of final states. #### Problem 1: 设计 PDA 一些比较基本的经验和操作。 对于栈操作来说,比如是 $op_a \to op_b$ 代表当前栈顶是 $op_a$,将栈顶变为 $op_b$。那么这个意思就比较丰富了: 1. 若形如:$a \to b$,其中 $a, b \in L$(就是说现在在栈里面要匹配的字符属于当前language的字符集),那么实际上的意思是 `pop(a) + push(b)`,相当于是用 $b$ 替换当前栈顶的元素 $a$。 2. 若形如:$\epsilon \to b$, 意思是 `push(b)`。因为 $\epsilon$ 是要匹配一个空。 3. 若形如:$b \to \epsilon$,意思是 `pop(b)`,其中 $b$ **一定是栈顶元素!!!!**。要时刻记得 $op_a$ 是栈顶元素。 下面是一些常见的设计PDA需要的栈操作: 1. $\epsilon \to \$$ **一定要加!**: 这一步是为了让一个空的栈有一个”空“的标记 (即 $\$$ ) 2. $\epsilon \to \epsilon$ :相当于是我们不对栈进行任何操作 (见 A2-Q1-a)。**一个比较好用的东西**: $\epsilon, \epsilon \to \epsilon$ 可以用来处理 $n, m = 0$ 的 case。 ##### e.g.1 $L = a^nb^{n+m}c^m$ 这道题可以学习的点:注意到其实我们设计的都是NPDA,那么对于一个 $w \in L$ (属于当前language的串),我们只要 PDA 存在一个路径让他到达 Final state 即可。我们这里通过 $a, b, c$ 的标志来区分数量,**中间用 $\epsilon, \epsilon \to \epsilon$** **来转移到下一个计数 state**。  ##### e.g.2 $L = a^n b^{2n}$ 这道题可以学习的点:这里需要处理的主要是 $n$ 个 a 和 $2n$ 个 b 的倍数关系。难点在于我们需要设计使得每读进来一个 $a$ 可以往栈里面 `push` 两个 $a$。实现可以参考答案。  ##### e.g.3 $L = a^nb^{m}c^{l}, n \geq m | n \geq l$ 答案错了。权威这一块,拿捏的死死的。 一些小细节: 1. 最后进入 Final state 的时候,由于可能 $n > m | l$ ,那么 stack 里面还有剩余的 $a$,设计转移的时候要注意。 2. 此外就是一个标准的双分支结构,用 $\epsilon, \epsilon \to \epsilon$ 转移就好。  #### Problem 2:PDA 和 CFG 的互相转换 感觉比较能出的实际上是CFG 2 PDA 比较要注意的实际上是: | Type | 做法 | | ------------------------- | ------------------------------------------------------------ | | Terminals | 1. 先从 $NT \to T$ (从变量推导出 Terminals);再加入:$T \to \epsilon$ (处理完毕,出栈); 2. 对于每一个 Terminals,都要有出栈。 | | Non-Terminals(Recursion) | **注意一定是从右到左**;比如说有:$S \to aSb$,那么要有转移 $\epsilon, S \to b | \epsilon \to S | \epsilon \to a$ | 最后一定要加入 $\epsilon, \$ \to \epsilon$ 到 final state 的转移。 放个作业题  #### Problem 3: 证明 CFG 是 ambiguous 的 Compiler 题型,做法也很简单:**找一个属于这个CFG的串,画出两棵不同的 parsing tree 即可** ### CFG Properties 感觉不是很重要,一笔带过吧 满足的性质: 1. Union: $L_1, L_2$ 都是 CFG $\Rightarrow$ $L_1 \cup L_2$ 也是 CFG 2. Concat: $L_1 \cdot L_2$ 也是 CFG 3. Star 4. 与 regular language 的交:$L_R \cup L_C$ 也是 CFG 不满足的性质: 1. Complement ### Pumping Lemma 感觉其实会简单一些,主要是由于 CFL 的构造会复杂一些,所以枚举的case必须要覆盖全面。其他的倒是比较简单。 ## Lec 9 TM A **Turing Machine** is a 7-tuple $$ M = (Q, \Sigma, \Gamma, \delta, q_0, q_{\text{accept}}, q_{\text{reject}}) $$ 1. $Q$ is the set of states; 2. $\Sigma$ is the input alphabet $$ \sqcup \notin \Sigma $$ 3. $\Gamma$ is the tape alphabet $$ \sqcup \in \Gamma \quad \text{and} \quad \Sigma \subseteq \Gamma $$ 4. The transition function is $$ \delta : Q \times \Gamma \rightarrow Q \times \Gamma \times \{L, R\} $$ 5. $q_0 \in Q$ is the start state; 6. $q_{\text{accept}} \in Q$ is the accept state; and 7. $q_{\text{reject}} \in Q$ is the reject state, where $$ q_{\text{reject}} \neq q_{\text{accept}} $$ 感觉一些比较容易忽略的点: 1. TM **rejects** a string $w$ if 1. it halts on the input $w$ at a reject state or 2. it has no where to move in the middle of the process 2. **Turing-decideable**: A language $L$ is **recursive** (or Turing-decidable) if there is a TM $M$ such that 1. $\forall w \in L$, $M$ accpets $w$; 2. $\forall w \not \in L$, M rejects $w$ 3. **Turing-recognizable**: A language $L$ is recursively enumerable (or Turing-recognizable) if there is a TM $M$ such that: 1. $\forall w \in L$, $M$ accpets $w$; 2. $\forall w \in L$, $M$ rejects $w$ or $M$ loops forever #### Problem 4a: 设计 TM (Decider) 一些比较好的设计规范: 1. 要对不同字符操作的时候最好退回到纸带起点 2. 可以用不同的字母表示不同的含义,比如说 (a,b) 配对用 x,(b,c) 配对用 y 这样。 ##### 类型 1: **数量倍数关系判定** 对于 $L_1 = \{a^nb^{m} | n = 2m, n \geq 0, m \geq 0\}$ 设计思路: - 参考 A3-Q1 中的 $a^ib^jc^k$ - 策略:每次划掉一个 a,然后去找一个 b,**退回到纸带最左边**,然后再划掉一个 a,最后又退回到最左边。如果 a 找不到了,就可以 accept 了 acc x → x, R □ → □, R a → x, R a → a, R x → x, R b → x, L a → a, L x → x, L □ → □, R x → x, R a → x, R x → x, L □ → □, R ##### 类型 2: **逆序结构判定(回文)** 对于 $L_2 = \{w \in \{0, 1\}^{*} | w = w^{R } \}$ 设计思路: - 读取最左边的字符,记住它是 0 还是 1(通过状态来记忆,相当于走到不同状态分支)。标记 - 然后移动到最右边未被标记的字符,检查其是否与左边的一致。如果一致,删掉右边这个字符并移回最左边; - 注意到奇数长度的串需要特别判断:如果从右边往左边扫的时候遇到空格了,可以直接进入 acc 状态 acc x \to x, R space \to space, R 0 \to x, R 1 \to x, R space \to space, R space \to space, R 0 \to x, L x \to x, L x \to x, L 1 \to x, L x \to x, L / 0 \to 0 L / 1 \to 1, L x \to x, L / 0 \to 0, L / 1 \to 1, L space \to space, R space \to space, R space \to space, R space \to space, R ##### 类型 3:加法 对于 $L_3 = \{a^ib^jc^k | i + k = j, i, j, k \geq 1\}$ 设计思路: - 可以先匹配 *a* 和 *b*。每次划掉一个 *a*,对应划掉一个 *b*。当 *a* 全部划掉后,继续匹配 *c* 和剩余的 *b*。如果 *c* 耗尽时 *b* 也刚好耗尽,则接受。 ##### 类型 4: 幂次判定 对于 $L_4 = \{a^n | n = 2^k, k \geq 0\}$ 设计思路: - 通过重复“除以 2”的过程。 - 从左到右扫描,每隔一个 *a* 划掉一个 *a*(保留一半)。 - 如果扫描过程中发现总数是奇数(且总数大于1),则拒绝。 - 扫描完一轮后,将读写头移回开头,重复步骤 1。 - 如果最后只剩下一个 *a*,则接受。 #### Problem 4b: 设计 TM (Computation) 由于TM会在tape上写写画画(称之为 side effect),故可以用来做一些 computation 任务 ##### 类型 1: 前驱后继 作业已经设计过一个前驱了,现在来考虑一下后继。 主要的问题都是: - 低位在右边 - 考虑进位 设计思路: **设计提示:** ◦ 这是 Q2x 的逆运算。你需要先将读写头移动到最右端的 LSB。 ◦ 从右向左扫描:如果你看到 `1`,将其变为 `0` 并继续向左进位(Carry);如果你看到 `0`,将其变为 `1` 并停止(进入 Halt 状态)。 ◦ **边界情况:** 如果移动到最左边还是进位(例如 `11` + 1),你需要处理溢出,可能需要整体右移数据或在左边插入一个 `1`。 acc any \to any, R space \to space, L 1 \to 0, L 0 \to 1, L / space \to 1, L ##### 类型 2: **一进制转二进制 (Unary to Binary Conversion)** 双带(2-tape)TM 设计思路: 这道题可以直接复用 **Q1** 的逻辑作为子程序(Subroutine)。 ◦ **策略:** 纸带 2 作为一个计数器,初始当作 `0`。读写头在纸带 1 上每读到一个 `x`,就在纸带 2 上执行一次“加 1”操作(调用 Q1 的逻辑)。 ◦ 当纸带 1 的 `x` 读完时,纸带 2 上的内容即为结果。 其他的我感觉考试也不可能出太过分了,据说去年出了一个去模,我感觉思路应该类似于辗转相除法。如果出了我就认账。 Loading... ## Lec 7 CFG ### PDA 形式化定义:A **pushdown automaton** is a 6-tuple $$ (Q, \Sigma, \Gamma, \delta, q_0, F), where: $$ - $Q$ is the finite set of states; - $\Sigma$ is the finite input alphabet; - $\Gamma$ is the finite stack alphabet; - $\delta : Q \times \Sigma_{\varepsilon} \times \Gamma_{\varepsilon} \rightarrow \mathcal{P}(Q \times \Gamma_{\varepsilon})$ is the transition function; - $q_0 \in Q$ is the initial state; and - $F \subseteq Q$ is the set of final states. #### Problem 1: 设计 PDA 一些比较基本的经验和操作。 对于栈操作来说,比如是 $op_a \to op_b$ 代表当前栈顶是 $op_a$,将栈顶变为 $op_b$。那么这个意思就比较丰富了: 1. 若形如:$a \to b$,其中 $a, b \in L$(就是说现在在栈里面要匹配的字符属于当前language的字符集),那么实际上的意思是 `pop(a) + push(b)`,相当于是用 $b$ 替换当前栈顶的元素 $a$。 2. 若形如:$\epsilon \to b$, 意思是 `push(b)`。因为 $\epsilon$ 是要匹配一个空。 3. 若形如:$b \to \epsilon$,意思是 `pop(b)`,其中 $b$ **一定是栈顶元素!!!!**。要时刻记得 $op_a$ 是栈顶元素。 下面是一些常见的设计PDA需要的栈操作: 1. $\epsilon \to \$$ **一定要加!**: 这一步是为了让一个空的栈有一个”空“的标记 (即 $\$$ ) 2. $\epsilon \to \epsilon$ :相当于是我们不对栈进行任何操作 (见 A2-Q1-a)。**一个比较好用的东西**: $\epsilon, \epsilon \to \epsilon$ 可以用来处理 $n, m = 0$ 的 case。 ##### e.g.1 $L = a^nb^{n+m}c^m$ 这道题可以学习的点:注意到其实我们设计的都是NPDA,那么对于一个 $w \in L$ (属于当前language的串),我们只要 PDA 存在一个路径让他到达 Final state 即可。我们这里通过 $a, b, c$ 的标志来区分数量,**中间用 $\epsilon, \epsilon \to \epsilon$** **来转移到下一个计数 state**。  ##### e.g.2 $L = a^n b^{2n}$ 这道题可以学习的点:这里需要处理的主要是 $n$ 个 a 和 $2n$ 个 b 的倍数关系。难点在于我们需要设计使得每读进来一个 $a$ 可以往栈里面 `push` 两个 $a$。实现可以参考答案。  ##### e.g.3 $L = a^nb^{m}c^{l}, n \geq m | n \geq l$ 答案错了。权威这一块,拿捏的死死的。 一些小细节: 1. 最后进入 Final state 的时候,由于可能 $n > m | l$ ,那么 stack 里面还有剩余的 $a$,设计转移的时候要注意。 2. 此外就是一个标准的双分支结构,用 $\epsilon, \epsilon \to \epsilon$ 转移就好。  #### Problem 2:PDA 和 CFG 的互相转换 感觉比较能出的实际上是CFG 2 PDA 比较要注意的实际上是: | Type | 做法 | | ------------------------- | ------------------------------------------------------------ | | Terminals | 1. 先从 $NT \to T$ (从变量推导出 Terminals);再加入:$T \to \epsilon$ (处理完毕,出栈); 2. 对于每一个 Terminals,都要有出栈。 | | Non-Terminals(Recursion) | **注意一定是从右到左**;比如说有:$S \to aSb$,那么要有转移 $\epsilon, S \to b | \epsilon \to S | \epsilon \to a$ | 最后一定要加入 $\epsilon, \$ \to \epsilon$ 到 final state 的转移。 放个作业题  #### Problem 3: 证明 CFG 是 ambiguous 的 Compiler 题型,做法也很简单:**找一个属于这个CFG的串,画出两棵不同的 parsing tree 即可** ### CFG Properties 感觉不是很重要,一笔带过吧 满足的性质: 1. Union: $L_1, L_2$ 都是 CFG $\Rightarrow$ $L_1 \cup L_2$ 也是 CFG 2. Concat: $L_1 \cdot L_2$ 也是 CFG 3. Star 4. 与 regular language 的交:$L_R \cup L_C$ 也是 CFG 不满足的性质: 1. Complement ### Pumping Lemma 感觉其实会简单一些,主要是由于 CFL 的构造会复杂一些,所以枚举的case必须要覆盖全面。其他的倒是比较简单。 ## Lec 9 TM A **Turing Machine** is a 7-tuple $$ M = (Q, \Sigma, \Gamma, \delta, q_0, q_{\text{accept}}, q_{\text{reject}}) $$ 1. $Q$ is the set of states; 2. $\Sigma$ is the input alphabet $$ \sqcup \notin \Sigma $$ 3. $\Gamma$ is the tape alphabet $$ \sqcup \in \Gamma \quad \text{and} \quad \Sigma \subseteq \Gamma $$ 4. The transition function is $$ \delta : Q \times \Gamma \rightarrow Q \times \Gamma \times \{L, R\} $$ 5. $q_0 \in Q$ is the start state; 6. $q_{\text{accept}} \in Q$ is the accept state; and 7. $q_{\text{reject}} \in Q$ is the reject state, where $$ q_{\text{reject}} \neq q_{\text{accept}} $$ 感觉一些比较容易忽略的点: 1. TM **rejects** a string $w$ if 1. it halts on the input $w$ at a reject state or 2. it has no where to move in the middle of the process 2. **Turing-decideable**: A language $L$ is **recursive** (or Turing-decidable) if there is a TM $M$ such that 1. $\forall w \in L$, $M$ accpets $w$; 2. $\forall w \not \in L$, M rejects $w$ 3. **Turing-recognizable**: A language $L$ is recursively enumerable (or Turing-recognizable) if there is a TM $M$ such that: 1. $\forall w \in L$, $M$ accpets $w$; 2. $\forall w \in L$, $M$ rejects $w$ or $M$ loops forever #### Problem 4a: 设计 TM (Decider) 一些比较好的设计规范: 1. 要对不同字符操作的时候最好退回到纸带起点 2. 可以用不同的字母表示不同的含义,比如说 (a,b) 配对用 x,(b,c) 配对用 y 这样。 ##### 类型 1: **数量倍数关系判定** 对于 $L_1 = \{a^nb^{m} | n = 2m, n \geq 0, m \geq 0\}$ 设计思路: - 参考 A3-Q1 中的 $a^ib^jc^k$ - 策略:每次划掉一个 a,然后去找一个 b,**退回到纸带最左边**,然后再划掉一个 a,最后又退回到最左边。如果 a 找不到了,就可以 accept 了 <?xml version="1.0" encoding="UTF-8"?> <svg width="800" height="600" version="1.1" xmlns="http://www.w3.org/2000/svg"> <!-- Notes for reliable rendering: 1) Save this file as UTF-8 (no ANSI). 2) Use a font stack with arrow support. --> <ellipse stroke="black" stroke-width="1" fill="none" cx="179.5" cy="186.5" rx="30" ry="30"/> <ellipse stroke="black" stroke-width="1" fill="none" cx="128.5" cy="323.5" rx="30" ry="30"/> <text x="115.5" y="329.5" font-family="Times New Roman, DejaVu Serif, Noto Serif, serif" font-size="20">acc</text> <ellipse stroke="black" stroke-width="1" fill="none" cx="128.5" cy="323.5" rx="24" ry="24"/> <ellipse stroke="black" stroke-width="1" fill="none" cx="321.5" cy="186.5" rx="30" ry="30"/> <ellipse stroke="black" stroke-width="1" fill="none" cx="471.5" cy="186.5" rx="30" ry="30"/> <ellipse stroke="black" stroke-width="1" fill="none" cx="471.5" cy="68.5" rx="30" ry="30"/> <ellipse stroke="black" stroke-width="1" fill="none" cx="673.5" cy="68.5" rx="30" ry="30"/> <ellipse stroke="black" stroke-width="1" fill="none" cx="673.5" cy="186.5" rx="30" ry="30"/> <path stroke="black" stroke-width="1" fill="none" d="M 166.275,159.703 A 22.5,22.5 0 1 1 192.725,159.703"/> <!-- use numeric entity → for “→” --> <text x="141.5" y="110.5" font-family="Times New Roman, DejaVu Serif, Noto Serif, serif" font-size="20"> x → x, R </text> <polygon fill="black" stroke-width="1" points="192.725,159.703 201.473,156.17 193.382,150.292"/> <polygon stroke="black" stroke-width="1" points="103.5,186.5 149.5,186.5"/> <polygon fill="black" stroke-width="1" points="149.5,186.5 141.5,181.5 141.5,191.5"/> <polygon stroke="black" stroke-width="1" points="169.034,214.615 138.966,295.385"/> <polygon fill="black" stroke-width="1" points="138.966,295.385 146.443,289.632 137.071,286.143"/> <!-- blank symbol: use numeric entity for □ --> <text x="-1.5" y="252.5" font-family="Times New Roman, DejaVu Serif, Noto Serif, serif" font-size="20"> □ → □, R </text> <polygon stroke="black" stroke-width="1" points="209.5,186.5 291.5,186.5"/> <polygon fill="black" stroke-width="1" points="291.5,186.5 283.5,181.5 283.5,191.5"/> <text x="211.5" y="207.5" font-family="Times New Roman, DejaVu Serif, Noto Serif, serif" font-size="20"> a → x, R </text> <path stroke="black" stroke-width="1" fill="none" d="M 308.275,159.703 A 22.5,22.5 0 1 1 334.725,159.703"/> <text x="233.5" y="110.5" font-family="Times New Roman, DejaVu Serif, Noto Serif, serif" font-size="20"> <tspan x="233.5" dy="0">a → a, R</tspan> <tspan x="233.5" dy="22">x → x, R</tspan> </text> <polygon fill="black" stroke-width="1" points="334.725,159.703 343.473,156.17 335.382,150.292"/> <polygon stroke="black" stroke-width="1" points="351.5,186.5 441.5,186.5"/> <polygon fill="black" stroke-width="1" points="441.5,186.5 433.5,181.5 433.5,191.5"/> <text x="357.5" y="207.5" font-family="Times New Roman, DejaVu Serif, Noto Serif, serif" font-size="20"> b → x, L </text> <path stroke="black" stroke-width="1" fill="none" d="M 484.725,213.297 A 22.5,22.5 0 1 1 458.275,213.297"/> <text x="384.5" y="275.5" font-family="Times New Roman, DejaVu Serif, Noto Serif, serif" font-size="20"> <tspan x="384.5" dy="0">a → a, L</tspan> <tspan x="384.5" dy="22">x → x, L</tspan> </text> <polygon fill="black" stroke-width="1" points="458.275,213.297 449.527,216.83 457.618,222.708"/> <polygon stroke="black" stroke-width="1" points="471.5,156.5 471.5,98.5"/> <polygon fill="black" stroke-width="1" points="471.5,98.5 466.5,106.5 476.5,106.5"/> <text x="476.5" y="133.5" font-family="Times New Roman, DejaVu Serif, Noto Serif, serif" font-size="20"> □ → □, R </text> <path stroke="black" stroke-width="1" fill="none" d="M 441.632,69.43 A 22.5,22.5 0 1 1 452.593,45.358"/> <text x="325.5" y="36.5" font-family="Times New Roman, DejaVu Serif, Noto Serif, serif" font-size="20"> x → x, R </text> <polygon fill="black" stroke-width="1" points="452.593,45.358 453.003,35.933 444.301,40.86"/> <polygon stroke="black" stroke-width="1" points="501.5,68.5 643.5,68.5"/> <polygon fill="black" stroke-width="1" points="643.5,68.5 635.5,63.5 635.5,73.5"/> <text x="533.5" y="59.5" font-family="Times New Roman, DejaVu Serif, Noto Serif, serif" font-size="20"> a → x, R </text> <polygon stroke="black" stroke-width="1" points="673.5,98.5 673.5,156.5"/> <polygon fill="black" stroke-width="1" points="673.5,156.5 678.5,148.5 668.5,148.5"/> <text x="678.5" y="133.5" font-family="Times New Roman, DejaVu Serif, Noto Serif, serif" font-size="20"> x → x, L </text> <path stroke="black" stroke-width="1" fill="none" d="M 655.417,210.421 A 298.677,298.677 0 0 1 197.583,210.421"/> <polygon fill="black" stroke-width="1" points="197.583,210.421 198.89,219.764 206.554,213.341"/> <text x="352.5" y="338.5" font-family="Times New Roman, DejaVu Serif, Noto Serif, serif" font-size="20"> □ → □, R </text> </svg> ##### 类型 2: **逆序结构判定(回文)** 对于 $L_2 = \{w \in \{0, 1\}^{*} | w = w^{R } \}$ 设计思路: - 读取最左边的字符,记住它是 0 还是 1(通过状态来记忆,相当于走到不同状态分支)。标记 - 然后移动到最右边未被标记的字符,检查其是否与左边的一致。如果一致,删掉右边这个字符并移回最左边; - 注意到奇数长度的串需要特别判断:如果从右边往左边扫的时候遇到空格了,可以直接进入 acc 状态 <?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "https://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg width="800" height="600" version="1.1" xmlns="http://www.w3.org/2000/svg"> <ellipse stroke="black" stroke-width="1" fill="none" cx="103.5" cy="257.5" rx="30" ry="30"/> <ellipse stroke="black" stroke-width="1" fill="none" cx="773.5" cy="257.5" rx="30" ry="30"/> <text x="760.5" y="263.5" font-family="Times New Roman" font-size="20">acc</text> <ellipse stroke="black" stroke-width="1" fill="none" cx="773.5" cy="257.5" rx="24" ry="24"/> <ellipse stroke="black" stroke-width="1" fill="none" cx="207.5" cy="108.5" rx="30" ry="30"/> <ellipse stroke="black" stroke-width="1" fill="none" cx="207.5" cy="400.5" rx="30" ry="30"/> <ellipse stroke="black" stroke-width="1" fill="none" cx="495.5" cy="150.5" rx="30" ry="30"/> <ellipse stroke="black" stroke-width="1" fill="none" cx="495.5" cy="371.5" rx="30" ry="30"/> <ellipse stroke="black" stroke-width="1" fill="none" cx="672.5" cy="150.5" rx="30" ry="30"/> <ellipse stroke="black" stroke-width="1" fill="none" cx="672.5" cy="371.5" rx="30" ry="30"/> <polygon stroke="black" stroke-width="1" points="41.5,257.5 73.5,257.5"/> <polygon fill="black" stroke-width="1" points="73.5,257.5 65.5,252.5 65.5,262.5"/> <path stroke="black" stroke-width="1" fill="none" d="M 75.057,248.335 A 22.5,22.5 0 1 1 93.474,229.349"/> <text x="-27.5" y="201.5" font-family="Times New Roman" font-size="20">x \to x, R</text> <polygon fill="black" stroke-width="1" points="93.474,229.349 97.028,220.61 87.177,222.325"/> <polygon stroke="black" stroke-width="1" points="133.5,257.5 743.5,257.5"/> <polygon fill="black" stroke-width="1" points="743.5,257.5 735.5,252.5 735.5,262.5"/> <text x="364.5" y="278.5" font-family="Times New Roman" font-size="20">space \to space, R</text> <polygon stroke="black" stroke-width="1" points="120.671,232.9 190.329,133.1"/> <polygon fill="black" stroke-width="1" points="190.329,133.1 181.651,136.798 189.851,142.522"/> <text x="72.5" y="175.5" font-family="Times New Roman" font-size="20">0 \to x, R</text> <polygon stroke="black" stroke-width="1" points="121.145,281.762 189.855,376.238"/> <polygon fill="black" stroke-width="1" points="189.855,376.238 189.193,366.827 181.106,372.709"/> <text x="72.5" y="348.5" font-family="Times New Roman" font-size="20">1 \to x, R</text> <polygon stroke="black" stroke-width="1" points="237.186,112.829 465.814,146.171"/> <polygon fill="black" stroke-width="1" points="465.814,146.171 458.619,140.069 457.176,149.964"/> <text x="305.5" y="113.5" font-family="Times New Roman" font-size="20">space \to space, R</text> <polygon stroke="black" stroke-width="1" points="237.349,397.494 465.651,374.506"/> <polygon fill="black" stroke-width="1" points="465.651,374.506 457.19,370.332 458.192,380.282"/> <text x="292.5" y="413.5" font-family="Times New Roman" font-size="20">space \to space, R</text> <polygon stroke="black" stroke-width="1" points="525.5,150.5 642.5,150.5"/> <polygon fill="black" stroke-width="1" points="642.5,150.5 634.5,145.5 634.5,155.5"/> <text x="545.5" y="141.5" font-family="Times New Roman" font-size="20">0 \to x, L</text> <path stroke="black" stroke-width="1" fill="none" d="M 482.275,123.703 A 22.5,22.5 0 1 1 508.725,123.703"/> <text x="457.5" y="74.5" font-family="Times New Roman" font-size="20">x \to x, L</text> <polygon fill="black" stroke-width="1" points="508.725,123.703 517.473,120.17 509.382,114.292"/> <path stroke="black" stroke-width="1" fill="none" d="M 508.725,398.297 A 22.5,22.5 0 1 1 482.275,398.297"/> <text x="457.5" y="460.5" font-family="Times New Roman" font-size="20">x \to x, L</text> <polygon fill="black" stroke-width="1" points="482.275,398.297 473.527,401.83 481.618,407.708"/> <polygon stroke="black" stroke-width="1" points="525.5,371.5 642.5,371.5"/> <polygon fill="black" stroke-width="1" points="642.5,371.5 634.5,366.5 634.5,376.5"/> <text x="545.5" y="392.5" font-family="Times New Roman" font-size="20">1 \to x, L</text> <path stroke="black" stroke-width="1" fill="none" d="M 659.275,123.703 A 22.5,22.5 0 1 1 685.725,123.703"/> <text x="540.5" y="73.5" font-family="Times New Roman" font-size="20">x \to x, L / 0 \to 0 L / 1 \to 1, L</text> <polygon fill="black" stroke-width="1" points="685.725,123.703 694.473,120.17 686.382,114.292"/> <path stroke="black" stroke-width="1" fill="none" d="M 685.725,398.297 A 22.5,22.5 0 1 1 659.275,398.297"/> <text x="538.5" y="460.5" font-family="Times New Roman" font-size="20">x \to x, L / 0 \to 0, L / 1 \to 1, L</text> <polygon fill="black" stroke-width="1" points="659.275,398.297 650.527,401.83 658.618,407.708"/> <polygon stroke="black" stroke-width="1" points="523.257,360.118 745.743,268.882"/> <polygon fill="black" stroke-width="1" points="745.743,268.882 736.444,267.291 740.238,276.544"/> <text x="484.5" y="304.5" font-family="Times New Roman" font-size="20">space \to space, R</text> <polygon stroke="black" stroke-width="1" points="523.498,161.276 745.502,246.724"/> <polygon fill="black" stroke-width="1" points="745.502,246.724 739.832,239.184 736.24,248.517"/> <text x="485.5" y="226.5" font-family="Times New Roman" font-size="20">space \to space, R</text> <polygon stroke="black" stroke-width="1" points="643.017,156.044 132.983,251.956"/> <polygon fill="black" stroke-width="1" points="132.983,251.956 141.769,255.391 139.921,245.563"/> <text x="272.5" y="187.5" font-family="Times New Roman" font-size="20">space \to space, R</text> <polygon stroke="black" stroke-width="1" points="643.085,365.607 132.915,263.393"/> <polygon fill="black" stroke-width="1" points="132.915,263.393 139.777,269.868 141.742,260.062"/> <text x="269.5" y="342.5" font-family="Times New Roman" font-size="20">space \to space, R</text> </svg> ##### 类型 3:加法 对于 $L_3 = \{a^ib^jc^k | i + k = j, i, j, k \geq 1\}$ 设计思路: - 可以先匹配 *a* 和 *b*。每次划掉一个 *a*,对应划掉一个 *b*。当 *a* 全部划掉后,继续匹配 *c* 和剩余的 *b*。如果 *c* 耗尽时 *b* 也刚好耗尽,则接受。 ##### 类型 4: 幂次判定 对于 $L_4 = \{a^n | n = 2^k, k \geq 0\}$ 设计思路: - 通过重复“除以 2”的过程。 - 从左到右扫描,每隔一个 *a* 划掉一个 *a*(保留一半)。 - 如果扫描过程中发现总数是奇数(且总数大于1),则拒绝。 - 扫描完一轮后,将读写头移回开头,重复步骤 1。 - 如果最后只剩下一个 *a*,则接受。 #### Problem 4b: 设计 TM (Computation) 由于TM会在tape上写写画画(称之为 side effect),故可以用来做一些 computation 任务 ##### 类型 1: 前驱后继 作业已经设计过一个前驱了,现在来考虑一下后继。 主要的问题都是: - 低位在右边 - 考虑进位 设计思路: **设计提示:** ◦ 这是 Q2x 的逆运算。你需要先将读写头移动到最右端的 LSB。 ◦ 从右向左扫描:如果你看到 `1`,将其变为 `0` 并继续向左进位(Carry);如果你看到 `0`,将其变为 `1` 并停止(进入 Halt 状态)。 ◦ **边界情况:** 如果移动到最左边还是进位(例如 `11` + 1),你需要处理溢出,可能需要整体右移数据或在左边插入一个 `1`。 <?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "https://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg width="800" height="400" version="1.1" xmlns="http://www.w3.org/2000/svg"> <ellipse stroke="black" stroke-width="1" fill="none" cx="126.5" cy="267.5" rx="30" ry="30"/> <ellipse stroke="black" stroke-width="1" fill="none" cx="353.5" cy="267.5" rx="30" ry="30"/> <ellipse stroke="black" stroke-width="1" fill="none" cx="650.5" cy="267.5" rx="30" ry="30"/> <text x="637.5" y="273.5" font-family="Times New Roman" font-size="20">acc</text> <ellipse stroke="black" stroke-width="1" fill="none" cx="650.5" cy="267.5" rx="24" ry="24"/> <polygon stroke="black" stroke-width="1" points="29.5,267.5 96.5,267.5"/> <polygon fill="black" stroke-width="1" points="96.5,267.5 88.5,262.5 88.5,272.5"/> <path stroke="black" stroke-width="1" fill="none" d="M 108.12,243.938 A 22.5,22.5 0 1 1 134.022,238.579"/> <text x="17.5" y="186.5" font-family="Times New Roman" font-size="20">any \to any, R</text> <polygon fill="black" stroke-width="1" points="134.022,238.579 141.872,233.347 132.758,229.23"/> <polygon stroke="black" stroke-width="1" points="156.5,267.5 323.5,267.5"/> <polygon fill="black" stroke-width="1" points="323.5,267.5 315.5,262.5 315.5,272.5"/> <text x="166.5" y="288.5" font-family="Times New Roman" font-size="20">space \to space, L</text> <path stroke="black" stroke-width="1" fill="none" d="M 340.275,240.703 A 22.5,22.5 0 1 1 366.725,240.703"/> <text x="315.5" y="191.5" font-family="Times New Roman" font-size="20">1 \to 0, L</text> <polygon fill="black" stroke-width="1" points="366.725,240.703 375.473,237.17 367.382,231.292"/> <polygon stroke="black" stroke-width="1" points="383.5,267.5 620.5,267.5"/> <polygon fill="black" stroke-width="1" points="620.5,267.5 612.5,262.5 612.5,272.5"/> <text x="398.5" y="288.5" font-family="Times New Roman" font-size="20">0 \to 1, L / space \to 1, L</text> </svg> ##### 类型 2: **一进制转二进制 (Unary to Binary Conversion)** 双带(2-tape)TM 设计思路: 这道题可以直接复用 **Q1** 的逻辑作为子程序(Subroutine)。 ◦ **策略:** 纸带 2 作为一个计数器,初始当作 `0`。读写头在纸带 1 上每读到一个 `x`,就在纸带 2 上执行一次“加 1”操作(调用 Q1 的逻辑)。 ◦ 当纸带 1 的 `x` 读完时,纸带 2 上的内容即为结果。 其他的我感觉考试也不可能出太过分了,据说去年出了一个去模,我感觉思路应该类似于辗转相除法。如果出了我就认账。 最后修改:2025 年 12 月 29 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请随意赞赏