# Epsilon Nondeterministic Finite Automata #

This file contains the definition of an epsilon Nondeterministic Finite Automaton (εNFA), a state machine which determines whether a string (implemented as a list over an arbitrary alphabet) is in a regular set by evaluating the string over every possible path, also having access to ε-transitions, which can be followed without reading a character. Since this definition allows for automata with infinite states, a Fintype instance must be supplied for true εNFA's.

structure εNFA (α : Type u) (σ : Type v) :
Type (max u v)

An εNFA is a set of states (σ), a transition function from state to state labelled by the alphabet (step), a starting state (start) and a set of acceptance states (accept). Note the transition function sends a state to a Set of states and can make ε-transitions by inputing none. Since this definition allows for Automata with infinite states, a Fintype instance must be supplied for true εNFA's.

• step : σSet σ

Transition function. The automaton is rendered non-deterministic by this transition function returning Set σ (rather than σ), and ε-transitions are made possible by taking Option α (rather than α).

• start : Set σ

Starting states.

• accept : Set σ

Set of acceptance states.

Instances For
inductive εNFA.εClosure {α : Type u} {σ : Type v} (M : εNFA α σ) (S : Set σ) :
Set σ

The εClosure of a set is the set of states which can be reached by taking a finite string of ε-transitions from an element of the set.

• base: ∀ {α : Type u} {σ : Type v} {M : εNFA α σ} {S : Set σ}, sS, M.εClosure S s
• step: ∀ {α : Type u} {σ : Type v} {M : εNFA α σ} {S : Set σ} (s t : σ), t M.step s noneM.εClosure S sM.εClosure S t
Instances For
@[simp]
theorem εNFA.subset_εClosure {α : Type u} {σ : Type v} (M : εNFA α σ) (S : Set σ) :
S M.εClosure S
@[simp]
theorem εNFA.εClosure_empty {α : Type u} {σ : Type v} (M : εNFA α σ) :
M.εClosure =
@[simp]
theorem εNFA.εClosure_univ {α : Type u} {σ : Type v} (M : εNFA α σ) :
M.εClosure Set.univ = Set.univ
def εNFA.stepSet {α : Type u} {σ : Type v} (M : εNFA α σ) (S : Set σ) (a : α) :
Set σ

M.stepSet S a is the union of the ε-closure of M.step s a for all s ∈ S.

Equations
• M.stepSet S a = sS, M.εClosure (M.step s (some a))
Instances For
@[simp]
theorem εNFA.mem_stepSet_iff {α : Type u} {σ : Type v} {M : εNFA α σ} {S : Set σ} {s : σ} {a : α} :
s M.stepSet S a tS, s M.εClosure (M.step t (some a))
@[simp]
theorem εNFA.stepSet_empty {α : Type u} {σ : Type v} {M : εNFA α σ} (a : α) :
M.stepSet a =
def εNFA.evalFrom {α : Type u} {σ : Type v} (M : εNFA α σ) (start : Set σ) :
List αSet σ

M.evalFrom S x computes all possible paths through M with input x starting at an element of S.

Equations
• M.evalFrom start = List.foldl M.stepSet (M.εClosure start)
Instances For
@[simp]
theorem εNFA.evalFrom_nil {α : Type u} {σ : Type v} (M : εNFA α σ) (S : Set σ) :
M.evalFrom S [] = M.εClosure S
@[simp]
theorem εNFA.evalFrom_singleton {α : Type u} {σ : Type v} (M : εNFA α σ) (S : Set σ) (a : α) :
M.evalFrom S [a] = M.stepSet (M.εClosure S) a
@[simp]
theorem εNFA.evalFrom_append_singleton {α : Type u} {σ : Type v} (M : εNFA α σ) (S : Set σ) (x : List α) (a : α) :
M.evalFrom S (x ++ [a]) = M.stepSet (M.evalFrom S x) a
@[simp]
theorem εNFA.evalFrom_empty {α : Type u} {σ : Type v} (M : εNFA α σ) (x : List α) :
M.evalFrom x =
def εNFA.eval {α : Type u} {σ : Type v} (M : εNFA α σ) :
List αSet σ

M.eval x computes all possible paths through M with input x starting at an element of M.start.

