Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit 5080dd5

Browse files
Smaug123jcommelin
andcommitted
feat(data/padics/padic_norm): lemmas about padic_val_nat (#3230)
Collection of lemmas about `padic_val_nat`, culminating in `lemma prod_pow_prime_padic_val_nat : ∀ (n : nat) (s : n ≠ 0) (m : nat) (pr : n < m), ∏ p in finset.filter nat.prime (finset.range m), pow p (padic_val_nat p n) = n`. Co-authored-by: Johan Commelin <johan@commelin.net>
1 parent 84d4ea7 commit 5080dd5

File tree

7 files changed

+223
-0
lines changed

7 files changed

+223
-0
lines changed

src/algebra/big_operators.lean

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,21 @@ lemma sum_range_one {δ : Type*} [add_comm_monoid δ] (f : ℕ → δ) :
654654

655655
attribute [to_additive finset.sum_range_one] prod_range_one
656656

657+
open multiset
658+
lemma prod_multiset_count [decidable_eq α] [comm_monoid α] (s : multiset α) :
659+
s.prod = ∏ m in s.to_finset, m ^ (s.count m) :=
660+
begin
661+
apply s.induction_on, { rw [prod_zero, to_finset_zero, finset.prod_empty] },
662+
intros a s ih, by_cases has : a ∈ s.to_finset,
663+
{ rw [prod_cons, to_finset_cons, finset.insert_eq_of_mem has, ih,
664+
← finset.insert_erase has, finset.prod_insert (finset.not_mem_erase _ _),
665+
finset.prod_insert (finset.not_mem_erase _ _), ← mul_assoc, count_cons_self, pow_succ],
666+
congr' 1, refine finset.prod_congr rfl (λ x hx, _), rw [count_cons_of_ne (finset.ne_of_mem_erase hx)] },
667+
rw [prod_cons, to_finset_cons, finset.prod_insert has, count_cons_self],
668+
rw mem_to_finset at has, rw [count_eq_zero_of_not_mem has, pow_one], congr' 1,
669+
rw ih, refine finset.prod_congr rfl (λ x hx, _), rw mem_to_finset at hx, rw count_cons_of_ne,
670+
rintro rfl, exact has hx
671+
end
657672

658673
/-- To prove a property of a product, it suffices to prove that the property is multiplicative and holds on factors.
659674
-/

src/algebra/char_zero.lean

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,16 @@ not_congr cast_eq_zero
6363
lemma cast_add_one_ne_zero (n : ℕ) : (n + 1 : α) ≠ 0 :=
6464
by exact_mod_cast n.succ_ne_zero
6565

66+
@[simp, norm_cast]
67+
theorem cast_dvd_char_zero {α : Type*} [field α] [char_zero α] {m n : ℕ}
68+
(n_dvd : n ∣ m) : ((m / n : ℕ) : α) = m / n :=
69+
begin
70+
by_cases hn : n = 0,
71+
{ subst hn,
72+
simp },
73+
{ exact cast_dvd n_dvd (cast_ne_zero.mpr hn), },
74+
end
75+
6676
end nat
6777

6878
@[field_simps] lemma two_ne_zero' {α : Type*} [add_monoid α] [has_one α] [char_zero α] : (2:α) ≠ 0 :=

src/data/nat/basic.lean

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1535,6 +1535,24 @@ begin
15351535
cc
15361536
end
15371537

1538+
@[simp]
1539+
lemma div_div_div_eq_div : ∀ {a b c : ℕ} (dvd : b ∣ a) (dvd2 : a ∣ c), (c / (a / b)) / b = c / a
1540+
| 0 _ := by simp
1541+
| (a + 1) 0 := λ _ dvd _, by simpa using dvd
1542+
| (a + 1) (c + 1) :=
1543+
have a_split : a + 10 := succ_ne_zero a,
1544+
have c_split : c + 10 := succ_ne_zero c,
1545+
λ b dvd dvd2,
1546+
begin
1547+
rcases dvd2 with ⟨k, rfl⟩,
1548+
rcases dvd with ⟨k2, pr⟩,
1549+
have k2_nonzero : k2 ≠ 0 := λ k2_zero, by simpa [k2_zero] using pr,
1550+
rw [nat.mul_div_cancel_left k (nat.pos_of_ne_zero a_split), pr,
1551+
nat.mul_div_cancel_left k2 (nat.pos_of_ne_zero c_split), nat.mul_comm ((c + 1) * k2) k,
1552+
←nat.mul_assoc k (c + 1) k2, nat.mul_div_cancel _ (nat.pos_of_ne_zero k2_nonzero),
1553+
nat.mul_div_cancel _ (nat.pos_of_ne_zero c_split)],
1554+
end
1555+
15381556
lemma pow_dvd_of_le_of_pow_dvd {p m n k : ℕ} (hmn : m ≤ n) (hdiv : p ^ n ∣ k) : p ^ m ∣ k :=
15391557
have p ^ m ∣ p ^ n, from pow_dvd_pow _ hmn,
15401558
dvd_trans this hdiv

src/data/nat/cast.lean

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,14 @@ eq_sub_of_add_eq $ by rw [← cast_add, nat.sub_add_cancel h]
9898
| (n+1) := (cast_add _ _).trans $
9999
show ((m * n : ℕ) : α) + m = m * (n + 1), by rw [cast_mul n, left_distrib, mul_one]
100100

101+
@[simp] theorem cast_dvd {α : Type*} [field α] {m n : ℕ} (n_dvd : n ∣ m) (n_nonzero : (n:α) ≠ 0) : ((m / n : ℕ) : α) = m / n :=
102+
begin
103+
rcases n_dvd with ⟨k, rfl⟩,
104+
have : n ≠ 0, {rintro rfl, simpa using n_nonzero},
105+
rw nat.mul_div_cancel_left _ (nat.pos_iff_ne_zero.2 this),
106+
rw [nat.cast_mul, mul_div_cancel_left _ n_nonzero],
107+
end
108+
101109
/-- `coe : ℕ → α` as a `ring_hom` -/
102110
def cast_ring_hom (α : Type*) [semiring α] : ℕ →+* α :=
103111
{ to_fun := coe,

src/data/nat/gcd.lean

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,20 @@ H.coprime_dvd_right (dvd_mul_left _ _)
266266
theorem coprime.coprime_mul_right_right {k m n : ℕ} (H : coprime m (n * k)) : coprime m n :=
267267
H.coprime_dvd_right (dvd_mul_right _ _)
268268

269+
theorem coprime.coprime_div_left {m n a : ℕ} (cmn : coprime m n) (dvd : a ∣ m) : coprime (m / a) n :=
270+
begin
271+
by_cases a_split : (a = 0),
272+
{ subst a_split,
273+
rw zero_dvd_iff at dvd,
274+
simpa [dvd] using cmn, },
275+
{ rcases dvd with ⟨k, rfl⟩,
276+
rw nat.mul_div_cancel_left _ (nat.pos_of_ne_zero a_split),
277+
exact coprime.coprime_mul_left cmn, },
278+
end
279+
280+
theorem coprime.coprime_div_right {m n a : ℕ} (cmn : coprime m n) (dvd : a ∣ n) : coprime m (n / a) :=
281+
(coprime.coprime_div_left cmn.symm dvd).symm
282+
269283
lemma coprime_mul_iff_left {k m n : ℕ} : coprime (m * n) k ↔ coprime m k ∧ coprime n k :=
270284
⟨λ h, ⟨coprime.coprime_mul_right h, coprime.coprime_mul_left h⟩,
271285
λ ⟨h, _⟩, by rwa [coprime, coprime.gcd_mul_left_cancel n h]⟩

src/data/nat/prime.lean

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@ theorem dvd_prime {p m : ℕ} (pp : prime p) : m ∣ p ↔ m = 1 ∨ m = p :=
117117
theorem dvd_prime_two_le {p m : ℕ} (pp : prime p) (H : 2 ≤ m) : m ∣ p ↔ m = p :=
118118
(dvd_prime pp).trans $ or_iff_right_of_imp $ not.elim $ ne_of_gt H
119119

120+
theorem prime_dvd_prime_iff_eq {p q : ℕ} (pp : p.prime) (qp : q.prime) : p ∣ q ↔ p = q :=
121+
dvd_prime_two_le qp (prime.two_le pp)
122+
120123
theorem prime.not_dvd_one {p : ℕ} (pp : prime p) : ¬ p ∣ 1
121124
| d := (not_le_of_gt pp.one_lt) $ le_of_dvd dec_trivial d
122125

@@ -375,6 +378,10 @@ begin
375378
{ simp only [this, nat.factors, nat.div_self (nat.prime.pos hp)], },
376379
end
377380

381+
/-- `factors` can be constructed inductively by extracting `min_fac`, for sufficiently large `n`. -/
382+
lemma factors_add_two (n : ℕ) :
383+
factors (n+2) = (min_fac (n+2)) :: (factors ((n+2) / (min_fac (n+2)))) := rfl
384+
378385
theorem prime.coprime_iff_not_dvd {p n : ℕ} (pp : prime p) : coprime p n ↔ ¬ p ∣ n :=
379386
⟨λ co d, pp.not_dvd_one $ co.dvd_of_dvd_mul_left (by simp [d]),
380387
λ nd, coprime_of_dvd $ λ m m2 mp, ((dvd_prime_two_le pp m2).1 mp).symm ▸ nd⟩

src/data/padics/padic_norm.lean

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import algebra.gcd_domain
77
import algebra.field_power
88
import ring_theory.multiplicity
99
import data.real.cau_seq
10+
import tactic.ring_exp
11+
import tactic.basic
1012

1113
/-!
1214
# p-adic norm
@@ -157,6 +159,24 @@ begin
157159
using padic_val_rat_def p n_nonzero,
158160
end
159161

162+
lemma one_le_padic_val_nat_of_dvd {n p : nat} [prime : fact p.prime] (nonzero : n ≠ 0) (div : p ∣ n) :
163+
1 ≤ padic_val_nat p n :=
164+
begin
165+
rw @padic_val_nat_def _ prime _ nonzero,
166+
let one_le_mul : _ ≤ multiplicity p n :=
167+
@multiplicity.le_multiplicity_of_pow_dvd _ _ _ p n 1 (begin norm_num, exact div end),
168+
simp only [enat.coe_one] at one_le_mul,
169+
rcases one_le_mul with ⟨_, q⟩,
170+
dsimp at q,
171+
solve_by_elim,
172+
end
173+
174+
@[simp]
175+
lemma padic_val_nat_zero (m : nat) : padic_val_nat m 0 = 0 := by simpa
176+
177+
@[simp]
178+
lemma padic_val_nat_one (m : nat) : padic_val_nat m 1 = 0 := by simp [padic_val_nat]
179+
160180
end padic_val_nat
161181

162182
namespace padic_val_rat
@@ -297,6 +317,137 @@ theorem min_le_padic_val_rat_add {q r : ℚ}
297317

298318
end padic_val_rat
299319

320+
namespace padic_val_nat
321+
322+
/--
323+
A rewrite lemma for `padic_val_nat p (q * r)` with conditions `q ≠ 0`, `r ≠ 0`.
324+
-/
325+
protected lemma mul (p : ℕ) [p_prime : fact p.prime] {q r : ℕ} (hq : q ≠ 0) (hr : r ≠ 0) :
326+
padic_val_nat p (q * r) = padic_val_nat p q + padic_val_nat p r :=
327+
begin
328+
apply int.coe_nat_inj,
329+
simp only [padic_val_rat_of_nat, nat.cast_mul],
330+
rw padic_val_rat.mul,
331+
norm_cast,
332+
exact cast_ne_zero.mpr hq,
333+
exact cast_ne_zero.mpr hr,
334+
end
335+
336+
/--
337+
Dividing out by a prime factor reduces the padic_val_nat by 1.
338+
-/
339+
protected lemma div {p : ℕ} [p_prime : fact p.prime] {b : ℕ} (dvd : p ∣ b) :
340+
(padic_val_nat p (b / p)) = (padic_val_nat p b) - 1 :=
341+
begin
342+
by_cases b_split : (b = 0),
343+
{ simp [b_split], },
344+
{ have split_frac : padic_val_rat p (b / p) = padic_val_rat p b - padic_val_rat p p :=
345+
padic_val_rat.div p (nat.cast_ne_zero.mpr b_split) (nat.cast_ne_zero.mpr (nat.prime.ne_zero p_prime)),
346+
rw padic_val_rat.padic_val_rat_self (nat.prime.one_lt p_prime) at split_frac,
347+
have r : 1 ≤ padic_val_nat p b := one_le_padic_val_nat_of_dvd b_split dvd,
348+
exact_mod_cast split_frac, }
349+
end
350+
351+
end padic_val_nat
352+
353+
section padic_val_nat
354+
355+
/--
356+
If a prime doesn't appear in `n`, `padic_val_nat p n` is `0`.
357+
-/
358+
lemma padic_val_nat_of_not_dvd {p : ℕ} [fact p.prime] {n : ℕ} (not_dvd : ¬(p ∣ n)) :
359+
padic_val_nat p n = 0 :=
360+
begin
361+
by_cases hn : n = 0,
362+
{ subst hn, simp at not_dvd, trivial, },
363+
{ rw padic_val_nat_def hn,
364+
exact (@multiplicity.unique' _ _ _ p n 0 (by simp) (by simpa using not_dvd)).symm,
365+
assumption, },
366+
end
367+
368+
lemma padic_val_nat_primes {p q : ℕ} [p_prime : fact p.prime] [q_prime : fact q.prime] (neq : p ≠ q) :
369+
padic_val_nat p q = 0 :=
370+
@padic_val_nat_of_not_dvd p p_prime q $ (not_congr (iff.symm (prime_dvd_prime_iff_eq p_prime q_prime))).mp neq
371+
372+
protected lemma padic_val_nat.div' {p : ℕ} [p_prime : fact p.prime] :
373+
∀ {m : ℕ} (cpm : coprime p m) {b : ℕ} (dvd : m ∣ b), padic_val_nat p (b / m) = padic_val_nat p b
374+
| 0 := λ cpm b dvd, by { rw zero_dvd_iff at dvd, rw [dvd, nat.zero_div], }
375+
| (n + 1) :=
376+
λ cpm b dvd,
377+
begin
378+
rcases dvd with ⟨c, rfl⟩,
379+
rw [mul_div_right c (nat.succ_pos _)],by_cases hc : c = 0,
380+
{ rw [hc, mul_zero] },
381+
{ rw padic_val_nat.mul,
382+
{ suffices : ¬ p ∣ (n+1),
383+
{ rw [padic_val_nat_of_not_dvd this, zero_add] },
384+
contrapose! cpm,
385+
exact p_prime.dvd_iff_not_coprime.mp cpm },
386+
{ exact nat.succ_ne_zero _ },
387+
{ exact hc } },
388+
end
389+
390+
lemma padic_val_nat_eq_factors_count (p : ℕ) [hp : fact p.prime] :
391+
∀ (n : ℕ), padic_val_nat p n = (factors n).count p
392+
| 0 := rfl
393+
| 1 := by { rw padic_val_nat_one, refl }
394+
| (m + 2) :=
395+
let n := m + 2 in
396+
let q := min_fac n in
397+
have hq : fact q.prime := min_fac_prime (show m + 21, by linarith),
398+
have wf : n / q < n := nat.div_lt_self (nat.succ_pos _) hq.one_lt,
399+
begin
400+
rw factors_add_two,
401+
show padic_val_nat p n = list.count p (q :: (factors (n / q))),
402+
rw [list.count_cons', ← padic_val_nat_eq_factors_count],
403+
split_ifs with h,
404+
have p_dvd_n : p ∣ n,
405+
{ have: q ∣ n := nat.min_fac_dvd n,
406+
cc },
407+
{ rw [←h, padic_val_nat.div],
408+
{ have: 1 ≤ padic_val_nat p n := one_le_padic_val_nat_of_dvd (by linarith) p_dvd_n,
409+
exact (nat.sub_eq_iff_eq_add this).mp rfl, },
410+
{ exact p_dvd_n, }, },
411+
{ suffices : p.coprime q,
412+
{ rw [padic_val_nat.div' this (min_fac_dvd n), add_zero], },
413+
rwa nat.coprime_primes hp hq, },
414+
end
415+
416+
open_locale big_operators
417+
418+
lemma prod_pow_prime_padic_val_nat (n : nat) (hn : n ≠ 0) (m : nat) (pr : n < m) :
419+
∏ p in finset.filter nat.prime (finset.range m), p ^ (padic_val_nat p n) = n :=
420+
begin
421+
rw ← nat.pos_iff_ne_zero at hn,
422+
have H : (factors n : multiset ℕ).prod = n,
423+
{ rw [multiset.coe_prod, prod_factors hn], },
424+
rw finset.prod_multiset_count at H,
425+
conv_rhs { rw ← H, },
426+
refine finset.prod_bij_ne_one (λ p hp hp', p) _ _ _ _,
427+
{ rintro p hp hpn,
428+
rw [finset.mem_filter, finset.mem_range] at hp,
429+
haveI Hp : fact p.prime := hp.2,
430+
rw [multiset.mem_to_finset, multiset.mem_coe, mem_factors_iff_dvd hn Hp],
431+
contrapose! hpn,
432+
rw [padic_val_nat_of_not_dvd hpn, nat.pow_zero], },
433+
{ intros, assumption },
434+
{ intros p hp hpn,
435+
rw [multiset.mem_to_finset, multiset.mem_coe] at hp,
436+
haveI Hp : fact p.prime := mem_factors hp,
437+
simp only [exists_prop, ne.def, finset.mem_filter, finset.mem_range],
438+
refine ⟨p, ⟨_, Hp⟩, ⟨_, rfl⟩⟩,
439+
{ rw mem_factors_iff_dvd hn Hp at hp, exact lt_of_le_of_lt (le_of_dvd hn hp) pr },
440+
{ rw padic_val_nat_eq_factors_count,
441+
simp only [pow_eq_pow, ne.def, multiset.coe_count] at hpn,
442+
convert hpn } },
443+
{ intros p hp hpn,
444+
rw [finset.mem_filter, finset.mem_range] at hp,
445+
haveI Hp : fact p.prime := hp.2,
446+
rw [padic_val_nat_eq_factors_count, multiset.coe_count, pow_eq_pow] }
447+
end
448+
449+
end padic_val_nat
450+
300451
/--
301452
If `q ≠ 0`, the p-adic norm of a rational `q` is `p ^ (-(padic_val_rat p q))`.
302453
If `q = 0`, the p-adic norm of `q` is 0.

0 commit comments

Comments
 (0)