VisFormalLang 形式语言可视化

第 4 章 正则语言

| 关于   英文版   «  4.2. 正则文法   ::   目录   ::   5.1. 识别非正则语言  »

4.3. 正则文法的封闭性

4.3.1. 正则文法的封闭性

4.3.1.1. 封闭性概念

定义: 一个集合在某种(二元)运算下是 封闭的,如果每当把该运算应用于该集合的任意两个成员时,结果仍是该集合的成员。

4.3.1.2. 正则语言的封闭性

考虑正则语言 \(L_1\) 和 \(L_2\)。由于它们是正则语言,我们知道存在正则表达式 \(r_1\) 和 \(r_2\),使得 \(L_1 = L(r_1)\) 且 \(L_2 = L(r_2)\)。

这些我们已经知道:[问问自己:我们为什么知道这些?]

  • \(r_1 + r_2\) 是表示 \(L_1 \cup L_2\) 的正则表达式。 因此,正则语言在并(union)运算下是封闭的。

  • \(r_1r_2\) 是表示 \(L_1 L_2\) 的正则表达式。 因此,正则语言在连接(concatenation)运算下是封闭的。

  • \(r_1^*\) 是表示 \(L_1^*\) 的正则表达式。 因此,正则语言在星闭包(star-closure)运算下是封闭的。

定理: 正则语言在补(complementation)运算下是封闭的。

证明:

\(L_1\) 是正则语言 \(\Rightarrow \exists\) 一个 DFA \(M\),使得 \(L_1 = L(M)\)。
构造 DFA \(M'\),使得:
\(M\) 中的终止状态是 \(M'\) 中的非终止状态。
\(M\) 中的非终止状态是 \(M'\) 中的终止状态。
\(w \in L(M') \Longleftrightarrow w \in \bar{L} \Rightarrow\) 在补运算下封闭。

备注

问:为什么用 DFA,NFA 可以吗?答:可以但有困难。它必须是加上陷阱状态(trap states)的完全 NFA。

定理: 正则语言在交(intersection)运算下是封闭的。

证明:

证明这一点的一个简单方法是使用德摩根定律(DeMorgan's Law):

\[L_1 \cap L_2 = \overline{\overline{L_1} \cup \overline{L_2}}\]

另一种方法是通过构造法。

\(L_1\) 和 \(L_2\) 是正则语言,因此存在 DFA \(M_1\) 和 \(M_2\),使得 \(L_1 = L(M_1)\) 且 \(L_2 = L(M_2)\)。
\(L_1 = L(M_1)\) 且 \(L_2 = L(M_2)\)
\(M_1 = (Q, \Sigma, \delta_1, q_0, F_1)\)
\(M_2 = (Q, \Sigma, \delta_2, p_0, F_2)\)

备注

思路是构造一个 DFA,使其仅当 \(M_1\) 和 \(M_2\) 都接受时才接受。

现在,构造 \(M' = (Q', \Sigma, \delta', (q_0, p_0), F')\)
\(Q' = (Q \times P)\)
\(\delta'\):
\(\delta'((q_i, p_j), a) = (q_k, p_l)\),如果
\(\delta_1((q_i, a) = q_k) \in M_1\) 且 \(\delta_2((p_j, a) = p_l) \in M_1\)。
\(F' = \{(q_i, p_j) \in Q' | q_i \in F_1\) 且 \(p_j \in F_2\}\)
\(w \in L(M') \Longleftrightarrow w \in L_1 \cap L_2 \Rightarrow\) 在交运算下封闭

4.3.1.3. 正则语言在这些运算下是封闭的

反转(Reversal): \(L^R\)

差(Difference): \(L_1 - L_2\)

右商(Right quotient):

定义: \(L_1 \backslash L_2 = \{x\ |\ xy \in L_1\ \mbox{for some}\ y \in L_2\}\)

换句话说,它是 \(L_1\) 中合适字符串的前缀。

定理: 如果 \(L_1\) 和 \(L_2\) 是正则的,那么 \(L_1 \backslash L_2\) 是正则的。

证明: (概要)

存在一个 DFA \(M = (Q, \Sigma, \delta, q_0, F)\),使得 \(L_1 = L(M)\)。

构造 DFA \(M'=(Q, \Sigma, \delta, q_0, F')\) (除了终止状态外,与 \(M\) 等价)。

对每个状态 \(i\) 执行
把 \(i\) 作为开始状态(表示 \(L_i'\))
如果 \(L_i' \cap L_2 \ne \emptyset\),那么
把 \(q_i\) 放入 \(M'\) 中的 \(F'\)

备注

非空意味着在开始状态与某个终止状态之间存在一条路径。

证毕。

同态(Homomorphism):

定义: 设 \(\Sigma, \Gamma\) 是字母表。同态是一个函数 \(h : \Sigma \rightarrow \Gamma^*\)

同态的意思是:用一个字符串替换单个字母。

4.3.1.4. 关于正则语言的问题

\(L\) 是一个正则语言。

  • 给定 \(L, \Sigma, w \in \Sigma^*\),\(w \in L\) 吗?

    答案:构造一个 FA,并测试它是否接受 \(w\)。

  • \(L\) 是空的吗?

    例:\(L = \{a^nb^m | n > 0, m > 0\} \cap \{b^na^m | n > 1, m > 1\}\) 是空的。

    构造一个 FA。如果从开始状态到某个终止状态存在一条路径,那么 \(L\) 不是空的。

    备注

    从开始状态出发,对图进行深度优先搜索。

  • \(L\) 的补是正则的吗?

    答案:只需取 DFA,并把终止状态与非终止状态互换。

    这很容易!但我们会在其他情境中看到,判断补是否正则并不总是这么简单。

  • \(L\) 是无限的吗?

    构造一个 FA。判断从开始状态到终止状态的路径上,是否有某个顶点是某个环(cycle)的基。如果是,那么 \(L\) 是无限的。

    注意:DFA 中环(cycle)这个概念以后会很重要!

  • \(L_1 = L_2\) 吗?

    构造 \(L_3 = (L_1 \cap \bar{L_2}) \cup (\bar{L_1} \cap L_2)\)。如果 \(L_3 = \emptyset\),那么 \(L_1 = L_2\)。

    同样,在其他情境中,两个计算表示是否做同样的事情可能是无法回答的。例如,我们将证明:一般而言,无法判定两个程序是否做同样的事情。

4.3.1.5. 小结:如何证明一种语言是正则的?

我们的工具箱里有若干方法。

  • 写出接受该语言的 DFA。

  • 写出接受该语言的 NFA。

  • 写出接受该语言的正则表达式。

  • 写出接受该语言的正则文法。

  • 用已知对正则语言封闭的运算符操作一个或多个已知正则语言,来定义该语言。

   «  4.2. 正则文法   ::   目录   ::   5.1. 识别非正则语言  »

关闭窗口