161 lines
6.7 KiB
Text
161 lines
6.7 KiB
Text
/-
|
|
Copyright (c) 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
Released under Apache 2.0 license as described in the file LICENSE.
|
|
Authors: Leonardo de Moura
|
|
-/
|
|
module
|
|
|
|
prelude
|
|
import Init.Tactics
|
|
|
|
namespace Lean.Parser
|
|
/--
|
|
Reset all `grind` attributes. This command is intended for testing purposes only and should not be used in applications.
|
|
-/
|
|
syntax (name := resetGrindAttrs) "reset_grind_attrs%" : command
|
|
|
|
namespace Attr
|
|
syntax grindGen := &"gen "
|
|
syntax grindEq := "= " (grindGen)?
|
|
syntax grindEqBoth := atomic("_" "=" "_ ") (grindGen)?
|
|
syntax grindEqRhs := atomic("=" "_ ") (grindGen)?
|
|
syntax grindEqBwd := atomic("←" "= ") <|> atomic("<-" "= ")
|
|
syntax grindBwd := ("← " <|> "<- ") (grindGen)?
|
|
syntax grindFwd := "→ " <|> "-> "
|
|
syntax grindRL := "⇐ " <|> "<= "
|
|
syntax grindLR := "⇒ " <|> "=> "
|
|
syntax grindUsr := &"usr "
|
|
syntax grindCases := &"cases "
|
|
syntax grindCasesEager := atomic(&"cases" &"eager ")
|
|
syntax grindIntro := &"intro "
|
|
syntax grindExt := &"ext "
|
|
syntax grindMod :=
|
|
grindEqBoth <|> grindEqRhs <|> grindEq <|> grindEqBwd <|> grindBwd
|
|
<|> grindFwd <|> grindRL <|> grindLR <|> grindUsr <|> grindCasesEager
|
|
<|> grindCases <|> grindIntro <|> grindExt <|> grindGen
|
|
syntax (name := grind) "grind" (grindMod)? : attr
|
|
syntax (name := grind?) "grind?" (grindMod)? : attr
|
|
end Attr
|
|
end Lean.Parser
|
|
|
|
namespace Lean.Grind
|
|
/--
|
|
The configuration for `grind`.
|
|
Passed to `grind` using, for example, the `grind (config := { matchEqs := true })` syntax.
|
|
-/
|
|
structure Config where
|
|
/-- If `trace` is `true`, `grind` records used E-matching theorems and case-splits. -/
|
|
trace : Bool := false
|
|
/-- Maximum number of case-splits in a proof search branch. It does not include splits performed during normalization. -/
|
|
splits : Nat := 8
|
|
/-- Maximum number of E-matching (aka heuristic theorem instantiation) rounds before each case split. -/
|
|
ematch : Nat := 5
|
|
/--
|
|
Maximum term generation.
|
|
The input goal terms have generation 0. When we instantiate a theorem using a term from generation `n`,
|
|
the new terms have generation `n+1`. Thus, this parameter limits the length of an instantiation chain. -/
|
|
gen : Nat := 5
|
|
/-- Maximum number of theorem instances generated using E-matching in a proof search tree branch. -/
|
|
instances : Nat := 1000
|
|
/-- If `matchEqs` is `true`, `grind` uses `match`-equations as E-matching theorems. -/
|
|
matchEqs : Bool := true
|
|
/-- If `splitMatch` is `true`, `grind` performs case-splitting on `match`-expressions during the search. -/
|
|
splitMatch : Bool := true
|
|
/-- If `splitIte` is `true`, `grind` performs case-splitting on `if-then-else` expressions during the search. -/
|
|
splitIte : Bool := true
|
|
/--
|
|
If `splitIndPred` is `true`, `grind` performs case-splitting on inductive predicates.
|
|
Otherwise, it performs case-splitting only on types marked with `[grind cases]` attribute. -/
|
|
splitIndPred : Bool := false
|
|
/--
|
|
If `splitImp` is `true`, then given an implication `p → q` or `(h : p) → q h`, `grind` splits on `p`
|
|
if the implication is true. Otherwise, it will split only if `p` is an arithmetic predicate.
|
|
-/
|
|
splitImp : Bool := false
|
|
/-- Maximum number of heartbeats (in thousands) the canonicalizer can spend per definitional equality test. -/
|
|
canonHeartbeats : Nat := 1000
|
|
/-- If `ext` is `true`, `grind` uses extensionality theorems that have been marked with `[grind ext]`. -/
|
|
ext : Bool := true
|
|
/-- If `extAll` is `true`, `grind` uses any extensionality theorems available in the environment. -/
|
|
extAll : Bool := false
|
|
/--
|
|
If `etaStruct` is `true`, then for each term `t : S` such that `S` is a structure,
|
|
and is tagged with `[grind ext]`, `grind` adds the equation `t = ⟨t.1, ..., t.n⟩`
|
|
which holds by reflexivity. Moreover, the extensionality theorem for `S` is not used.
|
|
-/
|
|
etaStruct : Bool := true
|
|
/--
|
|
If `funext` is `true`, `grind` creates new opportunities for applying function extensionality by case-splitting
|
|
on equalities between lambda expressions.
|
|
-/
|
|
funext : Bool := true
|
|
/-- TODO -/
|
|
lookahead : Bool := true
|
|
/-- If `verbose` is `false`, additional diagnostics information is not collected. -/
|
|
verbose : Bool := true
|
|
/-- If `clean` is `true`, `grind` uses `expose_names` and only generates accessible names. -/
|
|
clean : Bool := true
|
|
/--
|
|
If `qlia` is `true`, `grind` may generate counterexamples for integer constraints
|
|
using rational numbers, and ignoring divisibility constraints.
|
|
This approach is cheaper but incomplete. -/
|
|
qlia : Bool := false
|
|
/--
|
|
If `mbtc` is `true`, `grind` will use model-based theory combination for creating new case splits.
|
|
See paper "Model-based Theory Combination" for details.
|
|
-/
|
|
mbtc : Bool := true
|
|
/--
|
|
When set to `true` (default: `true`), local definitions are unfolded during normalization and internalization.
|
|
In other words, given a local context with an entry `x : t := e`, the free variable `x` is reduced to `e`.
|
|
Note that this behavior is also available in `simp`, but there its default is `false` because `simp` is not
|
|
always used as a terminal tactic, and it important to preserve the abstractions introduced by users.
|
|
Additionally, in `grind` we observed that `zetaDelta` is particularly important when combined with function induction.
|
|
In such scenarios, the same let-expressions can be introduced by function induction and also by unfolding the
|
|
corresponding definition. We want to avoid a situation in which `zetaDelta` is not applied to let-declarations
|
|
introduced by function induction while `zeta` unfolds the definition, causing a mismatch.
|
|
Finally, note that congruence closure is less effective on terms containing many binders such as
|
|
`lambda` and `let` expressions.
|
|
-/
|
|
zetaDelta := true
|
|
/--
|
|
When `true` (default: `true`), performs zeta reduction of let expressions during normalization.
|
|
That is, `let x := v; e[x]` reduces to `e[v]`. See also `zetaDelta`.
|
|
-/
|
|
zeta := true
|
|
/--
|
|
When `true` (default: `false`), uses procedure for handling equalities over commutative rings.
|
|
-/
|
|
ring := false
|
|
ringSteps := 10000
|
|
/--
|
|
When `true` (default: `false`), the commutative ring procedure in `grind` constructs stepwise
|
|
proof terms, instead of a single-step Nullstellensatz certificate
|
|
-/
|
|
ringNull := false
|
|
deriving Inhabited, BEq
|
|
|
|
end Lean.Grind
|
|
|
|
namespace Lean.Parser.Tactic
|
|
|
|
/-!
|
|
`grind` tactic and related tactics.
|
|
-/
|
|
|
|
syntax grindErase := "-" ident
|
|
syntax grindLemma := (Attr.grindMod)? ident
|
|
syntax grindParam := grindErase <|> grindLemma
|
|
|
|
syntax (name := grind)
|
|
"grind" optConfig (&" only")?
|
|
(" [" withoutPosition(grindParam,*) "]")?
|
|
("on_failure " term)? : tactic
|
|
|
|
|
|
syntax (name := grindTrace)
|
|
"grind?" optConfig (&" only")?
|
|
(" [" withoutPosition(grindParam,*) "]")?
|
|
("on_failure " term)? : tactic
|
|
|
|
end Lean.Parser.Tactic
|