|
| 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