Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
|
lfa:dfa [2018/10/03 11:24] pdmatei |
lfa:dfa [2020/10/19 15:36] (current) pdmatei |
||
|---|---|---|---|
| Line 1: | Line 1: | ||
| ====== Deterministic automata ====== | ====== Deterministic automata ====== | ||
| - | |||
| - | ===== Motivation ===== | ||
| - | |||
| - | In the last lecture, we have shown that, for **each** regular expression $math[e], we can construct an NFA $math[M], such that $math[L(e) = L(M)]. | ||
| - | |||
| - | While NFAs are a computational instrument for establishing acceptance, they **are not an ideal one**. Nondeterminism is difficult to translate per. se. in a programming language. It is also quite inefficient. We illustrate this via our previous example, below. Recall our NFA representation in Haskell: | ||
| - | |||
| - | <code haskell> | ||
| - | data NFA = NFA {delta :: [(Int,Char,Int)], fin :: [Int]} | ||
| - | </code> | ||
| - | |||
| - | The following code checks if a word $math[w] and NFA $math[nfa], whether $math[w\in L(nfa)]. | ||
| - | <code haskell> | ||
| - | check :: String -> NFA -> Bool | ||
| - | check w nfa = chk (w++"!") nfa [0] | ||
| - | where chk (x:xs) nfa set | ||
| - | | (x == '!') && ([s | s <- set, s 'elem' fin nfa] /= []) = True | ||
| - | | set == [] = False | ||
| - | | otherwise = chk xs nfa [s' | s <- set, (s,x,s') <- delta nfa] | ||
| - | </code> | ||
| - | |||
| - | At each step, the procedure builds the set of all successor states $math[s'] which can be reached from **some** current state $math[s], on current input $math[x]. | ||
| - | |||
| - | This procedure can be optimised, if we make the following observations: | ||
| - | * we can //pre-compute// all possible //state-combinations// (and rule-out those which are inaccessible); | ||
| - | * in so doing, we will have **only one transition** from one state-combination to the other; | ||
| - | * the number of state combinations may be exponential in the general case, but we will build them only **once**, not for each word, on each test $math[w\in L(nfa)], as it is done in the above example. | ||
| - | |||
| - | These observations lead us to Deterministic Finite Automata (DFA). More formally, we can easily obtain the definition for DFAs by enforcing the following restriction on the **transition relation** $math[\Delta]: | ||
| - | * $math[\Delta : K \times \Sigma \rightarrow K], | ||
| - | * the function $math[\Delta] is **total** (i.e. it is defined for all possible values in its input). | ||
| - | |||
| - | Thus: | ||
| - | * each transition must occur on a **symbol**, | ||
| - | * exactly **one** transition is possible for each state-symbol combination | ||
| $def[DFA] | $def[DFA] | ||
| - | A **Deterministic Finite Automata** is an NFA, where $math[\Delta : K \times \Sigma \rightarrow K] is a **total** function. In what follows, we write $math[\delta] instead of $math[\Delta] to refer to the transition function of a DFA. | + | A **Deterministic Finite Automata** is a tuple $math[(K,\Sigma,\delta,q_0,F)], where $math[K] is a set of states, $math[\Sigma] is the alphabet, $math[\Delta : K \times \Sigma \rightarrow K] is a **total** transition function. |
| $end | $end | ||
| Line 54: | Line 19: | ||
| We say a word $math[w] is **accepted** by a DFA $math[M] iff $math[(q_0,w)\vdash_M^*(q,\epsilon)] and $math[q\in F] ($math[q] is a final state). | We say a word $math[w] is **accepted** by a DFA $math[M] iff $math[(q_0,w)\vdash_M^*(q,\epsilon)] and $math[q\in F] ($math[q] is a final state). | ||
| $end | $end | ||
| - | |||
| - | Example(s) | ||