Skip to content

Commit 90cb7f7

Browse files
joelrioukim-em
andcommitted
feat: port Algebra.GroupPower.Ring (#979)
Mathlib SHA: fc2ed6f838ce7c9b7c7171e58d78eaf7b438fb0e Co-authored-by: Scott Morrison <scott.morrison@gmail.com>
1 parent 0ddfc70 commit 90cb7f7

File tree

3 files changed

+282
-10
lines changed

3 files changed

+282
-10
lines changed

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import Mathlib.Algebra.Group.WithOne.Units
2525
import Mathlib.Algebra.GroupPower.Basic
2626
import Mathlib.Algebra.GroupPower.Identities
2727
import Mathlib.Algebra.GroupPower.Lemmas
28+
import Mathlib.Algebra.GroupPower.Ring
2829
import Mathlib.Algebra.GroupWithZero.Basic
2930
import Mathlib.Algebra.GroupWithZero.Commute
3031
import Mathlib.Algebra.GroupWithZero.Defs
Lines changed: 280 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,280 @@
1+
/-
2+
Copyright (c) 2015 Jeremy Avigad. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Jeremy Avigad, Robert Y. Lewis
5+
Ported by: Joël Riou
6+
-/
7+
8+
import Mathlib.Algebra.GroupPower.Basic
9+
import Mathlib.Algebra.GroupWithZero.Commute
10+
import Mathlib.Algebra.Hom.Ring
11+
import Mathlib.Algebra.Ring.Commute
12+
import Mathlib.Algebra.GroupWithZero.Divisibility
13+
import Mathlib.Algebra.Ring.Divisibility
14+
import Mathlib.Data.Nat.Order.Basic
15+
16+
/-!
17+
# Power operations on monoids with zero, semirings, and rings
18+
19+
This file provides additional lemmas about the natural power operator on rings and semirings.
20+
Further lemmas about ordered semirings and rings can be found in `Algebra.GroupPower.Lemmas`.
21+
22+
-/
23+
24+
variable {R S M : Type _}
25+
26+
section MonoidWithZero
27+
28+
variable [MonoidWithZero M]
29+
30+
theorem zero_pow : ∀ {n : ℕ}, 0 < n → (0 : M) ^ n = 0
31+
| n + 1, _ => by rw [pow_succ, zero_mul]
32+
33+
@[simp]
34+
theorem zero_pow' : ∀ n : ℕ, n ≠ 0 → (0 : M) ^ n = 0
35+
| 0, h => absurd rfl h
36+
| k + 1, _ => by
37+
rw [pow_succ]
38+
exact zero_mul _
39+
40+
theorem zero_pow_eq (n : ℕ) : (0 : M) ^ n = if n = 0 then 1 else 0 := by
41+
split_ifs with h
42+
· rw [h, pow_zero]
43+
· rw [zero_pow (Nat.pos_of_ne_zero h)]
44+
45+
theorem pow_eq_zero_of_le {x : M} {n m : ℕ} (hn : n ≤ m) (hx : x ^ n = 0) : x ^ m = 0 := by
46+
rw [← tsub_add_cancel_of_le hn, pow_add, hx, mul_zero]
47+
48+
theorem pow_eq_zero [NoZeroDivisors M] {x : M} {n : ℕ} (H : x ^ n = 0) : x = 0 := by
49+
induction' n with n ih
50+
· rw [pow_zero] at H
51+
rw [← mul_one x, H, mul_zero]
52+
· rw [pow_succ] at H
53+
exact Or.casesOn (mul_eq_zero.1 H) id ih
54+
55+
@[simp]
56+
theorem pow_eq_zero_iff [NoZeroDivisors M] {a : M} {n : ℕ} (hn : 0 < n) : a ^ n = 0 ↔ a = 0 := by
57+
refine' ⟨pow_eq_zero, _⟩
58+
rintro rfl
59+
exact zero_pow hn
60+
61+
theorem pow_eq_zero_iff' [NoZeroDivisors M] [Nontrivial M] {a : M} {n : ℕ} :
62+
a ^ n = 0 ↔ a = 0 ∧ n ≠ 0 := by cases (zero_le n).eq_or_gt <;> simp [*, ne_of_gt]
63+
64+
theorem pow_ne_zero_iff [NoZeroDivisors M] {a : M} {n : ℕ} (hn : 0 < n) : a ^ n ≠ 0 ↔ a ≠ 0 :=
65+
(pow_eq_zero_iff hn).not
66+
67+
theorem ne_zero_pow {a : M} {n : ℕ} (hn : n ≠ 0) : a ^ n ≠ 0 → a ≠ 0 := by
68+
contrapose!
69+
rintro rfl
70+
exact zero_pow' n hn
71+
#align ne_zero_pow ne_zero_pow
72+
73+
@[field_simps]
74+
theorem pow_ne_zero [NoZeroDivisors M] {a : M} (n : ℕ) (h : a ≠ 0) : a ^ n ≠ 0 :=
75+
mt pow_eq_zero h
76+
#align pow_ne_zero pow_ne_zero
77+
78+
instance NeZero.pow [NoZeroDivisors M] {x : M} [NeZero x] {n : ℕ} : NeZero (x ^ n) :=
79+
⟨pow_ne_zero n NeZero.out⟩
80+
#align ne_zero.pow NeZero.pow
81+
82+
theorem sq_eq_zero_iff [NoZeroDivisors M] {a : M} : a ^ 2 = 0 ↔ a = 0 :=
83+
pow_eq_zero_iff two_pos
84+
#align sq_eq_zero_iff sq_eq_zero_iff
85+
86+
@[simp]
87+
theorem zero_pow_eq_zero [Nontrivial M] {n : ℕ} : (0 : M) ^ n = 00 < n := by
88+
constructor <;> intro h
89+
· rw [pos_iff_ne_zero]
90+
rintro rfl
91+
simp at h
92+
· exact zero_pow' n h.ne.symm
93+
94+
theorem Ring.inverse_pow (r : M) : ∀ n : ℕ, Ring.inverse r ^ n = Ring.inverse (r ^ n)
95+
| 0 => by rw [pow_zero, pow_zero, Ring.inverse_one]
96+
| n + 1 => by
97+
rw [pow_succ, pow_succ', Ring.mul_inverse_rev' ((Commute.refl r).pow_left n),
98+
Ring.inverse_pow r n]
99+
100+
end MonoidWithZero
101+
102+
section CommMonoidWithZero
103+
104+
variable [CommMonoidWithZero M] {n : ℕ} (hn : 0 < n)
105+
106+
/-- We define `x ↦ x^n` (for positive `n : ℕ`) as a `monoid_with_zero_hom` -/
107+
def powMonoidWithZeroHom : M →*₀ M :=
108+
{ powMonoidHom n with map_zero' := zero_pow hn }
109+
110+
@[simp]
111+
theorem coe_powMonoidWithZeroHom : (powMonoidWithZeroHom hn : M → M) = fun x ↦ (x^n : M) := rfl
112+
#align coe_pow_monoid_with_zero_hom coe_powMonoidWithZeroHom
113+
114+
@[simp]
115+
theorem powMonoidWithZeroHom_apply (a : M) : powMonoidWithZeroHom hn a = a ^ n :=
116+
rfl
117+
#align pow_monoid_with_zero_hom_apply powMonoidWithZeroHom_apply
118+
119+
end CommMonoidWithZero
120+
121+
theorem pow_dvd_pow_iff [CancelCommMonoidWithZero R] {x : R} {n m : ℕ} (h0 : x ≠ 0)
122+
(h1 : ¬IsUnit x) : x ^ n ∣ x ^ m ↔ n ≤ m := by
123+
constructor
124+
· intro h
125+
rw [← not_lt]
126+
intro hmn
127+
apply h1
128+
have : x ^ m * x ∣ x ^ m * 1 := by
129+
rw [← pow_succ', mul_one]
130+
exact (pow_dvd_pow _ (Nat.succ_le_of_lt hmn)).trans h
131+
rwa [mul_dvd_mul_iff_left, ← isUnit_iff_dvd_one] at this
132+
apply pow_ne_zero m h0
133+
· apply pow_dvd_pow
134+
135+
section Semiring
136+
137+
variable [Semiring R] [Semiring S]
138+
139+
protected theorem RingHom.map_pow (f : R →+* S) (a) : ∀ n : ℕ, f (a ^ n) = f a ^ n :=
140+
map_pow f a
141+
#align ring_hom.map_pow RingHom.map_pow
142+
143+
theorem min_pow_dvd_add {n m : ℕ} {a b c : R} (ha : c ^ n ∣ a) (hb : c ^ m ∣ b) :
144+
c ^ min n m ∣ a + b := by
145+
replace ha := (pow_dvd_pow c (min_le_left n m)).trans ha
146+
replace hb := (pow_dvd_pow c (min_le_right n m)).trans hb
147+
exact dvd_add ha hb
148+
149+
end Semiring
150+
151+
section CommSemiring
152+
153+
variable [CommSemiring R]
154+
155+
theorem add_sq (a b : R) : (a + b) ^ 2 = a ^ 2 + 2 * a * b + b ^ 2 := by
156+
simp only [sq, add_mul_self_eq]
157+
#align add_sq add_sq
158+
159+
theorem add_sq' (a b : R) : (a + b) ^ 2 = a ^ 2 + b ^ 2 + 2 * a * b := by
160+
rw [add_sq, add_assoc, add_comm _ (b ^ 2), add_assoc]
161+
#align add_sq' add_sq'
162+
163+
alias add_sq ← add_pow_two
164+
165+
end CommSemiring
166+
167+
section HasDistribNeg
168+
169+
variable [Monoid R] [HasDistribNeg R]
170+
171+
variable (R)
172+
173+
theorem neg_one_pow_eq_or : ∀ n : ℕ, (-1 : R) ^ n = 1 ∨ (-1 : R) ^ n = -1
174+
| 0 => Or.inl (pow_zero _)
175+
| n + 1 => (neg_one_pow_eq_or n).symm.imp
176+
(fun h ↦ by rw [pow_succ, h, neg_one_mul, neg_neg])
177+
(fun h ↦ by rw [pow_succ, h, mul_one])
178+
179+
variable {R}
180+
181+
theorem neg_pow (a : R) (n : ℕ) : (-a) ^ n = (-1) ^ n * a ^ n :=
182+
neg_one_mul a ▸ (Commute.neg_one_left a).mul_pow n
183+
184+
section
185+
set_option linter.deprecated false
186+
187+
@[simp]
188+
theorem neg_pow_bit0 (a : R) (n : ℕ) : (-a) ^ bit0 n = a ^ bit0 n := by
189+
rw [pow_bit0', neg_mul_neg, pow_bit0']
190+
#align neg_pow_bit0 neg_pow_bit0
191+
192+
@[simp]
193+
theorem neg_pow_bit1 (a : R) (n : ℕ) : (-a) ^ bit1 n = -a ^ bit1 n := by
194+
simp only [bit1, pow_succ, neg_pow_bit0, neg_mul_eq_neg_mul]
195+
#align neg_pow_bit1 neg_pow_bit1
196+
197+
end
198+
199+
@[simp]
200+
theorem neg_sq (a : R) : (-a) ^ 2 = a ^ 2 := by simp [sq]
201+
202+
-- Porting note: removed the simp attribute to please the simpNF linter
203+
theorem neg_one_sq : (-1 : R) ^ 2 = 1 := by simp [neg_sq, one_pow]
204+
205+
alias neg_sq ← neg_pow_two
206+
207+
alias neg_one_sq ← neg_one_pow_two
208+
209+
end HasDistribNeg
210+
211+
section Ring
212+
213+
variable [Ring R] {a b : R}
214+
215+
protected theorem Commute.sq_sub_sq (h : Commute a b) : a ^ 2 - b ^ 2 = (a + b) * (a - b) := by
216+
rw [sq, sq, h.mul_self_sub_mul_self_eq]
217+
218+
@[simp]
219+
theorem neg_one_pow_mul_eq_zero_iff {n : ℕ} {r : R} : (-1) ^ n * r = 0 ↔ r = 0 := by
220+
rcases neg_one_pow_eq_or R n with h | h <;> simp [h]
221+
222+
@[simp]
223+
theorem mul_neg_one_pow_eq_zero_iff {n : ℕ} {r : R} : r * (-1) ^ n = 0 ↔ r = 0 := by
224+
rcases neg_one_pow_eq_or R n with h | h <;> simp [h]
225+
226+
variable [NoZeroDivisors R]
227+
228+
protected theorem Commute.sq_eq_sq_iff_eq_or_eq_neg (h : Commute a b) :
229+
a ^ 2 = b ^ 2 ↔ a = b ∨ a = -b := by
230+
rw [← sub_eq_zero, h.sq_sub_sq, mul_eq_zero, add_eq_zero_iff_eq_neg, sub_eq_zero, or_comm]
231+
#align commute.sq_eq_sq_iff_eq_or_eq_neg Commute.sq_eq_sq_iff_eq_or_eq_neg
232+
233+
@[simp]
234+
theorem sq_eq_one_iff : a ^ 2 = 1 ↔ a = 1 ∨ a = -1 := by
235+
rw [← (Commute.one_right a).sq_eq_sq_iff_eq_or_eq_neg, one_pow]
236+
#align sq_eq_one_iff sq_eq_one_iff
237+
238+
theorem sq_ne_one_iff : a ^ 21 ↔ a ≠ 1 ∧ a ≠ -1 :=
239+
sq_eq_one_iff.not.trans not_or
240+
#align sq_ne_one_iff sq_ne_one_iff
241+
242+
end Ring
243+
244+
section CommRing
245+
246+
variable [CommRing R]
247+
248+
theorem sq_sub_sq (a b : R) : a ^ 2 - b ^ 2 = (a + b) * (a - b) :=
249+
(Commute.all a b).sq_sub_sq
250+
251+
alias sq_sub_sq ← pow_two_sub_pow_two
252+
253+
theorem sub_sq (a b : R) : (a - b) ^ 2 = a ^ 2 - 2 * a * b + b ^ 2 := by
254+
rw [sub_eq_add_neg, add_sq, neg_sq, mul_neg, ← sub_eq_add_neg]
255+
256+
alias sub_sq ← sub_pow_two
257+
258+
theorem sub_sq' (a b : R) : (a - b) ^ 2 = a ^ 2 + b ^ 2 - 2 * a * b := by
259+
rw [sub_eq_add_neg, add_sq', neg_sq, mul_neg, ← sub_eq_add_neg]
260+
261+
variable [NoZeroDivisors R] {a b : R}
262+
263+
theorem sq_eq_sq_iff_eq_or_eq_neg : a ^ 2 = b ^ 2 ↔ a = b ∨ a = -b :=
264+
(Commute.all a b).sq_eq_sq_iff_eq_or_eq_neg
265+
266+
theorem eq_or_eq_neg_of_sq_eq_sq (a b : R) : a ^ 2 = b ^ 2 → a = b ∨ a = -b :=
267+
sq_eq_sq_iff_eq_or_eq_neg.1
268+
269+
-- Copies of the above CommRing lemmas for `Units R`.
270+
namespace Units
271+
272+
protected theorem sq_eq_sq_iff_eq_or_eq_neg {a b : Rˣ} : a ^ 2 = b ^ 2 ↔ a = b ∨ a = -b := by
273+
simp_rw [ext_iff, val_pow_eq_pow_val, sq_eq_sq_iff_eq_or_eq_neg, Units.val_neg, iff_self]
274+
275+
protected theorem eq_or_eq_neg_of_sq_eq_sq (a b : Rˣ) (h : a ^ 2 = b ^ 2) : a = b ∨ a = -b :=
276+
Units.sq_eq_sq_iff_eq_or_eq_neg.1 h
277+
278+
end Units
279+
280+
end CommRing

Mathlib/Tactic/Positivity/Basic.lean

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import Mathlib.Tactic.Positivity.Core
88
import Mathlib.Tactic.Clear!
99
import Mathlib.Logic.Nontrivial
1010
import Mathlib.Algebra.CovariantAndContravariant
11-
import Mathlib.Algebra.GroupPower.Basic
11+
import Mathlib.Algebra.GroupPower.Ring
1212
import Mathlib.Algebra.GroupWithZero.Basic
1313
import Mathlib.Algebra.Order.Ring.Defs
1414
import Mathlib.Algebra.Order.Ring.Lemmas
@@ -61,15 +61,6 @@ instance [StrictOrderedSemiring α] : OrderedMonoidWithZero α :=
6161
instance [StrictOrderedSemiring α] : MulPosStrictMono α :=
6262
fun ⟨_, ha⟩ _ _ h => StrictOrderedSemiring.mul_lt_mul_of_pos_right _ _ _ h ha⟩
6363

64-
theorem pow_ne_zero [MonoidWithZero M] [NoZeroDivisors M] {a : M} (n : ℕ) (h : a ≠ 0) :
65-
a ^ n ≠ 0 := by
66-
refine mt (fun H => ?_) h
67-
induction' n with n IH
68-
· rw [pow_zero] at H
69-
rw [←mul_one a, H, mul_zero]
70-
· rw [pow_succ, mul_eq_zero] at H
71-
exact H.casesOn id IH
72-
7364
lemma mul_ne_zero_of_ne_zero_of_pos [Zero α] [Mul α] [PartialOrder α] [NoZeroDivisors α]
7465
{a b : α} (ha : a ≠ 0) (hb : 0 < b) : a * b ≠ 0 :=
7566
mul_ne_zero ha (ne_of_gt hb)

0 commit comments

Comments
 (0)