Skip to content

Commit 96ad93a

Browse files
committed
Progress proof of every regular language has a regular expression matching it
1 parent 5605bfa commit 96ad93a

1 file changed

Lines changed: 133 additions & 41 deletions

File tree

TraceTheory/TraceTheory/Computability.lean

Lines changed: 133 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,7 @@ end kstar
458458
section toSingleεNFA
459459

460460
variable {σ : Type*}
461+
variable {α : Type*}
461462
variable {M : εNFA α σ}
462463

463464
/-- The extended state space with a new start state and accept state. -/
@@ -607,7 +608,7 @@ section Kleene
607608
open RegularExpression
608609

609610
variable {σ : Type*} [Fintype σ] [DecidableEq σ]
610-
variable {α : Type*} [Fintype α] [DecidableEq α] [LinearOrder α]
611+
variable {α : Type*} [Fintype α] [DecidableEq α] [LinearOrder α] [Nonempty α]
611612
variable {M : εNFA α (ExtendedState σ)}
612613

613614
local notation "n" => Fintype.card (ExtendedState σ)
@@ -617,6 +618,7 @@ noncomputable def e : ExtendedState σ ≃ Fin n := Fintype.equivFin _
617618

618619
variable (M) in
619620
/-- The regex for a direct edge between indices i and j. -/
621+
@[simp]
620622
noncomputable def directRegex (i j : Fin n) : RegularExpression α :=
621623
let s_i := e.symm i
622624
let s_j := e.symm j
@@ -628,44 +630,48 @@ noncomputable def directRegex (i j : Fin n) : RegularExpression α :=
628630
if s_j ∈ M.step s_i none ∨ i = j then 1 else 0
629631
char_transitions + epsilon_transitions
630632

