@@ -39,7 +39,12 @@ def CriticalPairsJoinable {sig : Signature} (rules : RuleSet sig) : Prop :=
3939 Every local peak is either immediately joinable in one step or
4040 corresponds to a critical pair (up to symmetry). This abstracts the
4141 standard overlap analysis used in critical pair theorems. -/
42+ /-- Rules with non-variable left-hand sides (standard TRS assumption). -/
43+ def NonVarLHS {sig : Signature} (rules : RuleSet sig) : Prop :=
44+ ∀ r, rules r → NonVar r.lhs
45+
4246def CriticalPairsComplete {sig : Signature} (rules : RuleSet sig) : Prop :=
47+ NonVarLHS rules →
4348 ∀ s b c, Step rules s b → Step rules s c →
4449 (∃ d, Step rules b d ∧ Step rules c d) ∨
4550 ∃ cp p, CriticalPairs rules cp ∧
@@ -52,15 +57,210 @@ def CriticalPairsComplete {sig : Signature} (rules : RuleSet sig) : Prop :=
5257
5358open Term
5459
60+ /-- Position trichotomy: two positions are either prefix-related or disjoint. -/
61+ private theorem pos_trichotomy (p q : Pos) :
62+ PosPrefix p q ∨ PosPrefix q p ∨ (¬ PosPrefix p q ∧ ¬ PosPrefix q p) := by
63+ induction p generalizing q with
64+ | nil => exact Or.inl ⟨q, by simp⟩
65+ | cons i ps ih =>
66+ cases q with
67+ | nil => exact Or.inr (Or.inl ⟨i :: ps, by simp⟩)
68+ | cons j qs =>
69+ by_cases hij : i = j
70+ · subst hij
71+ rcases ih qs with h | h | ⟨h1, h2⟩
72+ · rcases h with ⟨r, rfl⟩
73+ exact Or.inl ⟨r, by simp⟩
74+ · rcases h with ⟨r, rfl⟩
75+ exact Or.inr (Or.inl ⟨r, by simp⟩)
76+ · exact Or.inr (Or.inr ⟨
77+ fun ⟨r, hr⟩ => h1 ⟨r, by simpa using hr⟩,
78+ fun ⟨r, hr⟩ => h2 ⟨r, by simpa using hr⟩⟩)
79+ · exact Or.inr (Or.inr ⟨
80+ fun ⟨r, hr⟩ => hij (by simpa using List.cons_eq_cons.mp hr |>.1 ),
81+ fun ⟨r, hr⟩ => hij (by simpa using List.cons_eq_cons.mp hr |>.1 ).symm⟩)
82+
5583/-- Peak decomposition for first-order steps. -/
5684theorem criticalPairsComplete_of_steps {sig : Signature} {rules : RuleSet sig} :
5785 CriticalPairsComplete rules := by
58- sorry
86+ intro hnvl s b c hb hc
87+ -- Unpack the two steps
88+ rcases hb with ⟨r1, hr1, p1, sub1, hsub1, hrep1⟩
89+ rcases hc with ⟨r2, hr2, p2, sub2, hsub2, hrep2⟩
90+ -- Case split on position relationship
91+ rcases pos_trichotomy p1 p2 with hp | hp | ⟨hnotp, hnotq⟩
92+ · -- Case 1: p1 is prefix of p2 (p2 = p1 ++ q)
93+ rcases hp with ⟨q, rfl⟩
94+ -- r2 is applied inside the subterm matched by r1
95+ -- This is an overlap: a critical pair
96+ -- The subterm of s at p1 is sub1(r1.lhs), and at p1++q is sub2(r2.lhs)
97+ -- So sub1(r1.lhs) has sub2(r2.lhs) at position q
98+ have hsub2' : Term.subterm (Term.subst sub1 r1.lhs) q = some (Term.subst sub2 r2.lhs) := by
99+ have := Term.subterm_append (t := s) (p := p1) (q := q) (u := Term.subst sub1 r1.lhs) hsub1
100+ simpa using this ▸ hsub2
101+ -- Build the critical pair
102+ have hnonvar : NonVar (Term.subst sub2 r2.lhs) := by
103+ have h_nvl := hnvl r2 hr2
104+ cases r2.lhs with
105+ | var y => exact (h_nvl (by simp [IsVar])).elim
106+ | app f args => simp [NonVar, IsVar]
107+ -- Build the overlap and critical pair
108+ have hoverlap : Overlap r1 r2 q sub1 sub2 := ⟨hsub2', hnonvar⟩
109+ -- mkCriticalPair builds the pair
110+ cases hmk : mkCriticalPair r1 r2 q sub1 sub2 with
111+ | none =>
112+ -- If mkCriticalPair returns none, replace failed, but we know replace succeeds
113+ exfalso
114+ unfold mkCriticalPair at hmk
115+ cases hrep_inner : Term.replace (Term.subst sub1 r1.lhs) q (Term.subst sub2 r2.rhs) with
116+ | none =>
117+ -- replace at q must succeed since subterm at q exists
118+ rcases Term.replace_defined_of_replace (t := Term.subst sub1 r1.lhs) (p := q)
119+ (u := Term.subst sub2 r2.lhs) (t' := Term.subst sub1 r1.lhs)
120+ (Term.replace_self (t := Term.subst sub1 r1.lhs) (p := q)
121+ (u := Term.subst sub2 r2.lhs) hsub2')
122+ (Term.subst sub2 r2.rhs) with ⟨_, hrep_ok⟩
123+ simp [hrep_inner] at hrep_ok
124+ | some _ => simp [hrep_inner] at hmk
125+ | some cp =>
126+ -- We have a critical pair
127+ right
128+ refine ⟨cp, p1, ?_, ?_⟩
129+ · exact ⟨r1, r2, q, sub1, sub2, hr1, hr2, hoverlap, hmk⟩
130+ · -- Show b and c correspond to replacing at p1
131+ unfold mkCriticalPair at hmk
132+ cases hrep_inner : Term.replace (Term.subst sub1 r1.lhs) q (Term.subst sub2 r2.rhs) with
133+ | none => simp [hrep_inner] at hmk
134+ | some t_inner =>
135+ simp [hrep_inner] at hmk
136+ left
137+ constructor
138+ · -- b = replace(s, p1, sub1(r1.rhs)) and cp.left = sub1(r1.rhs)
139+ have hcp_left : cp.left = Term.subst sub1 r1.rhs := hmk.1
140+ rw [hcp_left]
141+ exact hrep1
142+ · -- c = replace(s, p1++q, sub2(r2.rhs)) and cp.right = t_inner
143+ -- = replace(sub1(r1.lhs), q, sub2(r2.rhs))
144+ have hcp_right : cp.right = t_inner := hmk.2
145+ rw [hcp_right]
146+ -- c = replace(s, p1++q, sub2(r2.rhs))
147+ -- = replace(s, p1, replace(sub1(r1.lhs), q, sub2(r2.rhs)))
148+ -- = replace(s, p1, t_inner)
149+ -- This follows from replace_append_inv and the relationship
150+ rcases Term.replace_append_inv (t := s) (u := Term.subst sub1 r1.lhs)
151+ (t' := c) (p := p1) (q := q) (v := Term.subst sub2 r2.rhs)
152+ hsub1 hrep2 with ⟨u', hrep_u', hrep_s⟩
153+ have : u' = t_inner := by
154+ have : (some u' : Option (Term sig)) = some t_inner := by
155+ rw [← hrep_u', ← hrep_inner]
156+ exact Option.some.inj this
157+ rw [this] at hrep_s
158+ exact hrep_s
159+ · -- Case 2: p2 is prefix of p1 (p1 = p2 ++ q)
160+ rcases hp with ⟨q, rfl⟩
161+ -- Symmetric to case 1: r1 is applied inside the subterm matched by r2
162+ have hsub1' : Term.subterm (Term.subst sub2 r2.lhs) q = some (Term.subst sub1 r1.lhs) := by
163+ have := Term.subterm_append (t := s) (p := p2) (q := q) (u := Term.subst sub2 r2.lhs) hsub2
164+ simpa using this ▸ hsub1
165+ have hnonvar : NonVar (Term.subst sub1 r1.lhs) := by
166+ have h_nvl := hnvl r1 hr1
167+ cases r1.lhs with
168+ | var y => exact (h_nvl (by simp [IsVar])).elim
169+ | app f args => simp [NonVar, IsVar]
170+ have hoverlap : Overlap r2 r1 q sub2 sub1 := ⟨hsub1', hnonvar⟩
171+ cases hmk : mkCriticalPair r2 r1 q sub2 sub1 with
172+ | none =>
173+ exfalso
174+ unfold mkCriticalPair at hmk
175+ cases hrep_inner : Term.replace (Term.subst sub2 r2.lhs) q (Term.subst sub1 r1.rhs) with
176+ | none =>
177+ rcases Term.replace_defined_of_replace (t := Term.subst sub2 r2.lhs) (p := q)
178+ (u := Term.subst sub1 r1.lhs) (t' := Term.subst sub2 r2.lhs)
179+ (Term.replace_self (t := Term.subst sub2 r2.lhs) (p := q)
180+ (u := Term.subst sub1 r1.lhs) hsub1')
181+ (Term.subst sub1 r1.rhs) with ⟨_, hrep_ok⟩
182+ simp [hrep_inner] at hrep_ok
183+ | some _ => simp [hrep_inner] at hmk
184+ | some cp =>
185+ right
186+ refine ⟨cp, p2, ?_, ?_⟩
187+ · exact ⟨r2, r1, q, sub2, sub1, hr2, hr1, hoverlap, hmk⟩
188+ · unfold mkCriticalPair at hmk
189+ cases hrep_inner : Term.replace (Term.subst sub2 r2.lhs) q (Term.subst sub1 r1.rhs) with
190+ | none => simp [hrep_inner] at hmk
191+ | some t_inner =>
192+ simp [hrep_inner] at hmk
193+ -- cp.left = sub2(r2.rhs), cp.right = t_inner
194+ right
195+ constructor
196+ · -- c corresponds to cp.left
197+ have hcp_left : cp.left = Term.subst sub2 r2.rhs := hmk.1
198+ rw [hcp_left]
199+ exact hrep2
200+ · -- b corresponds to cp.right
201+ have hcp_right : cp.right = t_inner := hmk.2
202+ rw [hcp_right]
203+ rcases Term.replace_append_inv (t := s) (u := Term.subst sub2 r2.lhs)
204+ (t' := b) (p := p2) (q := q) (v := Term.subst sub1 r1.rhs)
205+ hsub2 hrep1 with ⟨u', hrep_u', hrep_s⟩
206+ have : u' = t_inner := by
207+ have : (some u' : Option (Term sig)) = some t_inner := by
208+ rw [← hrep_u', ← hrep_inner]
209+ exact Option.some.inj this
210+ rw [this] at hrep_s
211+ exact hrep_s
212+ · -- Case 3: Disjoint positions
213+ -- Both rewrites can be applied independently
214+ left
215+ rcases Term.replace_comm_of_disjoint (t := s) (u := Term.subst sub1 r1.rhs)
216+ (v := Term.subst sub2 r2.rhs) (t1 := b) (t2 := c) (p := p1) (q := p2)
217+ hrep1 hrep2 hnotp hnotq with ⟨d, hrepd_from_b, hrepd_from_c⟩
218+ refine ⟨d, ?_, ?_⟩
219+ · -- Step from b to d: apply r2 at p2 in b
220+ -- subterm of b at p2 = subterm of s at p2 (since p1 and p2 are disjoint)
221+ have hsub2_in_b : Term.subterm b p2 = some (Term.subst sub2 r2.lhs) := by
222+ have := Term.subterm_replace_of_disjoint (t := s) (u := Term.subst sub1 r1.rhs)
223+ (t' := b) (p := p1) (q := p2) hrep1 hnotq hnotp
224+ rw [this]
225+ exact hsub2
226+ exact ⟨r2, hr2, p2, sub2, hsub2_in_b, hrepd_from_b⟩
227+ · -- Step from c to d: apply r1 at p1 in c
228+ have hsub1_in_c : Term.subterm c p1 = some (Term.subst sub1 r1.lhs) := by
229+ have := Term.subterm_replace_of_disjoint (t := s) (u := Term.subst sub2 r2.rhs)
230+ (t' := c) (p := p2) (q := p1) hrep2 hnotp hnotq
231+ rw [this]
232+ exact hsub1
233+ exact ⟨r1, hr1, p1, sub1, hsub1_in_c, hrepd_from_c⟩
59234
60235theorem criticalPairsJoinable_of_localConfluent
61236 {sig : Signature} {rules : RuleSet sig} (hlocal : LocalConfluent rules) :
62237 CriticalPairsJoinable rules := by
63- sorry
238+ intro cp hcp
239+ rcases hcp with ⟨r1, r2, p, sub1, sub2, hr1, hr2, hover, hmk⟩
240+ rcases hover with ⟨hsub_eq, hnonvar⟩
241+ -- The overlap gives us two steps from the same term
242+ -- Step 1: r1 applied at root gives cp.left (i.e., sub1(r1.rhs))
243+ -- Step 2: r2 applied at position p gives cp.right
244+ -- Both rewrite the same source term = sub1(r1.lhs)
245+ -- This is a local peak, so by local confluence they are joinable
246+ have hsource := Term.subst sub1 r1.lhs
247+ have hstep1 : Step rules hsource (Term.subst sub1 r1.rhs) := by
248+ exact ⟨r1, hr1, [], sub1, by simp [Term.subterm], by simp [Term.replace]⟩
249+ -- For step2 we need to extract the critical pair structure
250+ -- mkCriticalPair r1 r2 p sub1 sub2 = some cp means
251+ -- cp.left = sub1(r1.rhs), cp.right = replace(sub1(r1.lhs), p, sub2(r2.rhs))
252+ unfold mkCriticalPair at hmk
253+ cases hrep : Term.replace (Term.subst sub1 r1.lhs) p (Term.subst sub2 r2.rhs) with
254+ | none => simp [hrep] at hmk
255+ | some t =>
256+ simp [hrep] at hmk
257+ have hcp_left : cp.left = Term.subst sub1 r1.rhs := hmk.1
258+ have hcp_right : cp.right = t := hmk.2
259+ have hstep2 : Step rules hsource t := by
260+ exact ⟨r2, hr2, p, sub2, hsub_eq, hrep⟩
261+ rcases hlocal hsource (Term.subst sub1 r1.rhs) t hstep1 hstep2 with ⟨d, hd1, hd2⟩
262+ rw [hcp_left, hcp_right]
263+ exact ⟨d, hd1, hd2⟩
64264
65265private theorem step_context {sig : Signature} {rules : RuleSet sig}
66266 {t u v b c : Term sig} {p : Pos} :
@@ -111,10 +311,11 @@ private theorem star_context {sig : Signature} {rules : RuleSet sig}
111311/-- Critical pair theorem (completeness direction). -/
112312theorem localConfluent_of_criticalPairsJoinable
113313 {sig : Signature} {rules : RuleSet sig}
314+ (hnvl : NonVarLHS rules)
114315 (hjoin : CriticalPairsJoinable rules) :
115316 LocalConfluent rules := by
116317 intro s b c hb hc
117- have hcomplete := criticalPairsComplete_of_steps (rules := rules) s b c hb hc
318+ have hcomplete := criticalPairsComplete_of_steps (rules := rules) hnvl s b c hb hc
118319 rcases hcomplete with ⟨d, hbd, hcd⟩ | ⟨cp, p, hcp, hcases⟩
119320 · exact ⟨d, Rewriting.Star.single hbd, Rewriting.Star.single hcd⟩
120321 ·
@@ -166,7 +367,8 @@ theorem stableSizeLt_wf {sig : Signature} : WellFounded (stableSizeLt (sig := si
166367 · exact InvImage.wf Term.size Nat.lt_wfRel.wf
167368
168369theorem stableSizeLt_trans {sig : Signature} {a b c : Term sig} (hab : stableSizeLt a b) (hbc : stableSizeLt b c) : stableSizeLt a c := by
169- sorry
370+ intro sub
371+ exact Nat.lt_trans (hab sub) (hbc sub)
170372
171373theorem stableSizeLt_subst {sig : Signature} {sub : Subst sig} {s t : Term sig} :
172374 stableSizeLt (sig := sig) s t →
@@ -246,17 +448,19 @@ theorem confluent_of_terminating_localConfluent
246448/-- Knuth-Bendix completion soundness: terminating + joinable critical pairs imply confluence. -/
247449theorem confluent_of_terminating_criticalPairsJoinable
248450 {sig : Signature} {rules : RuleSet sig}
451+ (hnvl : NonVarLHS rules)
249452 (hterm : Terminating rules)
250453 (hjoin : CriticalPairsJoinable rules) :
251454 Confluent rules := by
252455 apply confluent_of_terminating_localConfluent hterm
253- exact localConfluent_of_criticalPairsJoinable hjoin
456+ exact localConfluent_of_criticalPairsJoinable hnvl hjoin
254457
255458/-! ## Knuth-Bendix Completion Certificates -/
256459
257460/-- Knuth-Bendix completion certificate: oriented rules + joinable critical pairs. -/
258461structure KnuthBendixComplete {sig : Signature} (rules : RuleSet sig)
259462 (ord : ReductionOrdering sig) : Prop where
463+ nonVarLHS : NonVarLHS rules
260464 orient : ∀ r, rules r → ord.lt r.rhs r.lhs
261465 criticalPairsJoinable : CriticalPairsJoinable rules
262466
@@ -265,7 +469,7 @@ theorem confluent_of_knuthBendixComplete {sig : Signature} {rules : RuleSet sig}
265469 {ord : ReductionOrdering sig}
266470 (hkb : KnuthBendixComplete rules ord) :
267471 Confluent rules := by
268- apply confluent_of_terminating_criticalPairsJoinable
472+ apply confluent_of_terminating_criticalPairsJoinable hkb.nonVarLHS
269473 · exact terminating_of_ordering (ord := ord) hkb.orient
270474 · exact hkb.criticalPairsJoinable
271475
0 commit comments