Afternoon Tea - 形式语言与自动机

数学证明是一首叙事诗。

—— 知乎用户 “cyb 酱” 的曾使用的签名

这里是 Nickel 自学离散数学中“形式语言与自动机”的相关内容时的笔记。由于是单纯的看书自学,就拉来了 Windy 一起学习,以减弱 消除 笔记的正式性,可以看做是一个随笔,这也意味这学校开设这门课程时会再有一个正式的笔记。

这里是基于上海科学技术文献出版社出版的《离散数学》来学习相关知识点的,如果之后看情况可能会揉进一些《算法导论》中的相关内容。根据书上内容,本篇只会介绍最简单的形式语言——正则语言以及有限自动机。

由于 \(\LaTeX\) 公式中似乎没有数学书上幂集符号所对应的公式,故使用 \mathcal{P},即 \(\mathcal{P}\) 代替。

\[\newcommand{\lvert}{\left\vert} \newcommand{\rvert}{\right\vert} \newcommand{\cP}{\mathcal{P}} \newcommand{\bN}{\mathbf{N}} \newcommand{\Emp}{\mathsf{\Phi}} \newcommand{\emp}{\varnothing} \rule{750px}{1px} \]

Part 1 串和语言

W:好久没和 Nickel 一起学习了,让我们来看 Nickel 一直想学的内容吧,(翻书)第一节是“串和语言”看来书上想让我们从语言的定义本身学起。

N:看来是的,我曾看过《算法导论》中关于语言的相关内容,而书上似乎并没有很快给出语言的定义,它先告诉我们任意语言都是使用一些字符拼成的单词和句子相连接组成的。然后它将“单词”,“句子”抽象成字符串,并定义任意个符号组成的集合为字母表,其中的元素称为字母。通常我们使用小写字母表示字母,使用大写字母表示字母表。

W:这里还强调我们只讨论为有限集的字母表。接下来是的严格定义:由字母表 \(V\) 中有限个字母组成的序列,并将串 \(w\) 中所含字符的个数称为串的长度,记作 \(\lvert w \rvert\),规定空串记作 \(\lambda\),其长度为 0。

N:感觉我们说话的语气好像自己没有学过字符串似的,不过下面就似乎很有趣了,为了表示所有长度为 \(k\) 的串组成的集合,我们可以将这些串看成一个个 \(k\) 元组,这很容易使我们想起笛卡儿积,所以我们用 \(V^k\) 就可以表示所有长度为 \(k\) 的串组成的集合了!

W:看来 Nickel 几个月来将这章前所有知识都过了一遍还是有一定好处的。可惜的是这样无法定义由空串组成的集合,所以要单独规定 \(V^0\) 为只有空串的集合,也可记作 \(\Lambda\)。有了这些就可以再形式化的定义 \(V^+\) 为所有非空串组成的集合,\(V^*\) 为所有串组成的集合。当然上述讨论的所有串都是 \(V\) 上的串。

N:和《算法导论》中似乎对上了,不过《算法导论》中似乎是用 \(\Sigma\) 表示的字母表。我们可以看到 \(V^+, V^*\) 都是可数集。当然了,有集合,那么怎么能少了运算呢?我们定义在 \(V^*\) 上的二元运算连接 \(\circ\) 如下:两个串 \(w = u_1 u_2 \cdots u_m, \varphi = v_1 v_2 \cdots v_n\) 的连接 \(w \circ \varphi\) 也是一个串,为 \(u_1 u_2 \cdots u_m v_1 v_2 \cdots v_n\)。我们将其简记为 \(w \varphi\),而 \(w, \varphi\) 分别称为 \(w \varphi\) 的前缀后缀,当 \(w \ne \lambda\) 时,则其可称为 \(w \varphi\) 的真前缀,同样当 \(\varphi \ne \lambda\) 时,\(\varphi\) 可称为 \(w \varphi\) 的真后缀。居然可以这样定义前缀后缀,感觉真是奇特。

W:当然我们只要能注意到 \(\lambda\) 为代数系统 \(\langle V^*, \circ \rangle\) 上的幺元,就不难发现该代数系统为一个独异点,并且其不可交换。连接运算的性质也很好注意到:\(\lvert w \varphi \rvert = \lvert w \rvert + \lvert \varphi \rvert\)。

