-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Expand file tree
/
Copy pathDivisibility.lean
More file actions
199 lines (149 loc) · 6.52 KB
/
Copy pathDivisibility.lean
File metadata and controls
199 lines (149 loc) · 6.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
/-
Copyright (c) 2014 Jeremy Avigad. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Jeremy Avigad, Leonardo de Moura, Floris van Doorn, Amelia Livingston, Yury Kudryashov,
Neil Strickland, Aaron Anderson
-/
module
public import Mathlib.Algebra.GroupWithZero.Units.Basic
public import Mathlib.Algebra.Divisibility.Units
public import Mathlib.Data.Nat.Basic
/-!
# Divisibility in groups with zero.
Lemmas about divisibility in groups and monoids with zero.
-/
@[expose] public section
assert_not_exists DenselyOrdered Ring
variable {α : Type*}
section SemigroupWithZero
variable [SemigroupWithZero α] {a : α}
theorem eq_zero_of_zero_dvd (h : 0 ∣ a) : a = 0 :=
Dvd.elim h fun c H' => H'.trans (zero_mul c)
/-- Given an element `a` of a commutative semigroup with zero, there exists another element whose
product with zero equals `a` iff `a` equals zero. -/
@[simp]
theorem zero_dvd_iff : 0 ∣ a ↔ a = 0 :=
⟨eq_zero_of_zero_dvd, fun h => by
rw [h]
exact ⟨0, by simp⟩⟩
@[simp]
theorem dvd_zero (a : α) : a ∣ 0 :=
Dvd.intro 0 (by simp)
end SemigroupWithZero
/-- Given two elements `b`, `c` of a cancellative `MonoidWithZero` and a nonzero element `a`,
`a*b` divides `a*c` iff `b` divides `c`. -/
theorem mul_dvd_mul_iff_left [MonoidWithZero α] [IsLeftCancelMulZero α] {a b c : α} (ha : a ≠ 0) :
a * b ∣ a * c ↔ b ∣ c :=
exists_congr fun d => by rw [mul_assoc, mul_right_inj' ha]
/-- Given two elements `a`, `b` of a commutative cancellative `MonoidWithZero` and a nonzero
element `c`, `a*c` divides `b*c` iff `a` divides `b`. -/
theorem mul_dvd_mul_iff_right [CommMonoidWithZero α] [IsCancelMulZero α] {a b c : α} (hc : c ≠ 0) :
a * c ∣ b * c ↔ a ∣ b :=
exists_congr fun d => by rw [mul_right_comm, mul_left_inj' hc]
section CommMonoidWithZero
variable [CommMonoidWithZero α]
/-- `DvdNotUnit a b` expresses that `a` divides `b` "strictly", i.e. that `b` divided by `a`
is not a unit. -/
def DvdNotUnit (a b : α) : Prop :=
a ≠ 0 ∧ ∃ x, ¬IsUnit x ∧ b = a * x
theorem dvdNotUnit_of_dvd_of_not_dvd {a b : α} (hd : a ∣ b) (hnd : ¬b ∣ a) : DvdNotUnit a b := by
constructor
· rintro rfl
exact hnd (dvd_zero _)
· rcases hd with ⟨c, rfl⟩
refine ⟨c, ?_, rfl⟩
rintro ⟨u, rfl⟩
simp at hnd
variable {x y : α}
theorem isRelPrime_zero_left : IsRelPrime 0 x ↔ IsUnit x :=
⟨(· (dvd_zero _) dvd_rfl), IsUnit.isRelPrime_right⟩
theorem isRelPrime_zero_right : IsRelPrime x 0 ↔ IsUnit x :=
isRelPrime_comm.trans isRelPrime_zero_left
theorem not_isRelPrime_zero_zero [Nontrivial α] : ¬IsRelPrime (0 : α) 0 :=
mt isRelPrime_zero_right.mp not_isUnit_zero
theorem IsRelPrime.ne_zero_or_ne_zero [Nontrivial α] (h : IsRelPrime x y) : x ≠ 0 ∨ y ≠ 0 :=
not_or_of_imp <| by rintro rfl rfl; exact not_isRelPrime_zero_zero h
end CommMonoidWithZero
theorem isRelPrime_of_no_nonunits_factors [MonoidWithZero α] {x y : α} (nonzero : ¬(x = 0 ∧ y = 0))
(H : ∀ z, ¬ IsUnit z → z ≠ 0 → z ∣ x → ¬z ∣ y) : IsRelPrime x y := by
refine fun z hx hy ↦ by_contra fun h ↦ H z h ?_ hx hy
rintro rfl; exact nonzero ⟨zero_dvd_iff.1 hx, zero_dvd_iff.1 hy⟩
theorem dvd_and_not_dvd_iff [CommMonoidWithZero α] [IsCancelMulZero α] {x y : α} :
x ∣ y ∧ ¬y ∣ x ↔ DvdNotUnit x y :=
⟨fun ⟨⟨d, hd⟩, hyx⟩ =>
⟨fun hx0 => by simp [hx0] at hyx,
⟨d, mt isUnit_iff_dvd_one.1 fun ⟨e, he⟩ => hyx ⟨e, by rw [hd, mul_assoc, ← he, mul_one]⟩,
hd⟩⟩,
fun ⟨hx0, d, hdu, hdx⟩ =>
⟨⟨d, hdx⟩, fun ⟨e, he⟩ =>
hdu
(isUnit_of_dvd_one
⟨e, mul_left_cancel₀ hx0 <| by conv =>
lhs
rw [he, hdx]
simp [mul_assoc]⟩)⟩⟩
section MonoidWithZero
variable [MonoidWithZero α]
theorem ne_zero_of_dvd_ne_zero {p q : α} (h₁ : q ≠ 0) (h₂ : p ∣ q) : p ≠ 0 := by
rcases h₂ with ⟨u, rfl⟩
exact left_ne_zero_of_mul h₁
theorem isPrimal_zero : IsPrimal (0 : α) :=
fun a b h ↦ ⟨a, b, dvd_rfl, dvd_rfl, (zero_dvd_iff.mp h).symm⟩
theorem IsPrimal.mul {α} [CommMonoidWithZero α] [IsCancelMulZero α] {m n : α}
(hm : IsPrimal m) (hn : IsPrimal n) : IsPrimal (m * n) := by
obtain rfl | h0 := eq_or_ne m 0; · rwa [zero_mul]
intro b c h
obtain ⟨a₁, a₂, ⟨b, rfl⟩, ⟨c, rfl⟩, rfl⟩ := hm (dvd_of_mul_right_dvd h)
rw [mul_mul_mul_comm, mul_dvd_mul_iff_left h0] at h
obtain ⟨a₁', a₂', h₁, h₂, rfl⟩ := hn h
exact ⟨a₁ * a₁', a₂ * a₂', mul_dvd_mul_left _ h₁, mul_dvd_mul_left _ h₂, mul_mul_mul_comm _ _ _ _⟩
end MonoidWithZero
section CancelCommMonoidWithZero
variable [CommMonoidWithZero α] [IsCancelMulZero α] {a b : α} {m n : ℕ}
section Subsingleton
variable [Subsingleton αˣ]
theorem dvd_antisymm : a ∣ b → b ∣ a → a = b := by
rintro ⟨c, rfl⟩ ⟨d, hcd⟩
rw [mul_assoc, eq_comm, mul_right_eq_self₀, mul_eq_one] at hcd
obtain ⟨rfl, -⟩ | rfl := hcd <;> simp
theorem dvd_antisymm' : a ∣ b → b ∣ a → b = a :=
flip dvd_antisymm
alias Dvd.dvd.antisymm := dvd_antisymm
alias Dvd.dvd.antisymm' := dvd_antisymm'
theorem eq_of_forall_dvd (h : ∀ c, a ∣ c ↔ b ∣ c) : a = b :=
((h _).2 dvd_rfl).antisymm <| (h _).1 dvd_rfl
theorem eq_of_forall_dvd' (h : ∀ c, c ∣ a ↔ c ∣ b) : a = b :=
((h _).1 dvd_rfl).antisymm <| (h _).2 dvd_rfl
end Subsingleton
lemma pow_dvd_pow_iff (ha₀ : a ≠ 0) (ha : ¬IsUnit a) : a ^ n ∣ a ^ m ↔ n ≤ m := by
constructor
· intro h
rw [← not_lt]
intro hmn
apply ha
have : a ^ m * a ∣ a ^ m * 1 := by
rw [← pow_succ, mul_one]
exact (pow_dvd_pow _ (Nat.succ_le_of_lt hmn)).trans h
rwa [mul_dvd_mul_iff_left, ← isUnit_iff_dvd_one] at this
apply pow_ne_zero m ha₀
· apply pow_dvd_pow
lemma mul_dvd_left_iff_isUnit (ha0 : a ≠ 0) : a * b ∣ a ↔ IsUnit b := by
nth_rw 2 [← mul_one a]
rw [mul_dvd_mul_iff_left ha0]
exact isUnit_iff_dvd_one.symm
lemma mul_dvd_right_iff_isUnit (ha0 : a ≠ 0) : b * a ∣ a ↔ IsUnit b := by
rw [mul_comm]
exact mul_dvd_left_iff_isUnit ha0
end CancelCommMonoidWithZero
section GroupWithZero
variable [GroupWithZero α]
/-- `∣` is not a useful definition if an inverse is available. -/
@[simp]
lemma GroupWithZero.dvd_iff {m n : α} : m ∣ n ↔ (m = 0 → n = 0) := by
refine ⟨fun ⟨a, ha⟩ hm => ?_, fun h => ?_⟩
· simp [hm, ha]
· refine ⟨m⁻¹ * n, ?_⟩
obtain rfl | hn := eq_or_ne n 0
· simp
· rw [mul_inv_cancel_left₀ (mt h hn)]
end GroupWithZero