VisFormalLang 形式语言可视化

第 3 章 有限接受器

| 关于   英文版   «  2.2. 数学证明技巧   ::   目录   ::   3.2. 非确定性有限自动机  »

3.1. 确定有限接受器

3.1.1. DFA:确定有限接受器

我们从最简单的机器开始:确定有限接受器 (DFA)。这台机器可以从左到右处理输入字符串(输入显示在一条纸带上)。它有一个控制单元(包含若干状态),并且规定了:当处于给定状态、当前纸带方格上为给定符号时,应该如何行动。我们唯一能"做"的就是在移到右边下一个字符之前改变状态。也就是说,接受器不会修改纸带上的内容。

这里的 确定的 一词有特定的含义:当 DFA 处于给定状态时,对任何给定的输入符号,它都只有一种可以做的事。这与 非确定的 机器形成对比,后者在处于给定状态、看到给定符号时,可能有多种可选的处理方式。我们稍后再讨论非确定自动机。

在处理完字符串的所有字符之后,DFA 可以回答"是"或"否"。例如,一台用于检查字符串是否为合法整数的 DFA,当输入为 6789 时应输出"是"。一台用于检查字符串是否为合法 C++ 变量名的 DFA,当输入为 SUM 时应输出"是"。

备注

在继续阅读之前先想一想:我们需要哪些信息来刻画/描述/定义一个给定的 DFA?我们希望信息足够多,以便能够"构建"这台机器,但也仅此而已。

将 DFA 定义为 \((Q, \Sigma, \delta, q_0, F)\) ,其中

  • \(Q\) 是状态的有限集合

  • \(\Sigma\) 是输入字母表(有限集合)

  • \(\delta: Q \times\Sigma \rightarrow Q\) 。一组形如 \((q_i, a) \rightarrow q_j\) 的转移,含义是:当处于状态 \(q_i\) 时,若看到字母 \(a\) ,就消耗掉它并转移到状态 \(q_j\) 。

  • \(q_0\) 是初始状态( \(q_0 \in Q\) )

  • \(F \subseteq Q\) 是终态集合

我们的解释是:如果 DFA 在处理某个输入字符串结束时处于终态,就认为它对该字符串输出"是";如果在处理结束时不在终态,就认为它输出"否"。

DFA 是一台能力不大的简单机器。我们会看到,关于字符串,它有许多问题无法回答。例如,它无法判断 \(((9+5)+a)\) 是否为合法的算术表达式。

3.1.1.1. 示例

下面是一个接受偶二进制数的 DFA 的图形化展示。

我们可以为这些状态赋予语义:当已经处理的数字构成奇数时,机器处于状态 \(q_0\) ;当已经处理的数字构成偶数时,机器处于状态 \(q_1\) 。当然,我们这样去理解它们只是为了帮助自己理解所发生的事情。说这些状态"意味着"什么,并不会改变机器的实际行为。

备注

此时,你应该尝试在 OpenFLAP 中构建这台机器。

形式化定义:

\(M = (Q, \Sigma, \delta, q0, F) =\)

\((\{q0,q1\}, \{0,1\}, \delta, q0, \{q1\})\)

下面是 \(\delta\) 的表格形式:

备注

看看你能不能不看答案就写出这张表。

\[\begin{split}\begin{array}{r|cc} & 0 & 1 \\ \hline q0 & & \\ q1 & & \\ \end{array}\end{split}\]
\[\begin{split}\begin{array}{r|cc} & 0 & 1 \\ \hline q0 & q1 & q0 \\ q1 & q1 & q0 \\ \end{array}\end{split}\]

一次移动的示例:\(\delta(q0, 1) = q0\)

3.1.1.2. DFA 的算法:

从 初始状态 开始,输入在纸带上
q = 当前状态
s = 纸带上的当前符号
while (s != blank) do
\(q = \delta(q,s)\)
s = 纸带上右边下一个符号
if \(q \in F\) then accept
Settings

Proficient Saving... Error Saving
Server Error
Resubmit

DFA 示例:偶数的追踪

现在让我们看看这台机器如何接受/拒绝一些字符串。

Settings

Proficient Saving... Error Saving
Server Error
Resubmit

3.1.1.3. 定义

  • \({\delta}^{*}(q,\lambda)=q\)

    你没有去任何地方,你仍在状态 \(q\)

  • \({\delta}^{*}(q,wa)={\delta}({\delta}^{*}(q,w),a)\)

    先对 \(w\) (某个字符串)整体应用 \(\delta\) ,然后再应用到 \(a\)

  • DFA \(M = (Q, \Sigma, \delta, q_0, F)\) 接受的语言是 \(\Sigma\) 上所有被 \(M\) 接受的字符串的集合。形式化地,

    \[L(M) = \{w\in{\Sigma}^{*}\mid {\delta}^{*}(q_0,w)\in F\}\]

    备注

    画一幅图:从 q0 出发的弧……通向某个终态;任何通向终态的路径都对应一条被接受的字符串。

    这就是 DFA M 所接受的语言。所有由字母表元素构成的字符串,只要从 q0 开始处理完 w 中的所有符号后到达一个终态(接受态),就属于该语言。

  • 不被接受的字符串集合:

    \[\overline{L(M)} = \{w\in{\Sigma}^{*}\mid {\delta}^{*}(q_0,w)\not\in F\}\]

3.1.1.4. 陷阱状态

示例:考虑语言 \(L(M) = \{b^na | n > 0\}\)

备注

这是什么语言?答案:一个或多个 "b" 后面跟着一个 "a"。

所以,下面是一种画法:

备注

问题:我们需要状态 \(q_0\) 吗?

答案:需要。这是为了强制至少有一个 "b"。

注意,严格来说这是不完整的,因为这里有一些转移没有画出来。其思想是:如果我们能够到达一个接受状态,那么该字符串就被接受。但如果发生了图中未画出的转移(或者最终到达了接受状态以外的地方),那么该字符串就不被接受。

为了完整起见,我们可以添加一个或多个"陷阱"状态,并补上所有"额外"的转移。如下所示。

注意,陷阱状态并没有什么"特殊"之处。

给状态起有含义的名字是个好主意!

示例:\(L = \{ w \in \Sigma^* | w\) 含偶数个 a 且含偶数个 b。

备注

其他可以考虑的示例:可以为实数、整数、变量名(取决于规则)等创建 DFA。

示例:创建一个接受偶二进制数且含偶数个 1 的 DFA。

指定标签:
\(q_0\) - 开始,
\(q_1\) - 偶二进制数:偶数个 1,
\(q_2\) - 奇数,奇数个 1,
\(q_3\) - 奇数,偶数个 1

确定性指的是:当机器处于给定状态并看到给定字符时,只能有一种做法。

3.1.1.5. 概念:DFA 的能力

给定的 DFA 可以接受一个字符串集合(语言也不过如此)。所有可能的 DFA 构成一类机器。对于某一类型(某种)有限自动机,该类有限自动机所接受的语言集合称为一个 语言族 。因此,DFA 定义了它们所接受的一个语言族。一种语言是 正则 的,当且仅当存在一个 DFA \(M\) 使得 \(L = L(M)\) 。

   «  2.2. 数学证明技巧   ::   目录   ::   3.2. 非确定性有限自动机  »

关闭窗口