From 085c4ed3f9b56523e6c50b8da2cfd361eb656230 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Tue, 10 Jun 2025 12:06:47 -0400 Subject: [PATCH] fix: internalization issue in the interface between linarith and ring (#8708) This PR fixes an internalization bug in the interface between linarith and ring modules in `grind`. The `CommRing` module may create new terms during normalization. --- src/Lean/Meta/Tactic/Grind/Arith/Linear/DenoteExpr.lean | 7 +++++++ src/Lean/Meta/Tactic/Grind/Arith/Linear/IneqCnstr.lean | 5 +++-- src/Lean/Meta/Tactic/Grind/Arith/Linear/PropagateEq.lean | 5 +++-- tests/lean/run/grind_linarith_1.lean | 8 ++++++++ 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/Lean/Meta/Tactic/Grind/Arith/Linear/DenoteExpr.lean b/src/Lean/Meta/Tactic/Grind/Arith/Linear/DenoteExpr.lean index a2b2e9503c..832f602522 100644 --- a/src/Lean/Meta/Tactic/Grind/Arith/Linear/DenoteExpr.lean +++ b/src/Lean/Meta/Tactic/Grind/Arith/Linear/DenoteExpr.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura -/ prelude +import Lean.Meta.Tactic.Grind.ProveEq import Lean.Meta.Tactic.Grind.Arith.CommRing.DenoteExpr import Lean.Meta.Tactic.Grind.Arith.Linear.Util import Lean.Meta.Tactic.Grind.Arith.Linear.Var @@ -66,4 +67,10 @@ def _root_.Lean.Grind.CommRing.Poly.denoteAsIntModuleExpr (p : Grind.CommRing.Po | .num k => denoteNum k | .add k m p => return mkApp2 (← getStruct).addFn (mkApp2 (← getStruct).hmulFn (mkIntLit k) (← m.denoteExpr)) (← denoteAsIntModuleExpr p) +def _root_.Lean.Grind.CommRing.Poly.toIntModuleExpr (p : Grind.CommRing.Poly) (generation := 0) : LinearM Expr := do + let e ← p.denoteAsIntModuleExpr + let e ← preprocessLight e + internalize e generation none + return e + end Lean.Meta.Grind.Arith.Linear diff --git a/src/Lean/Meta/Tactic/Grind/Arith/Linear/IneqCnstr.lean b/src/Lean/Meta/Tactic/Grind/Arith/Linear/IneqCnstr.lean index c363f30f7d..555d94a782 100644 --- a/src/Lean/Meta/Tactic/Grind/Arith/Linear/IneqCnstr.lean +++ b/src/Lean/Meta/Tactic/Grind/Arith/Linear/IneqCnstr.lean @@ -41,9 +41,10 @@ def IneqCnstr.assert (c : IneqCnstr) : LinearM Unit := do def propagateCommRingIneq (e : Expr) (lhs rhs : Expr) (strict : Bool) (eqTrue : Bool) : LinearM Unit := do let some lhs ← withRingM <| CommRing.reify? lhs (skipVar := false) | return () let some rhs ← withRingM <| CommRing.reify? rhs (skipVar := false) | return () + let gen ← getGeneration e if eqTrue then let p' := (lhs.sub rhs).toPoly - let lhs' ← p'.denoteAsIntModuleExpr + let lhs' ← p'.toIntModuleExpr gen let some lhs' ← reify? lhs' (skipVar := false) | return () let p := lhs'.norm let c : IneqCnstr := { p, strict, h := .coreCommRing e lhs rhs p' lhs' } @@ -51,7 +52,7 @@ def propagateCommRingIneq (e : Expr) (lhs rhs : Expr) (strict : Bool) (eqTrue : else if (← isLinearOrder) then let p' := (rhs.sub lhs).toPoly let strict := !strict - let lhs' ← p'.denoteAsIntModuleExpr + let lhs' ← p'.toIntModuleExpr gen let some lhs' ← reify? lhs' (skipVar := false) | return () let p := lhs'.norm let c : IneqCnstr := { p, strict, h := .notCoreCommRing e lhs rhs p' lhs' } diff --git a/src/Lean/Meta/Tactic/Grind/Arith/Linear/PropagateEq.lean b/src/Lean/Meta/Tactic/Grind/Arith/Linear/PropagateEq.lean index 456d9d12cc..ab52417571 100644 --- a/src/Lean/Meta/Tactic/Grind/Arith/Linear/PropagateEq.lean +++ b/src/Lean/Meta/Tactic/Grind/Arith/Linear/PropagateEq.lean @@ -25,8 +25,9 @@ private def inSameStruct? (a b : Expr) : GoalM (Option Nat) := do private def processNewCommRingEq (a b : Expr) : LinearM Unit := do let some lhs ← withRingM <| CommRing.reify? a (skipVar := false) | return () let some rhs ← withRingM <| CommRing.reify? b (skipVar := false) | return () + let gen := max (← getGeneration a) (← getGeneration b) let p' := (lhs.sub rhs).toPoly - let lhs' ← p'.denoteAsIntModuleExpr + let lhs' ← p'.toIntModuleExpr gen let some lhs' ← reify? lhs' (skipVar := false) | return () let p := lhs'.norm if p == .nil then return () @@ -34,7 +35,7 @@ private def processNewCommRingEq (a b : Expr) : LinearM Unit := do c₁.assert let p := p.mul (-1) let p' := p'.mulConst (-1) - let lhs' ← p'.denoteAsIntModuleExpr + let lhs' ← p'.toIntModuleExpr gen let some lhs' ← reify? lhs' (skipVar := false) | return () let c₂ : IneqCnstr := { p, strict := false, h := .ofCommRingEq b a rhs lhs p' lhs' } c₂.assert diff --git a/tests/lean/run/grind_linarith_1.lean b/tests/lean/run/grind_linarith_1.lean index c606fad7d1..2d7685475c 100644 --- a/tests/lean/run/grind_linarith_1.lean +++ b/tests/lean/run/grind_linarith_1.lean @@ -135,3 +135,11 @@ example [CommRing α] [LinearOrder α] [Ring.IsOrdered α] (a b c : α) example [CommRing α] [LinearOrder α] [Ring.IsOrdered α] (a b : α) : a = 0 → b = 1 → a + b ≤ 2 := by grind + +example [CommRing α] [LinearOrder α] [Ring.IsOrdered α] (a b : α) + : a*b + b*a > 1 → a*b > 0 := by + grind + +example [CommRing α] [LinearOrder α] [Ring.IsOrdered α] (a b c : α) + : a*b + c > 1 → c = b*a → a*b > 0 := by + grind