Skip to content

Commit b24e232

Browse files
authored
feat: lemmas about ordered rings and fields for grind (#8443)
This PR adds the lemmas about ordered rings and ordered fields which will be needed by the new algebraic normalization components of `grind`.
1 parent 9ad3974 commit b24e232

File tree

6 files changed

+375
-12
lines changed

6 files changed

+375
-12
lines changed

src/Init/Grind/CommRing/Field.lean

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ namespace Lean.Grind
1212

1313
class Field (α : Type u) extends CommRing α, Inv α, Div α where
1414
div_eq_mul_inv : ∀ a b : α, a / b = a * b⁻¹
15+
zero_ne_one : (0 : α) ≠ 1
1516
inv_zero : (0 : α)⁻¹ = 0
16-
inv_one : (1 : α)⁻¹ = 1
1717
mul_inv_cancel : ∀ {a : α}, a ≠ 0 → a * a⁻¹ = 1
1818

1919
attribute [instance 100] Field.toInv Field.toDiv
@@ -25,6 +25,52 @@ variable [Field α] {a : α}
2525
theorem inv_mul_cancel (h : a ≠ 0) : a⁻¹ * a = 1 := by
2626
rw [CommSemiring.mul_comm, mul_inv_cancel h]
2727

28+
theorem eq_inv_of_mul_eq_one (h : a * b = 1) : a = b⁻¹ := by
29+
by_cases h' : b = 0
30+
· subst h'
31+
rw [Semiring.mul_zero] at h
32+
exfalso
33+
exact zero_ne_one h
34+
· replace h := congrArg (fun x => x * b⁻¹) h
35+
simpa [Semiring.mul_assoc, mul_inv_cancel h', Semiring.mul_one, Semiring.one_mul] using h
36+
37+
theorem inv_one : (1 : α)⁻¹ = 1 :=
38+
(eq_inv_of_mul_eq_one (Semiring.mul_one 1)).symm
39+
40+
theorem inv_inv (a : α) : a⁻¹⁻¹ = a := by
41+
by_cases h : a = 0
42+
· subst h
43+
simp [Field.inv_zero]
44+
· symm
45+
apply eq_inv_of_mul_eq_one
46+
exact mul_inv_cancel h
47+
48+
theorem inv_neg (a : α) : (-a)⁻¹ = -a⁻¹ := by
49+
by_cases h : a = 0
50+
· subst h
51+
simp [Field.inv_zero, Ring.neg_zero]
52+
· symm
53+
apply eq_inv_of_mul_eq_one
54+
simp [Ring.neg_mul, Ring.mul_neg, Ring.neg_neg, Field.inv_mul_cancel h]
55+
56+
theorem inv_eq_zero_iff {a : α} : a⁻¹ = 0 ↔ a = 0 := by
57+
constructor
58+
· intro w
59+
by_cases h : a = 0
60+
· subst h
61+
rfl
62+
· have := congrArg (fun x => x * a) w
63+
dsimp at this
64+
rw [Semiring.zero_mul, inv_mul_cancel h] at this
65+
exfalso
66+
exact zero_ne_one this.symm
67+
· intro w
68+
subst w
69+
simp [Field.inv_zero]
70+
71+
theorem zero_eq_inv_iff {a : α} : 0 = a⁻¹ ↔ 0 = a := by
72+
rw [eq_comm, inv_eq_zero_iff, eq_comm]
73+
2874
instance [IsCharP α 0] : NoNatZeroDivisors α where
2975
no_nat_zero_divisors := by
3076
intro a b h w

src/Init/Grind/Ordered.lean

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ Authors: Kim Morrison
66
module
77

88
prelude
9-
import Init.Grind.Ordered.PartialOrder
9+
import Init.Grind.Ordered.Order
1010
import Init.Grind.Ordered.Module
1111
import Init.Grind.Ordered.Ring
12+
import Init.Grind.Ordered.Field
1213
import Init.Grind.Ordered.Int

src/Init/Grind/Ordered/Field.lean

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
/-
2+
Copyright (c) 2025 Lean FRO, LLC. or its affiliates. All Rights Reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Kim Morrison
5+
-/
6+
module
7+
8+
prelude
9+
import Init.Grind.CommRing.Field
10+
import Init.Grind.Ordered.Ring
11+
12+
namespace Lean.Grind
13+
14+
namespace Field.IsOrdered
15+
16+
variable {R : Type u} [Field R] [LinearOrder R] [Ring.IsOrdered R]
17+
18+
open Ring.IsOrdered
19+
20+
theorem pos_of_inv_pos {a : R} (h : 0 < a⁻¹) : 0 < a := by
21+
rcases LinearOrder.trichotomy 0 a with (h' | rfl | h')
22+
· exact h'
23+
· simpa [Field.inv_zero] using h
24+
· exfalso
25+
have := Ring.IsOrdered.mul_neg_of_pos_of_neg h h'
26+
rw [inv_mul_cancel (Preorder.ne_of_lt h')] at this
27+
exact Ring.IsOrdered.not_one_lt_zero this
28+
29+
theorem inv_pos_iff {a : R} : 0 < a⁻¹ ↔ 0 < a := by
30+
constructor
31+
· exact pos_of_inv_pos
32+
· intro h
33+
rw [← Field.inv_inv a] at h
34+
exact pos_of_inv_pos h
35+
36+
theorem inv_neg_iff {a : R} : a⁻¹ < 0 ↔ a < 0 := by
37+
have := inv_pos_iff (a := -a)
38+
rw [Field.inv_neg] at this
39+
simpa [IntModule.IsOrdered.neg_pos_iff]
40+
41+
theorem inv_nonneg_iff {a : R} : 0 ≤ a⁻¹ ↔ 0 ≤ a := by
42+
simp [PartialOrder.le_iff_lt_or_eq, inv_pos_iff, Field.zero_eq_inv_iff]
43+
44+
theorem inv_nonpos_iff {a : R} : a⁻¹ ≤ 0 ↔ a ≤ 0 := by
45+
have := inv_nonneg_iff (a := -a)
46+
rw [Field.inv_neg] at this
47+
simpa [IntModule.IsOrdered.neg_nonneg_iff] using this
48+
49+
private theorem mul_le_of_le_mul_inv {a b c : R} (h : 0 < c) (h' : a ≤ b * c⁻¹) : a * c ≤ b := by
50+
simpa [Semiring.mul_assoc, Field.inv_mul_cancel (Preorder.ne_of_gt h), Semiring.mul_one] using
51+
Ring.IsOrdered.mul_le_mul_of_nonneg_right h' (Preorder.le_of_lt h)
52+
53+
private theorem le_mul_inv_of_mul_le {a b c : R} (h : 0 < b) (h' : a * b ≤ c) : a ≤ c * b⁻¹ := by
54+
simpa [Semiring.mul_assoc, Field.mul_inv_cancel (Preorder.ne_of_gt h), Semiring.mul_one] using
55+
Ring.IsOrdered.mul_le_mul_of_nonneg_right h' (Preorder.le_of_lt (inv_pos_iff.mpr h))
56+
57+
theorem le_mul_inv_iff_mul_le (a b : R) {c : R} (h : 0 < c) : a ≤ b * c⁻¹ ↔ a * c ≤ b :=
58+
⟨mul_le_of_le_mul_inv h, le_mul_inv_of_mul_le h⟩
59+
60+
private theorem mul_inv_le_iff_le_mul (a c : R) {b : R} (h : 0 < b) : a * b⁻¹ ≤ c ↔ a ≤ c * b := by
61+
have := (le_mul_inv_iff_mul_le a c (inv_pos_iff.mpr h)).symm
62+
simpa [Field.inv_inv] using this
63+
64+
private theorem mul_lt_of_lt_mul_inv {a b c : R} (h : 0 < c) (h' : a < b * c⁻¹) : a * c < b := by
65+
simpa [Semiring.mul_assoc, Field.inv_mul_cancel (Preorder.ne_of_gt h), Semiring.mul_one] using
66+
Ring.IsOrdered.mul_lt_mul_of_pos_right h' h
67+
68+
private theorem lt_mul_inv_of_mul_lt {a b c : R} (h : 0 < b) (h' : a * b < c) : a < c * b⁻¹ := by
69+
simpa [Semiring.mul_assoc, Field.mul_inv_cancel (Preorder.ne_of_gt h), Semiring.mul_one] using
70+
Ring.IsOrdered.mul_lt_mul_of_pos_right h' (inv_pos_iff.mpr h)
71+
72+
theorem lt_mul_inv_iff_mul_lt (a b : R) {c : R} (h : 0 < c) : a < b * c⁻¹ ↔ a * c < b :=
73+
⟨mul_lt_of_lt_mul_inv h, lt_mul_inv_of_mul_lt h⟩
74+
75+
theorem mul_inv_lt_iff_lt_mul (a c : R) {b : R} (h : 0 < b) : a * b⁻¹ < c ↔ a < c * b := by
76+
simpa [Field.inv_inv] using (lt_mul_inv_iff_mul_lt a c (inv_pos_iff.mpr h)).symm
77+
78+
private theorem le_mul_of_le_mul_inv {a b c : R} (h : c < 0) (h' : a ≤ b * c⁻¹) : b ≤ a * c := by
79+
simpa [Semiring.mul_assoc, Field.inv_mul_cancel (Preorder.ne_of_lt h), Semiring.mul_one] using
80+
Ring.IsOrdered.mul_le_mul_of_nonpos_right h' (Preorder.le_of_lt h)
81+
82+
private theorem mul_le_of_mul_inv_le {a b c : R} (h : b < 0) (h' : a * b⁻¹ ≤ c) : c * b ≤ a := by
83+
simpa [Semiring.mul_assoc, Field.inv_mul_cancel (Preorder.ne_of_lt h), Semiring.mul_one] using
84+
Ring.IsOrdered.mul_le_mul_of_nonpos_right h' (Preorder.le_of_lt h)
85+
86+
private theorem mul_inv_le_of_mul_le {a b c : R} (h : b < 0) (h' : a * b ≤ c) : c * b⁻¹ ≤ a := by
87+
simpa [Semiring.mul_assoc, Field.mul_inv_cancel (Preorder.ne_of_lt h), Semiring.mul_one] using
88+
Ring.IsOrdered.mul_le_mul_of_nonpos_right h' (Preorder.le_of_lt (inv_neg_iff.mpr h))
89+
90+
private theorem le_mul_inv_of_le_mul {a b c : R} (h : c < 0) (h' : a ≤ b * c) : b ≤ a * c⁻¹ := by
91+
simpa [Semiring.mul_assoc, Field.mul_inv_cancel (Preorder.ne_of_lt h), Semiring.mul_one] using
92+
Ring.IsOrdered.mul_le_mul_of_nonpos_right h' (Preorder.le_of_lt (inv_neg_iff.mpr h))
93+
94+
theorem le_mul_inv_iff_le_mul_of_neg (a b : R) {c : R} (h : c < 0) : a ≤ b * c⁻¹ ↔ b ≤ a * c :=
95+
⟨le_mul_of_le_mul_inv h, le_mul_inv_of_le_mul h⟩
96+
97+
theorem mul_inv_le_iff_mul_le_of_neg (a c : R) {b : R} (h : b < 0) : a * b⁻¹ ≤ c ↔ c * b ≤ a :=
98+
⟨mul_le_of_mul_inv_le h, mul_inv_le_of_mul_le h⟩
99+
100+
private theorem lt_mul_of_lt_mul_inv {a b c : R} (h : c < 0) (h' : a < b * c⁻¹) : b < a * c := by
101+
simpa [Semiring.mul_assoc, Field.inv_mul_cancel (Preorder.ne_of_lt h), Semiring.mul_one] using
102+
Ring.IsOrdered.mul_lt_mul_of_neg_right h' h
103+
104+
private theorem mul_lt_of_mul_inv_lt {a b c : R} (h : b < 0) (h' : a * b⁻¹ < c) : c * b < a := by
105+
simpa [Semiring.mul_assoc, Field.inv_mul_cancel (Preorder.ne_of_lt h), Semiring.mul_one] using
106+
Ring.IsOrdered.mul_lt_mul_of_neg_right h' h
107+
108+
private theorem mul_inv_lt_of_mul_lt {a b c : R} (h : b < 0) (h' : a * b < c) : c * b⁻¹ < a := by
109+
simpa [Semiring.mul_assoc, Field.mul_inv_cancel (Preorder.ne_of_lt h), Semiring.mul_one] using
110+
Ring.IsOrdered.mul_lt_mul_of_neg_right h' (inv_neg_iff.mpr h)
111+
112+
private theorem lt_mul_inv_of_lt_mul {a b c : R} (h : c < 0) (h' : a < b * c) : b < a * c⁻¹ := by
113+
simpa [Semiring.mul_assoc, Field.mul_inv_cancel (Preorder.ne_of_lt h), Semiring.mul_one] using
114+
Ring.IsOrdered.mul_lt_mul_of_neg_right h' (inv_neg_iff.mpr h)
115+
116+
theorem lt_mul_inv_iff_lt_mul_of_neg (a b : R) {c : R} (h : c < 0) : a < b * c⁻¹ ↔ b < a * c :=
117+
⟨lt_mul_of_lt_mul_inv h, lt_mul_inv_of_lt_mul h⟩
118+
119+
theorem mul_inv_lt_iff_mul_lt_of_neg (a c : R) {b : R} (h : b < 0) : a * b⁻¹ < c ↔ c * b < a :=
120+
⟨mul_lt_of_mul_inv_lt h, mul_inv_lt_of_mul_lt h⟩
121+
122+
theorem mul_lt_mul_iff_of_pos_right {a b c : R} (h : 0 < c) : a * c < b * c ↔ a < b := by
123+
constructor
124+
· intro h'
125+
have := mul_lt_mul_of_pos_right h' (inv_pos_iff.mpr h)
126+
rwa [Semiring.mul_assoc, Semiring.mul_assoc, mul_inv_cancel (Preorder.ne_of_gt h),
127+
Semiring.mul_one, Semiring.mul_one] at this
128+
· exact (mul_lt_mul_of_pos_right · h)
129+
130+
theorem mul_lt_mul_iff_of_pos_left {a b c : R} (h : 0 < c) : c * a < c * b ↔ a < b := by
131+
constructor
132+
· intro h'
133+
have := mul_lt_mul_of_pos_left h' (inv_pos_iff.mpr h)
134+
rwa [← Semiring.mul_assoc, ← Semiring.mul_assoc, inv_mul_cancel (Preorder.ne_of_gt h),
135+
Semiring.one_mul, Semiring.one_mul] at this
136+
· exact (mul_lt_mul_of_pos_left · h)
137+
138+
theorem mul_lt_mul_iff_of_neg_right {a b c : R} (h : c < 0) : a * c < b * c ↔ b < a := by
139+
constructor
140+
· intro h'
141+
have := mul_lt_mul_of_neg_right h' (inv_neg_iff.mpr h)
142+
rwa [Semiring.mul_assoc, Semiring.mul_assoc, mul_inv_cancel (Preorder.ne_of_lt h),
143+
Semiring.mul_one, Semiring.mul_one] at this
144+
· exact (mul_lt_mul_of_neg_right · h)
145+
146+
theorem mul_lt_mul_iff_of_neg_left {a b c : R} (h : c < 0) : c * a < c * b ↔ b < a := by
147+
constructor
148+
· intro h'
149+
have := mul_lt_mul_of_neg_left h' (inv_neg_iff.mpr h)
150+
rwa [← Semiring.mul_assoc, ← Semiring.mul_assoc, inv_mul_cancel (Preorder.ne_of_lt h),
151+
Semiring.one_mul, Semiring.one_mul] at this
152+
· exact (mul_lt_mul_of_neg_left · h)
153+
154+
theorem mul_le_mul_iff_of_pos_right {a b c : R} (h : 0 < c) : a * c ≤ b * c ↔ a ≤ b := by
155+
constructor
156+
· intro h'
157+
have := mul_le_mul_of_nonneg_right h' (Preorder.le_of_lt (inv_pos_iff.mpr h))
158+
rwa [Semiring.mul_assoc, Semiring.mul_assoc, mul_inv_cancel (Preorder.ne_of_gt h),
159+
Semiring.mul_one, Semiring.mul_one] at this
160+
· exact (mul_le_mul_of_nonneg_right · (Preorder.le_of_lt h))
161+
162+
theorem mul_le_mul_iff_of_pos_left {a b c : R} (h : 0 < c) : c * a ≤ c * b ↔ a ≤ b := by
163+
constructor
164+
· intro h'
165+
have := mul_le_mul_of_nonneg_left h' (Preorder.le_of_lt (inv_pos_iff.mpr h))
166+
rwa [← Semiring.mul_assoc, ← Semiring.mul_assoc, inv_mul_cancel (Preorder.ne_of_gt h),
167+
Semiring.one_mul, Semiring.one_mul] at this
168+
· exact (mul_le_mul_of_nonneg_left · (Preorder.le_of_lt h))
169+
170+
theorem mul_le_mul_iff_of_neg_right {a b c : R} (h : c < 0) : a * c ≤ b * c ↔ b ≤ a := by
171+
constructor
172+
· intro h'
173+
have := mul_le_mul_of_nonpos_right h' (Preorder.le_of_lt (inv_neg_iff.mpr h))
174+
rwa [Semiring.mul_assoc, Semiring.mul_assoc, mul_inv_cancel (Preorder.ne_of_lt h),
175+
Semiring.mul_one, Semiring.mul_one] at this
176+
· exact (mul_le_mul_of_nonpos_right · (Preorder.le_of_lt h))
177+
178+
theorem mul_le_mul_iff_of_neg_left {a b c : R} (h : c < 0) : c * a ≤ c * b ↔ b ≤ a := by
179+
constructor
180+
· intro h'
181+
have := mul_le_mul_of_nonpos_left h' (Preorder.le_of_lt (inv_neg_iff.mpr h))
182+
rwa [← Semiring.mul_assoc, ← Semiring.mul_assoc, inv_mul_cancel (Preorder.ne_of_lt h),
183+
Semiring.one_mul, Semiring.one_mul] at this
184+
· exact (mul_le_mul_of_nonpos_left · (Preorder.le_of_lt h))
185+
186+
end Field.IsOrdered
187+
188+
end Lean.Grind

src/Init/Grind/Ordered/Module.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ module
88
prelude
99
import Init.Data.Int.Order
1010
import Init.Grind.Module.Basic
11-
import Init.Grind.Ordered.PartialOrder
11+
import Init.Grind.Ordered.Order
1212

1313
namespace Lean.Grind
1414

src/Init/Grind/Ordered/PartialOrder.lean renamed to src/Init/Grind/Ordered/Order.lean

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,22 @@ theorem lt_of_le_of_lt {a b c : α} (h₁ : a ≤ b) (h₂ : b < c) : a < c := b
3434
theorem lt_trans {a b c : α} (h₁ : a < b) (h₂ : b < c) : a < c :=
3535
lt_of_lt_of_le h₁ (le_of_lt h₂)
3636

37-
theorem lt_irrefl {a : α} (h : a < a) : False := by
37+
theorem lt_irrefl (a : α) : ¬ (a < a) := by
38+
intro h
3839
simp [lt_iff_le_not_le] at h
3940

41+
theorem ne_of_lt {a b : α} (h : a < b) : a ≠ b :=
42+
fun w => lt_irrefl a (w.symm ▸ h)
43+
44+
theorem ne_of_gt {a b : α} (h : a > b) : a ≠ b :=
45+
fun w => lt_irrefl b (w.symm ▸ h)
46+
47+
theorem not_ge_of_lt {a b : α} (h : a < b) : ¬b ≤ a :=
48+
fun w => lt_irrefl a (lt_of_lt_of_le h w)
49+
50+
theorem not_gt_of_lt {a b : α} (h : a < b) : ¬a > b :=
51+
fun w => lt_irrefl a (lt_trans h w)
52+
4053
end Preorder
4154

4255
class PartialOrder (α : Type u) extends Preorder α where
@@ -58,4 +71,26 @@ theorem le_iff_lt_or_eq {a b : α} : a ≤ b ↔ a < b ∨ a = b := by
5871

5972
end PartialOrder
6073

74+
class LinearOrder (α : Type u) extends PartialOrder α where
75+
le_total : ∀ a b : α, a ≤ b ∨ b ≤ a
76+
77+
namespace LinearOrder
78+
79+
variable {α : Type u} [LinearOrder α]
80+
81+
theorem trichotomy (a b : α) : a < b ∨ a = b ∨ b < a := by
82+
cases LinearOrder.le_total a b with
83+
| inl h =>
84+
rw [PartialOrder.le_iff_lt_or_eq] at h
85+
cases h with
86+
| inl h => left; exact h
87+
| inr h => right; left; exact h
88+
| inr h =>
89+
rw [PartialOrder.le_iff_lt_or_eq] at h
90+
cases h with
91+
| inl h => right; right; exact h
92+
| inr h => right; left; exact h.symm
93+
94+
end LinearOrder
95+
6196
end Lean.Grind

0 commit comments

Comments
 (0)