Lean-auto is an interface between Lean and automated theorem provers. Up to now, lean-auto is maintained and developed primarily by Yicheng Qian (GitHub: PratherConid). It is currently in active development, and pull requests/issues are welcome. For more information, feel free to reach out to Yicheng Qian on Lean Zulip.
Lean-auto is based on a monomorphization procedure from dependent type theory to higher-order logic and a deep embedding of higher-order logic into dependent type theory. It is capable of handling dependently-typed and/or universe-polymorphic input terms. Currently, proof reconstruction can be handled by Duper, a higher-order superposition prover written in Lean. To enable Duper, please import the duper repo in your project, and set the following options:
import Auto.Tactic
import Duper.Tactic
open Lean Auto in
def Auto.duperRaw (lemmas : Array Lemma) (inhs : Array Lemma) : MetaM Expr := do
let lemmas : Array (Expr × Expr × Array Name × Bool) ← lemmas.mapM
(fun ⟨⟨proof, ty, _⟩, _⟩ => do return (ty, ← Meta.mkAppM ``eq_true #[proof], #[], true))
Duper.runDuper lemmas.toList [] 0
attribute [rebind Auto.Native.solverFunc] Auto.duperRaw
set_option auto.native true
Although Lean-auto is still under development, it's already able to solve nontrivial problems. For example the first part of the "snake lemma" in category theory can be solved by a direct invocation to auto (and the second part can also be partly automated):
Type "auto 👍" to test whether auto is set up.
auto [<term>,*] u[<ident>,*] d[<ident>,*]
u[<ident>,*]: Unfold identifiersd[<ident>,*]: Add definitional equality related to identifiersTest/Test_Regression.lean in this repo contains working examples of usages of lean-auto. Note that the native mode in Test/Test_Regression uses a dummy native solver, but this is only for testing. In real use cases, you should replace the dummy solver with a native theorem prover such as duper. See below for detailed instructions.set_option auto.smt true, but without proof reconstruction. Make sure that SMT solvers are installed, and that auto.smt.solver.name is correctly set. If you want to tryset_option auto.tptp true, but without proof reconstruction.
zipperpositionzipperposition executable, use set_option auto.tptp.solver.name "zipperposition". The executable will be automatically downloaded when lean-auto is built.zipperposition portfolio mode, use set_option auto.tptp.solver.name zeport-lams or set_option auto.tptp.solver.name zeport-fo. You need to obtain the source code of zipperposition and make sure that auto.tptp.zeport.path points to the correct python script that runs zipperposition with the portfolio mode, presumably in the portfolio folder of the source code of zipperposition.lean repository that has lean-auto as dependency. To enable proof search by native prover, use set_option auto.native true, and use attribute [rebind Auto.Native.solverFunc] <solve_interface> to bind lean-auto to the interface of the solver, which should be a Lean constant of type Array Lemma → Array Lemma → MetaM Expr.z3 version >= 4.12.2. Lower versions may not be able to deal with smt-lib 2.6 string escape sequence.cvc5zipperposition portfolio modeMonomorphization failed because ...:set_option auto.mono.ignoreNonQuasiHigherOrder true before you invoke autoDuper Saturated when using lean-auto + duper:auto is insufficientduper is unable to prove the translated problem, although the translated problem is provableauto is unable to handle certain Lean features in the problemrw, apply, simp only, and dsimp only) and the hints you provided to lean-auto. Try not to use simp, simp_all and grind because they might automatically use theorems that are not within the hint list provided to them. If you're able to prove the goal manually, it means that the list of hints you provided is sufficient.lean-auto + SMT solver and lean-auto + TPTP solver and see if they're able to solve the goal. Note that even if the goal is still not solved, it does not necessarily mean that the translated problem is unprovable.#getExprAndApply [ <term> | <ident> ]: Defined in ExprExtra.lean. This command first elaborates the <term> into a lean Expr, then applies function <ident> to Expr. The constant ident must be already declared and be of type Expr → TermElabM Unit#genMonadState <term>, #genMonadContext <term>: Defined in MonadUtils.lean. Refer to the comment at the beginning of MonadUtils.lean.#fromMetaTactic [<ident>]: Calls Tactic.liftMetaTactic on <ident>. The constant <ident> must be already declared and be of type MVarId → MetaM (List MVarId)Parser/LeanLex.lean. The frontend is not yet implemented. The backend can be found in NDFA.lean.let binders and unfold projections when we collect assumptions. So, in the following discussion, we'll assume that the expression contains no let binders and no projs.Type (u + 1), i.e., $α : Type \ (u + 1)$. This is necessary because we want to write a checker (instead of directly reconstructing proof in DTT) and the valuation function from less expressive logic to dependent type theory requires [the elements in the range of the valuation function] to be [of the same sort].GLift. For example, Nat.add is transformed into Nat.addLift
structure GLift.{u, v} (α : Sort u) : Sort (max u (v + 1)) where
/-- Lift a value into `GLift α` -/ up ::
/-- Extract a value from `GLift α` -/ down : α
def Nat.addLift.{u} (x y : GLift.{1, u} Nat) :=
GLift.up (Nat.add (GLift.down x) (GLift.down y))
GLift.up.Auto/Translation/LamReif.leanAuto/Translation/LamFOL2SMT.lean6s to typecheck the final example in BinderComplexity.lean. However, this is probably acceptable for mathlib usages, because e.g Mathlib/Analysis/BoxIntegral/DivergenceTheorem.lean has two theorems that take 4s to compile (but a large portion of the 4s are spent on typeclass inference)defeq <num> <name>: The <num>-th definitional equality associated with definition <name>hw <name>: Lemmas hard-wired into Lean-autolctxInh: Inhabitation fact from local contextlctxLem: Lemma from local contextrec <indName>.<ctorName>rw [0, 1]: Rewrite 0 using 1 (1 must be an equality)tyCanInh: Inhabitation instance synthesized for canonicalized typeciInstDefEq: Definitional equality resulting from instance relations between ConstInststermLikeDefEq: Definitional equality resulting from definitional equalities between term-like subexpressions❰<term>❱: User-provided lemma <term>queryNative::<func_name>: Proved by native proverLean
99.6%
Lean-auto is an interface between Lean and automated theorem provers. Up to now, lean-auto is maintained and developed primarily by Yicheng Qian (GitHub: PratherConid). It is currently in active development, and pull requests/issues are welcome. For more information, feel free to reach out to Yicheng Qian on Lean Zulip.
Lean-auto is based on a monomorphization procedure from dependent type theory to higher-order logic and a deep embedding of higher-order logic into dependent type theory. It is capable of handling dependently-typed and/or universe-polymorphic input terms. Currently, proof reconstruction can be handled by Duper, a higher-order superposition prover written in Lean. To enable Duper, please import the duper repo in your project, and set the following options:
import Auto.Tactic
import Duper.Tactic
open Lean Auto in
def Auto.duperRaw (lemmas : Array Lemma) (inhs : Array Lemma) : MetaM Expr := do
let lemmas : Array (Expr × Expr × Array Name × Bool) ← lemmas.mapM
(fun ⟨⟨proof, ty, _⟩, _⟩ => do return (ty, ← Meta.mkAppM ``eq_true #[proof], #[], true))
Duper.runDuper lemmas.toList [] 0
attribute [rebind Auto.Native.solverFunc] Auto.duperRaw
set_option auto.native true
Although Lean-auto is still under development, it's already able to solve nontrivial problems. For example the first part of the "snake lemma" in category theory can be solved by a direct invocation to auto (and the second part can also be partly automated):
Type "auto 👍" to test whether auto is set up.
auto [<term>,*] u[<ident>,*] d[<ident>,*]
u[<ident>,*]: Unfold identifiersd[<ident>,*]: Add definitional equality related to identifiersTest/Test_Regression.lean in this repo contains working examples of usages of lean-auto. Note that the native mode in Test/Test_Regression uses a dummy native solver, but this is only for testing. In real use cases, you should replace the dummy solver with a native theorem prover such as duper. See below for detailed instructions.set_option auto.smt true, but without proof reconstruction. Make sure that SMT solvers are installed, and that auto.smt.solver.name is correctly set. If you want to tryset_option auto.tptp true, but without proof reconstruction.
zipperpositionzipperposition executable, use set_option auto.tptp.solver.name "zipperposition". The executable will be automatically downloaded when lean-auto is built.zipperposition portfolio mode, use set_option auto.tptp.solver.name zeport-lams or set_option auto.tptp.solver.name zeport-fo. You need to obtain the source code of zipperposition and make sure that auto.tptp.zeport.path points to the correct python script that runs zipperposition with the portfolio mode, presumably in the portfolio folder of the source code of zipperposition.lean repository that has lean-auto as dependency. To enable proof search by native prover, use set_option auto.native true, and use attribute [rebind Auto.Native.solverFunc] <solve_interface> to bind lean-auto to the interface of the solver, which should be a Lean constant of type Array Lemma → Array Lemma → MetaM Expr.z3 version >= 4.12.2. Lower versions may not be able to deal with smt-lib 2.6 string escape sequence.cvc5zipperposition portfolio modeMonomorphization failed because ...:set_option auto.mono.ignoreNonQuasiHigherOrder true before you invoke autoDuper Saturated when using lean-auto + duper:auto is insufficientduper is unable to prove the translated problem, although the translated problem is provableauto is unable to handle certain Lean features in the problemrw, apply, simp only, and dsimp only) and the hints you provided to lean-auto. Try not to use simp, simp_all and grind because they might automatically use theorems that are not within the hint list provided to them. If you're able to prove the goal manually, it means that the list of hints you provided is sufficient.lean-auto + SMT solver and lean-auto + TPTP solver and see if they're able to solve the goal. Note that even if the goal is still not solved, it does not necessarily mean that the translated problem is unprovable.#getExprAndApply [ <term> | <ident> ]: Defined in ExprExtra.lean. This command first elaborates the <term> into a lean Expr, then applies function <ident> to Expr. The constant ident must be already declared and be of type Expr → TermElabM Unit#genMonadState <term>, #genMonadContext <term>: Defined in MonadUtils.lean. Refer to the comment at the beginning of MonadUtils.lean.#fromMetaTactic [<ident>]: Calls Tactic.liftMetaTactic on <ident>. The constant <ident> must be already declared and be of type MVarId → MetaM (List MVarId)Parser/LeanLex.lean. The frontend is not yet implemented. The backend can be found in NDFA.lean.let binders and unfold projections when we collect assumptions. So, in the following discussion, we'll assume that the expression contains no let binders and no projs.Type (u + 1), i.e., $α : Type \ (u + 1)$. This is necessary because we want to write a checker (instead of directly reconstructing proof in DTT) and the valuation function from less expressive logic to dependent type theory requires [the elements in the range of the valuation function] to be [of the same sort].GLift. For example, Nat.add is transformed into Nat.addLift
structure GLift.{u, v} (α : Sort u) : Sort (max u (v + 1)) where
/-- Lift a value into `GLift α` -/ up ::
/-- Extract a value from `GLift α` -/ down : α
def Nat.addLift.{u} (x y : GLift.{1, u} Nat) :=
GLift.up (Nat.add (GLift.down x) (GLift.down y))
GLift.up.Auto/Translation/LamReif.leanAuto/Translation/LamFOL2SMT.lean6s to typecheck the final example in BinderComplexity.lean. However, this is probably acceptable for mathlib usages, because e.g Mathlib/Analysis/BoxIntegral/DivergenceTheorem.lean has two theorems that take 4s to compile (but a large portion of the 4s are spent on typeclass inference)defeq <num> <name>: The <num>-th definitional equality associated with definition <name>hw <name>: Lemmas hard-wired into Lean-autolctxInh: Inhabitation fact from local contextlctxLem: Lemma from local contextrec <indName>.<ctorName>rw [0, 1]: Rewrite 0 using 1 (1 must be an equality)tyCanInh: Inhabitation instance synthesized for canonicalized typeciInstDefEq: Definitional equality resulting from instance relations between ConstInststermLikeDefEq: Definitional equality resulting from definitional equalities between term-like subexpressions❰<term>❱: User-provided lemma <term>queryNative::<func_name>: Proved by native proverLean
99.6%