Epsilon-NFA

Extended NFA with Epsilon-Transitions

epsilon epsilon ----- ....> ----- ....> ===== --> | q0 | ---------- | q1 | ---------- || q2 || ----- ----- ===== | | | a | b v v ----- ----- | q3 | | q4 | ----- -----

CS305 -- Formal Language Theory

Arrow Keys or Space to navigate • Press S to reveal steps

1 / 19

Big Picture: Where Does Epsilon-NFA Fit?

We have now seen DFAs and NFAs. The epsilon-NFA adds one more layer of nondeterminism -- but all three recognize exactly the same class of languages: the regular languages.

Expressive Power (all equivalent!): +===============+ +===============+ +===================+ | DFA | <=> | NFA | <=> | epsilon-NFA | | (deterministic| | (nondetermini-| | (NFA + free moves | | exactly 1 | | stic, set of | | on epsilon) | | move per | | moves per | | | | symbol) | | symbol) | | | +===============+ +===============+ +===================+ ^ | | | +------ can always convert back -------------+ All three define EXACTLY the regular languages.

Key Idea

Adding epsilon-transitions does NOT increase the power of the machine. It only makes designing automata easier and more modular. Any epsilon-NFA can be converted to an equivalent DFA.

2 / 19

Motivation: Why Add Epsilon-Transitions?

The Problem

Sometimes, designing an NFA for a complex language is still painful. We want to:

  • Build small machines for simple sub-languages
  • Glue them together without re-engineering
  • Translate regular expressions to automata mechanically

Analogy: Building with LEGO

Epsilon-transitions are like LEGO connectors: they let you snap small, tested components together into bigger machines without redesigning anything.

Example: L = {an | n ≥ 0} ∪ {bn | n ≥ 0}

Machine for a*: Machine for b*: === a === b ||q1|| --->---+ ||q3|| --->---+ === | | === | | +--<-+ +--<-+ Glue with epsilon: eps === a --> (q0) ....> ||q1|| --->---+ | === | | | +--<-+ | eps === b +.....> ||q3|| --->---+ === | | +--<-+

The epsilon-transitions from q0 let us "choose" which sub-machine to enter -- no input consumed!

3 / 19

What is an Epsilon-Transition?

An epsilon-transition (written as an ε-transition) is a transition that the machine can take without reading any input symbol.

  • The machine "teleports" to another state for free
  • The input head does NOT advance
  • The machine can choose to take it or not (nondeterminism)
Normal transition (reads 'a'): ----- a ----- | q0 | ---> | q1 | ----- ----- ^ reads 'a' from input Epsilon-transition (reads NOTHING): ----- ε ----- | q0 | ....> | q1 | ----- ----- ^ input head stays put!

Analogy: Secret Passages

Think of states as rooms in a castle. Normal transitions are doors that require a key (an input symbol) to pass through. Epsilon-transitions are secret passages -- you can slip through them at any time, for free, without spending a key.

Analogy: Teleporters

Or think of epsilon-transitions as teleporters between states. You can beam yourself to the destination instantly without consuming any resource. And you can chain teleporters: q0 → q1 → q2 all for free!

Warning

ε is NOT a symbol in the alphabet Σ. It represents the empty string. The machine never "reads" an ε from the tape.

4 / 19

Formal Definition: The 5-Tuple

An epsilon-NFA is a 5-tuple E = (Q, Σ, δ, q0, F) where:

ComponentMeaning
QFinite set of states
ΣFinite input alphabet (ε ∉ Σ)
δQ × (Σ ∪ {ε}) → P(Q)
q0Start state (q0 ∈ Q)
FSet of accept states (F ⊆ Q)

The ONE Difference from NFA

In a plain NFA: δ : Q × Σ → P(Q)

In an ε-NFA: δ : Q × (Σ ∪ {ε}) → P(Q)

The transition function now also accepts ε as input. This means the transition table gets an extra column for ε.

Common Mistake

Students sometimes add ε to the alphabet Σ. Don't! ε is never in Σ. The transition function's domain is extended to include ε, but the alphabet itself stays the same.

5 / 19

Example: An Epsilon-NFA

