Zulip Chat Archive
Stream: general
Topic: useful group theory lemmas
Frederick Pu (Oct 19 2025 at 00:58):
While doing some group theory assignment questions I came across some lemmas that I can't find in mathlib that may be useful:
theorem card_subgroupOf {G : Type*} [Group G] (H K : Subgroup G) (h : H ≤ K) : Nat.card (H.subgroupOf K) = Nat.card H := by
conv =>
enter [2]
rw [← Subgroup.map_subgroupOf_eq_of_le h]
symm
apply Subgroup.card_map_of_injective
exact Subgroup.subtype_injective K
theorem term_match {G : Type*} [Group G] (a1 a2 b1 b2 : G) : a1 * b1 = a2 * b2 → a2⁻¹ * a1 = b2 * b1⁻¹ := by
intro h
have : a1 = (a2 * b2) * b1⁻¹ := by exact eq_mul_inv_of_mul_eq h
rw [this]
group
#check Subgroup
open Classical
theorem card_mul_disjoint {G : Type*} [Group G] [Fintype G] (H K : Subgroup G) (hHK : Disjoint H K) : Finset.card {g | ∃ h ∈ H, ∃ k ∈ K, g = h * k } = Nat.card H * Nat.card K := by sorry
If anyone has a way of phrasing theorem card_mul_disjoint {G : Type*} [Group G] [Fintype G] (H K : Subgroup G) (hHK : Disjoint H K) : Finset.card {g | ∃ h ∈ H, ∃ k ∈ K, g = h * k } = Nat.card H * Nat.card K := by sorry in terms of set multiplication that would be great
Aaron Liu (Oct 19 2025 at 01:45):
definitely don't open Classical for the statement
Frederick Pu (Oct 19 2025 at 01:45):
I cant get access to the set mul operation for some reason
Aaron Liu (Oct 19 2025 at 01:46):
how about this
open scoped Pointwise in
theorem card_mul_disjoint {G : Type*} [Group G] [Fintype G] (H K : Subgroup G) (hHK : Disjoint H K) :
Nat.card ((H : Set G) * (K : Set G)) = Nat.card H * Nat.card K := by
sorry
Frederick Pu (Oct 19 2025 at 01:46):
ah that was the issue lol
Frederick Pu (Oct 19 2025 at 01:46):
i didnt know what pointwise was
Frederick Pu (Oct 19 2025 at 01:47):
so is + the minkowski sum then
Aaron Liu (Oct 19 2025 at 01:47):
correct
Aaron Liu (Oct 19 2025 at 01:47):
but it's scoped to Pointwise
Aaron Liu (Oct 19 2025 at 01:47):
since it's pointwise
Frederick Pu (Oct 19 2025 at 02:00):
is card_mul_disjoint something that is already in mathlib
Aaron Liu (Oct 19 2025 at 02:00):
I don't know
Aaron Liu (Oct 19 2025 at 02:00):
probably something more useful would be the equiv version
Aaron Liu (Oct 19 2025 at 02:01):
open scoped Pointwise in
def Subgroup.coeMulCoeEquivProdOfDisjoint {G : Type*} [Group G] (H K : Subgroup G) (hHK : Disjoint H K) :
((H : Set G) * (K : Set G)) ≃ H × K := by
sorry
Frederick Pu (Oct 19 2025 at 02:01):
Here's the proof btw
open scoped Pointwise in
theorem card_mul_disjoint {G : Type*} [Group G] [Fintype G] (H K : Subgroup G) (hHK : Disjoint H K) : Set.ncard ((H.carrier : Set G) * (K.carrier : Set G) : Set G) = Nat.card H * Nat.card K := by
have : Nat.card H = Set.ncard H.carrier := by exact rfl
rw [this]
have : Nat.card K = Set.ncard K.carrier := by exact rfl
rw [this]
rw [← Set.ncard_prod]
symm
apply Set.ncard_congr (fun (h, k) _ => h * k)
intro ⟨h, k⟩ HH
simp at HH
simp
use h
use HH.1
use k
use HH.2
simp only [Finset.coe_product, Set.coe_toFinset]
intro ⟨h1, k1⟩ ⟨h2, k2⟩
intro H1 H2
intro HH
simp at HH
have crux := term_match _ _ _ _ HH
rw [Subgroup.disjoint_def] at hHK
have : h2⁻¹ * h1 ∈ H := by
have : h2⁻¹ ∈ H := by exact (Subgroup.inv_mem_iff H).mpr (H2.1)
exact (Subgroup.mul_mem_cancel_right H H1.1).mpr this
specialize hHK this
have : k2 * k1⁻¹ ∈ K := by
have : k1⁻¹ ∈ K := by exact (Subgroup.inv_mem_iff K).mpr (H1.2)
exact (Subgroup.mul_mem_cancel_right K this).mpr H2.2
rw [← crux] at this
specialize hHK this
have : h2 * (h2 ⁻¹ * h1) = h2 * 1 := by
rw [hHK]
group at this
have : (k2 * k1⁻¹) * k1 = 1 * k1 := by
rw [← crux, hHK]
group at this
simp
tauto
intro g hg
simp at hg
obtain ⟨h, hh, k, hk, HH⟩ := hg
simp only [Finset.coe_product, Set.coe_toFinset, Set.image_prod, Set.image2_mul]
use ⟨h, k⟩
simp only [mem_prod, Subsemigroup.mem_carrier, Submonoid.mem_toSubsemigroup,
Subgroup.mem_toSubmonoid, exists_prop]
tauto
Aaron Liu (Oct 19 2025 at 02:01):
since this equiv version is now applicable to infinite groups
Frederick Pu (Oct 19 2025 at 02:02):
could you even make teh equivalence a group hom ?
Frederick Pu (Oct 19 2025 at 02:02):
like≃* or whateer
Aaron Liu (Oct 19 2025 at 02:02):
I don't think this pointwise product is always a subgroup
Frederick Pu (Oct 19 2025 at 02:03):
oh yeah it isnt for non abelian groups
Aaron Liu (Oct 19 2025 at 02:03):
unless they normalize each other or something
Frederick Pu (Oct 19 2025 at 02:04):
is there a linarith but for groups?
Frederick Pu (Oct 19 2025 at 02:04):
i find i have to prove a lot of trivial things a lot
Aaron Liu (Oct 19 2025 at 02:05):
like a tactic for groups?
Aaron Liu (Oct 19 2025 at 02:05):
well there's group for multiplicatively written groups
Frederick Pu (Oct 19 2025 at 02:05):
but group is only a terminal tactic anddoesnt use local hyps
Aaron Liu (Oct 19 2025 at 02:05):
and there's abel for additively written commutative groups
Frederick Pu (Oct 19 2025 at 02:05):
so i you have multiple equalities you want to combine
Aaron Liu (Oct 19 2025 at 02:06):
Frederick Pu said:
so i you have multiple equalities you want to combine
isn't that the word problem then which is undecidable
Frederick Pu (Oct 19 2025 at 02:06):
i mean yeah but in a lot of cases it's something that grind could solve with the right lemmas
Frederick Pu (Oct 19 2025 at 02:07):
presumably if you're writing a proof your expressions will be quite simple
Frederick Pu (Oct 19 2025 at 02:07):
like i had to congrArg + group a lot which is just very tedious
Frederick Pu (Oct 19 2025 at 02:07):
like maybe if group was a grind ruleset rather than a simp one it could be stronger
Aaron Liu (Oct 19 2025 at 02:07):
do you know about rw and calc and congr()
Frederick Pu (Oct 19 2025 at 02:08):
i also use calc sometimes
Aaron Liu (Oct 19 2025 at 02:08):
and oh cccc was replaced by grind
Frederick Pu (Oct 19 2025 at 02:08):
i usually have to multiple on both sides somehting or cancel on both sides
Frederick Pu (Oct 19 2025 at 02:09):
so you cant use calc for that
Aaron Liu (Oct 19 2025 at 02:09):
and simp is really great too
Aaron Liu (Oct 19 2025 at 02:09):
lots of things I think you could probably just do simpa using congr(...) for some appropriately chosen ...
Frederick Pu (Oct 19 2025 at 02:10):
can you give an example im not too familiar with this syntax
Aaron Liu (Oct 19 2025 at 02:10):
Frederick Pu said:
so you cant use calc for that
well having a group is really great since cancelling is just congrarg with multiplying by the inverse
Aaron Liu (Oct 19 2025 at 02:10):
Frederick Pu said:
can you give an example im not too familiar with this syntax
do you have an example lemma for me to prove
Frederick Pu (Oct 19 2025 at 02:11):
still cant use calc tho cause you're chaging the goal so it's technically not transitive you're using injectivitiy
Aaron Liu (Oct 19 2025 at 02:19):
alright here's your term_match lemma
import Mathlib
theorem term_match {G : Type*} [Group G] (a1 a2 b1 b2 : G)
(h : a1 * b1 = a2 * b2) : a2⁻¹ * a1 = b2 * b1⁻¹ := by
simpa only [mul_assoc, mul_inv_cancel, mul_one, inv_mul_cancel_left] using congr(a2⁻¹ * $h * b1⁻¹)
Frederick Pu (Oct 19 2025 at 02:39):
so is $h a metavriable hole?
Aaron Liu (Oct 19 2025 at 02:51):
it's an antiquotation
Aaron Liu (Oct 19 2025 at 02:51):
read the docstring of congr()
Aaron Liu (Oct 19 2025 at 02:51):
it should appear if you hover over the congr( part
Frederick Pu (Oct 19 2025 at 02:51):
if we're proving the version of the theorem for the equiv would it need to be noncomputable?
Aaron Liu (Oct 19 2025 at 02:51):
yes
Aaron Liu (Oct 19 2025 at 02:52):
since there's no algorithm to compute it
Aaron Liu (Oct 19 2025 at 02:52):
well, one direction has no algorithm
Aaron Liu (Oct 19 2025 at 02:52):
the other direction is just the group operation
Frederick Pu (Oct 19 2025 at 02:52):
do you think i could submit a pr?
Aaron Liu (Oct 19 2025 at 02:52):
yes I think you could
Chris Henson (Oct 19 2025 at 03:16):
Here's an attempt to keep your proof structure, but golf a bit with grind:
import Mathlib
@[grind]
theorem term_match {G : Type*} [Group G] (a1 a2 b1 b2 : G)
(h : a1 * b1 = a2 * b2) : a2⁻¹ * a1 = b2 * b1⁻¹ := by
simpa only [mul_assoc, mul_inv_cancel, mul_one, inv_mul_cancel_left] using congr(a2⁻¹ * $h * b1⁻¹)
open scoped Pointwise in
theorem card_mul_disjoint {G : Type*} [Group G] [Fintype G] (H K : Subgroup G) (hHK : Disjoint H K) : Set.ncard ((H.carrier : Set G) * (K.carrier : Set G) : Set G) = Nat.card H * Nat.card K := by
have : Nat.card H = Set.ncard H.carrier := rfl
have : Nat.card K = Set.ncard K.carrier := rfl
suffices h : (H.carrier ×ˢ K.carrier).ncard = (H.carrier * K.carrier).ncard by grind [Set.ncard_prod]
apply Set.ncard_congr (fun p _ => p.1 * p.2)
· intro ⟨h, k⟩ ⟨hc, kc⟩
exact ⟨h, hc, k, kc, rfl⟩
· intro ⟨h₁, k₁⟩ ⟨h₂, k₂⟩ ⟨hc₁, kc₁⟩ ⟨hc₂, kc₂⟩ _
have : h₂⁻¹ * h₁ ∈ H := (Subgroup.inv_mem_iff H).mpr hc₂ |> (Subgroup.mul_mem_cancel_right H hc₁).mpr
have : k₂ * k₁⁻¹ ∈ K := ((Subgroup.inv_mem_iff K).mpr kc₁ |> Subgroup.mul_mem_cancel_right K).mpr kc₂
have : h₂ * (h₂ ⁻¹ * h₁) = h₂ * 1 := by grind [Subgroup.disjoint_def]
have : k₂ * k₁⁻¹ * k₁ = 1 * k₁ := by grind [Subgroup.disjoint_def]
grind [inv_mul_cancel_right, one_mul, mul_inv_cancel_left, mul_one]
· intro _ ⟨h, _, k, _, _⟩
use ⟨h, k⟩
grind
Frederick Pu (Oct 19 2025 at 03:35):
here's the version with equiv:
theorem term_match {G : Type*} [Group G] (a1 a2 b1 b2 : G) : a1 * b1 = a2 * b2 → a2⁻¹ * a1 = b2 * b1⁻¹ := by
intro h
have : a1 = (a2 * b2) * b1⁻¹ := by exact eq_mul_inv_of_mul_eq h
rw [this]
group
open scoped Pointwise in
noncomputable def card_mul_disjoint {G : Type*} [Group G] (H K : Subgroup G) (hHK : Disjoint H K) : ((H.carrier : Set G) * (K.carrier : Set G) : Set G) ≃ (H:Set G) ×ˢ (K:Set G) := by
symm
apply Set.BijOn.equiv (fun (h, k) => h * k)
apply And.intro
· intro ⟨h, k⟩ HH
simp at HH
simp
use h
use HH.1
use k
use HH.2
simp only [Finset.coe_product, Set.coe_toFinset]
apply And.intro
intro ⟨h1, k1⟩ H1 ⟨h2, k2⟩ H2
intro HH
simp at HH
have crux : h2⁻¹ * h1 = k2 * k1⁻¹ := term_match _ _ _ _ HH
rw [Subgroup.disjoint_def] at hHK
have : h2⁻¹ * h1 ∈ H := by
have : h2⁻¹ ∈ H := by exact (Subgroup.inv_mem_iff H).mpr (H2.1)
exact (Subgroup.mul_mem_cancel_right H H1.1).mpr this
specialize hHK this
have : k2 * k1⁻¹ ∈ K := by
have : k1⁻¹ ∈ K := by exact (Subgroup.inv_mem_iff K).mpr (H1.2)
exact (Subgroup.mul_mem_cancel_right K this).mpr H2.2
rw [← crux] at this
specialize hHK this
have : h2 * (h2 ⁻¹ * h1) = h2 * 1 := by
rw [hHK]
group at this
have : (k2 * k1⁻¹) * k1 = 1 * k1 := by
rw [← crux, hHK]
group at this
simp
tauto
intro g hg
obtain ⟨h, hh, k, hk, HH⟩ := hg
simp only [Finset.coe_product, Set.coe_toFinset, Set.image_prod, Set.image2_mul]
rw [Set.mem_mul]
use h
use hh
use k
use hk
Eric Wieser (Oct 19 2025 at 13:06):
Aaron Liu said:
open scoped Pointwise in def Subgroup.coeMulCoeEquivProdOfDisjoint {G : Type*} [Group G] (H K : Subgroup G) (hHK : Disjoint H K) : ((H : Set G) * (K : Set G)) ≃ H × K := by sorry
Doesn't this require commutativity? Also, I think the LHS is more canonically spelt ↥(H ⊔ K)
Michael Stoll (Oct 19 2025 at 13:08):
Eric Wieser said:
Doesn't this require commutativity? Also, I think the LHS is more canonically spelt
↥(H ⊔ K)
It does not. And note that the LHS is in general not a subgroup.
Frederick Pu (Oct 19 2025 at 15:50):
here's teh pull request: https://github.com/leanprover-community/mathlib4/pull/30667
Frederick Pu (Oct 19 2025 at 16:40):
here are some other lemmas I found useful:
theorem card_subgroupOf {G : Type*} [Group G] (H K : Subgroup G) (h : H ≤ K) : Nat.card (H.subgroupOf K) = Nat.card H := by
conv =>
enter [2]
rw [← Subgroup.map_subgroupOf_eq_of_le h]
symm
apply Subgroup.card_map_of_injective
exact Subgroup.subtype_injective K
theorem eq_of_le_card_eq {G : Type*} [Group G] [Fintype G] (H K : Subgroup G) (h : H ≤ K) : Nat.card H = Nat.card K → H = K := by
intro hh
rw [← card_subgroupOf H K h, Subgroup.card_eq_iff_eq_top] at hh
simp only [Subgroup.subgroupOf_eq_top] at hh
order
Frederick Pu (Oct 19 2025 at 16:42):
also is there somehting along the lines of if all generators of a group commute then all elements of the group commute?
Eric Wieser (Oct 19 2025 at 17:14):
Here's a slightly shorter version of that first theorem:
@[to_additive]
theorem Subgroup.card_subgroupOf_of_le {G : Type*} [Group G] (H K : Subgroup G) (h : H ≤ K) :
Nat.card (H.subgroupOf K) = Nat.card H := by
conv_rhs => rw [← map_subgroupOf_eq_of_le h]
rw [card_map_of_injective Subtype.coe_injective]
Frederick Pu (Oct 19 2025 at 17:15):
also is there something along these lines?
every decompositino of the idenetity elemebt into trapsnpositions will have an even number of transpotions
Aaron Liu (Oct 19 2025 at 17:43):
Frederick Pu said:
also is there something along these lines?
every decompositino of the idenetity elemebt into trapsnpositions will have an even number of transpotions
Frederick Pu (Oct 19 2025 at 21:57):
is there a proof that the sign for permutation is unique/well defined anywhere?
Aaron Liu (Oct 19 2025 at 22:02):
what do you mean by "well defined"?
Aaron Liu (Oct 19 2025 at 22:03):
I guess uniqueness is docs#Equiv.Perm.eq_sign_of_surjective_hom
Frederick Pu (Oct 19 2025 at 22:05):
like for example every decomposition into transpoisitions will have sign parity number of elements
Aaron Liu (Oct 19 2025 at 22:07):
I think that follows from docs#Equiv.Perm.sign_swap and the fact that it's a monoid hom
Frederick Pu (Oct 20 2025 at 15:50):
where in mathlib should these lemmas go?
theorem card_subgroupOf {G : Type*} [Group G] (H K : Subgroup G) (h : H ≤ K) : Nat.card (H.subgroupOf K) = Nat.card H := by
conv =>
enter [2]
rw [← Subgroup.map_subgroupOf_eq_of_le h]
symm
apply Subgroup.card_map_of_injective
exact Subgroup.subtype_injective K
theorem eq_of_le_card_eq {G : Type*} [Group G] [Fintype G] (H K : Subgroup G) (h : H ≤ K) : Nat.card H = Nat.card K → H = K := by
intro hh
rw [← card_subgroupOf H K h, Subgroup.card_eq_iff_eq_top] at hh
simp only [Subgroup.subgroupOf_eq_top] at hh
order
Frederick Pu (Oct 20 2025 at 15:54):
should there be a thing like to_additive for automatically getting lemmas about subgroupof from lemmas abotu group. like a to_subgroup
Kenny Lau (Oct 20 2025 at 16:14):
but we do have @[to_additive]
Ruben Van de Velde (Oct 20 2025 at 16:18):
The question was whether there should be something analogous for subgroups
Frederick Pu (Oct 21 2025 at 20:17):
Frederick Pu said:
also is there somehting along the lines of if all generators of a group commute then all elements of the
Frederick Pu (Oct 21 2025 at 20:36):
also i just realize there is no usable mem_closure_iff for non abelian groups
Frederick Pu (Oct 21 2025 at 20:48):
here's what i have so far:
import Mathlib
#check Finsupp
theorem Subgroup.mem_closure_range_iff' {ι : Type*} {G : Type*} [Group G] {f : ι → G} : ∀ x, x ∈ Subgroup.closure (Set.range f) ↔ ∃ l : List ι, x = (l.map f).prod := sorry
example {G : Type*} [Group G] (s : Set G) (hs : ∀ g ∈ s, ∀ g' ∈ s, Commute g g') : CommGroup (Subgroup.closure s) := by
constructor
intro ⟨x, hx⟩ ⟨y, hy⟩
simp only [MulMemClass.mk_mul_mk, Subtype.mk.injEq]
have hss : Set.range (fun x : s => (x.val:G)) = s := by simp only [Set.range_id', Set.image_univ,
Subtype.range_coe_subtype, Set.setOf_mem_eq]
rw [← hss, Subgroup.mem_closure_range_iff'] at hx hy
obtain ⟨xl, hxl⟩ := hx
obtain ⟨yl, hyl⟩ := hy
/-
case mul_comm
G : Type u_1
inst✝ : Group G
s : Set G
hs : ∀ g ∈ s, ∀ g' ∈ s, Commute g g'
x y : G
hss : (Set.range fun x => ↑x) = s
xl : List ↑s
hxl : x = (List.map (fun x => ↑x) xl).prod
yl : List ↑s
hyl : y = (List.map (fun x => ↑x) yl).prod
⊢ x * y = y * x
-/
sorry
Frederick Pu (Oct 21 2025 at 20:50):
i think the way to prove it is probably double induction on the length of both representative lists
Aaron Liu (Oct 21 2025 at 20:57):
I think the way to prove it involves docs#Subgroup.centralizer and some universal properties
Aaron Liu (Oct 21 2025 at 20:58):
no need to get into lists
Frederick Pu (Oct 21 2025 at 21:12):
so we would need something like centralizer (closure s) = centralizer s right?
Frederick Pu (Oct 21 2025 at 21:36):
i have no idea what is going on in this proof but after chasing the tail a bunch i got this:
example {G : Type*} [Group G] (s : Set G) (hs : ∀ g ∈ s, ∀ g' ∈ s, Commute g g') : IsMulCommutative (Subgroup.closure s) := by
rw [← Subgroup.le_centralizer_iff_isMulCommutative]
have : Subgroup.closure s ≤ Subgroup.centralizer (Subgroup.centralizer s) := by
apply Subgroup.closure_le_centralizer_centralizer
suffices : Subgroup.centralizer (Subgroup.centralizer s) ≤ (Subgroup.centralizer (Subgroup.closure s : Subgroup G) : Subgroup G)
(expose_names; exact fun ⦃x⦄ a => this (this_1 a))
suffices : Subgroup.closure s ≤ Subgroup.centralizer s
apply Subgroup.centralizer_le
exact this
suffices : Subgroup.centralizer (Subgroup.centralizer s) ≤ Subgroup.centralizer s
(expose_names; exact fun ⦃x⦄ a => this (this_1 a))
intro x hx y hy
rw [Subgroup.mem_centralizer_iff] at hx
specialize hx y
apply hx
exact fun m a => hs m a y hy
Kevin Buzzard (Oct 21 2025 at 21:36):
You could just prove it using one of the induction principles for Subgroup.closure (you could prove your mem lemma that way, but I wouldn't bother; you can just prove the application that way too). I did one sorry as an example but all 7 look straightforward to me.
import Mathlib
example {G : Type*} [Group G] (s : Set G) (hs : ∀ g ∈ s, ∀ g' ∈ s, Commute g g') : CommGroup (Subgroup.closure s) := by
constructor
intro ⟨x, hx⟩ ⟨y, hy⟩
refine Subgroup.closure_induction₂ ?_ ?_ ?_ ?_ ?_ ?_ ?_ hx hy
· sorry -- hs
· sorry -- easy
· sorry -- easy
· intros x y z _ _ _ h1 h2
ext
simp_all
rw [mul_assoc, h2, ← mul_assoc, h1, mul_assoc]
· sorry -- similar
· sorry -- easy group theory
· sorry -- easy group theory
Induction principles are almost always easier than some kind of attempt to find a way to represent a general object.
Frederick Pu (Oct 21 2025 at 21:37):
i think there's a enough machinary with the cnetralizer to not require induction
Frederick Pu (Oct 21 2025 at 21:37):
this is really good to know for the future tho!
Frederick Pu (Oct 21 2025 at 21:58):
here's the golfed version:
example {G : Type*} [Group G] (s : Set G) (hs : ∀ g ∈ s, ∀ g' ∈ s, Commute g g') : IsMulCommutative (Subgroup.closure s) := by
rw [← Subgroup.le_centralizer_iff_isMulCommutative]
apply (Subgroup.closure_le_centralizer_centralizer s).trans
apply Subgroup.centralizer_le
apply (Subgroup.closure_le_centralizer_centralizer s).trans
intro x hx y hy
rw [Subgroup.mem_centralizer_iff] at hx
exact hx y (fun m a => hs m a y hy)
Chris Henson (Oct 21 2025 at 23:12):
You can omit that last rw.
Yury G. Kudryashov (Oct 21 2025 at 23:26):
Please make it an iff lemma when you PR it.
Frederick Pu (Oct 21 2025 at 23:27):
where would this go in mathlib?
Yury G. Kudryashov (Oct 21 2025 at 23:37):
#find_home could help
Yury G. Kudryashov (Oct 21 2025 at 23:38):
BTW, I've just found out that we use both docs#Std.Commutative and docs#IsMulCommutative for lemmas/instances about groups.
Frederick Pu (Oct 21 2025 at 23:39):
i think it should probably be IsMulCommutative so we can use the typeclass instance. Also you can better use to_additive with IsMulCommutative i thihnk
Yury G. Kudryashov (Oct 21 2025 at 23:42):
UPD: we already have docs#Subgroup.closureCommGroupOfComm
Frederick Pu (Oct 21 2025 at 23:59):
it's weird that I wasn't able to find that using mathlibsearch
Frederick Pu (Oct 22 2025 at 00:02):
Kevin Buzzard said:
You could just prove it using one of the induction principles for Subgroup.closure (you could prove your mem lemma that way, but I wouldn't bother; you can just prove the application that way too). I did one sorry as an example but all 7 look straightforward to me.
import Mathlib example {G : Type*} [Group G] (s : Set G) (hs : ∀ g ∈ s, ∀ g' ∈ s, Commute g g') : CommGroup (Subgroup.closure s) := by constructor intro ⟨x, hx⟩ ⟨y, hy⟩ refine Subgroup.closure_induction₂ ?_ ?_ ?_ ?_ ?_ ?_ ?_ hx hy · sorry -- hs · sorry -- easy · sorry -- easy · intros x y z _ _ _ h1 h2 ext simp_all rw [mul_assoc, h2, ← mul_assoc, h1, mul_assoc] · sorry -- similar · sorry -- easy group theory · sorry -- easy group theoryInduction principles are almost always easier than some kind of attempt to find a way to represent a general object.
should we put this inducton rule in the docstring for Subgroup.closure i feel like that would be really helpful
Yury G. Kudryashov (Oct 22 2025 at 00:11):
I found it using loogle.
Yury G. Kudryashov (Oct 22 2025 at 00:12):
We have many ways to say "commutative".
Yury G. Kudryashov (Oct 22 2025 at 00:40):
Frederick Pu said:
i think it should probably be IsMulCommutative so we can use the typeclass instance. Also you can better use to_additive with IsMulCommutative i thihnk
@Xavier Roblot added this class.
Frederick Pu (Oct 22 2025 at 00:46):
do we want to change docs#Subgroup.closureCommGroupOfComm to be an if and only if using IsMulCommutative?
Alex Meiburg (Oct 23 2025 at 13:08):
Yury G. Kudryashov said:
We have many ways to say "commutative".
Not to mention docs#Commute. And there's not a single lemma relating Commute with Std.Commutative or IsMulCommutative! And having an IsMulCommutative lying around is also always equivalent (propositionally, and in terms of the data-carrying instances available) to CommMagma.
Frederick Pu (Oct 23 2025 at 17:50):
should we also prove the general version where teh H, K aren't disjoint for
theorem card_mul_disjoint {G : Type*} [Group G] [Fintype G] (H K : Subgroup G) (hHK : Disjoint H K) : Set.ncard ((H.carrier : Set G) * (K.carrier : Set G) : Set G) = Nat.card H * Nat.card K := by sorry
Last updated: Dec 20 2025 at 21:32 UTC