Kleene's Algorithm #
Kleene's algorithm constructs a regular expression by induction on a bound that restricts
which interior states an execution may pass through.
It is used to prove a direction of Cslib.Language.IsRegular.iff_regex, that
every language accepted by a DFA comprised of finite states is the language of a regular expression.
We implement Kleene's algorithm for the more general case of an NFA instead of DFA,
since Execution is developed for LTS but not FLTS.
The main theorem is NA.FinAcc.nfa_eq_regex.
Main definitions #
LTS.bddLang start last bound: The language of finite words that are accepted by an execution of an LTS with state typeFin n, where the start state isstart, the last state islast, and all states of the execution except for the first and last are less thanbound.LTS.regex s t r: The regular expression for the executions of an LTS with state typeFin nfrom statesto statet, whose interior states are all under the boundr.
Main results #
NA.FinAcc.nfa_eq_regex: Any NFA has a matching regular expression.LTS.bddLang_eq_nfa:LTS.bddLangis equal to the language of an NFA whenboundis greater than or equal to the total number of states.LTS.bddLang_eq_regex:LTS.regex s t rmatches the languageLTS.bddLang s t r.
References #
The index of the first element in a list as that satisfies a predicate p,
excluding the first and last element.
Equations
- List.findIdxButFirstLast? p as = Option.map (fun (x : ℕ) => x + 1) (List.findIdx? p as.tail.dropLast)
Instances For
The index of the last element in a list as that satisfies a predicate p,
excluding the first and last element.
Equations
- List.findIdxButFirstLastRev? p as = Option.map (fun (x : ℕ) => as.length - 1 - x) (List.findIdxButFirstLast? p as.reverse)
Instances For
An execution of an LTS with state type Fin n,
where all states of the execution except for the first and last are less than bound.
Equations
Instances For
With an execution of the string xs through states ss,
splitFirstTake xs ss r returns a prefix of xs
which ends at the FIRST occurrence (excluding the first and last state) of state r in ss.
When no such occurrence of r exists, splitFirstTake returns the empty string; however,
the current file does not use the splitFirstTake in such situation.
The actual definition does not require an execution, just the string xs and the states ss.
Equations
Instances For
With an execution of the string xs through states ss,
splitFirstDrop xs ss r returns a suffix of xs
which starts at the FIRST occurrence (excluding the first and last state) of state r in ss.
When no such occurrence of r exists, splitFirstDrop returns the full string; however,
the current file does not use the splitFirstDrop in such situation.
The actual definition does not require an execution, just the string xs and the states ss.
Equations
- Cslib.LTS.splitFirstDrop xs ss r = match List.findIdxButFirstLast? (fun (x : Fin n) => decide (x = r)) ss with | none => xs | some i => List.drop i xs
Instances For
Part of the recursion step of Kleene's algorithm.
A run from s to t whose interior states are ≤ r either has all interior states < r,
or it splits at its first visit to r into
an execution from s to r with all interior states < r, followed by
an execution from r to t with all interior states ≤ r.
With an execution of the string xs through states ss,
splitLastTake xs ss r returns a prefix of xs
which ends at the LAST occurrence (excluding the first and last state) of state r in ss.
When no such occurrence of r exists, splitLastTake returns the empty string.
The actual definition does not require an execution, just the string xs and the states ss.
Equations
Instances For
With an execution of the string xs through states ss,
splitLastDrop xs ss r returns a prefix of xs
which ends at the LAST occurrence (excluding the first and last state) of state r in ss.
When no such occurrence of r exists, splitLastDrop returns the full string.
The actual definition does not require an execution, just the string xs and the states ss.
Equations
- Cslib.LTS.splitLastDrop xs ss r = match List.findIdxButFirstLastRev? (fun (x : Fin n) => decide (x = r)) ss with | none => xs | some i => List.drop i xs
Instances For
Part of the recursion step of Kleene's algorithm.
An execution from r to t whose interior states are ≤ r splits at its last visit to r into
an execution from r to r with all interior states ≤ r, followed by
an execution from r to t with all interior states < r.
regex s t r is the regular expression for the path from state s to t
passing through states < r.
When r = 0, s = t, the regex is empty string ε union all characters from state s to s.
When r = 0, s ≠ t, the regex is all characters from state s to t.
For r + 1, the regex is the union of regex s t r and
(regex s r r) (regex r r r)∗ (regex r t r).
Equations
- lts.regex s t 0 = if s = t then 1 + (List.map RegularExpression.char ⋯.toFinset.toList).sum else (List.map RegularExpression.char ⋯.toFinset.toList).sum
- lts.regex s t r.succ = if h : n ≤ r then lts.regex s t r else have rFin := ⟨r, ⋯⟩; lts.regex s t r + lts.regex s rFin r * (lts.regex rFin rFin r).star * lts.regex rFin t r
Instances For
An NFA with exactly one start state and exactly one accept state has a matching regular expression.
Any NFA has a matching regular expression.