l3lab/ntp-mathlib huggingface dataset:
/-- Any normed characteristic-zero division ring that is a normed algebra over the reals is also a
normed algebra over the rationals.

Phrased another way, if `𝕜` is a normed algebra over the reals, then `AlgebraRat` respects that
norm. -/
instance normedAlgebraRat {𝕜} [NormedDivisionRing 𝕜] [CharZero 𝕜] [NormedAlgebra ℝ 𝕜] :
    NormedAlgebra ℚ 𝕜 where
  norm_smul_le q x := by
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
𝕜✝ : Type u_5
𝕜' : Type u_6
inst✝⁵ : NormedField 𝕜✝
inst✝⁴ : SeminormedRing 𝕜'
inst✝³ : NormedAlgebra 𝕜✝ 𝕜'
𝕜 : Type ?u.406305
inst✝² : NormedDivisionRing 𝕜
inst✝¹ : CharZero 𝕜
inst✝ : NormedAlgebra ℝ 𝕜
q : ℚ
x : 𝕜
⊢ ‖q • x‖ ≤ ‖q‖ * ‖x‖

Next tactic:
rw [← smul_one_smul ℝ q x, Rat.smul_one_eq_coe, norm_smul, Rat.norm_cast_real]
instance PUnit.normedAlgebra : NormedAlgebra 𝕜 PUnit where
  norm_smul_le q _ := by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
𝕜 : Type u_5
𝕜' : Type u_6
inst✝² : NormedField 𝕜
inst✝¹ : SeminormedRing 𝕜'
inst✝ : NormedAlgebra 𝕜 𝕜'
q : 𝕜
x✝ : PUnit.{?u.409347 + 1}
⊢ ‖q • x✝‖ ≤ ‖q‖ * ‖x✝‖

Next tactic:
simp only [norm_eq_zero, mul_zero, le_refl]
/-- A non-unital algebra homomorphism from an `Algebra` to a `NormedAlgebra` induces a
`NormedAlgebra` structure on the domain, using the `SeminormedRing.induced` norm.

See note [reducible non-instances] -/
@[reducible]
def NormedAlgebra.induced {F : Type*} (α β γ : Type*) [NormedField α] [Ring β] [Algebra α β]
    [SeminormedRing γ] [NormedAlgebra α γ] [NonUnitalAlgHomClass F α β γ] (f : F) :
    @NormedAlgebra α β _ (SeminormedRing.induced β γ f) := by
  -- Porting note: trouble with SeminormedRing β, Algebra α β, and unfolding seminorm
  

Proof state:
α✝ : Type u_1
β✝ : Type u_2
γ✝ : Type u_3
ι : Type u_4
F : Type u_5
α : Type u_6
β : Type u_7
γ : Type u_8
inst✝⁵ : NormedField α
inst✝⁴ : Ring β
inst✝³ : Algebra α β
inst✝² : SeminormedRing γ
inst✝¹ : NormedAlgebra α γ
inst✝ : NonUnitalAlgHomClass F α β γ
f : F
⊢ NormedAlgebra α β

