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) | ||