@@ -13,6 +13,22 @@ def str_double (w : List α) : List α :=
1313 | [] => []
1414 | a :: u => a :: a :: str_double u
1515
16+ theorem str_double_injective (u : List α) (v : List α) :
17+ str_double u = str_double v -> u = v := by
18+ induction u generalizing v with
19+ | nil =>
20+ cases v with
21+ | nil => simp [str_double]
22+ | cons b v' => simp [str_double]
23+ | cons a u' IH =>
24+ cases v with
25+ | nil => simp [str_double]
26+ | cons b v' =>
27+ simp [str_double]
28+ intro h
29+ simp [h]
30+ apply IH
31+
1632namespace Language
1733
1834def double (L : Language α) : Language α := {str_double w | w ∈ L}
@@ -21,6 +37,10 @@ end Language
2137
2238namespace NFA
2339
40+ /-
41+ Lemmas for Theorem 1
42+ -/
43+
2444variable (M) in
2545/-- If [ M ] recognizes a language [ L ] , [ M.double ] is an NFA constructed
2646 such that it should recognize exactly [double L]. -/
@@ -76,7 +96,7 @@ lemma double_eval_equal {w : List α} :
7696 rw [double_steps_equal]
7797
7898/-- [ M.double ] accepts [double w] iff [ M ] accepts [ w ] . -/
79- lemma mem_iff_double_in_double_lang {w : List α} :
99+ lemma mem_iff_double_in_doubleNFA_lang {w : List α} :
80100 (w ∈ M.accepts) <-> (str_double w ∈ M.double.accepts) := by
81101 simp [accepts]
82102 repeat rw [Set.mem_setOf]
@@ -139,7 +159,7 @@ theorem stepSets_empty (x : List α) :
139159variable (M) in
140160/-- If [ S ] consists only of states in [ M ] , taking two steps [a, a] in [ M.double ]
141161 leads only to states also in [ M ] . -/
142- lemma even_two_steps_to_even {S : Set σ} (a : α) :
162+ lemma even_two_steps_leads_to_even {S : Set σ} (a : α) :
143163 ∃ T : Set σ, Sum.inl '' T = M.double.stepSet (M.double.stepSet (Sum.inl '' S) a) a := by
144164 rw [<- double_step_equal]
145165 use M.stepSet S a
@@ -168,7 +188,7 @@ lemma even_to_accepted_is_double {w : List α} :
168188 obtain ⟨h_ex1, ⟨h_ex2, h⟩⟩ := h
169189 have ex : (∃ T : Set σ, Sum.inl '' T
170190 = (M.double.stepSet (M.double.stepSet (Sum.inl '' h_ex1) a) a)) := by
171- simp [even_two_steps_to_even ]
191+ simp [even_two_steps_leads_to_even ]
172192 obtain ⟨T, ex⟩ := ex
173193 rw [<- ex] at h
174194 have rh := by exact IH ⟨T, h_ex2, h⟩
@@ -180,7 +200,7 @@ lemma even_to_accepted_is_double {w : List α} :
180200 simp [Ne.symm h_ab]
181201
182202/-- If [ w ] is accepted by [ M.double ] , [ w ] must be the double of a string. -/
183- lemma mem_of_double_lang_is_double {w : List α} :
203+ lemma mem_of_doubleNFA_lang_is_double {w : List α} :
184204 w ∈ M.double.accepts → ∃ j : List α, w = str_double j := by
185205 simp [accepts, eval]
186206 intro h
@@ -196,9 +216,9 @@ lemma mem_of_double_lang_is_double {w : List α} :
196216 use a
197217 · simp [double] at h -- impossible case
198218
199- /-- The language accepted by [ M.double ] is the double of the language
200- accepted by [ M ] . -/
201- theorem lang_of_double_is_double_of_lang {L : Language α} : -- Theorem-1
219+ /-- The language recognized by [ M.double ] is the double of the language
220+ recognized by [ M ] . -/
221+ theorem lang_of_doubleNFA_is_double_of_lang {L : Language α} : -- Theorem-1
202222 L = M.accepts -> L.double = M.double.accepts := by
203223 intro h
204224 ext x
@@ -209,32 +229,94 @@ theorem lang_of_double_is_double_of_lang {L : Language α} : -- Theorem-1
209229 rw [Set.mem_setOf, h]
210230 intro h
211231 obtain ⟨w, ⟨h_w, h_d⟩⟩ := h
212- rw [mem_iff_double_in_double_lang , h_d] at h_w
232+ rw [mem_iff_double_in_doubleNFA_lang , h_d] at h_w
213233 exact h_w
214234 · -- x ∈ M.double.accepts → x ∈ L.double
215235 /- use [ mem_of_double_lang_is_double ] to prove
216236 that [ M.double.accepts ] contains only doubled-strings -/
217237 intro h_x
218238 have h_xd : ∃ j, x = str_double j := by
219- apply mem_of_double_lang_is_double at h_x
239+ apply mem_of_doubleNFA_lang_is_double at h_x
220240 exact h_x
221241 obtain ⟨j, h_xd⟩ := h_xd
222242 /- then use [ mem_iff_double_in_double_lang ] to prove those
223243 strings have halves accepted by [ M ] -/
224- rw [h_xd, <- mem_iff_double_in_double_lang ] at h_x
244+ rw [h_xd, <- mem_iff_double_in_doubleNFA_lang ] at h_x
225245 rw [h]
226246 simp [Language.double]
227247 rw [Set.mem_setOf]
228248 use j
229249 simp [h_x, h_xd]
230250
231- -- Todo: Theorem 2
251+ /-
252+ Lemmas for Theorem 2
253+ -/
232254
233255variable (M) in
234- def lang_half : (NFA α σ) where
256+ /-- If [ M ] recognizes a language-double [double L], [ M.half ] is an NFA constructed
257+ such that it should recognize exactly [ L ] . -/
258+ def half : (NFA α σ) where
235259 step := fun (s : σ) (a : α) => ⋃ x ∈ (M.step s a), M.step x a
236- start := M.accept
237- accept := M.start
260+ start := M.start
261+ accept := M.accept
262+
263+ /-- Taking one steps [ a ] in [ M.half ] should lead to the same set of states
264+ as taking two step [a, a] in [ M ] (starting from any set of states). -/
265+ lemma half_step_equal (a : α) (S : Set σ) :
266+ M.half.stepSet S a = M.stepSet (M.stepSet S a) a := by
267+ simp [stepSet]
268+ simp [half]
269+
270+ /-- Following [ w ] in [ M.half ] should lead to the same set of states
271+ as following [double w] in [ M ] (starting from any set of states). -/
272+ lemma half_steps_equal {w : List α} :
273+ ∀ S : Set σ,
274+ M.half.evalFrom S w
275+ = M.evalFrom S (str_double w) := by
276+ induction w with
277+ | nil =>
278+ simp [str_double]
279+ | cons a u IH =>
280+ simp [str_double]
281+ intro s
282+ rw [<- M.half_step_equal a s]
283+ rw [IH]
284+
285+ /-- Evaluating [ w ] in [ M.half ] should lead to the same set of states
286+ as evaluating [double w] in [ M ] . -/
287+ lemma half_eval_equal {w : List α} :
288+ M.half.eval w = M.eval (str_double w) := by
289+ simp [eval]
290+ nth_rw 2 [half]
291+ simp
292+ rw [half_steps_equal]
293+
294+ /-- [ M.half ] accepts [ w ] iff [ M ] accepts [double w]. -/
295+ lemma mem_halfNFA_iff_double_in_lang {w : List α} :
296+ (w ∈ M.half.accepts) <-> (str_double w ∈ M.accepts) := by
297+ simp [accepts]
298+ repeat rw [Set.mem_setOf]
299+ rw [<- half_eval_equal]
300+ simp [half]
301+
302+ /-- If [ M ] accepts the double-language [double L], [ M.half ]
303+ accepted by [ M ] . -/
304+ theorem lang_is_double_of_halfNFA_lang {L : Language α} : -- Theorem-2
305+ L.double = M.accepts -> L = M.half.accepts := by
306+ intro h
307+ ext x
308+ simp [mem_halfNFA_iff_double_in_lang]
309+ rw [<- h]
310+ simp [Language.double]
311+ rw [Set.mem_setOf]
312+ constructor
313+ · intro h
314+ use x
315+ · intro h
316+ obtain ⟨w, ⟨h1, h2⟩⟩ := h
317+ apply str_double_injective at h2
318+ rw [<- h2]
319+ exact h1
238320
239321end NFA
240322
@@ -255,8 +337,29 @@ protected theorem IsRegular.double {α : Type} [hf_α : Fintype α]
255337 exact ⟨Fintype.ofFinite (Set (σ ⊕ σ × α))⟩
256338 use h_dirsum, M.toNFA.double.toDFA
257339 simp
258- rw [NFA.lang_of_double_is_double_of_lang ]
340+ rw [NFA.lang_of_doubleNFA_is_double_of_lang ]
259341 simp
260342 rw [hAcc]
261343
344+ -- Theorem-2
345+ -- If language [double L] is regular, the language [ L ] is regular.
346+ protected theorem IsRegular.half {α : Type } {L : Language α} (h : L.double.IsRegular) :
347+ L.IsRegular := by
348+ simp [IsRegular] at h
349+ simp [IsRegular]
350+ obtain ⟨σ, hNe, M, hAcc⟩ := h
351+ use Set σ
352+ -- prove (Set σ) is nonempty & finite, so that it can
353+ -- be used as the state set of a DFA/NFA
354+ have h_set : Nonempty (Fintype (Set σ)) := by
355+ have h_mem_σ : Fintype σ := Classical.choice hNe
356+ exact ⟨Fintype.ofFinite (Set σ)⟩
357+ use h_set, M.toNFA.half.toDFA
358+ -- convert the DFA [ M ] into a NFA in h_eqAcc so we can apply
359+ -- [ NFA.lang_is_double_of_halfNFA_lang ] to it
360+ have h_eqAcc : M.accepts = M.toNFA.accepts := by simp
361+ rw [h_eqAcc, eq_comm] at hAcc
362+ apply NFA.lang_is_double_of_halfNFA_lang at hAcc
363+ simp [hAcc]
364+
262365end Language
0 commit comments