Zulip Chat Archive

Stream: Is there code for X?

Topic: Explicit definition of tiny groups


Jihoon Hyun (Jun 30 2025 at 03:09):

Is there an explicit definitoin of non-trivial tiny groups, for example with cardinality 2, 3, 4, and possibly 5, 6, 7, and 8?

Kenny Lau (Jun 30 2025 at 09:42):

Jihoon Hyun said:

Is there an explicit definitoin of non-trivial tiny groups, for example with cardinality 2, 3, 4, and possibly 5, 6, 7, and 8?

QuaternionGroup, DihedralGroup

Personally I think it would be interesting to see a classification of groups of order <= 10 in mathlib! But i don't know if everyone else agrees.

Kenny Lau (Jun 30 2025 at 09:43):

Since we already have Sylow theory maybe it's even doable up to 60 (the first simple group)!

Jihoon Hyun (Jun 30 2025 at 09:49):

Kenny Lau said:

Since we already have Sylow theory maybe it's even doable up to 60 (the first simple group)!

That's probably too much for mathlib. I was just wondering if there is a definition of tiny groups, so that every element is explicit and anyone using it doesn't have to care about how it's constructed, for example the dihedral structure.

Kenny Lau (Jun 30 2025 at 09:52):

Jihoon Hyun said:

Kenny Lau said:

Since we already have Sylow theory maybe it's even doable up to 60 (the first simple group)!

That's probably too much for mathlib. I was just wondering if there is a definition of tiny groups, so that every element is explicit and anyone using it doesn't have to care about how it's constructed, for example the dihedral structure.

Yes, they're called r 0, r 1, r 2, sr 0, sr 1, sr 2.

Michael Rothgang (Jun 30 2025 at 09:52):

Kenny Lau said:

Jihoon Hyun said:

Is there an explicit definitoin of non-trivial tiny groups, for example with cardinality 2, 3, 4, and possibly 5, 6, 7, and 8?

QuaternionGroup, DihedralGroup

Personally I think it would be interesting to see a classification of groups of order <= 10 in mathlib! But i don't know if everyone else agrees.

FWIW, I would agree

Kenny Lau (Jun 30 2025 at 09:53):

Personally I don't see the point of just making abbreviations for small groups

Jihoon Hyun (Jun 30 2025 at 10:02):

Kenny Lau said:

Personally I don't see the point of just making abbreviations for small groups

Even for groups of order 2, there are Z2\mathbb{Z}_2, Z×\mathbb{Z}^{\times}, Z3×\mathbb{Z}_{3}^{\times}, and possibly more. All have different use cases, so why not have a classification of small groups and then give a single isomorphism to them, instead of making a small graph of isomorphisms?

Yaël Dillies (Jun 30 2025 at 10:04):

... but which isomorphism? :-)

Jihoon Hyun (Jun 30 2025 at 10:11):

Yaël Dillies said:

... but which isomorphism? :-)

The one from the group we have to the central group. By doing so we can make a group isomorphism from one group to the other by composing at most two isomorphism, while if not we might need to use more than that.

Yaël Dillies (Jun 30 2025 at 10:18):

What I mean to point out is that almost every group has non-trivial automorphisms. Therefore there isn't just "a single isomorphism" to the "central group". Eg xx1:C3C3x \mapsto x^{-1} : C_3 \to C_3 is a non-trivial automorphism, and therefore if you have some other group GG that's isomorphic to C3C_3 then it's not obvious which of the (two) isomorphisms GC3G \cong C_3 you should be writing down.

Jihoon Hyun (Jun 30 2025 at 11:07):

Thanks for the clarification. It seems like small groups are already classified outside mathlib, so maybe I'll wait for that to be imported to mathlib.

Kenny Lau (Jun 30 2025 at 11:07):

Jihoon Hyun said:

Kenny Lau said:

Personally I don't see the point of just making abbreviations for small groups

Even for groups of order 2, there are Z2\mathbb{Z}_2, Z×\mathbb{Z}^{\times}, Z3×\mathbb{Z}_{3}^{\times}, and possibly more. All have different use cases, so why not have a classification of small groups and then give a single isomorphism to them, instead of making a small graph of isomorphisms?

I think there are some misunderstandings here. We might be thinking about things from different perspectives. What you think mathematically about classifying small groups might not be the same as what I'm thinking.

I don't want abbreviations, and I'm claiming that I can make the classification work without using abbreviations, I'll just choose the standard group called Multiplicative (ZMod 2) (actually this highlights another problem, which is "mathematically trivial": we currently have groups with multiplication, and add groups with addition!).

