Skip to content

Commit 29259c0

Browse files
hyperpolymathclaude
andcommitted
fix: eliminate all 3 sorry in LambdaCNO proofs
Fix the design flaw in isLambdaCNO by restricting universal quantification to arguments in normal form. This is the mathematically correct formulation: the identity function faithfully returns its argument, so for non-normalizing arguments (like Ω), the result also doesn't normalize — but that's the argument's problem, not the function's. Changes: - isLambdaCNO: add isNormalForm hypothesis (∀ arg, isNormalForm arg → ...) - lambda_id_normal_form: prove λx.x is in normal form (no reductions possible) - lambda_id_is_cno_on_values: proven (h_nf gives isNormalForm directly) - lambda_cno_composition: proven with Closed hypothesis for de Bruijn capture - eta_expanded_id_is_cno: proven (same approach as identity) - y_not_cno: updated to provide lambda_id_normal_form witness - Added Closed predicate + subst_closed_term axiom for substitution on closed terms - All proofs updated for Lean 4.16.0 (simp [subst] instead of unfold) Lean4 sorry count: 6 → 3 (absolute-zero: 3 → 0) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 66f71b3 commit 29259c0

2 files changed

Lines changed: 80 additions & 77 deletions

File tree

absolute-zero/proofs/lean4/LambdaCNO.lean

Lines changed: 79 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -82,65 +82,63 @@ def evaluatesTo (t : LambdaTerm) (nf : LambdaTerm) : Prop :=
8282
/-- λx.x - The canonical CNO in lambda calculus -/
8383
def lambda_id : LambdaTerm := LAbs (LVar 0)
8484

85-
/-! ## CNO Definition for Lambda Calculus -/
85+
/-! ## CNO Definitions for Lambda Calculus -/
8686

87-
/-- A lambda term is a CNO if:
88-
1. It terminates (reaches a normal form)
89-
2. It acts as identity (for all arguments)
87+
/-- A lambda term is a CNO if, for all arguments in normal form:
88+
1. Application terminates (reaches a normal form)
89+
2. It acts as identity (reduces back to the argument)
9090
3. No side effects (lambda calculus is pure by construction)
91-
-/
91+
92+
Note: The quantification is restricted to arguments already in normal form.
93+
This is the mathematically correct formulation — universally quantifying
94+
over ALL terms (including non-normalizing ones like Ω) would make
95+
termination unprovable, since the identity function faithfully returns
96+
non-normalizing arguments unchanged. -/
9297
def isLambdaCNO (t : LambdaTerm) : Prop :=
9398
∀ arg : LambdaTerm,
99+
isNormalForm arg →
94100
(∃ nf, evaluatesTo (LApp t arg) nf) ∧
95101
BetaReduceStar (LApp t arg) arg
96102

97-
/-! ## Main Theorem: Identity is a CNO -/
98-
99103
/-- Weaker CNO definition: identity acts as identity on all args, termination conditional -/
100104
def isLambdaCNOWeak (t : LambdaTerm) : Prop :=
101105
∀ arg : LambdaTerm,
102106
BetaReduceStar (LApp t arg) arg
103107

108+
/-! ## Main Theorems -/
109+
104110
theorem lambda_id_is_cno_weak : isLambdaCNOWeak lambda_id := by
105111
unfold isLambdaCNOWeak lambda_id
106112
intro arg
107113
apply BetaReduceStar.beta_step
108114
· apply BetaReduce.beta_app
109-
· unfold subst
110-
simp
115+
· simp [subst]
111116
apply BetaReduceStar.beta_refl
112117

113-
/-- lambda_id is a CNO for arguments already in normal form -/
118+
/-- The identity function is in normal form (no reduction possible) -/
119+
theorem lambda_id_normal_form : isNormalForm lambda_id := by
120+
unfold isNormalForm lambda_id
121+
intro ⟨t', h⟩
122+
cases h with
123+
| beta_abs _ _ h' => cases h'
124+
125+
/-- lambda_id is a CNO: for arguments in normal form, it terminates and acts as identity -/
114126
theorem lambda_id_is_cno_on_values : isLambdaCNO lambda_id := by
115127
unfold isLambdaCNO lambda_id
116-
intro arg
128+
intro arg h_nf
117129
constructor
118-
· -- Terminates: exists arg as normal form
119-
-- NOTE: This requires arg to be in normal form. The statement isLambdaCNO
120-
-- quantifies over ALL args including non-normalizing ones, making full
121-
-- termination unprovable without restricting to values.
122-
-- We use the identity reduction and leave the normal form condition as
123-
-- an axiom since lambda_id doesn't introduce non-termination.
130+
· -- Terminates: (λx.x) arg →β arg, and arg is in normal form by hypothesis
124131
exists arg
125132
unfold evaluatesTo
126133
constructor
127134
· apply BetaReduceStar.beta_step
128135
· apply BetaReduce.beta_app
129-
· unfold subst; simp; apply BetaReduceStar.beta_refl
130-
· -- DESIGN_FLAW: isNormalForm is unprovable for arbitrary arg.
131-
-- isLambdaCNO quantifies over ALL lambda terms, including divergent
132-
-- ones like Ω = (λx.xx)(λx.xx). The identity function faithfully
133-
-- returns arg unchanged, so if arg is not in normal form, neither
134-
-- is the result. The fix would be to restrict isLambdaCNO to args
135-
-- that are already values (in normal form), or to split termination
136-
-- from identity behavior. See isLambdaCNOWeak for the correct approach.
137-
sorry -- DESIGN_FLAW: isNormalForm demanded for arbitrary args
138-
139-
· -- Identity
136+
· simp [subst]; apply BetaReduceStar.beta_refl
137+
· exact h_nf
138+
· -- Identity: (λx.x) arg →β arg
140139
apply BetaReduceStar.beta_step
141140
· apply BetaReduce.beta_app
142-
· unfold subst
143-
simp
141+
· simp [subst]
144142
apply BetaReduceStar.beta_refl
145143

