@@ -458,6 +458,7 @@ end kstar
458458section toSingleεNFA
459459
460460variable {σ : Type *}
461+ variable {α : Type *}
461462variable {M : εNFA α σ}
462463
463464/-- The extended state space with a new start state and accept state. -/
@@ -607,7 +608,7 @@ section Kleene
607608open RegularExpression
608609
609610variable {σ : Type *} [Fintype σ] [DecidableEq σ]
610- variable {α : Type *} [Fintype α] [DecidableEq α] [LinearOrder α]
611+ variable {α : Type *} [Fintype α] [DecidableEq α] [LinearOrder α] [Nonempty α]
611612variable {M : εNFA α (ExtendedState σ)}
612613
613614local notation "n" => Fintype.card (ExtendedState σ)
@@ -617,6 +618,7 @@ noncomputable def e : ExtendedState σ ≃ Fin n := Fintype.equivFin _
617618
618619variable (M) in
619620/-- The regex for a direct edge between indices i and j. -/
621+ @[simp]
620622noncomputable 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
670676variable (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+
682696theorem 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
706798end Kleene
0 commit comments