Compare commits

...

19 Commits

Author SHA1 Message Date
Leonardo de Moura
b7e28c5fe2 feat: mark EqMatch as reducible
but, we do not unfold it at `unfoldReducible`
2025-02-16 14:03:50 -08:00
Leonardo de Moura
db94e48bac feat: use reducible transparency setting in grind 2025-02-16 14:03:50 -08:00
Leonardo de Moura
99d8366fdd fix: avoid check at mkEqOfHEq
It may fail with `reducible` transparency setting
2025-02-16 14:03:50 -08:00
Leonardo de Moura
49af97ff5f feat: add flag check at mkEqOfHEq
Motivation: the types may be definitionally equal only with the
default transparency, and caller may be using `reducible`
transparency, but is sure the types are indeed definitionally equal.
2025-02-16 14:03:50 -08:00
Leonardo de Moura
42ab631d74 fix: mkProjection type error 2025-02-16 14:03:50 -08:00
Leonardo de Moura
29cbc3e56f fix: use markAsPreMatchCond 2025-02-16 14:03:50 -08:00
Leonardo de Moura
e696d6d881 fix: missing hint 2025-02-16 14:03:50 -08:00
Leonardo de Moura
865d4a335a chore: fix test 2025-02-16 14:03:50 -08:00
Leonardo de Moura
fba3bf69f0 fix: missing hint 2025-02-16 14:03:50 -08:00
Leonardo de Moura
a6b8676753 fix: hint at eraseSimpMatchDiscrsOnly 2025-02-16 14:03:50 -08:00
Leonardo de Moura
0771437154 fix: MatchCond reducibility 2025-02-16 14:03:50 -08:00
Leonardo de Moura
07fcc32a7d feat: add sanity check at pushEqCore 2025-02-16 14:03:50 -08:00
Leonardo de Moura
65c1ebf965 fix: missing mkExpectedTypeHint 2025-02-16 14:03:50 -08:00
Leonardo de Moura
d2da498ea0 fix: equality resolution should work with reducible transparency setting 2025-02-16 14:03:50 -08:00
Leonardo de Moura
c7386a1524 fix: checkInvariants in the offset constraint module 2025-02-16 14:03:50 -08:00
Leonardo de Moura
0e3ff950f8 fix: missing hint 2025-02-16 14:03:50 -08:00
Leonardo de Moura
5116fca8f6 feat: add sanity check at addNewFact 2025-02-16 14:03:50 -08:00
Leonardo de Moura
e801c473e2 doc: add note at simpMatchDiscrsOnly 2025-02-16 14:03:50 -08:00
Leonardo de Moura
2c6d56be6c fix: whnfD at applyCases? 2025-02-16 14:03:50 -08:00
19 changed files with 189 additions and 65 deletions

View File

@@ -14,6 +14,12 @@ def nestedProof (p : Prop) {h : p} : p := h
/--
Gadget for marking `match`-expressions that should not be reduced by the `grind` simplifier, but the discriminants should be normalized.
We use it when adding instances of `match`-equations to prevent them from being simplified to true.
Remark: it must not be marked as `[reducible]`. Otherwise, `simp` will reduce
```
simpMatchDiscrsOnly (match 0 with | 0 => true | _ => false) = true
```
using `eq_self`.
-/
def simpMatchDiscrsOnly {α : Sort u} (a : α) : α := a
@@ -28,7 +34,7 @@ Gadget for annotating the equalities in `match`-equations conclusions.
`_origin` is the term used to instantiate the `match`-equation using E-matching.
When `EqMatch a b origin` is `True`, we mark `origin` as a resolved case-split.
-/
def EqMatch (a b : α) {_origin : α} : Prop := a = b
abbrev EqMatch (a b : α) {_origin : α} : Prop := a = b
/--
Gadget for annotating conditions of `match` equational lemmas.
@@ -36,7 +42,13 @@ We use this annotation for two different reasons:
- We don't want to normalize them.
- We have a propagator for them.
-/
def MatchCond (p : Prop) : Prop := p
abbrev MatchCond (p : Prop) : Prop := p
/--
Similar to `MatchCond`, but not reducible. We use it to ensure `simp`
will not eliminate it. After we apply `simp`, we replace it with `MatchCond`.
-/
def PreMatchCond (p : Prop) : Prop := p
theorem nestedProof_congr (p q : Prop) (h : p = q) (hp : p) (hq : q) : HEq (@nestedProof p hp) (@nestedProof q hq) := by
subst h; apply HEq.refl

