lean4-htt/tests/lean/sym/perf_meta_apply.lean
Sebastian Ullrich f47dfe9e7f
perf: Options.hasTrace (#12001)
Drastically speeds up `isTracingEnabledFor` in the common case, which
has evolved from "no options set" to "`Elab.async` and probably some
linter options set but no `trace`".

## Breaking changes

`Lean.Options` is now an opaque type. The basic but not all of the
`KVMap` API has been redefined on top of it.
2026-01-16 09:03:40 +00:00

78 lines
2.6 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.

import Lean.Meta.Tactic
open Lean Meta
def profileM {α : Type} (k : MetaM α) (msg : String := "experiment") : MetaM α :=
profileitM Exception msg ({ : Options }.set `profiler true |>.setNat `profiler.threshold 0) k
def genTerm (n : Nat) : Expr := Id.run do
let mut e := mkConst ``True
let nat := mkConst ``Nat
for _ in 0...n do
let eq := mkApp3 (mkConst ``Eq [1]) nat (mkBVar 0) (mkNatAdd (mkBVar 2) (mkBVar 1))
e := mkApp2 (mkConst ``And) eq e
e := mkApp2 (mkConst ``Exists [1]) nat (mkLambda `y .default nat e)
e := mkForall `x .default nat e
e := mkLet `z nat (mkNatAdd (mkBVar 1) (mkBVar 0)) e
let eq := mkApp3 (mkConst ``Eq [1]) nat (mkBVar 0) (mkNatAdd (mkBVar 2) (mkBVar 1))
e := mkApp2 (mkConst ``And) eq e
e := mkApp2 (mkConst ``Exists [1]) nat (mkLambda `y .default nat e)
e := mkForall `x .default nat e
e := mkLet `z nat (mkNatLit 0) e
return e
set_option maxRecDepth 10000000
def tryIntros? (goals : List MVarId) : MetaM (Option (List MVarId)) := do
let goal :: goals := goals | return none
let (fvars, goal') ← goal.intros
if fvars.isEmpty then return none
return some (goal' :: goals)
def tryApply? (declName : Name) (goals : List MVarId) : MetaM (Option (List MVarId)) := do
let goal :: goals := goals | return none
try
let goals' ← goal.applyConst declName
return some (goals' ++ goals)
catch _ =>
return none
def tryApplyAny? (declNames : List Name) (goals : List MVarId) : MetaM (Option (List MVarId)) := do
match declNames with
| [] => return none
| declName :: declNames =>
if let some goals' ← tryApply? declName goals then
return some goals'
else
tryApplyAny? declNames goals
def solve (n : Nat) (type : Expr) : MetaM Unit := profileM (msg := s!"size {n}") do
let mvarId := (← mkFreshExprMVar type).mvarId!
discard <| go 10000000 [mvarId]
return ()
where
go (fuel : Nat) (goals : List MVarId) : MetaM Bool := do
let fuel + 1 := fuel | throwError "out of fuel"
let goal :: goals' := goals | return true
if (← goal.isAssigned) then
go fuel goals'
else
if let some goals' ← tryIntros? goals then
go fuel goals'
else if let some goals' ← tryApplyAny? [``Exists.intro, ``And.intro, ``Eq.refl, ``True.intro] goals then
go fuel goals'
else
throwError "Stuck at {goal}"
def test (n : Nat) : MetaM Unit := do
let e := genTerm n
solve n e
-- We are solving problems of the following form
#eval logInfo (genTerm 2)
#eval test 1000
#eval test 2000
#eval test 3000
#eval test 4000
#eval test 5000
#eval test 6000