This PR applies two minor tweaks: - `tests/bench/sym/simp_1.lean`: share-common the proof term before counting objects in `getProofSize`, so the reported size reflects the shared representation. - `tests/elab/sym_simp_3.lean`: use `>>` instead of `.andThen` when composing `Sym.Simp` methods. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
199 lines
5.1 KiB
Text
199 lines
5.1 KiB
Text
import Lean
|
||
open Lean Meta Elab Tactic
|
||
|
||
elab "sym_simp" "[" declNames:ident,* "]" : tactic => do
|
||
let rewrite ← Sym.mkSimprocFor (← declNames.getElems.mapM fun s => realizeGlobalConstNoOverload s.raw) Sym.Simp.dischargeSimpSelf
|
||
let methods : Sym.Simp.Methods := {
|
||
pre := Sym.Simp.simpControl
|
||
post := Sym.Simp.evalGround >> rewrite
|
||
}
|
||
liftMetaTactic1 fun mvarId => Sym.SymM.run do
|
||
let mvarId ← Sym.preprocessMVar mvarId
|
||
(← Sym.simpGoal mvarId methods).toOption
|
||
|
||
example : (1-1) + x*1 + (2-1)*0 = x := by
|
||
sym_simp [Nat.add_zero, Nat.zero_add, Nat.mul_one]
|
||
|
||
opaque f : Nat → Nat
|
||
axiom fax : x > 10 → f x = 0
|
||
|
||
example : f 12 = 0 := by
|
||
sym_simp [fax]
|
||
|
||
example : (if true then a else b) = a := by
|
||
sym_simp []
|
||
|
||
example : (if True then a else b) = a := by
|
||
sym_simp []
|
||
|
||
example : (if False then a else b) = b := by
|
||
sym_simp []
|
||
|
||
example (f g : Nat → Nat) : (if a + 0 = a then f else g) a = f a := by
|
||
sym_simp [Nat.add_zero]
|
||
|
||
example (f g : Nat → Nat → Nat) : (if a + 0 ≠ a then f else g) a (b + 0) = g a b := by
|
||
sym_simp [Nat.add_zero]
|
||
|
||
/--
|
||
trace: a b : Nat
|
||
f g : Nat → Nat → Nat
|
||
h : a = b
|
||
⊢ (if ¬a = b then id f else id (id g)) a (b + 0) = g a b
|
||
-/
|
||
#guard_msgs in
|
||
example (f g : Nat → Nat → Nat) (h : a = b) : (if a + 0 ≠ b then id f else id (id g)) a (b + 0) = g a b := by
|
||
sym_simp [Nat.add_zero, id_eq]
|
||
trace_state -- `if-then-else` branches should not have been simplified
|
||
subst h
|
||
sym_simp [Nat.add_zero, id_eq]
|
||
|
||
def isNil (xs : List α) : Bool :=
|
||
match xs with
|
||
| [] => true
|
||
| _::_ => false
|
||
|
||
example : isNil ([] : List Nat) = true := by
|
||
sym_simp [isNil.eq_def]
|
||
|
||
inductive Kind where
|
||
| a | b | c
|
||
|
||
def pick : Kind → Nat → Nat
|
||
| .a => Nat.succ
|
||
| .b => (2 * ·)
|
||
| .c => id
|
||
|
||
example : pick .a 2 = 3 := by
|
||
sym_simp [pick.eq_def]
|
||
|
||
example : pick .b 2 = 4 := by
|
||
sym_simp [pick.eq_def]
|
||
|
||
example : pick .c 2 = 2 := by
|
||
sym_simp [pick.eq_def, id_eq]
|
||
|
||
example : (match 1 - 1 with | 0 => 1 | _ => 2) = 1 := by
|
||
sym_simp []
|
||
|
||
/--
|
||
trace: c : Bool
|
||
h : c = false
|
||
⊢ (match 0, c with
|
||
| 0, true => 1 + 0
|
||
| 0, false => 2 + 1
|
||
| x, x_1 => 3 + 1) =
|
||
3
|
||
-/
|
||
#guard_msgs in
|
||
example (h : c = false) : (match 1 - 1, c with | 0, true => 1+0 | 0, false => 2+1 | _, _ => 3+1) = 3 := by
|
||
sym_simp [] -- Only discriminant should have been simplified, simplifier must not visit branches
|
||
trace_state
|
||
subst c
|
||
sym_simp []
|
||
|
||
/--
|
||
trace: a : Nat
|
||
h : a = 0
|
||
⊢ (match a, false with
|
||
| 0, true => 1 + 0
|
||
| 0, false => 2 + 1
|
||
| x, x_1 => 3 + 1) =
|
||
3
|
||
-/
|
||
#guard_msgs in
|
||
example (h : a = 0) : (match a, !true with | 0, true => 1+0 | 0, false => 2+1 | _, _ => 3+1) = 3 := by
|
||
sym_simp [Bool.not_true] -- Only discriminant should have been simplified, simplifier must not visit branches
|
||
trace_state
|
||
subst a
|
||
sym_simp []
|
||
|
||
inductive Foo where
|
||
| mk1 (a : Nat)
|
||
| mk2 (b : Bool)
|
||
| mk3 (c : Int)
|
||
|
||
example : (match Foo.mk3 c, Foo.mk2 b with | .mk1 _, _ => 1+0 | _, .mk2 _ => 2+1 | _, _ => id 4) = 3 := by
|
||
sym_simp [id_eq]
|
||
|
||
example : (match (true, false, true) with | (false, _, _) => 1 | (_, false, _) => 2 | _ => 3) = 2 := by
|
||
sym_simp []
|
||
|
||
example : (if _ : true then a else b) = a := by
|
||
sym_simp []
|
||
|
||
example : (if _ : True then a else b) = a := by
|
||
sym_simp []
|
||
|
||
example : (if _ : False then a else b) = b := by
|
||
sym_simp []
|
||
|
||
example (f g : Nat → Nat) : (if _ : a + 0 = a then f else g) a = f a := by
|
||
sym_simp [Nat.add_zero]
|
||
|
||
example (f g : Nat → Nat → Nat) : (if _ : a + 0 ≠ a then f else g) a (b + 0) = g a b := by
|
||
sym_simp [Nat.add_zero]
|
||
|
||
/--
|
||
trace: a b : Nat
|
||
f g : Nat → Nat → Nat
|
||
h : a = b
|
||
⊢ (if h : ¬a = b then id f else id (id g)) a (b + 0) = g a b
|
||
-/
|
||
#guard_msgs in
|
||
example (f g : Nat → Nat → Nat) (h : a = b) : (if _ : a + 0 ≠ b then id f else id (id g)) a (b + 0) = g a b := by
|
||
sym_simp [Nat.add_zero, id_eq]
|
||
trace_state -- `if-then-else` branches should not have been simplified
|
||
subst h
|
||
sym_simp [Nat.add_zero, id_eq]
|
||
|
||
example : (bif true then a else b) = a := by
|
||
sym_simp []
|
||
|
||
example : (bif false then a else b) = b := by
|
||
sym_simp []
|
||
|
||
example (f g : Nat → Nat) : (bif a + 0 == a then f else g) a = f a := by
|
||
sym_simp [Nat.add_zero, beq_self_eq_true]
|
||
|
||
example (f g : Nat → Nat → Nat) : (bif a + 0 != a then f else g) a (b + 0) = g a b := by
|
||
sym_simp [Nat.add_zero, bne_self_eq_false]
|
||
|
||
/--
|
||
trace: a b : Nat
|
||
f g : Nat → Nat → Nat
|
||
h : a = b
|
||
⊢ (bif a != b then id f else id (id g)) a (b + 0) = g a b
|
||
-/
|
||
#guard_msgs in
|
||
example (f g : Nat → Nat → Nat) (h : a = b) : (bif a + 0 != b then id f else id (id g)) a (b + 0) = g a b := by
|
||
sym_simp [Nat.add_zero, id_eq]
|
||
trace_state -- `cond` branches should not have been simplified
|
||
subst h
|
||
sym_simp [Nat.add_zero, bne_self_eq_false, id_eq]
|
||
|
||
def pw (n : Nat) : Nat :=
|
||
match n with
|
||
| 0 => 1
|
||
| n+1 => 2 * pw n
|
||
|
||
example : pw 0 = 1 := by
|
||
sym_simp [pw.eq_1]
|
||
|
||
example : pw 2 = 4 := by
|
||
sym_simp [pw.eq_1, pw.eq_2]
|
||
|
||
example : pw 4 = 16 := by
|
||
sym_simp [pw.eq_1, pw.eq_2]
|
||
|
||
example : pw (a + 2) = 2 * (2 * pw a) := by
|
||
sym_simp [pw.eq_2]
|
||
|
||
example : pw (Nat.succ a) = 2 * pw a := by
|
||
sym_simp [pw.eq_2]
|
||
|
||
example : pw (a + 3) = 2 * (2 * (2 * pw a)) := by
|
||
sym_simp [pw.eq_2]
|
||
|
||
example : pw (Nat.succ (Nat.succ a)) = 2 * (2 * pw a) := by
|
||
sym_simp [pw.eq_2]
|