N:当然由于 \(w\) 是可结合的,所以我们定义 \(w^k\) 为 \(\begin{matrix} k \\ \overbrace{w \circ w \circ \cdots \circ w} \end{matrix}\),即 \(w\) 的 \(k\) 次重复连接。当然我们再定义一种运算,求逆运算。称一个串 \(w = u_1 u_2 \cdots u_m\) 的逆为 \(w' = u_m u_{m - 1} \cdots u_1\)。显然此运算有以下性质:

\[\lambda = \lambda' \\ (w')' = w \\ w = \varphi \psi \Leftrightarrow w' = \psi' \varphi' \]

当一个串满足 \(w = w'\) 时,称为回文。当我看到书上使用 \('\) 表示串的逆时,我是拒绝的。

W:看来 Nickel 对不能随便使用加 ' 的变量这件事很敏感呢。不过有了这些知识,我们终于可以定义语言了,我们定义有限字母表 \(V\) 所生成的集合 \(V^*\) 的任意一个子集为 \(V\) 上的一个语言。语言通常用 \(L\) 表示。而字母表 \(V\) 上所有语言组成的集合正好就是幂集 \(\cP(V^*)\)。由于 \(V^*\) 是可数个有限集的并,所以 \(V^*\) 为可数集。即 \(V^*\) 和自然数集 \(\bN\) 等势,所以我们有 \(K[\cP(V^*)] = \aleph\),即 \(\cP(V^*)\) 为不可数集。而当 \(V = \emp\) 时,\(V\) 上仅有空语言 \(\Emp\) 一种语言。

N:而由于语言是集合,所以集合上的运算都可以作用在语言上。而语言是由串构成的,故串的连接运算也可定义在语言上,故定义语言 \(L_1, L_2\) 的连接运算为 \(L_1 \circ L_2 = \{w \varphi | w \in L_1 \and \varphi \in L_2 \}\),我们将其简记为 \(L_1 L_2\),而且由于串的连接是不可交换的,故语言的连接也不可交换。并且跟串一样,\(\langle \cP(V^*), \circ\rangle\) 是一个独异点。

W:那我们就来看一下这个代数系统的性质吧,设 \(A, B, C, D\) 是在 \(V\) 上的任意语言,则:

\[A \Lambda = \Lambda A = A \\ (A \subseteq B) \and (C \subseteq D) \Rightarrow AC \subseteq BD \\ A (B \cup C) = AB \cup AC \\ (B \cup C) A = BA \cup CA \\ A (B \cap C) \subseteq AB \cap AC \\ (B \cap C) A \subseteq BA \cap CA \]

N:最后两个式子似乎有些奇怪呢,让我想一想……

W:感觉可能是如果 \(w, \varphi \in A\) 且 \(w \in B - C, \varphi \in C - B\) 但却可以有 \(w \varphi, \varphi w \in AB \cap AC\) 所导致的呢……

N:好神奇,Windy 也进步不少呢。我们接着往下看吧,语言也有逆运算。语言 \(L\) 的逆 \(L'\) 为 \(\{\varphi' | \varphi \in L\}\),若一个语言满足 \(L = L'\) 则称其为镜像语言,需要注意镜像语言中的串不一定都回文,其实只要保证语言中所有串的逆都在语言中就可以。

W:由于语言的连接运算是可结合的,故定义 \(L^k\) 为 \(\begin{matrix} k \\ \overbrace{L \circ L \circ \cdots \circ L} \end{matrix}\),即 \(L\) 的 \(k\) 次重复连接。并定义 \(L^0 = \Lambda\)。看来下面是重头戏了,要介绍语言的 Kleene 闭包 \(L^*\) 和 + 闭包 \(L^+\) 了!下面是它们的定义:

\[L^* = \bigcup_{k = 0}^{\infty} L^k = \Lambda \cup L \cup L^2 \cup \cdots \\ L^+ = \bigcup_{k = 1}^{\infty} L^k = L \cup L^2 \cup \cdots \]

显然有 \(L^* = L^+ \cup \Lambda\)。我们称一元运算符 \(*\) 为 Kleene star(Kleene 星号)

N:虽然感觉比《算法导论》上讲的要慢,但是好像还是有点晕,我要思考一下……

W:闭包的性质好像有点多啊,不过好多都比较显然,唯一需要笔头写一写才能证出来的是 \((A^* B^*)^* = (A \cup B)^* = (A^* \cup B^*)^*\),今天看来 Nickel 已经很累了呢,我们明天再继续吧。

N:谢谢 Windy,明天第二部分再会 qwq!

上一篇:Ubuntu 查看cpu个数及核心数


下一篇:lscpu