l3lab/ntp-mathlib huggingface dataset:
@[to_additive]
theorem coe_eq_singleton {H : Subgroup G} : (∃ g : G, (H : Set G) = {g}) ↔ H = ⊥ :=
  ⟨fun ⟨g, hg⟩ =>
    haveI : Subsingleton (H : Set G) := by
      rw [hg]
      

Proof state:
G : Type u_1
G' : Type u_2
G'' : Type u_3
inst✝³ : Group G
inst✝² : Group G'
inst✝¹ : Group G''
A : Type u_4
inst✝ : AddGroup A
H✝ K H : Subgroup G
x✝ : ∃ g, ↑H = {g}
g : G
hg : ↑H = {g}
⊢ Subsingleton ↑{g}

Next tactic:
infer_instance
@[to_additive]
theorem nontrivial_iff_exists_ne_one (H : Subgroup G) : Nontrivial H ↔ ∃ x ∈ H, x ≠ (1 : G) := by
  

Proof state:
G : Type u_1
G' : Type u_2
G'' : Type u_3
inst✝³ : Group G
inst✝² : Group G'
inst✝¹ : Group G''
A : Type u_4
inst✝ : AddGroup A
H✝ K H : Subgroup G
⊢ Nontrivial ↥H ↔ ∃ x ∈ H, x ≠ 1

Next tactic:
rw [Subtype.nontrivial_iff_exists_ne (fun x => x ∈ H) (1 : H)]
@[to_additive]
theorem nontrivial_iff_exists_ne_one (H : Subgroup G) : Nontrivial H ↔ ∃ x ∈ H, x ≠ (1 : G) := by
  rw [Subtype.nontrivial_iff_exists_ne (fun x => x ∈ H) (1 : H)]
  

Proof state:
G : Type u_1
G' : Type u_2
G'' : Type u_3
inst✝³ : Group G
inst✝² : Group G'
inst✝¹ : Group G''
A : Type u_4
inst✝ : AddGroup A
H✝ K H : Subgroup G
⊢ (∃ y, ∃ (_ : y ∈ H), y ≠ ↑1) ↔ ∃ x ∈ H, x ≠ 1

Next tactic:
simp
@[to_additive]
theorem exists_ne_one_of_nontrivial (H : Subgroup G) [Nontrivial H] :
    ∃ x ∈ H, x ≠ 1 := by
  

Proof state:
G : Type u_1
G' : Type u_2
G'' : Type u_3
inst✝⁴ : Group G
inst✝³ : Group G'
inst✝² : Group G''
A : Type u_4
inst✝¹ : AddGroup A
H✝ K H : Subgroup G
inst✝ : Nontrivial ↥H
⊢ ∃ x ∈ H, x ≠ 1

Next tactic:
rwa [← Subgroup.nontrivial_iff_exists_ne_one]
@[to_additive]
theorem nontrivial_iff_ne_bot (H : Subgroup G) : Nontrivial H ↔ H ≠ ⊥ := by
  

Proof state:
G : Type u_1
G' : Type u_2
G'' : Type u_3
inst✝³ : Group G
inst✝² : Group G'
inst✝¹ : Group G''
A : Type u_4
inst✝ : AddGroup A
H✝ K H : Subgroup G
⊢ Nontrivial ↥H ↔ H ≠ ⊥

Next tactic:
rw [nontrivial_iff_exists_ne_one, ne_eq, eq_bot_iff_forall]
@[to_additive]
theorem nontrivial_iff_ne_bot (H : Subgroup G) : Nontrivial H ↔ H ≠ ⊥ := by
  rw [nontrivial_iff_exists_ne_one, ne_eq, eq_bot_iff_forall]
  

Proof state:
G : Type u_1
G' : Type u_2
G'' : Type u_3
inst✝³ : Group G
inst✝² : Group G'
inst✝¹ : Group G''
A : Type u_4
inst✝ : AddGroup A
H✝ K H : Subgroup G
⊢ (∃ x ∈ H, x ≠ 1) ↔ ¬∀ x ∈ H, x = 1

Next tactic:
simp only [ne_eq, not_forall, exists_prop]
/-- A subgroup is either the trivial subgroup or nontrivial. -/
@[to_additive "A subgroup is either the trivial subgroup or nontrivial."]
theorem bot_or_nontrivial (H : Subgroup G) : H = ⊥ ∨ Nontrivial H := by
  