Equations
• M.eval = M.evalFrom M.start
Instances For
@[simp]
theorem εNFA.eval_nil {α : Type u} {σ : Type v} (M : εNFA α σ) :
M.eval [] = M.εClosure M.start
@[simp]
theorem εNFA.eval_singleton {α : Type u} {σ : Type v} (M : εNFA α σ) (a : α) :
M.eval [a] = M.stepSet (M.εClosure M.start) a
@[simp]
theorem εNFA.eval_append_singleton {α : Type u} {σ : Type v} (M : εNFA α σ) (x : List α) (a : α) :
M.eval (x ++ [a]) = M.stepSet (M.eval x) a
def εNFA.accepts {α : Type u} {σ : Type v} (M : εNFA α σ) :

M.accepts is the language of x such that there is an accept state in M.eval x.

Equations
• M.accepts = {x : List α | SM.accept, S M.eval x}
Instances For

### Conversions between εNFA and NFA#

def εNFA.toNFA {α : Type u} {σ : Type v} (M : εNFA α σ) :
NFA α σ

M.toNFA is an NFA constructed from an εNFA M.

Equations
• M.toNFA = { step := fun (S : σ) (a : α) => M.εClosure (M.step S (some a)), start := M.εClosure M.start, accept := M.accept }
Instances For
@[simp]
theorem εNFA.toNFA_evalFrom_match {α : Type u} {σ : Type v} (M : εNFA α σ) (start : Set σ) :
M.toNFA.evalFrom (M.εClosure start) = M.evalFrom start
@[simp]
theorem εNFA.toNFA_correct {α : Type u} {σ : Type v} (M : εNFA α σ) :
M.toNFA.accepts = M.accepts
theorem εNFA.pumping_lemma {α : Type u} {σ : Type v} (M : εNFA α σ) [] {x : List α} (hx : x M.accepts) (hlen : Fintype.card (Set σ) x.length) :
∃ (a : List α) (b : List α) (c : List α), x = a ++ b ++ c a.length + b.length Fintype.card (Set σ) b [] {a} * KStar.kstar {b} * {c} M.accepts
def NFA.toεNFA {α : Type u} {σ : Type v} (M : NFA α σ) :
εNFA α σ

M.toεNFA is an εNFA constructed from an NFA M by using the same start and accept states and transition functions.

Equations
• M.toεNFA = { step := fun (s : σ) (a : ) => a.casesOn' fun (a : α) => M.step s a, start := M.start, accept := M.accept }
Instances For
@[simp]
theorem NFA.toεNFA_εClosure {α : Type u} {σ : Type v} (M : NFA α σ) (S : Set σ) :
M.toεNFA.εClosure S = S
@[simp]
theorem NFA.toεNFA_evalFrom_match {α : Type u} {σ : Type v} (M : NFA α σ) (start : Set σ) :
M.toεNFA.evalFrom start = M.evalFrom start
@[simp]
theorem NFA.toεNFA_correct {α : Type u} {σ : Type v} (M : NFA α σ) :
M.toεNFA.accepts = M.accepts

### Regex-like operations #

instance εNFA.instZero {α : Type u} {σ : Type v} :
Zero (εNFA α σ)
Equations
• εNFA.instZero = { zero := { step := fun (x : σ) (x : ) => , start := , accept := } }
instance εNFA.instOne {α : Type u} {σ : Type v} :
One (εNFA α σ)
Equations
• εNFA.instOne = { one := { step := fun (x : σ) (x : ) => , start := Set.univ, accept := Set.univ } }
instance εNFA.instInhabited {α : Type u} {σ : Type v} :
Equations
• εNFA.instInhabited = { default := 0 }
@[simp]
theorem εNFA.step_zero {α : Type u} {σ : Type v} (s : σ) (a : ) :
@[simp]
theorem εNFA.step_one {α : Type u} {σ : Type v} (s : σ) (a : ) :
@[simp]
theorem εNFA.start_zero {α : Type u} {σ : Type v} :
@[simp]
theorem εNFA.start_one {α : Type u} {σ : Type v} :
= Set.univ
@[simp]
theorem εNFA.accept_zero {α : Type u} {σ : Type v} :
@[simp]
theorem εNFA.accept_one {α : Type u} {σ : Type v} :
= Set.univ