Skip to content

Commit

Permalink
feat(data/list/{count,perm},data/multiset/basic): countp and count le…
Browse files Browse the repository at this point in the history
…mmas (#14108)

Co-authored-by: Arjun Pitchanathan <arjunpitchanathan@gmail.com>
  • Loading branch information
kmill and Superty committed May 13, 2022
1 parent 23a2205 commit 3185c25
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 7 deletions.
9 changes: 9 additions & 0 deletions src/data/list/count.lean
Expand Up @@ -30,6 +30,9 @@ if_pos pa
@[simp] lemma countp_cons_of_neg {a : α} (l) (pa : ¬ p a) : countp p (a::l) = countp p l :=
if_neg pa

lemma countp_cons (a : α) (l) : countp p (a :: l) = countp p l + ite (p a) 1 0 :=
by { by_cases h : p a; simp [h] }

lemma length_eq_countp_add_countp (l) : length l = countp p l + countp (λ a, ¬p a) l :=
by induction l with x h ih; [refl, by_cases p x];
[simp only [countp_cons_of_pos _ _ h, countp_cons_of_neg (λ a, ¬p a) _ (decidable.not_not.2 h),
Expand All @@ -50,6 +53,9 @@ by simp only [countp_eq_length_filter, filter_append, length_append]
lemma countp_pos {l} : 0 < countp p l ↔ ∃ a ∈ l, p a :=
by simp only [countp_eq_length_filter, length_pos_iff_exists_mem, mem_filter, exists_prop]

theorem countp_eq_zero {l} : countp p l = 0 ↔ ∀ a ∈ l, ¬ p a :=
by { rw [← not_iff_not, ← ne.def, ← pos_iff_ne_zero, countp_pos], simp }

lemma countp_eq_length {l} : countp p l = l.length ↔ ∀ a ∈ l, p a :=
by rw [countp_eq_length_filter, filter_length_eq_length]

Expand Down Expand Up @@ -125,6 +131,9 @@ decidable.by_contradiction $ λ h', h $ count_pos.1 (nat.pos_of_ne_zero h')
lemma not_mem_of_count_eq_zero {a : α} {l : list α} (h : count a l = 0) : a ∉ l :=
λ h', (count_pos.2 h').ne' h

lemma count_eq_zero {a : α} {l} : count a l = 0 ↔ a ∉ l :=
⟨not_mem_of_count_eq_zero, count_eq_zero_of_not_mem⟩

lemma count_eq_length {a : α} {l} : count a l = l.length ↔ ∀ b ∈ l, a = b :=
by rw [count, countp_eq_length]

Expand Down
29 changes: 29 additions & 0 deletions src/data/list/perm.lean
Expand Up @@ -215,6 +215,19 @@ theorem perm.filter (p : α → Prop) [decidable_pred p]
{l₁ l₂ : list α} (s : l₁ ~ l₂) : filter p l₁ ~ filter p l₂ :=
by rw ← filter_map_eq_filter; apply s.filter_map _

theorem filter_append_perm (p : α → Prop) [decidable_pred p]
(l : list α) : filter p l ++ filter (λ x, ¬ p x) l ~ l :=
begin
induction l with x l ih,
{ refl },
{ by_cases h : p x,
{ simp only [h, filter_cons_of_pos, filter_cons_of_neg, not_true, not_false_iff, cons_append],
exact ih.cons x },
{ simp only [h, filter_cons_of_neg, not_false_iff, filter_cons_of_pos],
refine perm.trans _ (ih.cons x),
exact perm_append_comm.trans (perm_append_comm.cons _), } }
end

theorem exists_perm_sublist {l₁ l₂ l₂' : list α}
(s : l₁ <+ l₂) (p : l₂ ~ l₂') : ∃ l₁' ~ l₁, l₁' <+ l₂' :=
begin
Expand Down Expand Up @@ -378,6 +391,22 @@ theorem subperm.countp_le (p : α → Prop) [decidable_pred p]
{l₁ l₂ : list α} : l₁ <+~ l₂ → countp p l₁ ≤ countp p l₂
| ⟨l, p', s⟩ := p'.countp_eq p ▸ s.countp_le p

theorem perm.countp_congr (s : l₁ ~ l₂) {p p' : α → Prop} [decidable_pred p] [decidable_pred p']
(hp : ∀ x ∈ l₁, p x = p' x) : l₁.countp p = l₂.countp p' :=
begin
rw ← s.countp_eq p',
clear s,
induction l₁ with y s hs,
{ refl },
{ simp only [mem_cons_iff, forall_eq_or_imp] at hp,
simp only [countp_cons, hs hp.2, hp.1], },
end

theorem countp_eq_countp_filter_add
(l : list α) (p q : α → Prop) [decidable_pred p] [decidable_pred q] :
l.countp p = (l.filter q).countp p + (l.filter (λ a, ¬ q a)).countp p :=
by { rw [← countp_append], exact perm.countp_eq _ (filter_append_perm _ _).symm }

theorem perm.count_eq [decidable_eq α] {l₁ l₂ : list α}
(p : l₁ ~ l₂) (a) : count a l₁ = count a l₂ :=
p.countp_eq _
Expand Down
48 changes: 41 additions & 7 deletions src/data/multiset/basic.lean
Expand Up @@ -1530,17 +1530,20 @@ quot.induction_on s $ countp_cons_of_neg p
variable (p)

theorem countp_cons (b : α) (s) : countp p (b ::ₘ s) = countp p s + (if p b then 1 else 0) :=
begin
split_ifs with h;
simp only [h, multiset.countp_cons_of_pos, add_zero, multiset.countp_cons_of_neg, not_false_iff],
end
quot.induction_on s $ by simp [list.countp_cons]

theorem countp_eq_card_filter (s) : countp p s = card (filter p s) :=
quot.induction_on s $ λ l, countp_eq_length_filter _ _
quot.induction_on s $ λ l, l.countp_eq_length_filter p

theorem countp_le_card (s) : countp p s ≤ card s :=
quot.induction_on s $ λ l, countp_le_length p

@[simp] theorem countp_add (s t) : countp p (s + t) = countp p s + countp p t :=
by simp [countp_eq_card_filter]

theorem card_eq_countp_add_countp (s) : card s = countp p s + countp (λ x, ¬ p x) s :=
quot.induction_on s $ λ l, by simp [l.length_eq_countp_add_countp p]

/-- `countp p`, the number of elements of a multiset satisfying `p`, promoted to an
`add_monoid_hom`. -/
def countp_add_monoid_hom : multiset α →+ ℕ :=
Expand All @@ -1562,6 +1565,17 @@ by simpa [countp_eq_card_filter] using card_le_of_le (filter_le_filter p h)
countp p (filter q s) = countp (λ a, p a ∧ q a) s :=
by simp [countp_eq_card_filter]

theorem countp_eq_countp_filter_add
(s) (p q : α → Prop) [decidable_pred p] [decidable_pred q] :
countp p s = (filter q s).countp p + (filter (λ a, ¬ q a) s).countp p :=
quot.induction_on s $ λ l, l.countp_eq_countp_filter_add _ _

@[simp] lemma countp_true {s : multiset α} : countp (λ _, true) s = card s :=
quot.induction_on s $ λ l, list.countp_true

@[simp] lemma countp_false {s : multiset α} : countp (λ _, false) s = 0 :=
quot.induction_on s $ λ l, list.countp_false

theorem countp_map (f : α → β) (s : multiset α) (p : β → Prop) [decidable_pred p] :
countp p (map f s) = (s.filter (λ a, p (f a))).card :=
begin
Expand All @@ -1574,11 +1588,25 @@ end
variable {p}

theorem countp_pos {s} : 0 < countp p s ↔ ∃ a ∈ s, p a :=
by simp [countp_eq_card_filter, card_pos_iff_exists_mem]
quot.induction_on s $ λ l, list.countp_pos p

theorem countp_eq_zero {s} : countp p s = 0 ↔ ∀ a ∈ s, ¬ p a :=
quot.induction_on s $ λ l, list.countp_eq_zero p

theorem countp_eq_card {s} : countp p s = card s ↔ ∀ a ∈ s, p a :=
quot.induction_on s $ λ l, list.countp_eq_length p

theorem countp_pos_of_mem {s a} (h : a ∈ s) (pa : p a) : 0 < countp p s :=
countp_pos.2 ⟨_, h, pa⟩

theorem countp_congr {s s' : multiset α} (hs : s = s')
{p p' : α → Prop} [decidable_pred p] [decidable_pred p']
(hp : ∀ x ∈ s, p x = p' x) : s.countp p = s'.countp p' :=
quot.induction_on₂ s s' (λ l l' hs hp, begin
simp only [quot_mk_to_coe'', coe_eq_coe] at hs,
exact hs.countp_congr hp,
end) hs hp

end

/-! ### Multiplicity of an element -/
Expand All @@ -1600,6 +1628,9 @@ countp_cons_of_pos _ rfl
theorem count_cons_of_ne {a b : α} (h : a ≠ b) (s : multiset α) : count a (b ::ₘ s) = count a s :=
countp_cons_of_neg _ h

theorem count_le_card (a : α) (s) : count a s ≤ card s :=
countp_le_card _ _

theorem count_le_of_le (a : α) {s t} : s ≤ t → count a s ≤ count a t :=
countp_le_of_le _

Expand All @@ -1608,7 +1639,7 @@ count_le_of_le _ (le_cons_self _ _)

theorem count_cons (a b : α) (s : multiset α) :
count a (b ::ₘ s) = count a s + (if a = b then 1 else 0) :=
by by_cases h : a = b; simp [h]
countp_cons _ _ _

@[simp] theorem count_singleton_self (a : α) : count a ({a} : multiset α) = 1 :=
by simp only [count_cons_self, singleton_eq_cons, eq_self_iff_true, count_zero]
Expand Down Expand Up @@ -1644,6 +1675,9 @@ iff_not_comm.1 $ count_pos.symm.trans pos_iff_ne_zero
theorem count_ne_zero {a : α} {s : multiset α} : count a s ≠ 0 ↔ a ∈ s :=
by simp [ne.def, count_eq_zero]

theorem count_eq_card {a : α} {s} : count a s = card s ↔ ∀ (x ∈ s), a = x :=
countp_eq_card

@[simp] theorem count_repeat_self (a : α) (n : ℕ) : count a (repeat a n) = n :=
by simp [repeat]

Expand Down

0 comments on commit 3185c25

Please sign in to comment.