Proof state:
G : Type u_1
G' : Type u_2
G'' : Type u_3
inst✝³ : Group G
inst✝² : Group G'
inst✝¹ : Group G''
A : Type u_4
inst✝ : AddGroup A
H✝ K H : Subgroup G
⊢ H = ⊥ ∨ Nontrivial ↥H

Next tactic:
have := nontrivial_iff_ne_bot H
/-- A subgroup is either the trivial subgroup or nontrivial. -/
@[to_additive "A subgroup is either the trivial subgroup or nontrivial."]
theorem bot_or_nontrivial (H : Subgroup G) : H = ⊥ ∨ Nontrivial H := by
  have := nontrivial_iff_ne_bot H
  

Proof state:
G : Type u_1
G' : Type u_2
G'' : Type u_3
inst✝³ : Group G
inst✝² : Group G'
inst✝¹ : Group G''
A : Type u_4
inst✝ : AddGroup A
H✝ K H : Subgroup G
this : Nontrivial ↥H ↔ H ≠ ⊥
⊢ H = ⊥ ∨ Nontrivial ↥H

Next tactic:
tauto
/-- A subgroup is either the trivial subgroup or contains a non-identity element. -/
@[to_additive "A subgroup is either the trivial subgroup or contains a nonzero element."]
theorem bot_or_exists_ne_one (H : Subgroup G) : H = ⊥ ∨ ∃ x ∈ H, x ≠ (1 : G) := by
  

Proof state:
G : Type u_1
G' : Type u_2
G'' : Type u_3
inst✝³ : Group G
inst✝² : Group G'
inst✝¹ : Group G''
A : Type u_4
inst✝ : AddGroup A
H✝ K H : Subgroup G
⊢ H = ⊥ ∨ ∃ x ∈ H, x ≠ 1

Next tactic:
convert H.bot_or_nontrivial
/-- A subgroup is either the trivial subgroup or contains a non-identity element. -/
@[to_additive "A subgroup is either the trivial subgroup or contains a nonzero element."]
theorem bot_or_exists_ne_one (H : Subgroup G) : H = ⊥ ∨ ∃ x ∈ H, x ≠ (1 : G) := by
  convert H.bot_or_nontrivial
  

Proof state:
case h.e'_2.a
G : Type u_1
G' : Type u_2
G'' : Type u_3
inst✝³ : Group G
inst✝² : Group G'
inst✝¹ : Group G''
A : Type u_4
inst✝ : AddGroup A
H✝ K H : Subgroup G
⊢ (∃ x ∈ H, x ≠ 1) ↔ Nontrivial ↥H

Next tactic:
rw [nontrivial_iff_exists_ne_one]
@[to_additive]
lemma ne_bot_iff_exists_ne_one {H : Subgroup G} : H ≠ ⊥ ↔ ∃ a : ↥H, a ≠ 1 := by
  

Proof state:
G : Type u_1
G' : Type u_2
G'' : Type u_3
inst✝³ : Group G
inst✝² : Group G'
inst✝¹ : Group G''
A : Type u_4
inst✝ : AddGroup A
H✝ K H : Subgroup G
⊢ H ≠ ⊥ ↔ ∃ a, a ≠ 1

Next tactic:
rw [← nontrivial_iff_ne_bot, nontrivial_iff_exists_ne_one]
@[to_additive]
lemma ne_bot_iff_exists_ne_one {H : Subgroup G} : H ≠ ⊥ ↔ ∃ a : ↥H, a ≠ 1 := by
  rw [← nontrivial_iff_ne_bot, nontrivial_iff_exists_ne_one]
  

Proof state:
G : Type u_1
G' : Type u_2
G'' : Type u_3
inst✝³ : Group G
inst✝² : Group G'
inst✝¹ : Group G''
A : Type u_4
inst✝ : AddGroup A
H✝ K H : Subgroup G
⊢ (∃ x ∈ H, x ≠ 1) ↔ ∃ a, a ≠ 1

