Skip to content

Commit ef9094d

Browse files
authored
feat: CommRing interface for grind linarith (#8670)
This PR adds helper theorems that will be used to interface the `CommRing` module with the linarith procedure in `grind`.
1 parent d50292d commit ef9094d

File tree

3 files changed

+103
-19
lines changed

3 files changed

+103
-19
lines changed

src/Init/Grind/CommRing/Poly.lean

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import Init.Data.Hashable
1111
import all Init.Data.Ord
1212
import Init.Data.RArray
1313
import Init.Grind.CommRing.Basic
14+
import Init.Grind.Ordered.Ring
1415

1516
namespace Lean.Grind
1617
namespace CommRing
@@ -35,13 +36,13 @@ abbrev Context (α : Type u) := RArray α
3536
def Var.denote {α} (ctx : Context α) (v : Var) : α :=
3637
ctx.get v
3738

38-
def denoteInt {α} [CommRing α] (k : Int) : α :=
39+
def denoteInt {α} [Ring α] (k : Int) : α :=
3940
bif k < 0 then
4041
- OfNat.ofNat (α := α) k.natAbs
4142
else
4243
OfNat.ofNat (α := α) k.natAbs
4344

44-
def Expr.denote {α} [CommRing α] (ctx : Context α) : Expr → α
45+
def Expr.denote {α} [Ring α] (ctx : Context α) : Expr → α
4546
| .add a b => denote ctx a + denote ctx b
4647
| .sub a b => denote ctx a - denote ctx b
4748
| .mul a b => denote ctx a * denote ctx b
@@ -1139,5 +1140,72 @@ theorem imp_keqC {α c} [CommRing α] [IsCharP α c] (ctx : Context α) [NoNatZe
11391140

11401141
end Stepwise
11411142

1143+
/-! IntModule interface -/
1144+
1145+
def Poly.denoteAsIntModule [CommRing α] (ctx : Context α) (p : Poly) : α :=
1146+
match p with
1147+
| .num k => Int.cast k * 1
1148+
| .add k m p => Int.cast k * m.denote ctx + denote ctx p
1149+
1150+
theorem Poly.denoteAsIntModule_eq_denote {α} [CommRing α] (ctx : Context α) (p : Poly) : p.denoteAsIntModule ctx = p.denote ctx := by
1151+
induction p <;> simp [*, denoteAsIntModule, denote, mul_one]
1152+
1153+
open Stepwise
1154+
1155+
theorem eq_norm {α} [CommRing α] (ctx : Context α) (lhs rhs : Expr) (p : Poly)
1156+
: core_cert lhs rhs p → lhs.denote ctx = rhs.denote ctx → p.denoteAsIntModule ctx = 0 := by
1157+
rw [Poly.denoteAsIntModule_eq_denote]; apply core
1158+
1159+
theorem diseq_norm {α} [CommRing α] (ctx : Context α) (lhs rhs : Expr) (p : Poly)
1160+
: core_cert lhs rhs p → lhs.denote ctx ≠ rhs.denote ctx → p.denoteAsIntModule ctx ≠ 0 := by
1161+
simp [core_cert, Poly.denoteAsIntModule_eq_denote]; intro _ h; subst p; simp [Expr.denote_toPoly, Expr.denote]
1162+
intro h; rw [sub_eq_zero_iff] at h; contradiction
1163+
1164+
open IntModule.IsOrdered
1165+
1166+
theorem le_norm {α} [CommRing α] [Preorder α] [Ring.IsOrdered α] (ctx : Context α) (lhs rhs : Expr) (p : Poly)
1167+
: core_cert lhs rhs p → lhs.denote ctx ≤ rhs.denote ctx → p.denoteAsIntModule ctx ≤ 0 := by
1168+
simp [core_cert, Poly.denoteAsIntModule_eq_denote]; intro _ h; subst p; simp [Expr.denote_toPoly, Expr.denote]
1169+
replace h := add_le_left h ((-1) * rhs.denote ctx)
1170+
rw [neg_mul, ← sub_eq_add_neg, one_mul, ← sub_eq_add_neg, sub_self] at h
1171+
assumption
1172+
1173+
theorem lt_norm {α} [CommRing α] [Preorder α] [Ring.IsOrdered α] (ctx : Context α) (lhs rhs : Expr) (p : Poly)
1174+
: core_cert lhs rhs p → lhs.denote ctx < rhs.denote ctx → p.denoteAsIntModule ctx < 0 := by
1175+
simp [core_cert, Poly.denoteAsIntModule_eq_denote]; intro _ h; subst p; simp [Expr.denote_toPoly, Expr.denote]
1176+
replace h := add_lt_left h ((-1) * rhs.denote ctx)
1177+
rw [neg_mul, ← sub_eq_add_neg, one_mul, ← sub_eq_add_neg, sub_self] at h
1178+
assumption
1179+
1180+
theorem not_le_norm {α} [CommRing α] [LinearOrder α] [Ring.IsOrdered α] (ctx : Context α) (lhs rhs : Expr) (p : Poly)
1181+
: core_cert rhs lhs p → ¬ lhs.denote ctx ≤ rhs.denote ctx → p.denote ctx < 0 := by
1182+
simp [core_cert]; intro _ h₁; subst p; simp [Expr.denote_toPoly, Expr.denote]
1183+
replace h₁ := LinearOrder.lt_of_not_le h₁
1184+
replace h₁ := add_lt_left h₁ (-lhs.denote ctx)
1185+
simp [← sub_eq_add_neg, sub_self] at h₁
1186+
assumption
1187+
1188+
theorem not_lt_norm {α} [CommRing α] [LinearOrder α] [Ring.IsOrdered α] (ctx : Context α) (lhs rhs : Expr) (p : Poly)
1189+
: core_cert rhs lhs p → ¬ lhs.denote ctx < rhs.denote ctx → p.denote ctx ≤ 0 := by
1190+
simp [core_cert]; intro _ h₁; subst p; simp [Expr.denote_toPoly, Expr.denote]
1191+
replace h₁ := LinearOrder.le_of_not_lt h₁
1192+
replace h₁ := add_le_left h₁ (-lhs.denote ctx)
1193+
simp [← sub_eq_add_neg, sub_self] at h₁
1194+
assumption
1195+
1196+
theorem not_le_norm' {α} [CommRing α] [Preorder α] [Ring.IsOrdered α] (ctx : Context α) (lhs rhs : Expr) (p : Poly)
1197+
: core_cert lhs rhs p → ¬ lhs.denote ctx ≤ rhs.denote ctx → ¬ p.denote ctx ≤ 0 := by
1198+
simp [core_cert]; intro _ h₁; subst p; simp [Expr.denote_toPoly, Expr.denote]; intro h
1199+
replace h := add_le_right (rhs.denote ctx) h
1200+
rw [sub_eq_add_neg, add_left_comm, ← sub_eq_add_neg, sub_self] at h; simp [add_zero] at h
1201+
contradiction
1202+
1203+
theorem not_lt_norm' {α} [CommRing α] [Preorder α] [Ring.IsOrdered α] (ctx : Context α) (lhs rhs : Expr) (p : Poly)
1204+
: core_cert lhs rhs p → ¬ lhs.denote ctx < rhs.denote ctx → ¬ p.denote ctx < 0 := by
1205+
simp [core_cert]; intro _ h₁; subst p; simp [Expr.denote_toPoly, Expr.denote]; intro h
1206+
replace h := add_lt_right (rhs.denote ctx) h
1207+
rw [sub_eq_add_neg, add_left_comm, ← sub_eq_add_neg, sub_self] at h; simp [add_zero] at h
1208+
contradiction
1209+
11421210
end CommRing
11431211
end Lean.Grind

src/Init/Grind/Ordered/Linarith.lean

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -386,35 +386,38 @@ theorem lt_norm {α} [IntModule α] [Preorder α] [IntModule.IsOrdered α] (ctx
386386
simp [← sub_eq_add_neg, sub_self] at h₁
387387
assumption
388388

389-
private theorem le_of_not_lt {α} [LinearOrder α] {a b : α} (h : ¬ a < b) : b ≤ a := by
390-
cases LinearOrder.trichotomy a b
391-
next => contradiction
392-
next h => apply PartialOrder.le_iff_lt_or_eq.mpr; cases h <;> simp [*]
393-
394-
private theorem lt_of_not_le {α} [LinearOrder α] {a b : α} (h : ¬ a ≤ b) : b < a := by
395-
cases LinearOrder.trichotomy a b
396-
next h₁ h₂ => have := Preorder.lt_iff_le_not_le.mp h₂; simp [h] at this
397-
next h =>
398-
cases h
399-
next h => subst a; exact False.elim <| h (Preorder.le_refl b)
400-
next => assumption
401-
402389
theorem not_le_norm {α} [IntModule α] [LinearOrder α] [IntModule.IsOrdered α] (ctx : Context α) (lhs rhs : Expr) (p : Poly)
403390
: norm_cert rhs lhs p → ¬ lhs.denote ctx ≤ rhs.denote ctx → p.denote ctx < 0 := by
404391
simp [norm_cert]; intro _ h₁; subst p; simp [Expr.denote, h₁, sub_self]
405-
replace h₁ := lt_of_not_le h₁
392+
replace h₁ := LinearOrder.lt_of_not_le h₁
406393
replace h₁ := add_lt_left h₁ (-lhs.denote ctx)
407394
simp [← sub_eq_add_neg, sub_self] at h₁
408395
assumption
409396

410397
theorem not_lt_norm {α} [IntModule α] [LinearOrder α] [IntModule.IsOrdered α] (ctx : Context α) (lhs rhs : Expr) (p : Poly)
411398
: norm_cert rhs lhs p → ¬ lhs.denote ctx < rhs.denote ctx → p.denote ctx ≤ 0 := by
412399
simp [norm_cert]; intro _ h₁; subst p; simp [Expr.denote, h₁, sub_self]
413-
replace h₁ := le_of_not_lt h₁
400+
replace h₁ := LinearOrder.le_of_not_lt h₁
414401
replace h₁ := add_le_left h₁ (-lhs.denote ctx)
415402
simp [← sub_eq_add_neg, sub_self] at h₁
416403
assumption
417404

405+
-- If the module does not have a linear order, we can still put the expressions in polynomial forms
406+
407+
theorem not_le_norm' {α} [IntModule α] [Preorder α] [IntModule.IsOrdered α] (ctx : Context α) (lhs rhs : Expr) (p : Poly)
408+
: norm_cert lhs rhs p → ¬ lhs.denote ctx ≤ rhs.denote ctx → ¬ p.denote ctx ≤ 0 := by
409+
simp [norm_cert]; intro _ h₁; subst p; simp [Expr.denote, h₁, sub_self]; intro h
410+
replace h := add_le_right (rhs.denote ctx) h
411+
rw [sub_eq_add_neg, add_left_comm, ← sub_eq_add_neg, sub_self] at h; simp at h
412+
contradiction
413+
414+
theorem not_lt_norm' {α} [IntModule α] [Preorder α] [IntModule.IsOrdered α] (ctx : Context α) (lhs rhs : Expr) (p : Poly)
415+
: norm_cert lhs rhs p → ¬ lhs.denote ctx < rhs.denote ctx → ¬ p.denote ctx < 0 := by
416+
simp [norm_cert]; intro _ h₁; subst p; simp [Expr.denote, h₁, sub_self]; intro h
417+
replace h := add_lt_right (rhs.denote ctx) h
418+
rw [sub_eq_add_neg, add_left_comm, ← sub_eq_add_neg, sub_self] at h; simp at h
419+
contradiction
420+
418421
/-!
419422
Equality detection
420423
-/
@@ -459,7 +462,7 @@ theorem le_coeff {α} [IntModule α] [LinearOrder α] [IntModule.IsOrdered α] (
459462
simp [coeff_cert]; intro h _; subst p₁; simp
460463
have : ↑k > (0 : Int) := Int.natCast_pos.mpr h
461464
intro h₁; apply Classical.byContradiction
462-
intro h₂; replace h₂ := lt_of_not_le h₂
465+
intro h₂; replace h₂ := LinearOrder.lt_of_not_le h₂
463466
replace h₂ := IsOrdered.hmul_pos (↑k) h₂ |>.mp this
464467
exact Preorder.lt_irrefl 0 (Preorder.lt_of_lt_of_le h₂ h₁)
465468

@@ -468,7 +471,7 @@ theorem lt_coeff {α} [IntModule α] [LinearOrder α] [IntModule.IsOrdered α] (
468471
simp [coeff_cert]; intro h _; subst p₁; simp
469472
have : ↑k > (0 : Int) := Int.natCast_pos.mpr h
470473
intro h₁; apply Classical.byContradiction
471-
intro h₂; replace h₂ := le_of_not_lt h₂
474+
intro h₂; replace h₂ := LinearOrder.le_of_not_lt h₂
472475
replace h₂ := IsOrdered.hmul_nonneg (Int.le_of_lt this) h₂
473476
exact Preorder.lt_irrefl 0 (Preorder.lt_of_le_of_lt h₂ h₁)
474477

src/Init/Grind/Ordered/Order.lean

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,19 @@ theorem trichotomy (a b : α) : a < b ∨ a = b ∨ b < a := by
9191
| inl h => right; right; exact h
9292
| inr h => right; left; exact h.symm
9393

94+
theorem le_of_not_lt {α} [LinearOrder α] {a b : α} (h : ¬ a < b) : b ≤ a := by
95+
cases LinearOrder.trichotomy a b
96+
next => contradiction
97+
next h => apply PartialOrder.le_iff_lt_or_eq.mpr; cases h <;> simp [*]
98+
99+
theorem lt_of_not_le {α} [LinearOrder α] {a b : α} (h : ¬ a ≤ b) : b < a := by
100+
cases LinearOrder.trichotomy a b
101+
next h₁ h₂ => have := Preorder.lt_iff_le_not_le.mp h₂; simp [h] at this
102+
next h =>
103+
cases h
104+
next h => subst a; exact False.elim <| h (Preorder.le_refl b)
105+
next => assumption
106+
94107
end LinearOrder
95108

96109
end Lean.Grind

0 commit comments

Comments
 (0)