Skip to content

Commit 65a1391

Browse files
committed
feat(data/{list,multiset,finset}/*): attach and filter lemmas (leanprover-community#18087)
Left commutativity and cardinality of `list.filter`/`multiset.filter`/`finset.filter`. Interaction of `count`/`countp` and `attach`.
1 parent 3365b20 commit 65a1391

File tree

11 files changed

+108
-25
lines changed

11 files changed

+108
-25
lines changed

src/algebra/big_operators/basic.lean

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@ variables {s s₁ s₂ : finset α} {a : α} {f g : α → β}
106106
@[to_additive] lemma prod_eq_multiset_prod [comm_monoid β] (s : finset α) (f : α → β) :
107107
∏ x in s, f x = (s.1.map f).prod := rfl
108108

109+
@[simp, to_additive] lemma prod_map_val [comm_monoid β] (s : finset α) (f : α → β) :
110+
(s.1.map f).prod = ∏ a in s, f a := rfl
111+
109112
@[to_additive]
110113
theorem prod_eq_fold [comm_monoid β] (s : finset α) (f : α → β) :
111114
∏ x in s, f x = s.fold (*) 1 f :=
@@ -1418,16 +1421,19 @@ begin
14181421
apply sum_congr rfl h₁
14191422
end
14201423

1424+
lemma nat_cast_card_filter [add_comm_monoid_with_one β] (p) [decidable_pred p] (s : finset α) :
1425+
((filter p s).card : β) = ∑ a in s, if p a then 1 else 0 :=
1426+
by simp only [add_zero, sum_const, nsmul_eq_mul, eq_self_iff_true, sum_const_zero, sum_ite,
1427+
nsmul_one]
1428+
1429+
lemma card_filter (p) [decidable_pred p] (s : finset α) :
1430+
(filter p s).card = ∑ a in s, ite (p a) 1 0 :=
1431+
nat_cast_card_filter _ _
1432+
14211433
@[simp]
1422-
lemma sum_boole {s : finset α} {p : α → Prop} [non_assoc_semiring β] {hp : decidable_pred p} :
1423-
(∑ x in s, if p x then (1 : β) else (0 : β)) = (s.filter p).card :=
1424-
by simp only [add_zero,
1425-
mul_one,
1426-
finset.sum_const,
1427-
nsmul_eq_mul,
1428-
eq_self_iff_true,
1429-
finset.sum_const_zero,
1430-
finset.sum_ite]
1434+
lemma sum_boole {s : finset α} {p : α → Prop} [add_comm_monoid_with_one β] {hp : decidable_pred p} :
1435+
(∑ x in s, if p x then 1 else 0 : β) = (s.filter p).card :=
1436+
(nat_cast_card_filter _ _).symm
14311437

14321438
lemma _root_.commute.sum_right [non_unital_non_assoc_semiring β] (s : finset α)
14331439
(f : α → β) (b : β) (h : ∀ i ∈ s, commute b (f i)) :

src/algebra/big_operators/order.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ lemma prod_le_pow_card (s : finset ι) (f : ι → N) (n : N) (h : ∀ x ∈ s,
174174
begin
175175
refine (multiset.prod_le_pow_card (s.val.map f) n _).trans _,
176176
{ simpa using h },
177-
{ simpa }
177+
{ simp }
178178
end
179179

180180
@[to_additive card_nsmul_le_sum]

src/data/finset/card.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ variables {s t : finset α} {a b : α}
4242
def card (s : finset α) : ℕ := s.1.card
4343

4444
lemma card_def (s : finset α) : s.card = s.1.card := rfl
45+
@[simp] lemma card_val (s : finset α) : s.1.card = s.card := rfl
4546

4647
@[simp] lemma card_mk {m nodup} : (⟨m, nodup⟩ : finset α).card = m.card := rfl
4748

src/data/finset/image.lean

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,22 @@ lemma filter_map {p : β → Prop} [decidable_pred p] :
127127
(s.map f).filter p = (s.filter (p ∘ f)).map f :=
128128
eq_of_veq (map_filter _ _ _)
129129

130+
lemma map_filter' (p : α → Prop) [decidable_pred p] (f : α ↪ β) (s : finset α)
131+
[decidable_pred (λ b, ∃ a, p a ∧ f a = b)] :
132+
(s.filter p).map f = (s.map f).filter (λ b, ∃ a, p a ∧ f a = b) :=
133+
by simp [(∘), filter_map, f.injective.eq_iff]
134+
135+
lemma filter_attach' [decidable_eq α] (s : finset α) (p : s → Prop) [decidable_pred p] :
136+
s.attach.filter p =
137+
(s.filter $ λ x, ∃ h, p ⟨x, h⟩).attach.map ⟨subtype.map id $ filter_subset _ _,
138+
subtype.map_injective _ injective_id⟩ :=
139+
eq_of_veq $ multiset.filter_attach' _ _
140+
141+
@[simp] lemma filter_attach (p : α → Prop) [decidable_pred p] (s : finset α) :
142+
(s.attach.filter (λ x, p ↑x)) =
143+
(s.filter p).attach.map ((embedding.refl _).subtype_map mem_of_mem_filter) :=
144+
eq_of_veq $ multiset.filter_attach _ _
145+
130146
lemma map_filter {f : α ≃ β} {p : α → Prop} [decidable_pred p] :
131147
(s.filter p).map f.to_embedding = (s.map f.to_embedding).filter (p ∘ f.symm) :=
132148
by simp only [filter_map, function.comp, equiv.to_embedding_apply, equiv.symm_apply_apply]

src/data/list/basic.lean

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2716,6 +2716,8 @@ end split_at_on
27162716
with the same elements but in the type `{x // x ∈ l}`. -/
27172717
def attach (l : list α) : list {x // x ∈ l} := pmap subtype.mk l (λ a, id)
27182718

2719+
@[simp] lemma attach_nil : ([] : list α).attach = [] := rfl
2720+
27192721
theorem sizeof_lt_sizeof_of_mem [has_sizeof α] {x : α} {l : list α} (hx : x ∈ l) :
27202722
sizeof x < sizeof l :=
27212723
begin
@@ -3250,12 +3252,35 @@ theorem map_filter (f : β → α) (l : list β) :
32503252
filter p (map f l) = map f (filter (p ∘ f) l) :=
32513253
by rw [← filter_map_eq_map, filter_filter_map, filter_map_filter]; refl
32523254

3255+
lemma map_filter' {f : α → β} (hf : injective f) (l : list α)
3256+
[decidable_pred (λ b, ∃ a, p a ∧ f a = b)] :
3257+
(l.filter p).map f = (l.map f).filter (λ b, ∃ a, p a ∧ f a = b) :=
3258+
by simp [(∘), map_filter, hf.eq_iff]
3259+
3260+
lemma filter_attach' (l : list α) (p : {a // a ∈ l} → Prop) [decidable_eq α] [decidable_pred p] :
3261+
l.attach.filter p = (l.filter $ λ x, ∃ h, p ⟨x, h⟩).attach.map
3262+
(subtype.map id $ λ x hx, let ⟨h, _⟩ := of_mem_filter hx in h) :=
3263+
begin
3264+
classical,
3265+
refine map_injective_iff.2 subtype.coe_injective _,
3266+
simp [(∘), map_filter' _ subtype.coe_injective],
3267+
end
3268+
3269+
@[simp] lemma filter_attach (l : list α) (p : α → Prop) [decidable_pred p] :
3270+
l.attach.filter (λ x, p ↑x) = (l.filter p).attach.map (subtype.map id $ λ _, mem_of_mem_filter) :=
3271+
map_injective_iff.2 subtype.coe_injective $ by
3272+
simp_rw [map_map, (∘), subtype.map, subtype.coe_mk, id.def, ←map_filter, attach_map_coe]
3273+
32533274
@[simp] theorem filter_filter (q) [decidable_pred q] : ∀ l,
32543275
filter p (filter q l) = filter (λ a, p a ∧ q a) l
32553276
| [] := rfl
32563277
| (a :: l) := by by_cases hp : p a; by_cases hq : q a; simp only [hp, hq, filter, if_true, if_false,
32573278
true_and, false_and, filter_filter l, eq_self_iff_true]
32583279

3280+
lemma filter_comm (q) [decidable_pred q] (l : list α) :
3281+
filter p (filter q l) = filter q (filter p l) :=
3282+
by simp [and_comm]
3283+
32593284
@[simp] lemma filter_true {h : decidable_pred (λ a : α, true)} (l : list α) :
32603285
@filter α (λ _, true) h l = l :=
32613286
by convert filter_eq_self.2 (λ _ _, trivial)

src/data/list/count.lean

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ by simp only [countp_eq_length_filter, filter_filter]
8484
| [] := rfl
8585
| (a::l) := by rw [map_cons, countp_cons, countp_cons, countp_map]
8686

87+
@[simp] lemma countp_attach (l : list α) : l.attach.countp (λ a, p ↑a) = l.countp p :=
88+
by rw [←countp_map, attach_map_coe]
89+
8790
variables {p q}
8891

8992
lemma countp_mono_left (h : ∀ x ∈ l, p x → q x) : countp p l ≤ countp q l :=
@@ -197,6 +200,9 @@ lemma count_bind {α β} [decidable_eq β] (l : list α) (f : α → list β) (x
197200
count x (l.bind f) = sum (map (count x ∘ f) l) :=
198201
by rw [list.bind, count_join, map_map]
199202

203+
@[simp] lemma count_attach (a : {x // x ∈ l}) : l.attach.count a = l.count a :=
204+
eq.trans (countp_congr $ λ _ _, subtype.ext_iff) $ countp_attach _ _
205+
200206
@[simp] lemma count_map_of_injective {α β} [decidable_eq α] [decidable_eq β]
201207
(l : list α) (f : α → β) (hf : function.injective f) (x : α) :
202208
count (f x) (map f l) = count x l :=

src/data/list/perm.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ theorem subperm.countp_le (p : α → Prop) [decidable_pred p]
396396
| ⟨l, p', s⟩ := p'.countp_eq p ▸ s.countp_le p
397397

398398
theorem perm.countp_congr (s : l₁ ~ l₂) {p p' : α → Prop} [decidable_pred p] [decidable_pred p']
399-
(hp : ∀ x ∈ l₁, p x = p' x) : l₁.countp p = l₂.countp p' :=
399+
(hp : ∀ x ∈ l₁, p x p' x) : l₁.countp p = l₂.countp p' :=
400400
begin
401401
rw ← s.countp_eq p',
402402
clear s,

src/data/multiset/basic.lean

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ These are implemented as the quotient of a list by permutations.
1616
We define the global infix notation `::ₘ` for `multiset.cons`.
1717
-/
1818

19-
open list subtype nat
19+
open function list nat subtype
2020

2121
variables {α : Type*} {β : Type*} {γ : Type*}
2222

@@ -1543,6 +1543,10 @@ le_antisymm (le_inter
15431543
filter p (filter q s) = filter (λ a, p a ∧ q a) s :=
15441544
quot.induction_on s $ λ l, congr_arg coe $ filter_filter p q l
15451545

1546+
lemma filter_comm (q) [decidable_pred q] (s : multiset α) :
1547+
filter p (filter q s) = filter q (filter p s) :=
1548+
by simp [and_comm]
1549+
15461550
theorem filter_add_filter (q) [decidable_pred q] (s : multiset α) :
15471551
filter p s + filter q s = filter (λ a, p a ∨ q a) s + filter (λ a, p a ∧ q a) s :=
15481552
multiset.induction_on s rfl $ λ a s IH,
@@ -1556,6 +1560,11 @@ theorem map_filter (f : β → α) (s : multiset β) :
15561560
filter p (map f s) = map f (filter (p ∘ f) s) :=
15571561
quot.induction_on s (λ l, by simp [map_filter])
15581562

1563+
lemma map_filter' {f : α → β} (hf : injective f) (s : multiset α)
1564+
[decidable_pred (λ b, ∃ a, p a ∧ f a = b)] :
1565+
(s.filter p).map f = (s.map f).filter (λ b, ∃ a, p a ∧ f a = b) :=
1566+
by simp [(∘), map_filter, hf.eq_iff]
1567+
15591568
/-! ### Simultaneously filter and map elements of a multiset -/
15601569

15611570
/-- `filter_map f s` is a combination filter/map operation on `s`.
@@ -1704,6 +1713,18 @@ begin
17041713
card_singleton, add_comm] },
17051714
end
17061715

1716+
@[simp] lemma countp_attach (s : multiset α) : s.attach.countp (λ a, p ↑a) = s.countp p :=
1717+
quotient.induction_on s $ λ l, begin
1718+
simp only [quot_mk_to_coe, coe_countp],
1719+
rw [quot_mk_to_coe, coe_attach, coe_countp],
1720+
exact list.countp_attach _ _,
1721+
end
1722+
1723+
@[simp] lemma filter_attach (m : multiset α) (p : α → Prop) [decidable_pred p] :
1724+
(m.attach.filter (λ x, p ↑x)) =
1725+
(m.filter p).attach.map (subtype.map id $ λ _, multiset.mem_of_mem_filter) :=
1726+
quotient.induction_on m $ λ l, congr_arg coe (list.filter_attach l p)
1727+
17071728
variable {p}
17081729

17091730
theorem countp_pos {s} : 0 < countp p s ↔ ∃ a ∈ s, p a :=
@@ -1720,7 +1741,7 @@ countp_pos.2 ⟨_, h, pa⟩
17201741

17211742
theorem countp_congr {s s' : multiset α} (hs : s = s')
17221743
{p p' : α → Prop} [decidable_pred p] [decidable_pred p']
1723-
(hp : ∀ x ∈ s, p x = p' x) : s.countp p = s'.countp p' :=
1744+
(hp : ∀ x ∈ s, p x p' x) : s.countp p = s'.countp p' :=
17241745
quot.induction_on₂ s s' (λ l l' hs hp, begin
17251746
simp only [quot_mk_to_coe'', coe_eq_coe] at hs,
17261747
exact hs.countp_congr hp,
@@ -1731,7 +1752,7 @@ end
17311752
/-! ### Multiplicity of an element -/
17321753

17331754
section
1734-
variable [decidable_eq α]
1755+
variables [decidable_eq α] {s : multiset α}
17351756

17361757
/-- `count a s` is the multiplicity of `a` in `s`. -/
17371758
def count (a : α) : multiset α → ℕ := countp (eq a)
@@ -1778,6 +1799,9 @@ def count_add_monoid_hom (a : α) : multiset α →+ ℕ := countp_add_monoid_ho
17781799
@[simp] theorem count_nsmul (a : α) (n s) : count a (n • s) = n * count a s :=
17791800
by induction n; simp [*, succ_nsmul', succ_mul, zero_nsmul]
17801801

1802+
@[simp] lemma count_attach (a : {x // x ∈ s}) : s.attach.count a = s.count a :=
1803+
eq.trans (countp_congr rfl $ λ _ _, subtype.ext_iff) $ countp_attach _ _
1804+
17811805
theorem count_pos {a : α} {s : multiset α} : 0 < count a s ↔ a ∈ s :=
17821806
by simp [count, countp_pos]
17831807

@@ -1901,13 +1925,6 @@ begin
19011925
contradiction }
19021926
end
19031927

1904-
@[simp]
1905-
lemma attach_count_eq_count_coe (m : multiset α) (a) : m.attach.count a = m.count (a : α) :=
1906-
calc m.attach.count a
1907-
= (m.attach.map (coe : _ → α)).count (a : α) :
1908-
(multiset.count_map_eq_count' _ _ subtype.coe_injective _).symm
1909-
... = m.count (a : α) : congr_arg _ m.attach_map_coe
1910-
19111928
lemma filter_eq' (s : multiset α) (b : α) : s.filter (= b) = replicate (count b s) b :=
19121929
quotient.induction_on s $ λ l, congr_arg coe $ filter_eq' l b
19131930

@@ -2174,6 +2191,19 @@ theorem map_injective {f : α → β} (hf : function.injective f) :
21742191
function.injective (multiset.map f) :=
21752192
assume x y, (map_eq_map hf).1
21762193

2194+
lemma filter_attach' (s : multiset α) (p : {a // a ∈ s} → Prop) [decidable_eq α]
2195+
[decidable_pred p] :
2196+
s.attach.filter p =
2197+
(s.filter $ λ x, ∃ h, p ⟨x, h⟩).attach.map (subtype.map id $ λ x hx,
2198+
let ⟨h, _⟩ := of_mem_filter hx in h) :=
2199+
begin
2200+
classical,
2201+
refine multiset.map_injective subtype.coe_injective _,
2202+
simp only [function.comp, map_filter' _ subtype.coe_injective, subtype.exists, coe_mk,
2203+
exists_and_distrib_right, exists_eq_right, attach_map_coe, map_map, map_coe, id.def],
2204+
rw attach_map_coe,
2205+
end
2206+
21772207
end map
21782208

21792209
section quot

src/data/multiset/lattice.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ sup_bot_eq
3939
@[simp] lemma sup_add (s₁ s₂ : multiset α) : (s₁ + s₂).sup = s₁.sup ⊔ s₂.sup :=
4040
eq.trans (by simp [sup]) (fold_add _ _ _ _ _)
4141

42-
lemma sup_le {s : multiset α} {a : α} : s.sup ≤ a ↔ (∀b ∈ s, b ≤ a) :=
42+
@[simp] lemma sup_le {s : multiset α} {a : α} : s.sup ≤ a ↔ (∀b ∈ s, b ≤ a) :=
4343
multiset.induction_on s (by simp)
4444
(by simp [or_imp_distrib, forall_and_distrib] {contextual := tt})
4545

src/data/set/finite.lean

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -927,8 +927,7 @@ eq.trans (by congr) empty_card
927927

928928
theorem card_fintype_insert_of_not_mem {a : α} (s : set α) [fintype s] (h : a ∉ s) :
929929
@fintype.card _ (fintype_insert_of_not_mem s h) = fintype.card s + 1 :=
930-
by rw [fintype_insert_of_not_mem, fintype.card_of_finset];
931-
simp [finset.card, to_finset]; refl
930+
by simp [fintype_insert_of_not_mem, fintype.card_of_finset]
932931

933932
@[simp] theorem card_insert {a : α} (s : set α)
934933
[fintype s] (h : a ∉ s) {d : fintype.{u} (insert a s : set α)} :

0 commit comments

Comments
 (0)