l3lab/ntp-mathlib huggingface dataset:
/-- **Class formula** for a finite group acting on a finite type. See
`MulAction.card_eq_sum_card_group_div_card_stabilizer` for a specialized version using
`Quotient.out'`. -/
@[to_additive
      "**Class formula** for a finite group acting on a finite type. See
      `AddAction.card_eq_sum_card_addGroup_div_card_stabilizer` for a specialized version using
      `Quotient.out'`."]
theorem card_eq_sum_card_group_div_card_stabilizer' [Fintype α] [Fintype β] [Fintype Ω]
    [∀ b : β, Fintype <| stabilizer α b] {φ : Ω → β} (hφ : LeftInverse Quotient.mk'' φ) :
    Fintype.card β = ∑ ω : Ω, Fintype.card α / Fintype.card (stabilizer α (φ ω)) := by
  classical
    have : ∀ ω : Ω, Fintype.card α / Fintype.card (stabilizer α (φ ω)) =
        Fintype.card (α ⧸ stabilizer α (φ ω)) := by
      intro ω
      rw [Fintype.card_congr (@Subgroup.groupEquivQuotientProdSubgroup α _ (stabilizer α <| φ ω)),
        Fintype.card_prod, Nat.mul_div_cancel]
      exact Fintype.card_pos_iff.mpr (by infer_instance)
    

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝⁶ inst✝⁵ : Group α
inst✝⁴ : MulAction α β
x : β
inst✝³ : Fintype α
inst✝² : Fintype β
inst✝¹ : Fintype (Quotient (orbitRel α β))
inst✝ : (b : β) → Fintype ↥(stabilizer α b)
φ : Quotient (orbitRel α β) → β
hφ : LeftInverse Quotient.mk'' φ
this :
  ∀ (ω : Quotient (orbitRel α β)),
    Fintype.card α / Fintype.card ↥(stabilizer α (φ ω)) = Fintype.card (α ⧸ stabilizer α (φ ω))
⊢ Fintype.card β = ∑ ω : Quotient (orbitRel α β), Fintype.card α / Fintype.card ↥(stabilizer α (φ ω))

Next tactic:
simp_rw [this, ← Fintype.card_sigma,
      Fintype.card_congr (selfEquivSigmaOrbitsQuotientStabilizer' α β hφ)]
/-- **Burnside's lemma** : given a finite group `G` acting on a set `X`, the average number of
elements fixed by each `g ∈ G` is the number of orbits. -/
@[to_additive
      "**Burnside's lemma** : given a finite additive group `G` acting on a set `X`,
      the average number of elements fixed by each `g ∈ G` is the number of orbits. "]
theorem sum_card_fixedBy_eq_card_orbits_mul_card_group [Fintype α] [∀ a : α, Fintype <| fixedBy β a]
    [Fintype Ω] : (∑ a : α, Fintype.card (fixedBy β a)) = Fintype.card Ω * Fintype.card α := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝⁵ inst✝⁴ : Group α
inst✝³ : MulAction α β
x : β
inst✝² : Fintype α
inst✝¹ : (a : α) → Fintype ↑(fixedBy β a)
inst✝ : Fintype (Quotient (orbitRel α β))
⊢ ∑ a : α, Fintype.card ↑(fixedBy β a) = Fintype.card (Quotient (orbitRel α β)) * Fintype.card α

Next tactic:
rw [← Fintype.card_prod, ← Fintype.card_sigma,
    Fintype.card_congr (sigmaFixedByEquivOrbitsProdGroup α β)]
@[to_additive]
instance isPretransitive_quotient (G) [Group G] (H : Subgroup G) : IsPretransitive G (G ⧸ H) where
  exists_smul_eq := by
    

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝³ inst✝² : Group α
inst✝¹ : MulAction α β
x : β
G : Type ?u.96305
inst✝ : Group G
H : Subgroup G
⊢ ∀ (x y : G ⧸ H), ∃ g, g • x = y

Next tactic:
{ rintro ⟨x⟩ ⟨y⟩
      refine' ⟨y * x⁻¹, QuotientGroup.eq.mpr _⟩
      simp only [smul_eq_mul, H.one_mem, mul_left_inv, inv_mul_cancel_right]}
@[to_additive]
instance isPretransitive_quotient (G) [Group G] (H : Subgroup G) : IsPretransitive G (G ⧸ H) where
  exists_smul_eq := by
    { 

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝³ inst✝² : Group α
inst✝¹ : MulAction α β
x : β
G : Type ?u.96305
inst✝ : Group G
H : Subgroup G
⊢ ∀ (x y : G ⧸ H), ∃ g, g • x = y

Next tactic:
rintro ⟨x⟩ ⟨y⟩
@[to_additive]
instance isPretransitive_quotient (G) [Group G] (H : Subgroup G) : IsPretransitive G (G ⧸ H) where
  exists_smul_eq := by
    { rintro ⟨x⟩ ⟨y⟩
      

Proof state:
case mk.mk
α : Type u
β : Type v
γ : Type w
inst✝³ inst✝² : Group α
inst✝¹ : MulAction α β
x✝¹ : β
G : Type ?u.96305
inst✝ : Group G
H : Subgroup G
x✝ : G ⧸ H
x : G
y✝ : G ⧸ H
y : G
⊢ ∃ g, g • Quot.mk Setoid.r x = Quot.mk Setoid.r y

Next tactic:
refine' ⟨y * x⁻¹, QuotientGroup.eq.mpr _⟩
@[to_additive]
instance isPretransitive_quotient (G) [Group G] (H : Subgroup G) : IsPretransitive G (G ⧸ H) where
  exists_smul_eq := by
    { rintro ⟨x⟩ ⟨y⟩
      refine' ⟨y * x⁻¹, QuotientGroup.eq.mpr _⟩
      

Proof state:
case mk.mk
α : Type u
β : Type v
γ : Type w
inst✝³ inst✝² : Group α
inst✝¹ : MulAction α β
x✝¹ : β
G : Type ?u.96305
inst✝ : Group G
H : Subgroup G
x✝ : G ⧸ H
x : G
y✝ : G ⧸ H
y : G
⊢ ((fun x_1 => (y * x⁻¹) • x_1) x)⁻¹ * y ∈ H

Next tactic:
simp only [smul_eq_mul, H.one_mem, mul_left_inv, inv_mul_cancel_right]
set_option autoImplicit true in
theorem ConjClasses.card_carrier [Group G] [Fintype G] (g : G) [Fintype (ConjClasses.mk g).carrier]
    [Fintype <| MulAction.stabilizer (ConjAct G) g] : Fintype.card (ConjClasses.mk g).carrier =
      Fintype.card G / Fintype.card (MulAction.stabilizer (ConjAct G) g) := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
G : Type u_1
inst✝³ : Group G
inst✝² : Fintype G
g : G
inst✝¹ : Fintype ↑(carrier (ConjClasses.mk g))
inst✝ : Fintype ↥(MulAction.stabilizer (ConjAct G) g)
⊢ Fintype.card ↑(carrier (ConjClasses.mk g)) = Fintype.card G / Fintype.card ↥(MulAction.stabilizer (ConjAct G) g)

Next tactic:
classical
  rw [Fintype.card_congr <| ConjAct.toConjAct (G := G) |>.toEquiv]
  rw [← MulAction.card_orbit_mul_card_stabilizer_eq_card_group (ConjAct G) g, Nat.mul_div_cancel]
  simp_rw [ConjAct.orbit_eq_carrier_conjClasses]
  exact Fintype.card_pos_iff.mpr inferInstance
set_option autoImplicit true in
theorem ConjClasses.card_carrier [Group G] [Fintype G] (g : G) [Fintype (ConjClasses.mk g).carrier]
    [Fintype <| MulAction.stabilizer (ConjAct G) g] : Fintype.card (ConjClasses.mk g).carrier =
      Fintype.card G / Fintype.card (MulAction.stabilizer (ConjAct G) g) := by
  classical
  

Proof state:
α : Type u
β : Type v
γ : Type w
G : Type u_1
inst✝³ : Group G
inst✝² : Fintype G
g : G
inst✝¹ : Fintype ↑(carrier (ConjClasses.mk g))
inst✝ : Fintype ↥(MulAction.stabilizer (ConjAct G) g)
⊢ Fintype.card ↑(carrier (ConjClasses.mk g)) = Fintype.card G / Fintype.card ↥(MulAction.stabilizer (ConjAct G) g)

Next tactic:
rw [Fintype.card_congr <| ConjAct.toConjAct (G := G) |>.toEquiv]
set_option autoImplicit true in
theorem ConjClasses.card_carrier [Group G] [Fintype G] (g : G) [Fintype (ConjClasses.mk g).carrier]
    [Fintype <| MulAction.stabilizer (ConjAct G) g] : Fintype.card (ConjClasses.mk g).carrier =
      Fintype.card G / Fintype.card (MulAction.stabilizer (ConjAct G) g) := by
  classical
  rw [Fintype.card_congr <| ConjAct.toConjAct (G := G) |>.toEquiv]
  

Proof state:
α : Type u
β : Type v
γ : Type w
G : Type u_1
inst✝³ : Group G
inst✝² : Fintype G
g : G
inst✝¹ : Fintype ↑(carrier (ConjClasses.mk g))
inst✝ : Fintype ↥(MulAction.stabilizer (ConjAct G) g)
⊢ Fintype.card ↑(carrier (ConjClasses.mk g)) =
    Fintype.card (ConjAct G) / Fintype.card ↥(MulAction.stabilizer (ConjAct G) g)

Next tactic:
rw [← MulAction.card_orbit_mul_card_stabilizer_eq_card_group (ConjAct G) g, Nat.mul_div_cancel]
set_option autoImplicit true in
theorem ConjClasses.card_carrier [Group G] [Fintype G] (g : G) [Fintype (ConjClasses.mk g).carrier]
    [Fintype <| MulAction.stabilizer (ConjAct G) g] : Fintype.card (ConjClasses.mk g).carrier =
      Fintype.card G / Fintype.card (MulAction.stabilizer (ConjAct G) g) := by
  classical
  rw [Fintype.card_congr <| ConjAct.toConjAct (G := G) |>.toEquiv]
  rw [← MulAction.card_orbit_mul_card_stabilizer_eq_card_group (ConjAct G) g, Nat.mul_div_cancel]
  

Proof state:
α : Type u
β : Type v
γ : Type w
G : Type u_1
inst✝³ : Group G
inst✝² : Fintype G
g : G
inst✝¹ : Fintype ↑(carrier (ConjClasses.mk g))
inst✝ : Fintype ↥(MulAction.stabilizer (ConjAct G) g)
⊢ Fintype.card ↑(carrier (ConjClasses.mk g)) = Fintype.card ↑(MulAction.orbit (ConjAct G) g)
case H
α : Type u
β : Type v
γ : Type w
G : Type u_1
inst✝³ : Group G
inst✝² : Fintype G
g : G
inst✝¹ : Fintype ↑(carrier (ConjClasses.mk g))
inst✝ : Fintype ↥(MulAction.stabilizer (ConjAct G) g)
⊢ 0 < Fintype.card ↥(MulAction.stabilizer (ConjAct G) g)

Next tactic:
simp_rw [ConjAct.orbit_eq_carrier_conjClasses]
set_option autoImplicit true in
theorem ConjClasses.card_carrier [Group G] [Fintype G] (g : G) [Fintype (ConjClasses.mk g).carrier]
    [Fintype <| MulAction.stabilizer (ConjAct G) g] : Fintype.card (ConjClasses.mk g).carrier =
      Fintype.card G / Fintype.card (MulAction.stabilizer (ConjAct G) g) := by
  classical
  rw [Fintype.card_congr <| ConjAct.toConjAct (G := G) |>.toEquiv]
  rw [← MulAction.card_orbit_mul_card_stabilizer_eq_card_group (ConjAct G) g, Nat.mul_div_cancel]
  simp_rw [ConjAct.orbit_eq_carrier_conjClasses]
  

Proof state:
case H
α : Type u
β : Type v
γ : Type w
G : Type u_1
inst✝³ : Group G
inst✝² : Fintype G
g : G
inst✝¹ : Fintype ↑(carrier (ConjClasses.mk g))
inst✝ : Fintype ↥(MulAction.stabilizer (ConjAct G) g)
⊢ 0 < Fintype.card ↥(MulAction.stabilizer (ConjAct G) g)

Next tactic:
exact Fintype.card_pos_iff.mpr inferInstance
theorem normalCore_eq_ker : H.normalCore = (MulAction.toPermHom G (G ⧸ H)).ker := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
G : Type u_1
inst✝ : Group G
H : Subgroup G
⊢ normalCore H = MonoidHom.ker (MulAction.toPermHom G (G ⧸ H))

Next tactic:
apply le_antisymm
theorem normalCore_eq_ker : H.normalCore = (MulAction.toPermHom G (G ⧸ H)).ker := by
  apply le_antisymm
  · 

Proof state:
case a
α : Type u
β : Type v
γ : Type w
G : Type u_1
inst✝ : Group G
H : Subgroup G
⊢ normalCore H ≤ MonoidHom.ker (MulAction.toPermHom G (G ⧸ H))

Next tactic:
intro g hg
theorem normalCore_eq_ker : H.normalCore = (MulAction.toPermHom G (G ⧸ H)).ker := by
  apply le_antisymm
  · intro g hg
    

Proof state:
case a
α : Type u
β : Type v
γ : Type w
G : Type u_1
inst✝ : Group G
H : Subgroup G
g : G
hg : g ∈ normalCore H
⊢ g ∈ MonoidHom.ker (MulAction.toPermHom G (G ⧸ H))

Next tactic:
apply Equiv.Perm.ext
theorem normalCore_eq_ker : H.normalCore = (MulAction.toPermHom G (G ⧸ H)).ker := by
  apply le_antisymm
  · intro g hg
    apply Equiv.Perm.ext
    

Proof state:
case a.H
α : Type u
β : Type v
γ : Type w
G : Type u_1
inst✝ : Group G
H : Subgroup G
g : G
hg : g ∈ normalCore H
⊢ ∀ (x : G ⧸ H), ((MulAction.toPermHom G (G ⧸ H)) g) x = 1 x

Next tactic:
refine' fun q ↦ QuotientGroup.induction_on q _
theorem normalCore_eq_ker : H.normalCore = (MulAction.toPermHom G (G ⧸ H)).ker := by
  apply le_antisymm
  · intro g hg
    apply Equiv.Perm.ext
    refine' fun q ↦ QuotientGroup.induction_on q _
    

Proof state:
case a.H
α : Type u
β : Type v
γ : Type w
G : Type u_1
inst✝ : Group G
H : Subgroup G
g : G
hg : g ∈ normalCore H
q : G ⧸ H
⊢ ∀ (z : G), ((MulAction.toPermHom G (G ⧸ H)) g) ↑z = 1 ↑z

Next tactic:
refine' fun g' => (MulAction.Quotient.smul_mk H g g').trans (QuotientGroup.eq.mpr _)
theorem normalCore_eq_ker : H.normalCore = (MulAction.toPermHom G (G ⧸ H)).ker := by
  apply le_antisymm
  · intro g hg
    apply Equiv.Perm.ext
    refine' fun q ↦ QuotientGroup.induction_on q _
    refine' fun g' => (MulAction.Quotient.smul_mk H g g').trans (QuotientGroup.eq.mpr _)
    

Proof state:
case a.H
α : Type u
β : Type v
γ : Type w
G : Type u_1
inst✝ : Group G
H : Subgroup G
g : G
hg : g ∈ normalCore H
q : G ⧸ H
g' : G
⊢ (g • g')⁻¹ * g' ∈ H

Next tactic:
rw [smul_eq_mul, mul_inv_rev, ← inv_inv g', inv_inv]
theorem normalCore_eq_ker : H.normalCore = (MulAction.toPermHom G (G ⧸ H)).ker := by
  apply le_antisymm
  · intro g hg
    apply Equiv.Perm.ext
    refine' fun q ↦ QuotientGroup.induction_on q _
    refine' fun g' => (MulAction.Quotient.smul_mk H g g').trans (QuotientGroup.eq.mpr _)
    rw [smul_eq_mul, mul_inv_rev, ← inv_inv g', inv_inv]
    

Proof state:
case a.H
α : Type u
β : Type v
γ : Type w
G : Type u_1
inst✝ : Group G
H : Subgroup G
g : G
hg : g ∈ normalCore H
q : G ⧸ H
g' : G
⊢ g'⁻¹ * g⁻¹ * g'⁻¹⁻¹ ∈ H

Next tactic:
exact H.normalCore.inv_mem hg g'⁻¹
theorem normalCore_eq_ker : H.normalCore = (MulAction.toPermHom G (G ⧸ H)).ker := by
  apply le_antisymm
  · intro g hg
    apply Equiv.Perm.ext
    refine' fun q ↦ QuotientGroup.induction_on q _
    refine' fun g' => (MulAction.Quotient.smul_mk H g g').trans (QuotientGroup.eq.mpr _)
    rw [smul_eq_mul, mul_inv_rev, ← inv_inv g', inv_inv]
    exact H.normalCore.inv_mem hg g'⁻¹
  · 

Proof state:
case a
α : Type u
β : Type v
γ : Type w
G : Type u_1
inst✝ : Group G
H : Subgroup G
⊢ MonoidHom.ker (MulAction.toPermHom G (G ⧸ H)) ≤ normalCore H

Next tactic:
refine' (Subgroup.normal_le_normalCore.mpr fun g hg => _)
theorem normalCore_eq_ker : H.normalCore = (MulAction.toPermHom G (G ⧸ H)).ker := by
  apply le_antisymm
  · intro g hg
    apply Equiv.Perm.ext
    refine' fun q ↦ QuotientGroup.induction_on q _
    refine' fun g' => (MulAction.Quotient.smul_mk H g g').trans (QuotientGroup.eq.mpr _)
    rw [smul_eq_mul, mul_inv_rev, ← inv_inv g', inv_inv]
    exact H.normalCore.inv_mem hg g'⁻¹
  · refine' (Subgroup.normal_le_normalCore.mpr fun g hg => _)
    

Proof state:
case a
α : Type u
β : Type v
γ : Type w
G : Type u_1
inst✝ : Group G
H : Subgroup G
g : G
hg : g ∈ MonoidHom.ker (MulAction.toPermHom G (G ⧸ H))
⊢ g ∈ H

Next tactic:
rw [← H.inv_mem_iff, ← mul_one g⁻¹, ← QuotientGroup.eq, ← mul_one g]
theorem normalCore_eq_ker : H.normalCore = (MulAction.toPermHom G (G ⧸ H)).ker := by
  apply le_antisymm
  · intro g hg
    apply Equiv.Perm.ext
    refine' fun q ↦ QuotientGroup.induction_on q _
    refine' fun g' => (MulAction.Quotient.smul_mk H g g').trans (QuotientGroup.eq.mpr _)
    rw [smul_eq_mul, mul_inv_rev, ← inv_inv g', inv_inv]
    exact H.normalCore.inv_mem hg g'⁻¹
  · refine' (Subgroup.normal_le_normalCore.mpr fun g hg => _)
    rw [← H.inv_mem_iff, ← mul_one g⁻¹, ← QuotientGroup.eq, ← mul_one g]
    

Proof state:
case a
α : Type u
β : Type v
γ : Type w
G : Type u_1
inst✝ : Group G
H : Subgroup G
g : G
hg : g ∈ MonoidHom.ker (MulAction.toPermHom G (G ⧸ H))
⊢ ↑(g * 1) = ↑1

Next tactic:
exact (MulAction.Quotient.smul_mk H g 1).symm.trans (Equiv.Perm.ext_iff.mp hg (1 : G))
theorem card_comm_eq_card_conjClasses_mul_card (G : Type*) [Group G] :
    Nat.card { p : G × G // Commute p.1 p.2 } = Nat.card (ConjClasses G) * Nat.card G := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
G : Type u_1
inst✝ : Group G
⊢ Nat.card { p // Commute p.1 p.2 } = Nat.card (ConjClasses G) * Nat.card G

Next tactic:
classical
  rcases fintypeOrInfinite G; swap
  · rw [mul_comm, Nat.card_eq_zero_of_infinite, Nat.card_eq_zero_of_infinite, zero_mul]
  simp only [Nat.card_eq_fintype_card]
  -- Porting note: Changed `calc` proof into a `rw` proof.
  rw [card_congr (Equiv.subtypeProdEquivSigmaSubtype Commute), card_sigma,
    sum_equiv ConjAct.toConjAct.toEquiv (fun a ↦ card { b // Commute a b })
      (fun g ↦ card (MulAction.fixedBy G g))
      fun g ↦ card_congr' <| congr_arg _ <| funext fun h ↦ mul_inv_eq_iff_eq_mul.symm.to_eq,
    MulAction.sum_card_fixedBy_eq_card_orbits_mul_card_group]
  congr 1; apply card_congr'; congr; ext;
  exact (Setoid.comm' _).trans isConj_iff.symm
theorem card_comm_eq_card_conjClasses_mul_card (G : Type*) [Group G] :
    Nat.card { p : G × G // Commute p.1 p.2 } = Nat.card (ConjClasses G) * Nat.card G := by
  classical
  

Proof state:
α : Type u
β : Type v
γ : Type w
G : Type u_1
inst✝ : Group G
⊢ Nat.card { p // Commute p.1 p.2 } = Nat.card (ConjClasses G) * Nat.card G

Next tactic:
rcases fintypeOrInfinite G
theorem card_comm_eq_card_conjClasses_mul_card (G : Type*) [Group G] :
    Nat.card { p : G × G // Commute p.1 p.2 } = Nat.card (ConjClasses G) * Nat.card G := by
  classical
  rcases fintypeOrInfinite G; 

Proof state:
case inl
α : Type u
β : Type v
γ : Type w
G : Type u_1
inst✝ : Group G
val✝ : Fintype G
⊢ Nat.card { p // Commute p.1 p.2 } = Nat.card (ConjClasses G) * Nat.card G
case inr
α : Type u
β : Type v
γ : Type w
G : Type u_1
inst✝ : Group G
val✝ : Infinite G
⊢ Nat.card { p // Commute p.1 p.2 } = Nat.card (ConjClasses G) * Nat.card G

Next tactic:
swap
theorem card_comm_eq_card_conjClasses_mul_card (G : Type*) [Group G] :
    Nat.card { p : G × G // Commute p.1 p.2 } = Nat.card (ConjClasses G) * Nat.card G := by
  classical
  rcases fintypeOrInfinite G; swap
  · 

Proof state:
case inr
α : Type u
β : Type v
γ : Type w
G : Type u_1
inst✝ : Group G
val✝ : Infinite G
⊢ Nat.card { p // Commute p.1 p.2 } = Nat.card (ConjClasses G) * Nat.card G

Next tactic:
rw [mul_comm, Nat.card_eq_zero_of_infinite, Nat.card_eq_zero_of_infinite, zero_mul]
theorem card_comm_eq_card_conjClasses_mul_card (G : Type*) [Group G] :
    Nat.card { p : G × G // Commute p.1 p.2 } = Nat.card (ConjClasses G) * Nat.card G := by
  classical
  rcases fintypeOrInfinite G; swap
  · rw [mul_comm, Nat.card_eq_zero_of_infinite, Nat.card_eq_zero_of_infinite, zero_mul]
  

Proof state:
case inl
α : Type u
β : Type v
γ : Type w
G : Type u_1
inst✝ : Group G
val✝ : Fintype G
⊢ Nat.card { p // Commute p.1 p.2 } = Nat.card (ConjClasses G) * Nat.card G

Next tactic:
simp only [Nat.card_eq_fintype_card]
theorem card_comm_eq_card_conjClasses_mul_card (G : Type*) [Group G] :
    Nat.card { p : G × G // Commute p.1 p.2 } = Nat.card (ConjClasses G) * Nat.card G := by
  classical
  rcases fintypeOrInfinite G; swap
  · rw [mul_comm, Nat.card_eq_zero_of_infinite, Nat.card_eq_zero_of_infinite, zero_mul]
  simp only [Nat.card_eq_fintype_card]
  -- Porting note: Changed `calc` proof into a `rw` proof.
  

Proof state:
case inl
α : Type u
β : Type v
γ : Type w
G : Type u_1
inst✝ : Group G
val✝ : Fintype G
⊢ card { p // Commute p.1 p.2 } = card (ConjClasses G) * card G

Next tactic:
rw [card_congr (Equiv.subtypeProdEquivSigmaSubtype Commute), card_sigma,
    sum_equiv ConjAct.toConjAct.toEquiv (fun a ↦ card { b // Commute a b })
      (fun g ↦ card (MulAction.fixedBy G g))
      fun g ↦ card_congr' <| congr_arg _ <| funext fun h ↦ mul_inv_eq_iff_eq_mul.symm.to_eq,
    MulAction.sum_card_fixedBy_eq_card_orbits_mul_card_group]
theorem card_comm_eq_card_conjClasses_mul_card (G : Type*) [Group G] :
    Nat.card { p : G × G // Commute p.1 p.2 } = Nat.card (ConjClasses G) * Nat.card G := by
  classical
  rcases fintypeOrInfinite G; swap
  · rw [mul_comm, Nat.card_eq_zero_of_infinite, Nat.card_eq_zero_of_infinite, zero_mul]
  simp only [Nat.card_eq_fintype_card]
  -- Porting note: Changed `calc` proof into a `rw` proof.
  rw [card_congr (Equiv.subtypeProdEquivSigmaSubtype Commute), card_sigma,
    sum_equiv ConjAct.toConjAct.toEquiv (fun a ↦ card { b // Commute a b })
      (fun g ↦ card (MulAction.fixedBy G g))
      fun g ↦ card_congr' <| congr_arg _ <| funext fun h ↦ mul_inv_eq_iff_eq_mul.symm.to_eq,
    MulAction.sum_card_fixedBy_eq_card_orbits_mul_card_group]
  

Proof state:
case inl
α : Type u
β : Type v
γ : Type w
G : Type u_1
inst✝ : Group G
val✝ : Fintype G
⊢ card (Quotient (MulAction.orbitRel (ConjAct G) G)) * card (ConjAct G) = card (ConjClasses G) * card G

Next tactic:
congr 1
theorem card_comm_eq_card_conjClasses_mul_card (G : Type*) [Group G] :
    Nat.card { p : G × G // Commute p.1 p.2 } = Nat.card (ConjClasses G) * Nat.card G := by
  classical
  rcases fintypeOrInfinite G; swap
  · rw [mul_comm, Nat.card_eq_zero_of_infinite, Nat.card_eq_zero_of_infinite, zero_mul]
  simp only [Nat.card_eq_fintype_card]
  -- Porting note: Changed `calc` proof into a `rw` proof.
  rw [card_congr (Equiv.subtypeProdEquivSigmaSubtype Commute), card_sigma,
    sum_equiv ConjAct.toConjAct.toEquiv (fun a ↦ card { b // Commute a b })
      (fun g ↦ card (MulAction.fixedBy G g))
      fun g ↦ card_congr' <| congr_arg _ <| funext fun h ↦ mul_inv_eq_iff_eq_mul.symm.to_eq,
    MulAction.sum_card_fixedBy_eq_card_orbits_mul_card_group]
  congr 1; 

Proof state:
case inl.e_a
α : Type u
β : Type v
γ : Type w
G : Type u_1
inst✝ : Group G
val✝ : Fintype G
⊢ card (Quotient (MulAction.orbitRel (ConjAct G) G)) = card (ConjClasses G)

Next tactic:
apply card_congr'
theorem card_comm_eq_card_conjClasses_mul_card (G : Type*) [Group G] :
    Nat.card { p : G × G // Commute p.1 p.2 } = Nat.card (ConjClasses G) * Nat.card G := by
  classical
  rcases fintypeOrInfinite G; swap
  · rw [mul_comm, Nat.card_eq_zero_of_infinite, Nat.card_eq_zero_of_infinite, zero_mul]
  simp only [Nat.card_eq_fintype_card]
  -- Porting note: Changed `calc` proof into a `rw` proof.
  rw [card_congr (Equiv.subtypeProdEquivSigmaSubtype Commute), card_sigma,
    sum_equiv ConjAct.toConjAct.toEquiv (fun a ↦ card { b // Commute a b })
      (fun g ↦ card (MulAction.fixedBy G g))
      fun g ↦ card_congr' <| congr_arg _ <| funext fun h ↦ mul_inv_eq_iff_eq_mul.symm.to_eq,
    MulAction.sum_card_fixedBy_eq_card_orbits_mul_card_group]
  congr 1; apply card_congr'; 

Proof state:
case inl.e_a.h
α : Type u
β : Type v
γ : Type w
G : Type u_1
inst✝ : Group G
val✝ : Fintype G
⊢ Quotient (MulAction.orbitRel (ConjAct G) G) = ConjClasses G

Next tactic:
congr
theorem card_comm_eq_card_conjClasses_mul_card (G : Type*) [Group G] :
    Nat.card { p : G × G // Commute p.1 p.2 } = Nat.card (ConjClasses G) * Nat.card G := by
  classical
  rcases fintypeOrInfinite G; swap
  · rw [mul_comm, Nat.card_eq_zero_of_infinite, Nat.card_eq_zero_of_infinite, zero_mul]
  simp only [Nat.card_eq_fintype_card]
  -- Porting note: Changed `calc` proof into a `rw` proof.
  rw [card_congr (Equiv.subtypeProdEquivSigmaSubtype Commute), card_sigma,
    sum_equiv ConjAct.toConjAct.toEquiv (fun a ↦ card { b // Commute a b })
      (fun g ↦ card (MulAction.fixedBy G g))
      fun g ↦ card_congr' <| congr_arg _ <| funext fun h ↦ mul_inv_eq_iff_eq_mul.symm.to_eq,
    MulAction.sum_card_fixedBy_eq_card_orbits_mul_card_group]
  congr 1; apply card_congr'; congr; 

Proof state:
case inl.e_a.h.e_s
α : Type u
β : Type v
γ : Type w
G : Type u_1
inst✝ : Group G
val✝ : Fintype G
⊢ MulAction.orbitRel (ConjAct G) G = IsConj.setoid G

Next tactic:
ext
theorem card_comm_eq_card_conjClasses_mul_card (G : Type*) [Group G] :
    Nat.card { p : G × G // Commute p.1 p.2 } = Nat.card (ConjClasses G) * Nat.card G := by
  classical
  rcases fintypeOrInfinite G; swap
  · rw [mul_comm, Nat.card_eq_zero_of_infinite, Nat.card_eq_zero_of_infinite, zero_mul]
  simp only [Nat.card_eq_fintype_card]
  -- Porting note: Changed `calc` proof into a `rw` proof.
  rw [card_congr (Equiv.subtypeProdEquivSigmaSubtype Commute), card_sigma,
    sum_equiv ConjAct.toConjAct.toEquiv (fun a ↦ card { b // Commute a b })
      (fun g ↦ card (MulAction.fixedBy G g))
      fun g ↦ card_congr' <| congr_arg _ <| funext fun h ↦ mul_inv_eq_iff_eq_mul.symm.to_eq,
    MulAction.sum_card_fixedBy_eq_card_orbits_mul_card_group]
  congr 1; apply card_congr'; congr; ext;
  

Proof state:
case inl.e_a.h.e_s.H
α : Type u
β : Type v
γ : Type w
G : Type u_1
inst✝ : Group G
val✝ : Fintype G
a✝ b✝ : G
⊢ Setoid.Rel (MulAction.orbitRel (ConjAct G) G) a✝ b✝ ↔ Setoid.Rel (IsConj.setoid G) a✝ b✝

Next tactic:
exact (Setoid.comm' _).trans isConj_iff.symm
theorem fromBlocks_toBlocks (M : Matrix (Sum n o) (Sum l m) α) :
    fromBlocks M.toBlocks₁₁ M.toBlocks₁₂ M.toBlocks₂₁ M.toBlocks₂₂ = M := by
  

Proof state:
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
p : Type u_5
q : Type u_6
m' : o → Type u_7
n' : o → Type u_8
p' : o → Type u_9
R : Type u_10
S : Type u_11
α : Type u_12
β : Type u_13
M : Matrix (n ⊕ o) (l ⊕ m) α
⊢ fromBlocks (toBlocks₁₁ M) (toBlocks₁₂ M) (toBlocks₂₁ M) (toBlocks₂₂ M) = M

Next tactic:
ext i j
theorem fromBlocks_toBlocks (M : Matrix (Sum n o) (Sum l m) α) :
    fromBlocks M.toBlocks₁₁ M.toBlocks₁₂ M.toBlocks₂₁ M.toBlocks₂₂ = M := by
  ext i j
  

Proof state:
case a.h
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
p : Type u_5
q : Type u_6
m' : o → Type u_7
n' : o → Type u_8
p' : o → Type u_9
R : Type u_10
S : Type u_11
α : Type u_12
β : Type u_13
M : Matrix (n ⊕ o) (l ⊕ m) α
i : n ⊕ o
j : l ⊕ m
⊢ fromBlocks (toBlocks₁₁ M) (toBlocks₁₂ M) (toBlocks₂₁ M) (toBlocks₂₂ M) i j = M i j

Next tactic:
rcases i with ⟨⟩
theorem fromBlocks_toBlocks (M : Matrix (Sum n o) (Sum l m) α) :
    fromBlocks M.toBlocks₁₁ M.toBlocks₁₂ M.toBlocks₂₁ M.toBlocks₂₂ = M := by
  ext i j
  rcases i with ⟨⟩ <;> 

Proof state:
case a.h.inl
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
p : Type u_5
q : Type u_6
m' : o → Type u_7
n' : o → Type u_8
p' : o → Type u_9
R : Type u_10
S : Type u_11
α : Type u_12
β : Type u_13
M : Matrix (n ⊕ o) (l ⊕ m) α
j : l ⊕ m
val✝ : n
⊢ fromBlocks (toBlocks₁₁ M) (toBlocks₁₂ M) (toBlocks₂₁ M) (toBlocks₂₂ M) (Sum.inl val✝) j = M (Sum.inl val✝) j

Next tactic:
rcases j with ⟨⟩