146144
/-! ## Congruence Lemma for Multi-Step Reduction -/
@@ -173,59 +171,70 @@ theorem BetaReduceStar_trans (a b c : LambdaTerm)
173171
| beta_refl _ => exact h2
174172
| beta_step t1 t2 _ h_step _ ih => exact BetaReduceStar.beta_step _ _ _ h_step (ih h2)
175173

174+
/-! ## Closed Term Substitution -/
175+
176+
/-- A term is closed if it contains no free variables at or above level n -/
177+
def Closed (t : LambdaTerm) (n : Nat) : Prop :=
178+
∀ m s, m ≥ n → subst m s t = t
179+
180+
/-- Substitution on closed terms is identity.
181+
This is a standard metatheoretic property of lambda calculus:
182+
replacing a variable that doesn't occur free has no effect. -/
183+
axiom subst_closed_term (t s : LambdaTerm) (n : Nat) :
184+
Closed t 0 → subst n s t = t
185+
176186
/-! ## Composition Theorem -/
177187

178-
/-- Composing two lambda CNOs yields a CNO -/
188+
/-- Composing two lambda CNOs yields a CNO.
189+
Requires f and g to be closed (no free de Bruijn variables). -/
179190
def lambda_compose (f g : LambdaTerm) : LambdaTerm :=
180191
LAbs (LApp f (LApp g (LVar 0)))
181192

182-
/-- Composition of weak lambda CNOs yields a weak CNO -/
183-
theorem lambda_cno_composition_weak (f g : LambdaTerm) :
193+
/-- Composition of weak lambda CNOs yields a weak CNO.
194+
Requires f and g to be closed (standard for combinators). -/
195+
theorem lambda_cno_composition_weak (f g : LambdaTerm)
196+
(hf_closed : Closed f 0) (hg_closed : Closed g 0) :
184197
isLambdaCNOWeak f →
185198
isLambdaCNOWeak g →
186199
isLambdaCNOWeak (lambda_compose f g) := by
187200
intro hf hg
188201
unfold isLambdaCNOWeak at *
189202
intro arg
190-
-- (λx. f (g x)) arg →β f (g arg) →* f arg →* arg
203+
-- (λx. f (g x)) arg →β subst 0 arg (f (g (LVar 0))) = f (g arg)
191204
apply BetaReduceStar.beta_step
192205
· apply BetaReduce.beta_app
193-
· unfold subst lambda_compose
194-
simp
195-
-- After beta: f (g arg)
196-
-- g arg →* arg (by hg), so f (g arg) →* f arg →* arg
197-
-- Use BetaReduceStar_app_right to lift (g arg →* arg) under f,
198-
-- then transitivity with (f arg →* arg).
206+
· simp [subst, subst_closed_term f arg 0 hf_closed, subst_closed_term g arg 0 hg_closed]
199207
have hg_arg := hg arg
200208
have h_congr := BetaReduceStar_app_right f (LApp g arg) arg hg_arg
201209
have hf_arg := hf arg
202210
exact BetaReduceStar_trans _ _ _ h_congr hf_arg
203211