And my theorem will just look like, for all group G with Fintype G and Fintype.card G = 2, Nonempty (G isomorphism with Multiplicative (ZMod 2))

my point here is that we don't need to "unify the names", which is what you're proposing by providing a "central name".

Kenny Lau (Jun 30 2025 at 11:08):

Jihoon Hyun said:

Thanks for the clarification. It seems like small groups are already classified outside mathlib, so maybe I'll wait for that to be imported to mathlib.

do you have a link? it would also be helpful (to us both) to see how they translate it to lean

Floris van Doorn (Jun 30 2025 at 11:23):

A student of mine did a project where she classified the groups of order 8: https://github.com/lucia3125/LeanCourse23/tree/master/LeanCourse/Project

Floris van Doorn (Jun 30 2025 at 11:24):

(main result)

Kenny Lau (Jun 30 2025 at 11:25):

Nice. As expected, it's fine to just work with the names we currently have.

Eric Wieser (Jun 30 2025 at 11:39):

Instead of

        Nonempty (G ≃* Multiplicative (ZMod 8))
     Nonempty (G ≃* Multiplicative (ZMod 4) × Multiplicative (ZMod 2))
     Nonempty (G ≃* Multiplicative (ZMod 2) × Multiplicative (ZMod 2) × Multiplicative (ZMod 2))
     Nonempty (G ≃* DihedralGroup 4)
     Nonempty (G ≃* QuaternionGroup 2)

does it makes sense to have something like

import Mathlib

abbrev groups := ![
  Multiplicative (ZMod 8),
  Multiplicative (ZMod 4) × Multiplicative (ZMod 2),
  Multiplicative (ZMod 2) × Multiplicative (ZMod 2) × Multiplicative (ZMod 2),
  DihedralGroup 4,
  QuaternionGroup 2]

instance :  i, Group (groups i) := by
  refine Fin.cons ?_ <| Fin.cons ?_ <| Fin.cons ?_ <| Fin.cons ?_ <| Fin.cons ?_ <| (Fin.elim0 ·) <;>
    (dsimp [groups]; infer_instance)

theorem groups_inj : ( i j, groups i ≃* groups j  i = j) := sorry

