|
| 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 |
| 5 | +
|
| 6 | +! This file was ported from Lean 3 source module data.finsupp.multiset |
| 7 | +! leanprover-community/mathlib commit 59694bd07f0a39c5beccba34bd9f413a160782bf |
| 8 | +! Please do not edit these lines, except to modify the commit id |
| 9 | +! if you have ported upstream changes. |
| 10 | +-/ |
| 11 | +import Mathlib.Data.Finsupp.Basic |
| 12 | +import Mathlib.Data.Finsupp.Order |
| 13 | + |
| 14 | +/-! |
| 15 | +# Equivalence between `multiset` and `ℕ`-valued finitely supported functions |
| 16 | +
|
| 17 | +This defines `Finsupp.toMultiset` the equivalence between `α →₀ ℕ` and `Multiset α`, along |
| 18 | +with `Multiset.toFinsupp` the reverse equivalence and `Finsupp.orderIsoMultiset` the equivalence |
| 19 | +promoted to an order isomorphism. |
| 20 | +-/ |
| 21 | + |
| 22 | + |
| 23 | +open Finset |
| 24 | + |
| 25 | +open BigOperators Classical |
| 26 | + |
| 27 | +noncomputable section |
| 28 | + |
| 29 | +variable {α β ι : Type _} |
| 30 | + |
| 31 | +namespace Finsupp |
| 32 | +/-- Given `f : α →₀ ℕ`, `f.toMultiset` is the multiset with multiplicities given by the values of |
| 33 | +`f` on the elements of `α`. We define this function as an `AddEquiv`. -/ |
| 34 | +def toMultiset : (α →₀ ℕ) ≃+ Multiset α |
| 35 | + where |
| 36 | + toFun f := Finsupp.sum f fun a n => n • {a} |
| 37 | + invFun s := ⟨s.toFinset, fun a => s.count a, fun a => by simp⟩ |
| 38 | + left_inv f := |
| 39 | + ext fun a => |
| 40 | + by |
| 41 | + simp only [sum, Multiset.count_sum', Multiset.count_singleton, mul_boole, coe_mk, |
| 42 | + mem_support_iff, Multiset.count_nsmul, Finset.sum_ite_eq, ite_not, ite_eq_right_iff] |
| 43 | + exact Eq.symm |
| 44 | + right_inv s := by simp only [sum, coe_mk, Multiset.toFinset_sum_count_nsmul_eq] |
| 45 | + -- Porting note: times out if h is not specified |
| 46 | + map_add' f g := sum_add_index' (h := fun a n => n • ({a} : Multiset α)) |
| 47 | + (fun _ ↦ zero_nsmul _) (fun _ ↦ add_nsmul _) |
| 48 | +#align finsupp.to_multiset Finsupp.toMultiset |
| 49 | + |
| 50 | +theorem toMultiset_zero : toMultiset (0 : α →₀ ℕ) = 0 := |
| 51 | + rfl |
| 52 | +#align finsupp.to_multiset_zero Finsupp.toMultiset_zero |
| 53 | + |
| 54 | +theorem toMultiset_add (m n : α →₀ ℕ) : toMultiset (m + n) = toMultiset m + toMultiset n := |
| 55 | + toMultiset.map_add m n |
| 56 | +#align finsupp.to_multiset_add Finsupp.toMultiset_add |
| 57 | + |
| 58 | +theorem toMultiset_apply (f : α →₀ ℕ) : toMultiset f = f.sum fun a n => n • {a} := |
| 59 | + rfl |
| 60 | +#align finsupp.to_multiset_apply Finsupp.toMultiset_apply |
| 61 | + |
| 62 | +@[simp] |
| 63 | +theorem toMultiset_symm_apply [DecidableEq α] (s : Multiset α) (x : α) : |
| 64 | + Finsupp.toMultiset.symm s x = s.count x := by |
| 65 | + -- Porting note: proof used to be `convert rfl` |
| 66 | + have : Finsupp.toMultiset.symm s x = Finsupp.toMultiset.invFun s x := rfl |
| 67 | + simp_rw [this, toMultiset, coe_mk] |
| 68 | + congr |
| 69 | +#align finsupp.to_multiset_symm_apply Finsupp.toMultiset_symm_apply |
| 70 | + |
| 71 | +@[simp] |
| 72 | +theorem toMultiset_single (a : α) (n : ℕ) : toMultiset (single a n) = n • {a} := by |
| 73 | + rw [toMultiset_apply, sum_single_index]; apply zero_nsmul |
| 74 | +#align finsupp.to_multiset_single Finsupp.toMultiset_single |
| 75 | + |
| 76 | +theorem toMultiset_sum {f : ι → α →₀ ℕ} (s : Finset ι) : |
| 77 | + Finsupp.toMultiset (∑ i in s, f i) = ∑ i in s, Finsupp.toMultiset (f i) := |
| 78 | + map_sum _ _ _ |
| 79 | +#align finsupp.to_multiset_sum Finsupp.toMultiset_sum |
| 80 | + |
| 81 | +theorem toMultiset_sum_single (s : Finset ι) (n : ℕ) : |
| 82 | + Finsupp.toMultiset (∑ i in s, single i n) = n • s.val := by |
| 83 | + simp_rw [toMultiset_sum, Finsupp.toMultiset_single, sum_nsmul, sum_multiset_singleton] |
| 84 | +#align finsupp.to_multiset_sum_single Finsupp.toMultiset_sum_single |
| 85 | + |
| 86 | +theorem card_toMultiset (f : α →₀ ℕ) : Multiset.card (toMultiset f) = f.sum fun _ => id := by |
| 87 | + simp [toMultiset_apply, map_finsupp_sum, Function.id_def] |
| 88 | +#align finsupp.card_to_multiset Finsupp.card_toMultiset |
| 89 | + |
| 90 | +theorem toMultiset_map (f : α →₀ ℕ) (g : α → β) : |
| 91 | + f.toMultiset.map g = toMultiset (f.mapDomain g) := by |
| 92 | + refine' f.induction _ _ |
| 93 | + · rw [toMultiset_zero, Multiset.map_zero, mapDomain_zero, toMultiset_zero] |
| 94 | + · intro a n f _ _ ih |
| 95 | + rw [toMultiset_add, Multiset.map_add, ih, mapDomain_add, mapDomain_single, |
| 96 | + toMultiset_single, toMultiset_add, toMultiset_single, ← Multiset.coe_mapAddMonoidHom, |
| 97 | + (Multiset.mapAddMonoidHom g).map_nsmul] |
| 98 | + rfl |
| 99 | +#align finsupp.to_multiset_map Finsupp.toMultiset_map |
| 100 | + |
| 101 | +@[simp] |
| 102 | +theorem prod_toMultiset [CommMonoid α] (f : α →₀ ℕ) : |
| 103 | + f.toMultiset.prod = f.prod fun a n => a ^ n := by |
| 104 | + refine' f.induction _ _ |
| 105 | + · rw [toMultiset_zero, Multiset.prod_zero, Finsupp.prod_zero_index] |
| 106 | + · intro a n f _ _ ih |
| 107 | + rw [toMultiset_add, Multiset.prod_add, ih, toMultiset_single, Multiset.prod_nsmul, |
| 108 | + Finsupp.prod_add_index' pow_zero pow_add, Finsupp.prod_single_index, Multiset.prod_singleton] |
| 109 | + · exact pow_zero a |
| 110 | +#align finsupp.prod_to_multiset Finsupp.prod_toMultiset |
| 111 | + |
| 112 | +@[simp] |
| 113 | +theorem toFinset_toMultiset [DecidableEq α] (f : α →₀ ℕ) : f.toMultiset.toFinset = f.support := by |
| 114 | + refine' f.induction _ _ |
| 115 | + · rw [toMultiset_zero, Multiset.toFinset_zero, support_zero] |
| 116 | + · intro a n f ha hn ih |
| 117 | + rw [toMultiset_add, Multiset.toFinset_add, ih, toMultiset_single, support_add_eq, |
| 118 | + support_single_ne_zero _ hn, Multiset.toFinset_nsmul _ _ hn, Multiset.toFinset_singleton] |
| 119 | + refine' Disjoint.mono_left support_single_subset _ |
| 120 | + rwa [Finset.disjoint_singleton_left] |
| 121 | +#align finsupp.to_finset_to_multiset Finsupp.toFinset_toMultiset |
| 122 | + |
| 123 | +@[simp] |
| 124 | +theorem count_toMultiset [DecidableEq α] (f : α →₀ ℕ) (a : α) : (toMultiset f).count a = f a := |
| 125 | + calc |
| 126 | + (toMultiset f).count a = Finsupp.sum f (fun x n => (n • {x} : Multiset α).count a) := |
| 127 | + by rw [toMultiset_apply]; exact map_sum (Multiset.countAddMonoidHom a) _ f.support |
| 128 | + _ = f.sum fun x n => n * ({x} : Multiset α).count a := by simp only [Multiset.count_nsmul] |
| 129 | + _ = f a * ({a} : Multiset α).count a := |
| 130 | + sum_eq_single _ |
| 131 | + (fun a' _ H => by simp only [Multiset.count_singleton, if_false, H.symm, mul_zero]) fun H => |
| 132 | + by simp only [not_mem_support_iff.1 H, zero_mul] |
| 133 | + _ = f a := by rw [Multiset.count_singleton_self, mul_one] |
| 134 | + |
| 135 | +#align finsupp.count_to_multiset Finsupp.count_toMultiset |
| 136 | + |
| 137 | +@[simp] |
| 138 | +theorem mem_toMultiset (f : α →₀ ℕ) (i : α) : i ∈ toMultiset f ↔ i ∈ f.support := by |
| 139 | + rw [← Multiset.count_ne_zero, Finsupp.count_toMultiset, Finsupp.mem_support_iff] |
| 140 | +#align finsupp.mem_to_multiset Finsupp.mem_toMultiset |
| 141 | + |
| 142 | +end Finsupp |
| 143 | + |
| 144 | +namespace Multiset |
| 145 | + |
| 146 | +/-- Given a multiset `s`, `s.toFinsupp` returns the finitely supported function on `ℕ` given by |
| 147 | +the multiplicities of the elements of `s`. -/ |
| 148 | +def toFinsupp : Multiset α ≃+ (α →₀ ℕ) := |
| 149 | + Finsupp.toMultiset.symm |
| 150 | +#align multiset.to_finsupp Multiset.toFinsupp |
| 151 | + |
| 152 | +@[simp] |
| 153 | +theorem toFinsupp_support [DecidableEq α] (s : Multiset α) : s.toFinsupp.support = s.toFinset := by |
| 154 | + -- Porting note: used to be `convert rfl` |
| 155 | + ext |
| 156 | + simp [toFinsupp] |
| 157 | +#align multiset.to_finsupp_support Multiset.toFinsupp_support |
| 158 | + |
| 159 | +@[simp] |
| 160 | +theorem toFinsupp_apply [DecidableEq α] (s : Multiset α) (a : α) : toFinsupp s a = s.count a := by |
| 161 | + -- Porting note: used to be `convert rfl` |
| 162 | + exact Finsupp.toMultiset_symm_apply s a |
| 163 | +#align multiset.to_finsupp_apply Multiset.toFinsupp_apply |
| 164 | + |
| 165 | +theorem toFinsupp_zero : toFinsupp (0 : Multiset α) = 0 := |
| 166 | + AddEquiv.map_zero _ |
| 167 | +#align multiset.to_finsupp_zero Multiset.toFinsupp_zero |
| 168 | + |
| 169 | +theorem toFinsupp_add (s t : Multiset α) : toFinsupp (s + t) = toFinsupp s + toFinsupp t := |
| 170 | + toFinsupp.map_add s t |
| 171 | +#align multiset.to_finsupp_add Multiset.toFinsupp_add |
| 172 | + |
| 173 | +@[simp] |
| 174 | +theorem toFinsupp_singleton (a : α) : toFinsupp ({a} : Multiset α) = Finsupp.single a 1 := |
| 175 | + Finsupp.toMultiset.symm_apply_eq.2 <| by simp |
| 176 | +#align multiset.to_finsupp_singleton Multiset.toFinsupp_singleton |
| 177 | + |
| 178 | +@[simp] |
| 179 | +theorem toFinsupp_toMultiset (s : Multiset α) : Finsupp.toMultiset (toFinsupp s) = s := |
| 180 | + Finsupp.toMultiset.apply_symm_apply s |
| 181 | +#align multiset.to_finsupp_to_multiset Multiset.toFinsupp_toMultiset |
| 182 | + |
| 183 | +theorem toFinsupp_eq_iff {s : Multiset α} {f : α →₀ ℕ} : |
| 184 | + toFinsupp s = f ↔ s = Finsupp.toMultiset f := |
| 185 | + Finsupp.toMultiset.symm_apply_eq |
| 186 | +#align multiset.to_finsupp_eq_iff Multiset.toFinsupp_eq_iff |
| 187 | + |
| 188 | +end Multiset |
| 189 | + |
| 190 | +@[simp] |
| 191 | +theorem Finsupp.toMultiset_toFinsupp (f : α →₀ ℕ) : |
| 192 | + Multiset.toFinsupp (Finsupp.toMultiset f) = f := |
| 193 | + Finsupp.toMultiset.symm_apply_apply f |
| 194 | +#align finsupp.to_multiset_to_finsupp Finsupp.toMultiset_toFinsupp |
| 195 | + |
| 196 | +/-! ### As an order isomorphism -/ |
| 197 | + |
| 198 | + |
| 199 | +namespace Finsupp |
| 200 | +/-- `Finsupp.toMultiset` as an order isomorphism. -/ |
| 201 | +def orderIsoMultiset : (ι →₀ ℕ) ≃o Multiset ι |
| 202 | + where |
| 203 | + toEquiv := toMultiset.toEquiv |
| 204 | + map_rel_iff' := by |
| 205 | + -- Porting note: This proof used to be simp [Multiset.le_iff_count, le_def] |
| 206 | + intro f g; |
| 207 | + -- Porting note: the following should probably be a simp lemma somewhere; |
| 208 | + -- maybe coe_toEquiv in Hom/Equiv/Basic? |
| 209 | + have : ⇑ (toMultiset (α := ι)).toEquiv = toMultiset := rfl |
| 210 | + simp [Multiset.le_iff_count, le_def, ← toMultiset_symm_apply, this] |
| 211 | +#align finsupp.order_iso_multiset Finsupp.orderIsoMultiset |
| 212 | + |
| 213 | +@[simp] |
| 214 | +theorem coe_orderIsoMultiset : ⇑(@orderIsoMultiset ι) = toMultiset := |
| 215 | + rfl |
| 216 | +#align finsupp.coe_order_iso_multiset Finsupp.coe_orderIsoMultiset |
| 217 | + |
| 218 | +@[simp] |
| 219 | +theorem coe_orderIsoMultiset_symm : ⇑(@orderIsoMultiset ι).symm = Multiset.toFinsupp := |
| 220 | + rfl |
| 221 | +#align finsupp.coe_order_iso_multiset_symm Finsupp.coe_orderIsoMultiset_symm |
| 222 | + |
| 223 | +theorem toMultiset_strictMono : StrictMono (@toMultiset ι) := |
| 224 | + (@orderIsoMultiset ι).strictMono |
| 225 | +#align finsupp.to_multiset_strict_mono Finsupp.toMultiset_strictMono |
| 226 | + |
| 227 | +theorem sum_id_lt_of_lt (m n : ι →₀ ℕ) (h : m < n) : (m.sum fun _ => id) < n.sum fun _ => id := by |
| 228 | + rw [← card_toMultiset, ← card_toMultiset] |
| 229 | + apply Multiset.card_lt_of_lt |
| 230 | + exact toMultiset_strictMono h |
| 231 | +#align finsupp.sum_id_lt_of_lt Finsupp.sum_id_lt_of_lt |
| 232 | + |
| 233 | +variable (ι) |
| 234 | + |
| 235 | +/-- The order on `ι →₀ ℕ` is well-founded. -/ |
| 236 | +theorem lt_wf : WellFounded (@LT.lt (ι →₀ ℕ) _) := |
| 237 | + Subrelation.wf (sum_id_lt_of_lt _ _) <| InvImage.wf _ Nat.lt_wfRel.2 |
| 238 | +#align finsupp.lt_wf Finsupp.lt_wf |
| 239 | + |
| 240 | +end Finsupp |
| 241 | + |
| 242 | +theorem Multiset.toFinsupp_strictMono : StrictMono (@Multiset.toFinsupp ι) := |
| 243 | + (@Finsupp.orderIsoMultiset ι).symm.strictMono |
| 244 | +#align multiset.to_finsupp_strict_mono Multiset.toFinsupp_strictMono |
0 commit comments