Skip to content

Commit 9c6f795

Browse files
feat: port Algebra.BigOperators.Associated (#1943)
Co-authored-by: Ruben Van de Velde <65514131+Ruben-VandeVelde@users.noreply.github.com>
1 parent 29ffa06 commit 9c6f795

File tree

2 files changed

+194
-0
lines changed

2 files changed

+194
-0
lines changed

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import Mathlib.Algebra.Abs
22
import Mathlib.Algebra.Associated
3+
import Mathlib.Algebra.BigOperators.Associated
34
import Mathlib.Algebra.BigOperators.Basic
45
import Mathlib.Algebra.BigOperators.Finprod
56
import Mathlib.Algebra.BigOperators.Finsupp
Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
/-
2+
Copyright (c) 2018 Johannes Hölzl. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Johannes Hölzl, Jens Wagemaker, Anne Baanen
5+
6+
! This file was ported from Lean 3 source module algebra.big_operators.associated
7+
! leanprover-community/mathlib commit f7fc89d5d5ff1db2d1242c7bb0e9062ce47ef47c
8+
! Please do not edit these lines, except to modify the commit id
9+
! if you have ported upstream changes.
10+
-/
11+
import Mathlib.Algebra.Associated
12+
import Mathlib.Algebra.BigOperators.Finsupp
13+
14+
/-!
15+
# Products of associated, prime, and irreducible elements.
16+
17+
This file contains some theorems relating definitions in `Algebra.Associated`
18+
and products of multisets, finsets, and finsupps.
19+
20+
-/
21+
22+
23+
variable {α β γ δ : Type _}
24+
25+
-- the same local notation used in `Algebra.Associated`
26+
local infixl:50 " ~ᵤ " => Associated
27+
28+
open BigOperators
29+
30+
namespace Prime
31+
32+
variable [CommMonoidWithZero α] {p : α} (hp : Prime p)
33+
34+
theorem exists_mem_multiset_dvd {s : Multiset α} : p ∣ s.prod → ∃ a ∈ s, p ∣ a :=
35+
Multiset.induction_on s (fun h => (hp.not_dvd_one h).elim) fun a s ih h =>
36+
have : p ∣ a * s.prod := by simpa using h
37+
match hp.dvd_or_dvd this with
38+
| Or.inl h => ⟨a, Multiset.mem_cons_self a s, h⟩
39+
| Or.inr h =>
40+
let ⟨a, has, h⟩ := ih h
41+
⟨a, Multiset.mem_cons_of_mem has, h⟩
42+
#align prime.exists_mem_multiset_dvd Prime.exists_mem_multiset_dvd
43+
44+
theorem exists_mem_multiset_map_dvd {s : Multiset β} {f : β → α} :
45+
p ∣ (s.map f).prod → ∃ a ∈ s, p ∣ f a := fun h => by
46+
simpa only [exists_prop, Multiset.mem_map, exists_exists_and_eq_and] using
47+
hp.exists_mem_multiset_dvd h
48+
#align prime.exists_mem_multiset_map_dvd Prime.exists_mem_multiset_map_dvd
49+
50+
theorem exists_mem_finset_dvd {s : Finset β} {f : β → α} : p ∣ s.prod f → ∃ i ∈ s, p ∣ f i :=
51+
hp.exists_mem_multiset_map_dvd
52+
#align prime.exists_mem_finset_dvd Prime.exists_mem_finset_dvd
53+
54+
end Prime
55+
56+
theorem exists_associated_mem_of_dvd_prod [CancelCommMonoidWithZero α] {p : α} (hp : Prime p)
57+
{s : Multiset α} : (∀ r ∈ s, Prime r) → p ∣ s.prod → ∃ q ∈ s, p ~ᵤ q :=
58+
Multiset.induction_on s (by simp [mt isUnit_iff_dvd_one.2 hp.not_unit]) fun a s ih hs hps =>
59+
by
60+
rw [Multiset.prod_cons] at hps
61+
cases' hp.dvd_or_dvd hps with h h
62+
· have hap := hs a (Multiset.mem_cons.2 (Or.inl rfl))
63+
exact ⟨a, Multiset.mem_cons_self a _, hp.associated_of_dvd hap h⟩
64+
· rcases ih (fun r hr => hs _ (Multiset.mem_cons.2 (Or.inr hr))) h with ⟨q, hq₁, hq₂⟩
65+
exact ⟨q, Multiset.mem_cons.2 (Or.inr hq₁), hq₂⟩
66+
#align exists_associated_mem_of_dvd_prod exists_associated_mem_of_dvd_prod
67+
68+
theorem Multiset.prod_primes_dvd [CancelCommMonoidWithZero α]
69+
[∀ a : α, DecidablePred (Associated a)] {s : Multiset α} (n : α) (h : ∀ a ∈ s, Prime a)
70+
(div : ∀ a ∈ s, a ∣ n) (uniq : ∀ a, s.countp (Associated a) ≤ 1) : s.prod ∣ n := by
71+
induction' s using Multiset.induction_on with a s induct n primes divs generalizing n
72+
· simp only [Multiset.prod_zero, one_dvd]
73+
· rw [Multiset.prod_cons]
74+
obtain ⟨k, rfl⟩ : a ∣ n := div a (Multiset.mem_cons_self a s)
75+
apply mul_dvd_mul_left a
76+
refine induct _ (fun a ha => h a (Multiset.mem_cons_of_mem ha)) (fun b b_in_s => ?_)
77+
fun a => (Multiset.countp_le_of_le _ (Multiset.le_cons_self _ _)).trans (uniq a)
78+
· have b_div_n := div b (Multiset.mem_cons_of_mem b_in_s)
79+
have a_prime := h a (Multiset.mem_cons_self a s)
80+
have b_prime := h b (Multiset.mem_cons_of_mem b_in_s)
81+
refine' (b_prime.dvd_or_dvd b_div_n).resolve_left fun b_div_a => _
82+
have assoc := b_prime.associated_of_dvd a_prime b_div_a
83+
have := uniq a
84+
rw [Multiset.countp_cons_of_pos _ (Associated.refl _), Nat.succ_le_succ_iff, ← not_lt,
85+
Multiset.countp_pos] at this
86+
exact this ⟨b, b_in_s, assoc.symm⟩
87+
#align multiset.prod_primes_dvd Multiset.prod_primes_dvd
88+
89+
theorem Finset.prod_primes_dvd [CancelCommMonoidWithZero α] [Unique αˣ] {s : Finset α} (n : α)
90+
(h : ∀ a ∈ s, Prime a) (div : ∀ a ∈ s, a ∣ n) : (∏ p in s, p) ∣ n := by
91+
classical
92+
exact
93+
Multiset.prod_primes_dvd n (by simpa only [Multiset.map_id', Finset.mem_def] using h)
94+
(by simpa only [Multiset.map_id', Finset.mem_def] using div)
95+
(by
96+
-- POrting note: was
97+
-- `simp only [Multiset.map_id', associated_eq_eq, Multiset.countp_eq_card_filter, ←
98+
-- Multiset.count_eq_card_filter_eq, ← Multiset.nodup_iff_count_le_one, s.nodup]`
99+
intro a
100+
simp only [Multiset.map_id', associated_eq_eq, Multiset.countp_eq_card_filter]
101+
change Multiset.card (Multiset.filter (fun b => a = b) s.val) ≤ 1
102+
simp_rw [@eq_comm _ a]
103+
apply le_of_eq_of_le (Multiset.count_eq_card_filter_eq _ _).symm
104+
apply Multiset.nodup_iff_count_le_one.mp
105+
exact s.nodup)
106+
#align finset.prod_primes_dvd Finset.prod_primes_dvd
107+
108+
namespace Associates
109+
110+
section CommMonoid
111+
112+
variable [CommMonoid α]
113+
114+
theorem prod_mk {p : Multiset α} : (p.map Associates.mk).prod = Associates.mk p.prod :=
115+
Multiset.induction_on p (by simp) fun a s ih => by simp [ih, Associates.mk_mul_mk]
116+
#align associates.prod_mk Associates.prod_mk
117+
118+
theorem finset_prod_mk {p : Finset β} {f : β → α} :
119+
(∏ i in p, Associates.mk (f i)) = Associates.mk (∏ i in p, f i) := by
120+
-- Porting note: added
121+
have : (fun i => Associates.mk (f i)) = Associates.mk ∘ f :=
122+
funext <| fun x => Function.comp_apply
123+
rw [Finset.prod_eq_multiset_prod, this, ←Multiset.map_map, prod_mk, ←Finset.prod_eq_multiset_prod]
124+
#align associates.finset_prod_mk Associates.finset_prod_mk
125+
126+
theorem rel_associated_iff_map_eq_map {p q : Multiset α} :
127+
Multiset.Rel Associated p q ↔ p.map Associates.mk = q.map Associates.mk := by
128+
rw [← Multiset.rel_eq, Multiset.rel_map]
129+
simp only [mk_eq_mk_iff_associated]
130+
#align associates.rel_associated_iff_map_eq_map Associates.rel_associated_iff_map_eq_map
131+
132+
theorem prod_eq_one_iff {p : Multiset (Associates α)} :
133+
p.prod = 1 ↔ ∀ a ∈ p, (a : Associates α) = 1 :=
134+
Multiset.induction_on p (by simp)
135+
(by simp (config := { contextual := true }) [mul_eq_one_iff, or_imp, forall_and])
136+
#align associates.prod_eq_one_iff Associates.prod_eq_one_iff
137+
138+
theorem prod_le_prod {p q : Multiset (Associates α)} (h : p ≤ q) : p.prod ≤ q.prod := by
139+
haveI := Classical.decEq (Associates α)
140+
haveI := Classical.decEq α
141+
suffices p.prod ≤ (p + (q - p)).prod by rwa [add_tsub_cancel_of_le h] at this
142+
suffices p.prod * 1 ≤ p.prod * (q - p).prod by simpa
143+
exact mul_mono (le_refl p.prod) one_le
144+
#align associates.prod_le_prod Associates.prod_le_prod
145+
146+
end CommMonoid
147+
148+
section CancelCommMonoidWithZero
149+
150+
variable [CancelCommMonoidWithZero α]
151+
152+
theorem exists_mem_multiset_le_of_prime {s : Multiset (Associates α)} {p : Associates α}
153+
(hp : Prime p) : p ≤ s.prod → ∃ a ∈ s, p ≤ a :=
154+
Multiset.induction_on s (fun ⟨d, Eq⟩ => (hp.ne_one (mul_eq_one_iff.1 Eq.symm).1).elim)
155+
fun a s ih h =>
156+
have : p ≤ a * s.prod := by simpa using h
157+
match Prime.le_or_le hp this with
158+
| Or.inl h => ⟨a, Multiset.mem_cons_self a s, h⟩
159+
| Or.inr h =>
160+
let ⟨a, has, h⟩ := ih h
161+
⟨a, Multiset.mem_cons_of_mem has, h⟩
162+
#align associates.exists_mem_multiset_le_of_prime Associates.exists_mem_multiset_le_of_prime
163+
164+
end CancelCommMonoidWithZero
165+
166+
end Associates
167+
168+
namespace Multiset
169+
170+
theorem prod_ne_zero_of_prime [CancelCommMonoidWithZero α] [Nontrivial α] (s : Multiset α)
171+
(h : ∀ x ∈ s, Prime x) : s.prod ≠ 0 :=
172+
Multiset.prod_ne_zero fun h0 => Prime.ne_zero (h 0 h0) rfl
173+
#align multiset.prod_ne_zero_of_prime Multiset.prod_ne_zero_of_prime
174+
175+
end Multiset
176+
177+
open Finset Finsupp
178+
179+
section CommMonoidWithZero
180+
181+
variable {M : Type _} [CommMonoidWithZero M]
182+
183+
theorem Prime.dvd_finset_prod_iff {S : Finset α} {p : M} (pp : Prime p) (g : α → M) :
184+
p ∣ S.prod g ↔ ∃ a ∈ S, p ∣ g a :=
185+
⟨pp.exists_mem_finset_dvd, fun ⟨_, ha1, ha2⟩ => dvd_trans ha2 (dvd_prod_of_mem g ha1)⟩
186+
#align prime.dvd_finset_prod_iff Prime.dvd_finset_prod_iff
187+
188+
theorem Prime.dvd_finsupp_prod_iff {f : α →₀ M} {g : α → M → ℕ} {p : ℕ} (pp : Prime p) :
189+
p ∣ f.prod g ↔ ∃ a ∈ f.support, p ∣ g a (f a) :=
190+
Prime.dvd_finset_prod_iff pp _
191+
#align prime.dvd_finsupp_prod_iff Prime.dvd_finsupp_prod_iff
192+
193+
end CommMonoidWithZero

0 commit comments

Comments
 (0)