631-
variable (M) in
632633
/-- The path regex using intermediate states < k. -/
633-
noncomputable def pathRegex : ℕ → Fin n → Fin n → RegularExpression α
634+
@[simp]
635+
noncomputable def pathRegex (M : εNFA α (ExtendedState σ)) : ℕ → Fin n → Fin n → RegularExpression α
634636
| 0, i, j => directRegex M i j
635637
| k + 1, i, j =>
636638
if hk : k < n then
637639
let k' : Fin n := ⟨k, hk⟩
638-
let R_to_k := pathRegex k i k'
639-
let R_loop := pathRegex k k' k'
640-
let R_from := pathRegex k k' j
641-
let R_old := pathRegex k i j
640+
let R_to_k := pathRegex M k i k'
641+
let R_loop := pathRegex M k k' k'
642+
let R_from := pathRegex M k k' j
643+
let R_old := pathRegex M k i j
642644
R_to_k * R_loop.star * R_from + R_old
643645
else
644-
pathRegex k i j
646+
pathRegex M k i j
647+
648+
lemma iSup_eq_const {ι α : Type*} [CompleteLattice α] (b : ι) (g : ι → α) :
649+
(⨆ x, ⨆ (_ : x = b), g x) = g b := by
650+
apply le_antisymm
651+
· apply iSup_le
652+
intro x
653+
apply iSup_le
654+
intro hx
655+
simp [hx]
656+
· apply le_iSup_of_le b
657+
apply le_iSup_of_le rfl
658+
simp
659+
660+
theorem matches'_foldl_acc {α : Type*}
661+
(L : List α) (f : α → RegularExpression α) (acc : RegularExpression α) :
662+
(L.foldl (fun acc a => acc + f a) acc).matches' =
663+
acc.matches' + ⨆ x ∈ L, (f x).matches' := by
664+
induction L generalizing acc with
665+
| nil => simp
666+
| cons b L' ih =>
667+
simp only [List.foldl_cons, ih, matches', add_eq_sup, List.mem_cons, iSup_or]
668+
rw [iSup_sup_eq, iSup_eq_const, ← sup_assoc]
645669

646-
omit [Fintype α] [DecidableEq α] [LinearOrder α] in
647-
theorem matches'_foldl_sum (L : List α) (f : α → RegularExpression α) :
670+
theorem matches'_foldl_sum {α : Type*} (L : List α) (f : α → RegularExpression α) :
648671
(L.foldl (fun acc a => acc + f a) 0).matches' =
649-
((⋃ x ∈ L, (f x).matches') : Language α) := by
650-
let g := fun (acc : RegularExpression α) (a : α) => acc + f a
651-
let u : Language α := (⋃ x ∈ L, (f x).matches')
652-
have h : ∀ acc, (L.foldl g acc).matches' = acc.matches' + u := by
653-
dsimp [u]
654-
induction L with
655-
| nil =>
656-
intro acc
657-
simp
658-
apply Set.empty_subset
659-
| cons a L' ih =>
660-
intro acc
661-
dsimp [g]
662-
rw [ih, matches'_add, add_assoc]
663-
apply congr_arg
664-
simp
665-
rfl
666-
specialize h 0
667-
simp [g, u] at h
668-
exact h
672+
⋃ x ∈ L, (f x).matches' := by
673+
simp only [matches'_foldl_acc, matches', add_eq_sup, zero_le, sup_of_le_right]
674+
rfl
669675

670676
variable (M) in
671677
/-- A path in the NFA restricted to intermediate states < k. -/
@@ -679,28 +685,114 @@ inductive IsRestrictedPath (k : ℕ) : Fin n → Fin n → List α → Prop
679685
IsRestrictedPath k m j x₂ →
680686
IsRestrictedPath k i j (x₁ ++ x₂)
681687

688+
omit [DecidableEq σ] [DecidableEq α] [Nonempty α] in
689+
lemma IsRestrictedPath.mono {k k' : ℕ} (h_le : k ≤ k') {i j : Fin n} {w : List α}
690+
(h : IsRestrictedPath M k i j w) : IsRestrictedPath M k' i j w := by
691+
induction h with
692+
| direct i' j' x hx => exact direct i' j' x hx
693+
| trans i' j' m x₁ x₂ _ h_lt _ ih₁ ih₂ =>
694+
exact trans i' j' m x₁ x₂ ih₁ (lt_of_lt_of_le h_lt h_le) ih₂
695+
682696
theorem mem_pathRegex_iff_isRestrictedPath (k : ℕ) (i j : Fin n) (w : List α) :
683697
w ∈ (pathRegex M k i j).matches' ↔ IsRestrictedPath M k i j w := by
684-
sorry
698+
induction k generalizing i j with
699+
| zero =>
700+
constructor
701+
· intro h
702+
apply IsRestrictedPath.direct
703+
simp_all
704+
· intro h
705+
cases h with
706+
| direct _ _ _ hx => simp_all
707+
| trans _ _ m _ _ _ hlt => cases m; simp_all
708+
| succ k' ih =>
709+
simp
710+
split_ifs with hk'
711+
· sorry
712+
· sorry
685713

686-
noncomputable def toRegex (M : εNFA a σ) : RegularExpression α :=
687-
sorry
714+
noncomputable def toRegex (M : εNFA α σ) : RegularExpression α :=
715+
pathRegex M.toSingleεNFA n (e .start) (e .accept)
716+
717+
#check And.intro
688718

689-
theorem isRestrictedPath_iff_isPath {i j : Fin n} {x : List α} :
690-
IsRestrictedPath M n i j x ↔ M.IsPath (e.symm i) (e.symm j) x := by
719+
omit [DecidableEq σ] [DecidableEq α] in
720+
theorem isRestrictedPath_iff_isPath {i j : Fin n} {x : (List α)} :
721+
IsRestrictedPath M n i j x ↔
722+
∃ y : List (Option α),
723+
M.IsPath (e.symm i) (e.symm j) y ∧
724+
y.reduceOption = x := by
691725
constructor
692726
· intro h
693727
induction h with
694728
| direct i' j' x' h_match =>
695729
dsimp [directRegex] at h_match
696-
simp only [matches'_foldl_sum] at h_match
697-
simp only [Language.mem_add] at h_match
698-
sorry
730+
simp only [matches'_foldl_sum, Finset.mem_sort, Finset.mem_univ, iUnion_true,
731+
Language.add_def, iUnion_union] at h_match
732+
rw [iUnion_union_distrib, mem_union, mem_iUnion, mem_iUnion] at h_match
733+
rcases h_match with ⟨k, hx'⟩ | ⟨k, hx'⟩
734+
· split_ifs at hx' with h_step
735+
· simp at hx'
736+
replace hx' := mem_singleton_iff.mp hx'
737+
use [k]
738+
constructor
739+
· exact IsPath.singleton M h_step
740+
· simp [hx']
741+
· simp [Language.zero_def] at hx'
742+
· split_ifs at hx' with h_step
743+
· simp [Language.one_def] at hx'
744+
rcases h_step with h_step | rfl
745+
· use [none]
746+
constructor
747+
· exact IsPath.singleton M h_step
748+
· simpa
749+
· use []
750+
simpa
751+
· simp [Language.zero_def] at hx'
699752
| trans i' j' m x₁ x₂ h₁ hlt h₂ ih₁ ih₂ =>
700-
sorry
701-
· sorry
753+
rcases ih₁ with ⟨y₁, h_path₁, rfl⟩
754+
rcases ih₂ with ⟨y₂, h_path₂, rfl⟩
755+
use y₁ ++ y₂
756+
constructor
757+
· apply M.isPath_append.mpr
758+
use e.symm m
759+
· rw [List.reduceOption_append]
760+
· intro h
761+
rcases h with ⟨y, h_path, rfl⟩
762+
generalize h_start : e.symm i = u at h_path
763+
generalize h_end : e.symm j = v at h_path
764+
induction h_path generalizing i with
765+
| nil s =>
766+
rw [List.reduceOption_nil]
767+
apply IsRestrictedPath.direct
768+
subst h_end
769+
rw [Equiv.apply_eq_iff_eq] at h_start
770+
subst h_start
771+
simp only [directRegex, or_true, ↓reduceIte, matches', matches'_foldl_sum, Finset.mem_sort,
772+
Finset.mem_univ, iUnion_true, Language.one_def, Language.add_def]
773+
rw [mem_union]
774+
simp
775+
| cons t s u' oa x h_step h_path ih =>
776+
subst h_start
777+
subst h_end
778+
rw [← List.singleton_append, List.reduceOption_append]
779+
apply IsRestrictedPath.trans (m := e t)
780+
· apply IsRestrictedPath.direct
781+
cases oa with
782+
| some a =>
783+
simp [matches'_foldl_sum]
784+
left
785+
rw [mem_iUnion]
786+
use a
787+
simp [h_step, mem_singleton [a]]
788+
| none =>
789+
simp [matches'_foldl_sum]
790+
right
791+
simp [h_step, Language.one_def]
792+
· exact (e t).isLt
793+
· exact ih (Equiv.symm_apply_apply _ _) rfl
702794

703-
theorem accepts_toRegex (M : εNFA a σ) : (toRegex M).matches' = M.accepts := by
795+
theorem accepts_toRegex (M : εNFA α σ) : (toRegex M).matches' = M.accepts := by
704796
sorry
705797

706798
end Kleene

0 commit comments

Comments
 (0)