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

Commit ccf8aa0

Browse files
feat(data/finset/basic): disj_Union (#16421)
`finset.disj_Union` is to `finset.bUnion` as: * `finset.disj_union` is to `finset.union` * `finset.cons` is to `insert` * `finset.map` is to `finset.image` Co-authored-by: Yaël Dillies <yael.dillies@gmail.com>
1 parent 0a0be05 commit ccf8aa0

File tree

8 files changed

+137
-13
lines changed

8 files changed

+137
-13
lines changed

src/algebra/big_operators/basic.lean

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,16 @@ attribute [congr] finset.sum_congr
261261
lemma prod_disj_union (h) : ∏ x in s₁.disj_union s₂ h, f x = (∏ x in s₁, f x) * ∏ x in s₂, f x :=
262262
by { refine eq.trans _ (fold_disj_union h), rw one_mul, refl }
263263

264+
@[to_additive]
265+
lemma prod_disj_Union (s : finset ι) (t : ι → finset α) (h) :
266+
∏ x in s.disj_Union t h, f x = ∏ i in s, ∏ x in t i, f x :=
267+
begin
268+
refine eq.trans _ (fold_disj_Union h),
269+
dsimp [finset.prod, multiset.prod, multiset.fold, finset.disj_Union, finset.fold],
270+
congr',
271+
exact prod_const_one.symm,
272+
end
273+
264274
@[to_additive]
265275
lemma prod_union_inter [decidable_eq α] :
266276
(∏ x in (s₁ ∪ s₂), f x) * (∏ x in (s₁ ∩ s₂), f x) = (∏ x in s₁, f x) * (∏ x in s₂, f x) :=
@@ -1469,6 +1479,10 @@ end comm_group
14691479
card (s.sigma t) = ∑ a in s, card (t a) :=
14701480
multiset.card_sigma _ _
14711481

1482+
@[simp] lemma card_disj_Union (s : finset α) (t : α → finset β) (h) :
1483+
(s.disj_Union t h).card = s.sum (λ i, (t i).card) :=
1484+
multiset.card_bind _ _
1485+
14721486
lemma card_bUnion [decidable_eq β] {s : finset α} {t : α → finset β}
14731487
(h : ∀ x ∈ s, ∀ y ∈ s, x ≠ y → disjoint (t x) (t y)) :
14741488
(s.bUnion t).card = ∑ u in s, card (t u) :=

src/data/finset/basic.lean

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2623,6 +2623,78 @@ cons_eq_insert _ _ h ▸ to_list_cons _
26232623

26242624
end to_list
26252625

2626+
/-!
2627+
### disj_Union
2628+
2629+
This section is about the bounded union of a disjoint indexed family `t : α → finset β` of finite
2630+
sets over a finite set `s : finset α`. In most cases `finset.bUnion` should be preferred.
2631+
-/
2632+
section disj_Union
2633+
2634+
variables {s s₁ s₂ : finset α} {t t₁ t₂ : α → finset β}
2635+
2636+
/-- `disj_Union s f h` is the set such that `a ∈ disj_Union s f` iff `a ∈ f i` for some `i ∈ s`.
2637+
It is the same as `s.bUnion f`, but it does not require decidable equality on the type. The
2638+
hypothesis ensures that the sets are disjoint. -/
2639+
def disj_Union (s : finset α) (t : α → finset β)
2640+
(hf : (s : set α).pairwise $ λ a b, ∀ x, x ∈ t a → x ∉ t b) : finset β :=
2641+
⟨(s.val.bind (finset.val ∘ t)), multiset.nodup_bind.mpr
2642+
⟨λ a ha, (t a).nodup, s.nodup.pairwise hf⟩⟩
2643+
2644+
@[simp] theorem disj_Union_val (s : finset α) (t : α → finset β) (h) :
2645+
(s.disj_Union t h).1 = (s.1.bind (λ a, (t a).1)) := rfl
2646+
2647+
@[simp] theorem disj_Union_empty (t : α → finset β) : disj_Union ∅ t (by simp) = ∅ := rfl
2648+
2649+
@[simp] lemma mem_disj_Union {b : β} {h} :
2650+
b ∈ s.disj_Union t h ↔ ∃ a ∈ s, b ∈ t a :=
2651+
by simp only [mem_def, disj_Union_val, mem_bind, exists_prop]
2652+
2653+
@[simp, norm_cast] lemma coe_disj_Union {h} : (s.disj_Union t h : set β) = ⋃ x ∈ (s : set α), t x :=
2654+
by simp only [set.ext_iff, mem_disj_Union, set.mem_Union, iff_self, mem_coe, implies_true_iff]
2655+
2656+
@[simp] theorem disj_Union_cons (a : α) (s : finset α) (ha : a ∉ s) (f : α → finset β) (H) :
2657+
disj_Union (cons a s ha) f H = (f a).disj_union
2658+
(s.disj_Union f $
2659+
λ b hb c hc, H (mem_cons_of_mem hb) (mem_cons_of_mem hc))
2660+
(λ b hb h, let ⟨c, hc, h⟩ := mem_disj_Union.mp h in
2661+
H (mem_cons_self a s) (mem_cons_of_mem hc) (ne_of_mem_of_not_mem hc ha).symm b hb h) :=
2662+
eq_of_veq $ multiset.cons_bind _ _ _
2663+
2664+
@[simp] lemma singleton_disj_Union (a : α) {h} : finset.disj_Union {a} t h = t a :=
2665+
eq_of_veq $ multiset.singleton_bind _ _
2666+
2667+
theorem map_disj_Union {f : α ↪ β} {s : finset α} {t : β → finset γ} {h} :
2668+
(s.map f).disj_Union t h = s.disj_Union (λa, t (f a))
2669+
(λ a ha b hb hab, h (mem_map_of_mem _ ha) (mem_map_of_mem _ hb) (f.injective.ne hab)) :=
2670+
eq_of_veq $ multiset.bind_map _ _ _
2671+
2672+
theorem disj_Union_map {s : finset α} {t : α → finset β} {f : β ↪ γ} {h} :
2673+
(s.disj_Union t h).map f = s.disj_Union (λa, (t a).map f)
2674+
(λ a ha b hb hab x hxa hxb, begin
2675+
obtain ⟨xa, hfa, rfl⟩ := mem_map.mp hxa,
2676+
obtain ⟨xb, hfb, hfab⟩ := mem_map.mp hxb,
2677+
obtain rfl := f.injective hfab,
2678+
exact h ha hb hab _ hfa hfb,
2679+
end) :=
2680+
eq_of_veq $ multiset.map_bind _ _ _
2681+
2682+
lemma disj_Union_disj_Union (s : finset α) (f : α → finset β) (g : β → finset γ) (h1 h2) :
2683+
(s.disj_Union f h1).disj_Union g h2 =
2684+
s.attach.disj_Union (λ a, (f a).disj_Union g $
2685+
λ b hb c hc, h2 (mem_disj_Union.mpr ⟨_, a.prop, hb⟩) (mem_disj_Union.mpr ⟨_, a.prop, hc⟩))
2686+
(λ a ha b hb hab x hxa hxb, begin
2687+
obtain ⟨xa, hfa, hga⟩ := mem_disj_Union.mp hxa,
2688+
obtain ⟨xb, hfb, hgb⟩ := mem_disj_Union.mp hxb,
2689+
refine h2
2690+
(mem_disj_Union.mpr ⟨_, a.prop, hfa⟩) (mem_disj_Union.mpr ⟨_, b.prop, hfb⟩) _ _ hga hgb,
2691+
rintro rfl,
2692+
exact h1 a.prop b.prop (subtype.coe_injective.ne hab) _ hfa hfb,
2693+
end) :=
2694+
eq_of_veq $ multiset.bind_assoc.trans (multiset.attach_bind_coe _ _).symm
2695+
2696+
end disj_Union
2697+
26262698
section bUnion
26272699
/-!
26282700
### bUnion
@@ -2657,6 +2729,14 @@ ext $ λ x, by simp only [mem_bUnion, exists_prop, mem_union, mem_insert,
26572729
lemma bUnion_congr (hs : s₁ = s₂) (ht : ∀ a ∈ s₁, t₁ a = t₂ a) : s₁.bUnion t₁ = s₂.bUnion t₂ :=
26582730
ext $ λ x, by simp [hs, ht] { contextual := tt }
26592731

2732+
@[simp] lemma disj_Union_eq_bUnion (s : finset α) (f : α → finset β) (hf) :
2733+
s.disj_Union f hf = s.bUnion f :=
2734+
begin
2735+
dsimp [disj_Union, finset.bUnion, function.comp],
2736+
generalize_proofs h,
2737+
exact eq_of_veq h.dedup.symm,
2738+
end
2739+
26602740
theorem bUnion_subset {s' : finset β} : s.bUnion t ⊆ s' ↔ ∀ x ∈ s, t x ⊆ s' :=
26612741
by simp only [subset_iff, mem_bUnion]; exact
26622742
⟨λ H a ha b hb, H ⟨a, ha, hb⟩, λ H b ⟨a, ha, hb⟩, H a ha hb⟩

src/data/finset/fold.lean

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ theorem fold_disj_union {s₁ s₂ : finset α} {b₁ b₂ : β} (h) :
7474
(s₁.disj_union s₂ h).fold op (b₁ * b₂) f = s₁.fold op b₁ f * s₂.fold op b₂ f :=
7575
(congr_arg _ $ multiset.map_add _ _ _).trans (multiset.fold_add _ _ _ _ _)
7676

77+
theorem fold_disj_Union {ι : Type*} {s : finset ι} {t : ι → finset α} {b : ι → β} {b₀ : β} (h) :
78+
(s.disj_Union t h).fold op (s.fold op b₀ b) f = s.fold op b₀ (λ i, (t i).fold op (b i) f) :=
79+
(congr_arg _ $ multiset.map_bind _ _ _).trans (multiset.fold_bind _ _ _ _ _)
80+
7781
theorem fold_union_inter [decidable_eq α] {s₁ s₂ : finset α} {b₁ b₂ : β} :
7882
(s₁ ∪ s₂).fold op b₁ f * (s₁ ∩ s₂).fold op b₂ f = s₁.fold op b₂ f * s₂.fold op b₁ f :=
7983
by unfold fold; rw [← fold_add op, ← multiset.map_add, union_val,

src/data/list/basic.lean

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2710,8 +2710,16 @@ theorem pmap_eq_map_attach {p : α → Prop} (f : Π a, p a → β)
27102710
(l H) : pmap f l H = l.attach.map (λ x, f x.1 (H _ x.2)) :=
27112711
by rw [attach, map_pmap]; exact pmap_congr l (λ _ _ _ _, rfl)
27122712

2713-
theorem attach_map_val (l : list α) : l.attach.map subtype.val = l :=
2714-
by rw [attach, map_pmap]; exact (pmap_eq_map _ _ _ _).trans (map_id l)
2713+
@[simp] lemma attach_map_coe' (l : list α) (f : α → β) : l.attach.map (λ i, f i) = l.map f :=
2714+
by rw [attach, map_pmap]; exact (pmap_eq_map _ _ _ _)
2715+
2716+
lemma attach_map_val' (l : list α) (f : α → β) : l.attach.map (λ i, f i.val) = l.map f :=
2717+
attach_map_coe' _ _
2718+
2719+
@[simp] lemma attach_map_coe (l : list α) : l.attach.map (coe : _ → α) = l :=
2720+
(attach_map_coe' _ _).trans l.map_id
2721+
2722+
lemma attach_map_val (l : list α) : l.attach.map subtype.val = l := attach_map_coe _
27152723

27162724
@[simp] theorem mem_attach (l : list α) : ∀ x, x ∈ l.attach | ⟨a, h⟩ :=
27172725
by have := mem_map.1 (by rw [attach_map_val]; exact h);

src/data/multiset/basic.lean

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,11 +1077,19 @@ theorem map_pmap {p : α → Prop} (g : β → γ) (f : Π a, p a → β)
10771077
quot.induction_on s $ λ l H, congr_arg coe $ map_pmap g f l H
10781078

10791079
theorem pmap_eq_map_attach {p : α → Prop} (f : Π a, p a → β)
1080-
(s) : ∀ H, pmap f s H = s.attach.map (λ x, f x.1 (H _ x.2)) :=
1080+
(s) : ∀ H, pmap f s H = s.attach.map (λ x, f x (H _ x.prop)) :=
10811081
quot.induction_on s $ λ l H, congr_arg coe $ pmap_eq_map_attach f l H
10821082

1083-
theorem attach_map_val (s : multiset α) : s.attach.map subtype.val = s :=
1084-
quot.induction_on s $ λ l, congr_arg coe $ attach_map_val l
1083+
@[simp] lemma attach_map_coe' (s : multiset α) (f : α → β) : s.attach.map (λ i, f i) = s.map f :=
1084+
quot.induction_on s $ λ l, congr_arg coe $ attach_map_coe' l f
1085+
1086+
lemma attach_map_val' (s : multiset α) (f : α → β) : s.attach.map (λ i, f i.val) = s.map f :=
1087+
attach_map_coe' _ _
1088+
1089+
@[simp] lemma attach_map_coe (s : multiset α) : s.attach.map (coe : _ → α) = s :=
1090+
(attach_map_coe' _ _).trans s.map_id
1091+
1092+
lemma attach_map_val (s : multiset α) : s.attach.map subtype.val = s := attach_map_coe _
10851093

10861094
@[simp] theorem mem_attach (s : multiset α) : ∀ x, x ∈ s.attach :=
10871095
quot.induction_on s $ λ l, mem_attach _
@@ -1103,9 +1111,6 @@ lemma attach_cons (a : α) (m : multiset α) :
11031111
quotient.induction_on m $ assume l, congr_arg coe $ congr_arg (list.cons _) $
11041112
by rw [list.map_pmap]; exact list.pmap_congr _ (λ _ _ _ _, subtype.eq rfl)
11051113

1106-
@[simp]
1107-
lemma attach_map_coe (m : multiset α) : multiset.map (coe : _ → α) m.attach = m := m.attach_map_val
1108-
11091114
section decidable_pi_exists
11101115
variables {m : multiset α}
11111116

src/data/multiset/bind.lean

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@ begin
139139
rw count_bind, apply le_sum_of_mem,
140140
rw mem_map, exact ⟨x, hx, rfl⟩
141141
end
142+
143+
@[simp] theorem attach_bind_coe (s : multiset α) (f : α → multiset β) :
144+
s.attach.bind (λ i, f i) = s.bind f :=
145+
congr_arg join $ attach_map_coe' _ _
146+
142147
end bind
143148

144149
/-! ### Product of two multisets -/

src/data/multiset/fold.lean

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,14 @@ multiset.induction_on s₂
5555
(by rw [add_zero, fold_zero, ← fold_cons'_right, ← fold_cons_right op])
5656
(by simp {contextual := tt}; cc)
5757

58+
theorem fold_bind {ι : Type*} (s : multiset ι) (t : ι → multiset α) (b : ι → α) (b₀ : α) :
59+
(s.bind t).fold op ((s.map b).fold op b₀) = (s.map (λ i, (t i).fold op (b i))).fold op b₀ :=
60+
begin
61+
induction s using multiset.induction_on with a ha ih,
62+
{ rw [zero_bind, map_zero, map_zero, fold_zero] },
63+
{ rw [cons_bind, map_cons, map_cons, fold_cons_left, fold_cons_left, fold_add, ih] },
64+
end
65+
5866
theorem fold_singleton (b a : α) : ({a} : multiset α).fold op b = a * b := foldr_singleton _ _ _ _
5967

6068
theorem fold_distrib {f g : β → α} (u₁ u₂ : α) (s : multiset β) :

src/data/multiset/nodup.lean

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -205,14 +205,14 @@ lemma map_eq_map_of_bij_of_nodup (f : α → γ) (g : β → γ) {s : multiset
205205
(i_inj : ∀a₁ a₂ ha₁ ha₂, i a₁ ha₁ = i a₂ ha₂ → a₁ = a₂)
206206
(i_surj : ∀b∈t, ∃a ha, b = i a ha) :
207207
s.map f = t.map g :=
208-
have t = s.attach.map (λ x, i x.1 x.2),
208+
have t = s.attach.map (λ x, i x x.2),
209209
from (ht.ext $ (nodup_attach.2 hs).map $
210-
show injective (λ x : {x // x ∈ s}, i x.1 x.2), from λ x y hxy,
211-
subtype.eq $ i_inj x.1 y.1 x.2 y.2 hxy).2
210+
show injective (λ x : {x // x ∈ s}, i x x.2), from λ x y hxy,
211+
subtype.ext $ i_inj x y x.2 y.2 hxy).2
212212
(λ x, by simp only [mem_map, true_and, subtype.exists, eq_comm, mem_attach];
213213
exact ⟨i_surj _, λ ⟨y, hy⟩, hy.snd.symm ▸ hi _ _⟩),
214-
calc s.map f = s.pmap (λ x _, f x) (λ _, id) : by rw [pmap_eq_map]
215-
... = s.attach.map (λ x, f x.1) : by rw [pmap_eq_map_attach]
214+
calc s.map f = s.pmap (λ x _, f x) (λ _, id) : by rw [pmap_eq_map]
215+
... = s.attach.map (λ x, f x) : by rw [pmap_eq_map_attach]
216216
... = t.map g : by rw [this, multiset.map_map]; exact map_congr rfl (λ x _, h _ _)
217217

218218
end multiset

0 commit comments

Comments
 (0)