1
+ /-
2
+ Copyright (c) 2018 Robert Y. Lewis. All rights reserved.
3
+ Released under Apache 2.0 license as described in the file LICENSE.
4
+ Authors: Robert Y. Lewis, Chris Hughes
5
+ -/
6
+ import data.nat.enat ring_theory.associated
7
+ import tactic.converter.interactive
8
+
9
+ variables {α : Type *}
10
+
11
+ open nat roption
12
+
13
+ /-- `multiplicity a b` returns the largest natural number `n` such that
14
+ `a ^ n ∣ b`, as an `enat` or natural with infinity. If `∀ n, a ^ n ∣ b`,
15
+ the it return `⊤`-/
16
+ def multiplicity [comm_semiring α] [decidable_rel ((∣) : α → α → Prop )] (a b : α) : enat :=
17
+ ⟨∃ n : ℕ, ¬a ^ (n + 1 ) ∣ b, λ h, nat.find h⟩
18
+
19
+ namespace multiplicity
20
+
21
+ section comm_semiring
22
+ variables [comm_semiring α]
23
+
24
+ @[reducible] def finite (a b : α) : Prop := ∃ n : ℕ, ¬a ^ (n + 1 ) ∣ b
25
+
26
+ lemma finite_iff_dom [decidable_rel ((∣) : α → α → Prop )] {a b : α} :
27
+ finite a b ↔ (multiplicity a b).dom := iff.rfl
28
+
29
+ lemma finite_def {a b : α} : finite a b ↔ ∃ n : ℕ, ¬a ^ (n + 1 ) ∣ b := iff.rfl
30
+
31
+ lemma not_finite_iff_forall {a b : α} : (¬ finite a b) ↔ ∀ n : ℕ, a ^ n ∣ b :=
32
+ ⟨λ h n, nat.cases_on n (one_dvd _) (by simpa [finite, classical.not_not] using h),
33
+ by simp [finite, multiplicity, classical.not_not]; tauto⟩
34
+
35
+ lemma not_unit_of_finite {a b : α} (h : finite a b) : ¬is_unit a :=
36
+ let ⟨n, hn⟩ := h in mt (is_unit_iff_forall_dvd.1 ∘ is_unit_pow (n + 1 )) $
37
+ λ h, hn (h b)
38
+
39
+ lemma ne_zero_of_finite {a b : α} (h : finite a b) : b ≠ 0 :=
40
+ let ⟨n, hn⟩ := h in λ hb, by simpa [hb] using hn
41
+
42
+ lemma finite_of_finite_mul_left {a b c : α} : finite a (b * c) → finite a c :=
43
+ λ ⟨n, hn⟩, ⟨n, λ h, hn (dvd.trans h (by simp [_root_.mul_pow]))⟩
44
+
45
+ lemma finite_of_finite_mul_right {a b c : α} : finite a (b * c) → finite a b :=
46
+ by rw mul_comm; exact finite_of_finite_mul_left
47
+
48
+ variable [decidable_rel ((∣) : α → α → Prop )]
49
+
50
+ lemma pow_dvd_of_le_multiplicity {a b : α} {k : ℕ} : (k : enat) ≤ multiplicity a b → a ^ k ∣ b :=
51
+ nat.cases_on k (λ _, one_dvd _)
52
+ (λ k ⟨h₁, h₂⟩, by_contradiction (λ hk, (nat.find_min _ (lt_of_succ_le (h₂ ⟨k, hk⟩)) hk)))
53
+
54
+ lemma pow_multiplicity_dvd {a b : α} (h : finite a b) : a ^ get (multiplicity a b) h ∣ b :=
55
+ pow_dvd_of_le_multiplicity (by rw enat.coe_get)
56
+
57
+ lemma is_greatest {a b : α} {m : ℕ} (hm : multiplicity a b < m) : ¬a ^ m ∣ b :=
58
+ λ h, have finite a b, from enat.dom_of_le_some (le_of_lt hm),
59
+ by rw [← enat.coe_get (finite_iff_dom.1 this ), enat.coe_lt_coe] at hm;
60
+ exact nat.find_spec this (dvd.trans (pow_dvd_pow _ hm) h)
61
+
62
+ lemma is_greatest' {a b : α} {m : ℕ} (h : finite a b) (hm : get (multiplicity a b) h < m) :
63
+ ¬a ^ m ∣ b :=
64
+ is_greatest (by rwa [← enat.coe_lt_coe, enat.coe_get] at hm)
65
+
66
+ lemma unique {a b : α} {k : ℕ} (hk : a ^ k ∣ b) (hsucc : ¬a ^ (k + 1 ) ∣ b) :
67
+ (k : enat) = multiplicity a b :=
68
+ le_antisymm (le_of_not_gt (λ hk', is_greatest hk' hk)) $
69
+ have finite a b, from ⟨k, hsucc⟩,
70
+ by rw [← enat.coe_get (finite_iff_dom.1 this ), enat.coe_le_coe];
71
+ exact nat.find_min' _ hsucc
72
+
73
+ lemma unique' {a b : α} {k : ℕ} (hk : a ^ k ∣ b) (hsucc : ¬ a ^ (k + 1 ) ∣ b) :
74
+ k = get (multiplicity a b) ⟨k, hsucc⟩ :=
75
+ by rw [← enat.coe_inj, enat.coe_get, unique hk hsucc]
76
+
77
+ lemma le_multiplicity_of_pow_dvd {a b : α}
78
+ {k : ℕ} (hk : a ^ k ∣ b) : (k : enat) ≤ multiplicity a b :=
79
+ le_of_not_gt $ λ hk', is_greatest hk' hk
80
+
81
+ lemma pow_dvd_iff_le_multiplicity {a b : α}
82
+ {k : ℕ} : a ^ k ∣ b ↔ (k : enat) ≤ multiplicity a b :=
83
+ ⟨le_multiplicity_of_pow_dvd, pow_dvd_of_le_multiplicity⟩
84
+
85
+ lemma eq_some_iff {a b : α} {n : ℕ} :
86
+ multiplicity a b = (n : enat) ↔ a ^ n ∣ b ∧ ¬a ^ (n + 1 ) ∣ b :=
87
+ ⟨λ h, let ⟨h₁, h₂⟩ := eq_some_iff.1 h in
88
+ h₂ ▸ ⟨pow_multiplicity_dvd _, is_greatest
89
+ (by conv_lhs {rw ← enat.coe_get h₁ }; rw [enat.coe_lt_coe]; exact lt_succ_self _)⟩,
90
+ λ h, eq_some_iff.2 ⟨⟨n, h.2 ⟩, eq.symm $ unique' h.1 h.2 ⟩⟩
91
+
92
+ lemma eq_top_iff {a b : α} :
93
+ multiplicity a b = ⊤ ↔ ∀ n : ℕ, a ^ n ∣ b :=
94
+ ⟨λ h n, nat.cases_on n (one_dvd _)
95
+ (λ n, by_contradiction (not_exists.1 (eq_none_iff'.1 h) n : _)),
96
+ λ h, eq_none_iff.2 (λ n ⟨⟨_, h₁⟩, _⟩, h₁ (h _))⟩
97
+
98
+ @[simp] protected lemma zero (a : α) : multiplicity a 0 = ⊤ :=
99
+ roption.eq_none_iff.2 (λ n ⟨⟨k, hk⟩, _⟩, hk (dvd_zero _))
100
+
101
+ lemma one_right {a : α} (ha : ¬is_unit a) : multiplicity a 1 = 0 :=
102
+ eq_some_iff.2 ⟨dvd_refl _, mt is_unit_iff_dvd_one.2 $ by simpa⟩
103
+
104
+ @[simp] lemma get_one_right {a : α} (ha : finite a 1 ) : get (multiplicity a 1 ) ha = 0 :=
105
+ get_eq_iff_eq_some.2 (eq_some_iff.2 ⟨dvd_refl _,
106
+ by simpa [is_unit_iff_dvd_one.symm] using not_unit_of_finite ha⟩)
107
+
108
+ @[simp] lemma one_left (b : α) : multiplicity 1 b = ⊤ := by simp [eq_top_iff]
109
+
110
+ @[simp] lemma multiplicity_unit {a : α} (b : α) (ha : is_unit a) : multiplicity a b = ⊤ :=
111
+ eq_top_iff.2 (λ _, is_unit_iff_forall_dvd.1 (is_unit_pow _ ha) _)
112
+
113
+ lemma multiplicity_eq_zero_of_not_dvd {a b : α} (ha : ¬a ∣ b) : multiplicity a b = 0 :=
114
+ eq_some_iff.2 (by simpa)
115
+
116
+
117
+ lemma eq_top_iff_not_finite {a b : α} : multiplicity a b = ⊤ ↔ ¬ finite a b :=
118
+ roption.eq_none_iff'
119
+
120
+ local attribute [instance, priority 0 ] classical.prop_decidable
121
+
122
+ lemma multiplicity_le_multiplicity_iff {a b c d : α} : multiplicity a b ≤ multiplicity c d ↔
123
+ (∀ n : ℕ, a ^ n ∣ b → c ^ n ∣ d) :=
124
+ ⟨λ h n hab, (pow_dvd_of_le_multiplicity (le_trans (le_multiplicity_of_pow_dvd hab) h)),
125
+ λ h, if hab : finite a b
126
+ then by rw [← enat.coe_get (finite_iff_dom.1 hab)]; exact le_multiplicity_of_pow_dvd (h _ (pow_multiplicity_dvd _))
127
+ else
128
+ have ∀ n : ℕ, c ^ n ∣ d, from λ n, h n (not_finite_iff_forall.1 hab _),
129
+ by rw [eq_top_iff_not_finite.2 hab, eq_top_iff_not_finite.2
130
+ (not_finite_iff_forall.2 this )]⟩
131
+
132
+ lemma min_le_multiplicity_add {p a b : α} :
133
+ min (multiplicity p a) (multiplicity p b) ≤ multiplicity p (a + b) :=
134
+ (le_total (multiplicity p a) (multiplicity p b)).elim
135
+ (λ h, by rw [min_eq_left h, multiplicity_le_multiplicity_iff];
136
+ exact λ n hn, dvd_add hn (multiplicity_le_multiplicity_iff.1 h n hn))
137
+ (λ h, by rw [min_eq_right h, multiplicity_le_multiplicity_iff];
138
+ exact λ n hn, dvd_add (multiplicity_le_multiplicity_iff.1 h n hn) hn)
139
+
140
+ lemma dvd_of_multiplicity_pos {a b : α} (h : (0 : enat) < multiplicity a b) : a ∣ b :=
141
+ by rw [← _root_.pow_one a]; exact pow_dvd_of_le_multiplicity (enat.pos_iff_one_le.1 h)
142
+
143
+ lemma finite_nat_iff {a b : ℕ} : finite a b ↔ (a ≠ 1 ∧ 0 < b) :=
144
+ begin
145
+ rw [← not_iff_not, not_finite_iff_forall, not_and_distrib, ne.def,
146
+ not_not, not_lt, nat.le_zero_iff],
147
+ exact ⟨λ h, or_iff_not_imp_right.2 (λ hb,
148
+ have ha : a ≠ 0 , from λ ha, by simpa [ha] using h 1 ,
149
+ by_contradiction (λ ha1 : a ≠ 1 ,
150
+ have ha_gt_one : 1 < a, from
151
+ have ∀ a : ℕ, a ≤ 1 → a ≠ 0 → a ≠ 1 → false, from dec_trivial,
152
+ lt_of_not_ge (λ ha', this a ha' ha ha1),
153
+ not_lt_of_ge (le_of_dvd (nat.pos_of_ne_zero hb) (h b))
154
+ (by simp only [nat.pow_eq_pow]; exact lt_pow_self ha_gt_one b))),
155
+ λ h, by cases h; simp *⟩
156
+ end
157
+
158
+ lemma finite_int_iff_nat_abs_finite {a b : ℤ} : finite a b ↔ finite a.nat_abs b.nat_abs :=
159
+ begin
160
+ rw [finite_def, finite_def],
161
+ conv in (a ^ _ ∣ b)
162
+ { rw [← int.nat_abs_dvd_abs_iff, int.nat_abs_pow, ← pow_eq_pow] }
163
+ end
164
+
165
+ lemma finite_int_iff {a b : ℤ} : finite a b ↔ (a.nat_abs ≠ 1 ∧ b ≠ 0 ) :=
166
+ begin
167
+ have := int.nat_abs_eq a,
168
+ have := @int.nat_abs_ne_zero_of_ne_zero b,
169
+ rw [finite_int_iff_nat_abs_finite, finite_nat_iff, nat.pos_iff_ne_zero'],
170
+ split; finish
171
+ end
172
+
173
+ instance decidable_nat : decidable_rel (λ a b : ℕ, (multiplicity a b).dom) :=
174
+ λ a b, decidable_of_iff _ finite_nat_iff.symm
175
+
176
+ instance decidable_int : decidable_rel (λ a b : ℤ, (multiplicity a b).dom) :=
177
+ λ a b, decidable_of_iff _ finite_int_iff.symm
178
+
179
+ end comm_semiring
180
+
181
+ section comm_ring
182
+
183
+ variables [comm_ring α] [decidable_rel ((∣) : α → α → Prop )]
184
+
185
+ local attribute [instance, priority 0 ] classical.prop_decidable
186
+
187
+ @[simp] protected lemma neg (a b : α) : multiplicity a (-b) = multiplicity a b :=
188
+ roption.ext' (by simp only [multiplicity]; conv in (_ ∣ - _) {rw dvd_neg})
189
+ (λ h₁ h₂, enat.coe_inj.1 (by rw [enat.coe_get]; exact
190
+ eq.symm (unique ((dvd_neg _ _).2 (pow_multiplicity_dvd _))
191
+ (mt (dvd_neg _ _).1 (is_greatest' _ (lt_succ_self _))))))
192
+
193
+ end comm_ring
194
+
195
+ section integral_domain
196
+
197
+ variables [integral_domain α] [decidable_rel ((∣) : α → α → Prop )]
198
+
199
+ @[simp] lemma multiplicity_self {a : α} (ha : ¬is_unit a) (ha0 : a ≠ 0 ) :
200
+ multiplicity a a = 1 :=
201
+ eq_some_iff.2 ⟨by simp, λ ⟨b, hb⟩, ha (is_unit_iff_dvd_one.2
202
+ ⟨b, (domain.mul_left_inj ha0).1 $ by clear _fun_match;
203
+ simpa [_root_.pow_succ, mul_assoc] using hb⟩)⟩
204
+
205
+ @[simp] lemma get_multiplicity_self {a : α} (ha : finite a a) :
206
+ get (multiplicity a a) ha = 1 :=
207
+ roption.get_eq_iff_eq_some.2 (eq_some_iff.2
208
+ ⟨by simp, λ ⟨b, hb⟩,
209
+ by rw [← mul_one a, _root_.pow_add, _root_.pow_one, mul_assoc, mul_assoc,
210
+ domain.mul_left_inj (ne_zero_of_finite ha)] at hb;
211
+ exact mt is_unit_iff_dvd_one.2 (not_unit_of_finite ha)
212
+ ⟨b, by clear _fun_match; simp * at *⟩⟩)
213
+
214
+ lemma finite_mul_aux {p : α} (hp : prime p) : ∀ {n m : ℕ} {a b : α},
215
+ ¬p ^ (n + 1 ) ∣ a → ¬p ^ (m + 1 ) ∣ b → ¬p ^ (n + m + 1 ) ∣ a * b
216
+ | n m := λ a b ha hb ⟨s, hs⟩,
217
+ have p ∣ a * b, from ⟨p ^ (n + m) * s,
218
+ by simp [hs, _root_.pow_add, mul_comm, mul_assoc, mul_left_comm]⟩,
219
+ (hp.2 .2 a b this ).elim
220
+ (λ ⟨x, hx⟩, have hn0 : 0 < n,
221
+ from nat.pos_of_ne_zero (λ hn0, by clear _fun_match _fun_match; simpa [hx, hn0] using ha),
222
+ have wf : (n - 1 ) < n, from nat.sub_lt_self hn0 dec_trivial,
223
+ have hpx : ¬ p ^ (n - 1 + 1 ) ∣ x,
224
+ from λ ⟨y, hy⟩, ha (hx.symm ▸ ⟨y, (domain.mul_left_inj hp.1 ).1
225
+ $ by rw [nat.sub_add_cancel hn0] at hy;
226
+ simp [hy, _root_.pow_add, mul_comm, mul_assoc, mul_left_comm]⟩),
227
+ have 1 ≤ n + m, from le_trans hn0 (le_add_right n m),
228
+ finite_mul_aux hpx hb ⟨s, (domain.mul_left_inj hp.1 ).1 begin
229
+ rw [← nat.sub_add_comm hn0, nat.sub_add_cancel this ],
230
+ clear _fun_match _fun_match finite_mul_aux,
231
+ simp [*, mul_comm, mul_assoc, mul_left_comm, _root_.pow_add] at *
232
+ end ⟩)
233
+ (λ ⟨x, hx⟩, have hm0 : 0 < m,
234
+ from nat.pos_of_ne_zero (λ hm0, by clear _fun_match _fun_match; simpa [hx, hm0] using hb),
235
+ have wf : (m - 1 ) < m, from nat.sub_lt_self hm0 dec_trivial,
236
+ have hpx : ¬ p ^ (m - 1 + 1 ) ∣ x,
237
+ from λ ⟨y, hy⟩, hb (hx.symm ▸ ⟨y, (domain.mul_left_inj hp.1 ).1
238
+ $ by rw [nat.sub_add_cancel hm0] at hy;
239
+ simp [hy, _root_.pow_add, mul_comm, mul_assoc, mul_left_comm]⟩),
240
+ finite_mul_aux ha hpx ⟨s, (domain.mul_left_inj hp.1 ).1 begin
241
+ rw [add_assoc, nat.sub_add_cancel hm0],
242
+ clear _fun_match _fun_match finite_mul_aux,
243
+ simp [*, mul_comm, mul_assoc, mul_left_comm, _root_.pow_add] at *
244
+ end ⟩)
245
+
246
+ lemma finite_mul {p a b : α} (hp : prime p) : finite p a → finite p b → finite p (a * b) :=
247
+ λ ⟨n, hn⟩ ⟨m, hm⟩, ⟨n + m, finite_mul_aux hp hn hm⟩
248
+
249
+ lemma finite_mul_iff {p a b : α} (hp : prime p) : finite p (a * b) ↔ finite p a ∧ finite p b :=
250
+ ⟨λ h, ⟨finite_of_finite_mul_right h, finite_of_finite_mul_left h⟩,
251
+ λ h, finite_mul hp h.1 h.2 ⟩
252
+
253
+ lemma finite_pow {p a : α} (hp : prime p) : Π {k : ℕ} (ha : finite p a), finite p (a ^ k)
254
+ | 0 ha := ⟨0 , by simp [mt is_unit_iff_dvd_one.2 hp.2 .1 ]⟩
255
+ | (k+1 ) ha := by rw [_root_.pow_succ]; exact finite_mul hp ha (finite_pow ha)
256
+
257
+ protected lemma mul' {p a b : α} (hp : prime p)
258
+ (h : (multiplicity p (a * b)).dom) :
259
+ get (multiplicity p (a * b)) h =
260
+ get (multiplicity p a) ((finite_mul_iff hp).1 h).1 +
261
+ get (multiplicity p b) ((finite_mul_iff hp).1 h).2 :=
262
+ have hdiva : p ^ get (multiplicity p a) ((finite_mul_iff hp).1 h).1 ∣ a, from pow_multiplicity_dvd _,
263
+ have hdivb : p ^ get (multiplicity p b) ((finite_mul_iff hp).1 h).2 ∣ b, from pow_multiplicity_dvd _,
264
+ have hpoweq : p ^ (get (multiplicity p a) ((finite_mul_iff hp).1 h).1 +
265
+ get (multiplicity p b) ((finite_mul_iff hp).1 h).2 ) =
266
+ p ^ get (multiplicity p a) ((finite_mul_iff hp).1 h).1 *
267
+ p ^ get (multiplicity p b) ((finite_mul_iff hp).1 h).2 ,
268
+ by simp [_root_.pow_add],
269
+ have hdiv : p ^ (get (multiplicity p a) ((finite_mul_iff hp).1 h).1 +
270
+ get (multiplicity p b) ((finite_mul_iff hp).1 h).2 ) ∣ a * b,
271
+ by rw [hpoweq]; apply mul_dvd_mul; assumption,
272
+ have hsucc : ¬p ^ ((get (multiplicity p a) ((finite_mul_iff hp).1 h).1 +
273
+ get (multiplicity p b) ((finite_mul_iff hp).1 h).2 ) + 1 ) ∣ a * b,
274
+ from λ h, not_or (is_greatest' _ (lt_succ_self _)) (is_greatest' _ (lt_succ_self _))
275
+ (succ_dvd_or_succ_dvd_of_succ_sum_dvd_mul hp (by convert hdiva)
276
+ (by convert hdivb) h),
277
+ by rw [← enat.coe_inj, enat.coe_get, eq_some_iff];
278
+ exact ⟨hdiv, hsucc⟩
279
+
280
+ local attribute [instance, priority 0 ] classical.prop_decidable
281
+
282
+ protected lemma mul {p a b : α} (hp : prime p) :
283
+ multiplicity p (a * b) = multiplicity p a + multiplicity p b :=
284
+ if h : finite p a ∧ finite p b then
285
+ by rw [← enat.coe_get (finite_iff_dom.1 h.1 ), ← enat.coe_get (finite_iff_dom.1 h.2 ),
286
+ ← enat.coe_get (finite_iff_dom.1 (finite_mul hp h.1 h.2 )),
287
+ ← enat.coe_add, enat.coe_inj, multiplicity.mul' hp]; refl
288
+ else begin
289
+ rw [eq_top_iff_not_finite.2 (mt (finite_mul_iff hp).1 h)],
290
+ cases not_and_distrib.1 h with h h;
291
+ simp [eq_top_iff_not_finite.2 h]
292
+ end
293
+
294
+ protected lemma pow' {p a : α} (hp : prime p) (ha : finite p a) : ∀ {k : ℕ},
295
+ get (multiplicity p (a ^ k)) (finite_pow hp ha) = k * get (multiplicity p a) ha
296
+ | 0 := by dsimp [_root_.pow_zero]; simp [one_right hp.2 .1 ]; refl
297
+ | (k+1 ) := by dsimp only [_root_.pow_succ];
298
+ erw [multiplicity.mul' hp, pow', add_mul, one_mul, add_comm]
299
+
300
+ lemma pow {p a : α} (hp : prime p) : ∀ {k : ℕ},
301
+ multiplicity p (a ^ k) = add_monoid.smul k (multiplicity p a)
302
+ | 0 := by simp [one_right hp.2 .1 ]
303
+ | (succ k) := by simp [_root_.pow_succ, succ_smul, pow, multiplicity.mul hp]
304
+
305
+ end integral_domain
306
+
307
+ end multiplicity
308
+
309
+ section nat
310
+ open multiplicity
311
+
312
+ lemma multiplicity_eq_zero_of_coprime {p a b : ℕ} (hp : p ≠ 1 )
313
+ (hle : multiplicity p a ≤ multiplicity p b)
314
+ (hab : nat.coprime a b) : multiplicity p a = 0 :=
315
+ begin
316
+ rw [multiplicity_le_multiplicity_iff] at hle,
317
+ rw [← le_zero_iff_eq, ← not_lt, enat.pos_iff_one_le, ← enat.coe_one,
318
+ ← pow_dvd_iff_le_multiplicity],
319
+ assume h,
320
+ have := nat.dvd_gcd h (hle _ h),
321
+ rw [coprime.gcd_eq_one hab, nat.dvd_one, _root_.pow_one] at this ,
322
+ exact hp this
323
+ end
324
+
325
+ end nat
0 commit comments