mirror of
https://github.com/leanprover/lean4.git
synced 2026-03-17 18:34:06 +00:00
Compare commits
7 Commits
5c685465bd
...
kernel_tc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e746613ecc | ||
|
|
a2d41bf1f8 | ||
|
|
2fd1f2b588 | ||
|
|
f644affd8f | ||
|
|
8ed9e3b0c0 | ||
|
|
a50abdcf88 | ||
|
|
7caad98589 |
@@ -29,6 +29,29 @@ theorem id_def {α : Sort u} (a : α) : id a = a := rfl
|
||||
|
||||
attribute [grind] id
|
||||
|
||||
/--
|
||||
A helper gadget for instructing the kernel to eagerly reduce terms.
|
||||
|
||||
When the gadget wraps the argument of an application, then when checking that
|
||||
the expected and inferred type of the argument match, the kernel will evaluate terms more eagerly.
|
||||
It is often used to wrap `Eq.refl true` proof terms as `eagerReduce (Eq.refl true)`
|
||||
when using proof by reflection.
|
||||
As an example, consider the theorem:
|
||||
```
|
||||
theorem eq_norm (ctx : Context) (p₁ p₂ : Poly) (h : (p₁.norm == p₂) = true) :
|
||||
p₁.denote ctx = 0 → p₂.denote ctx = 0
|
||||
```
|
||||
The argument `h : (p₁.norm == p₂) = true` is a candidate for `eagerReduce`.
|
||||
When applying this theorem, we would write:
|
||||
|
||||
```
|
||||
eq_norm ctx p q (eagerReduce (Eq.refl true)) h
|
||||
```
|
||||
to instruct the kernel to use eager reduction when establishing that `(p.norm == q) = true` is
|
||||
definitionally equal to `true = true`.
|
||||
-/
|
||||
@[expose] def eagerReduce {α : Sort u} (a : α) : α := a
|
||||
|
||||
/--
|
||||
`flip f a b` is `f b a`. It is useful for "point-free" programming,
|
||||
since it can sometimes be used to avoid introducing variables.
|
||||
|
||||
@@ -2384,4 +2384,10 @@ def reflBoolTrue : Expr :=
|
||||
def reflBoolFalse : Expr :=
|
||||
mkApp2 (mkConst ``Eq.refl [levelOne]) (mkConst ``Bool) (mkConst ``Bool.false)
|
||||
|
||||
def eagerReflBoolTrue : Expr :=
|
||||
mkApp2 (mkConst ``eagerReduce [0]) (mkApp3 (mkConst ``Eq [1]) (mkConst ``Bool) (mkConst ``Bool.true) (mkConst ``Bool.true)) reflBoolTrue
|
||||
|
||||
def eagerReflBoolFalse : Expr :=
|
||||
mkApp2 (mkConst ``eagerReduce [0]) (mkApp3 (mkConst ``Eq [1]) (mkConst ``Bool) (mkConst ``Bool.false) (mkConst ``Bool.false)) reflBoolFalse
|
||||
|
||||
end Lean
|
||||
|
||||
@@ -177,7 +177,7 @@ def litToCtor (e : Expr) : MetaM Expr := do
|
||||
let p := mkApp4 (mkConst ``LT.lt [0]) (mkConst ``Nat) (mkConst ``instLTNat) i n
|
||||
let h := mkApp3 (mkConst ``of_decide_eq_true) p
|
||||
(mkApp2 (mkConst ``Nat.decLt) i n)
|
||||
reflBoolTrue
|
||||
eagerReflBoolTrue
|
||||
return mkApp3 (mkConst ``Fin.mk) n i h
|
||||
return e
|
||||
|
||||
|
||||
@@ -86,17 +86,17 @@ private def processInv (e inst a : Expr) : RingM Unit := do
|
||||
if c == 0 then
|
||||
let expected ← mkEq (mkApp2 (← getMulFn) a e) (← denoteNum 1)
|
||||
pushNewFact <| mkExpectedPropHint
|
||||
(mkApp5 (mkConst ``Grind.CommRing.inv_int_eq [ring.u]) ring.type fieldInst charInst (mkIntLit k) reflBoolTrue)
|
||||
(mkApp5 (mkConst ``Grind.CommRing.inv_int_eq [ring.u]) ring.type fieldInst charInst (mkIntLit k) eagerReflBoolTrue)
|
||||
expected
|
||||
else if k % c == 0 then
|
||||
let expected ← mkEq e (← denoteNum 0)
|
||||
pushNewFact <| mkExpectedPropHint
|
||||
(mkApp6 (mkConst ``Grind.CommRing.inv_zero_eqC [ring.u]) ring.type (mkNatLit c) fieldInst charInst (mkIntLit k) reflBoolTrue)
|
||||
(mkApp6 (mkConst ``Grind.CommRing.inv_zero_eqC [ring.u]) ring.type (mkNatLit c) fieldInst charInst (mkIntLit k) eagerReflBoolTrue)
|
||||
expected
|
||||
else
|
||||
let expected ← mkEq (mkApp2 (← getMulFn) a e) (← denoteNum 1)
|
||||
pushNewFact <| mkExpectedPropHint
|
||||
(mkApp6 (mkConst ``Grind.CommRing.inv_int_eqC [ring.u]) ring.type (mkNatLit c) fieldInst charInst (mkIntLit k) reflBoolTrue)
|
||||
(mkApp6 (mkConst ``Grind.CommRing.inv_int_eqC [ring.u]) ring.type (mkNatLit c) fieldInst charInst (mkIntLit k) eagerReflBoolTrue)
|
||||
expected
|
||||
return ()
|
||||
pushNewFact <| mkApp3 (mkConst ``Grind.CommRing.inv_split [ring.u]) ring.type fieldInst a
|
||||
|
||||
@@ -267,7 +267,7 @@ def setEqUnsat (c : EqCnstr) : RingM Unit := do
|
||||
mkApp2 (mkConst ``Grind.CommRing.NullCert.eq_unsatC [ring.u]) ring.type (toExpr char)
|
||||
let ctx ← toContextExpr
|
||||
let nc := toExpr (ncx.toNullCert)
|
||||
let h := mkApp6 h ring.commRingInst charInst ctx nc (toExpr k) reflBoolTrue
|
||||
let h := mkApp6 h ring.commRingInst charInst ctx nc (toExpr k) eagerReflBoolTrue
|
||||
closeGoal <| ncx.applyEqs h
|
||||
|
||||
def setDiseqUnsat (c : DiseqCnstr) : RingM Unit := do
|
||||
@@ -287,7 +287,7 @@ def setDiseqUnsat (c : DiseqCnstr) : RingM Unit := do
|
||||
mkApp6 (mkConst ``Grind.CommRing.NullCert.ne_nzdiv_unsat [ring.u]) ring.type ring.commRingInst nzDivInst ctx nc (toExpr k)
|
||||
| none, none =>
|
||||
mkApp4 (mkConst ``Grind.CommRing.NullCert.ne_unsat [ring.u]) ring.type ring.commRingInst ctx nc
|
||||
let h := mkApp4 h (toExpr c.rlhs) (toExpr c.rrhs) reflBoolTrue (← mkDiseqProof c.lhs c.rhs)
|
||||
let h := mkApp4 h (toExpr c.rlhs) (toExpr c.rrhs) eagerReflBoolTrue (← mkDiseqProof c.lhs c.rhs)
|
||||
closeGoal <| ncx.applyEqs h
|
||||
|
||||
def propagateEq (a b : Expr) (ra rb : RingExpr) (d : PolyDerivation) : RingM Unit := do
|
||||
@@ -305,7 +305,7 @@ def propagateEq (a b : Expr) (ra rb : RingExpr) (d : PolyDerivation) : RingM Uni
|
||||
mkApp6 (mkConst ``Grind.CommRing.NullCert.eq_nzdiv [ring.u]) ring.type ring.commRingInst nzDivInst ctx nc (toExpr k)
|
||||
| none, none =>
|
||||
mkApp4 (mkConst ``Grind.CommRing.NullCert.eq [ring.u]) ring.type ring.commRingInst ctx nc
|
||||
let h := mkApp3 h (toExpr ra) (toExpr rb) reflBoolTrue
|
||||
let h := mkApp3 h (toExpr ra) (toExpr rb) eagerReflBoolTrue
|
||||
trace_goal[grind.debug.ring.impEq] "{a}, {b}"
|
||||
let eq := mkApp3 (mkConst ``Eq [.succ ring.u]) ring.type a b
|
||||
pushEq a b <| mkExpectedPropHint (ncx.applyEqs h) eq
|
||||
@@ -419,40 +419,40 @@ partial def _root_.Lean.Meta.Grind.Arith.CommRing.EqCnstr.toExprProof (c : EqCns
|
||||
match c.h with
|
||||
| .core a b lhs rhs =>
|
||||
let h ← mkStepPrefix ``Stepwise.core ``Stepwise.coreC
|
||||
return mkApp5 h (← mkExprDecl lhs) (← mkExprDecl rhs) (← mkPolyDecl c.p) reflBoolTrue (← mkEqProof a b)
|
||||
return mkApp5 h (← mkExprDecl lhs) (← mkExprDecl rhs) (← mkPolyDecl c.p) eagerReflBoolTrue (← mkEqProof a b)
|
||||
| .coreS a b sa sb ra rb =>
|
||||
let h' ← mkSemiringPrefix ``Grind.Ring.OfSemiring.of_eq
|
||||
let h' := mkApp3 h' (← mkSExprDecl sa) (← mkSExprDecl sb) (← mkEqProof a b)
|
||||
let h ← mkStepPrefix ``Stepwise.core ``Stepwise.coreC
|
||||
return mkApp5 h (← mkExprDecl ra) (← mkExprDecl rb) (← mkPolyDecl c.p) reflBoolTrue h'
|
||||
return mkApp5 h (← mkExprDecl ra) (← mkExprDecl rb) (← mkPolyDecl c.p) eagerReflBoolTrue h'
|
||||
| .superpose k₁ m₁ c₁ k₂ m₂ c₂ =>
|
||||
let h ← mkStepPrefix ``Stepwise.superpose ``Stepwise.superposeC
|
||||
return mkApp10 h
|
||||
(toExpr k₁) (← mkMonDecl m₁) (← mkPolyDecl c₁.p)
|
||||
(toExpr k₂) (← mkMonDecl m₂) (← mkPolyDecl c₂.p)
|
||||
(← mkPolyDecl c.p) reflBoolTrue (← toExprProof c₁) (← toExprProof c₂)
|
||||
(← mkPolyDecl c.p) eagerReflBoolTrue (← toExprProof c₁) (← toExprProof c₂)
|
||||
| .simp k₁ c₁ k₂ m₂ c₂ =>
|
||||
let h ← mkStepPrefix ``Stepwise.simp ``Stepwise.simpC
|
||||
return mkApp9 h
|
||||
(toExpr k₁) (← mkPolyDecl c₁.p)
|
||||
(toExpr k₂) (← mkMonDecl m₂) (← mkPolyDecl c₂.p)
|
||||
(← mkPolyDecl c.p) reflBoolTrue (← toExprProof c₁) (← toExprProof c₂)
|
||||
(← mkPolyDecl c.p) eagerReflBoolTrue (← toExprProof c₁) (← toExprProof c₂)
|
||||
| .mul k c₁ =>
|
||||
let h ← mkStepPrefix ``Stepwise.mul ``Stepwise.mulC
|
||||
return mkApp5 h (← mkPolyDecl c₁.p) (toExpr k) (← mkPolyDecl c.p) reflBoolTrue (← toExprProof c₁)
|
||||
return mkApp5 h (← mkPolyDecl c₁.p) (toExpr k) (← mkPolyDecl c.p) eagerReflBoolTrue (← toExprProof c₁)
|
||||
| .div k c₁ =>
|
||||
let h ← mkStepPrefix ``Stepwise.div ``Stepwise.divC
|
||||
let some nzInst ← noZeroDivisorsInst?
|
||||
| throwNoNatZeroDivisors
|
||||
return mkApp6 h nzInst (← mkPolyDecl c₁.p) (toExpr k) (← mkPolyDecl c.p) reflBoolTrue (← toExprProof c₁)
|
||||
return mkApp6 h nzInst (← mkPolyDecl c₁.p) (toExpr k) (← mkPolyDecl c.p) eagerReflBoolTrue (← toExprProof c₁)
|
||||
| .gcd a b c₁ c₂ =>
|
||||
let h ← mkStepBasicPrefix ``Grind.CommRing.eq_gcd
|
||||
return mkApp8 h (toExpr a) (toExpr b) (← mkPolyDecl c₁.p) (← mkPolyDecl c₂.p) (← mkPolyDecl c.p)
|
||||
reflBoolTrue (← toExprProof c₁) (← toExprProof c₂)
|
||||
eagerReflBoolTrue (← toExprProof c₁) (← toExprProof c₂)
|
||||
| .numEq0 k c₁ c₂ =>
|
||||
let h ← mkStepBasicPrefix ``Grind.CommRing.eq_normEq0
|
||||
return mkApp7 h (toExpr k) (← mkPolyDecl c₁.p) (← mkPolyDecl c₂.p) (← mkPolyDecl c.p)
|
||||
reflBoolTrue (← toExprProof c₁) (← toExprProof c₂)
|
||||
eagerReflBoolTrue (← toExprProof c₁) (← toExprProof c₂)
|
||||
|
||||
open Lean.Grind.CommRing in
|
||||
/--
|
||||
@@ -474,7 +474,7 @@ private def derivToExprProof (d : PolyDerivation) : ProofM (Int × Poly × Expr)
|
||||
let h := mkApp10 h
|
||||
(toExpr k) (← mkPolyDecl p₀) (← mkPolyDecl d.p)
|
||||
(toExpr k₂) (← mkMonDecl m₂) (← mkPolyDecl c₂.p) (← mkPolyDecl p)
|
||||
reflBoolTrue h₁ h₂
|
||||
eagerReflBoolTrue h₁ h₂
|
||||
return (k₁*k, p₀, h)
|
||||
| .normEq0 p d c =>
|
||||
let (k, p₀, h₁) ← derivToExprProof d
|
||||
@@ -483,7 +483,7 @@ private def derivToExprProof (d : PolyDerivation) : ProofM (Int × Poly × Expr)
|
||||
let h ← mkStepBasicPrefix ``Grind.CommRing.d_normEq0
|
||||
let h := mkApp9 h
|
||||
(toExpr k) (toExpr a.natAbs) (← mkPolyDecl p₀) (← mkPolyDecl d.p)
|
||||
(← mkPolyDecl c.p) (← mkPolyDecl p) reflBoolTrue h₁ h₂
|
||||
(← mkPolyDecl c.p) (← mkPolyDecl p) eagerReflBoolTrue h₁ h₂
|
||||
return (k, p₀, h)
|
||||
|
||||
open Lean.Grind.CommRing in
|
||||
@@ -499,7 +499,7 @@ private def mkImpEqExprProof (lhs rhs : RingExpr) (d : PolyDerivation) : ProofM
|
||||
let some nzInst ← noZeroDivisorsInst?
|
||||
| throwNoNatZeroDivisors
|
||||
pure <| mkApp2 (← mkStepPrefix ``Stepwise.imp_keq ``Stepwise.imp_keqC) nzInst (toExpr k)
|
||||
return mkApp6 h (← mkExprDecl lhs) (← mkExprDecl rhs) (← mkPolyDecl p₀) (← mkPolyDecl d.p) reflBoolTrue h₁
|
||||
return mkApp6 h (← mkExprDecl lhs) (← mkExprDecl rhs) (← mkPolyDecl p₀) (← mkPolyDecl d.p) eagerReflBoolTrue h₁
|
||||
|
||||
private abbrev withSemiringContext (k : Option Expr → RingM Expr) : RingM Expr := do
|
||||
let some semiringId := (← getRing).semiringId? | k none
|
||||
@@ -532,10 +532,10 @@ def setEqUnsat (c : EqCnstr) : RingM Unit := do
|
||||
if char == 0 then
|
||||
h := mkApp h charInst
|
||||
let k ← getPolyConst c.p
|
||||
return mkApp4 h (← mkPolyDecl c.p) (toExpr k) reflBoolTrue (← c.toExprProof)
|
||||
return mkApp4 h (← mkPolyDecl c.p) (toExpr k) eagerReflBoolTrue (← c.toExprProof)
|
||||
else if let some fieldInst := ring.fieldInst? then
|
||||
return mkApp6 (mkConst ``Grind.CommRing.one_eq_zero_unsat [ring.u]) ring.type fieldInst (← getContext)
|
||||
(← mkPolyDecl c.p) reflBoolTrue (← c.toExprProof)
|
||||
(← mkPolyDecl c.p) eagerReflBoolTrue (← c.toExprProof)
|
||||
else
|
||||
throwError "`grind ring` internal error, unexpected unsat eq proof {← c.denoteExpr}"
|
||||
closeGoal h
|
||||
@@ -587,7 +587,7 @@ def setSemiringDiseqUnsat (a b : Expr) (sa sb : SemiringExpr) : SemiringM Unit :
|
||||
let semiring ← getSemiring
|
||||
let hne ← mkDiseqProof a b
|
||||
let h := mkApp3 (mkConst ``Grind.Ring.OfSemiring.eq_normS [semiring.u]) semiring.type semiring.commSemiringInst ctx
|
||||
let h := mkApp3 h (toExpr sa) (toExpr sb) reflBoolTrue
|
||||
let h := mkApp3 h (toExpr sa) (toExpr sb) eagerReflBoolTrue
|
||||
closeGoal (mkApp hne h)
|
||||
|
||||
end Lean.Meta.Grind.Arith.CommRing
|
||||
|
||||
@@ -107,7 +107,7 @@ def propagateIntDvd (e : Expr) : GoalM Unit := do
|
||||
let c := { d, p, h := .core e : DvdCnstr }
|
||||
c.assertCore
|
||||
else if (← isEqFalse e) then
|
||||
pushNewFact <| mkApp4 (mkConst ``Int.Linear.of_not_dvd) a b reflBoolTrue (mkOfEqFalseCore e (← mkEqFalseProof e))
|
||||
pushNewFact <| mkApp4 (mkConst ``Int.Linear.of_not_dvd) a b eagerReflBoolTrue (mkOfEqFalseCore e (← mkEqFalseProof e))
|
||||
|
||||
def propagateNatDvd (e : Expr) : GoalM Unit := do
|
||||
let_expr Dvd.dvd _ inst d₀ a := e | return ()
|
||||
|
||||
@@ -403,8 +403,8 @@ private def expandDivMod (a : Expr) (b : Int) : GoalM Unit := do
|
||||
let n : Int := 1 - b.natAbs
|
||||
let b := mkIntLit b
|
||||
pushNewFact <| mkApp2 (mkConst ``Int.Linear.ediv_emod) a b
|
||||
pushNewFact <| mkApp3 (mkConst ``Int.Linear.emod_nonneg) a b reflBoolTrue
|
||||
pushNewFact <| mkApp4 (mkConst ``Int.Linear.emod_le) a b (toExpr n) reflBoolTrue
|
||||
pushNewFact <| mkApp3 (mkConst ``Int.Linear.emod_nonneg) a b eagerReflBoolTrue
|
||||
pushNewFact <| mkApp4 (mkConst ``Int.Linear.emod_le) a b (toExpr n) eagerReflBoolTrue
|
||||
|
||||
private def propagateDiv (e : Expr) : GoalM Unit := do
|
||||
let_expr HDiv.hDiv _ _ _ inst a b ← e | return ()
|
||||
|
||||
@@ -156,7 +156,7 @@ partial def mkNonnegThm? (e : Expr) : GoalM (Option Expr) := do
|
||||
where
|
||||
go (e : Expr) : MetaM Expr := do
|
||||
match_expr e with
|
||||
| OfNat.ofNat _ _ _ => return mkApp2 (mkConst ``Int.Nonneg.num) e reflBoolTrue
|
||||
| OfNat.ofNat _ _ _ => return mkApp2 (mkConst ``Int.Nonneg.num) e eagerReflBoolTrue
|
||||
| HAdd.hAdd _ _ _ _ a b => return mkApp4 (mkConst ``Int.Nonneg.add) a b (← go a) (← go b)
|
||||
| HMul.hMul _ _ _ _ a b => return mkApp4 (mkConst ``Int.Nonneg.mul) a b (← go a) (← go b)
|
||||
| HDiv.hDiv _ _ _ _ a b => return mkApp4 (mkConst ``Int.Nonneg.div) a b (← go a) (← go b)
|
||||
|
||||
@@ -149,44 +149,44 @@ partial def EqCnstr.toExprProof (c' : EqCnstr) : ProofM Expr := caching c' do
|
||||
mkEqProof a zero
|
||||
| .core a b p₁ p₂ =>
|
||||
let h ← mkEqProof a b
|
||||
return mkApp6 (mkConst ``Int.Linear.eq_of_core) (← getContext) (← mkPolyDecl p₁) (← mkPolyDecl p₂) (← mkPolyDecl c'.p) reflBoolTrue h
|
||||
return mkApp6 (mkConst ``Int.Linear.eq_of_core) (← getContext) (← mkPolyDecl p₁) (← mkPolyDecl p₂) (← mkPolyDecl c'.p) eagerReflBoolTrue h
|
||||
| .coreToInt a b toIntThm lhs rhs =>
|
||||
let h := mkApp toIntThm (← mkEqProof a b)
|
||||
return mkApp6 (mkConst ``Int.Linear.eq_norm_expr) (← getContext) (← mkExprDecl lhs) (← mkExprDecl rhs) (← mkPolyDecl c'.p) reflBoolTrue h
|
||||
return mkApp6 (mkConst ``Int.Linear.eq_norm_expr) (← getContext) (← mkExprDecl lhs) (← mkExprDecl rhs) (← mkPolyDecl c'.p) eagerReflBoolTrue h
|
||||
| .defn e p =>
|
||||
let some x := (← getVarMap).find? { expr := e } | throwError "`grind` internal error, missing cutsat variable{indentExpr e}"
|
||||
return mkApp6 (mkConst ``Int.Linear.eq_def) (← getContext) (toExpr x) (← mkPolyDecl p) (← mkPolyDecl c'.p) reflBoolTrue (← mkEqRefl e)
|
||||
return mkApp6 (mkConst ``Int.Linear.eq_def) (← getContext) (toExpr x) (← mkPolyDecl p) (← mkPolyDecl c'.p) eagerReflBoolTrue (← mkEqRefl e)
|
||||
| .defnNat h x e =>
|
||||
return mkApp6 (mkConst ``Int.Linear.eq_def') (← getContext) (toExpr x) (← mkExprDecl e) (← mkPolyDecl c'.p) reflBoolTrue h
|
||||
return mkApp6 (mkConst ``Int.Linear.eq_def') (← getContext) (toExpr x) (← mkExprDecl e) (← mkPolyDecl c'.p) eagerReflBoolTrue h
|
||||
| .norm c =>
|
||||
return mkApp5 (mkConst ``Int.Linear.eq_norm) (← getContext) (← mkPolyDecl c.p) (← mkPolyDecl c'.p) reflBoolTrue (← c.toExprProof)
|
||||
return mkApp5 (mkConst ``Int.Linear.eq_norm) (← getContext) (← mkPolyDecl c.p) (← mkPolyDecl c'.p) eagerReflBoolTrue (← c.toExprProof)
|
||||
| .divCoeffs c =>
|
||||
let k := c.p.gcdCoeffs c.p.getConst
|
||||
return mkApp6 (mkConst ``Int.Linear.eq_coeff) (← getContext) (← mkPolyDecl c.p) (← mkPolyDecl c'.p) (toExpr k) reflBoolTrue (← c.toExprProof)
|
||||
return mkApp6 (mkConst ``Int.Linear.eq_coeff) (← getContext) (← mkPolyDecl c.p) (← mkPolyDecl c'.p) (toExpr k) eagerReflBoolTrue (← c.toExprProof)
|
||||
| .subst x c₁ c₂ =>
|
||||
let a := c₁.p.coeff x
|
||||
let b := c₂.p.coeff x
|
||||
return mkApp9 (mkConst ``Int.Linear.eq_eq_subst')
|
||||
(← getContext) (toExpr a) (toExpr b) (← mkPolyDecl c₁.p) (← mkPolyDecl c₂.p) (← mkPolyDecl c'.p)
|
||||
reflBoolTrue (← c₁.toExprProof) (← c₂.toExprProof)
|
||||
eagerReflBoolTrue (← c₁.toExprProof) (← c₂.toExprProof)
|
||||
| .ofLeGe c₁ c₂ =>
|
||||
return mkApp6 (mkConst ``Int.Linear.eq_of_le_ge)
|
||||
(← getContext) (← mkPolyDecl c₁.p) (← mkPolyDecl c₂.p)
|
||||
reflBoolTrue (← c₁.toExprProof) (← c₂.toExprProof)
|
||||
eagerReflBoolTrue (← c₁.toExprProof) (← c₂.toExprProof)
|
||||
| .reorder c => withUnordered <| c.toExprProof
|
||||
| .commRingNorm c e p =>
|
||||
let h := mkApp4 (mkConst ``Grind.CommRing.norm_int) (← getRingContext) (← mkRingExprDecl e) (← mkRingPolyDecl p) reflBoolTrue
|
||||
let h := mkApp4 (mkConst ``Grind.CommRing.norm_int) (← getRingContext) (← mkRingExprDecl e) (← mkRingPolyDecl p) eagerReflBoolTrue
|
||||
return mkApp5 (mkConst ``Int.Linear.eq_norm_poly) (← getContext) (← mkPolyDecl c.p) (← mkPolyDecl c'.p) h (← c.toExprProof)
|
||||
| .defnCommRing e p re rp p' =>
|
||||
let h := mkApp4 (mkConst ``Grind.CommRing.norm_int) (← getRingContext) (← mkRingExprDecl re) (← mkRingPolyDecl rp) reflBoolTrue
|
||||
let h := mkApp4 (mkConst ``Grind.CommRing.norm_int) (← getRingContext) (← mkRingExprDecl re) (← mkRingPolyDecl rp) eagerReflBoolTrue
|
||||
let some x := (← getVarMap).find? { expr := e } | throwError "`grind` internal error, missing cutsat variable{indentExpr e}"
|
||||
return mkApp8 (mkConst ``Int.Linear.eq_def_norm) (← getContext)
|
||||
(toExpr x) (← mkPolyDecl p) (← mkPolyDecl p') (← mkPolyDecl c'.p)
|
||||
reflBoolTrue (← mkEqRefl e) h
|
||||
eagerReflBoolTrue (← mkEqRefl e) h
|
||||
| .defnNatCommRing h₁ x e' p re rp p' =>
|
||||
let h₂ := mkApp4 (mkConst ``Grind.CommRing.norm_int) (← getRingContext) (← mkRingExprDecl re) (← mkRingPolyDecl rp) reflBoolTrue
|
||||
let h₂ := mkApp4 (mkConst ``Grind.CommRing.norm_int) (← getRingContext) (← mkRingExprDecl re) (← mkRingPolyDecl rp) eagerReflBoolTrue
|
||||
return mkApp9 (mkConst ``Int.Linear.eq_def'_norm) (← getContext) (toExpr x) (← mkExprDecl e')
|
||||
(← mkPolyDecl p) (← mkPolyDecl p') (← mkPolyDecl c'.p) reflBoolTrue h₁ h₂
|
||||
(← mkPolyDecl p) (← mkPolyDecl p') (← mkPolyDecl c'.p) eagerReflBoolTrue h₁ h₂
|
||||
|
||||
partial def DvdCnstr.toExprProof (c' : DvdCnstr) : ProofM Expr := caching c' do
|
||||
trace[grind.debug.cutsat.proof] "{← c'.pp}"
|
||||
@@ -195,15 +195,15 @@ partial def DvdCnstr.toExprProof (c' : DvdCnstr) : ProofM Expr := caching c' do
|
||||
mkOfEqTrue (← mkEqTrueProof e)
|
||||
| .coreOfNat e thm d a' =>
|
||||
let h := mkApp thm (← mkOfEqTrue (← mkEqTrueProof e))
|
||||
return mkApp6 (mkConst ``Int.Linear.dvd_norm_expr) (← getContext) (toExpr (Int.ofNat d)) (← mkExprDecl a') (← mkPolyDecl c'.p) reflBoolTrue h
|
||||
return mkApp6 (mkConst ``Int.Linear.dvd_norm_expr) (← getContext) (toExpr (Int.ofNat d)) (← mkExprDecl a') (← mkPolyDecl c'.p) eagerReflBoolTrue h
|
||||
| .norm c =>
|
||||
return mkApp6 (mkConst ``Int.Linear.dvd_norm) (← getContext) (toExpr c.d) (← mkPolyDecl c.p) (← mkPolyDecl c'.p) reflBoolTrue (← c.toExprProof)
|
||||
return mkApp6 (mkConst ``Int.Linear.dvd_norm) (← getContext) (toExpr c.d) (← mkPolyDecl c.p) (← mkPolyDecl c'.p) eagerReflBoolTrue (← c.toExprProof)
|
||||
| .elim c =>
|
||||
return mkApp7 (mkConst ``Int.Linear.dvd_elim) (← getContext) (toExpr c.d) (← mkPolyDecl c.p) (toExpr c'.d) (← mkPolyDecl c'.p) reflBoolTrue (← c.toExprProof)
|
||||
return mkApp7 (mkConst ``Int.Linear.dvd_elim) (← getContext) (toExpr c.d) (← mkPolyDecl c.p) (toExpr c'.d) (← mkPolyDecl c'.p) eagerReflBoolTrue (← c.toExprProof)
|
||||
| .divCoeffs c =>
|
||||
let g := c.p.gcdCoeffs c.d
|
||||
let g := if c.d < 0 then -g else g
|
||||
return mkApp8 (mkConst ``Int.Linear.dvd_coeff) (← getContext) (toExpr c.d) (← mkPolyDecl c.p) (toExpr c'.d) (← mkPolyDecl c'.p) (toExpr g) reflBoolTrue (← c.toExprProof)
|
||||
return mkApp8 (mkConst ``Int.Linear.dvd_coeff) (← getContext) (toExpr c.d) (← mkPolyDecl c.p) (toExpr c'.d) (← mkPolyDecl c'.p) (toExpr g) eagerReflBoolTrue (← c.toExprProof)
|
||||
| .solveCombine c₁ c₂ =>
|
||||
let (d₁, a₁) ← c₁.get_d_a
|
||||
let (d₂, a₂) ← c₂.get_d_a
|
||||
@@ -211,19 +211,19 @@ partial def DvdCnstr.toExprProof (c' : DvdCnstr) : ProofM Expr := caching c' do
|
||||
let r := mkApp10 (mkConst ``Int.Linear.dvd_solve_combine)
|
||||
(← getContext) (toExpr c₁.d) (← mkPolyDecl c₁.p) (toExpr c₂.d) (← mkPolyDecl c₂.p) (toExpr c'.d) (← mkPolyDecl c'.p)
|
||||
(toExpr g) (toExpr α) (toExpr β)
|
||||
return mkApp3 r reflBoolTrue (← c₁.toExprProof) (← c₂.toExprProof)
|
||||
return mkApp3 r eagerReflBoolTrue (← c₁.toExprProof) (← c₂.toExprProof)
|
||||
| .solveElim c₁ c₂ =>
|
||||
return mkApp10 (mkConst ``Int.Linear.dvd_solve_elim)
|
||||
(← getContext) (toExpr c₁.d) (← mkPolyDecl c₁.p) (toExpr c₂.d) (← mkPolyDecl c₂.p) (toExpr c'.d) (← mkPolyDecl c'.p)
|
||||
reflBoolTrue (← c₁.toExprProof) (← c₂.toExprProof)
|
||||
eagerReflBoolTrue (← c₁.toExprProof) (← c₂.toExprProof)
|
||||
| .ofEq x c =>
|
||||
return mkApp7 (mkConst ``Int.Linear.dvd_of_eq)
|
||||
(← getContext) (toExpr x) (← mkPolyDecl c.p) (toExpr c'.d) (← mkPolyDecl c'.p)
|
||||
reflBoolTrue (← c.toExprProof)
|
||||
eagerReflBoolTrue (← c.toExprProof)
|
||||
| .subst x c₁ c₂ =>
|
||||
return mkApp10 (mkConst ``Int.Linear.eq_dvd_subst)
|
||||
(← getContext) (toExpr x) (← mkPolyDecl c₁.p) (toExpr c₂.d) (← mkPolyDecl c₂.p) (toExpr c'.d) (← mkPolyDecl c'.p)
|
||||
reflBoolTrue (← c₁.toExprProof) (← c₂.toExprProof)
|
||||
eagerReflBoolTrue (← c₁.toExprProof) (← c₂.toExprProof)
|
||||
| .cooper₁ s =>
|
||||
let { c₁, c₂, c₃?, left } := s.pred
|
||||
let p₁ := c₁.p
|
||||
@@ -232,12 +232,12 @@ partial def DvdCnstr.toExprProof (c' : DvdCnstr) : ProofM Expr := caching c' do
|
||||
| none =>
|
||||
let thmName := if left then ``Int.Linear.cooper_left_split_dvd else ``Int.Linear.cooper_right_split_dvd
|
||||
return mkApp8 (mkConst thmName)
|
||||
(← getContext) (← mkPolyDecl p₁) (← mkPolyDecl p₂) (toExpr s.k) (toExpr c'.d) (← mkPolyDecl c'.p) (← s.toExprProof) reflBoolTrue
|
||||
(← getContext) (← mkPolyDecl p₁) (← mkPolyDecl p₂) (toExpr s.k) (toExpr c'.d) (← mkPolyDecl c'.p) (← s.toExprProof) eagerReflBoolTrue
|
||||
| some c₃ =>
|
||||
let thmName := if left then ``Int.Linear.cooper_dvd_left_split_dvd1 else ``Int.Linear.cooper_dvd_right_split_dvd1
|
||||
return mkApp10 (mkConst thmName)
|
||||
(← getContext) (← mkPolyDecl p₁) (← mkPolyDecl p₂) (← mkPolyDecl c₃.p) (toExpr c₃.d) (toExpr s.k) (toExpr c'.d) (← mkPolyDecl c'.p)
|
||||
(← s.toExprProof) reflBoolTrue
|
||||
(← s.toExprProof) eagerReflBoolTrue
|
||||
| .cooper₂ s =>
|
||||
let { c₁, c₂, c₃?, left } := s.pred
|
||||
let p₁ := c₁.p
|
||||
@@ -246,10 +246,10 @@ partial def DvdCnstr.toExprProof (c' : DvdCnstr) : ProofM Expr := caching c' do
|
||||
let thmName := if left then ``Int.Linear.cooper_dvd_left_split_dvd2 else ``Int.Linear.cooper_dvd_right_split_dvd2
|
||||
return mkApp10 (mkConst thmName)
|
||||
(← getContext) (← mkPolyDecl p₁) (← mkPolyDecl p₂) (← mkPolyDecl c₃.p) (toExpr c₃.d) (toExpr s.k) (toExpr c'.d) (← mkPolyDecl c'.p)
|
||||
(← s.toExprProof) reflBoolTrue
|
||||
(← s.toExprProof) eagerReflBoolTrue
|
||||
| .reorder c => withUnordered <| c.toExprProof
|
||||
| .commRingNorm c e p =>
|
||||
let h := mkApp4 (mkConst ``Grind.CommRing.norm_int) (← getRingContext) (← mkRingExprDecl e) (← mkRingPolyDecl p) reflBoolTrue
|
||||
let h := mkApp4 (mkConst ``Grind.CommRing.norm_int) (← getRingContext) (← mkRingExprDecl e) (← mkRingPolyDecl p) eagerReflBoolTrue
|
||||
return mkApp6 (mkConst ``Int.Linear.dvd_norm_poly) (← getContext) (toExpr c.d) (← mkPolyDecl c.p) (← mkPolyDecl c'.p) h (← c.toExprProof)
|
||||
|
||||
partial def LeCnstr.toExprProof (c' : LeCnstr) : ProofM Expr := caching c' do
|
||||
@@ -259,30 +259,30 @@ partial def LeCnstr.toExprProof (c' : LeCnstr) : ProofM Expr := caching c' do
|
||||
mkOfEqTrue (← mkEqTrueProof e)
|
||||
| .coreNeg e p =>
|
||||
let h ← mkOfEqFalse (← mkEqFalseProof e)
|
||||
return mkApp5 (mkConst ``Int.Linear.le_neg) (← getContext) (← mkPolyDecl p) (← mkPolyDecl c'.p) reflBoolTrue h
|
||||
return mkApp5 (mkConst ``Int.Linear.le_neg) (← getContext) (← mkPolyDecl p) (← mkPolyDecl c'.p) eagerReflBoolTrue h
|
||||
| .coreToInt e pos toIntThm lhs rhs =>
|
||||
let h ← if pos then pure <| mkOfEqTrueCore e (← mkEqTrueProof e) else pure <| mkOfEqFalseCore e (← mkEqFalseProof e)
|
||||
let h := mkApp toIntThm h
|
||||
return mkApp6 (mkConst ``Int.Linear.le_norm_expr) (← getContext) (← mkExprDecl lhs) (← mkExprDecl rhs) (← mkPolyDecl c'.p) reflBoolTrue h
|
||||
return mkApp6 (mkConst ``Int.Linear.le_norm_expr) (← getContext) (← mkExprDecl lhs) (← mkExprDecl rhs) (← mkPolyDecl c'.p) eagerReflBoolTrue h
|
||||
| .ofNatNonneg a =>
|
||||
return mkApp (mkConst ``Nat.ToInt.toNat_nonneg) a
|
||||
| .bound h => return h
|
||||
| .dec h =>
|
||||
return mkFVar h
|
||||
| .norm c =>
|
||||
return mkApp5 (mkConst ``Int.Linear.le_norm) (← getContext) (← mkPolyDecl c.p) (← mkPolyDecl c'.p) reflBoolTrue (← c.toExprProof)
|
||||
return mkApp5 (mkConst ``Int.Linear.le_norm) (← getContext) (← mkPolyDecl c.p) (← mkPolyDecl c'.p) eagerReflBoolTrue (← c.toExprProof)
|
||||
| .divCoeffs c =>
|
||||
let k := c.p.gcdCoeffs'
|
||||
return mkApp6 (mkConst ``Int.Linear.le_coeff) (← getContext) (← mkPolyDecl c.p) (← mkPolyDecl c'.p) (toExpr (Int.ofNat k)) reflBoolTrue (← c.toExprProof)
|
||||
return mkApp6 (mkConst ``Int.Linear.le_coeff) (← getContext) (← mkPolyDecl c.p) (← mkPolyDecl c'.p) (toExpr (Int.ofNat k)) eagerReflBoolTrue (← c.toExprProof)
|
||||
| .combine c₁ c₂ =>
|
||||
return mkApp7 (mkConst ``Int.Linear.le_combine)
|
||||
(← getContext) (← mkPolyDecl c₁.p) (← mkPolyDecl c₂.p) (← mkPolyDecl c'.p)
|
||||
reflBoolTrue
|
||||
eagerReflBoolTrue
|
||||
(← c₁.toExprProof) (← c₂.toExprProof)
|
||||
| .combineDivCoeffs c₁ c₂ k =>
|
||||
return mkApp8 (mkConst ``Int.Linear.le_combine_coeff)
|
||||
(← getContext) (← mkPolyDecl c₁.p) (← mkPolyDecl c₂.p) (← mkPolyDecl c'.p) (toExpr k)
|
||||
reflBoolTrue
|
||||
eagerReflBoolTrue
|
||||
(← c₁.toExprProof) (← c₂.toExprProof)
|
||||
| .subst x c₁ c₂ =>
|
||||
let a := c₁.p.coeff x
|
||||
@@ -292,26 +292,26 @@ partial def LeCnstr.toExprProof (c' : LeCnstr) : ProofM Expr := caching c' do
|
||||
mkConst ``Int.Linear.eq_le_subst_nonpos
|
||||
return mkApp8 thm
|
||||
(← getContext) (toExpr x) (← mkPolyDecl c₁.p) (← mkPolyDecl c₂.p) (← mkPolyDecl c'.p)
|
||||
reflBoolTrue
|
||||
eagerReflBoolTrue
|
||||
(← c₁.toExprProof) (← c₂.toExprProof)
|
||||
| .ofLeDiseq c₁ c₂ =>
|
||||
return mkApp7 (mkConst ``Int.Linear.le_of_le_diseq)
|
||||
(← getContext) (← mkPolyDecl c₁.p) (← mkPolyDecl c₂.p) (← mkPolyDecl c'.p)
|
||||
reflBoolTrue (← c₁.toExprProof) (← c₂.toExprProof)
|
||||
eagerReflBoolTrue (← c₁.toExprProof) (← c₂.toExprProof)
|
||||
| .dvdTight c₁ c₂ =>
|
||||
return mkApp8 (mkConst ``Int.Linear.dvd_le_tight)
|
||||
(← getContext) (toExpr c₁.d) (← mkPolyDecl c₁.p) (← mkPolyDecl c₂.p) (← mkPolyDecl c'.p)
|
||||
reflBoolTrue (← c₁.toExprProof) (← c₂.toExprProof)
|
||||
eagerReflBoolTrue (← c₁.toExprProof) (← c₂.toExprProof)
|
||||
| .negDvdTight c₁ c₂ =>
|
||||
return mkApp8 (mkConst ``Int.Linear.dvd_neg_le_tight)
|
||||
(← getContext) (toExpr c₁.d) (← mkPolyDecl c₁.p) (← mkPolyDecl c₂.p) (← mkPolyDecl c'.p)
|
||||
reflBoolTrue (← c₁.toExprProof) (← c₂.toExprProof)
|
||||
eagerReflBoolTrue (← c₁.toExprProof) (← c₂.toExprProof)
|
||||
| .ofDiseqSplit c₁ fvarId h _ =>
|
||||
let p₂ := c₁.p.addConst 1
|
||||
let hFalse ← h.toExprProofCore
|
||||
let hNot := mkLambda `h .default (mkIntLE (← p₂.denoteExpr') (mkIntLit 0)) (hFalse.abstract #[mkFVar fvarId])
|
||||
return mkApp7 (mkConst ``Int.Linear.diseq_split_resolve)
|
||||
(← getContext) (← mkPolyDecl c₁.p) (← mkPolyDecl p₂) (← mkPolyDecl c'.p) reflBoolTrue (← c₁.toExprProof) hNot
|
||||
(← getContext) (← mkPolyDecl c₁.p) (← mkPolyDecl p₂) (← mkPolyDecl c'.p) eagerReflBoolTrue (← c₁.toExprProof) hNot
|
||||
| .cooper s =>
|
||||
let { c₁, c₂, c₃?, left } := s.pred
|
||||
let p₁ := c₁.p
|
||||
@@ -321,14 +321,14 @@ partial def LeCnstr.toExprProof (c' : LeCnstr) : ProofM Expr := caching c' do
|
||||
| none =>
|
||||
let thmName := if left then ``Int.Linear.cooper_left_split_ineq else ``Int.Linear.cooper_right_split_ineq
|
||||
return mkApp8 (mkConst thmName)
|
||||
(← getContext) (← mkPolyDecl p₁) (← mkPolyDecl p₂) (toExpr s.k) (toExpr coeff) (← mkPolyDecl c'.p) (← s.toExprProof) reflBoolTrue
|
||||
(← getContext) (← mkPolyDecl p₁) (← mkPolyDecl p₂) (toExpr s.k) (toExpr coeff) (← mkPolyDecl c'.p) (← s.toExprProof) eagerReflBoolTrue
|
||||
| some c₃ =>
|
||||
let thmName := if left then ``Int.Linear.cooper_dvd_left_split_ineq else ``Int.Linear.cooper_dvd_right_split_ineq
|
||||
return mkApp10 (mkConst thmName)
|
||||
(← getContext) (← mkPolyDecl p₁) (← mkPolyDecl p₂) (← mkPolyDecl c₃.p) (toExpr c₃.d) (toExpr s.k) (toExpr coeff) (← mkPolyDecl c'.p) (← s.toExprProof) reflBoolTrue
|
||||
(← getContext) (← mkPolyDecl p₁) (← mkPolyDecl p₂) (← mkPolyDecl c₃.p) (toExpr c₃.d) (toExpr s.k) (toExpr coeff) (← mkPolyDecl c'.p) (← s.toExprProof) eagerReflBoolTrue
|
||||
| .reorder c => withUnordered <| c.toExprProof
|
||||
| .commRingNorm c e p =>
|
||||
let h := mkApp4 (mkConst ``Grind.CommRing.norm_int) (← getRingContext) (← mkRingExprDecl e) (← mkRingPolyDecl p) reflBoolTrue
|
||||
let h := mkApp4 (mkConst ``Grind.CommRing.norm_int) (← getRingContext) (← mkRingExprDecl e) (← mkRingPolyDecl p) eagerReflBoolTrue
|
||||
return mkApp5 (mkConst ``Int.Linear.le_norm_poly) (← getContext) (← mkPolyDecl c.p) (← mkPolyDecl c'.p) h (← c.toExprProof)
|
||||
|
||||
partial def DiseqCnstr.toExprProof (c' : DiseqCnstr) : ProofM Expr := caching c' do
|
||||
@@ -337,24 +337,24 @@ partial def DiseqCnstr.toExprProof (c' : DiseqCnstr) : ProofM Expr := caching c'
|
||||
mkDiseqProof a zero
|
||||
| .core a b p₁ p₂ =>
|
||||
let h ← mkDiseqProof a b
|
||||
return mkApp6 (mkConst ``Int.Linear.diseq_of_core) (← getContext) (← mkPolyDecl p₁) (← mkPolyDecl p₂) (← mkPolyDecl c'.p) reflBoolTrue h
|
||||
return mkApp6 (mkConst ``Int.Linear.diseq_of_core) (← getContext) (← mkPolyDecl p₁) (← mkPolyDecl p₂) (← mkPolyDecl c'.p) eagerReflBoolTrue h
|
||||
| .coreToInt a b toIntThm lhs rhs =>
|
||||
let h := mkApp toIntThm (← mkDiseqProof a b)
|
||||
return mkApp6 (mkConst ``Int.Linear.not_eq_norm_expr) (← getContext) (← mkExprDecl lhs) (← mkExprDecl rhs) (← mkPolyDecl c'.p) reflBoolTrue h
|
||||
return mkApp6 (mkConst ``Int.Linear.not_eq_norm_expr) (← getContext) (← mkExprDecl lhs) (← mkExprDecl rhs) (← mkPolyDecl c'.p) eagerReflBoolTrue h
|
||||
| .norm c =>
|
||||
return mkApp5 (mkConst ``Int.Linear.diseq_norm) (← getContext) (← mkPolyDecl c.p) (← mkPolyDecl c'.p) reflBoolTrue (← c.toExprProof)
|
||||
return mkApp5 (mkConst ``Int.Linear.diseq_norm) (← getContext) (← mkPolyDecl c.p) (← mkPolyDecl c'.p) eagerReflBoolTrue (← c.toExprProof)
|
||||
| .divCoeffs c =>
|
||||
let k := c.p.gcdCoeffs c.p.getConst
|
||||
return mkApp6 (mkConst ``Int.Linear.diseq_coeff) (← getContext) (← mkPolyDecl c.p) (← mkPolyDecl c'.p) (toExpr k) reflBoolTrue (← c.toExprProof)
|
||||
return mkApp6 (mkConst ``Int.Linear.diseq_coeff) (← getContext) (← mkPolyDecl c.p) (← mkPolyDecl c'.p) (toExpr k) eagerReflBoolTrue (← c.toExprProof)
|
||||
| .neg c =>
|
||||
return mkApp5 (mkConst ``Int.Linear.diseq_neg) (← getContext) (← mkPolyDecl c.p) (← mkPolyDecl c'.p) reflBoolTrue (← c.toExprProof)
|
||||
return mkApp5 (mkConst ``Int.Linear.diseq_neg) (← getContext) (← mkPolyDecl c.p) (← mkPolyDecl c'.p) eagerReflBoolTrue (← c.toExprProof)
|
||||
| .subst x c₁ c₂ =>
|
||||
return mkApp8 (mkConst ``Int.Linear.eq_diseq_subst)
|
||||
(← getContext) (toExpr x) (← mkPolyDecl c₁.p) (← mkPolyDecl c₂.p) (← mkPolyDecl c'.p)
|
||||
reflBoolTrue (← c₁.toExprProof) (← c₂.toExprProof)
|
||||
eagerReflBoolTrue (← c₁.toExprProof) (← c₂.toExprProof)
|
||||
| .reorder c => withUnordered <| c.toExprProof
|
||||
| .commRingNorm c e p =>
|
||||
let h := mkApp4 (mkConst ``Grind.CommRing.norm_int) (← getRingContext) (← mkRingExprDecl e) (← mkRingPolyDecl p) reflBoolTrue
|
||||
let h := mkApp4 (mkConst ``Grind.CommRing.norm_int) (← getRingContext) (← mkRingExprDecl e) (← mkRingPolyDecl p) eagerReflBoolTrue
|
||||
return mkApp5 (mkConst ``Int.Linear.diseq_norm_poly) (← getContext) (← mkPolyDecl c.p) (← mkPolyDecl c'.p) h (← c.toExprProof)
|
||||
|
||||
partial def CooperSplit.toExprProof (s : CooperSplit) : ProofM Expr := caching s do
|
||||
@@ -372,14 +372,14 @@ partial def CooperSplit.toExprProof (s : CooperSplit) : ProofM Expr := caching s
|
||||
let thmName := if left then ``Int.Linear.cooper_left else ``Int.Linear.cooper_right
|
||||
let predName := if left then ``Int.Linear.cooper_left_split else ``Int.Linear.cooper_right_split
|
||||
let base := mkApp7 (mkConst thmName) (← getContext) (← mkPolyDecl p₁) (← mkPolyDecl p₂) (toExpr n)
|
||||
reflBoolTrue (← c₁.toExprProof) (← c₂.toExprProof)
|
||||
eagerReflBoolTrue (← c₁.toExprProof) (← c₂.toExprProof)
|
||||
let pred := mkApp3 (mkConst predName) (← getContext) (← mkPolyDecl p₁) (← mkPolyDecl p₂)
|
||||
pure (base, pred)
|
||||
| some c₃ =>
|
||||
let thmName := if left then ``Int.Linear.cooper_dvd_left else ``Int.Linear.cooper_dvd_right
|
||||
let predName := if left then ``Int.Linear.cooper_dvd_left_split else ``Int.Linear.cooper_dvd_right_split
|
||||
let base := mkApp10 (mkConst thmName) (← getContext) (← mkPolyDecl p₁) (← mkPolyDecl p₂) (← mkPolyDecl c₃.p) (toExpr c₃.d) (toExpr n)
|
||||
reflBoolTrue (← c₁.toExprProof) (← c₂.toExprProof) (← c₃.toExprProof)
|
||||
eagerReflBoolTrue (← c₁.toExprProof) (← c₂.toExprProof) (← c₃.toExprProof)
|
||||
let pred := mkApp5 (mkConst predName) (← getContext) (← mkPolyDecl p₁) (← mkPolyDecl p₂) (← mkPolyDecl c₃.p) (toExpr c₃.d)
|
||||
pure (base, pred)
|
||||
-- `pred` is an expressions of the form `cooper_*_split ...` with type `Nat → Prop`
|
||||
@@ -399,23 +399,23 @@ partial def CooperSplit.toExprProof (s : CooperSplit) : ProofM Expr := caching s
|
||||
partial def UnsatProof.toExprProofCore (h : UnsatProof) : ProofM Expr := do
|
||||
match h with
|
||||
| .le c =>
|
||||
return mkApp4 (mkConst ``Int.Linear.le_unsat) (← getContext) (← mkPolyDecl c.p) reflBoolTrue (← c.toExprProof)
|
||||
return mkApp4 (mkConst ``Int.Linear.le_unsat) (← getContext) (← mkPolyDecl c.p) eagerReflBoolTrue (← c.toExprProof)
|
||||
| .dvd c =>
|
||||
return mkApp5 (mkConst ``Int.Linear.dvd_unsat) (← getContext) (toExpr c.d) (← mkPolyDecl c.p) reflBoolTrue (← c.toExprProof)
|
||||
return mkApp5 (mkConst ``Int.Linear.dvd_unsat) (← getContext) (toExpr c.d) (← mkPolyDecl c.p) eagerReflBoolTrue (← c.toExprProof)
|
||||
| .eq c =>
|
||||
if c.p.isUnsatEq then
|
||||
return mkApp4 (mkConst ``Int.Linear.eq_unsat) (← getContext) (← mkPolyDecl c.p) reflBoolTrue (← c.toExprProof)
|
||||
return mkApp4 (mkConst ``Int.Linear.eq_unsat) (← getContext) (← mkPolyDecl c.p) eagerReflBoolTrue (← c.toExprProof)
|
||||
else
|
||||
let k := c.p.gcdCoeffs'
|
||||
return mkApp5 (mkConst ``Int.Linear.eq_unsat_coeff) (← getContext) (← mkPolyDecl c.p) (toExpr (Int.ofNat k)) reflBoolTrue (← c.toExprProof)
|
||||
return mkApp5 (mkConst ``Int.Linear.eq_unsat_coeff) (← getContext) (← mkPolyDecl c.p) (toExpr (Int.ofNat k)) eagerReflBoolTrue (← c.toExprProof)
|
||||
| .diseq c =>
|
||||
return mkApp4 (mkConst ``Int.Linear.diseq_unsat) (← getContext) (← mkPolyDecl c.p) reflBoolTrue (← c.toExprProof)
|
||||
return mkApp4 (mkConst ``Int.Linear.diseq_unsat) (← getContext) (← mkPolyDecl c.p) eagerReflBoolTrue (← c.toExprProof)
|
||||
| .cooper c₁ c₂ c₃ =>
|
||||
let .add c _ _ := c₃.p | c₃.throwUnexpected
|
||||
let d := c₃.d
|
||||
let (_, α, β) := gcdExt c d
|
||||
let h := mkApp7 (mkConst ``Int.Linear.cooper_unsat) (← getContext) (← mkPolyDecl c₁.p) (← mkPolyDecl c₂.p) (← mkPolyDecl c₃.p) (toExpr c₃.d) (toExpr α) (toExpr β)
|
||||
return mkApp4 h reflBoolTrue (← c₁.toExprProof) (← c₂.toExprProof) (← c₃.toExprProof)
|
||||
return mkApp4 h eagerReflBoolTrue (← c₁.toExprProof) (← c₂.toExprProof) (← c₃.toExprProof)
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -63,19 +63,19 @@ where
|
||||
let toInt := mkApp3 (mkConst ``Grind.ToInt.toInt [u]) type rangeExpr toIntInst
|
||||
let wrap := mkApp (mkConst ``Grind.IntInterval.wrap) rangeExpr
|
||||
let ofWrap0? := if let .co 0 hi := range then
|
||||
some <| mkApp3 (mkConst ``Grind.ToInt.of_eq_wrap_co_0) rangeExpr (toExpr hi) reflBoolTrue
|
||||
some <| mkApp3 (mkConst ``Grind.ToInt.of_eq_wrap_co_0) rangeExpr (toExpr hi) eagerReflBoolTrue
|
||||
else
|
||||
none
|
||||
let ofEq := mkApp3 (mkConst ``Grind.ToInt.of_eq [u]) type rangeExpr toIntInst
|
||||
let ofDiseq := mkApp3 (mkConst ``Grind.ToInt.of_diseq [u]) type rangeExpr toIntInst
|
||||
let lowerThm? := if let some lo := range.lo? then
|
||||
if lo == 0 then
|
||||
some <| mkApp4 (mkConst ``Grind.ToInt.ge_lower0 [u]) type rangeExpr toIntInst reflBoolTrue
|
||||
some <| mkApp4 (mkConst ``Grind.ToInt.ge_lower0 [u]) type rangeExpr toIntInst eagerReflBoolTrue
|
||||
else
|
||||
some <| mkApp5 (mkConst ``Grind.ToInt.ge_lower [u]) type rangeExpr toIntInst (toExpr lo) reflBoolTrue
|
||||
some <| mkApp5 (mkConst ``Grind.ToInt.ge_lower [u]) type rangeExpr toIntInst (toExpr lo) eagerReflBoolTrue
|
||||
else none
|
||||
let upperThm? := if let some hi := range.hi? then
|
||||
some <| mkApp5 (mkConst ``Grind.ToInt.le_upper [u]) type rangeExpr toIntInst (toExpr (-hi + 1)) reflBoolTrue
|
||||
some <| mkApp5 (mkConst ``Grind.ToInt.le_upper [u]) type rangeExpr toIntInst (toExpr (-hi + 1)) eagerReflBoolTrue
|
||||
else none
|
||||
trace[grind.debug.cutsat.toInt] "registered toInt: {type}"
|
||||
let id := (← get').toIntInfos.size
|
||||
@@ -187,15 +187,15 @@ private def mkBinOpThms (opBaseName : Name) (thmName : Name) : ToIntM ToIntThms
|
||||
let cwrName := thmName ++ `wr
|
||||
let info ← getInfo
|
||||
let c_ww? := if info.range.isFinite && env.contains cwwName then
|
||||
some <| mkApp6 (mkConst cwwName [info.u]) info.type info.rangeExpr info.toIntInst opInst toIntOpInst reflBoolTrue
|
||||
some <| mkApp6 (mkConst cwwName [info.u]) info.type info.rangeExpr info.toIntInst opInst toIntOpInst eagerReflBoolTrue
|
||||
else
|
||||
none
|
||||
let c_wl? := if info.range.isFinite && info.range.nonEmpty && env.contains cwwName then
|
||||
some <| mkApp7 (mkConst cwlName [info.u]) info.type info.rangeExpr info.toIntInst opInst toIntOpInst reflBoolTrue reflBoolTrue
|
||||
let c_wl? := if info.range.isFinite && info.range.nonEmpty && env.contains cwwName then -- TODO: nonEmpty may be unknown if symbolic bounds
|
||||
some <| mkApp7 (mkConst cwlName [info.u]) info.type info.rangeExpr info.toIntInst opInst toIntOpInst eagerReflBoolTrue eagerReflBoolTrue
|
||||
else
|
||||
none
|
||||
let c_wr? := if info.range.isFinite && info.range.nonEmpty && env.contains cwwName then
|
||||
some <| mkApp7 (mkConst cwrName [info.u]) info.type info.rangeExpr info.toIntInst opInst toIntOpInst reflBoolTrue reflBoolTrue
|
||||
let c_wr? := if info.range.isFinite && info.range.nonEmpty && env.contains cwwName then -- TODO: nonEmpty may be unknown if symbolic bounds
|
||||
some <| mkApp7 (mkConst cwrName [info.u]) info.type info.rangeExpr info.toIntInst opInst toIntOpInst eagerReflBoolTrue eagerReflBoolTrue
|
||||
else
|
||||
none
|
||||
return { c? := some c, c_ww?, c_wl?, c_wr? }
|
||||
|
||||
@@ -192,20 +192,20 @@ partial def IneqCnstr.toExprProof (c' : IneqCnstr) : ProofM Expr := caching c' d
|
||||
match c'.h with
|
||||
| .core e lhs rhs =>
|
||||
let h ← mkIntModPreOrdThmPrefix (if c'.strict then ``Grind.Linarith.lt_norm else ``Grind.Linarith.le_norm)
|
||||
return mkApp5 h (← mkExprDecl lhs) (← mkExprDecl rhs) (← mkPolyDecl c'.p) reflBoolTrue (mkOfEqTrueCore e (← mkEqTrueProof e))
|
||||
return mkApp5 h (← mkExprDecl lhs) (← mkExprDecl rhs) (← mkPolyDecl c'.p) eagerReflBoolTrue (mkOfEqTrueCore e (← mkEqTrueProof e))
|
||||
| .notCore e lhs rhs =>
|
||||
let h ← mkIntModLinOrdThmPrefix (if c'.strict then ``Grind.Linarith.not_le_norm else ``Grind.Linarith.not_lt_norm)
|
||||
return mkApp5 h (← mkExprDecl lhs) (← mkExprDecl rhs) (← mkPolyDecl c'.p) reflBoolTrue (mkOfEqFalseCore e (← mkEqFalseProof e))
|
||||
return mkApp5 h (← mkExprDecl lhs) (← mkExprDecl rhs) (← mkPolyDecl c'.p) eagerReflBoolTrue (mkOfEqFalseCore e (← mkEqFalseProof e))
|
||||
| .coreCommRing e lhs rhs p' lhs' =>
|
||||
let h' ← mkCommRingPreOrdThmPrefix (if c'.strict then ``Grind.CommRing.lt_norm else ``Grind.CommRing.le_norm)
|
||||
let h' := mkApp5 h' (← mkRingExprDecl lhs) (← mkRingExprDecl rhs) (← mkRingPolyDecl p') reflBoolTrue (mkOfEqTrueCore e (← mkEqTrueProof e))
|
||||
let h' := mkApp5 h' (← mkRingExprDecl lhs) (← mkRingExprDecl rhs) (← mkRingPolyDecl p') eagerReflBoolTrue (mkOfEqTrueCore e (← mkEqTrueProof e))
|
||||
let h ← mkIntModPreOrdThmPrefix (if c'.strict then ``Grind.Linarith.lt_norm else ``Grind.Linarith.le_norm)
|
||||
return mkApp5 h (← mkExprDecl lhs') (← mkExprDecl .zero) (← mkPolyDecl c'.p) reflBoolTrue h'
|
||||
return mkApp5 h (← mkExprDecl lhs') (← mkExprDecl .zero) (← mkPolyDecl c'.p) eagerReflBoolTrue h'
|
||||
| .notCoreCommRing e lhs rhs p' lhs' =>
|
||||
let h' ← mkCommRingLinOrdThmPrefix (if c'.strict then ``Grind.CommRing.not_le_norm else ``Grind.CommRing.not_lt_norm)
|
||||
let h' := mkApp5 h' (← mkRingExprDecl lhs) (← mkRingExprDecl rhs) (← mkRingPolyDecl p') reflBoolTrue (mkOfEqFalseCore e (← mkEqFalseProof e))
|
||||
let h' := mkApp5 h' (← mkRingExprDecl lhs) (← mkRingExprDecl rhs) (← mkRingPolyDecl p') eagerReflBoolTrue (mkOfEqFalseCore e (← mkEqFalseProof e))
|
||||
let h ← mkIntModPreOrdThmPrefix (if c'.strict then ``Grind.Linarith.lt_norm else ``Grind.Linarith.le_norm)
|
||||
return mkApp5 h (← mkExprDecl lhs') (← mkExprDecl .zero) (← mkPolyDecl c'.p) reflBoolTrue h'
|
||||
return mkApp5 h (← mkExprDecl lhs') (← mkExprDecl .zero) (← mkPolyDecl c'.p) eagerReflBoolTrue h'
|
||||
| .combine c₁ c₂ =>
|
||||
let (declName, c₁, c₂) :=
|
||||
match c₁.strict, c₂.strict with
|
||||
@@ -213,49 +213,49 @@ partial def IneqCnstr.toExprProof (c' : IneqCnstr) : ProofM Expr := caching c' d
|
||||
| true, false => (``Grind.Linarith.le_lt_combine, c₂, c₁)
|
||||
| false, true => (``Grind.Linarith.le_lt_combine, c₁, c₂)
|
||||
| false, false => (``Grind.Linarith.le_le_combine, c₁, c₂)
|
||||
return mkApp6 (← mkIntModPreOrdThmPrefix declName) (← mkPolyDecl c₁.p) (← mkPolyDecl c₂.p) (← mkPolyDecl c'.p) reflBoolTrue
|
||||
return mkApp6 (← mkIntModPreOrdThmPrefix declName) (← mkPolyDecl c₁.p) (← mkPolyDecl c₂.p) (← mkPolyDecl c'.p) eagerReflBoolTrue
|
||||
(← c₁.toExprProof) (← c₂.toExprProof)
|
||||
| .oneGtZero =>
|
||||
let s ← getStruct
|
||||
let h := mkApp5 (mkConst ``Grind.Linarith.zero_lt_one [s.u]) s.type (← getRingInst) (← getPreorderInst) (← getOrderedRingInst) (← getContext)
|
||||
return mkApp3 h (← mkPolyDecl c'.p) reflBoolTrue (← mkEqRefl (← getOne))
|
||||
return mkApp3 h (← mkPolyDecl c'.p) eagerReflBoolTrue (← mkEqRefl (← getOne))
|
||||
| .ofEq a b la lb =>
|
||||
let h ← mkIntModPreOrdThmPrefix ``Grind.Linarith.le_of_eq
|
||||
return mkApp5 h (← mkExprDecl la) (← mkExprDecl lb) (← mkPolyDecl c'.p) reflBoolTrue (← mkEqProof a b)
|
||||
return mkApp5 h (← mkExprDecl la) (← mkExprDecl lb) (← mkPolyDecl c'.p) eagerReflBoolTrue (← mkEqProof a b)
|
||||
| .ofCommRingEq a b la lb p' lhs' =>
|
||||
let h' ← mkCommRingThmPrefix ``Grind.CommRing.eq_norm
|
||||
let h' := mkApp5 h' (← mkRingExprDecl la) (← mkRingExprDecl lb) (← mkRingPolyDecl p') reflBoolTrue (← mkEqProof a b)
|
||||
let h' := mkApp5 h' (← mkRingExprDecl la) (← mkRingExprDecl lb) (← mkRingPolyDecl p') eagerReflBoolTrue (← mkEqProof a b)
|
||||
let h ← mkIntModPreOrdThmPrefix ``Grind.Linarith.le_of_eq
|
||||
return mkApp5 h (← mkExprDecl lhs') (← mkExprDecl .zero) (← mkPolyDecl c'.p) reflBoolTrue h'
|
||||
return mkApp5 h (← mkExprDecl lhs') (← mkExprDecl .zero) (← mkPolyDecl c'.p) eagerReflBoolTrue h'
|
||||
| .dec h => return mkFVar h
|
||||
| .ofDiseqSplit c₁ fvarId h _ =>
|
||||
let hFalse ← h.toExprProofCore
|
||||
let lt ← getLtFn
|
||||
let hNot := mkLambda `h .default (mkApp2 lt (← c₁.p.denoteExpr) (← getZero)) (hFalse.abstract #[mkFVar fvarId])
|
||||
let h ← mkIntModLinOrdThmPrefix ``Grind.Linarith.diseq_split_resolve
|
||||
return mkApp5 h (← mkPolyDecl c₁.p) (← mkPolyDecl c'.p) reflBoolTrue (← c₁.toExprProof) hNot
|
||||
return mkApp5 h (← mkPolyDecl c₁.p) (← mkPolyDecl c'.p) eagerReflBoolTrue (← c₁.toExprProof) hNot
|
||||
| _ => throwError "not implemented yet"
|
||||
|
||||
partial def DiseqCnstr.toExprProof (c' : DiseqCnstr) : ProofM Expr := caching c' do
|
||||
match c'.h with
|
||||
| .core a b lhs rhs =>
|
||||
let h ← mkIntModThmPrefix ``Grind.Linarith.diseq_norm
|
||||
return mkApp5 h (← mkExprDecl lhs) (← mkExprDecl rhs) (← mkPolyDecl c'.p) reflBoolTrue (← mkDiseqProof a b)
|
||||
return mkApp5 h (← mkExprDecl lhs) (← mkExprDecl rhs) (← mkPolyDecl c'.p) eagerReflBoolTrue (← mkDiseqProof a b)
|
||||
| .coreCommRing a b lhs rhs p' lhs' =>
|
||||
let h' ← mkCommRingThmPrefix ``Grind.CommRing.diseq_norm
|
||||
let h' := mkApp5 h' (← mkRingExprDecl lhs) (← mkRingExprDecl rhs) (← mkRingPolyDecl p') reflBoolTrue (← mkDiseqProof a b)
|
||||
let h' := mkApp5 h' (← mkRingExprDecl lhs) (← mkRingExprDecl rhs) (← mkRingPolyDecl p') eagerReflBoolTrue (← mkDiseqProof a b)
|
||||
let h ← mkIntModThmPrefix ``Grind.Linarith.diseq_norm
|
||||
return mkApp5 h (← mkExprDecl lhs') (← mkExprDecl .zero) (← mkPolyDecl c'.p) reflBoolTrue h'
|
||||
return mkApp5 h (← mkExprDecl lhs') (← mkExprDecl .zero) (← mkPolyDecl c'.p) eagerReflBoolTrue h'
|
||||
| .neg c =>
|
||||
let h ← mkIntModThmPrefix ``Grind.Linarith.diseq_neg
|
||||
return mkApp4 h (← mkPolyDecl c.p) (← mkPolyDecl c'.p) reflBoolTrue (← c.toExprProof)
|
||||
return mkApp4 h (← mkPolyDecl c.p) (← mkPolyDecl c'.p) eagerReflBoolTrue (← c.toExprProof)
|
||||
| .subst k₁ k₂ c₁ c₂ =>
|
||||
let h ← mkIntModNoNatDivThmPrefix ``Grind.Linarith.eq_diseq_subst
|
||||
return mkApp8 h (toExpr k₁) (toExpr k₂) (← mkPolyDecl c₁.p) (← mkPolyDecl c₂.p) (← mkPolyDecl c'.p)
|
||||
reflBoolTrue (← c₁.toExprProof) (← c₂.toExprProof)
|
||||
eagerReflBoolTrue (← c₁.toExprProof) (← c₂.toExprProof)
|
||||
| .subst1 k c₁ c₂ =>
|
||||
let h ← mkIntModThmPrefix ``Grind.Linarith.eq_diseq_subst1
|
||||
return mkApp7 h (toExpr k) (← mkPolyDecl c₁.p) (← mkPolyDecl c₂.p) (← mkPolyDecl c'.p) reflBoolTrue
|
||||
return mkApp7 h (toExpr k) (← mkPolyDecl c₁.p) (← mkPolyDecl c₂.p) (← mkPolyDecl c'.p) eagerReflBoolTrue
|
||||
(← c₁.toExprProof) (← c₂.toExprProof)
|
||||
| .oneNeZero => throwError "not implemented yet"
|
||||
|
||||
@@ -263,17 +263,17 @@ partial def EqCnstr.toExprProof (c' : EqCnstr) : ProofM Expr := caching c' do
|
||||
match c'.h with
|
||||
| .core a b lhs rhs =>
|
||||
let h ← mkIntModThmPrefix ``Grind.Linarith.eq_norm
|
||||
return mkApp5 h (← mkExprDecl lhs) (← mkExprDecl rhs) (← mkPolyDecl c'.p) reflBoolTrue (← mkEqProof a b)
|
||||
return mkApp5 h (← mkExprDecl lhs) (← mkExprDecl rhs) (← mkPolyDecl c'.p) eagerReflBoolTrue (← mkEqProof a b)
|
||||
| .coreCommRing .. => throwError "not implemented yet"
|
||||
| .neg c =>
|
||||
let h ← mkIntModThmPrefix ``Grind.Linarith.eq_neg
|
||||
return mkApp4 h (← mkPolyDecl c.p) (← mkPolyDecl c'.p) reflBoolTrue (← c.toExprProof)
|
||||
return mkApp4 h (← mkPolyDecl c.p) (← mkPolyDecl c'.p) eagerReflBoolTrue (← c.toExprProof)
|
||||
| .coeff k c =>
|
||||
let h ← mkIntModNoNatDivThmPrefix ``Grind.Linarith.eq_coeff
|
||||
return mkApp5 h (← mkPolyDecl c.p) (← mkPolyDecl c'.p) (toExpr k) reflBoolTrue (← c.toExprProof)
|
||||
return mkApp5 h (← mkPolyDecl c.p) (← mkPolyDecl c'.p) (toExpr k) eagerReflBoolTrue (← c.toExprProof)
|
||||
| .subst x c₁ c₂ =>
|
||||
let h ← mkIntModThmPrefix ``Grind.Linarith.eq_eq_subst
|
||||
return mkApp7 h (toExpr x) (← mkPolyDecl c₁.p) (← mkPolyDecl c₂.p) (← mkPolyDecl c'.p) reflBoolTrue
|
||||
return mkApp7 h (toExpr x) (← mkPolyDecl c₁.p) (← mkPolyDecl c₂.p) (← mkPolyDecl c'.p) eagerReflBoolTrue
|
||||
(← c₁.toExprProof) (← c₂.toExprProof)
|
||||
|
||||
partial def UnsatProof.toExprProofCore (h : UnsatProof) : ProofM Expr := do
|
||||
|
||||
@@ -83,7 +83,7 @@ private def closeGoalWithValuesEq (lhs rhs : Expr) : GoalM Unit := do
|
||||
let p ← mkEq lhs rhs
|
||||
let hp ← mkEqProof lhs rhs
|
||||
let d ← mkDecide p
|
||||
let pEqFalse := mkApp3 (mkConst ``eq_false_of_decide) p d.appArg! reflBoolFalse
|
||||
let pEqFalse := mkApp3 (mkConst ``eq_false_of_decide) p d.appArg! eagerReflBoolFalse
|
||||
let falseProof := mkApp4 (mkConst ``Eq.mp [levelZero]) p (← getFalseExpr) pEqFalse hp
|
||||
closeGoal falseProof
|
||||
|
||||
|
||||
@@ -40,37 +40,37 @@ def simpEq? (e : Expr) : MetaM (Option (Expr × Expr)) := do
|
||||
let p := a.sub b |>.norm
|
||||
if p.isUnsatEq then
|
||||
let r := mkConst ``False
|
||||
let h := mkApp4 (mkConst ``Int.Linear.eq_eq_false) (← toContextExpr atoms) (toExpr a) (toExpr b) reflBoolTrue
|
||||
let h := mkApp4 (mkConst ``Int.Linear.eq_eq_false) (← toContextExpr atoms) (toExpr a) (toExpr b) eagerReflBoolTrue
|
||||
return some (r, mkExpectedPropHint h (mkPropEq e r))
|
||||
else if p.isValidEq then
|
||||
let r := mkConst ``True
|
||||
let h := mkApp4 (mkConst ``Int.Linear.eq_eq_true) (← toContextExpr atoms) (toExpr a) (toExpr b) reflBoolTrue
|
||||
let h := mkApp4 (mkConst ``Int.Linear.eq_eq_true) (← toContextExpr atoms) (toExpr a) (toExpr b) eagerReflBoolTrue
|
||||
return some (r, mkExpectedPropHint h (mkPropEq e r))
|
||||
else if p.toExpr == a && b == .num 0 then
|
||||
return none
|
||||
else match p with
|
||||
| .add 1 x (.add (-1) y (.num 0)) =>
|
||||
let r := mkIntEq atoms[x]! atoms[y]!
|
||||
let h := mkApp6 (mkConst ``Int.Linear.norm_eq_var) (← toContextExpr atoms) (toExpr a) (toExpr b) (toExpr x) (toExpr y) reflBoolTrue
|
||||
let h := mkApp6 (mkConst ``Int.Linear.norm_eq_var) (← toContextExpr atoms) (toExpr a) (toExpr b) (toExpr x) (toExpr y) eagerReflBoolTrue
|
||||
return some (r, mkExpectedPropHint h (mkPropEq e r))
|
||||
| .add 1 x (.num k) =>
|
||||
let r := mkIntEq atoms[x]! (toExpr (-k))
|
||||
let h := mkApp6 (mkConst ``Int.Linear.norm_eq_var_const) (← toContextExpr atoms) (toExpr a) (toExpr b) (toExpr x) (toExpr (-k)) reflBoolTrue
|
||||
let h := mkApp6 (mkConst ``Int.Linear.norm_eq_var_const) (← toContextExpr atoms) (toExpr a) (toExpr b) (toExpr x) (toExpr (-k)) eagerReflBoolTrue
|
||||
return some (r, mkExpectedPropHint h (mkPropEq e r))
|
||||
| _ =>
|
||||
let k := p.gcdCoeffs'
|
||||
if k == 1 then
|
||||
let r := mkIntEq (← p.denoteExpr (atoms[·]!)) (mkIntLit 0)
|
||||
let h := mkApp5 (mkConst ``Int.Linear.norm_eq) (← toContextExpr atoms) (toExpr a) (toExpr b) (toExpr p) reflBoolTrue
|
||||
let h := mkApp5 (mkConst ``Int.Linear.norm_eq) (← toContextExpr atoms) (toExpr a) (toExpr b) (toExpr p) eagerReflBoolTrue
|
||||
return some (r, mkExpectedPropHint h (mkPropEq e r))
|
||||
else if p.getConst % k == 0 then
|
||||
let p := p.div k
|
||||
let r := mkIntEq (← p.denoteExpr (atoms[·]!)) (mkIntLit 0)
|
||||
let h := mkApp6 (mkConst ``Int.Linear.norm_eq_coeff) (← toContextExpr atoms) (toExpr a) (toExpr b) (toExpr p) (toExpr (Int.ofNat k)) reflBoolTrue
|
||||
let h := mkApp6 (mkConst ``Int.Linear.norm_eq_coeff) (← toContextExpr atoms) (toExpr a) (toExpr b) (toExpr p) (toExpr (Int.ofNat k)) eagerReflBoolTrue
|
||||
return some (r, mkExpectedPropHint h (mkPropEq e r))
|
||||
else
|
||||
let r := mkConst ``False
|
||||
let h := mkApp5 (mkConst ``Int.Linear.eq_eq_false_of_divCoeff) (← toContextExpr atoms) (toExpr a) (toExpr b) (toExpr (Int.ofNat k)) reflBoolTrue
|
||||
let h := mkApp5 (mkConst ``Int.Linear.eq_eq_false_of_divCoeff) (← toContextExpr atoms) (toExpr a) (toExpr b) (toExpr (Int.ofNat k)) eagerReflBoolTrue
|
||||
return some (r, mkExpectedPropHint h (mkPropEq e r))
|
||||
|
||||
|
||||
@@ -83,11 +83,11 @@ def simpLe? (e : Expr) (checkIfModified : Bool) : MetaM (Option (Expr × Expr))
|
||||
let p := a.sub b |>.norm
|
||||
if p.isUnsatLe then
|
||||
let r := mkConst ``False
|
||||
let h := mkApp4 (mkConst ``Int.Linear.le_eq_false) (← toContextExpr atoms) (toExpr a) (toExpr b) reflBoolTrue
|
||||
let h := mkApp4 (mkConst ``Int.Linear.le_eq_false) (← toContextExpr atoms) (toExpr a) (toExpr b) eagerReflBoolTrue
|
||||
return some (r, mkExpectedPropHint h (mkPropEq e r))
|
||||
else if p.isValidLe then
|
||||
let r := mkConst ``True
|
||||
let h := mkApp4 (mkConst ``Int.Linear.le_eq_true) (← toContextExpr atoms) (toExpr a) (toExpr b) reflBoolTrue
|
||||
let h := mkApp4 (mkConst ``Int.Linear.le_eq_true) (← toContextExpr atoms) (toExpr a) (toExpr b) eagerReflBoolTrue
|
||||
return some (r, mkExpectedPropHint h (mkPropEq e r))
|
||||
else if checkIfModified && p.toExpr == a && b == .num 0 then
|
||||
return none
|
||||
@@ -95,16 +95,16 @@ def simpLe? (e : Expr) (checkIfModified : Bool) : MetaM (Option (Expr × Expr))
|
||||
let k := p.gcdCoeffs'
|
||||
if k == 1 then
|
||||
let r := mkIntLE (← p.denoteExpr (atoms[·]!)) (mkIntLit 0)
|
||||
let h := mkApp5 (mkConst ``Int.Linear.norm_le) (← toContextExpr atoms) (toExpr a) (toExpr b) (toExpr p) reflBoolTrue
|
||||
let h := mkApp5 (mkConst ``Int.Linear.norm_le) (← toContextExpr atoms) (toExpr a) (toExpr b) (toExpr p) eagerReflBoolTrue
|
||||
return some (r, mkExpectedPropHint h (mkPropEq e r))
|
||||
else
|
||||
let tight := p.getConst % k != 0
|
||||
let p := p.div k
|
||||
let r := mkIntLE (← p.denoteExpr (atoms[·]!)) (mkIntLit 0)
|
||||
let h ← if tight then
|
||||
pure <| mkApp6 (mkConst ``Int.Linear.norm_le_coeff_tight) (← toContextExpr atoms) (toExpr a) (toExpr b) (toExpr p) (toExpr (Int.ofNat k)) reflBoolTrue
|
||||
pure <| mkApp6 (mkConst ``Int.Linear.norm_le_coeff_tight) (← toContextExpr atoms) (toExpr a) (toExpr b) (toExpr p) (toExpr (Int.ofNat k)) eagerReflBoolTrue
|
||||
else
|
||||
pure <| mkApp6 (mkConst ``Int.Linear.norm_le_coeff) (← toContextExpr atoms) (toExpr a) (toExpr b) (toExpr p) (toExpr (Int.ofNat k)) reflBoolTrue
|
||||
pure <| mkApp6 (mkConst ``Int.Linear.norm_le_coeff) (← toContextExpr atoms) (toExpr a) (toExpr b) (toExpr p) (toExpr (Int.ofNat k)) eagerReflBoolTrue
|
||||
return some (r, mkExpectedPropHint h (mkPropEq e r))
|
||||
|
||||
def simpRel? (e : Expr) : MetaM (Option (Expr × Expr)) := do
|
||||
@@ -150,13 +150,13 @@ def simpDvd? (e : Expr) : MetaM (Option (Expr × Expr)) := do
|
||||
return none
|
||||
let rhs := mkIntDvd (toExpr d') (← p.denoteExpr (atoms[·]!))
|
||||
let h ← if g == 1 then
|
||||
pure <| mkApp5 (mkConst ``Int.Linear.norm_dvd) (← toContextExpr atoms) (toExpr d) (toExpr e) (toExpr p) reflBoolTrue
|
||||
pure <| mkApp5 (mkConst ``Int.Linear.norm_dvd) (← toContextExpr atoms) (toExpr d) (toExpr e) (toExpr p) eagerReflBoolTrue
|
||||
else
|
||||
pure <| mkApp7 (mkConst ``Int.Linear.norm_dvd_gcd) (← toContextExpr atoms) (toExpr d) (toExpr e) (toExpr d') (toExpr p) (toExpr g) reflBoolTrue
|
||||
pure <| mkApp7 (mkConst ``Int.Linear.norm_dvd_gcd) (← toContextExpr atoms) (toExpr d) (toExpr e) (toExpr d') (toExpr p) (toExpr g) eagerReflBoolTrue
|
||||
return some (rhs, mkExpectedPropHint h (mkPropEq lhs rhs))
|
||||
else
|
||||
let rhs := mkConst ``False
|
||||
let h := mkApp4 (mkConst ``Int.Linear.dvd_eq_false) (← toContextExpr atoms) (toExpr d) (toExpr e) reflBoolTrue
|
||||
let h := mkApp4 (mkConst ``Int.Linear.dvd_eq_false) (← toContextExpr atoms) (toExpr d) (toExpr e) eagerReflBoolTrue
|
||||
return some (rhs, mkExpectedPropHint h (mkPropEq lhs rhs))
|
||||
|
||||
def simpExpr? (lhs : Expr) : MetaM (Option (Expr × Expr)) := do
|
||||
@@ -165,7 +165,7 @@ def simpExpr? (lhs : Expr) : MetaM (Option (Expr × Expr)) := do
|
||||
let p := e.norm
|
||||
let e' := p.toExpr
|
||||
if e != e' then
|
||||
let h := mkApp4 (mkConst ``Int.Linear.Expr.eq_of_norm_eq) (← toContextExpr ctx) (toExpr e) (toExpr p) reflBoolTrue
|
||||
let h := mkApp4 (mkConst ``Int.Linear.Expr.eq_of_norm_eq) (← toContextExpr ctx) (toExpr e) (toExpr p) eagerReflBoolTrue
|
||||
let lhs ← e.denoteExpr (ctx[·]!)
|
||||
let rhs ← p.denoteExpr (ctx[·]!)
|
||||
return some (rhs, mkExpectedPropHint h (mkIntEq lhs rhs))
|
||||
|
||||
@@ -22,17 +22,17 @@ def simpCnstrPos? (e : Expr) : MetaM (Option (Expr × Expr)) := do
|
||||
let c₂ := c₁.norm
|
||||
if c₂.isUnsat then
|
||||
let r := mkConst ``False
|
||||
let p := mkApp3 (mkConst ``Nat.Linear.ExprCnstr.eq_false_of_isUnsat) (← toContextExpr atoms) (toExpr c) reflBoolTrue
|
||||
let p := mkApp3 (mkConst ``Nat.Linear.ExprCnstr.eq_false_of_isUnsat) (← toContextExpr atoms) (toExpr c) eagerReflBoolTrue
|
||||
return some (r, mkExpectedPropHint p (mkPropEq lhs r))
|
||||
else if c₂.isValid then
|
||||
let r := mkConst ``True
|
||||
let p := mkApp3 (mkConst ``Nat.Linear.ExprCnstr.eq_true_of_isValid) (← toContextExpr atoms) (toExpr c) reflBoolTrue
|
||||
let p := mkApp3 (mkConst ``Nat.Linear.ExprCnstr.eq_true_of_isValid) (← toContextExpr atoms) (toExpr c) eagerReflBoolTrue
|
||||
return some (r, mkExpectedPropHint p (mkPropEq lhs r))
|
||||
else
|
||||
let c₂ : LinearCnstr := c₂.toExpr
|
||||
let r ← c₂.toArith atoms
|
||||
if r != lhs then
|
||||
let p := mkApp4 (mkConst ``Nat.Linear.ExprCnstr.eq_of_toNormPoly_eq) (← toContextExpr atoms) (toExpr c) (toExpr c₂) reflBoolTrue
|
||||
let p := mkApp4 (mkConst ``Nat.Linear.ExprCnstr.eq_of_toNormPoly_eq) (← toContextExpr atoms) (toExpr c) (toExpr c₂) eagerReflBoolTrue
|
||||
return some (r, mkExpectedPropHint p (mkPropEq lhs r))
|
||||
else
|
||||
return none
|
||||
@@ -74,7 +74,7 @@ def simpExpr? (input : Expr) : MetaM (Option (Expr × Expr)) := do
|
||||
let e' : LinearExpr := p'.toExpr
|
||||
if e' == e then
|
||||
return none
|
||||
let p := mkApp4 (mkConst ``Nat.Linear.Expr.eq_of_toNormPoly_eq) (← toContextExpr ctx) (toExpr e) (toExpr e') reflBoolTrue
|
||||
let p := mkApp4 (mkConst ``Nat.Linear.Expr.eq_of_toNormPoly_eq) (← toContextExpr ctx) (toExpr e) (toExpr e') eagerReflBoolTrue
|
||||
let l ← e.toArith ctx
|
||||
let r ← e'.toArith ctx
|
||||
return some (r, mkExpectedPropHint p (mkNatEq l r))
|
||||
|
||||
@@ -118,9 +118,9 @@ builtin_simproc [simp, seval] reduceDvd ((_ : Int) ∣ _) := fun e => do
|
||||
let some va ← fromExpr? a | return .continue
|
||||
let some vb ← fromExpr? b | return .continue
|
||||
if vb % va == 0 then
|
||||
return .done { expr := mkConst ``True, proof? := mkApp3 (mkConst ``Int.dvd_eq_true_of_mod_eq_zero) a b reflBoolTrue}
|
||||
return .done { expr := mkConst ``True, proof? := mkApp3 (mkConst ``Int.dvd_eq_true_of_mod_eq_zero) a b eagerReflBoolTrue}
|
||||
else
|
||||
return .done { expr := mkConst ``False, proof? := mkApp3 (mkConst ``Int.dvd_eq_false_of_mod_ne_zero) a b reflBoolTrue}
|
||||
return .done { expr := mkConst ``False, proof? := mkApp3 (mkConst ``Int.dvd_eq_false_of_mod_ne_zero) a b eagerReflBoolTrue}
|
||||
|
||||
private def reduceNatCastCore (inst : Expr) (a : Expr) : SimpM DStep := do
|
||||
let some a ← getNatValue? a | return .continue
|
||||
|
||||
@@ -355,8 +355,8 @@ builtin_simproc [simp, seval] reduceDvd ((_ : Nat) ∣ _) := fun e => do
|
||||
let some va ← fromExpr? a | return .continue
|
||||
let some vb ← fromExpr? b | return .continue
|
||||
if vb % va == 0 then
|
||||
return .done { expr := mkConst ``True, proof? := mkApp3 (mkConst ``Nat.dvd_eq_true_of_mod_eq_zero) a b reflBoolTrue}
|
||||
return .done { expr := mkConst ``True, proof? := mkApp3 (mkConst ``Nat.dvd_eq_true_of_mod_eq_zero) a b eagerReflBoolTrue}
|
||||
else
|
||||
return .done { expr := mkConst ``False, proof? := mkApp3 (mkConst ``Nat.dvd_eq_false_of_mod_ne_zero) a b reflBoolTrue}
|
||||
return .done { expr := mkConst ``False, proof? := mkApp3 (mkConst ``Nat.dvd_eq_false_of_mod_ne_zero) a b eagerReflBoolTrue}
|
||||
|
||||
end Nat
|
||||
|
||||
@@ -24,6 +24,7 @@ namespace lean {
|
||||
static name * g_kernel_fresh = nullptr;
|
||||
static expr * g_dont_care = nullptr;
|
||||
static name * g_bool_true = nullptr;
|
||||
static name * g_eager_reduce = nullptr;
|
||||
static expr * g_nat_zero = nullptr;
|
||||
static expr * g_nat_succ = nullptr;
|
||||
static expr * g_nat_add = nullptr;
|
||||
@@ -154,12 +155,23 @@ expr type_checker::infer_pi(expr const & _e, bool infer_only) {
|
||||
return mk_sort(r);
|
||||
}
|
||||
|
||||
/* Returns `true` if `e` is of the form `eagerReduce _ _` */
|
||||
static bool is_eager_reduce(expr const & e) {
|
||||
return is_const(get_app_fn(e), *g_eager_reduce) && get_app_num_args(e) == 2;
|
||||
}
|
||||
|
||||
expr type_checker::infer_app(expr const & e, bool infer_only) {
|
||||
if (!infer_only) {
|
||||
expr f_type = ensure_pi_core(infer_type_core(app_fn(e), infer_only), e);
|
||||
expr a_type = infer_type_core(app_arg(e), infer_only);
|
||||
expr d_type = binding_domain(f_type);
|
||||
if (!is_def_eq(a_type, d_type)) {
|
||||
if (is_eager_reduce(app_arg(e))) {
|
||||
// If argument is of the form `eagerReduce`, set m_eager_reduction mode
|
||||
flet<bool> scope(m_eager_reduce, true);
|
||||
if (!is_def_eq(a_type, d_type)) {
|
||||
throw app_type_mismatch_exception(env(), m_lctx, e, f_type, a_type);
|
||||
}
|
||||
} else if (!is_def_eq(a_type, d_type)) {
|
||||
throw app_type_mismatch_exception(env(), m_lctx, e, f_type, a_type);
|
||||
}
|
||||
return instantiate(binding_body(f_type), app_arg(e));
|
||||
@@ -987,7 +999,7 @@ lbool type_checker::lazy_delta_reduction(expr & t_n, expr & s_n) {
|
||||
lbool r = is_def_eq_offset(t_n, s_n);
|
||||
if (r != l_undef) return r;
|
||||
|
||||
if (!has_fvar(t_n) && !has_fvar(s_n)) {
|
||||
if ((!has_fvar(t_n) && !has_fvar(s_n)) || m_eager_reduce) {
|
||||
if (auto t_v = reduce_nat(t_n)) {
|
||||
return to_lbool(is_def_eq_core(*t_v, s_n));
|
||||
} else if (auto s_v = reduce_nat(s_n)) {
|
||||
@@ -1075,7 +1087,7 @@ bool type_checker::is_def_eq_core(expr const & t, expr const & s) {
|
||||
// we fully reduce `t` and check whether result is `s`.
|
||||
// This code path is taken in particular when using the `decide` tactic, which produces
|
||||
// proof terms of the form `Eq.refl true : decide p = true`.
|
||||
if (!has_fvar(t) && is_constant(s, *g_bool_true)) {
|
||||
if ((!has_fvar(t) || m_eager_reduce) && is_constant(s, *g_bool_true)) {
|
||||
if (is_constant(whnf(t), *g_bool_true)) {
|
||||
return true;
|
||||
}
|
||||
@@ -1204,6 +1216,7 @@ void initialize_type_checker() {
|
||||
mark_persistent(g_kernel_fresh->raw());
|
||||
g_bool_true = new name{"Bool", "true"};
|
||||
mark_persistent(g_bool_true->raw());
|
||||
g_eager_reduce = new name{"eagerReduce"};
|
||||
g_dont_care = new_persistent_expr_const("dontcare");
|
||||
g_nat_zero = new_persistent_expr_const({"Nat", "zero"});
|
||||
g_nat_succ = new_persistent_expr_const({"Nat", "succ"});
|
||||
@@ -1230,6 +1243,7 @@ void initialize_type_checker() {
|
||||
void finalize_type_checker() {
|
||||
delete g_kernel_fresh;
|
||||
delete g_bool_true;
|
||||
delete g_eager_reduce;
|
||||
delete g_dont_care;
|
||||
delete g_nat_succ;
|
||||
delete g_nat_zero;
|
||||
|
||||
@@ -46,6 +46,11 @@ private:
|
||||
diagnostics * m_diag;
|
||||
local_ctx m_lctx;
|
||||
definition_safety m_definition_safety;
|
||||
/*
|
||||
`m_eager_reduce` is set to true whenever we are type checking an application argument that has been
|
||||
wrapped with `eagerReduce`.
|
||||
*/
|
||||
bool m_eager_reduce = false;
|
||||
/* When `m_lparams != nullptr, the `check` method makes sure all level parameters
|
||||
are in `m_lparams`. */
|
||||
names const * m_lparams;
|
||||
|
||||
2
tests/lean/run/grind_9854.lean
Normal file
2
tests/lean/run/grind_9854.lean
Normal file
@@ -0,0 +1,2 @@
|
||||
example (x: Nat) : UInt32.size - x < UInt64.size := by
|
||||
grind only
|
||||
@@ -16,7 +16,8 @@ trace: [grind.debug.proof] Classical.byContradiction fun h =>
|
||||
let e_2 := Expr.intMul 0 (Expr.var 0);
|
||||
let p_1 := Poly.nil;
|
||||
diseq_unsat ctx
|
||||
(diseq_norm ctx e_2 e_1 p_1 (Eq.refl true) (CommRing.diseq_norm rctx re_1 re_2 rp_1 (Eq.refl true) h))
|
||||
(diseq_norm ctx e_2 e_1 p_1 (eagerReduce (Eq.refl true))
|
||||
(CommRing.diseq_norm rctx re_1 re_2 rp_1 (eagerReduce (Eq.refl true)) h))
|
||||
-/
|
||||
#guard_msgs in
|
||||
open Linarith in
|
||||
|
||||
@@ -148,7 +148,7 @@ fun x y z =>
|
||||
(((((((Expr.var 1).add (Expr.mulL 3 (Expr.var 0))).add (Expr.num 1)).add (Expr.num 1)).add (Expr.var 2)).add
|
||||
(Expr.var 1)).sub
|
||||
(Expr.var 0))
|
||||
(Eq.refl true)))
|
||||
(eagerReduce (Eq.refl true))))
|
||||
-/
|
||||
#guard_msgs (info) in
|
||||
open Int.Linear in
|
||||
@@ -170,7 +170,7 @@ fun x y z f =>
|
||||
(((((((Expr.var 0).add (Expr.mulL 3 (Expr.var 1))).add (Expr.num 1)).add (Expr.num 1)).add (Expr.var 2)).add
|
||||
(Expr.var 0)).sub
|
||||
(Expr.var 1))
|
||||
(Eq.refl true)))
|
||||
(eagerReduce (Eq.refl true))))
|
||||
(f y))
|
||||
-/
|
||||
#guard_msgs (info) in
|
||||
@@ -295,7 +295,7 @@ fun a b =>
|
||||
((((Expr.var 1).add ((Expr.num 21).sub (Expr.var 1))).add
|
||||
(Expr.mulL 3 ((Expr.var 1).add (Expr.mulL 2 (Expr.var 0))))).add
|
||||
(Expr.num 12))
|
||||
2 (Poly.add 1 1 (Poly.add 2 0 (Poly.num 11))) 3 (Eq.refl true))))
|
||||
2 (Poly.add 1 1 (Poly.add 2 0 (Poly.num 11))) 3 (eagerReduce (Eq.refl true)))))
|
||||
(iff_self (2 ∣ a + 2 * b + 11)))
|
||||
-/
|
||||
#guard_msgs (info) in
|
||||
@@ -318,7 +318,7 @@ fun a b =>
|
||||
((((Expr.var 1).add ((Expr.num 11).sub (Expr.var 1))).add
|
||||
(Expr.mulL 3 ((Expr.var 1).add (Expr.mulL 2 (Expr.var 0))))).sub
|
||||
(Expr.num 11))
|
||||
2 (Poly.add 1 1 (Poly.add 2 0 (Poly.num 0))) 3 (Eq.refl true)))
|
||||
2 (Poly.add 1 1 (Poly.add 2 0 (Poly.num 0))) 3 (eagerReduce (Eq.refl true))))
|
||||
Int.dvd_add_self_mul._simp_1))
|
||||
Int.dvd_add_self_mul._simp_1)
|
||||
(iff_self (2 ∣ a)))
|
||||
|
||||
Reference in New Issue
Block a user