Skip to content

Commit 88a42cb

Browse files
committed
feat: port Data.Finsupp.Multiset (#1988)
Some proofs needed rewriting because or different unfolding behaviour of `Equiv`s and `toFun`s, but in the end it was not too bad. Revisiting Hom/Equiv/Basic might be valuable at some point
1 parent c6a881b commit 88a42cb

File tree

2 files changed

+245
-0
lines changed

2 files changed

+245
-0
lines changed

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ import Mathlib.Data.Finsupp.Defs
329329
import Mathlib.Data.Finsupp.Fin
330330
import Mathlib.Data.Finsupp.Fintype
331331
import Mathlib.Data.Finsupp.Indicator
332+
import Mathlib.Data.Finsupp.Multiset
332333
import Mathlib.Data.Finsupp.NeLocus
333334
import Mathlib.Data.Finsupp.Order
334335
import Mathlib.Data.Finsupp.Pointwise

Mathlib/Data/Finsupp/Multiset.lean

Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
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

Comments
 (0)