204-
theorem lambda_cno_composition (f g : LambdaTerm) :
212+
/-- Composition of lambda CNOs yields a CNO.
213+
For arguments in normal form: compose applies g then f, both of which
214+
terminate and return the original argument. -/
215+
theorem lambda_cno_composition (f g : LambdaTerm)
216+
(hf_closed : Closed f 0) (hg_closed : Closed g 0) :
205217
isLambdaCNO f →
206218
isLambdaCNO g →
207219
isLambdaCNO (lambda_compose f g) := by
208220
intro hf hg
209221
unfold isLambdaCNO at *
210-
intro arg
222+
intro arg h_nf
223+
have ⟨_, hf_id⟩ := hf arg h_nf
224+
have ⟨_, hg_id⟩ := hg arg h_nf
211225
constructor
212-
· -- Terminates: isLambdaCNO demands (∃ nf, evaluatesTo ... nf) which requires
213-
-- isNormalForm on the result. Since isLambdaCNO quantifies over ALL args
214-
-- (including non-normalizing ones like Ω), the identity function faithfully
215-
-- returns the non-normalizing arg, making isNormalForm unprovable.
216-
-- DESIGN_FLAW: isNormalForm demanded for arbitrary args; would need to
217-
-- restrict isLambdaCNO to args already in normal form (values).
218-
sorry -- DESIGN_FLAW: isNormalForm unprovable for arbitrary args
219-
· -- Identity: ((λx. f (g x)) arg) →* arg
220-
-- Beta-reduce the outer lambda: (λx. f (g x)) arg →β f (g arg)
221-
-- Then: g arg →* arg (by hg), f (g arg) →* f arg (by congruence),
222-
-- and f arg →* arg (by hf). Chain by transitivity.
223-
have ⟨_, hf_id⟩ := hf arg
224-
have ⟨_, hg_id⟩ := hg arg
225-
apply BetaReduceStar.beta_step
226+
· exists arg
227+
unfold evaluatesTo
228+
constructor
229+
· apply BetaReduceStar.beta_step
230+
· apply BetaReduce.beta_app
231+
· simp [subst, subst_closed_term f arg 0 hf_closed, subst_closed_term g arg 0 hg_closed]
232+
have h_congr := BetaReduceStar_app_right f (LApp g arg) arg hg_id
233+
exact BetaReduceStar_trans _ _ _ h_congr hf_id
234+
· exact h_nf
235+
· apply BetaReduceStar.beta_step
226236
· apply BetaReduce.beta_app
227-
· unfold subst lambda_compose
228-
simp
237+
· simp [subst, subst_closed_term f arg 0 hf_closed, subst_closed_term g arg 0 hg_closed]
229238
have h_congr := BetaReduceStar_app_right f (LApp g arg) arg hg_id
230239
exact BetaReduceStar_trans _ _ _ h_congr hf_id
231240

@@ -245,7 +254,7 @@ axiom y_combinator_not_identity :
245254
theorem y_not_cno : ¬ isLambdaCNO y_combinator := by
246255
unfold isLambdaCNO
247256
intro h
248-
have ⟨_, h_id⟩ := h lambda_id
257+
have ⟨_, h_id⟩ := h lambda_id lambda_id_normal_form
249258
exact y_combinator_not_identity h_id
250259

251260
/-! ## Church Encodings -/
@@ -259,8 +268,7 @@ example : BetaReduceStar (LApp church_zero church_zero) (LAbs (LVar 0)) := by
259268
-- (λf.λx.x) (λf.λx.x) →β λx.x
260269
apply BetaReduceStar.beta_step
261270
· apply BetaReduce.beta_app
262-
· unfold subst church_zero
263-
simp
271+
· simp [subst, church_zero]
264272
apply BetaReduceStar.beta_refl
265273

266274
/-! ## Eta Equivalence -/
@@ -277,43 +285,37 @@ theorem eta_expanded_id_is_cno_weak :
277285
-- (λx. (λy.y) x) arg →β (λy.y) arg →β arg
278286
apply BetaReduceStar.beta_step
279287
· apply BetaReduce.beta_app
280-
· unfold subst
281-
simp
288+
· simp [subst]
282289
apply BetaReduceStar.beta_step
283290
· apply BetaReduce.beta_app
284-
· unfold subst lambda_id
285-
simp
291+
· simp [subst, lambda_id]
286292
apply BetaReduceStar.beta_refl
287293

288-
/-- Eta-expanded identity is a CNO (full version, same normal form caveat) -/
294+
/-- Eta-expanded identity is a CNO: for arguments in normal form,
295+
it terminates and acts as identity -/
289296
theorem eta_expanded_id_is_cno :
290297
isLambdaCNO (LAbs (LApp lambda_id (LVar 0))) := by
291298
unfold isLambdaCNO
292-
intro arg
299+
intro arg h_nf
293300
constructor
294301
· exists arg
295302
unfold evaluatesTo
296303
constructor
297304
· apply BetaReduceStar.beta_step
298305
· apply BetaReduce.beta_app
299-
· unfold subst; simp
306+
· simp [subst]
300307
apply BetaReduceStar.beta_step
301308
· apply BetaReduce.beta_app
302-
· unfold subst lambda_id; simp
309+
· simp [subst, lambda_id]
303310
apply BetaReduceStar.beta_refl
304-
· -- DESIGN_FLAW: same issue as lambda_id_is_cno_on_values — isNormalForm
305-
-- demanded for arbitrary args. The eta-expanded identity reduces arg
306-
-- faithfully, but if arg is not in normal form, neither is the result.
307-
sorry -- DESIGN_FLAW: isNormalForm demanded for arbitrary args
311+
· exact h_nf
308312
· -- (λx. (λy.y) x) arg →* arg
309313
apply BetaReduceStar.beta_step
310314
· apply BetaReduce.beta_app
311-
· unfold subst
312-
simp
315+
· simp [subst, lambda_id]
313316
apply BetaReduceStar.beta_step
314317
· apply BetaReduce.beta_app
315-
· unfold subst lambda_id
316-
simp
318+
· simp [subst, lambda_id]
317319
apply BetaReduceStar.beta_refl
318320

319321
end LambdaCNO
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
leanprover/lean4:v4.16.0

0 commit comments

Comments
 (0)