Zulip Chat Archive

Stream: mathlib4

Topic: Multiset.powerset lemmas


Alessandra Simmons (Feb 17 2026 at 20:07):

I formalized a few small lemmas relating to Multiset.powerset (mainly Monotonicity and Injectivity, but also a few small utility lemmas), and I think they would probably be useful results to someone else, but I've never contributed to Mathlib before.

Could I get a second opinion on if these are good candidates for inclusion in Mathlib, and if any of them should be cut?

Ruben Van de Velde (Feb 17 2026 at 20:43):

Seems mostly sensible; some suggestions below:

import Mathlib

-- Not about Multisets
def ne_cards_ne {α : Type} {m n : Multiset α} : m.card  n.card  m  n :=
  ne_of_apply_ne _

-- Not about Multisets
def ne_one_not_empty {α : Type} {m n : Multiset α} : m  n  m  0  n  0 :=
  fun a => Ne.ne_or_ne 0 a

def self_ne_cons {α : Type} {m : Multiset α} {a : α} : m  a ::ₘ m := by
  induction m using Multiset.induction
  case empty =>
    exact Multiset.zero_ne_cons
  case cons head tail ih =>
    rw [@Multiset.cons_swap, ne_eq, Multiset.cons_inj_right]
    exact Ne.intro ih

def ne_exists_nonmember {α : Type} {m n : Multiset α} [DecidableEq α] : m  n   a, m.count a  n.count a := by
  contrapose!
  exact Multiset.ext.mpr

-- Should be called something like powerset_eq_singleton_empty_iff in this direction
def empty_iff_powerset_empty {α : Type} {m : Multiset α} : m.powerset = {0}  m = 0 where
  mpr := by
    rintro rfl
    exact Multiset.powerset_zero
  mp powerset := by
    simpa using congr(Multiset.card $powerset)

-- zero_mem_powerset
def empty_in_powerset {α : Type} {m : Multiset α} : 0  m.powerset :=
  Multiset.mem_powerset.mpr m.zero_le

-- self_mem_powerset
def self_in_powerset {α : Type} {m : Multiset α} : m  m.powerset :=
  Multiset.mem_powerset.mpr le_rfl

def List.Subperm.append {l₁ l₂ r₁ r₂ : List α}
    (hl : l₁.Subperm l₂) (hr : r₁.Subperm r₂) :
    (l₁ ++ r₁).Subperm (l₂ ++ r₂) := by
  obtain l, hl_perm, hl_sub := hl
  obtain r, hr_perm, hr_sub := hr
  exact l ++ r, hl_perm.append hr_perm, hl_sub.append hr_sub

def List.Subperm.map {l₁ l₂ : List α} (f : α  β)
    (h : l₁.Subperm l₂) :
    (l₁.map f).Subperm (l₂.map f) := by
  obtain l, hl_perm, hl_sub := h
  exact l.map f, hl_perm.map f, hl_sub.map f

def List.Subperm.sublists'_subperm_sublists' {l₁ l₂ : List α}
    (sublist : l₁.Sublist l₂) :
    l₁.sublists'.Subperm l₂.sublists' := by
  induction sublist with
  | slnil => exact .refl _
  | cons a _ ih =>
    rw [List.sublists'_cons]
    exact ih.trans (List.sublist_append_left ..).subperm
  | cons₂ a _ ih =>
    rw [List.sublists'_cons, List.sublists'_cons]
    exact ih.append (ih.map _)

def le_powerset_iff_le {α : Type} {m n : Multiset α} : m.powerset  n.powerset  m  n where
  mp powerset := Multiset.mem_powerset.mp <| Multiset.mem_of_le powerset self_in_powerset
  mpr le :=
    Multiset.leInductionOn le fun {l₁ l₂} hsub => by
      rw [Multiset.powerset_coe', Multiset.powerset_coe', Multiset.coe_le]
      exact (List.Subperm.sublists'_subperm_sublists' hsub).map Multiset.ofList

instance powerset_mono {α : Type} : Monotone (@Multiset.powerset α) := by
  unfold Monotone
  intro a₁ a₂ a
  exact le_powerset_iff_le.mpr a

-- Should be powerset_injective
instance powerset_inj {α : Type} : Function.Injective (@Multiset.powerset α) := by
  unfold Function.Injective
  intro a₁ a₂ a
  exact le_antisymm
    (le_powerset_iff_le.mp (le_of_eq a))
    (le_powerset_iff_le.mp (le_of_eq a.symm))

Alessandra Simmons (Feb 18 2026 at 00:23):

Hey, thanks for the suggestions! I thought that the naming changes made sense given the policy, that the Ne results being unrelated to Multisets made a lot of sense, and that a lot of your definitions seemed a lot simpler/more maintainable, so I opened a PR against Mathlib with those revisions (and a few other changes): https://github.com/leanprover-community/mathlib4/pull/35465

Violeta Hernández (Feb 20 2026 at 00:18):

You can also write #35465 to link to your PRs more easily


Last updated: Feb 28 2026 at 14:05 UTC