Module docstring
{"# Preparations for defining operations on Finset.
The operations here ignore multiplicities,
and preparatory for defining the corresponding operations on Finset.
","### finset insert ","### finset union ","### finset inter "}
{"# Preparations for defining operations on Finset.
The operations here ignore multiplicities,
and preparatory for defining the corresponding operations on Finset.
","### finset insert ","### finset union ","### finset inter "}
Multiset.ndinsert
definition
(a : α) (s : Multiset α) : Multiset α
/-- `ndinsert a s` is the lift of the list `insert` operation. This operation
does not respect multiplicities, unlike `cons`, but it is suitable as
an insert operation on `Finset`. -/
def ndinsert (a : α) (s : Multiset α) : Multiset α :=
Quot.liftOn s (fun l => (l.insert a : Multiset α)) fun _ _ p => Quot.sound (p.insert a)
Multiset.coe_ndinsert
theorem
(a : α) (l : List α) : ndinsert a l = (insert a l : List α)
Multiset.ndinsert_zero
theorem
(a : α) : ndinsert a 0 = { a }
@[simp]
theorem ndinsert_zero (a : α) : ndinsert a 0 = {a} :=
rfl
Multiset.ndinsert_of_mem
theorem
{a : α} {s : Multiset α} : a ∈ s → ndinsert a s = s
@[simp]
theorem ndinsert_of_mem {a : α} {s : Multiset α} : a ∈ s → ndinsert a s = s :=
Quot.inductionOn s fun _ h => congr_arg ((↑) : List α → Multiset α) <| insert_of_mem h
Multiset.ndinsert_of_not_mem
theorem
{a : α} {s : Multiset α} : a ∉ s → ndinsert a s = a ::ₘ s
@[simp]
theorem ndinsert_of_not_mem {a : α} {s : Multiset α} : a ∉ s → ndinsert a s = a ::ₘ s :=
Quot.inductionOn s fun _ h => congr_arg ((↑) : List α → Multiset α) <| insert_of_not_mem h
Multiset.mem_ndinsert
theorem
{a b : α} {s : Multiset α} : a ∈ ndinsert b s ↔ a = b ∨ a ∈ s
@[simp]
theorem mem_ndinsert {a b : α} {s : Multiset α} : a ∈ ndinsert b sa ∈ ndinsert b s ↔ a = b ∨ a ∈ s :=
Quot.inductionOn s fun _ => mem_insert_iff
Multiset.le_ndinsert_self
theorem
(a : α) (s : Multiset α) : s ≤ ndinsert a s
@[simp]
theorem le_ndinsert_self (a : α) (s : Multiset α) : s ≤ ndinsert a s :=
Quot.inductionOn s fun _ => (sublist_insert _ _).subperm
Multiset.mem_ndinsert_self
theorem
(a : α) (s : Multiset α) : a ∈ ndinsert a s
theorem mem_ndinsert_self (a : α) (s : Multiset α) : a ∈ ndinsert a s := by simp
Multiset.mem_ndinsert_of_mem
theorem
{a b : α} {s : Multiset α} (h : a ∈ s) : a ∈ ndinsert b s
theorem mem_ndinsert_of_mem {a b : α} {s : Multiset α} (h : a ∈ s) : a ∈ ndinsert b s :=
mem_ndinsert.2 (Or.inr h)
Multiset.length_ndinsert_of_mem
theorem
{a : α} {s : Multiset α} (h : a ∈ s) : card (ndinsert a s) = card s
Multiset.length_ndinsert_of_not_mem
theorem
{a : α} {s : Multiset α} (h : a ∉ s) : card (ndinsert a s) = card s + 1
Multiset.dedup_cons
theorem
{a : α} {s : Multiset α} : dedup (a ::ₘ s) = ndinsert a (dedup s)
theorem dedup_cons {a : α} {s : Multiset α} : dedup (a ::ₘ s) = ndinsert a (dedup s) := by
by_cases h : a ∈ s <;> simp [h]
Multiset.Nodup.ndinsert
theorem
(a : α) : Nodup s → Nodup (ndinsert a s)
theorem Nodup.ndinsert (a : α) : Nodup s → Nodup (ndinsert a s) :=
Quot.inductionOn s fun _ => Nodup.insert
Multiset.ndinsert_le
theorem
{a : α} {s t : Multiset α} : ndinsert a s ≤ t ↔ s ≤ t ∧ a ∈ t
theorem ndinsert_le {a : α} {s t : Multiset α} : ndinsertndinsert a s ≤ t ↔ s ≤ t ∧ a ∈ t :=
⟨fun h => ⟨le_trans (le_ndinsert_self _ _) h, mem_of_le h (mem_ndinsert_self _ _)⟩, fun ⟨l, m⟩ =>
if h : a ∈ s then by simp [h, l]
else by
rw [ndinsert_of_not_mem h, ← cons_erase m, cons_le_cons_iff, ← le_cons_of_not_mem h,
cons_erase m]
exact l⟩
Multiset.attach_ndinsert
theorem
(a : α) (s : Multiset α) :
(s.ndinsert a).attach = ndinsert ⟨a, mem_ndinsert_self a s⟩ (s.attach.map fun p => ⟨p.1, mem_ndinsert_of_mem p.2⟩)
theorem attach_ndinsert (a : α) (s : Multiset α) :
(s.ndinsert a).attach =
ndinsert ⟨a, mem_ndinsert_self a s⟩ (s.attach.map fun p => ⟨p.1, mem_ndinsert_of_mem p.2⟩) :=
have eq :
∀ h : ∀ p : { x // x ∈ s }, p.1 ∈ s,
(fun p : { x // x ∈ s } => ⟨p.val, h p⟩ : { x // x ∈ s } → { x // x ∈ s }) = id :=
fun _ => funext fun _ => Subtype.eq rfl
have : ∀ (t) (eq : s.ndinsert a = t), t.attach = ndinsert ⟨a, eq ▸ mem_ndinsert_self a s⟩
(s.attach.map fun p => ⟨p.1, eq ▸ mem_ndinsert_of_mem p.2⟩) := by
intro t ht
by_cases h : a ∈ s
· rw [ndinsert_of_mem h] at ht
subst ht
rw [eq, map_id, ndinsert_of_mem (mem_attach _ _)]
· rw [ndinsert_of_not_mem h] at ht
subst ht
simp [attach_cons, h]
this _ rfl
Multiset.disjoint_ndinsert_left
theorem
{a : α} {s t : Multiset α} : Disjoint (ndinsert a s) t ↔ a ∉ t ∧ Disjoint s t
@[simp]
theorem disjoint_ndinsert_left {a : α} {s t : Multiset α} :
DisjointDisjoint (ndinsert a s) t ↔ a ∉ t ∧ Disjoint s t :=
Iff.trans (by simp [disjoint_left]) disjoint_cons_left
Multiset.disjoint_ndinsert_right
theorem
{a : α} {s t : Multiset α} : Disjoint s (ndinsert a t) ↔ a ∉ s ∧ Disjoint s t
@[simp]
theorem disjoint_ndinsert_right {a : α} {s t : Multiset α} :
DisjointDisjoint s (ndinsert a t) ↔ a ∉ s ∧ Disjoint s t := by
rw [_root_.disjoint_comm, disjoint_ndinsert_left]; tauto
Multiset.ndunion
definition
(s t : Multiset α) : Multiset α
/-- `ndunion s t` is the lift of the list `union` operation. This operation
does not respect multiplicities, unlike `s ∪ t`, but it is suitable as
a union operation on `Finset`. (`s ∪ t` would also work as a union operation
on finset, but this is more efficient.) -/
def ndunion (s t : Multiset α) : Multiset α :=
(Quotient.liftOn₂ s t fun l₁ l₂ => (l₁.union l₂ : Multiset α)) fun _ _ _ _ p₁ p₂ =>
Quot.sound <| p₁.union p₂
Multiset.coe_ndunion
theorem
(l₁ l₂ : List α) : @ndunion α _ l₁ l₂ = (l₁ ∪ l₂ : List α)
Multiset.zero_ndunion
theorem
(s : Multiset α) : ndunion 0 s = s
theorem zero_ndunion (s : Multiset α) : ndunion 0 s = s :=
Quot.inductionOn s fun _ => rfl
Multiset.cons_ndunion
theorem
(s t : Multiset α) (a : α) : ndunion (a ::ₘ s) t = ndinsert a (ndunion s t)
@[simp]
theorem cons_ndunion (s t : Multiset α) (a : α) : ndunion (a ::ₘ s) t = ndinsert a (ndunion s t) :=
Quot.induction_on₂ s t fun _ _ => rfl
Multiset.mem_ndunion
theorem
{s t : Multiset α} {a : α} : a ∈ ndunion s t ↔ a ∈ s ∨ a ∈ t
@[simp]
theorem mem_ndunion {s t : Multiset α} {a : α} : a ∈ ndunion s ta ∈ ndunion s t ↔ a ∈ s ∨ a ∈ t :=
Quot.induction_on₂ s t fun _ _ => List.mem_union_iff
Multiset.le_ndunion_right
theorem
(s t : Multiset α) : t ≤ ndunion s t
theorem le_ndunion_right (s t : Multiset α) : t ≤ ndunion s t :=
Quot.induction_on₂ s t fun _ _ => (suffix_union_right _ _).sublist.subperm
Multiset.subset_ndunion_right
theorem
(s t : Multiset α) : t ⊆ ndunion s t
theorem subset_ndunion_right (s t : Multiset α) : t ⊆ ndunion s t :=
subset_of_le (le_ndunion_right s t)
Multiset.ndunion_le_add
theorem
(s t : Multiset α) : ndunion s t ≤ s + t
theorem ndunion_le_add (s t : Multiset α) : ndunion s t ≤ s + t :=
Quot.induction_on₂ s t fun _ _ => (union_sublist_append _ _).subperm
Multiset.ndunion_le
theorem
{s t u : Multiset α} : ndunion s t ≤ u ↔ s ⊆ u ∧ t ≤ u
theorem ndunion_le {s t u : Multiset α} : ndunionndunion s t ≤ u ↔ s ⊆ u ∧ t ≤ u :=
Multiset.induction_on s (by simp [zero_ndunion])
(fun _ _ h =>
by simp only [cons_ndunion, mem_ndunion, ndinsert_le, and_comm, cons_subset, and_left_comm, h,
and_assoc])
Multiset.subset_ndunion_left
theorem
(s t : Multiset α) : s ⊆ ndunion s t
theorem subset_ndunion_left (s t : Multiset α) : s ⊆ ndunion s t := fun _ h =>
mem_ndunion.2 <| Or.inl h
Multiset.le_ndunion_left
theorem
{s} (t : Multiset α) (d : Nodup s) : s ≤ ndunion s t
theorem le_ndunion_left {s} (t : Multiset α) (d : Nodup s) : s ≤ ndunion s t :=
(le_iff_subset d).2 <| subset_ndunion_left _ _
Multiset.ndunion_le_union
theorem
(s t : Multiset α) : ndunion s t ≤ s ∪ t
theorem ndunion_le_union (s t : Multiset α) : ndunion s t ≤ s ∪ t :=
ndunion_le.2 ⟨subset_of_le le_union_left, le_union_right⟩
Multiset.Nodup.ndunion
theorem
(s : Multiset α) {t : Multiset α} : Nodup t → Nodup (ndunion s t)
theorem Nodup.ndunion (s : Multiset α) {t : Multiset α} : Nodup t → Nodup (ndunion s t) :=
Quot.induction_on₂ s t fun _ _ => List.Nodup.union _
Multiset.ndunion_eq_union
theorem
{s t : Multiset α} (d : Nodup s) : ndunion s t = s ∪ t
@[simp]
theorem ndunion_eq_union {s t : Multiset α} (d : Nodup s) : ndunion s t = s ∪ t :=
le_antisymm (ndunion_le_union _ _) <| union_le (le_ndunion_left _ d) (le_ndunion_right _ _)
Multiset.dedup_add
theorem
(s t : Multiset α) : dedup (s + t) = ndunion s (dedup t)
theorem dedup_add (s t : Multiset α) : dedup (s + t) = ndunion s (dedup t) :=
Quot.induction_on₂ s t fun _ _ => congr_arg ((↑) : List α → Multiset α) <| dedup_append _ _
Multiset.Disjoint.ndunion_eq
theorem
{s t : Multiset α} (h : Disjoint s t) : s.ndunion t = s.dedup + t
theorem Disjoint.ndunion_eq {s t : Multiset α} (h : Disjoint s t) :
s.ndunion t = s.dedup + t := by
induction s, t using Quot.induction_on₂
exact congr_arg ((↑) : List α → Multiset α) <| List.Disjoint.union_eq <| by simpa using h
Multiset.Subset.ndunion_eq_right
theorem
{s t : Multiset α} (h : s ⊆ t) : s.ndunion t = t
theorem Subset.ndunion_eq_right {s t : Multiset α} (h : s ⊆ t) : s.ndunion t = t := by
induction s, t using Quot.induction_on₂
exact congr_arg ((↑) : List α → Multiset α) <| List.Subset.union_eq_right h
Multiset.ndinter
definition
(s t : Multiset α) : Multiset α
/-- `ndinter s t` is the lift of the list `∩` operation. This operation
does not respect multiplicities, unlike `s ∩ t`, but it is suitable as
an intersection operation on `Finset`. (`s ∩ t` would also work as a union operation
on finset, but this is more efficient.) -/
def ndinter (s t : Multiset α) : Multiset α :=
filter (· ∈ t) s
Multiset.coe_ndinter
theorem
(l₁ l₂ : List α) : @ndinter α _ l₁ l₂ = (l₁ ∩ l₂ : List α)
@[simp]
theorem coe_ndinter (l₁ l₂ : List α) : @ndinter α _ l₁ l₂ = (l₁ ∩ l₂ : List α) := by
simp only [ndinter, mem_coe, filter_coe, coe_eq_coe, ← elem_eq_mem]
apply Perm.refl
Multiset.zero_ndinter
theorem
(s : Multiset α) : ndinter 0 s = 0
@[simp]
theorem zero_ndinter (s : Multiset α) : ndinter 0 s = 0 :=
rfl
Multiset.cons_ndinter_of_mem
theorem
{a : α} (s : Multiset α) {t : Multiset α} (h : a ∈ t) : ndinter (a ::ₘ s) t = a ::ₘ ndinter s t
@[simp]
theorem cons_ndinter_of_mem {a : α} (s : Multiset α) {t : Multiset α} (h : a ∈ t) :
ndinter (a ::ₘ s) t = a ::ₘ ndinter s t := by simp [ndinter, h]
Multiset.ndinter_cons_of_not_mem
theorem
{a : α} (s : Multiset α) {t : Multiset α} (h : a ∉ t) : ndinter (a ::ₘ s) t = ndinter s t
Multiset.mem_ndinter
theorem
{s t : Multiset α} {a : α} : a ∈ ndinter s t ↔ a ∈ s ∧ a ∈ t
@[simp]
theorem mem_ndinter {s t : Multiset α} {a : α} : a ∈ ndinter s ta ∈ ndinter s t ↔ a ∈ s ∧ a ∈ t := by
simp [ndinter, mem_filter]
Multiset.Nodup.ndinter
theorem
{s : Multiset α} (t : Multiset α) : Nodup s → Nodup (ndinter s t)
@[simp]
theorem Nodup.ndinter {s : Multiset α} (t : Multiset α) : Nodup s → Nodup (ndinter s t) :=
Nodup.filter _
Multiset.le_ndinter
theorem
{s t u : Multiset α} : s ≤ ndinter t u ↔ s ≤ t ∧ s ⊆ u
theorem le_ndinter {s t u : Multiset α} : s ≤ ndinter t u ↔ s ≤ t ∧ s ⊆ u := by
simp [ndinter, le_filter, subset_iff]
Multiset.ndinter_le_left
theorem
(s t : Multiset α) : ndinter s t ≤ s
theorem ndinter_le_left (s t : Multiset α) : ndinter s t ≤ s :=
(le_ndinter.1 le_rfl).1
Multiset.ndinter_subset_left
theorem
(s t : Multiset α) : ndinter s t ⊆ s
theorem ndinter_subset_left (s t : Multiset α) : ndinterndinter s t ⊆ s :=
subset_of_le (ndinter_le_left s t)
Multiset.ndinter_subset_right
theorem
(s t : Multiset α) : ndinter s t ⊆ t
theorem ndinter_subset_right (s t : Multiset α) : ndinterndinter s t ⊆ t :=
(le_ndinter.1 le_rfl).2
Multiset.ndinter_le_right
theorem
{s} (t : Multiset α) (d : Nodup s) : ndinter s t ≤ t
theorem ndinter_le_right {s} (t : Multiset α) (d : Nodup s) : ndinter s t ≤ t :=
(le_iff_subset <| d.ndinter _).2 <| ndinter_subset_right _ _
Multiset.inter_le_ndinter
theorem
(s t : Multiset α) : s ∩ t ≤ ndinter s t
theorem inter_le_ndinter (s t : Multiset α) : s ∩ t ≤ ndinter s t :=
le_ndinter.2 ⟨inter_le_left, subset_of_le inter_le_right⟩
Multiset.ndinter_eq_inter
theorem
{s t : Multiset α} (d : Nodup s) : ndinter s t = s ∩ t
@[simp]
theorem ndinter_eq_inter {s t : Multiset α} (d : Nodup s) : ndinter s t = s ∩ t :=
le_antisymm (le_inter (ndinter_le_left _ _) (ndinter_le_right _ d)) (inter_le_ndinter _ _)
Multiset.ndinter_eq_zero_iff_disjoint
theorem
{s t : Multiset α} : ndinter s t = 0 ↔ Disjoint s t
theorem ndinter_eq_zero_iff_disjoint {s t : Multiset α} : ndinterndinter s t = 0 ↔ Disjoint s t := by
rw [← subset_zero]; simp [subset_iff, disjoint_left]
Multiset.Subset.ndinter_eq_left
theorem
{s t : Multiset α} (h : s ⊆ t) : s.ndinter t = s
theorem Subset.ndinter_eq_left {s t : Multiset α} (h : s ⊆ t) : s.ndinter t = s := by
induction s, t using Quot.induction_on₂
rw [quot_mk_to_coe'', quot_mk_to_coe'', coe_ndinter, List.Subset.inter_eq_left h]