View File

@@ -165,12 +165,13 @@ def mkHEqTrans (h₁ h₂ : Expr) : MetaM Expr := do
| _, none => throwAppBuilderException ``HEq.trans ("heterogeneous equality proof expected" ++ hasTypeMsg h₂ hType₂)
/-- Given `h : HEq a b` where `a` and `b` have the same type, returns a proof of `Eq a b`. -/
def mkEqOfHEq (h : Expr) : MetaM Expr := do
def mkEqOfHEq (h : Expr) (check := true) : MetaM Expr := do
let hType infer h
match hType.heq? with
| some (α, a, β, b) =>
unless ( isDefEq α β) do
throwAppBuilderException ``eq_of_heq m!"heterogeneous equality types are not definitionally equal{indentExpr α}\nis not definitionally equal to{indentExpr β}"
if check then
unless ( isDefEq α β) do
throwAppBuilderException ``eq_of_heq m!"heterogeneous equality types are not definitionally equal{indentExpr α}\nis not definitionally equal to{indentExpr β}"
let u getLevel α
return mkApp4 (mkConst ``eq_of_heq [u]) α a b h
| _ =>

View File

@@ -233,6 +233,7 @@ def Cnstr.toExpr (c : Cnstr NodeId) : GoalM Expr := do
return mkNatLE u (mkNatAdd v (Lean.toExpr c.k.toNat))
def checkInvariants : GoalM Unit := do
unless ( isInconsistent) do
let s get'
for u in [:s.targets.size], es in s.targets.toArray do
for (v, k) in es do
@@ -242,8 +243,7 @@ def checkInvariants : GoalM Unit := do
trace[grind.debug.offset.proof] "{p} : {← inferType p}"
check p
unless ( withDefault <| isDefEq ( inferType p) ( Cnstr.toExpr c)) do
trace[grind.debug.offset.proof] "failed: {← inferType p} =?= {← Cnstr.toExpr c}"
unreachable!
throwError "`grind` internal error in the offset constraint module, constraint{indentExpr (← Cnstr.toExpr c)}\nis not definitionally equal to type of its proof{indentExpr (← inferType p)}"
/--
Adds an edge `u --(k) --> v` justified by the proof term `p`, and then

View File

@@ -23,7 +23,7 @@ conditions corresponding to overlapping patterns.
private def addMatchCondsToAlt (alt : Expr) : Expr := Id.run do
let .forallE _ d b _ := alt
| return alt
let d := if isMatchCondCandidate d then markAsMatchCond d else d
let d := if isMatchCondCandidate d then markAsPreMatchCond d else d
return alt.updateForallE! d (addMatchCondsToAlt b)
/--

View File

