-
Notifications
You must be signed in to change notification settings - Fork 50
feat: prove that an omega-language is regular iff it is a finite union of omega-languages of a special form #249
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,81 @@ | ||||||||||||||||||||||||
| /- | ||||||||||||||||||||||||
| Copyright (c) 2025 Ching-Tsun Chou. All rights reserved. | ||||||||||||||||||||||||
| Released under Apache 2.0 license as described in the file LICENSE. | ||||||||||||||||||||||||
| Authors: Ching-Tsun Chou | ||||||||||||||||||||||||
| -/ | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| module | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| public import Cslib.Computability.Languages.RegularLanguage | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| @[expose] public section | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| /-! # Languages determined by pairs of states | ||||||||||||||||||||||||
| -/ | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| namespace Cslib | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| open Language Automata Acceptor | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| variable {Symbol : Type*} {State : Type} | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| /-- `LTS.pairLang s t` is the language of finite words that can take the LTS | ||||||||||||||||||||||||
| from state `s` to state `t`. -/ | ||||||||||||||||||||||||
| def LTS.pairLang (lts : LTS State Symbol) (s t : State) : Language Symbol := | ||||||||||||||||||||||||
| { xl | lts.MTr s xl t } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| @[simp, scoped grind =] | ||||||||||||||||||||||||
| theorem LTS.mem_pairLang (lts : LTS State Symbol) (s t : State) (xl : List Symbol) : | ||||||||||||||||||||||||
| xl ∈ (lts.pairLang s t) ↔ lts.MTr s xl t := Iff.rfl | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| /-- `LTS.pairLang s t` is a regular language if there are only finitely many states. -/ | ||||||||||||||||||||||||
| @[simp] | ||||||||||||||||||||||||
| theorem LTS.pairLang_regular [Finite State] (lts : LTS State Symbol) (s t : State) : | ||||||||||||||||||||||||
| (lts.pairLang s t).IsRegular := by | ||||||||||||||||||||||||
| rw [IsRegular.iff_nfa] | ||||||||||||||||||||||||
| use State, inferInstance, (NA.FinAcc.mk ⟨lts, {s}⟩ {t}) | ||||||||||||||||||||||||
| ext xl; simp [LTS.mem_pairLang] | ||||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Either of these works:
Suggested change
or
Suggested change
(is this a missing |
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| namespace NA.Buchi | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| open Set Filter ωSequence ωLanguage ωAcceptor | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| /-- The ω-language accepted by a finite-state Büchi automaton is the finite union of ω-languages | ||||||||||||||||||||||||
| of the form `L * M^ω`, where all `L`s and `M`s are regular languages. -/ | ||||||||||||||||||||||||
| theorem language_eq_fin_iSup_hmul_omegaPow | ||||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you try to open the LTS scope here, Soon there will be an equivalent for |
||||||||||||||||||||||||
| [Inhabited Symbol] [Finite State] (na : NA.Buchi State Symbol) : | ||||||||||||||||||||||||
| language na = ⨆ s ∈ na.start, ⨆ t ∈ na.accept, (na.pairLang s t) * (na.pairLang t t)^ω := by | ||||||||||||||||||||||||
| ext xs | ||||||||||||||||||||||||
| simp only [NA.Buchi.instωAcceptor, ωAcceptor.mem_language, | ||||||||||||||||||||||||
| ωLanguage.mem_iSup, ωLanguage.mem_hmul, LTS.mem_pairLang] | ||||||||||||||||||||||||
| constructor | ||||||||||||||||||||||||
| · rintro ⟨ss, h_run, h_inf⟩ | ||||||||||||||||||||||||
| obtain ⟨t, _, h_t⟩ := frequently_in_finite_type.mp h_inf | ||||||||||||||||||||||||
| refine ⟨ss 0, by grind [h_run.start], t, by assumption, ?_⟩ | ||||||||||||||||||||||||
|
Comment on lines
+53
to
+54
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Two things here:
Suggested change
|
||||||||||||||||||||||||
| obtain ⟨f, h_mono, h_f⟩ := frequently_iff_strictMono.mp h_t | ||||||||||||||||||||||||
| refine ⟨xs.take (f 0), ?_, xs.drop (f 0), ?_, by grind⟩ | ||||||||||||||||||||||||
| · grind [extract_eq_drop_take, LTS.ωTr_mTr h_run.trans (Nat.zero_le (f 0))] | ||||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is a bit more clear if you split it up and pass off arithmetic to
Suggested change
|
||||||||||||||||||||||||
| · simp only [omegaPow_seq_prop, LTS.mem_pairLang] | ||||||||||||||||||||||||
| refine ⟨(f · - f 0), by grind [Nat.base_zero_strictMono], by simp, ?_⟩ | ||||||||||||||||||||||||
| intro n | ||||||||||||||||||||||||
| grind [extract_drop, h_mono.monotone (Nat.zero_le n), h_mono.monotone (Nat.zero_le (n + 1)), | ||||||||||||||||||||||||
| LTS.ωTr_mTr h_run.trans <| h_mono.monotone (show n ≤ n + 1 by grind)] | ||||||||||||||||||||||||
|
Comment on lines
+59
to
+62
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here's what I came up with for readability:
Suggested change
In general, I think we are doing something wrong with |
||||||||||||||||||||||||
| · rintro ⟨s, _, t, _, yl, h_yl, zs, h_zs, rfl⟩ | ||||||||||||||||||||||||
| obtain ⟨zls, rfl, h_zls⟩ := mem_omegaPow.mp h_zs | ||||||||||||||||||||||||
| let ts := ωSequence.const t | ||||||||||||||||||||||||
| have h_mtr (n : ℕ) : na.MTr (ts n) (zls n) (ts (n + 1)) := by | ||||||||||||||||||||||||
| grind [Language.mem_sub_one, LTS.mem_pairLang] | ||||||||||||||||||||||||
| have h_pos (n : ℕ) : (zls n).length > 0 := by | ||||||||||||||||||||||||
| grind [Language.mem_sub_one, List.eq_nil_iff_length_eq_zero] | ||||||||||||||||||||||||
| obtain ⟨zss, h_zss, _⟩ := LTS.ωTr.flatten h_mtr h_pos | ||||||||||||||||||||||||
| have (n : ℕ) : zss (zls.cumLen n) = t := by grind | ||||||||||||||||||||||||
| obtain ⟨xss, _, _, _, _⟩ := LTS.ωTr.append h_yl h_zss (by grind [cumLen_zero (ls := zls)]) | ||||||||||||||||||||||||
| refine ⟨xss, by grind [NA.Run.mk], ?_⟩ | ||||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||
| apply (drop_frequently_iff_frequently yl.length).mp | ||||||||||||||||||||||||
| apply frequently_iff_strictMono.mpr | ||||||||||||||||||||||||
| use zls.cumLen | ||||||||||||||||||||||||
| grind [cumLen_strictMono] | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| end NA.Buchi | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| end Cslib | ||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -7,7 +7,7 @@ Authors: Fabrizio Montesi | |||||||||||
| module | ||||||||||||
|
|
||||||||||||
| public import Cslib.Init | ||||||||||||
| public import Cslib.Foundations.Data.OmegaSequence.Init | ||||||||||||
| public import Cslib.Foundations.Data.OmegaSequence.Flatten | ||||||||||||
| public import Cslib.Foundations.Semantics.FLTS.Basic | ||||||||||||
| public import Mathlib.Data.Set.Finite.Basic | ||||||||||||
| public import Mathlib.Order.ConditionallyCompleteLattice.Basic | ||||||||||||
|
|
@@ -264,17 +264,54 @@ theorem LTS.ωTr.cons (htr : lts.Tr s μ t) (hωtr : lts.ωTr ss μs) (hm : ss 0 | |||||||||||
| induction i <;> grind | ||||||||||||
|
|
||||||||||||
| /-- Prepends an infinite execution with a finite execution. -/ | ||||||||||||
| theorem LTS.ωTr.append (hmtr : lts.MTr s μl t) (hωtr : lts.ωTr ss μs) | ||||||||||||
| (hm : ss 0 = t) : ∃ ss', lts.ωTr ss' (μl ++ω μs) ∧ ss' 0 = s ∧ ss' μl.length = t := by | ||||||||||||
| theorem LTS.ωTr.append | ||||||||||||
| (hmtr : lts.MTr s μl t) (hωtr : lts.ωTr ss μs) (hm : ss 0 = t) : | ||||||||||||
| ∃ ss', lts.ωTr ss' (μl ++ω μs) ∧ ss' 0 = s ∧ ss' μl.length = t ∧ ss'.drop μl.length = ss := by | ||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this new condition have been here from the initial addition of this theorem? |
||||||||||||
| obtain ⟨sl, _, _, _, _⟩ := LTS.MTr.exists_states hmtr | ||||||||||||
| refine ⟨sl ++ω ss.drop 1, ?_, by grind [get_append_left], by grind [get_append_left]⟩ | ||||||||||||
| refine ⟨sl.take μl.length ++ω ss, ?_, | ||||||||||||
| by grind [get_append_left], by grind [get_append_left], by grind [drop_append_of_ge_length]⟩ | ||||||||||||
|
Comment on lines
+271
to
+272
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My rule of thumb would be if it doesn't fit on a single line and you have a nicely ordered conjunction as your goal, do
Suggested change
and then a bullet for each proof. |
||||||||||||
| intro n | ||||||||||||
| by_cases n < μl.length | ||||||||||||
| · grind [get_append_left] | ||||||||||||
| · by_cases n = μl.length | ||||||||||||
| · grind [get_append_left] | ||||||||||||
| · grind [get_append_left, get_append_right'] | ||||||||||||
| · grind [get_append_right', hωtr (n - μl.length - 1)] | ||||||||||||
|
|
||||||||||||
| open Nat in | ||||||||||||
| /-- Concatenating an infinite sequence of finite executions that connect an infinite sequence | ||||||||||||
| of intermediate states. -/ | ||||||||||||
| theorem LTS.ωTr.flatten [Inhabited Label] {ts : ωSequence State} {μls : ωSequence (List Label)} | ||||||||||||
| (hmtr : ∀ k, lts.MTr (ts k) (μls k) (ts (k + 1))) (hpos : ∀ k, (μls k).length > 0) : | ||||||||||||
| ∃ ss, lts.ωTr ss μls.flatten ∧ ∀ k, ss (μls.cumLen k) = ts k := by | ||||||||||||
| have : Inhabited State := by exact {default := ts 0} | ||||||||||||
| choose sls h_sls using fun k ↦ LTS.MTr.exists_states (hmtr k) | ||||||||||||
| let segs := ωSequence.mk fun k ↦ (sls k).take (μls k).length | ||||||||||||
| have h_len : μls.cumLen = segs.cumLen := by ext k; induction k <;> grind | ||||||||||||
| have h_pos (k : ℕ) : (segs k).length > 0 := by grind [List.eq_nil_iff_length_eq_zero] | ||||||||||||
| have h_mono := cumLen_strictMono h_pos | ||||||||||||
| have h_zero := cumLen_zero (ls := segs) | ||||||||||||
| have h_seg0 (k : ℕ) : (segs k)[0]! = ts k := by grind | ||||||||||||
| refine ⟨segs.flatten, ?_, by simp [h_len, flatten_def, segment_idem h_mono, h_seg0]⟩ | ||||||||||||
| intro n | ||||||||||||
| simp only [h_len, flatten_def] | ||||||||||||
| have := segment_lower_bound h_mono h_zero n | ||||||||||||
| by_cases h_n : n + 1 < segs.cumLen (segment segs.cumLen n + 1) | ||||||||||||
| · have := segment_range_val h_mono (by grind) h_n | ||||||||||||
| have : n + 1 - segs.cumLen (segment segs.cumLen n) < (μls (segment segs.cumLen n)).length := by | ||||||||||||
| grind | ||||||||||||
| grind | ||||||||||||
| · have h1 : segs.cumLen (segment segs.cumLen n + 1) = n + 1 := by | ||||||||||||
| grind [segment_upper_bound h_mono h_zero n] | ||||||||||||
| have h2 : segment segs.cumLen (n + 1) = segment segs.cumLen n + 1 := by | ||||||||||||
| simp [← h1, segment_idem h_mono] | ||||||||||||
| have : n + 1 - segs.cumLen (segment segs.cumLen n) = (μls (segment segs.cumLen n)).length := by | ||||||||||||
| grind | ||||||||||||
| have h3 : ts (segment segs.cumLen n + 1) = | ||||||||||||
| (sls (segment segs.cumLen n))[n + 1 - segs.cumLen (segment segs.cumLen n)]! := by | ||||||||||||
| grind | ||||||||||||
| simp [h1, h2, h_seg0, h3] | ||||||||||||
|
Comment on lines
+309
to
+312
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this file very slow to edit for you as well? This is all the proof golfing I could stand to do:
Suggested change
|
||||||||||||
| grind | ||||||||||||
|
|
||||||||||||
| end ωMultiStep | ||||||||||||
|
|
||||||||||||
| section Total | ||||||||||||
|
|
@@ -319,7 +356,8 @@ theorem LTS.Total.mTr_ωTr [Inhabited Label] [ht : lts.Total] {μl : List Label} | |||||||||||
| (hm : lts.MTr s μl t) : ∃ μs ss, lts.ωTr ss (μl ++ω μs) ∧ ss 0 = s ∧ ss μl.length = t := by | ||||||||||||
| let μs : ωSequence Label := .const default | ||||||||||||
| obtain ⟨ss', ho, h0⟩ := LTS.Total.ωTr_exists (h := ht) t μs | ||||||||||||
| refine ⟨μs, LTS.ωTr.append hm ho h0⟩ | ||||||||||||
| use μs | ||||||||||||
| grind [LTS.ωTr.append hm ho h0] | ||||||||||||
|
|
||||||||||||
| /-- `LTS.totalize` constructs a total LTS from any given LTS by adding a sink state. -/ | ||||||||||||
| def LTS.totalize (lts : LTS State Label) : LTS (State ⊕ Unit) Label where | ||||||||||||
|
|
||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems these should be in the
LTSmodule.