lemma groups_order_eight {G : Type*}[Group G][Fintype G](hG: Fintype.card G = 8):
     i, Nonempty (G ≃* groups i) := sorry
  ```

Eric Wieser (Jun 30 2025 at 11:39):

Or should be be using category theory and a skeleton category for classification results?

Kenny Lau (Jun 30 2025 at 11:40):

What we should be doing is an auxiliary type Classified n with API for easy use

Kenny Lau (Jun 30 2025 at 11:40):

once you have the API I don't really care if you're using skeleton or any other formulation

Kenny Lau (Jun 30 2025 at 11:41):

(actually skeleton might be bad, one bad thing about category is that they're not universe polymorphic, sadly)

Eric Wieser (Jun 30 2025 at 11:45):

I think you're in universe trouble whatever you do

Kenny Lau (Jun 30 2025 at 11:47):

No, group isomorphism is universe polymorphic

Eric Wieser (Jun 30 2025 at 11:49):

Sure, but my groups above is not

Eric Wieser (Jun 30 2025 at 11:50):

Nor will any Classified type you produce be

Eric Wieser (Jun 30 2025 at 11:50):

Here's the skeleton API:

import Mathlib


instance classification : Fintype
    {G : CategoryTheory.Skeleton Grp.{0} |  i : Fintype G, Fintype.card G = 8} =
    CategoryTheory.toSkeleton '' {
      Grp.of <| Multiplicative (ZMod 8),
      Grp.of <| Multiplicative (ZMod 4) × Multiplicative (ZMod 2),
      Grp.of <| Multiplicative (ZMod 2) × Multiplicative (ZMod 2) × Multiplicative (ZMod 2),
      Grp.of <| DihedralGroup 4,
      Grp.of <| QuaternionGroup 2
    } := sorry

Kim Morrison (Jun 30 2025 at 11:57):

Tiny groups live in Type 0, I promise. :-) (In fact, Type 0 is even big enough for the monster. :-)

Eric Wieser (Jun 30 2025 at 11:59):

At any rate, any kind of classification that can be written as a chain of Nonemptys can be lifted into some maximal universe (which indeed happens to be 0 here)

Kenny Lau (Jun 30 2025 at 11:59):

Eric Wieser said:

Nor will any Classified type you produce be

import Mathlib

universe u

/-- A classification of groups of order `n`. -/
class Classified (n : ) : Type 1 where
  (number : )
  (groups : Fin number  Type) [group :  i, Group (groups i)]
  (distinct (i j) : groups i  groups j  i = j)
  (classifies (G : Type u) [Group G] [Fintype G] (hg : Fintype.card G = n) :
     i, Nonempty (G ≃* groups i))

Eric Wieser (Jun 30 2025 at 12:00):

Right, all your groups live in Type, so also not universe polymorphic

Eric Wieser (Jun 30 2025 at 12:00):

Oh, your point was that you want polymorphism in the input G, not within the classifications

Kenny Lau (Jun 30 2025 at 12:00):

yes

Aaron Liu (Jun 30 2025 at 12:00):

There're all finite, so you can just Shrink them if you need to

Kenny Lau (Jun 30 2025 at 12:02):

import Mathlib

universe u

/-- A classification of groups of order `n`. -/
class Classified (n : ) : Type 1 where
  number : 
  groups : Fin number  Type
  group :  i, Group (groups i)
  distinct (i j) : groups i  groups j  i = j
  classifies (G : Type u) [Group G] [Fintype G] (hg : Fintype.card G = n) :
     i, Nonempty (G ≃* groups i)

namespace Classified

instance : Classified.{u} 0 where
  number := 0
  groups := nofun
  group := nofun
  distinct := nofun
  classifies _ _ _ _ := by aesop

end Classified

Kenny Lau (Jun 30 2025 at 12:03):

0 has been done for you :slight_smile: 1 is left as an exercise

Jireh Loreaux (Jun 30 2025 at 13:28):

Classified is wrong.

  1. It never says the groups have order n
  2. It says that if there is a bijection between them, then they're equal. It should say if they're isomorphic then they're equal.

Eric Wieser (Jun 30 2025 at 13:47):

Isn't 1 implied by classifies?

Kenny Lau (Jun 30 2025 at 13:50):

it isn't, there could still be junk values that G is just never isomorphic to

Kenny Lau (Jun 30 2025 at 13:53):

import Mathlib

universe u

/-- A classification of groups of order `n`. -/
class Classified (n : ) : Type 1 where
  number : 
  groups : Fin number  Type
  group (i) : Group (groups i)
  fintype (i) : Fintype (groups i)
  card (i) : Fintype.card (groups i) = n
  distinct (i j) : groups i ≃* groups j  i = j
  classifies (G : Type u) [Group G] [Fintype G] (hg : Fintype.card G = n) :
     i, Nonempty (G ≃* groups i)

attribute [instance] Classified.group Classified.fintype

namespace Classified

instance : Classified.{u} 0 where
  number := 0
  groups := nofun
  group := nofun
  fintype := nofun
  card := nofun
  distinct := nofun
  classifies _ _ _ _ := by aesop

lemma unique' {n : } (x y : Classified n) :  e : Fin x.number  Fin y.number,
     i, Nonempty (x.groups i ≃* y.groups (e i)) := by
  refine
  { toFun i := (y.classifies (ULift <| x.groups i) (by simp [card])).choose
     invFun j := (x.classifies (ULift <| y.groups j) (by simp [card])).choose
     left_inv i := x.distinct _ _ sorry
     right_inv j := y.distinct _ _ sorry },
  fun i  sorry⟩⟩

end Classified

Kenny Lau (Jun 30 2025 at 14:05):

now with a uniqueness lemma with 3 sorries!

Kevin Buzzard (Jun 30 2025 at 15:08):

This Classified class comes with the universe footgun; there's a universe in the fields which is not in the inputs, so the moment you forget to write Classified.{u} Lean starts timing out when attempting to figure out the maximally general universe set-up for declarations using it. Surely better to stick with the claim that we're classifying groups in Type and then if the user is unlucky enough to have a finite group in Type u then make it their problem to descend it to Type first.

Jireh Loreaux (Jun 30 2025 at 15:40):

Yes, this kind of pattern arises in other places too. The example that comes to mind (only because I happened to write it) is docs#TietzeExtension, where it would have been possible (and indeed, I originally did) to write the extension in terms of a closed embedding from a third type (instead of a from a closed subset) as in docs#ContinuousMap.exists_extension, but this would have involved a third universe parameter which is not really relevant to the type class. But after you have the class, you can write the universe polymorphic theorem that you want.

Kenny Lau (Jun 30 2025 at 15:43):

sounds like a problem with Lean...

Kevin Buzzard (Jun 30 2025 at 15:43):

Maybe, but it's still a footgun.

Kenny Lau (Jun 30 2025 at 16:15):

Actually, I can do better!

Kenny Lau (Jun 30 2025 at 16:18):

import Mathlib

universe u

/-- A classification of groups of order `n`. -/
class Classified (n : ) : Type 1 where
  number : 
  groups : Fin number  Type
  group (i) : Group (groups i)
  fintype (i) : Fintype (groups i)
  card (i) : Fintype.card (groups i) = n
  distinct (i j) : groups i ≃* groups j  i = j
  classifies' (G : Type) [Group G] [Fintype G] (hg : Fintype.card G = n) :
     i, Nonempty (G ≃* groups i)

attribute [instance] Classified.group Classified.fintype

namespace Classified

instance : Classified 0 where
  number := 0
  groups := nofun
  group := nofun
  fintype := nofun
  card := nofun
  distinct := nofun
  classifies' _ _ _ _ := by aesop

lemma classifies {n : } [Classified n] (G : Type u) [Group G] [Fintype G] (hg : Fintype.card G = n) :
     i, Nonempty (G ≃* groups (n := n) i) :=
  let i, e⟩⟩ := classifies' (n := n) (Shrink G) (by simp [hg]);
  i, Shrink.mulEquiv.symm.trans e⟩⟩

lemma unique' {n : } (x y : Classified n) :  e : Fin x.number  Fin y.number,
     i, Nonempty (x.groups i ≃* y.groups (e i)) := by
  refine
  { toFun i := (y.classifies' (x.groups i) (by simp [card])).choose
     invFun j := (x.classifies' (y.groups j) (by simp [card])).choose
     left_inv i := x.distinct _ _ sorry
     right_inv j := y.distinct _ _ sorry },
  fun i  sorry⟩⟩

end Classified

Kenny Lau (Jun 30 2025 at 16:19):

Thanks a lot for the reminder, you only have to classify groups in Type 0, and you automatically get that groups in Type u are still classified!

Kenny Lau (Jun 30 2025 at 16:19):

@Kevin Buzzard

Jz Pan (Jun 30 2025 at 16:22):

Actually your Classified can live in Type 0 but you need to do some stupid things

Jz Pan (Jun 30 2025 at 16:24):

Just like here Sequence.NonIsoSubgroupsSymm

Kenny Lau (Jun 30 2025 at 16:24):

I'm not sure the "stupid things" is worth it

Kenny Lau (Jun 30 2025 at 16:24):

you can just use unique to Shrink it if you really wanted to

Jz Pan (Jun 30 2025 at 16:25):

I mean you can realize every group of order n as a subgroup of S_n of order n, so you don't need to mention Type at all in Classified

Jz Pan (Jun 30 2025 at 16:25):

Just like the link I gave in sequencelib

Kenny Lau (Jun 30 2025 at 16:26):

i want my defeqs to Multiplicative ZMod 37

Jz Pan (Jun 30 2025 at 16:28):

Kenny Lau said:

i want my defeqs to Multiplicative ZMod 37

(A group of order 37) ≃* (some stupid internal thing but is unique) ≃* Multiplicative ZMod 37

Kenny Lau (Jun 30 2025 at 16:30):

but how would Classified generate Muliplicative ZMod 37

Jz Pan (Jun 30 2025 at 16:31):

Kenny Lau said:

but how would Classified generate Muliplicative ZMod 37

You call classification on (A group of order 37) and Multiplicative ZMod 37, get two isomorphisms, then compose them

Kenny Lau (Jun 30 2025 at 16:41):

hmm... that could work ...

Thomas Browning (Jun 30 2025 at 21:11):

Floris van Doorn said:

A student of mine did a project where she classified the groups of order 8: https://github.com/lucia3125/LeanCourse23/tree/master/LeanCourse/Project

From this it should be pretty easy to get groups of order <= 11 since we have docs#IsPGroup.commGroupOfCardEqPrimeSq and docs#isZGroup_iff_exists_mulEquiv (group of squarefree order is a semidirect product of cyclic groups).

Kenny Lau (Jun 30 2025 at 21:53):

but what about 8? :slight_smile:

Kevin Buzzard (Jun 30 2025 at 22:11):

8 is done -- see above

Kenny Lau (Jun 30 2025 at 22:13):

ah, sorry I misunderstood


Last updated: Dec 20 2025 at 21:32 UTC