lean4-htt/tests/lean/simpZetaFalse.lean.expected.out
Kyle Miller 7abc9106d7
feat: optimized simp routine for let telescopes (#8968)
This PR adds the following features to `simp`:
- A routine for simplifying `have` telescopes in a way that avoids
quadratic complexity arising from locally nameless expression
representations, like what #6220 did for `letFun` telescopes.
Furthermore, simp converts `letFun`s into `have`s (nondependent lets),
and we remove the #6220 routine since we are moving away from `letFun`
encodings of nondependent lets.
- A `+letToHave` configuration option (enabled by default) that converts
lets into haves when possible, when `-zeta` is set. Previously Lean
would need to do a full typecheck of the bodies of `let`s, but the
`letToHave` procedure can skip checking some subexpressions, and it
modifies the `let`s in an entire expression at once rather than one at a
time.
- A `+zetaHave` configuration option, to turn off zeta reduction of
`have`s specifically. The motivation is that dependent `let`s can only
be dsimped by let, so zeta reducing just the dependent lets is a
reasonable way to make progress. The `+zetaHave` option is also added to
the meta configuration.
- When `simp` is zeta reducing, it now uses an algorithm that avoids
complexity quadratic in the depth of the let telescope.
- Additionally, the zeta reduction routines in `simp`, `whnf`, and
`isDefEq` now all are consistent with how they apply the `zeta`,
`zetaHave`, and `zetaUnused` configurations.

The `letToFun` option is addressing a TODO in `getSimpLetCase` ("handle
a block of nested let decls in a single pass if this becomes a
performance problem").

Performance should be compared to before #8804, which temporarily
disabled the #6220 optimizations for `letFun` telescopes.

Good kernel performance depends on carefully handling the `have`
encoding. Due to the way the kernel instantiates bvars (it does *not*
beta reduce when instantiating), we cannot use congruence theorems of
the form `(have x := v; f x) = (have x ;= v'; f' x)`, since the bodies
of the `have`s will not be syntactically equal, which triggers zeta
reduction in the kernel in `is_def_eq`. Instead, we work with `f v = f'
v'`, where `f` and `f'` are lambda expressions. There is still zeta
reduction, but only when converting between these two forms at the
outset of the generated proof.
2025-06-27 02:13:20 +00:00

73 lines
2 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

x : Nat
h : f (f x) = x
⊢ (have y := x * x;
if True then 1 else y + 1) =
1
theorem ex0 : ∀ (x : Nat),
f (f x) = x →
(have y := 0 + x * x;
if f (f x) = x then 1 else y + 1) =
1 :=
fun x h =>
Eq.mpr
(id
(congrArg (fun x => x = 1)
(id
(id
(have_congr' (Nat.zero_add (x * x)) fun y =>
ite_congr (Eq.trans (congrArg (fun x_1 => x_1 = x) h) (eq_self x)) (fun a => Eq.refl 1) fun a =>
Eq.refl (y + 1))))))
(of_eq_true (Eq.trans (congrArg (fun x => x = 1) (ite_cond_eq_true 1 (x * x + 1) (Eq.refl True))) (eq_self 1)))
x : Nat
h : f (f x) = x
⊢ (have y := x * x;
if True then 1 else y + 1) =
1
theorem ex1 : ∀ (x : Nat),
f (f x) = x →
(have y := x * x;
if f (f x) = x then 1 else y + 1) =
1 :=
fun x h =>
Eq.mpr
(id
(congrArg (fun x => x = 1)
(id
(id
(have_body_congr' (x * x) fun y =>
ite_congr (Eq.trans (congrArg (fun x_1 => x_1 = x) h) (eq_self x)) (fun a => Eq.refl 1) fun a =>
Eq.refl (y + 1))))))
(of_eq_true (Eq.trans (congrArg (fun x => x = 1) (ite_cond_eq_true 1 (x * x + 1) (Eq.refl True))) (eq_self 1)))
x z : Nat
h : f (f x) = x
h' : z = x
⊢ (have y := x;
y) =
z
theorem ex2 : ∀ (x z : Nat),
f (f x) = x →
z = x →
(have y := f (f x);
y) =
z :=
fun x z h h' =>
Eq.mpr (id (congrArg (fun x => x = z) (id (id (have_val_congr' h)))))
(of_eq_true (Eq.trans (congrArg (Eq x) h') (eq_self x)))
x z : Nat
⊢ (let α := Nat;
fun x => 0 + x) =
id
p : Prop
h : p
⊢ (have n := 10;
fun x => True) =
fun z => p
theorem ex4 : ∀ (p : Prop),
p →
(have n := 10;
fun x => x = x) =
fun z => p :=
fun p h =>
Eq.mpr
(id (congrArg (fun x => x = fun z => p) (id (id (have_body_congr_dep' 10 fun n => funext fun x => eq_self x)))))
(of_eq_true (Eq.trans (congrArg (Eq fun x => True) (funext fun z => eq_true h)) (eq_self fun x => True)))