Zulip Chat Archive

Stream: mathlib4

Topic: Multiset of fixed cardinality


Martin Dvořák (Mar 11 2024 at 07:37):

I would like to work with multisets of fixed cardinality.
MWE:

import Mathlib.Data.List.OfFn
open scoped List

-- `n`-ary operation on `α`
abbrev MyOperation (α : Type) (n : ) : Type := (Fin n  α)  α

-- permuting the input does not change the output
def MyOperation.IsSymmetric {α : Type} {n : } (g : MyOperation α n) : Prop :=
   x y : Fin n  α, List.ofFn x ~ List.ofFn y  g x = g y

For those operations that happen to be symmetric, I would like to convert them to a function Multiset α → α but only on multisets of cardinality n. The motivation is that I do a lot of summations later. Working with Multiset.sum should be easier than with List.sum since I already have Finset.sum elsewhere and they will have to be compared.

Do we have such a notion in Mathlib? I could use a subtype, but it wouldn't be very convenient.

Eric Wieser (Mar 11 2024 at 08:10):

docs#Sym is that notion.

Martin Dvořák (Mar 11 2024 at 08:16):

Thanks a lot!

Martin Dvořák (Mar 11 2024 at 08:37):

Eric Wieser said:

docs#Sym is that notion.

Should
https://github.com/leanprover-community/mathlib4/blob/c671da20f0a9c6375a329f6b4a723ba9e0d8eb5a/Mathlib/Combinatorics/Optimization/ValuedCSP.lean#L120
be refactored to

 g  ω, some_existing_Mathlib_notion g

for better compatibility with Sym please?

I would like to know if there is more API that I could (and indeed should) reüse.

Eric Wieser (Mar 11 2024 at 09:02):

I would have gone with

def FractionalOperation.IsSymmetric (ω : FractionalOperation D m) : Prop :=
   (σ : Equiv.Perm (Fin m)),  g  ω, g   σ = g

Eric Wieser (Mar 11 2024 at 09:03):

But that's probably less not more compatible with Sym

Martin Dvořák (Mar 11 2024 at 09:10):

Is there a canonical way to "require symmetry" before converting an operation to Sym please?

Eric Wieser (Mar 11 2024 at 09:52):

What do you mean by "converting to Sym"?

Martin Dvořák (Mar 11 2024 at 10:22):

Eric Wieser said:

What do you mean by "converting to Sym"?

def FractionalOperation.IsSymmetric.toSym {ω : FractionalOperation D m} ( : ω.IsSymmetric) :
    Multiset (Sym D m  D) := sorry

Martin Dvořák (Mar 11 2024 at 10:24):

In particular, I want to convert every term of the (Fin m → D) → D type to a term of the Sym D m → D type.

Martin Dvořák (Mar 11 2024 at 10:24):

Which also brings up a question whether there is a canonical conversion from Sym D m to Fin m → D.

Martin Dvořák (Mar 11 2024 at 10:31):

This is not a usual conversion, is it? I guess it is up to me how I do it and then I have to write the API myself?

Martin Dvořák (Mar 11 2024 at 10:54):

Perhaps I should build on top of docs#Sym.ofVector ...

Eric Wieser (Mar 11 2024 at 11:00):

Martin Dvořák said:

Which also brings up a question whether there is a canonical conversion from Sym D m to Fin m → D.

No, this direction cannot be canonical (unless you can sort D or similar)

Martin Dvořák (Mar 11 2024 at 11:01):

Sorry, I misused the word "canonical". I meant standard.

Martin Dvořák (Mar 11 2024 at 11:03):

Martin Dvořák said:

Perhaps I should build on top of docs#Sym.ofVector ...

Together with docs#Vector.ofFn should work.

Martin Dvořák (Mar 11 2024 at 11:06):

Well, I am the other way around...

Martin Dvořák (Mar 11 2024 at 11:23):

I manage to put together this conversion

import Mathlib.Data.Sym.Basic

noncomputable def Function.ofSym {D : Type*} {m : }
    (x : Sym D m) (i : Fin m) : D := by
  refine (x.attach.toMultiset.toList.get (Fin.cast ?_ i)).1
  rw [Sym.coe_attach, Multiset.length_toList, Multiset.attach, Multiset.card_pmap]
  exact x.property.symm

but it feels very very very wrong.

Martin Dvořák (Mar 11 2024 at 11:35):

Don't get me wrong — the noncomputable is not the problem — I will end up having noncomputable in one place or the other either way. The "body" of the definition is horrendous!

Antoine Chambert-Loir (Mar 11 2024 at 12:55):

Then just prove that the map you see is surjective and take a right inverse for the one you want, using docs#Function.surjInv

Eric Wieser (Mar 11 2024 at 14:05):

I think that's probably a worse approach here, because you lose the ability to translate to toList

Eric Wieser (Mar 11 2024 at 14:06):

I don't see why you needed the attach; why not just x.toMultiset.toList.get (Fin.cast ?_ i)?

Martin Dvořák (Mar 11 2024 at 14:12):

You are completely right! I thought I was losing the property, but I was wrong, fortunately.
This works:

import Mathlib.Data.Sym.Basic

noncomputable def Function.ofSym (x : Sym D m) (i : Fin m) : D := by
  refine x.toMultiset.toList.get (Fin.cast ?_ i)
  rw [Multiset.length_toList]
  exact x.property.symm

Martin Dvořák (Mar 11 2024 at 14:17):

Better:

import Mathlib.Data.Sym.Basic

lemma Sym.toMultiset_toList_length (x : Sym D m) : x.toMultiset.toList.length = m := by
  rw [Multiset.length_toList]
  exact x.property

noncomputable def Function.ofSym (x : Sym D m) (i : Fin m) : D :=
  x.toMultiset.toList.get (Fin.cast x.toMultiset_toList_length.symm i)

Last updated: May 02 2025 at 03:31 UTC