Skip to content

Commit a141203

Browse files
committed
Prove lang-doubling Theorem 2
1 parent 7b5ad89 commit a141203

1 file changed

Lines changed: 118 additions & 15 deletions

File tree

TraceTheoryLean/LangDouble.lean

Lines changed: 118 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
1632
namespace Language
1733

1834
def double (L : Language α) : Language α := {str_double w | w ∈ L}
@@ -21,6 +37,10 @@ end Language
2137

2238
namespace NFA
2339

40+
/-
41+
Lemmas for Theorem 1
42+
-/
43+
2444
variable (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 α) :
139159
variable (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

233255
variable (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

239321
end 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+
262365
end Language

0 commit comments

Comments
 (0)