@@ -218,7 +218,7 @@ Annotate the conditions using `Grind.MatchCond`. See `MatchCond.lean`.
private partial def annotateEqnTypeConds (prop : Expr) (k : Expr M Expr := pure) : M Expr := do
if let .forallE n d b bi := prop then
let d := if ( isProp d) then
markAsMatchCond d
markAsPreMatchCond d
else
d
withLocalDecl n bi d fun x => do
@@ -247,10 +247,17 @@ private def addNewInstance (thm : EMatchTheorem) (proof : Expr) (generation : Na
if grind.debug.proofs.get ( getOptions) then
check proof
let mut prop inferType proof
let mut proof := proof
if Match.isMatchEqnTheorem ( getEnv) thm.origin.key then
prop annotateMatchEqnType prop ( read).initApp
-- We must add a hint here because `annotateMatchEqnType` introduces `simpMatchDiscrsOnly` and
-- `Grind.PreMatchCond` which are not reducible.
proof mkExpectedTypeHint proof prop
else if ( isEqnThm thm.origin.key) then
prop annotateEqnTypeConds prop
-- We must add a hint because `annotateEqnTypeConds` introduces `Grind.PreMatchCond`
-- which is not reducible.
proof mkExpectedTypeHint proof prop
trace_goal[grind.ematch.instance] "{← thm.origin.pp}: {prop}"
addTheoremInstance thm proof prop (generation+1)

View File

@@ -5,12 +5,35 @@ Authors: Leonardo de Moura
-/
prelude
import Lean.Meta.AppBuilder
import Lean.Meta.MatchUtil
namespace Lean.Meta.Grind
/-! A basic "equality resolution" procedure. -/
private def eqResCore (prop proof : Expr) : MetaM (Option (Expr × Expr)) := withNewMCtxDepth do
/--
Similar to `forallMetaTelescopeReducing`, but if `prop` resulting type is of the form `¬ p`, it will "convert" it so `p → False`, and
will return a hypothesis for it and return `False` as the resulting type.
-/
private def forallMetaTelescopeReducingAndUnfoldingNot (prop : Expr) : MetaM (Array Expr × Expr) := do
let (ms, _, type) forallMetaTelescopeReducing prop
if let some p matchNot? type then
let m mkFreshExprMVar p
return (ms.push m, mkConst ``False)
return (ms, type)
private def eqResCore (prop proof : Expr) : MetaM (Option (Expr × Expr)) := withNewMCtxDepth do
/-
We use `forallMetaTelescopeReducingAndUnfoldingNot` because we want to treat
```
∀ x, ¬ f x = f a
```
as
```
∀ x, f x = f a → False
```
recall that `¬` is not reducible.
-/
let (ms, type) forallMetaTelescopeReducingAndUnfoldingNot prop
if ms.isEmpty then return none
let mut progress := false
for m in ms do

View File

@@ -31,7 +31,7 @@ We added this feature because it may be coming from external sources
-/
private def preprocessHypothesis (e : Expr) : GoalM Simp.Result := do
if isMatchCondCandidate e then
preprocess (markAsMatchCond e)
preprocess (markAsPreMatchCond e)
else
preprocess e
@@ -141,7 +141,11 @@ private def isEagerCasesCandidate (goal : Goal) (type : Expr) : Bool := Id.run d
return goal.split.casesTypes.isEagerSplit declName
private def applyCases? (goal : Goal) (fvarId : FVarId) : GrindM (Option (List Goal)) := goal.mvarId.withContext do
let type whnfD ( fvarId.getType)
/-
Remark: we used to use `whnfD`. This was a mistake, we don't want to unfold user-defined abstractions.
Example: `a b` is defined as `∃ x, b = a * x`
-/
let type whnf ( fvarId.getType)
if isEagerCasesCandidate goal type then
if let .const declName _ := type.getAppFn then
saveCases declName true

View File

@@ -153,7 +153,7 @@ def Result.toMessageData (result : Result) : MetaM MessageData := do
return MessageData.joinSep msgs m!"\n"
def main (mvarId : MVarId) (params : Params) (mainDeclName : Name) (fallback : Fallback) : MetaM Result := do profileitM Exception "grind" ( getOptions) do
let go : GrindM Result := do
let go : GrindM Result := withReducible do
let goals initCore mvarId params
let (failures, skipped) solve goals fallback
trace[grind.debug.final] "{← ppGoals goals}"

View File

@@ -7,7 +7,6 @@ prelude
import Init.Grind
import Init.Simproc
import Lean.Meta.Tactic.Contradiction
import Lean.Meta.Tactic.Simp.Simproc
import Lean.Meta.Tactic.Grind.ProveEq
import Lean.Meta.Tactic.Grind.PropagatorAttr
@@ -65,8 +64,11 @@ In the two equational theorems above, we have the following conditions.
- `(∀ (b_1 c : S), b = S.mk2 1 (b_1.mk4 c) → False)`
- `(∀ (a_1 : Bool) (b_1 c : S), a = S.mk3 a_1 → b = b_1.mk4 c → False)`
```
When instantiating the equations (and `match`-splitter), we wrap the conditions with the gadget `Grind.MatchCond`.
This gadget is used for implementing truth-value propagation. See the propagator `propagateMatchCond` below.
When instantiating the equations (and `match`-splitter), we wrap the conditions with the gadget `Grind.PreMatchCond`.
`Grind.PreMatchCond` uses the default reducibility setting and cannot be accidentally reduced by `simp`.
After `simp` is applied, it is replaced with `Grind.MatchCond` which is reducible.
This `Grind.MatchCond` is used for implementing truth-value propagation.
See the propagator `propagateMatchCond` below.
For example, given a condition `C` of the form `Grind.MatchCond (∀ (a : Nat), t = S.mk1 a → False)`,
if `t` is merged with an equivalence class containing `S.mk2 n s`, then `C` is asseted to `true` by `propagateMatchCond`.
@@ -80,26 +82,6 @@ would require major refactoring and affect many modules, this issue is important
A different representation could simplify `grind`, but it could add extra complexity to other modules.
-/
/--
Returns `Grind.MatchCond e`.
Recall that `Grind.MatchCond` is an identity function,
but the following simproc is used to prevent the term `e` from being simplified,
and we have special support for propagating is truth value.
-/
def markAsMatchCond (e : Expr) : Expr :=
mkApp (mkConst ``Grind.MatchCond) e
def isMatchCond (e : Expr) : Bool :=
e.isAppOfArity ``Grind.MatchCond 1
builtin_dsimproc_decl reduceMatchCond (Grind.MatchCond _) := fun e => do
let_expr Grind.MatchCond _ e | return .continue
return .done e
/-- Adds `reduceMatchCond` to `s` -/
def addMatchCond (s : Simprocs) : CoreM Simprocs := do
s.add ``reduceMatchCond (post := false)
/--
Returns `some (α?, lhs, rhs)` if `e` is of the form
- `Eq _ lhs rhs` (`?α := none`), or
@@ -305,7 +287,7 @@ where
return none
let isHEq := α?.isSome
let h if isHEq then
mkEqOfHEq ( mkHEqTrans ( mkHEqProof root.self lhs) h)
mkEqOfHEq ( mkHEqTrans ( mkHEqProof root.self lhs) h) (check := false)
else
mkEqTrans ( mkEqProof root.self lhs) h
if root.ctor then

View File

@@ -18,6 +18,9 @@ the discriminants of a `match`-expression. See `reduceSimpMatchDiscrsOnly`.
def markAsSimpMatchDiscrsOnly (e : Expr) : MetaM Expr :=
mkAppM ``Grind.simpMatchDiscrsOnly #[e]
def isSimpMatchDiscrsOnly (e : Expr) :=
e.isAppOfArity ``Grind.simpMatchDiscrsOnly 2
builtin_simproc_decl reduceSimpMatchDiscrsOnly (Grind.simpMatchDiscrsOnly _) := fun e => do
let_expr Grind.simpMatchDiscrsOnly _ m e | return .continue
let .const declName _ := m.getAppFn
@@ -33,10 +36,19 @@ def addSimpMatchDiscrsOnly (s : Simprocs) : CoreM Simprocs := do
s.add ``reduceSimpMatchDiscrsOnly (post := false)
/-- Erases `Grind.simpMatchDiscrsOnly` annotations. -/
def eraseSimpMatchDiscrsOnly (e : Expr) : CoreM Expr := do
let pre (e : Expr) := do
let_expr Grind.simpMatchDiscrsOnly _ a := e | return .continue e
return .continue a
Core.transform e (pre := pre)
def eraseSimpMatchDiscrsOnly (e : Expr) : MetaM Simp.Result := do
if e.find? isSimpMatchDiscrsOnly |>.isNone then
return { expr := e }
else
let pre (e : Expr) := do
let_expr Grind.simpMatchDiscrsOnly _ a := e | return .continue e
return .continue a
let e' Core.transform e (pre := pre)
/-
`grind` uses the `.reducible` transparency setting, and `Grind.simpMatchDiscrsOnly` is not
reducible. Thus, `e` and `e'` are not definitionally equal in this setting, and we must
add a hint.
-/
return { expr := e', proof? := ( mkExpectedTypeHint ( mkEqRefl e') ( mkEq e e')) }
end Lean.Meta.Grind

View File

@@ -39,7 +39,7 @@ Given `h : HEq a b`, returns a proof `a = b` if `heq == false`.
Otherwise, it returns `h`.
-/
private def mkEqOfHEqIfNeeded (h : Expr) (heq : Bool) : MetaM Expr := do
if heq then return h else mkEqOfHEq h
if heq then return h else mkEqOfHEq h (check := false)
/--
Given `lhs` and `rhs` that are in the same equivalence class,
@@ -240,7 +240,7 @@ mutual
else if heq then
mkHEqOfEq lhsEqRhs
else
mkEqOfHEq lhsEqRhs
mkEqOfHEq lhsEqRhs (check := false)
end

View File

@@ -35,7 +35,12 @@ def preprocess (e : Expr) : GoalM Simp.Result := do
let e' eraseIrrelevantMData e'
let e' foldProjs e'
let e' normalizeLevels e'
let e' eraseSimpMatchDiscrsOnly e'
let r' eraseSimpMatchDiscrsOnly e'
let r r.mkEqTrans r'
let e' := r'.expr
let r' replacePreMatchCond e'
let r r.mkEqTrans r'
let e' := r'.expr
let e' canon e'
let e' shareCommon e'
trace_goal[grind.simp] "{e}\n===>\n{e'}"

View File

@@ -41,7 +41,7 @@ protected def getSimprocs : MetaM (Array Simprocs) := do
-/
let s := s.erase ``List.reduceReplicate
let s addSimpMatchDiscrsOnly s
let s addMatchCond s
let s addPreMatchCondSimproc s
return #[s]
/-- Returns the simplification context used by `grind`. -/

View File

@@ -568,6 +568,9 @@ def markTheoremInstance (proof : Expr) (assignment : Array Expr) : GoalM Bool :=
/-- Adds a new fact `prop` with proof `proof` to the queue for processing. -/
def addNewFact (proof : Expr) (prop : Expr) (generation : Nat) : GoalM Unit := do
if grind.debug.get ( getOptions) then
unless ( withReducible <| isDefEq ( inferType proof) prop) do
throwError "`grind` internal error, trying to assert{indentExpr prop}\nwith proof{indentExpr proof}\nwhich has type{indentExpr (← inferType proof)}\nwhich is not definitionally equal with `reducible` transparency setting}"
modify fun s => { s with newFacts := s.newFacts.enqueue { proof, prop, generation } }
/-- Adds a new theorem instance produced using E-matching. -/
@@ -704,7 +707,13 @@ def Goal.getTarget? (goal : Goal) (e : Expr) : Option Expr := Id.run do
If `isHEq` is `false`, it pushes `lhs = rhs` with `proof` to `newEqs`.
Otherwise, it pushes `HEq lhs rhs`.
-/
def pushEqCore (lhs rhs proof : Expr) (isHEq : Bool) : GoalM Unit :=
def pushEqCore (lhs rhs proof : Expr) (isHEq : Bool) : GoalM Unit := do
if grind.debug.get ( getOptions) then
unless proof == congrPlaceholderProof do
let expectedType if isHEq then mkHEq lhs rhs else mkEq lhs rhs
unless ( withReducible <| isDefEq ( inferType proof) expectedType) do
throwError "`grind` internal error, trying to assert equality{indentExpr expectedType}\nwith proof{indentExpr proof}\nwhich has type{indentExpr (← inferType proof)}\nwhich is not definitionally equal with `reducible` transparency setting}"
trace[grind.debug] "pushEqCore: {expectedType}"
modify fun s => { s with newEqs := s.newEqs.push { lhs, rhs, proof, isHEq } }
/-- Return `true` if `a` and `b` have the same type. -/

View File

@@ -4,10 +4,12 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
prelude
import Init.Simproc
import Lean.Meta.AbstractNestedProofs
import Lean.Meta.Transform
import Lean.Meta.Tactic.Util
import Lean.Meta.Tactic.Clear
import Lean.Meta.Tactic.Simp.Simproc
namespace Lean.Meta.Grind
/--
@@ -35,6 +37,13 @@ def _root_.Lean.MVarId.transformTarget (mvarId : MVarId) (f : Expr → MetaM Exp
mvarId.assign mvarNew
return mvarNew.mvarId!
/--
Returns `true` if `declName` is the name of a grind helper declaration that
should not be unfolded by `unfoldReducible`.
-/
def isGrindGadget (declName : Name) : Bool :=
declName == ``Grind.EqMatch
/--
Unfolds all `reducible` declarations occurring in `e`.
-/
@@ -42,6 +51,7 @@ def unfoldReducible (e : Expr) : MetaM Expr :=
let pre (e : Expr) : MetaM TransformStep := do
let .const declName _ := e.getAppFn | return .continue
unless ( isReducible declName) do return .continue
if isGrindGadget declName then return .continue
let some v unfoldDefinition? e | return .continue
return .visit v
Core.transform e (pre := pre)
@@ -123,7 +133,18 @@ def foldProjs (e : Expr) : MetaM Expr := do
return .done e
if h : idx < info.fieldNames.size then
let fieldName := info.fieldNames[idx]
return .done ( mkProjection s fieldName)
/-
In the test `grind_cat.lean`, the following operation fails if we are not using default
transparency. We get the following error.
```
error: AppBuilder for 'mkProjection', structure expected
T
has type
F ⟶ G
```
We should make `mkProjection` more robust.
-/
return .done ( withDefault <| mkProjection s fieldName)
else
trace[grind.issues] "found `Expr.proj` with invalid field index `{idx}`{indentExpr e}"
return .done e
@@ -147,4 +168,51 @@ This function is used for normalzing E-matching patterns. Note that it does not
@[extern "lean_grind_normalize"] -- forward definition
opaque normalize (e : Expr) : MetaM Expr
/--
Returns `Grind.MatchCond e`.
We have special support for propagating is truth value.
See comment at `MatchCond.lean`.
-/
def markAsMatchCond (e : Expr) : Expr :=
mkApp (mkConst ``Grind.MatchCond) e
def isMatchCond (e : Expr) : Bool :=
e.isAppOfArity ``Grind.MatchCond 1
/--
Returns `Grind.PreMatchCond e`.
Recall that `Grind.PreMatchCond` is an identity function,
but the simproc `reducePreMatchCond` is used to prevent the term `e` from being simplified.
`Grind.PreMatchCond` is later converted into `Grind.MatchCond`.
See comment at `MatchCond.lean`.
-/
def markAsPreMatchCond(e : Expr) : Expr :=
mkApp (mkConst ``Grind.PreMatchCond) e
def isPreMatchCond (e : Expr) : Bool :=
e.isAppOfArity ``Grind.PreMatchCond 1
builtin_dsimproc_decl reducePreMatchCond (Grind.PreMatchCond _) := fun e => do
let_expr Grind.PreMatchCond _ e | return .continue
return .done e
/-- Adds `reducePreMatchCond` to `s` -/
def addPreMatchCondSimproc (s : Simprocs) : CoreM Simprocs := do
s.add ``reducePreMatchCond (post := false)
/--
Converts `Grind.PreMatchCond` into `Grind.MatchCond`.
Recall that `Grind.PreMatchCond` uses default reducibility setting, but
`Grind.MatchCond` does not.
-/
def replacePreMatchCond (e : Expr) : MetaM Simp.Result := do
if e.find? isPreMatchCond |>.isNone then
return { expr := e }
else
let pre (e : Expr) := do
let_expr Grind.PreMatchCond p := e | return .continue e
return .continue (markAsMatchCond p)
let e' Core.transform e (pre := pre)
return { expr := e', proof? := ( mkExpectedTypeHint ( mkEqRefl e') ( mkEq e e')) }
end Lean.Meta.Grind

View File

@@ -144,15 +144,15 @@ def simpDvdCnstr? (e : Expr) : MetaM (Option (Expr × Expr)) := do
let h := mkApp3 (mkConst ``Int.Linear.RawDvdCnstr.eq_false_of_isUnsat) (toContextExpr atoms) (toExpr c) reflBoolTrue
return some (r, mkExpectedTypeHint h ( mkEq lhs r))
def simpExpr? (e : Expr) : MetaM (Option (Expr × Expr)) := do
let (e, atoms) toLinearExpr e
def simpExpr? (input : Expr) : MetaM (Option (Expr × Expr)) := do
let (e, atoms) toLinearExpr input
let p := e.toPoly
let e' := p.toExpr
if e != e' then
-- We only return some if monomials were fused
let p := mkApp4 (mkConst ``Int.Linear.Expr.eq_of_toPoly_eq) (toContextExpr atoms) (toExpr e) (toExpr e') reflBoolTrue
let r e'.denoteExpr atoms
return some (r, p)
return some (r, mkExpectedTypeHint p ( mkEq input r))
else
return none

View File

@@ -67,8 +67,8 @@ def simpCnstr? (e : Expr) : MetaM (Option (Expr × Expr)) := do
else
simpCnstrPos? e
def simpExpr? (e : Expr) : MetaM (Option (Expr × Expr)) := do
let (e, ctx) toLinearExpr e
def simpExpr? (input : Expr) : MetaM (Option (Expr × Expr)) := do
let (e, ctx) toLinearExpr input
let p := e.toPoly
let p' := p.norm
if p'.length < p.length then
@@ -76,7 +76,7 @@ def simpExpr? (e : Expr) : MetaM (Option (Expr × Expr)) := do
let e' : LinearExpr := p'.toExpr
let p := mkApp4 (mkConst ``Nat.Linear.Expr.eq_of_toNormPoly_eq) (toContextExpr ctx) (toExpr e) (toExpr e') reflBoolTrue
let r e'.toArith ctx
return some (r, p)
return some (r, mkExpectedTypeHint p ( mkEq input r))
else
return none

View File

@@ -47,23 +47,23 @@ info: [grind] Counters
[thm] Array.size_set ↦ 3
---
info: [diag] Diagnostics
[reduction] unfolded declarations (max: 11842, num: 3):
[reduction] LT.lt ↦ 11842
[reduction] unfolded declarations (max: 11519, num: 3):
[reduction] LT.lt ↦ 11519
[reduction] getElem ↦ 76
[reduction] Nat.lt ↦ 35
[reduction] Nat.lt ↦ 34
[reduction] unfolded instances (max: 38, num: 1):
[reduction] Array.instGetElemNatLtSize ↦ 38
[reduction] unfolded reducible declarations (max: 7091, num: 7):
[reduction] Array.size ↦ 7091
[reduction] Array.toList ↦ 1897
[reduction] autoParam ↦ 1724
[reduction] outParam ↦ 172
[reduction] unfolded reducible declarations (max: 6907, num: 7):
[reduction] Array.size ↦ 6907
[reduction] Array.toList ↦ 1851
[reduction] autoParam ↦ 1675
[reduction] outParam ↦ 168
[reduction] Ne ↦ 60
[reduction] GT.gt ↦ 46
[reduction] List.casesOn ↦ 24
[def_eq] heuristic for solving `f a =?= f b` (max: 5067, num: 2):
[def_eq] Nat.lt ↦ 5067
[def_eq] List.length ↦ 1691
[def_eq] heuristic for solving `f a =?= f b` (max: 4929, num: 2):
[def_eq] Nat.lt ↦ 4929
[def_eq] List.length ↦ 1645
[kernel] unfolded declarations (max: 106, num: 5):
[kernel] LT.lt ↦ 106
[kernel] outParam ↦ 46

View File

@@ -1,3 +1,4 @@
set_option grind.debug true
inductive S where
| mk1 (n : Nat)
| mk2 (n : Nat) (s : S)