LeanHammer is an automated reasoning tool for Lean which aims to bring together multiple proof search and reconstruction techniques and combine them into one tool. The hammer tactic provided by LeanHammer utilizes this variety of techniques to search for a proof of the current goal, then constructs a suggestion for a tactic script which can replace the hammer invocation.
LeanHammer is in an early stage of its development and therefore may be subject to breaking changes. It is currently compatible with Lean v4.20.
Pull requests and issues are welcome.
To use LeanHammer in an existing project with a lakefile.toml file, add the following lines to your list of dependencies in lakefile.toml:
[[require]]
name = "Hammer"
git = "https://github.com/JOSHCLUNE/LeanHammer"
rev = "main"You must put this before the Mathlib requirement; otherwise, you will find Lean recompiling large parts of Mathlib later on.
To use LeanHammer in an existing project with a lakefile.lean file, add the following line to your list of dependencies in lakefile.lean:
require Hammer from git "https://github.com/JOSHCLUNE/LeanHammer" @ "main"Once again, you must do this before requiring Mathlib.
After LeanHammer has been added as a dependency to your project, run lake update or lake update hammer to retrieve the Zipperposition executable that comes with LeanHammer (this executable will be stored in the existing project's .lake directory). You can then optionally use lake build to compile the hammer components, which takes a few minutes. After that, the following example should compile without any warnings or errors:
import Hammer
-- Setting `aesopPremises` and `autoPremises` to 0 to bypass premise selection
-- which is slow on its first uncached invocation
example : True := by
hammer {aesopPremises := 0, autoPremises := 0}If you skip the lake build step, the hammer components will be compiled the first time you import the hammer.
If you are using a Mac with an Apple silicon chip, Zipperposition may not work out of the box. To test this, try this from the top folder of your project:
.lake/packages/auto/.lake/build/zipperposition-bin-macos-big-sur.exe --version
If it doesn't successfully return the version,
softwareupdate --install-rosetta
should fix it.
Currently, LeanHammer consists of/depends on the following components:
- Premise selection
- A cloud-based premise selector developed specifically for LeanHammer
- MePo which has been widely used in Isabelle's Sledgehammer and was implemented in Lean by Kim Morrison
- Translation procedure
- Lean-auto which serves as an interface to translate from Lean into TPTP and SMT
- Automatic theorem provers
- Zipperposition which is retrieved automatically via this post_update script
- cvc5 via the Lean cvc5 FFI (Not yet integrated)
- Proof search and proof reconstruction tools native to Lean
The above list only consists of components that LeanHammer currently consists of/depends on. As additional components are added and integrated, they will be added to the above list.
For more details about the premise selection component of LeanHammer, please refer to our paper Premise Selection for a Lean Hammer (Thomas Zhu, Joshua Clune, Jeremy Avigad, Albert Jiang, Sean Welleck).
The syntax for invoking the hammer tactic is by hammer [lemmas] {options}. The lemmas and options arguments are both optional, with the former being used to tell hammer to use the supplied list of lemmas (in addition to any lemmas recommended by premise selection), and the latter being used to set LeanHammer's various configuration options.
Each of the options supplied to hammer have the form option := value and are separated by commas. Options that can be used to customize a LeanHammer call include:
disableAesop: Can be set totrueorfalse(defaultfalse). This option is used to remove Aesop from the LeanHammer call.disableAuto: Can be set totrueorfalse(defaultfalse). This option is used to remove Lean-auto, Zipperposition, and Duper from the LeanHammer call (each of these tools are part of a single pipeline)preprocessing: Can be set toaesop,simp_target,simp_all, orno_preprocessing(defaultaesop). This option determines whether the initial goal is first processed byaesop,simp,simp_all, or none of these. This option can only be set to a value other thanaesopifdisableAesopis set totrue, and must be set toaesopifdisableAesopis set tofalse.aesopPremises: Can be set to any Nat (default 32). This option determines the number of lemmas from premise selection that are passed to Aesop as unsafe rules.autoPremises: Can be set to any Nat (default 16). This option determines the number of lemmas from premises selection that are passed to Lean-auto, Zipperposition, and Duper.aesopPremisePriority: Can be set to any Nat between 0 and 100 (default 20). This option determines the Aesop success priority assigned to each of the lemmas from premise selection when passed to Aesop as unsafe rules. See Aesop's README for additional details on the meaning of this success priority.aesopAutoPriority: Can be set to any Nat between 0 and 100 (default 10). This option determines the Aesop success priority assigned to the unsafe rule that attempts to use Lean-auto, Zipperposition, and Duper to solve the current goal.solver: Can be set tozipperposition_exeorzipperposition(defaultzipperposition_exe). This option determines the external automatic theorem prover that Lean-auto sends its translated problem to. Currently, the only options arezipperposition_exe(which uses the Zipperposition executable that LeanHammer's post_update script retrieves) andzipperposition(which allows the user to use their own preinstalled version of Zipperposition).
Each of these options' defaults can be changed with set_option hammer.<option_name>Default <new default>. For example, the command that changes the default number of premises passed to Lean-auto from 16 to 32 is set_option hammer.autoPremisesDefault 32.
You can use:
hammerto run the full pipelinehammer {disableAuto := true}to try Aesop with premise selectionhammer {disableAesop := true, preprocessing := no_preprocessing}to try Zipperposition and Duper with premise selection
In addition to the above options, LeanHammer has a premise selection component, based on the Lean.PremiseSelection API introduced in Lean 4 core. You may also use the premise selection component individually by:
import PremiseSelection
example : True := by
premisesThe premise selector can be modified with the command set_premise_selector <myPremiseSelector>. If no premise selector is specified by the user via this API, then LeanHammer uses the default selector Cloud.premiseSelector <|> mepoSelector (useRarity := true) (p := 0.6) (c := 0.9). For more information on the interpretation of this selector, as well as information on Cloud.premiseSelector's caching behavior, see the premise-selection repository.
The default premise selection server used by Cloud.premiseSelector hosted at http://leanpremise.net is intended for individual use. For heavy use cases, (e.g. performing an evaluation of hammer on a large number of theorems), we encourage users to use this code to host their own server which can be accessed following the instructions in this README.
To view the set of premises that are passed to LeanHammer via premise selection, use the command set_option trace.hammer.premises true.
You can use the following to get more information:
set_option trace.hammer.premises trueto display the list of premises retrievedset_option trace.hammer.debug trueto display what is passed to Zipperposition and the minimized set sent to Duper if it succeedsset_option trace.auto.tptp.printQuery trueto display the query sent to Zipperpositionset_option trace.auto.tptp.result trueto display the response from Zipperpositionset_option trace.aesop trueto display the Aesop search tree