Skip to content

Commit 439b965

Browse files
committed
Refactor path equivalence proofs
1 parent a25e663 commit 439b965

3 files changed

Lines changed: 83 additions & 172 deletions

File tree

correctness/RegexCorrectness/NFA/Semantics/Equivalence/CapturesOfPath.lean

Lines changed: 37 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -23,46 +23,11 @@ theorem captures_of_path.group {tag} (eq : nfa.pushRegex next (.group tag e) = r
2323
∃ groups, EquivUpdate groups update ∧ (Expr.group tag e).Captures pos pos' groups := by
2424
open Compile.ProofData Group in
2525
let pd := Group.intro eq
26-
simp [pd.eq_result eq] at path
27-
28-
cases path with
29-
| last step =>
30-
have ⟨eqnext, _, _⟩ := step_start_iff.mp step
31-
have ge := ge_pushRegex_start (result := nfaExpr) rfl
32-
simp [←eqnext, nfaClose] at ge
33-
have : next < pd.nfa.size := next_lt
34-
omega
35-
| @more i pos j posm k pos'' update updates step rest =>
36-
have ⟨hj, hpos, hupdate⟩ := step_start_iff.mp step
37-
simp [hupdate]
38-
simp [hj, hpos] at rest
39-
40-
have rest := castToExpr wf next_lt rest
41-
have next_lt_close : next < nfaClose.size := by
42-
simp [nfaClose]
43-
exact Nat.lt_trans next_lt (Nat.lt_add_one _)
44-
have ge_expr_start : nfaClose.size ≤ nfaExpr.start := ge_pushRegex_start rfl
45-
have ne_next : next ≠ nfaClose.start := by
46-
simp [nfaClose]
47-
exact Nat.ne_of_lt next_lt
48-
have ⟨posm, updateExpr, updateClose, equ, pathExpr, pathClose⟩ :=
49-
rest.path_next_of_ne (result := nfaExpr) rfl next_lt_close ge_expr_start ne_next
50-
51-
have wfClose := wfClose wf next_lt
52-
have ⟨groupExpr, eqv, c⟩ := ih (result := nfaExpr) rfl wfClose wfClose.start_lt pathExpr
53-
54-
have : nfaExpr[nfaClose.start]'(by grind) = nfa'[nfaClose.start]'(by grind) := by
55-
grind
56-
cases pathClose with
57-
| last step =>
58-
have ⟨_, hpos, hupdate⟩ := step_close_iff.mp (step.cast this)
59-
rw [←hpos] at c
60-
simp [equ, hupdate, ←hpos]
61-
exact ⟨.group tag pos pos' groupExpr, .group eqv, .group c⟩
62-
| more step rest =>
63-
have ⟨hj, _, _⟩ := step_close_iff.mp (step.cast this)
64-
have : nfa.size ≤ next := show nfa.size ≤ pd.next from hj ▸ rest.ge
65-
omega
26+
simp only [pd.eq_result eq] at path
27+
obtain ⟨updates, rfl, pathExpr⟩ := (pd.path_start_iff wf next_lt).mp path
28+
have wfClose := pd.wfClose wf next_lt
29+
have ⟨groups, eqv, c⟩ := ih rfl wfClose wfClose.start_lt pathExpr
30+
exact ⟨.group tag pos pos' groups, .group eqv, .group c⟩
6631

6732
theorem captures_of_path.alternate {e₁ e₂} (eq : nfa.pushRegex next (.alternate e₁ e₂) = result)
6833
(wf : nfa.WellFormed) (next_lt : next < nfa.size)
@@ -80,39 +45,16 @@ theorem captures_of_path.alternate {e₁ e₂} (eq : nfa.pushRegex next (.altern
8045
∃ groups, EquivUpdate groups update ∧ (Expr.alternate e₁ e₂).Captures pos pos' groups := by
8146
open Compile.ProofData Alternate in
8247
let pd := Alternate.intro eq
83-
simp [pd.eq_result eq] at path
84-
48+
simp only [pd.eq_result eq] at path
49+
obtain path := (pd.path_start_iff wf next_lt).mp path
8550
cases path with
86-
| last step =>
87-
have := step_start_iff.mp step
88-
have : next < nfa₁.start := Nat.lt_of_lt_of_le next_lt (ge_pushRegex_start rfl)
89-
have : next < nfa₂.start := Nat.lt_of_lt_of_le (Nat.lt_trans next_lt nfa₁_property) (ge_pushRegex_start rfl)
90-
omega
91-
| @more i pos j posm k pos'' update updates step rest =>
92-
have ⟨hj, hpos, hupdate⟩ := step_start_iff.mp step
93-
simp [hupdate]
94-
cases hj with
95-
| inl hj =>
96-
simp [hj, hpos] at rest
97-
have rest := castTo₁ wf next_lt rest
98-
have ⟨groups, eqv, c⟩ := ih₁ rfl wf next_lt rest
99-
exact ⟨groups, eqv, .alternateLeft c⟩
100-
| inr hj =>
101-
simp [hj, hpos] at rest
102-
103-
have rest := castTo₂ wf next_lt rest
104-
have rest : nfa₂.Path nfa₁.size nfa₂.start pos next pos' updates := by
105-
apply rest.liftBound' (ge_pushRegex_start rfl)
106-
intro i pos j pos' update gei gej step
107-
cases (step.liftBound' gei).eq_or_ge_of_pushRegex with
108-
| inl eq =>
109-
have : nfa.size ≤ next := show nfa.size ≤ pd.next from eq ▸ gej
110-
omega
111-
| inr ge => exact ge
112-
113-
have wf₁ := wf₁ wf next_lt
114-
have ⟨groups, eqv, c⟩ := ih₂ rfl wf₁ (Nat.lt_trans next_lt nfa₁_property) rest
115-
exact ⟨groups, eqv, .alternateRight c⟩
51+
| inl path₁ =>
52+
have ⟨groups, eqv, c⟩ := ih₁ rfl wf next_lt path₁
53+
exact ⟨groups, eqv, .alternateLeft c⟩
54+
| inr path₂ =>
55+
have wf₁ := wf₁ wf next_lt
56+
have ⟨groups, eqv, c⟩ := ih₂ rfl wf₁ (by grind) path₂
57+
exact ⟨groups, eqv, .alternateRight c⟩
11658

11759
theorem captures_of_path.concat {e₁ e₂} (eq : nfa.pushRegex next (.concat e₁ e₂) = result)
11860
(wf : nfa.WellFormed) (next_lt : next < nfa.size)
@@ -130,19 +72,15 @@ theorem captures_of_path.concat {e₁ e₂} (eq : nfa.pushRegex next (.concat e
13072
∃ groups, EquivUpdate groups update ∧ (Expr.concat e₁ e₂).Captures pos pos' groups := by
13173
open Compile.ProofData Concat in
13274
let pd := Concat.intro eq
133-
simp [pd.eq_result eq] at path
134-
have next_lt₂ : next < nfa₂.size := Nat.lt_trans next_lt nfa₂_property
135-
have ge_start : nfa₂.size ≤ nfa'.start := ge_pushRegex_start rfl
136-
have ne_next : next ≠ nfa₂.start := Nat.ne_of_lt (Nat.lt_of_lt_of_le next_lt (ge_pushRegex_start rfl))
137-
have ⟨itm, update₁, update₂, equ, path₁, path₂⟩ := path.path_next_of_ne rfl next_lt₂ ge_start ne_next
138-
75+
simp only [pd.eq_result eq] at path
76+
obtain ⟨pm, updates₁, updates₂, rfl, path₁, path₂⟩ := (pd.path_start_iff wf next_lt).mp path
13977
have wf₂ := wf₂ wf next_lt
140-
havegroup₁, eqv₁, c₁⟩ := ih₁ rfl wf₂ wf₂.start_lt path₁
141-
havegroup₂, eqv₂, c₂⟩ := ih₂ rfl wf next_lt (castTo₂ wf next_lt path₂)
142-
exact ⟨.concat group₁ group₂, equ ▸ .concat eqv₁ eqv₂, .concat c₁ c₂⟩
78+
havegroups₁, eqv₁, c₁⟩ := ih₁ rfl wf₂ wf₂.start_lt path₁
79+
havegroups₂, eqv₂, c₂⟩ := ih₂ rfl wf next_lt path₂
80+
exact ⟨.concat groups₁ groups₂, .concat eqv₁ eqv₂, .concat c₁ c₂⟩
14381

14482
open Compile.ProofData Star in
145-
theorem captures_of_path.star_of_loop [Star] {greedy} (loop : Loop pos pos' update)
83+
theorem captures_of_path.star_of_loop [Star] {greedy : Bool} (loop : Loop pos pos' update)
14684
(ih : ∀ {pos pos' : Pos s} {update},
14785
nfa'.Path nfaPlaceholder.size nfaExpr.start pos nfaPlaceholder.start pos' update →
14886
∃ groups, EquivUpdate groups update ∧ e.Captures pos pos' groups) :
@@ -165,23 +103,20 @@ theorem captures_of_path.star {greedy e} (eq : nfa.pushRegex next (.star greedy
165103
∃ groups, EquivUpdate groups update ∧ (Expr.star greedy e).Captures pos pos' groups := by
166104
open Compile.ProofData Star in
167105
let pd := Star.intro eq
168-
simp [pd.eq_result eq] at path
169-
cases path with
170-
| last step =>
171-
obtain ⟨_, rfl, rfl⟩ := step_start_iff.mp step
106+
simp only [pd.eq_result eq] at path
107+
have h := (pd.path_start_iff next_lt).mp path
108+
match h with
109+
| .inl ⟨hp, hupdate⟩ =>
110+
subst pos' update
172111
exact ⟨.empty, .empty, .starEpsilon⟩
173-
| @more _ _ i pos'' _ _ _ updates step rest =>
174-
obtain ⟨eqi, rfl, rfl⟩ := step_start_iff.mp step
175-
cases eqi with
176-
| inl eqi =>
177-
have loop := Loop.intro wf next_lt (eqi ▸ rest)
178-
apply captures_of_path.star_of_loop (greedy := greedy) loop
112+
| .inr path =>
113+
have loop := Loop.intro wf next_lt path
114+
apply captures_of_path.star_of_loop loop
179115

180-
intro pos pos' update path
181-
have path := castToExpr wf path
182-
have wfPlaceholder := wfPlaceholder wf
183-
exact ih (by grind) wfPlaceholder wfPlaceholder.start_lt path
184-
| inr eqi => grind
116+
intro pos pos' update path
117+
have path := castToExpr wf path
118+
have wfPlaceholder := wfPlaceholder wf
119+
exact ih (by grind) wfPlaceholder wfPlaceholder.start_lt path
185120

186121
public theorem captures_of_path (eq : nfa.pushRegex next e = result)
187122
(wf : nfa.WellFormed) (next_lt : next < nfa.size)
@@ -191,27 +126,27 @@ public theorem captures_of_path (eq : nfa.pushRegex next e = result)
191126
induction e generalizing nfa next result pos pos' update with
192127
| empty =>
193128
let pd := Empty.intro eq
194-
simp [pd.eq_result eq] at path
129+
simp only [pd.eq_result eq] at path
195130
exact absurd path pd.not_path_start
196131
| epsilon =>
197132
let pd := Epsilon.intro eq
198-
simp [pd.eq_result eq] at path
133+
simp only [pd.eq_result eq] at path
199134
have := (pd.path_start_iff next_lt).mp path
200135
simp [this]
201136
exact ⟨.empty, .empty, .epsilon⟩
202137
| anchor a =>
203138
let pd := Anchor.intro eq
204-
simp [pd.eq_result eq] at path
139+
simp only [pd.eq_result eq] at path
205140
obtain ⟨_, rfl, rfl, test⟩:= (pd.path_start_iff next_lt).mp path
206141
exact ⟨.empty, .empty, .anchor test⟩
207142
| char c =>
208143
let pd := Char.intro eq
209-
simp [pd.eq_result eq] at path
144+
simp only [pd.eq_result eq] at path
210145
obtain ⟨_, rfl, ne, rfl, rfl⟩ := (pd.path_start_iff next_lt).mp path
211146
exact ⟨.empty, .empty, .char ne rfl⟩
212147
| classes cs =>
213148
let pd := Classes.intro eq
214-
simp [pd.eq_result eq] at path
149+
simp only [pd.eq_result eq] at path
215150
obtain ⟨_, rfl, ne, rfl, mem⟩ := (pd.path_start_iff next_lt).mp path
216151
exact ⟨.empty, .empty, .sparse ne mem⟩
217152
| group tag e ih => exact captures_of_path.group eq wf next_lt path ih

correctness/RegexCorrectness/NFA/Semantics/Equivalence/PathOfCaptures.lean

Lines changed: 33 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -21,24 +21,15 @@ theorem path_of_captures.group {tag} (eq : nfa.pushRegex next (.group tag e) = r
2121
∃ update, EquivUpdate (.group tag pos pos' groups) update ∧ result.Path nfa.size result.start pos next pos' update := by
2222
open Compile.ProofData Group in
2323
let pd := Group.intro eq
24-
simp [eq_result eq]
24+
simp only [eq_result eq]
2525

2626
have wfClose := wfClose wf next_lt
27-
have ⟨update, eqv, path⟩ := ih (result := nfaExpr) rfl wfClose wfClose.start_lt
28-
exists (2 * tag, pos) :: update ++ [(2 * tag + 1, pos')], .group eqv
29-
30-
have stepOpen : nfa'.Step nfa.size nfa'.start pos nfaExpr.start pos (.some (2 * tag, pos)) := by
31-
apply step_start_iff.mpr
32-
exact ⟨rfl, rfl, rfl⟩
33-
have path := castFromExpr path
34-
have path : nfa'.Path nfa.size nfaExpr.start pos nfaClose.start pos' update :=
35-
path.liftBound (by simp [Group.nfaClose]; exact Nat.le_succ _)
36-
have pathClose : nfa'.Path nfa.size nfaClose.start pos' next pos' [(2 * tag + 1, pos')] := by
37-
have stepClose : nfa'.Step nfa.size nfaClose.start pos' next pos' (.some (2 * tag + 1, pos')) := by
38-
apply step_close_iff.mpr
39-
exact ⟨rfl, rfl, rfl⟩
40-
exact .last stepClose
41-
exact .more stepOpen (path.trans pathClose)
27+
have ⟨updates, eqv, path⟩ := ih (show nfaClose.pushRegex nfaClose.start e' = nfaExpr from rfl) wfClose wfClose.start_lt
28+
exact ⟨
29+
(2 * tag, pos) :: updates ++ [(2 * tag + 1, pos')],
30+
.group eqv,
31+
(pd.path_start_iff wf next_lt).mpr (by grind)
32+
4233

4334
theorem path_of_captures.alternateLeft {e₁ e₂} (eq : nfa.pushRegex next (.alternate e₁ e₂) = result)
4435
(wf : nfa.WellFormed) (next_lt : next < nfa.size)
@@ -49,16 +40,10 @@ theorem path_of_captures.alternateLeft {e₁ e₂} (eq : nfa.pushRegex next (.al
4940
∃ update, EquivUpdate groups update ∧ result.Path nfa.size result.start pos next pos' update := by
5041
open Compile.ProofData Alternate in
5142
let pd := Alternate.intro eq
52-
simp [eq_result eq]
43+
simp only [eq_result eq]
5344

54-
have ⟨update, eqv, path⟩ := ih (result := nfa₁) rfl wf next_lt
55-
exists update, eqv
56-
57-
have step : nfa'.Step nfa.size nfa'.start pos nfa₁.start pos .none := by
58-
apply step_start_iff.mpr
59-
simp
60-
have path := castFrom₁ path
61-
exact .more step path
45+
have ⟨update, eqv, path⟩ := ih (show nfa.pushRegex next e₁ = nfa₁ from rfl) wf next_lt
46+
exact ⟨update, eqv, (pd.path_start_iff wf next_lt).mpr (by grind)⟩
6247

6348
theorem path_of_captures.alternateRight {e₁ e₂} (eq : nfa.pushRegex next (.alternate e₁ e₂) = result)
6449
(wf : nfa.WellFormed) (next_lt : next < nfa.size)
@@ -69,17 +54,11 @@ theorem path_of_captures.alternateRight {e₁ e₂} (eq : nfa.pushRegex next (.a
6954
∃ update, EquivUpdate groups update ∧ result.Path nfa.size result.start pos next pos' update := by
7055
open Compile.ProofData Alternate in
7156
let pd := Alternate.intro eq
72-
simp [eq_result eq]
57+
simp only [eq_result eq]
7358

7459
have wf₁ := wf₁ wf next_lt
75-
have ⟨update, eqv, path⟩ := ih (result := nfa₂) rfl wf₁ (Nat.lt_trans next_lt nfa₁_property)
76-
exists update, eqv
77-
78-
have step : nfa'.Step nfa.size nfa'.start pos nfa₂.start pos .none := by
79-
apply step_start_iff.mpr
80-
simp
81-
have path := castFrom₂ (path.liftBound (Nat.le_of_lt nfa₁_property))
82-
exact .more step path
60+
have ⟨update, eqv, path⟩ := ih (show nfa₁.pushRegex next e₂ = nfa₂ from rfl) wf₁ (Nat.lt_trans next_lt nfa₁_property)
61+
exact ⟨update, eqv, (pd.path_start_iff wf next_lt).mpr (by grind)⟩
8362

8463
theorem path_of_captures.concat {pos'' e₁ e₂ groups₁ groups₂} (eq : nfa.pushRegex next (.concat e₁ e₂) = result)
8564
(wf : nfa.WellFormed) (next_lt : next < nfa.size)
@@ -94,15 +73,12 @@ theorem path_of_captures.concat {pos'' e₁ e₂ groups₁ groups₂} (eq : nfa.
9473
∃ update, EquivUpdate (.concat groups₁ groups₂) update ∧ result.Path nfa.size result.start pos next pos'' update := by
9574
open Compile.ProofData Concat in
9675
let pd := Concat.intro eq
97-
simp [pd.eq_result eq]
76+
simp only [pd.eq_result eq]
9877

9978
have wf₂ := wf₂ wf next_lt
10079
have ⟨update₁, eqv₁, path₁⟩ := ih₁ eq_push.symm wf₂ wf₂.start_lt
101-
have ⟨update₂, eqv₂, path₂⟩ := ih₂ (result := nfa₂) rfl wf next_lt
102-
exists update₁ ++ update₂, .concat eqv₁ eqv₂
103-
104-
have path₂ := castFrom₂ path₂
105-
exact (path₁.liftBound (Nat.le_of_lt nfa₂_property)).trans path₂
80+
have ⟨update₂, eqv₂, path₂⟩ := ih₂ (show nfa.pushRegex next e₂ = nfa₂ from rfl) wf next_lt
81+
exact ⟨update₁ ++ update₂, .concat eqv₁ eqv₂, (pd.path_start_iff wf next_lt).mpr (by grind)⟩
10682

10783
theorem path_of_captures.starConcat {pos'' greedy e groups₁ groups₂} (eq : nfa.pushRegex next (.star greedy e) = result)
10884
(wf : nfa.WellFormed) (next_lt : next < nfa.size)
@@ -117,24 +93,19 @@ theorem path_of_captures.starConcat {pos'' greedy e groups₁ groups₂} (eq : n
11793
∃ update, EquivUpdate (.concat groups₁ groups₂) update ∧ result.Path nfa.size result.start pos next pos'' update := by
11894
open Compile.ProofData Star in
11995
let pd := Star.intro eq
120-
simp [pd.eq_result eq]
96+
simp only [pd.eq_result eq]
12197

12298
have wfPlaceholder := wfPlaceholder wf
123-
have ⟨update₁, eqv₁, path₁⟩ := ih₁ (result := nfaExpr) (by grind only [= nfaPlaceholder,
124-
= Star.intro, = nfaExpr, = pushNode_start]) wfPlaceholder wfPlaceholder.start_lt
125-
have ⟨update₂, eqv₂, path₂⟩ := ih₂ (result := nfa') rfl wf next_lt
126-
exists update₁ ++ update₂, .concat eqv₁ eqv₂
127-
128-
have wf' : nfa'.WellFormed := pushRegex_wf wf next_lt
129-
130-
have path₁ : nfa'.Path nfa.size nfaExpr.start pos nfaPlaceholder.start pos' update₁ :=
131-
(castFromExpr path₁).liftBound (by grind only [nfaPlaceholder, Star.intro, = pushNode_size])
132-
have step : nfa'.Step nfa.size nfa'.start pos nfaExpr.start pos .none :=
133-
step_start_iff.mpr ⟨.inl rfl, rfl, rfl⟩
134-
have path₁ : nfa'.Path nfa.size nfa'.start pos nfaPlaceholder.start pos' update₁ :=
135-
.more step path₁
136-
137-
have path₂ : nfa'.Path nfa.size nfaPlaceholder.start pos' next pos'' update₂ := by
99+
have ⟨updates₁, eqv₁, path₁⟩ :=
100+
ih₁ (show nfaPlaceholder.pushRegex nfaPlaceholder.start e = nfaExpr by grind) wfPlaceholder wfPlaceholder.start_lt
101+
have ⟨updates₂, eqv₂, path₂⟩ := ih₂ (show nfa.pushRegex next (.star greedy e) = nfa' from rfl) wf next_lt
102+
exists updates₁ ++ updates₂, .concat eqv₁ eqv₂
103+
apply (pd.path_start_iff next_lt).mpr (.inr ?_)
104+
105+
have path₁ : nfa'.Path nfa.size nfaExpr.start pos nfaPlaceholder.start pos' updates₁ :=
106+
(castFromExpr path₁).liftBound (by grind)
107+
have path₂ : nfa'.Path nfa.size nfaPlaceholder.start pos' next pos'' updates₂ := by
108+
have wf' : nfa'.WellFormed := pushRegex_wf wf next_lt
138109
apply path₂.castHead
139110
. simp [pd.get_placeholder_start, pd.get_start]
140111
. grind only [nfaPlaceholder, Star.intro, = start.eq_1, = pushNode_start]
@@ -152,25 +123,25 @@ public theorem path_of_captures (eq : nfa.pushRegex next e = result)
152123
| char ne hc =>
153124
let pd := Char.intro eq
154125
exists [], .empty
155-
simp [pd.eq_result eq]
126+
simp only [pd.eq_result eq]
156127
apply (pd.path_start_iff next_lt).mpr
157128
exact ⟨rfl, rfl, ne, rfl, hc⟩
158129
| sparse ne mem =>
159130
let pd := Classes.intro eq
160131
exists [], .empty
161-
simp [pd.eq_result eq]
132+
simp only [pd.eq_result eq]
162133
apply (pd.path_start_iff next_lt).mpr
163134
exact ⟨rfl, rfl, ne, rfl, mem⟩
164135
| epsilon =>
165136
let pd := Epsilon.intro eq
166137
exists [], .empty
167-
simp [pd.eq_result eq]
138+
simp only [pd.eq_result eq]
168139
apply (pd.path_start_iff next_lt).mpr
169140
trivial
170141
| anchor h =>
171142
let pd := Anchor.intro eq
172143
exists [], .empty
173-
simp [pd.eq_result eq]
144+
simp only [pd.eq_result eq]
174145
apply (pd.path_start_iff next_lt).mpr
175146
trivial
176147
| group c ih => exact path_of_captures.group eq wf next_lt ih
@@ -180,12 +151,8 @@ public theorem path_of_captures (eq : nfa.pushRegex next e = result)
180151
| @starEpsilon pos _ _ =>
181152
let pd := Star.intro eq
182153
exists [], .empty
183-
simp [pd.eq_result eq]
184-
185-
have step : nfa'.Step nfa.size nfa'.start pos next pos .none := by
186-
apply (pd.step_start_iff).mpr
187-
exact ⟨.inr rfl, rfl, rfl⟩
188-
exact .last step
154+
simp only [pd.eq_result eq]
155+
exact (pd.path_start_iff next_lt).mpr (.inl ⟨rfl, rfl⟩)
189156
| starConcat c₁ _ ih₁ ih₂ => exact path_of_captures.starConcat eq wf next_lt ih₁ ih₂
190157

191158
public theorem path_of_captures_compile (eq : compile e = nfa) (c : e.Captures pos pos' groups) :

0 commit comments

Comments
 (0)