Next tactic:
refine @NormedAlgebra.mk (𝕜 := α) (𝕜' := β) _ ?_ ?_ ?_
/-- A non-unital algebra homomorphism from an `Algebra` to a `NormedAlgebra` induces a
`NormedAlgebra` structure on the domain, using the `SeminormedRing.induced` norm.

See note [reducible non-instances] -/
@[reducible]
def NormedAlgebra.induced {F : Type*} (α β γ : Type*) [NormedField α] [Ring β] [Algebra α β]
    [SeminormedRing γ] [NormedAlgebra α γ] [NonUnitalAlgHomClass F α β γ] (f : F) :
    @NormedAlgebra α β _ (SeminormedRing.induced β γ f) := by
  -- Porting note: trouble with SeminormedRing β, Algebra α β, and unfolding seminorm
  refine @NormedAlgebra.mk (𝕜 := α) (𝕜' := β) _ ?_ ?_ ?_
  · 

Proof state:
case refine_1
α✝ : Type u_1
β✝ : Type u_2
γ✝ : Type u_3
ι : Type u_4
F : Type u_5
α : Type u_6
β : Type u_7
γ : Type u_8
inst✝⁵ : NormedField α
inst✝⁴ : Ring β
inst✝³ : Algebra α β
inst✝² : SeminormedRing γ
inst✝¹ : NormedAlgebra α γ
inst✝ : NonUnitalAlgHomClass F α β γ
f : F
⊢ Algebra α β

Next tactic:
infer_instance
/-- A non-unital algebra homomorphism from an `Algebra` to a `NormedAlgebra` induces a
`NormedAlgebra` structure on the domain, using the `SeminormedRing.induced` norm.

See note [reducible non-instances] -/
@[reducible]
def NormedAlgebra.induced {F : Type*} (α β γ : Type*) [NormedField α] [Ring β] [Algebra α β]
    [SeminormedRing γ] [NormedAlgebra α γ] [NonUnitalAlgHomClass F α β γ] (f : F) :
    @NormedAlgebra α β _ (SeminormedRing.induced β γ f) := by
  -- Porting note: trouble with SeminormedRing β, Algebra α β, and unfolding seminorm
  refine @NormedAlgebra.mk (𝕜 := α) (𝕜' := β) _ ?_ ?_ ?_
  · infer_instance
  · 

Proof state:
case refine_2
α✝ : Type u_1
β✝ : Type u_2
γ✝ : Type u_3
ι : Type u_4
F : Type u_5
α : Type u_6
β : Type u_7
γ : Type u_8
inst✝⁵ : NormedField α
inst✝⁴ : Ring β
inst✝³ : Algebra α β
inst✝² : SeminormedRing γ
inst✝¹ : NormedAlgebra α γ
inst✝ : NonUnitalAlgHomClass F α β γ
f : F
⊢ ∀ (r : α) (x : β), ‖r • x‖ ≤ ‖r‖ * ‖x‖

Next tactic:
intro a b
/-- A non-unital algebra homomorphism from an `Algebra` to a `NormedAlgebra` induces a
`NormedAlgebra` structure on the domain, using the `SeminormedRing.induced` norm.

See note [reducible non-instances] -/
@[reducible]
def NormedAlgebra.induced {F : Type*} (α β γ : Type*) [NormedField α] [Ring β] [Algebra α β]
    [SeminormedRing γ] [NormedAlgebra α γ] [NonUnitalAlgHomClass F α β γ] (f : F) :
    @NormedAlgebra α β _ (SeminormedRing.induced β γ f) := by
  -- Porting note: trouble with SeminormedRing β, Algebra α β, and unfolding seminorm
  refine @NormedAlgebra.mk (𝕜 := α) (𝕜' := β) _ ?_ ?_ ?_
  · infer_instance
  · intro a b
    

Proof state:
case refine_2
α✝ : Type u_1
β✝ : Type u_2
γ✝ : Type u_3
ι : Type u_4
F : Type u_5
α : Type u_6
β : Type u_7
γ : Type u_8
inst✝⁵ : NormedField α
inst✝⁴ : Ring β
inst✝³ : Algebra α β
inst✝² : SeminormedRing γ
inst✝¹ : NormedAlgebra α γ
inst✝ : NonUnitalAlgHomClass F α β γ
f : F
a : α
b : β
⊢ ‖a • b‖ ≤ ‖a‖ * ‖b‖

Next tactic:
change ‖(⇑f) (a • b)‖ ≤ ‖a‖ * ‖(⇑f) b‖
/-- A non-unital algebra homomorphism from an `Algebra` to a `NormedAlgebra` induces a
`NormedAlgebra` structure on the domain, using the `SeminormedRing.induced` norm.

See note [reducible non-instances] -/
@[reducible]
def NormedAlgebra.induced {F : Type*} (α β γ : Type*) [NormedField α] [Ring β] [Algebra α β]
    [SeminormedRing γ] [NormedAlgebra α γ] [NonUnitalAlgHomClass F α β γ] (f : F) :
    @NormedAlgebra α β _ (SeminormedRing.induced β γ f) := by
  -- Porting note: trouble with SeminormedRing β, Algebra α β, and unfolding seminorm
  refine @NormedAlgebra.mk (𝕜 := α) (𝕜' := β) _ ?_ ?_ ?_
  · infer_instance
  · intro a b
    change ‖(⇑f) (a • b)‖ ≤ ‖a‖ * ‖(⇑f) b‖
    

Proof state:
case refine_2
α✝ : Type u_1
β✝ : Type u_2
γ✝ : Type u_3
ι : Type u_4
F : Type u_5
α : Type u_6
β : Type u_7
γ : Type u_8
inst✝⁵ : NormedField α
inst✝⁴ : Ring β
inst✝³ : Algebra α β
inst✝² : SeminormedRing γ
inst✝¹ : NormedAlgebra α γ
inst✝ : NonUnitalAlgHomClass F α β γ
f : F
a : α
b : β
⊢ ‖f (a • b)‖ ≤ ‖a‖ * ‖f b‖

Next tactic:
exact (map_smul f a b).symm ▸ norm_smul_le a (f b)
/-- If `E` is a normed space over `𝕜'` and `𝕜` is a normed algebra over `𝕜'`, then
`RestrictScalars.module` is additionally a `NormedSpace`. -/
instance RestrictScalars.normedSpace : NormedSpace 𝕜 (RestrictScalars 𝕜 𝕜' E) :=
  { RestrictScalars.module 𝕜 𝕜' E with
    norm_smul_le := fun c x =>
      (norm_smul_le (algebraMap 𝕜 𝕜' c) (_ : E)).trans_eq <| by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
𝕜 : Type u_5
𝕜' : Type u_6
inst✝⁴ : NormedField 𝕜
inst✝³ : NormedField 𝕜'
inst✝² : NormedAlgebra 𝕜 𝕜'
E : Type u_7
inst✝¹ : SeminormedAddCommGroup E
inst✝ : NormedSpace 𝕜' E
src✝ : Module 𝕜 (RestrictScalars 𝕜 𝕜' E) := module 𝕜 𝕜' E
c : 𝕜
x : RestrictScalars 𝕜 𝕜' E
⊢ ‖(algebraMap 𝕜 𝕜') c‖ * ‖x‖ = ‖c‖ * ‖x‖

Next tactic:
rw [norm_algebraMap']
theorem commProb_prod (M' : Type*) [Mul M'] : commProb (M × M') = commProb M * commProb M' := by
  

Proof state:
M : Type u_1
inst✝¹ : Mul M
M' : Type u_2
inst✝ : Mul M'
⊢ commProb (M × M') = commProb M * commProb M'

Next tactic:
simp_rw [commProb_def, div_mul_div_comm, Nat.card_prod, Nat.cast_mul, mul_pow, ← Nat.cast_mul,
    ← Nat.card_prod, Commute, SemiconjBy, Prod.ext_iff]
theorem commProb_prod (M' : Type*) [Mul M'] : commProb (M × M') = commProb M * commProb M' := by
  simp_rw [commProb_def, div_mul_div_comm, Nat.card_prod, Nat.cast_mul, mul_pow, ← Nat.cast_mul,
    ← Nat.card_prod, Commute, SemiconjBy, Prod.ext_iff]
  

Proof state:
M : Type u_1
inst✝¹ : Mul M
M' : Type u_2
inst✝ : Mul M'
⊢ ↑(Nat.card { p // (p.1 * p.2).1 = (p.2 * p.1).1 ∧ (p.1 * p.2).2 = (p.2 * p.1).2 }) /
      (↑(Nat.card M) ^ 2 * ↑(Nat.card M') ^ 2) =
    ↑(Nat.card ({ p // p.1 * p.2 = p.2 * p.1 } × { p // p.1 * p.2 = p.2 * p.1 })) /
      (↑(Nat.card M) ^ 2 * ↑(Nat.card M') ^ 2)

Next tactic:
congr 2
theorem commProb_prod (M' : Type*) [Mul M'] : commProb (M × M') = commProb M * commProb M' := by
  simp_rw [commProb_def, div_mul_div_comm, Nat.card_prod, Nat.cast_mul, mul_pow, ← Nat.cast_mul,
    ← Nat.card_prod, Commute, SemiconjBy, Prod.ext_iff]
  congr 2
  

Proof state:
case e_a.e_a
M : Type u_1
inst✝¹ : Mul M
M' : Type u_2
inst✝ : Mul M'
⊢ Nat.card { p // (p.1 * p.2).1 = (p.2 * p.1).1 ∧ (p.1 * p.2).2 = (p.2 * p.1).2 } =
    Nat.card ({ p // p.1 * p.2 = p.2 * p.1 } × { p // p.1 * p.2 = p.2 * p.1 })

Next tactic:
exact Nat.card_congr ⟨fun x => ⟨⟨⟨x.1.1.1, x.1.2.1⟩, x.2.1⟩, ⟨⟨x.1.1.2, x.1.2.2⟩, x.2.2⟩⟩,
    fun x => ⟨⟨⟨x.1.1.1, x.2.1.1⟩, ⟨x.1.1.2, x.2.1.2⟩⟩, ⟨x.1.2, x.2.2⟩⟩, fun x => rfl, fun x => rfl⟩
theorem commProb_pi (i : α → Type*) [Fintype α] [∀ a, Mul (i a)] :
    commProb (∀ a, i a) = ∏ a, commProb (i a) := by
  

Proof state:
M : Type u_1
inst✝² : Mul M
α : Type u_3
i : α → Type u_2
inst✝¹ : Fintype α
inst✝ : (a : α) → Mul (i a)
⊢ commProb ((a : α) → i a) = ∏ a : α, commProb (i a)

Next tactic:
simp_rw [commProb_def, Finset.prod_div_distrib, Finset.prod_pow, ← Nat.cast_prod,
    ← Nat.card_pi, Commute, SemiconjBy, Function.funext_iff]
theorem commProb_pi (i : α → Type*) [Fintype α] [∀ a, Mul (i a)] :
    commProb (∀ a, i a) = ∏ a, commProb (i a) := by
  simp_rw [commProb_def, Finset.prod_div_distrib, Finset.prod_pow, ← Nat.cast_prod,
    ← Nat.card_pi, Commute, SemiconjBy, Function.funext_iff]
  

Proof state:
M : Type u_1
inst✝² : Mul M
α : Type u_3
i : α → Type u_2
inst✝¹ : Fintype α
inst✝ : (a : α) → Mul (i a)
⊢ ↑(Nat.card { p // ∀ (a : α), (p.1 * p.2) a = (p.2 * p.1) a }) / ↑(Nat.card ((a : α) → i a)) ^ 2 =
    ↑(Nat.card ((a : α) → { p // p.1 * p.2 = p.2 * p.1 })) / ↑(Nat.card ((a : α) → i a)) ^ 2

Next tactic:
congr 2
theorem commProb_pi (i : α → Type*) [Fintype α] [∀ a, Mul (i a)] :
    commProb (∀ a, i a) = ∏ a, commProb (i a) := by
  simp_rw [commProb_def, Finset.prod_div_distrib, Finset.prod_pow, ← Nat.cast_prod,
    ← Nat.card_pi, Commute, SemiconjBy, Function.funext_iff]
  congr 2
  

Proof state:
case e_a.e_a
M : Type u_1
inst✝² : Mul M
α : Type u_3
i : α → Type u_2
inst✝¹ : Fintype α
inst✝ : (a : α) → Mul (i a)
⊢ Nat.card { p // ∀ (a : α), (p.1 * p.2) a = (p.2 * p.1) a } = Nat.card ((a : α) → { p // p.1 * p.2 = p.2 * p.1 })

Next tactic:
exact Nat.card_congr ⟨fun x a => ⟨⟨x.1.1 a, x.1.2 a⟩, x.2 a⟩, fun x => ⟨⟨fun a => (x a).1.1,
    fun a => (x a).1.2⟩, fun a => (x a).2⟩, fun x => rfl, fun x => rfl⟩
theorem commProb_function [Fintype α] [Mul β] :
    commProb (α → β) = (commProb β) ^ Fintype.card α := by
  

Proof state:
M : Type u_1
inst✝² : Mul M
α : Type u_2
β : Type u_3
inst✝¹ : Fintype α
inst✝ : Mul β
⊢ commProb (α → β) = commProb β ^ card α

Next tactic:
rw [commProb_pi, Finset.prod_const, Finset.card_univ]
theorem commProb_le_one : commProb M ≤ 1 := by
  

Proof state:
M : Type u_1
inst✝¹ : Mul M
inst✝ : Finite M
⊢ commProb M ≤ 1

Next tactic:
refine' div_le_one_of_le _ (sq_nonneg (Nat.card M : ℚ))
theorem commProb_le_one : commProb M ≤ 1 := by
  refine' div_le_one_of_le _ (sq_nonneg (Nat.card M : ℚ))
  

Proof state:
M : Type u_1
inst✝¹ : Mul M
inst✝ : Finite M
⊢ ↑(Nat.card { p // Commute p.1 p.2 }) ≤ ↑(Nat.card M) ^ 2

Next tactic:
rw [← Nat.cast_pow, Nat.cast_le, sq, ← Nat.card_prod]
theorem commProb_le_one : commProb M ≤ 1 := by
  refine' div_le_one_of_le _ (sq_nonneg (Nat.card M : ℚ))
  rw [← Nat.cast_pow, Nat.cast_le, sq, ← Nat.card_prod]
  

Proof state:
M : Type u_1
inst✝¹ : Mul M
inst✝ : Finite M
⊢ Nat.card { p // Commute p.1 p.2 } ≤ Nat.card (M × M)

Next tactic:
apply Finite.card_subtype_le
theorem commProb_eq_one_iff [h : Nonempty M] :
    commProb M = 1 ↔ Commutative ((· * ·) : M → M → M) := by
  

Proof state:
M : Type u_1
inst✝¹ : Mul M
inst✝ : Finite M
h : Nonempty M
⊢ commProb M = 1 ↔ Commutative fun x x_1 => x * x_1

Next tactic:
haveI := Fintype.ofFinite M
theorem commProb_eq_one_iff [h : Nonempty M] :
    commProb M = 1 ↔ Commutative ((· * ·) : M → M → M) := by
  haveI := Fintype.ofFinite M
  

Proof state:
M : Type u_1
inst✝¹ : Mul M
inst✝ : Finite M
h : Nonempty M
this : Fintype M
⊢ commProb M = 1 ↔ Commutative fun x x_1 => x * x_1

Next tactic:
rw [commProb, ← Set.coe_setOf, Nat.card_eq_fintype_card, Nat.card_eq_fintype_card]
theorem commProb_eq_one_iff [h : Nonempty M] :
    commProb M = 1 ↔ Commutative ((· * ·) : M → M → M) := by
  haveI := Fintype.ofFinite M
  rw [commProb, ← Set.coe_setOf, Nat.card_eq_fintype_card, Nat.card_eq_fintype_card]
  

Proof state:
M : Type u_1
inst✝¹ : Mul M
inst✝ : Finite M
h : Nonempty M
this : Fintype M
⊢ ↑(card ↑{x | Commute x.1 x.2}) / ↑(card M) ^ 2 = 1 ↔ Commutative fun x x_1 => x * x_1

Next tactic:
rw [div_eq_one_iff_eq, ← Nat.cast_pow, Nat.cast_inj, sq, ← card_prod,
    set_fintype_card_eq_univ_iff, Set.eq_univ_iff_forall]
theorem commProb_eq_one_iff [h : Nonempty M] :
    commProb M = 1 ↔ Commutative ((· * ·) : M → M → M) := by
  haveI := Fintype.ofFinite M
  rw [commProb, ← Set.coe_setOf, Nat.card_eq_fintype_card, Nat.card_eq_fintype_card]
  rw [div_eq_one_iff_eq, ← Nat.cast_pow, Nat.cast_inj, sq, ← card_prod,
    set_fintype_card_eq_univ_iff, Set.eq_univ_iff_forall]
  · 

Proof state:
M : Type u_1
inst✝¹ : Mul M
inst✝ : Finite M
h : Nonempty M
this : Fintype M
⊢ (∀ (x : M × M), x ∈ {x | Commute x.1 x.2}) ↔ Commutative fun x x_1 => x * x_1

Next tactic:
exact ⟨fun h x y ↦ h (x, y), fun h x ↦ h x.1 x.2⟩
theorem commProb_eq_one_iff [h : Nonempty M] :
    commProb M = 1 ↔ Commutative ((· * ·) : M → M → M) := by
  haveI := Fintype.ofFinite M
  rw [commProb, ← Set.coe_setOf, Nat.card_eq_fintype_card, Nat.card_eq_fintype_card]
  rw [div_eq_one_iff_eq, ← Nat.cast_pow, Nat.cast_inj, sq, ← card_prod,
    set_fintype_card_eq_univ_iff, Set.eq_univ_iff_forall]
  · exact ⟨fun h x y ↦ h (x, y), fun h x ↦ h x.1 x.2⟩
  · 

Proof state:
M : Type u_1
inst✝¹ : Mul M
inst✝ : Finite M
h : Nonempty M
this : Fintype M
⊢ ↑(card M) ^ 2 ≠ 0

Next tactic:
exact pow_ne_zero 2 (Nat.cast_ne_zero.mpr card_ne_zero)
theorem commProb_def' : commProb G = Nat.card (ConjClasses G) / Nat.card G := by
  

Proof state:
M : Type u_1
inst✝² : Mul M
inst✝¹ : Finite M
G : Type u_2
inst✝ : Group G
⊢ commProb G = ↑(Nat.card (ConjClasses G)) / ↑(Nat.card G)

Next tactic:
rw [commProb, card_comm_eq_card_conjClasses_mul_card, Nat.cast_mul, sq]
theorem commProb_def' : commProb G = Nat.card (ConjClasses G) / Nat.card G := by
  rw [commProb, card_comm_eq_card_conjClasses_mul_card, Nat.cast_mul, sq]
  

Proof state:
M : Type u_1
inst✝² : Mul M
inst✝¹ : Finite M
G : Type u_2
inst✝ : Group G
⊢ ↑(Nat.card (ConjClasses G)) * ↑(Nat.card G) / (↑(Nat.card G) * ↑(Nat.card G)) =
    ↑(Nat.card (ConjClasses G)) / ↑(Nat.card G)

Next tactic:
by_cases h : (Nat.card G : ℚ) = 0
theorem commProb_def' : commProb G = Nat.card (ConjClasses G) / Nat.card G := by
  rw [commProb, card_comm_eq_card_conjClasses_mul_card, Nat.cast_mul, sq]
  by_cases h : (Nat.card G : ℚ) = 0
  · 

Proof state:
case pos
M : Type u_1
inst✝² : Mul M
inst✝¹ : Finite M
G : Type u_2
inst✝ : Group G
h : ↑(Nat.card G) = 0
⊢ ↑(Nat.card (ConjClasses G)) * ↑(Nat.card G) / (↑(Nat.card G) * ↑(Nat.card G)) =
    ↑(Nat.card (ConjClasses G)) / ↑(Nat.card G)

Next tactic:
rw [h, zero_mul, div_zero, div_zero]
theorem commProb_def' : commProb G = Nat.card (ConjClasses G) / Nat.card G := by
  rw [commProb, card_comm_eq_card_conjClasses_mul_card, Nat.cast_mul, sq]
  by_cases h : (Nat.card G : ℚ) = 0
  · rw [h, zero_mul, div_zero, div_zero]
  · 

Proof state:
case neg
M : Type u_1
inst✝² : Mul M
inst✝¹ : Finite M
G : Type u_2
inst✝ : Group G
h : ¬↑(Nat.card G) = 0
⊢ ↑(Nat.card (ConjClasses G)) * ↑(Nat.card G) / (↑(Nat.card G) * ↑(Nat.card G)) =
    ↑(Nat.card (ConjClasses G)) / ↑(Nat.card G)

Next tactic:
exact mul_div_mul_right _ _ h
theorem Subgroup.commProb_subgroup_le : commProb H ≤ commProb G * (H.index : ℚ) ^ 2 := by
  /- After rewriting with `commProb_def`, we reduce to showing that `G` has at least as many
      commuting pairs as `H`. -/
  

Proof state:
M : Type u_1
inst✝³ : Mul M
inst✝² : Finite M
G : Type u_2
inst✝¹ : Group G
inst✝ : Finite G
H : Subgroup G
⊢ commProb ↥H ≤ commProb G * ↑(index H) ^ 2

Next tactic:
rw [commProb_def, commProb_def, div_le_iff, mul_assoc, ← mul_pow, ← Nat.cast_mul,
    mul_comm H.index, H.card_mul_index, div_mul_cancel, Nat.cast_le]
theorem Subgroup.commProb_subgroup_le : commProb H ≤ commProb G * (H.index : ℚ) ^ 2 := by
  /- After rewriting with `commProb_def`, we reduce to showing that `G` has at least as many
      commuting pairs as `H`. -/
  rw [commProb_def, commProb_def, div_le_iff, mul_assoc, ← mul_pow, ← Nat.cast_mul,
    mul_comm H.index, H.card_mul_index, div_mul_cancel, Nat.cast_le]
  · 

Proof state:
M : Type u_1
inst✝³ : Mul M
inst✝² : Finite M
G : Type u_2
inst✝¹ : Group G
inst✝ : Finite G
H : Subgroup G
⊢ Nat.card { p // Commute p.1 p.2 } ≤ Nat.card { p // Commute p.1 p.2 }

Next tactic:
refine' Finite.card_le_of_injective (fun p ↦ ⟨⟨p.1.1, p.1.2⟩, Subtype.ext_iff.mp p.2⟩) _
theorem Subgroup.commProb_subgroup_le : commProb H ≤ commProb G * (H.index : ℚ) ^ 2 := by
  /- After rewriting with `commProb_def`, we reduce to showing that `G` has at least as many
      commuting pairs as `H`. -/
  rw [commProb_def, commProb_def, div_le_iff, mul_assoc, ← mul_pow, ← Nat.cast_mul,
    mul_comm H.index, H.card_mul_index, div_mul_cancel, Nat.cast_le]
  · refine' Finite.card_le_of_injective (fun p ↦ ⟨⟨p.1.1, p.1.2⟩, Subtype.ext_iff.mp p.2⟩) _
    

Proof state:
M : Type u_1
inst✝³ : Mul M
inst✝² : Finite M
G : Type u_2
inst✝¹ : Group G
inst✝ : Finite G
H : Subgroup G
⊢ Function.Injective fun p => { val := (↑(↑p).1, ↑(↑p).2), property := (_ : ↑((↑p).1 * (↑p).2) = ↑((↑p).2 * (↑p).1)) }

Next tactic:
exact fun p q h ↦ by simpa only [Subtype.ext_iff, Prod.ext_iff] using h
theorem Subgroup.commProb_subgroup_le : commProb H ≤ commProb G * (H.index : ℚ) ^ 2 := by
  /- After rewriting with `commProb_def`, we reduce to showing that `G` has at least as many
      commuting pairs as `H`. -/
  rw [commProb_def, commProb_def, div_le_iff, mul_assoc, ← mul_pow, ← Nat.cast_mul,
    mul_comm H.index, H.card_mul_index, div_mul_cancel, Nat.cast_le]
  · refine' Finite.card_le_of_injective (fun p ↦ ⟨⟨p.1.1, p.1.2⟩, Subtype.ext_iff.mp p.2⟩) _
    exact fun p q h ↦ by 

Proof state:
M : Type u_1
inst✝³ : Mul M
inst✝² : Finite M
G : Type u_2
inst✝¹ : Group G
inst✝ : Finite G
H : Subgroup G
p q : { p // Commute p.1 p.2 }
h :
  (fun p => { val := (↑(↑p).1, ↑(↑p).2), property := (_ : ↑((↑p).1 * (↑p).2) = ↑((↑p).2 * (↑p).1)) }) p =
    (fun p => { val := (↑(↑p).1, ↑(↑p).2), property := (_ : ↑((↑p).1 * (↑p).2) = ↑((↑p).2 * (↑p).1)) }) q
⊢ p = q

Next tactic:
simpa only [Subtype.ext_iff, Prod.ext_iff] using h
theorem Subgroup.commProb_subgroup_le : commProb H ≤ commProb G * (H.index : ℚ) ^ 2 := by
  /- After rewriting with `commProb_def`, we reduce to showing that `G` has at least as many
      commuting pairs as `H`. -/
  rw [commProb_def, commProb_def, div_le_iff, mul_assoc, ← mul_pow, ← Nat.cast_mul,
    mul_comm H.index, H.card_mul_index, div_mul_cancel, Nat.cast_le]
  · refine' Finite.card_le_of_injective (fun p ↦ ⟨⟨p.1.1, p.1.2⟩, Subtype.ext_iff.mp p.2⟩) _
    exact fun p q h ↦ by simpa only [Subtype.ext_iff, Prod.ext_iff] using h
  · 

Proof state:
case h
M : Type u_1
inst✝³ : Mul M
inst✝² : Finite M
G : Type u_2
inst✝¹ : Group G
inst✝ : Finite G
H : Subgroup G
⊢ ↑(Nat.card G) ^ 2 ≠ 0

Next tactic:
exact pow_ne_zero 2 (Nat.cast_ne_zero.mpr Finite.card_pos.ne')
theorem Subgroup.commProb_subgroup_le : commProb H ≤ commProb G * (H.index : ℚ) ^ 2 := by
  /- After rewriting with `commProb_def`, we reduce to showing that `G` has at least as many
      commuting pairs as `H`. -/
  rw [commProb_def, commProb_def, div_le_iff, mul_assoc, ← mul_pow, ← Nat.cast_mul,
    mul_comm H.index, H.card_mul_index, div_mul_cancel, Nat.cast_le]
  · refine' Finite.card_le_of_injective (fun p ↦ ⟨⟨p.1.1, p.1.2⟩, Subtype.ext_iff.mp p.2⟩) _
    exact fun p q h ↦ by simpa only [Subtype.ext_iff, Prod.ext_iff] using h
  · exact pow_ne_zero 2 (Nat.cast_ne_zero.mpr Finite.card_pos.ne')
  · 

Proof state:
M : Type u_1
inst✝³ : Mul M
inst✝² : Finite M
G : Type u_2
inst✝¹ : Group G
inst✝ : Finite G
H : Subgroup G
⊢ 0 < ↑(Nat.card ↥H) ^ 2

Next tactic:
exact pow_pos (Nat.cast_pos.mpr Finite.card_pos) 2
theorem Subgroup.commProb_quotient_le [H.Normal] : commProb (G ⧸ H) ≤ commProb G * Nat.card H := by
  /- After rewriting with `commProb_def'`, we reduce to showing that `G` has at least as many
      conjugacy classes as `G ⧸ H`. -/
  

Proof state:
M : Type u_1
inst✝⁴ : Mul M
inst✝³ : Finite M
G : Type u_2
inst✝² : Group G
inst✝¹ : Finite G
H : Subgroup G
inst✝ : Normal H
⊢ commProb (G ⧸ H) ≤ commProb G * ↑(Nat.card ↥H)

Next tactic:
rw [commProb_def', commProb_def', div_le_iff, mul_assoc, ← Nat.cast_mul, ← Subgroup.index,
    H.card_mul_index, div_mul_cancel, Nat.cast_le]
theorem Subgroup.commProb_quotient_le [H.Normal] : commProb (G ⧸ H) ≤ commProb G * Nat.card H := by
  /- After rewriting with `commProb_def'`, we reduce to showing that `G` has at least as many
      conjugacy classes as `G ⧸ H`. -/
  rw [commProb_def', commProb_def', div_le_iff, mul_assoc, ← Nat.cast_mul, ← Subgroup.index,
    H.card_mul_index, div_mul_cancel, Nat.cast_le]
  · 

Proof state:
M : Type u_1
inst✝⁴ : Mul M
inst✝³ : Finite M
G : Type u_2
inst✝² : Group G
inst✝¹ : Finite G
H : Subgroup G
inst✝ : Normal H
⊢ Nat.card (ConjClasses (G ⧸ H)) ≤ Nat.card (ConjClasses G)

Next tactic:
apply Finite.card_le_of_surjective
theorem Subgroup.commProb_quotient_le [H.Normal] : commProb (G ⧸ H) ≤ commProb G * Nat.card H := by
  /- After rewriting with `commProb_def'`, we reduce to showing that `G` has at least as many
      conjugacy classes as `G ⧸ H`. -/
  rw [commProb_def', commProb_def', div_le_iff, mul_assoc, ← Nat.cast_mul, ← Subgroup.index,
    H.card_mul_index, div_mul_cancel, Nat.cast_le]
  · apply Finite.card_le_of_surjective
    

Proof state:
case hf
M : Type u_1
inst✝⁴ : Mul M
inst✝³ : Finite M
G : Type u_2
inst✝² : Group G
inst✝¹ : Finite G
H : Subgroup G
inst✝ : Normal H
⊢ Function.Surjective ?f
case f
M : Type u_1
inst✝⁴ : Mul M
inst✝³ : Finite M
G : Type u_2
inst✝² : Group G
inst✝¹ : Finite G
H : Subgroup G
inst✝ : Normal H
⊢ ConjClasses G → ConjClasses (G ⧸ H)

Next tactic:
show Function.Surjective (ConjClasses.map (QuotientGroup.mk' H))
theorem Subgroup.commProb_quotient_le [H.Normal] : commProb (G ⧸ H) ≤ commProb G * Nat.card H := by
  /- After rewriting with `commProb_def'`, we reduce to showing that `G` has at least as many
      conjugacy classes as `G ⧸ H`. -/
  rw [commProb_def', commProb_def', div_le_iff, mul_assoc, ← Nat.cast_mul, ← Subgroup.index,
    H.card_mul_index, div_mul_cancel, Nat.cast_le]
  · apply Finite.card_le_of_surjective
    show Function.Surjective (ConjClasses.map (QuotientGroup.mk' H))
    

Proof state:
case hf
M : Type u_1
inst✝⁴ : Mul M
inst✝³ : Finite M
G : Type u_2
inst✝² : Group G
inst✝¹ : Finite G
H : Subgroup G
inst✝ : Normal H
⊢ Function.Surjective (ConjClasses.map (QuotientGroup.mk' H))

Next tactic:
exact ConjClasses.map_surjective Quotient.surjective_Quotient_mk''
theorem Subgroup.commProb_quotient_le [H.Normal] : commProb (G ⧸ H) ≤ commProb G * Nat.card H := by
  /- After rewriting with `commProb_def'`, we reduce to showing that `G` has at least as many
      conjugacy classes as `G ⧸ H`. -/
  rw [commProb_def', commProb_def', div_le_iff, mul_assoc, ← Nat.cast_mul, ← Subgroup.index,
    H.card_mul_index, div_mul_cancel, Nat.cast_le]
  · apply Finite.card_le_of_surjective
    show Function.Surjective (ConjClasses.map (QuotientGroup.mk' H))
    exact ConjClasses.map_surjective Quotient.surjective_Quotient_mk''
  · 

Proof state:
case h
M : Type u_1
inst✝⁴ : Mul M
inst✝³ : Finite M
G : Type u_2
inst✝² : Group G
inst✝¹ : Finite G
H : Subgroup G
inst✝ : Normal H
⊢ ↑(Nat.card G) ≠ 0

Next tactic:
exact Nat.cast_ne_zero.mpr Finite.card_pos.ne'