Let's build an ε-NFA for the language L = { strings over {a,b} that start with 'a' or end with 'b' or are empty }.

State Diagram

ε a a,b ---> (q0) ....> (q1) ---> ((q2)) <---+ | | | | +---------+ | | ε b b +.....> (q3) ---> (q4) ---> ((q5)) | ^ | a,b | +---------+ Legend: (qX) = state ....> = epsilon-transition ((qX)) = accept state ---> = symbol transition ---> before q0 = start

Transition Table

Stateabε
→ q0{q1, q3}
q1{q2}
*q2{q2}{q2}
q3{q3}{q4}
q4{q3}{q5}
*q5

Note the ε column -- that's what makes this an ε-NFA, not just an NFA.

6 / 19

Epsilon-Closure: CL(q)

The epsilon-closure of a state q, written CL(q) or ECLOSE(q), is the set of all states reachable from q by following zero or more epsilon-transitions.

Formal Definition

CL(q) is the smallest set such that:

  • Base: q ∈ CL(q)   (you're always reachable from yourself via zero ε-moves)
  • Induction: If p ∈ CL(q) and r ∈ δ(p, ε), then r ∈ CL(q)

Analogy: Wormhole Network

Imagine each ε-transition is a wormhole. CL(q) is the set of all places you can reach from q using only wormholes (no fuel/input needed). You always include your starting location!

Example from Previous Slide

ε ε (q0) ....> (q1) (q0) ....> (q3) CL(q0) = {q0, q1, q3} ^^^^ q0 is always included! CL(q1) = {q1} (no ε-transitions out of q1) CL(q3) = {q3} (no ε-transitions out of q3) CL(q2) = {q2} CL(q4) = {q4} CL(q5) = {q5}

Don't Forget!

A state is always in its own epsilon-closure. CL(q) always contains q itself (zero epsilon-transitions = staying put).

7 / 19

Computing Epsilon-Closure: Step by Step

Use BFS or DFS starting from q, following only ε-transitions.

Interactive ε-Closure Explorer

q0 q1 q2 q3 q4 q5 ε ε ε ε a

Click a state to explore its ε-closure via BFS:

Click a state above to visualize its ε-closure BFS.

BFS Algorithm

ECLOSE(q): result = {q} queue = [q] while queue is not empty: p = dequeue(queue) for each r in δ(p, ε): if r not in result: result = result ∪ {r} enqueue(queue, r) return result

Key Insight

Epsilon-closure is essentially a graph reachability problem. The ε-transitions form a directed graph, and CL(q) is just all nodes reachable from q in that graph.

Watch Out for Cycles!

Epsilon-transitions can form cycles. Always track visited states to avoid infinite loops.

ε ε (q0) ....> (q1) ....> (q0) <-- cycle! CL(q0) = {q0, q1} (still finite)
8 / 19

Epsilon-Closure for Sets: CL(S)

We often need the epsilon-closure of a set of states, not just one state.

Definition

For a set of states S ⊆ Q:

CL(S) = ⋃q ∈ S CL(q)

Just take the union of the epsilon-closures of every state in S.

Example

Using the machine from slide 8: CL(q1) = {q1, q2, q3, q4} CL(q5) = {q5} CL({q1, q5}) = CL(q1) ∪ CL(q5) = {q1, q2, q3, q4} ∪ {q5} = {q1, q2, q3, q4, q5}

Why Do We Need This?

When processing input in an ε-NFA, after reading a symbol we may land in multiple states (just like regular NFA). We need the epsilon-closure of that entire set before processing the next symbol.

Processing input "ab": Start: CL({q0}) <-- closure of a set | | read 'a' v CL( δ(CL({q0}), a) ) <-- closure again! | | read 'b' v CL( δ(..., b) ) <-- and again!

Analogy

After each "real" step (reading a symbol), all your tokens teleport through every wormhole they can reach. You always "expand" via epsilon before and after reading input.

9 / 19

Extended Transition Function: δ̂

The extended transition function δ̂(q, w) tells us the set of states reachable from q after reading string w, accounting for all epsilon-transitions.

Recursive Definition

Base case:

δ̂(q, ε) = CL(q)

On empty input, you can reach anything via epsilon.

Inductive case: For string w = xa (x is a string, a is a symbol):

δ̂(q, xa) = CL( ⋃p ∈ δ̂(q,x) δ(p, a) )

In words: first process x to get a set of states, then from each of those states follow the 'a'-transition, then take the epsilon-closure of all the resulting states.

The Pattern

δ̂(q, w) computation: 1. Start with CL(q) <-- epsilon first! 2. For each symbol a in w: a. From current set S, compute δ(S, a) <-- "real" move b. Take CL of result <-- epsilon again! 3. Final set = δ̂(q, w)
CL(q0) --a--> CL(...) --b--> CL(...) ^^^^^^ ^^^^^^ ^^^^^^ always always always close! close! close!

Difference from NFA

In a plain NFA, δ̂(q, ε) = {q}. In an ε-NFA, δ̂(q, ε) = CL(q), which may include many states!

10 / 19

Interactive ε-NFA Simulator

State Diagram

q0 q1 q2 q3 q4 q5 ε ε a b b

ε-NFA: accepts "ab" or "b"

Simulator

Active: --
Input: --
11 / 19

Acceptance in Epsilon-NFA

Definition

An ε-NFA E = (Q, Σ, δ, q0, F) accepts string w if and only if:

δ̂(q0, w) ∩ F ≠ ∅

That is, after processing w (with all epsilon-closures), at least one of the states we end up in is an accept state.

The language recognized by E is:

L(E) = { w ∈ Σ* | δ̂(q0, w) ∩ F ≠ ∅ }

Important Subtlety: The Empty String

Does the machine accept ε? δ̂(q0, ε) = CL(q0) If CL(q0) contains an accept state, then YES, ε is accepted!

Watch Out

Even if q0 is NOT an accept state, the ε-NFA might still accept the empty string! If any state in CL(q0) is an accept state, then ε ∈ L(E).

Example: ε --> (q0) ....> ((q1)) q0 is NOT an accept state, but: CL(q0) = {q0, q1} q1 ∈ F => ε is accepted!
12 / 19

Converting ε-NFA to Ordinary NFA

We can eliminate all epsilon-transitions to get an equivalent ordinary NFA.

The Algorithm

Given ε-NFA E = (Q, Σ, δE, q0, F), construct NFA N = (Q, Σ, δN, q0, F') where:

  1. New transitions: For each state q and symbol a:
    δN(q, a) = CL( δE( CL(q), a ) )
    First epsilon-close q, then follow a, then epsilon-close again.
  2. New accept states:
    F' = { q ∈ Q | CL(q) ∩ F ≠ ∅ }
    Any state whose epsilon-closure touches an accept state becomes an accept state.
  3. Same start state: q0
Intuition: BEFORE (epsilon-NFA): ε a ε (q0) ...> (q1) --> (q2) ...> ((q3)) AFTER (ordinary NFA): a (q0) --------------------> ((q3)) ^accept? ^always was Check: CL(q0)={q0,q1} Neither is in F, so q0 stays non-accepting. The "a" transition from q0 in the NFA bakes in: ε to q1, then a to q2, then ε to q3.

Don't Forget F'

If CL(q0) ∩ F ≠ ∅, then q0 becomes an accept state in the NFA (even if it wasn't before). This ensures the NFA still accepts ε when the ε-NFA did.

13 / 19

Interactive: ε-NFA → NFA Conversion

ε-NFA Reference

q0 q1 q2 q3 q4 ε a ε b
abε
→ q0{q1}
q1{q2}
q2{q3}
q3{q4}
*q4
Ready. Click "Next Step" to begin.

NFA Being Built

Step 0 / 12
ab
→ q0----
q1----
q2----
q3----
*q4----
14 / 19

Converting ε-NFA Directly to DFA

We can skip the intermediate NFA and go straight from ε-NFA to DFA using a modified subset construction with epsilon-closures baked in.

Modified Subset Construction

  1. Start state: CL(q0) -- not just {q0}!
  2. For each DFA state S (a set of ε-NFA states) and each symbol a ∈ Σ:

    δDFA(S, a) = CL( ⋃q ∈ S δ(q, a) )

    Move on a, then epsilon-close.
  3. Accept states: Any DFA state S where S ∩ F ≠ ∅
  4. Repeat until no new DFA states are generated.
The Process: ε-NFA ====(subset construction)====> DFA with CL() at every step Step 1: DFA start = CL(q0) (may contain multiple states) Step 2: For DFA state {q0, q1, q4} and symbol 'a': Compute: δ(q0,a) ∪ δ(q1,a) ∪ δ(q4,a) = ... some set T ... Then: CL(T) = new DFA state Step 3: Repeat for all symbols, all new DFA states. Step 4: Mark accepting DFA states.

Same Old Subset Construction

It's the same algorithm you already know from NFA → DFA, except you wrap every intermediate result in CL(). Think of it as "subset construction wearing epsilon-closure glasses."

15 / 19

Interactive: ε-NFA → DFA Subset Construction

ε-NFA Reference

q0 q1 q2 q3 ε a b
abε
→ q0{q1}
q1{q2}
q2{q3}
*q3
Ready. Click "Next Step" to begin.

DFA Being Built

Step 0 / 10
DFA Stateε-NFA StatesabAccept?
16 / 19

Challenge Quiz: Does This ε-NFA Accept...?

ε-NFA (from Slide 11)

q0 q1 q2 q3 q4 q5 ε ε a b b

F = {q3, q5}, ε: q0→{q1,q4}

Loading quiz...

Question 1 / 3
17 / 19

Why Epsilon-NFA Matters

1. Regular Expression → NFA

Thompson's Construction converts any regex to an ε-NFA mechanically. Epsilon-transitions are the glue:

Regex: (a|b)* Thompson builds: ε a ε +-->(q1)-->(q2)--+ | | -->((q0)) (q5)--+ | | | +-->(q3)-->(q4)--+ | ε b ε | ^ | | ε (loop back) | +----------------------+

Every regex operator (union, concat, star) maps to an ε-NFA pattern.

2. Modular Machine Construction

Machine for L1: Machine for L2: -->(A)-->((B)) -->(C)-->((D)) L1 ∪ L2 (Union): ε +-->(A)-->((B)) -->(S)--| +-->(C)-->((D)) ε L1 · L2 (Concatenation): ε -->(A)-->(B) ....> (C)-->((D)) L1* (Kleene Star): ε -->((S))-->(A)-->(B) ^ | | ε | +--------------+

The Big Win

Epsilon-transitions let us compose automata like functions. Build small, test small, combine freely. This is the foundation of how tools like grep, lex, and regex engines work internally.

18 / 19

Summary & Cheat Sheet

Core Concepts

ConceptDefinition
ε-transitionMove between states without consuming input
CL(q)All states reachable from q via ε*
CL(S)∪ CL(q) for all q in S
δ̂(q,ε)= CL(q)
δ̂(q,xa)= CL( δ( δ̂(q,x), a ) )
Accepts wδ̂(q0,w) ∩ F ≠ ∅

Conversion Cheat Sheet

ε-NFA --> NFA: δ_N(q,a) = CL( δ_E( CL(q), a ) ) F' = { q | CL(q) ∩ F ≠ ∅ } ε-NFA --> DFA (direct): Start = CL(q0) δ_DFA(S,a) = CL( ∪ δ(q,a) for q in S ) Accept if S ∩ F ≠ ∅

Equivalence Chain

DFA ≡ NFA ≡ ε-NFA ≡ RegEx Every conversion is possible: RegEx --Thompson--> ε-NFA ε-NFA --eliminate ε--> NFA NFA --subset const.--> DFA DFA --state elim.--> RegEx

Key Takeaways

  • ε-transitions add NO extra power -- just convenience
  • Always compute CL() before AND after reading symbols
  • CL(q) always includes q itself
  • ε is NOT in the alphabet
  • Start state may become accepting after conversion
  • Thompson's construction is why ε-NFA exists in practice

Final Analogy

ε-transitions are like escalators in a mall -- they move you between floors for free. The mall (language recognized) doesn't change if you remove them and add staircases (direct transitions) instead. Just the convenience of getting around changes.

19 / 19