Skip to content

Commit c5ca4eb

Browse files
committed
docs: add TCS lec06-lec09
1 parent 7cb0d3b commit c5ca4eb

8 files changed

Lines changed: 519 additions & 1 deletion

File tree

docs/config.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ nav:
66
- lec03
77
- lec04
88
- lec05
9+
- lec06
10+
- lec07
11+
- lec08
12+
- lec09
913
- rl:
1014
- fundamentals
1115
- value-based
396 KB
Loading

docs/cs/tcs/assets/lec08-tm.png

359 KB
Loading

docs/cs/tcs/lec05.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,6 @@ DFA 转 NFA 是显然的,考虑 NFA 转 DFA。
7272
:::fold{title="证明" expand}
7373
只需证明 NFA 和正则表达式等等价。右到左显然,考虑左到右。
7474

75-
略。
75+
(在 Lec06 讲的,直觉上是通过删 node 实现,理论上是一个 DP 过程,没有详细记笔记,期末记得看一下视频)
7676
:::
7777
::

docs/cs/tcs/lec06.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
---
2+
title: Lecture 06
3+
---
4+
5+
## Pumping Theorem
6+
7+
::fold{title="**泵引理**:正则表达式的必要条件" success always expand}
8+
若语言 $L$ 是正则的,则存在一个整数 $p \geqslant 1$(称为 **Pumping length**),使得对任意字符串 $w \in L$,只要 $|w| \geqslant p$,就可以将 $w$ 分解为 $w = xyz$,满足:
9+
10+
1. 对任意 $i \geqslant 0$,字符串 $xy^iz \in L$;
11+
2. $|y| > 0$;
12+
3. $|xy| \leqslant p$。
13+
14+
:::fold{title="证明" expand}
15+
设 $M = (K, s, F, \delta)$ 是一个接受 $L$ 的 DFA,令 $p = |K|$(**State 数**)。对任意 $w \in L$,且 $|w| \geqslant p$,考虑 $M$ 处理 $w$ 的过程:
16+
17+
由于 $|w| \geqslant p$,根据抽屉原理,在处理前 $p$ 个字符时,**$M$ 一定会访问某个状态两次**。设这两个位置分别为 $j$ 和 $k$,其中 $0 \leqslant j < k \leqslant p$。
18+
19+
将 $w$ 分解为 $w = xyz$,其中:
20+
21+
- $x$ 是 $w$ 的前 $j$ 个字符;
22+
- $y$ 是从位置 $j$ 到 $k$ 的字符;
23+
- $z$ 是剩余的字符。
24+
25+
由于 $M$ 在处理 $y$ 时从状态 $q$ 回到状态 $q$,因此对于任意 $i \geqslant 0$,字符串 $xy^iz$ 也会被 $M$ 接受。
26+
27+
此外,$|y| = k - j > 0$,且 $|xy| = k \leqslant p$。
28+
:::
29+
30+
:::fold{title="例题" info expand}
31+
_Use pumping theorem to show that $L=\{ww : w\in\{0, 1\}^*\}$ is not regular._
32+
33+
假设 $L$ 是正则的,则存在一个整数 $p \geqslant 1$ 满足泵引理。
34+
35+
选择字符串 $s = 0^p1^p0^p1^p \in L$,显然 $|s| = 4p > p$。根据泵引理,$s$ 可以被分解为 $s = xyz$,满足上述三个条件。由于 $|xy| \leqslant p$,所以 $y$ 只能包含字符 '0'。设 $y = 0^k$,其中 $k > 0$。根据泵引理,对任意 $i \geqslant 0$,字符串 $xy^iz \in L$。选择 $i = 2$,则有:
36+
37+
$$xy^2z = 0^{p+k}1^p0^p1^p$$
38+
39+
显然,$xy^2z \notin L$,因为它不再是形如 $ww$ 的字符串。这与假设 $L$ 是正则的矛盾。因此,语言 $L = \{ww : w\in\{0, 1\}^*\}$ 不是正则的。
40+
:::
41+
::

