This PR implements the option `revert`, which is set to `false` by default. To recover the old `grind` behavior, you should use `grind +revert`. Previously, `grind` used the `RevSimpIntro` idiom, i.e., it would revert all hypotheses and then re-introduce them while simplifying and applying eager `cases`. This idiom created several problems: * Users reported that `grind` would include unnecessary parameters. See [here](https://leanprover.zulipchat.com/#narrow/channel/270676-lean4/topic/Grind.20aggressively.20includes.20local.20hypotheses.2E/near/554887715). * Unnecessary section variables were also being introduced. See the new test contributed by Sebastian Graf. * Finally, it prevented us from supporting arbitrary parameters as we do in `simp`. In `simp`, I implemented a mechanism that simulates local universe-polymorphic theorems, but this approach could not be used in `grind` because there is no mechanism for reverting (and re-introducing) local universe-polymorphic theorems. Adding such a mechanism would require substantial work: I would need to modify the local context object. I considered maintaining a substitution from the original variables to the new ones, but this is also tricky, because the mapping would have to be stored in the `grind` goal objects, and it is not just a simple mapping. After reverting everything, I would need to keep a sequence of original variables that must be added to the mapping as we re-introduce them, but eager case splits complicate this quite a bit. The whole approach felt overly messy. The new behavior `grind -revert` addresses all these issues. None of the `grind` proofs in our test suite broke after we fixed the bugs exposed by the new feature. That said, the traces and counterexamples produced by `grind` are different. The new proof terms are also different.
107 lines
2.9 KiB
Text
107 lines
2.9 KiB
Text
module
|
||
opaque g : Nat → Nat
|
||
|
||
set_option trace.Meta.debug true
|
||
|
||
@[grind] def f (a : Nat) :=
|
||
match a with
|
||
| 0 => 10
|
||
| x+1 => g (f x)
|
||
|
||
set_option grind.debug true
|
||
set_option grind.debug.proofs true
|
||
|
||
set_option trace.grind.ematch.instance true
|
||
set_option trace.grind.assert true
|
||
|
||
/--
|
||
trace: [grind.assert] f (y + 1) = a
|
||
[grind.assert] ¬a = g (f y)
|
||
[grind.ematch.instance] f.eq_2: f y.succ = g (f y)
|
||
[grind.assert] f (y + 1) = g (f y)
|
||
-/
|
||
#guard_msgs (trace) in
|
||
example : f (y + 1) = a → a = g (f y):= by
|
||
grind
|
||
|
||
@[grind] def app (xs ys : List α) :=
|
||
match xs with
|
||
| [] => ys
|
||
| x::xs => x :: app xs ys
|
||
|
||
/--
|
||
trace: [grind.assert] app [1, 2] ys = xs
|
||
[grind.assert] ¬xs = 1 :: 2 :: ys
|
||
[grind.ematch.instance] app.eq_2: app [1, 2] ys = 1 :: app [2] ys
|
||
[grind.assert] app [1, 2] ys = 1 :: app [2] ys
|
||
[grind.ematch.instance] app.eq_2: app [2] ys = 2 :: app [] ys
|
||
[grind.assert] app [2] ys = 2 :: app [] ys
|
||
[grind.ematch.instance] app.eq_1: app [] ys = ys
|
||
[grind.assert] app [] ys = ys
|
||
-/
|
||
#guard_msgs (trace) in
|
||
example : app [1, 2] ys = xs → xs = 1::2::ys := by
|
||
grind
|
||
|
||
opaque p : Nat → Nat → Prop
|
||
opaque q : Nat → Prop
|
||
|
||
@[grind =] theorem pq : p x x ↔ q x := by sorry
|
||
|
||
/--
|
||
trace: [grind.assert] p a a
|
||
[grind.assert] ¬q a
|
||
[grind.ematch.instance] pq: p a a ↔ q a
|
||
[grind.assert] p a a = q a
|
||
-/
|
||
#guard_msgs (trace) in
|
||
example : p a a → q a := by
|
||
grind
|
||
|
||
opaque appV (xs : Vector α n) (ys : Vector α m) : Vector α (n + m) :=
|
||
Vector.append xs ys
|
||
|
||
@[grind =]
|
||
theorem appV_assoc (a : Vector α n) (b : Vector α m) (c : Vector α n') :
|
||
appV a (appV b c) ≍ appV (appV a b) c := sorry
|
||
|
||
/--
|
||
trace: [grind.assert] x1 = appV a b
|
||
[grind.assert] x2 = appV x1 c
|
||
[grind.assert] x3 = appV b c
|
||
[grind.assert] x4 = appV a x3
|
||
[grind.assert] ¬x2 ≍ x4
|
||
[grind.ematch.instance] appV_assoc: appV a (appV b c) ≍ appV (appV a b) c
|
||
[grind.assert] appV a (appV b c) ≍ appV (appV a b) c
|
||
-/
|
||
#guard_msgs (trace) in
|
||
example : x1 = appV a b → x2 = appV x1 c → x3 = appV b c → x4 = appV a x3 → x2 ≍ x4 := by
|
||
grind
|
||
|
||
|
||
/--
|
||
info: appV_assoc': [@appV #6 #5 (@HAdd.hAdd `[Nat] `[Nat] `[Nat] `[instHAdd] #4 #3) #2 (@appV _ #4 #3 #1 #0)]
|
||
-/
|
||
#guard_msgs (info) in
|
||
@[grind? =]
|
||
theorem appV_assoc' (a : Vector α n) (b : Vector α m) (c : Vector α n') :
|
||
appV a (appV b c) ≍ appV (appV a b) c := sorry
|
||
|
||
|
||
example (p : Prop) (h₁ h₂ : Decidable p) : h₁ = h₂ := by
|
||
grind
|
||
|
||
example (p q : Prop) (h₁ : Decidable p) (h₂ : Decidable (p ∧ q)) : (p ↔ q) → h₁ ≍ h₂ := by
|
||
grind
|
||
|
||
example (a₁ a₂ : α) (b₁ b₂ : β) : a₁ ≍ b₁ → a₂ ≍ b₂ → (a₁ = a₂) = (b₁ = b₂) := by
|
||
grind
|
||
|
||
example (a₁ a₂ : α) (b₁ b₂ : β) : a₁ ≍ b₁ → a₂ ≍ b₂ → (a₁ = a₂) = (b₂ = b₁) := by
|
||
grind
|
||
|
||
example (a₁ a₂ : α) (b₁ b₂ : β) : a₁ ≍ b₁ → a₂ ≍ b₂ → (a₁ = a₂) ≍ (b₁ = b₂) := by
|
||
grind
|
||
|
||
example (a₁ a₂ : α) (b₁ b₂ : β) : a₁ ≍ b₁ → a₂ ≍ b₂ → (a₁ = a₂) ≍ (b₂ = b₁) := by
|
||
grind
|