Notebook 4: Epsilon-Closure and Epsilon-Removal
Epsilon-Closure & Epsilon-Removal (epsilon-NFA to NFA)
This notebook walks through the epsilon-closure computation and the epsilon-removal algorithm that converts an epsilon-NFA into an equivalent NFA without epsilon-transitions. The running example is the concatenation automaton for the language \(\{ab\}\).
epsilon-NFA states:
- \(q_0\) — initial (non-accepting)
- \(q_1\) — reached from \(q_0\) reading \(a\)
- \(r_0\) — reached from \(q_1\) via the \(\varepsilon\)-edge
- \(r_1\) — accepting
epsilon-NFA transitions: \(\Delta(q_0,a)=\{q_1\}\), \(\Delta(q_1,\varepsilon)=\{r_0\}\), \(\Delta(r_0,b)=\{r_1\}\). All other transitions yield \(\varnothing\).
This epsilon-NFA recognises exactly the language \(\{ab\}\).
Widget 1: Epsilon-Closure Step-by-Step
Click Step → to compute the epsilon-closure for each state.
ε-NFA
ε-Closure Table
| State | ECl(state) |
|---|
Widget 2: Epsilon-Removal Algorithm
Click Step → to step through the construction of the new NFA \(\mathcal{A}' = (Q, \Sigma, \Delta', q_0, F')\) from the epsilon-closures above.
For each state \(q\) and symbol \(a\): \[\Delta'(q, a) = \text{ECl}\!\bigl(\textstyle\bigcup_{p \in \text{ECl}(q)} \Delta(p, a)\bigr)\]
ε-NFA (original)
New NFA Transition Table (Δ')
| State | a | b |
|---|
Widget 3: Word Simulation on Both Automata
Type a word over \(\{a,b\}\) (default ab) and step through it on both the original \(\varepsilon\)-NFA and the resulting NFA side by side, confirming they accept the same words.
ε-NFA — active states
NFA (ε-free) — active states
Simulation trace
| Prefix | ε-NFA active | NFA active | Accepted? |
|---|
What To Notice
The \(\varepsilon\)-closure absorbs free moves into transition targets. Instead of taking an \(a\)-step and then following \(\varepsilon\)-edges, the \(\varepsilon\)-removal construction folds those free moves directly into the transition function: \(\Delta'(q_0, a) = \{q_1, r_0\}\) already includes \(r_0\), which was originally reachable only via \(q_1 \xrightarrow{\varepsilon} r_0\).
The resulting NFA has no \(\varepsilon\)-edges but accepts the same language. Both Widget 3 traces show identical accept/reject verdicts for every word. The language \(\{ab\}\) is preserved exactly.
States \(q_1\) and \(r_0\) become equivalent in the resulting NFA. After \(\varepsilon\)-removal, both \(q_1\) and \(r_0\) have the same outgoing transitions: nothing on \(a\), and \(\{r_1\}\) on \(b\). They are indistinguishable and could be merged by a subsequent minimisation step.
The accepting set \(F'\) can grow. In this example \(\text{ECl}(q_0) \cap F = \varnothing\), so \(F' = F\). But if the initial state could reach an accepting state via \(\varepsilon\)-edges, we would need to add the initial state to \(F'\), making the empty word \(\varepsilon\) accepted.