docs/cs/tcs/lec07.md

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
---
2+
title: Lecture 07
3+
---
4+
5+
之前学的 DFA、NFA、RegExp 的表达能力等价,都很有限,甚至无法表达一些简单的语言,比如 $\{0^n1^n \mid n \geqslant 0\}$。因此本节课尝试对其扩展。
6+
7+
## Pushdown Automaton (PDA)
8+
9+
**PDA = DFA + Stack**(额外加了内存部分)。
10+
11+
**PDA**:$P = (K, \Delta, s, F)$,其中
12+
13+
- $K$、$s$、$F$ 同 DFA;
14+
- $\Delta$ 仍然是转移函数,但变成了 $(K\times\{0,1,e\}\times\{0,1\}^*)\times(K\times\{0,1\}^*)$ 的**有限子集**。其中:
15+
- $K$:当前状态
16+
- $\{0,1,e\}$:当前读入的非确定性 symbol(和 NFA 一致)
17+
- $\{0,1\}^*$:从当前栈顶 pop 出来的串
18+
- $K$:下一个状态
19+
- $\{0,1\}^*$:push 进栈的串
20+
- e.g. $((p,0,110),(q,01))$:如果当前状态为 p,读到 0,且栈顶为 110,则转移到状态 q,并将栈顶的 110 pop 出,push 入 01。
21+
![$((p,0,110),(q,01))$,执行过程可理解为纸带+读写头](./assets/lec07-pda-example.png)
22+
23+
---
24+
25+
**配置(Configuration)**:三元组 $(p, x, \alpha) \in K \times \{0,1\}^* \times \{0,1\}^*$,表示当前状态为 $p$,纸带**剩余**输入串为 $x$(因为之前读入的已经不会影响后续结果了),栈内容为 $\alpha$。
26+
27+
**Yield in one step**:$(p, x, \alpha) \vdash_P (q, y, \beta)$,表示从配置 $(p, x, \alpha)$ 可以通过**一次转移**到达配置 $(q, y, \beta)$,下标 $P$ 表示 PDA。符号 $\vdash_P$ 读作“yields in one step”。
28+
29+
**Yield**:$\vdash_P^*$ 为 $\vdash_P$ 的闭包,表示通过**若干次转移**可以从一个配置到达另一个配置。读作“yields”。
30+
31+
**$P$ accepts $w\in\{0,1\}^*$, if $(s, w, e) \vdash_P^* (f, e, e)$ for some $f \in F$.** 即从初始配置 $(s, w, e)$ 出发,经过若干次转移,可以到达某个接受状态 $f$,且此时纸带和栈均清空。
32+
33+
**Language of $P$** $L(P)$ 为被 $P$ 接受的所有字符串的集合。称 $P$ **decides** $L(P)$。如果语言 $L$ 能被某台 PDA 判定,则称 $L$ 为**上下文无关语言(Context-Free Language, CFL)**
34+
35+
::fold{title="例题" info always expand}
36+
37+
1. 设计 PDA 接受语言 $L = \{w\in\{0,1\}^* \mid \text{\#0's = \#1's in } w\}$(即 0 和 1 个数相同)。
38+
$K = \{q\}$,$s = q$,$F = \{q\}$,$\Delta$ 包含以下转移:
39+
- $((q,0,e), (q,0))$:读到 0,不管栈顶是什么,都 push 入 0;
40+
- $((q,0,1), (q,e))$:读到 0,栈顶为 1,则 pop 出 1(PDA 和 NFA 类似,也能去“猜”,所以和上一条不矛盾);
41+
- $((q,1,e), (q,1))$:读到 1,不管栈顶是什么,都 push 入 1;
42+
- $((q,1,0), (q,e))$:读到 1,栈顶为 0,则 pop 出 0。
43+
2. 设计 PDA 接受语言 $L = \{ww^\text{Reverse} \mid w\in\{0,1\}^*\}$(即任意串拼上其逆序串)。
44+
$K = \{l, r\}$,$s = l$,$F = \{r\}$,$\Delta$ 包含以下转移:
45+
- $((l,0,e), (l,0))$:读到 0,不管栈顶是什么,都 push 入 0;
46+
- $((l,1,e), (l,1))$:读到 1,不管栈顶是什么,都 push 入 1;
47+
- $((l,e,e), (r,e))$:通过 $e$-transition 转移到状态 $r$;
48+
- $((r,0,0), (r,e))$:读到 0,栈顶为 0,则 pop 出 0;
49+
- $((r,1,1), (r,e))$:读到 1,栈顶为 1,则 pop 出 1。
50+
51+
::
52+
53+
---
54+
55+
之前研究的 DFA、NFA、PDA 都属于 **Language Recognizer**,即给定一个字符串,判断其是否属于某个语言。接下来研究 **Language Generator**,即通过某种规则生成语言中的字符串。
56+
57+
研究 **Language Generator** 的一个重要工具是 **语法(Grammar)**
58+
59+
## Context-Free Grammar (CFG)
60+
61+
**CFG**:$G = (V, S, R)$,其中
62+
63+
- $V$:有限符号集合,包括 $\{0,1\}$。其中 $V\setminus\{0,1\}$ 中的符号称为**非终结符(Non-terminal)**,与之相对 $0,1$ 称为**终结符(Terminal)**
64+
- $S \in V\setminus\{0,1\}$:Start Symbol,属于非终结符
65+
- $R \subset (V \setminus \{0,1\}) \times V^*$:有限规则集合(右侧是无穷集,但是要求 $R$ 有限)
66+
67+
---
68+
69+
**Derive in one step**:对 $x, y, u \in V^*$,$A \in V\setminus\{0,1\}$,如果 $(A, u) \in R$,则有 $xAy \Rightarrow_G =xuy$,符号 $\Rightarrow_G$ 读作“derives in one step”。
70+
71+
**Derive**:$\Rightarrow_G^*$ 为 $\Rightarrow_G$ 的闭包,即可以用多次规则替换。
72+
73+
**$G$ generates $w \in \{0,1\}^*$, if $S \Rightarrow_G^* w$.** 即从 Start Symbol $S$ 出发,经过若干次规则替换,可以得到字符串 $w$。
74+
75+
**Language of $G$** $L(G)$ 为被 $G$ 生成的所有字符串的集合。称 $G$ **generates** $L(G)$。
76+
77+
::fold{title="例题" info always expand}
78+
设计 CFG 生成语言 $L = \{w\in\{0,1\}^* \mid w=w^\text{Reverse}\}$(即回文串):
79+
80+
$S \to e \mid 0 \mid 1 \mid 0S0 \mid 1S1$(竖线表示“或”)
81+
::
82+
83+
---
84+
85+
::fold{title="**定理**:PDA 和 CFG 等价" success always expand}
86+
对于语言 $L$,存在 PDA $P$ 接受 $L$ 当且仅当存在 CFG $G$ 生成 $L$。
87+
88+
:::fold{title="证明" expand}
89+
**$P\Leftarrow G$:**
90+
91+
> 思路:1. 非确定性地在栈上构造目标串;2. 读入目标串并与栈上内容相消;3. 若栈空且读完输入串,则接受。
92+
93+
令 $G = (V, S, R)$,构造 $P = (K, \Delta, s, F)$ 如下:
94+
95+
- $K = \{p, q\}$,$s = p$,$F = \{q\}$;
96+
- $\Delta$ 包含以下转移:
97+
- $((p,e,e), (q,S))$:初始时将 $S$ push 入栈,并转移到状态 $q$;
98+
- $((q,e,A), (q,u))$ for $\forall (A,u) \in R$:非确定性地用规则替换栈顶的非终结符 $A$ 为 $u$;
99+
- $((q,a,a), (q,e))$ for $\forall a \in \{0,1\}$:读入输入串并与栈顶内容相消;
100+
101+
---
102+
103+
**$P\Rightarrow G$:**
104+
105+
> 思路:先化简 PDA,然后再构造 CFG。
106+
107+
将 $P$ 化简为满足以下条件的 $P = (K, \Delta, s, F)$:
108+
109+
1. 只有一个接受状态 $f$,即 $F = \{f\}$;
110+
2. 每次转移要么只 push,要么只 pop,而且每次只 push/pop 一个 symbol。
111+
112+
显然任意 PDA 都可以化简为满足上述条件的 PDA。
113+
114+
构造 CFG $G = (V, S, R)$ 如下:
115+
116+
- $V = \{0,1\} \cup \{A_{p,q} \mid p,q \in K\}$,其中 $A_{p,q}$ 为非终结符,表示从状态 $p$ 出发,经过若干次转移,到达状态 $q$ 且栈空的字符串集合,**我们的目标是实现 $A_{p,q} \Rightarrow_G^* w$ iff $(p, w, e) \vdash_P^* (q, e, e)$**
117+
- $S = A_{s,f}$;
118+
- $R$ 包含以下规则:
119+
- **空串规则** $A_{p,p} \to e$;
120+
- **连接规则** $A_{p,q} \to A_{p,r} A_{r,q}$:过程中栈清空,则可以分成两半;
121+
- **Push-pop** $A_{p,q} \to aA_{r,s}b$,如果存在 PDA转移 $((p,a,e),(r,c))$(读入 $a$ 压入 $c$)和 $((s,b,c),(q,e))$(读入 $b$ 弹出 $c$)。
122+
123+
:::
124+
::

docs/cs/tcs/lec08.md

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
---
2+
title: Lecture 08
3+
---
4+
5+
PDA 虽然拓展了 DFA/NFA 的表达能力,但其能力还是有限,例如无法表达 $\{0^n1^n0^n \mid n \geqslant 0\}$(通过 PDA 版本的 Pumping Theorem 证明,没有细讲)。一个更强大的模型是 **图灵机(Turing Machine)**
6+
7+
## 图灵机
8+
9+
**图灵机(Turing Machine, TM)**:$M = (K, \Sigma, s, \delta)$,其中
10+
11+
- $K$、$s$ 同 DFA/PDA;
12+
- $\Sigma$:有限字母表,至少包含 $\{0,1,\triangleright,\sqcup\}$,其中 $\triangleright$ 为**左端标记**,$\sqcup$ 为**空白符**
13+
- $\delta$:转移函数,$\delta: K \times \Sigma \to K \times \Sigma \times \{L, R, S, H\}$,其中
14+
- $K$:当前状态
15+
- $\Sigma$:当前读入的 symbol
16+
- $K$:下一个状态
17+
- $\Sigma$:写入的 symbol(覆盖当前格子)
18+
- $\{L, R, S, H\}$:移动方向,L 表示左移一格,R 表示右移一格,S 表示不动,H 表示停机
19+
20+
**运算过程**:给定输入 $x=x_0x_1\cdots x_{n-1} \in \{0,1\}^*$,图灵机纸带初始内容为 $\triangleright x_0x_1\cdots x_{n-1}\sqcup\sqcup\sqcup\cdots$,读写头初始位置在 $\triangleright$ 上。
21+
22+
![图灵机运算过程](./assets/lec08-tm.png)
23+
24+
- 如果停机:输出 $M(x)$ 为纸带上从 $\triangleright$ 之后开始到第一个 $\sqcup$ 之前的内容;
25+
- 如果不停机:$M(x)$ 记为 $\bot$。
26+
27+
A TM $M$ computes a function $f: \{0,1\}^* \to \{0,1\}^*$ if $\forall x \in \{0,1\}^*$, $M(x) = f(x)$.
28+
29+
所有能被图灵机计算的函数称为**可计算函数(computable function)**
30+
31+
## NAND-TM
32+
33+
我们先考虑更简单的模型 **NAND-TM**
34+
35+
**NAND-TM**(= NAND-CIRC + arrays + loops):
36+
37+
1. 数据类型:
38+
- **下标 $i$**:唯一的整数变量,表示下标;
39+
- **Scalars**:布尔变量;
40+
- **Arrays**:布尔数组,无限长度,所有数组共用相同的下标 $i$;
41+
2. 输入 $X$ 和输出 $Y$ 都是数组
42+
3. 程序**一定以 $\text{MODANDJUMP}(a,b)$ 指令结尾**,作用为修改 $i$ 并跳转到第一行:
43+
- 如果 $a=1$ 且 $b=1$,则 $i \leftarrow i + 1$;
44+
- 如果 $a=0$ 且 $b=1$,则 $i \leftarrow i - 1$;
45+
- 如果 $a=1$ 且 $b=0$,则 $i \leftarrow i$;
46+
- 如果 $a=0$ 且 $b=0$,则停机。
47+
4. 除最后一行外,其他行均为 $z = \text{NAND}(x,y)$,其中 $x,y,z$ 可以是 scalars 或 array 的第 $i$ 个元素
48+
5. 除 $X$ 外,所有变量初始值为 0
49+
50+
**如何区分 $\sqcup$ 和 0?**可以创建数组 $X\text{-nonblank}$,其中 $X\text{-nonblank}[i] = 1$ 则表示 $X[i] \neq \sqcup$,否则为 0。因此传入输入 $X$ 的时候还会同时传入 $X\text{-nonblank}$,输出同理。
51+
52+
::fold{title="**例子**:NAND-TM 实现 INC" info always expand}
53+
**输入:**$X=x_0x_1\cdots x_{n-1}$,表示 $\sum_{i=0}^{n-1} x_i 2^i$。
54+
55+
**要求输出:**$Y=y_0y_1\cdots y_{n-1}y_n$,满足 $\sum_{i=0}^{n} y_i 2^i = \sum_{i=0}^{n-1} x_i 2^i + 1$。
56+
57+
定义辅助标量 carry(表示进位),started(表示是否开始计算)。
58+
59+
```
60+
carry = IF(started, carry, ONE(started))
61+
started = ONE(started)
62+
Y[i] = XOR(X[i], carry)
63+
carry = AND(X[i], carry)
64+
Y-nonblank[i] = ONE(started)
65+
MODANDJUMP(X-nonblank[i], X-nonblank[i])
66+
```
67+
68+
上述 `IF``ONE``XOR``AND` 均可由 NAND 实现。
69+
::
70+
71+
---
72+
73+
::fold{title="**定理**:NAND-TM 和图灵机等价" success always expand}
74+
对于函数 $f: \{0,1\}^* \to \{0,1\}^*$,存在 NAND-TM 程序 $P$ 计算 $f$ 当且仅当存在图灵机 $M=(K, \Sigma, s, \delta)$ 计算 $f$。
75+
76+
:::fold{title="证明" expand}
77+
**$P\Leftarrow M$:**
78+
79+
先考虑如何编码一个图灵机。
80+
81+
- $K$ states $\to$ $\lceil\log|K|\rceil$ scalar variables;
82+
- $\Sigma$ tape symbols $\to$ $\lceil\log|\Sigma|\rceil$ arrays;(例如 $\Sigma=\{0,1,\triangleright,\sqcup\}$,至少需要 $\log_2 4 = 2$ 个数组去编码一整个 tape)
83+
- $\{L, R, S, H\}$ head movements $\to$ 2 extra scalar variables;
84+
- $\delta: \{0,1\}^{\lceil\log|K|\rceil + \lceil\log|\Sigma|\rceil} \to \{0,1\}^{\lceil\log|K|\rceil + \lceil\log|\Sigma|\rceil + 2}$ 是 **finite function**,可以用 NAND-CIRC 实现,记为 P-CIRC。
85+
86+
取出 P-CIRC 计算结果的最后两项(Head movements),传入给 `MODANDJUMP` 指令,从而完成 NAND-TM 的构造。
87+
88+
**$P\Rightarrow M$:**
89+
90+
(就是上面的过程反过来,这里讲得很粗略)
91+
92+
:::
93+
94+
::
95+
96+
## NAND-TM 语法糖
97+
98+
::fold{title="**GOTO** / **WHILE**" info expand}
99+
原理:给定原始程序:
100+
101+
```
102+
1. ?1 = NAND(?1, ?1)
103+
2. ?2 = NAND(?2, ?2)
104+
...
105+
t. ?t = NAND(?t, ?t)
106+
t+1. MODANDJUMP(?, ?)
107+
```
108+
109+
将其行号用变量 `line` 代替:
110+
111+
```
112+
IF line == 1:
113+
?1 = NAND(?1, ?1)
114+
line = 2
115+
IF line == 2:
116+
?2 = NAND(?2, ?2)
117+
line = 3
118+
...
119+
IF line == t:
120+
?t = NAND(?t, ?t)
121+
line = t+1
122+
IF line == t+1:
123+
MODANDJUMP(?, ?)
124+
```
125+
126+
只需要修改 `line` 的值,即可实现任意行号跳转,也即 **GOTO** 指令。
127+
128+
有了 GOTO,就可以实现 **WHILE** 循环。
129+
130+
::
131+
132+
::fold{title="**多 index**" info expand}
133+
例如想访问下标 j 和 k,创建两个 one-hot array `indexJ``indexK`,其中 `indexJ[j] = 1``indexK[k] = 1`,其他位置均为 0。
134+
135+
再创建一个辅助数组 `AtZero`,只在 `AtZero[0] = 1`,其他位置均为 0。
136+
137+
每次要访问下标前,先用 WHILE 循环将 `i` 移动到 0:
138+
139+
```
140+
WHILE (AtZero[i] != 1):
141+
修改 MODANDJUMP 的两个参数,使 i--
142+
```
143+
144+
然后再用 WHILE 循环将 `i` 移动到 j 或 k:
145+
146+
```
147+
WHILE (indexJ[i] != 1):
148+
修改 MODANDJUMP 的两个参数,使 i++
149+
```
150+
151+
::
152+
153+
::fold{title="**多维数组**" info expand}
154+
多维数组是 $\mathbb{N}^n$,是可数集,可以映射到一维数组,直接拿一维数组模拟即可。
155+
::
156+
157+
## NAND-RAM 模型
158+
159+
提供:
160+
161+
1. Bounded integer variables;
162+
2. Index array access;
163+
3. +, -, \*, /, etc.
164+
165+
容易证明 NAND-RAM 和 NAND-TM 等价(只给了 sketch,没细讲),而前者就是现代计算机使用的 RAM 模型。
166+
167+
因此,**图灵机与现代计算机等价**

0 commit comments

Comments
 (0)