Next tactic:
simp only [ne_eq, Subtype.exists, mk_eq_one_iff, exists_prop]
@[to_additive]
instance : InfSet (Subgroup G) :=
  ⟨fun s =>
    { (⨅ S ∈ s, Subgroup.toSubmonoid S).copy (⋂ S ∈ s, ↑S) (by 

Proof state:
G : Type u_1
G' : Type u_2
G'' : Type u_3
inst✝³ : Group G
inst✝² : Group G'
inst✝¹ : Group G''
A : Type u_4
inst✝ : AddGroup A
H K : Subgroup G
s : Set (Subgroup G)
⊢ ⋂ S ∈ s, ↑S = ↑(⨅ S ∈ s, S.toSubmonoid)

Next tactic:
simp
@[to_additive]
instance : InfSet (Subgroup G) :=
  ⟨fun s =>
    { (⨅ S ∈ s, Subgroup.toSubmonoid S).copy (⋂ S ∈ s, ↑S) (by simp) with
      inv_mem' := fun {x} hx =>
        Set.mem_biInter fun i h => i.inv_mem (by 

Proof state:
G : Type u_1
G' : Type u_2
G'' : Type u_3
inst✝³ : Group G
inst✝² : Group G'
inst✝¹ : Group G''
A : Type u_4
inst✝ : AddGroup A
H K : Subgroup G
s : Set (Subgroup G)
src✝ : Submonoid G :=
  Submonoid.copy (⨅ S ∈ s, S.toSubmonoid) (⋂ S ∈ s, ↑S) (_ : ⋂ S ∈ s, ↑S = ↑(⨅ i ∈ s, i.toSubmonoid))
x : G
hx : x ∈ { toSubsemigroup := src✝.toSubsemigroup, one_mem' := (_ : 1 ∈ src✝.carrier) }.toSubsemigroup.carrier
i : Subgroup G
h : i ∈ s
⊢ x ∈ i

Next tactic:
apply Set.mem_iInter₂.1 hx i h
@[to_additive]
theorem mem_iInf {ι : Sort*} {S : ι → Subgroup G} {x : G} : (x ∈ ⨅ i, S i) ↔ ∀ i, x ∈ S i := by
  

Proof state:
G : Type u_1
G' : Type u_2
G'' : Type u_3
inst✝³ : Group G
inst✝² : Group G'
inst✝¹ : Group G''
A : Type u_4
inst✝ : AddGroup A
H K : Subgroup G
ι : Sort u_5
S : ι → Subgroup G
x : G
⊢ x ∈ ⨅ i, S i ↔ ∀ (i : ι), x ∈ S i

Next tactic:
simp only [iInf, mem_sInf, Set.forall_range_iff]
@[to_additive (attr := simp, norm_cast)]
theorem coe_iInf {ι : Sort*} {S : ι → Subgroup G} : (↑(⨅ i, S i) : Set G) = ⋂ i, S i := by
  

Proof state:
G : Type u_1
G' : Type u_2
G'' : Type u_3
inst✝³ : Group G
inst✝² : Group G'
inst✝¹ : Group G''
A : Type u_4
inst✝ : AddGroup A
H K : Subgroup G
ι : Sort u_5
S : ι → Subgroup G
⊢ ↑(⨅ i, S i) = ⋂ i, ↑(S i)

Next tactic:
simp only [iInf, coe_sInf, Set.biInter_range]
@[to_additive (attr := simp)]
theorem subsingleton_iff : Subsingleton (Subgroup G) ↔ Subsingleton G :=
  ⟨fun h =>
    ⟨fun x y =>
      have : ∀ i : G, i = 1 := fun i =>
        mem_bot.mp <| Subsingleton.elim (⊤ : Subgroup G) ⊥ ▸ mem_top i
      (this x).trans (this y).symm⟩,
    fun h => ⟨fun x y => Subgroup.ext fun i => Subsingleton.elim 1 i ▸ by 

Proof state:
G : Type u_1
G' : Type u_2
G'' : Type u_3
inst✝³ : Group G
inst✝² : Group G'
inst✝¹ : Group G''
A : Type u_4
inst✝ : AddGroup A
H K : Subgroup G
h : Subsingleton G
x y : Subgroup G
i : G
⊢ 1 ∈ x ↔ 1 ∈ y

Next tactic:
simp [Subgroup.one_mem]
/-- A dependent version of `Subgroup.closure_induction`.  -/
@[to_additive (attr := elab_as_elim) "A dependent version of `AddSubgroup.closure_induction`. "]
theorem closure_induction' {p : ∀ x, x ∈ closure k → Prop}
    (Hs : ∀ (x) (h : x ∈ k), p x (subset_closure h)) (H1 : p 1 (one_mem _))
    (Hmul : ∀ x hx y hy, p x hx → p y hy → p (x * y) (mul_mem hx hy))
    (Hinv : ∀ x hx, p x hx → p x⁻¹ (inv_mem hx)) {x} (hx : x ∈ closure k) : p x hx := by
  

Proof state:
G : Type u_1
G' : Type u_2
G'' : Type u_3
inst✝³ : Group G
inst✝² : Group G'
inst✝¹ : Group G''
A : Type u_4
inst✝ : AddGroup A
H K : Subgroup G
k : Set G
p : (x : G) → x ∈ closure k → Prop
Hs : ∀ (x : G) (h : x ∈ k), p x (_ : x ∈ ↑(closure k))
H1 : p 1 (_ : 1 ∈ closure k)
Hmul : ∀ (x : G) (hx : x ∈ closure k) (y : G) (hy : y ∈ closure k), p x hx → p y hy → p (x * y) (_ : x * y ∈ closure k)
Hinv : ∀ (x : G) (hx : x ∈ closure k), p x hx → p x⁻¹ (_ : x⁻¹ ∈ closure k)
x : G
hx : x ∈ closure k
⊢ p x hx

Next tactic:
refine' Exists.elim _ fun (hx : x ∈ closure k) (hc : p x hx) => hc
/-- A dependent version of `Subgroup.closure_induction`.  -/
@[to_additive (attr := elab_as_elim) "A dependent version of `AddSubgroup.closure_induction`. "]
theorem closure_induction' {p : ∀ x, x ∈ closure k → Prop}
    (Hs : ∀ (x) (h : x ∈ k), p x (subset_closure h)) (H1 : p 1 (one_mem _))
    (Hmul : ∀ x hx y hy, p x hx → p y hy → p (x * y) (mul_mem hx hy))
    (Hinv : ∀ x hx, p x hx → p x⁻¹ (inv_mem hx)) {x} (hx : x ∈ closure k) : p x hx := by
  refine' Exists.elim _ fun (hx : x ∈ closure k) (hc : p x hx) => hc
  

Proof state:
G : Type u_1
G' : Type u_2
G'' : Type u_3
inst✝³ : Group G
inst✝² : Group G'
inst✝¹ : Group G''
A : Type u_4
inst✝ : AddGroup A
H K : Subgroup G
k : Set G
p : (x : G) → x ∈ closure k → Prop
Hs : ∀ (x : G) (h : x ∈ k), p x (_ : x ∈ ↑(closure k))
H1 : p 1 (_ : 1 ∈ closure k)
Hmul : ∀ (x : G) (hx : x ∈ closure k) (y : G) (hy : y ∈ closure k), p x hx → p y hy → p (x * y) (_ : x * y ∈ closure k)
Hinv : ∀ (x : G) (hx : x ∈ closure k), p x hx → p x⁻¹ (_ : x⁻¹ ∈ closure k)
x : G
hx : x ∈ closure k
⊢ ∃ (x_1 : x ∈ closure k), p x x_1

Next tactic:
exact
    closure_induction hx (fun x hx => ⟨_, Hs x hx⟩) ⟨_, H1⟩
      (fun x y ⟨hx', hx⟩ ⟨hy', hy⟩ => ⟨_, Hmul _ _ _ _ hx hy⟩) fun x ⟨hx', hx⟩ => ⟨_, Hinv _ _ hx⟩
@[to_additive (attr := simp)]
theorem closure_closure_coe_preimage {k : Set G} : closure (((↑) : closure k → G) ⁻¹' k) = ⊤ :=
  eq_top_iff.2 fun x =>
    Subtype.recOn x fun x hx _ => by
      

Proof state:
G : Type u_1
G' : Type u_2
G'' : Type u_3
inst✝³ : Group G
inst✝² : Group G'
inst✝¹ : Group G''
A : Type u_4
inst✝ : AddGroup A
H K : Subgroup G
k✝ k : Set G
x✝¹ : { x // x ∈ ↑(closure k) }
x : G
hx : x ∈ ↑(closure k)
x✝ : { val := x, property := hx } ∈ ⊤
⊢ { val := x, property := hx } ∈ closure (Subtype.val ⁻¹' k)

Next tactic:
refine' closure_induction' (fun g hg => _) _ (fun g₁ g₂ hg₁ hg₂ => _) (fun g hg => _) hx
@[to_additive (attr := simp)]
theorem closure_closure_coe_preimage {k : Set G} : closure (((↑) : closure k → G) ⁻¹' k) = ⊤ :=
  eq_top_iff.2 fun x =>
    Subtype.recOn x fun x hx _ => by
      refine' closure_induction' (fun g hg => _) _ (fun g₁ g₂ hg₁ hg₂ => _) (fun g hg => _) hx
      · 

Proof state:
case refine'_1
G : Type u_1
G' : Type u_2
G'' : Type u_3
inst✝³ : Group G
inst✝² : Group G'
inst✝¹ : Group G''
A : Type u_4
inst✝ : AddGroup A
H K : Subgroup G
k✝ k : Set G
x✝¹ : { x // x ∈ ↑(closure k) }
x : G
hx : x ∈ ↑(closure k)
x✝ : { val := x, property := hx } ∈ ⊤
g : G
hg : g ∈ k
⊢ { val := g, property := (_ : g ∈ ↑(closure k)) } ∈ closure (Subtype.val ⁻¹' k)

Next tactic:
exact subset_closure hg
@[to_additive (attr := simp)]
theorem closure_closure_coe_preimage {k : Set G} : closure (((↑) : closure k → G) ⁻¹' k) = ⊤ :=
  eq_top_iff.2 fun x =>
    Subtype.recOn x fun x hx _ => by
      refine' closure_induction' (fun g hg => _) _ (fun g₁ g₂ hg₁ hg₂ => _) (fun g hg => _) hx
      · exact subset_closure hg
      · 

Proof state:
case refine'_2
G : Type u_1
G' : Type u_2
G'' : Type u_3
inst✝³ : Group G
inst✝² : Group G'
inst✝¹ : Group G''
A : Type u_4
inst✝ : AddGroup A
H K : Subgroup G
k✝ k : Set G
x✝¹ : { x // x ∈ ↑(closure k) }
x : G
hx : x ∈ ↑(closure k)
x✝ : { val := x, property := hx } ∈ ⊤
⊢ { val := 1, property := (_ : 1 ∈ closure k) } ∈ closure (Subtype.val ⁻¹' k)

Next tactic:
exact one_mem _
@[to_additive (attr := simp)]
theorem closure_closure_coe_preimage {k : Set G} : closure (((↑) : closure k → G) ⁻¹' k) = ⊤ :=
  eq_top_iff.2 fun x =>
    Subtype.recOn x fun x hx _ => by
      refine' closure_induction' (fun g hg => _) _ (fun g₁ g₂ hg₁ hg₂ => _) (fun g hg => _) hx
      · exact subset_closure hg
      · exact one_mem _
      · 

Proof state:
case refine'_3
G : Type u_1
G' : Type u_2
G'' : Type u_3
inst✝³ : Group G
inst✝² : Group G'
inst✝¹ : Group G''
A : Type u_4
inst✝ : AddGroup A
H K : Subgroup G
k✝ k : Set G
x✝¹ : { x // x ∈ ↑(closure k) }
x : G
hx : x ∈ ↑(closure k)
x✝ : { val := x, property := hx } ∈ ⊤
g₁ : G
g₂ : g₁ ∈ closure k
hg₁ : G
hg₂ : hg₁ ∈ closure k
⊢ { val := g₁, property := g₂ } ∈ closure (Subtype.val ⁻¹' k) →
    { val := hg₁, property := hg₂ } ∈ closure (Subtype.val ⁻¹' k) →
      { val := g₁ * hg₁, property := (_ : g₁ * hg₁ ∈ closure k) } ∈ closure (Subtype.val ⁻¹' k)

Next tactic:
exact mul_mem
@[to_additive (attr := simp)]
theorem closure_closure_coe_preimage {k : Set G} : closure (((↑) : closure k → G) ⁻¹' k) = ⊤ :=
  eq_top_iff.2 fun x =>
    Subtype.recOn x fun x hx _ => by
      refine' closure_induction' (fun g hg => _) _ (fun g₁ g₂ hg₁ hg₂ => _) (fun g hg => _) hx
      · exact subset_closure hg
      · exact one_mem _
      · exact mul_mem
      · 

Proof state:
case refine'_4
G : Type u_1
G' : Type u_2
G'' : Type u_3
inst✝³ : Group G
inst✝² : Group G'
inst✝¹ : Group G''
A : Type u_4
inst✝ : AddGroup A
H K : Subgroup G
k✝ k : Set G
x✝¹ : { x // x ∈ ↑(closure k) }
x : G
hx : x ∈ ↑(closure k)
x✝ : { val := x, property := hx } ∈ ⊤
g : G
hg : g ∈ closure k
⊢ { val := g, property := hg } ∈ closure (Subtype.val ⁻¹' k) →
    { val := g⁻¹, property := (_ : g⁻¹ ∈ closure k) } ∈ closure (Subtype.val ⁻¹' k)

Next tactic:
exact inv_mem
/-- If all the elements of a set `s` commute, then `closure s` is a commutative group. -/
@[to_additive
      "If all the elements of a set `s` commute, then `closure s` is an additive
      commutative group."]
def closureCommGroupOfComm {k : Set G} (hcomm : ∀ x ∈ k, ∀ y ∈ k, x * y = y * x) :
    CommGroup (closure k) :=
  { (closure k).toGroup with
    mul_comm := fun x y => by
      

Proof state:
G : Type u_1
G' : Type u_2
G'' : Type u_3
inst✝³ : Group G
inst✝² : Group G'
inst✝¹ : Group G''
A : Type u_4
inst✝ : AddGroup A
H K : Subgroup G
k✝ k : Set G
hcomm : ∀ x ∈ k, ∀ y ∈ k, x * y = y * x
src✝ : Group ↥(closure k) := toGroup (closure k)
x y : ↥(closure k)
⊢ x * y = y * x

Next tactic:
ext
/-- If all the elements of a set `s` commute, then `closure s` is a commutative group. -/
@[to_additive
      "If all the elements of a set `s` commute, then `closure s` is an additive
      commutative group."]
def closureCommGroupOfComm {k : Set G} (hcomm : ∀ x ∈ k, ∀ y ∈ k, x * y = y * x) :
    CommGroup (closure k) :=
  { (closure k).toGroup with
    mul_comm := fun x y => by
      ext
      

Proof state:
case a
G : Type u_1
G' : Type u_2
G'' : Type u_3
inst✝³ : Group G
inst✝² : Group G'
inst✝¹ : Group G''
A : Type u_4
inst✝ : AddGroup A
H K : Subgroup G
k✝ k : Set G
hcomm : ∀ x ∈ k, ∀ y ∈ k, x * y = y * x
src✝ : Group ↥(closure k) := toGroup (closure k)
x y : ↥(closure k)
⊢ ↑(x * y) = ↑(y * x)

Next tactic:
simp only [Subgroup.coe_mul]
/-- If all the elements of a set `s` commute, then `closure s` is a commutative group. -/
@[to_additive
      "If all the elements of a set `s` commute, then `closure s` is an additive
      commutative group."]
def closureCommGroupOfComm {k : Set G} (hcomm : ∀ x ∈ k, ∀ y ∈ k, x * y = y * x) :
    CommGroup (closure k) :=
  { (closure k).toGroup with
    mul_comm := fun x y => by
      ext
      simp only [Subgroup.coe_mul]
      

Proof state:
case a
G : Type u_1
G' : Type u_2
G'' : Type u_3
inst✝³ : Group G
inst✝² : Group G'
inst✝¹ : Group G''
A : Type u_4
inst✝ : AddGroup A
H K : Subgroup G
k✝ k : Set G
hcomm : ∀ x ∈ k, ∀ y ∈ k, x * y = y * x
src✝ : Group ↥(closure k) := toGroup (closure k)
x y : ↥(closure k)
⊢ ↑x * ↑y = ↑y * ↑x

Next tactic:
refine'
        closure_induction₂ x.prop y.prop hcomm (fun x => by simp only [mul_one, one_mul])
          (fun x => by simp only [mul_one, one_mul])
          (fun x y z h₁ h₂ => by rw [mul_assoc, h₂, ← mul_assoc, h₁, mul_assoc])
          (fun x y z h₁ h₂ => by rw [← mul_assoc, h₁, mul_assoc, h₂, ← mul_assoc])
          (fun x y h => by
            rw [inv_mul_eq_iff_eq_mul, ← mul_assoc, h, mul_assoc, mul_inv_self, mul_one])
          fun x y h => by
          rw [mul_inv_eq_iff_eq_mul, mul_assoc, h, ← mul_assoc, inv_mul_self, one_mul]
/-- If all the elements of a set `s` commute, then `closure s` is a commutative group. -/
@[to_additive
      "If all the elements of a set `s` commute, then `closure s` is an additive
      commutative group."]
def closureCommGroupOfComm {k : Set G} (hcomm : ∀ x ∈ k, ∀ y ∈ k, x * y = y * x) :
    CommGroup (closure k) :=
  { (closure k).toGroup with
    mul_comm := fun x y => by
      ext
      simp only [Subgroup.coe_mul]
      refine'
        closure_induction₂ x.prop y.prop hcomm (fun x => by 

Proof state:
G : Type u_1
G' : Type u_2
G'' : Type u_3
inst✝³ : Group G
inst✝² : Group G'
inst✝¹ : Group G''
A : Type u_4
inst✝ : AddGroup A
H K : Subgroup G
k✝ k : Set G
hcomm : ∀ x ∈ k, ∀ y ∈ k, x * y = y * x
src✝ : Group ↥(closure k) := toGroup (closure k)
x✝ y : ↥(closure k)
x : G
⊢ 1 * x = x * 1

Next tactic:
simp only [mul_one, one_mul]
/-- If all the elements of a set `s` commute, then `closure s` is a commutative group. -/
@[to_additive
      "If all the elements of a set `s` commute, then `closure s` is an additive
      commutative group."]
def closureCommGroupOfComm {k : Set G} (hcomm : ∀ x ∈ k, ∀ y ∈ k, x * y = y * x) :
    CommGroup (closure k) :=
  { (closure k).toGroup with
    mul_comm := fun x y => by
      ext
      simp only [Subgroup.coe_mul]
      refine'
        closure_induction₂ x.prop y.prop hcomm (fun x => by simp only [mul_one, one_mul])
          (fun x => by 

Proof state:
G : Type u_1
G' : Type u_2
G'' : Type u_3
inst✝³ : Group G
inst✝² : Group G'
inst✝¹ : Group G''
A : Type u_4
inst✝ : AddGroup A
H K : Subgroup G
k✝ k : Set G
hcomm : ∀ x ∈ k, ∀ y ∈ k, x * y = y * x
src✝ : Group ↥(closure k) := toGroup (closure k)
x✝ y : ↥(closure k)
x : G
⊢ x * 1 = 1 * x

Next tactic:
simp only [mul_one, one_mul]
/-- If all the elements of a set `s` commute, then `closure s` is a commutative group. -/
@[to_additive
      "If all the elements of a set `s` commute, then `closure s` is an additive
      commutative group."]
def closureCommGroupOfComm {k : Set G} (hcomm : ∀ x ∈ k, ∀ y ∈ k, x * y = y * x) :
    CommGroup (closure k) :=
  { (closure k).toGroup with
    mul_comm := fun x y => by
      ext
      simp only [Subgroup.coe_mul]
      refine'
        closure_induction₂ x.prop y.prop hcomm (fun x => by simp only [mul_one, one_mul])
          (fun x => by simp only [mul_one, one_mul])
          (fun x y z h₁ h₂ => by 

Proof state:
G : Type u_1
G' : Type u_2
G'' : Type u_3
inst✝³ : Group G
inst✝² : Group G'
inst✝¹ : Group G''
A : Type u_4
inst✝ : AddGroup A
H K : Subgroup G
k✝ k : Set G
hcomm : ∀ x ∈ k, ∀ y ∈ k, x * y = y * x
src✝ : Group ↥(closure k) := toGroup (closure k)
x✝ y✝ : ↥(closure k)
x y z : G
h₁ : x * z = z * x
h₂ : y * z = z * y
⊢ x * y * z = z * (x * y)

Next tactic:
rw [mul_assoc, h₂, ← mul_assoc, h₁, mul_assoc]
/-- If all the elements of a set `s` commute, then `closure s` is a commutative group. -/
@[to_additive
      "If all the elements of a set `s` commute, then `closure s` is an additive
      commutative group."]
def closureCommGroupOfComm {k : Set G} (hcomm : ∀ x ∈ k, ∀ y ∈ k, x * y = y * x) :
    CommGroup (closure k) :=
  { (closure k).toGroup with
    mul_comm := fun x y => by
      ext
      simp only [Subgroup.coe_mul]
      refine'
        closure_induction₂ x.prop y.prop hcomm (fun x => by simp only [mul_one, one_mul])
          (fun x => by simp only [mul_one, one_mul])
          (fun x y z h₁ h₂ => by rw [mul_assoc, h₂, ← mul_assoc, h₁, mul_assoc])
          (fun x y z h₁ h₂ => by 

Proof state:
G : Type u_1
G' : Type u_2
G'' : Type u_3
inst✝³ : Group G
inst✝² : Group G'
inst✝¹ : Group G''
A : Type u_4
inst✝ : AddGroup A
H K : Subgroup G
k✝ k : Set G
hcomm : ∀ x ∈ k, ∀ y ∈ k, x * y = y * x
src✝ : Group ↥(closure k) := toGroup (closure k)
x✝ y✝ : ↥(closure k)
x y z : G
h₁ : x * y = y * x
h₂ : x * z = z * x
⊢ x * (y * z) = y * z * x

Next tactic:
rw [← mul_assoc, h₁, mul_assoc, h₂, ← mul_assoc]
/-- If all the elements of a set `s` commute, then `closure s` is a commutative group. -/
@[to_additive
      "If all the elements of a set `s` commute, then `closure s` is an additive
      commutative group."]
def closureCommGroupOfComm {k : Set G} (hcomm : ∀ x ∈ k, ∀ y ∈ k, x * y = y * x) :
    CommGroup (closure k) :=
  { (closure k).toGroup with
    mul_comm := fun x y => by
      ext
      simp only [Subgroup.coe_mul]
      refine'
        closure_induction₂ x.prop y.prop hcomm (fun x => by simp only [mul_one, one_mul])
          (fun x => by simp only [mul_one, one_mul])
          (fun x y z h₁ h₂ => by rw [mul_assoc, h₂, ← mul_assoc, h₁, mul_assoc])
          (fun x y z h₁ h₂ => by rw [← mul_assoc, h₁, mul_assoc, h₂, ← mul_assoc])
          (fun x y h => by
            

Proof state:
G : Type u_1
G' : Type u_2
G'' : Type u_3
inst✝³ : Group G
inst✝² : Group G'
inst✝¹ : Group G''
A : Type u_4
inst✝ : AddGroup A
H K : Subgroup G
k✝ k : Set G
hcomm : ∀ x ∈ k, ∀ y ∈ k, x * y = y * x
src✝ : Group ↥(closure k) := toGroup (closure k)
x✝ y✝ : ↥(closure k)
x y : G
h : x * y = y * x
⊢ x⁻¹ * y = y * x⁻¹

Next tactic:
rw [inv_mul_eq_iff_eq_mul, ← mul_assoc, h, mul_assoc, mul_inv_self, mul_one]
/-- If all the elements of a set `s` commute, then `closure s` is a commutative group. -/
@[to_additive
      "If all the elements of a set `s` commute, then `closure s` is an additive
      commutative group."]
def closureCommGroupOfComm {k : Set G} (hcomm : ∀ x ∈ k, ∀ y ∈ k, x * y = y * x) :
    CommGroup (closure k) :=
  { (closure k).toGroup with
    mul_comm := fun x y => by
      ext
      simp only [Subgroup.coe_mul]
      refine'
        closure_induction₂ x.prop y.prop hcomm (fun x => by simp only [mul_one, one_mul])
          (fun x => by simp only [mul_one, one_mul])
          (fun x y z h₁ h₂ => by rw [mul_assoc, h₂, ← mul_assoc, h₁, mul_assoc])
          (fun x y z h₁ h₂ => by rw [← mul_assoc, h₁, mul_assoc, h₂, ← mul_assoc])
          (fun x y h => by
            rw [inv_mul_eq_iff_eq_mul, ← mul_assoc, h, mul_assoc, mul_inv_self, mul_one])
          fun x y h => by
          

Proof state:
G : Type u_1
G' : Type u_2
G'' : Type u_3
inst✝³ : Group G
inst✝² : Group G'
inst✝¹ : Group G''
A : Type u_4
inst✝ : AddGroup A
H K : Subgroup G
k✝ k : Set G
hcomm : ∀ x ∈ k, ∀ y ∈ k, x * y = y * x
src✝ : Group ↥(closure k) := toGroup (closure k)
x✝ y✝ : ↥(closure k)
x y : G
h : x * y = y * x
⊢ x * y⁻¹ = y⁻¹ * x

Next tactic:
rw [mul_inv_eq_iff_eq_mul, mul_assoc, h, ← mul_assoc, inv_mul_self, one_mul]
@[to_additive]
theorem sup_eq_closure (H H' : Subgroup G) : H ⊔ H' = closure ((H : Set G) ∪ (H' : Set G)) :=
  by 

Proof state:
G : Type u_1
G' : Type u_2
G'' : Type u_3
inst✝³ : Group G
inst✝² : Group G'
inst✝¹ : Group G''
A : Type u_4
inst✝ : AddGroup A
H✝ K : Subgroup G
k : Set G
H H' : Subgroup G
⊢ H ⊔ H' = closure (↑H ∪ ↑H')

Next tactic:
simp_rw [closure_union, closure_eq]
@[to_additive]
theorem iSup_eq_closure {ι : Sort*} (p : ι → Subgroup G) :
    ⨆ i, p i = closure (⋃ i, (p i : Set G)) := by 

Proof state:
G : Type u_1
G' : Type u_2
G'' : Type u_3
inst✝³ : Group G
inst✝² : Group G'
inst✝¹ : Group G''
A : Type u_4
inst✝ : AddGroup A
H K : Subgroup G
k : Set G
ι : Sort u_5
p : ι → Subgroup G
⊢ ⨆ i, p i = closure (⋃ i, ↑(p i))

Next tactic:
simp_rw [closure_iUnion, closure_eq]