# Deterministic Finite Automaton
以一個 5-tuple 來定義一個有限自動機 Finite Automaton:
$$
(Q,\sum,\delta,q_{0},F)
$$
其中:
- $Q$ 狀態 states 的有限集合
- $\sum$ 有限的字母 alphabet
- $\delta:Q\times \sum \rightarrow Q$ 在當前狀態,得到輸入後決定下一狀態的轉移函數
- $q_{0}\in Q$ 起始狀態 start state
- $F\subseteq Q$ 允許狀態 accept states
:::info
- 起始狀態可以是允許狀態
:::
## 運作方式
給一個字串,然後從 $q_{0}$ 開始,使用 $\delta$ 根據當前狀態還有讀到的字母來決定下一狀態。
例如給個字串 $0123$,則:
$$
q_{0}\rightarrow q_{1}\rightarrow q_{2}\rightarrow q_{3}\rightarrow q_{4}\\
q_{1}=\delta(q_{0},0)\\
q_{2}=\delta(q_{1},1)\\
q_{3}=\delta(q_{2},2)\\
q_{4}=\delta(q_{3},3)\\
$$
# Nondeterministic Finite Automaton / NFA
跟 DFA 類似,只不過 alphabet 是 ${\sum}_{\Large\epsilon}$,可以注意到字母中多了 $\epsilon$,代表空字串,
轉移函數變成:
$$
\delta:Q\times {\sum}_{\Large\epsilon} \rightarrow \mathcal{P}(Q)
$$
其中 $\mathcal{P}(Q)$ 是由所有的狀態構成的可能組合的集合,又叫做 Power Set。
會這樣的原因是,在 NFA 中給予某個輸入後,不是只有一個向外箭頭,而是可能有很多個,因此函數的輸出是一個集合。
## 運作方式
大致也跟 DFA 一樣,不過因為有可能有多條路可以走,所以會以畫出樹狀圖的方式運作,並且:
- 如果當前狀態 $q_{0}$ 得到字母 $a$,所有可以抵達的 ${q_{1},q_{2}...}$ 都畫出來後,如果 ${q_{1},q_{2}...}$ 當中有人有空字串 $\epsilon$ 的向外箭頭,則會將該箭頭指向的下一個狀態加入 ${q_{1},q_{2}...}$ 裡面。
- 如果當前狀態得到字母 $a$ 沒有向外箭頭,代表這個分支「枯萎/死亡」
- 如果得到字母 $a$ 後的所有狀態中有重複的,每種狀態保留一個就好
- 因為只需要代表在該時刻,可以抵達的狀態有哪些
# 允許狀態
如果讀完一個字串後,停留的狀態屬於允許狀態,代表該自動機「允許 accept」該字串。
# Language of Automaton
對於一個有限自動機 $M$,我們將 $M$ 允許的全部字串蒐集起來;這些字串的集合就是有限自動機「辨識出的語言 Recognized Language」
# Regular Language
如果語言 $A$ 有某個 DFA 辨識他,那麼 $A$ 就是個 Regular Language。
因此我們可以知道對於一個 DFA $M$,他所對應的 Language 就是 Regular Language。
# NFA 和等價的 DFA
每一個 NFA 其實都可以建構出一個等價的 DFA,方法就是先弄出 $Q'=\mathcal{P}(Q)$,也就是說由 $Q$ 的所有狀態構成的 Power State。
>Power State 是所有 State 可以組合出的所有可能,如果有 3 個 State 就是 2^3^ 種
然後對每個在 $Q'$ 中的狀態,由於他其實是個子狀態的集合,所以當他得到一個輸入的時候,每個子狀態會得到下一個狀態,他也是個子狀態的集合,所以我們把所有子狀態得到的狀態聯集起來;記得,如果走到的某個狀態有 $\epsilon$ 的向外箭頭,就要繼續走下去。
起始狀態,就跟原本 NFA 的一樣,但是要記得起始狀態也可能有 $\epsilon$ 的向外箭頭,所以也要讓起始狀態變成一個狀態的集合。
允許狀態就是包含原本 NFA 允許狀態的狀態。
這樣一來,對於一個 NFA 辨識的語言 $A$,在上面的 DFA 架構中,因為最終都會走到允許狀態,所以這個新建構出的 DFA 同樣辨識出 $A$。
## Corollary
因為一個 NFA 可以推導出價的 DFA,於是我們便可推得:
$$
\text{Language is regular} \leftrightarrow \text{a NFA recognize it}
$$
---
# Regular Operations
對 Regular Language 的操作,例如聯集,貓咪,跟星星。
但是做了操作之後,有一個重點是要重新證明封閉性。
## 聯集
對於兩個正常語言 $A_{1}$ 跟 $A_{2}$,如果其對應的 NFA 為 $N_{1}$ 跟 $N_{2}$:
- 在 $N_{1}$ 跟 $N_{2}$ 前加入一個共同的 $q_{0}$,並且指向各自 $q_{0}$ 時的輸入是 $\epsilon$
- 這樣一來組成的新的 $N=N_{1}\cup N_{2} \cup {q_0}$,依舊是個 NFA
- 所以也就還是有個正常語言對應他
## 貓咪/連結 Concatenation
跟上面很類似,不過換成 $N_{1}$ 的 $F$ 都要接空字串輸出到 $N_{2}$ 的起始狀態 $q_{2}$,並且要注意:
- $\delta(q,a)=\delta_{1}(q,a)$ 如果 $q\in Q,q \notin F_{1}$
- $\delta(q,a)=\delta_{1}(q,a)$ 如果 $q \in F_{1}$ 且 $a\ne \epsilon$
- $\delta(q,a)=\delta_{1}(q,a)\cup \{q_{2}\}$ 如果 $q \in F_{1}$ 且 $a= \epsilon$
- $\delta(q,a)=\delta_{2}(q,a)$
:::warning
在 $q \in F_{1}$ 且 $a=\epsilon$,可以看到是 $\delta_{1}(q,a)\cup {q_{2}}$,原因是因為 $F_{1}$ 的某些點可能本身就自帶 $\epsilon$ 向外箭頭,要記得考慮原本就有的 $\delta_{1}(q,a)$。
:::
## 星星 Star
把自己的字母複製好幾遍出來,記為 $A_{1}^{*}$。
建構方法直覺蠻簡單的,就是把 $F_{1}$ 的所有狀態都拉一條空字串箭頭到 $q_{1}$。
但是星星操作還有一個重點,它可以是空字串,所以需要稍微修改一下:
- 如果直接把 $q_{1}$ 令作允許狀態
- 有可能其他不被 $A_{1}^{*}$ 認可的字串,繞了一圈又回到起始狀態
因此我們用了一個巧妙的方法,建立一個新的起始狀態 $q_{2}$,他同時也是允許狀態,並且讓他以空字串指向原本的起始狀態 $q_{1},這樣就可以避免上面的問題。
- $\delta(q,a)=\delta_{1}(q,a)$ 如果 $q\in Q,q \notin F_{1}$
- $\delta(q,a)=\delta_{1}(q,a)$ 如果 $q \in F_{1}$ 且 $a\ne \epsilon$
- $\delta(q,a)=\delta_{1}(q,a)\cup \{q_{1}\}$ 如果 $q \in F_{1}$ 且 $a= \epsilon$
- $\delta(q,a)=q_{1}$ 如果 $q=q_{2}$ 且 $a = \epsilon$
- $\delta(q,a)=\emptyset$ 如果 $q =q_{2}$ 且 $a\ne \epsilon$
:::warning
在 $q \in F_{1}$ 且 $a = \epsilon$當中,也會發生跟貓咪一樣的情況。
:::