l3lab/ntp-mathlib huggingface dataset:
/-- The subgroup generated by an element of a group equals the set of integer number powers of
    the element. -/
@[to_additive
      "The `AddSubgroup` generated by an element of an `AddGroup` equals the set of
      natural number multiples of the element."]
theorem mem_closure_singleton {x y : G} : y ∈ closure ({x} : Set G) ↔ ∃ n : ℤ, x ^ n = 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 : Set G
x y : G
⊢ y ∈ closure {x} ↔ ∃ n, x ^ n = y

Next tactic:
refine'
    ⟨fun hy => closure_induction hy _ _ _ _, fun ⟨n, hn⟩ =>
      hn ▸ zpow_mem (subset_closure <| mem_singleton x) n⟩
/-- The subgroup generated by an element of a group equals the set of integer number powers of
    the element. -/
@[to_additive
      "The `AddSubgroup` generated by an element of an `AddGroup` equals the set of
      natural number multiples of the element."]
theorem mem_closure_singleton {x y : G} : y ∈ closure ({x} : Set G) ↔ ∃ n : ℤ, x ^ n = y := by
  refine'
    ⟨fun hy => closure_induction hy _ _ _ _, fun ⟨n, hn⟩ =>
      hn ▸ zpow_mem (subset_closure <| mem_singleton x) n⟩
  · 

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 : Set G
x y : G
hy : y ∈ closure {x}
⊢ ∀ x_1 ∈ {x}, ∃ n, x ^ n = x_1

Next tactic:
intro y hy
/-- The subgroup generated by an element of a group equals the set of integer number powers of
    the element. -/
@[to_additive
      "The `AddSubgroup` generated by an element of an `AddGroup` equals the set of
      natural number multiples of the element."]
theorem mem_closure_singleton {x y : G} : y ∈ closure ({x} : Set G) ↔ ∃ n : ℤ, x ^ n = y := by
  refine'
    ⟨fun hy => closure_induction hy _ _ _ _, fun ⟨n, hn⟩ =>
      hn ▸ zpow_mem (subset_closure <| mem_singleton x) n⟩
  · intro y hy
    

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 : Set G
x y✝ : G
hy✝ : y✝ ∈ closure {x}
y : G
hy : y ∈ {x}
⊢ ∃ n, x ^ n = y

Next tactic:
rw [eq_of_mem_singleton hy]
/-- The subgroup generated by an element of a group equals the set of integer number powers of
    the element. -/
@[to_additive
      "The `AddSubgroup` generated by an element of an `AddGroup` equals the set of
      natural number multiples of the element."]
theorem mem_closure_singleton {x y : G} : y ∈ closure ({x} : Set G) ↔ ∃ n : ℤ, x ^ n = y := by
  refine'
    ⟨fun hy => closure_induction hy _ _ _ _, fun ⟨n, hn⟩ =>
      hn ▸ zpow_mem (subset_closure <| mem_singleton x) n⟩
  · intro y hy
    rw [eq_of_mem_singleton hy]
    

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 : Set G
x y✝ : G
hy✝ : y✝ ∈ closure {x}
y : G
hy : y ∈ {x}
⊢ ∃ n, x ^ n = x

Next tactic:
exact ⟨1, zpow_one x⟩
/-- The subgroup generated by an element of a group equals the set of integer number powers of
    the element. -/
@[to_additive
      "The `AddSubgroup` generated by an element of an `AddGroup` equals the set of
      natural number multiples of the element."]
theorem mem_closure_singleton {x y : G} : y ∈ closure ({x} : Set G) ↔ ∃ n : ℤ, x ^ n = y := by
  refine'
    ⟨fun hy => closure_induction hy _ _ _ _, fun ⟨n, hn⟩ =>
      hn ▸ zpow_mem (subset_closure <| mem_singleton x) n⟩
  · intro y hy
    rw [eq_of_mem_singleton hy]
    exact ⟨1, zpow_one x⟩
  · 

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 : Set G
x y : G
hy : y ∈ closure {x}
⊢ ∃ n, x ^ n = 1

Next tactic:
exact ⟨0, zpow_zero x⟩
/-- The subgroup generated by an element of a group equals the set of integer number powers of
    the element. -/
@[to_additive
      "The `AddSubgroup` generated by an element of an `AddGroup` equals the set of
      natural number multiples of the element."]
theorem mem_closure_singleton {x y : G} : y ∈ closure ({x} : Set G) ↔ ∃ n : ℤ, x ^ n = y := by
  refine'
    ⟨fun hy => closure_induction hy _ _ _ _, fun ⟨n, hn⟩ =>
      hn ▸ zpow_mem (subset_closure <| mem_singleton x) n⟩
  · intro y hy
    rw [eq_of_mem_singleton hy]
    exact ⟨1, zpow_one x⟩
  · exact ⟨0, zpow_zero x⟩
  · 

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 : Set G
x y : G
hy : y ∈ closure {x}
⊢ ∀ (x_1 y : G), (∃ n, x ^ n = x_1) → (∃ n, x ^ n = y) → ∃ n, x ^ n = x_1 * y

Next tactic:
rintro _ _ ⟨n, rfl⟩ ⟨m, rfl⟩
/-- The subgroup generated by an element of a group equals the set of integer number powers of
    the element. -/
@[to_additive
      "The `AddSubgroup` generated by an element of an `AddGroup` equals the set of
      natural number multiples of the element."]
theorem mem_closure_singleton {x y : G} : y ∈ closure ({x} : Set G) ↔ ∃ n : ℤ, x ^ n = y := by
  refine'
    ⟨fun hy => closure_induction hy _ _ _ _, fun ⟨n, hn⟩ =>
      hn ▸ zpow_mem (subset_closure <| mem_singleton x) n⟩
  · intro y hy
    rw [eq_of_mem_singleton hy]
    exact ⟨1, zpow_one x⟩
  · exact ⟨0, zpow_zero x⟩
  · rintro _ _ ⟨n, rfl⟩ ⟨m, rfl⟩
    

Proof state:
case refine'_3.intro.intro
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
x y : G
hy : y ∈ closure {x}
n m : ℤ
⊢ ∃ n_1, x ^ n_1 = x ^ n * x ^ m

Next tactic:
exact ⟨n + m, zpow_add x n m⟩
/-- The subgroup generated by an element of a group equals the set of integer number powers of
    the element. -/
@[to_additive
      "The `AddSubgroup` generated by an element of an `AddGroup` equals the set of
      natural number multiples of the element."]
theorem mem_closure_singleton {x y : G} : y ∈ closure ({x} : Set G) ↔ ∃ n : ℤ, x ^ n = y := by
  refine'
    ⟨fun hy => closure_induction hy _ _ _ _, fun ⟨n, hn⟩ =>
      hn ▸ zpow_mem (subset_closure <| mem_singleton x) n⟩
  · intro y hy
    rw [eq_of_mem_singleton hy]
    exact ⟨1, zpow_one x⟩
  · exact ⟨0, zpow_zero x⟩
  · rintro _ _ ⟨n, rfl⟩ ⟨m, rfl⟩
    exact ⟨n + m, zpow_add x n m⟩
  

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 : Set G
x y : G
hy : y ∈ closure {x}
⊢ ∀ (x_1 : G), (∃ n, x ^ n = x_1) → ∃ n, x ^ n = x_1⁻¹

Next tactic:
rintro _ ⟨n, rfl⟩
/-- The subgroup generated by an element of a group equals the set of integer number powers of
    the element. -/
@[to_additive
      "The `AddSubgroup` generated by an element of an `AddGroup` equals the set of
      natural number multiples of the element."]
theorem mem_closure_singleton {x y : G} : y ∈ closure ({x} : Set G) ↔ ∃ n : ℤ, x ^ n = y := by
  refine'
    ⟨fun hy => closure_induction hy _ _ _ _, fun ⟨n, hn⟩ =>
      hn ▸ zpow_mem (subset_closure <| mem_singleton x) n⟩
  · intro y hy
    rw [eq_of_mem_singleton hy]
    exact ⟨1, zpow_one x⟩
  · exact ⟨0, zpow_zero x⟩
  · rintro _ _ ⟨n, rfl⟩ ⟨m, rfl⟩
    exact ⟨n + m, zpow_add x n m⟩
  rintro _ ⟨n, rfl⟩
  

Proof state:
case refine'_4.intro
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
x y : G
hy : y ∈ closure {x}
n : ℤ
⊢ ∃ n_1, x ^ n_1 = (x ^ n)⁻¹

Next tactic:
exact ⟨-n, zpow_neg x n⟩
@[to_additive]
theorem closure_singleton_one : closure ({1} : 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
⊢ closure {1} = ⊥

Next tactic:
simp [eq_bot_iff_forall, mem_closure_singleton]
@[to_additive]
theorem mem_iSup_of_directed {ι} [hι : Nonempty ι] {K : ι → Subgroup G} (hK : Directed (· ≤ ·) K)
    {x : G} : x ∈ (iSup K : Subgroup G) ↔ ∃ i, x ∈ K 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
k : Set G
ι : Sort u_5
hι : Nonempty ι
K : ι → Subgroup G
hK : Directed (fun x x_1 => x ≤ x_1) K
x : G
⊢ x ∈ iSup K ↔ ∃ i, x ∈ K i

Next tactic:
refine ⟨?_, fun ⟨i, hi⟩ ↦ le_iSup K i hi⟩
@[to_additive]
theorem mem_iSup_of_directed {ι} [hι : Nonempty ι] {K : ι → Subgroup G} (hK : Directed (· ≤ ·) K)
    {x : G} : x ∈ (iSup K : Subgroup G) ↔ ∃ i, x ∈ K i := by
  refine ⟨?_, fun ⟨i, hi⟩ ↦ le_iSup K i hi⟩
  

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
hι : Nonempty ι
K : ι → Subgroup G
hK : Directed (fun x x_1 => x ≤ x_1) K
x : G
⊢ x ∈ iSup K → ∃ i, x ∈ K i

Next tactic:
suffices x ∈ closure (⋃ i, (K i : Set G)) → ∃ i, x ∈ K i by
    simpa only [closure_iUnion, closure_eq (K _)] using this
@[to_additive]
theorem mem_iSup_of_directed {ι} [hι : Nonempty ι] {K : ι → Subgroup G} (hK : Directed (· ≤ ·) K)
    {x : G} : x ∈ (iSup K : Subgroup G) ↔ ∃ i, x ∈ K i := by
  refine ⟨?_, fun ⟨i, hi⟩ ↦ le_iSup K i hi⟩
  suffices x ∈ closure (⋃ i, (K i : Set G)) → ∃ i, x ∈ K 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
k : Set G
ι : Sort u_5
hι : Nonempty ι
K : ι → Subgroup G
hK : Directed (fun x x_1 => x ≤ x_1) K
x : G
this : x ∈ closure (⋃ i, ↑(K i)) → ∃ i, x ∈ K i
⊢ x ∈ iSup K → ∃ i, x ∈ K i

Next tactic:
simpa only [closure_iUnion, closure_eq (K _)] using this
@[to_additive]
theorem mem_iSup_of_directed {ι} [hι : Nonempty ι] {K : ι → Subgroup G} (hK : Directed (· ≤ ·) K)
    {x : G} : x ∈ (iSup K : Subgroup G) ↔ ∃ i, x ∈ K i := by
  refine ⟨?_, fun ⟨i, hi⟩ ↦ le_iSup K i hi⟩
  suffices x ∈ closure (⋃ i, (K i : Set G)) → ∃ i, x ∈ K i by
    simpa only [closure_iUnion, closure_eq (K _)] using this
  

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
hι : Nonempty ι
K : ι → Subgroup G
hK : Directed (fun x x_1 => x ≤ x_1) K
x : G
⊢ x ∈ closure (⋃ i, ↑(K i)) → ∃ i, x ∈ K i

Next tactic:
refine fun hx ↦ closure_induction hx (fun _ ↦ mem_iUnion.1) ?_ ?_ ?_
@[to_additive]
theorem mem_iSup_of_directed {ι} [hι : Nonempty ι] {K : ι → Subgroup G} (hK : Directed (· ≤ ·) K)
    {x : G} : x ∈ (iSup K : Subgroup G) ↔ ∃ i, x ∈ K i := by
  refine ⟨?_, fun ⟨i, hi⟩ ↦ le_iSup K i hi⟩
  suffices x ∈ closure (⋃ i, (K i : Set G)) → ∃ i, x ∈ K i by
    simpa only [closure_iUnion, closure_eq (K _)] using this
  refine fun hx ↦ closure_induction hx (fun _ ↦ mem_iUnion.1) ?_ ?_ ?_
  · 

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 : Set G
ι : Sort u_5
hι : Nonempty ι
K : ι → Subgroup G
hK : Directed (fun x x_1 => x ≤ x_1) K
x : G
hx : x ∈ closure (⋃ i, ↑(K i))
⊢ ∃ i, 1 ∈ K i

Next tactic:
exact hι.elim fun i ↦ ⟨i, (K i).one_mem⟩
@[to_additive]
theorem mem_iSup_of_directed {ι} [hι : Nonempty ι] {K : ι → Subgroup G} (hK : Directed (· ≤ ·) K)
    {x : G} : x ∈ (iSup K : Subgroup G) ↔ ∃ i, x ∈ K i := by
  refine ⟨?_, fun ⟨i, hi⟩ ↦ le_iSup K i hi⟩
  suffices x ∈ closure (⋃ i, (K i : Set G)) → ∃ i, x ∈ K i by
    simpa only [closure_iUnion, closure_eq (K _)] using this
  refine fun hx ↦ closure_induction hx (fun _ ↦ mem_iUnion.1) ?_ ?_ ?_
  · exact hι.elim fun i ↦ ⟨i, (K i).one_mem⟩
  · 

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 : Set G
ι : Sort u_5
hι : Nonempty ι
K : ι → Subgroup G
hK : Directed (fun x x_1 => x ≤ x_1) K
x : G
hx : x ∈ closure (⋃ i, ↑(K i))
⊢ ∀ (x y : G), (∃ i, x ∈ K i) → (∃ i, y ∈ K i) → ∃ i, x * y ∈ K i

Next tactic:
rintro x y ⟨i, hi⟩ ⟨j, hj⟩
@[to_additive]
theorem mem_iSup_of_directed {ι} [hι : Nonempty ι] {K : ι → Subgroup G} (hK : Directed (· ≤ ·) K)
    {x : G} : x ∈ (iSup K : Subgroup G) ↔ ∃ i, x ∈ K i := by
  refine ⟨?_, fun ⟨i, hi⟩ ↦ le_iSup K i hi⟩
  suffices x ∈ closure (⋃ i, (K i : Set G)) → ∃ i, x ∈ K i by
    simpa only [closure_iUnion, closure_eq (K _)] using this
  refine fun hx ↦ closure_induction hx (fun _ ↦ mem_iUnion.1) ?_ ?_ ?_
  · exact hι.elim fun i ↦ ⟨i, (K i).one_mem⟩
  · rintro x y ⟨i, hi⟩ ⟨j, hj⟩
    

Proof state:
case refine_2.intro.intro
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
hι : Nonempty ι
K : ι → Subgroup G
hK : Directed (fun x x_1 => x ≤ x_1) K
x✝ : G
hx : x✝ ∈ closure (⋃ i, ↑(K i))
x y : G
i : ι
hi : x ∈ K i
j : ι
hj : y ∈ K j
⊢ ∃ i, x * y ∈ K i

Next tactic:
rcases hK i j with ⟨k, hki, hkj⟩
@[to_additive]
theorem mem_iSup_of_directed {ι} [hι : Nonempty ι] {K : ι → Subgroup G} (hK : Directed (· ≤ ·) K)
    {x : G} : x ∈ (iSup K : Subgroup G) ↔ ∃ i, x ∈ K i := by
  refine ⟨?_, fun ⟨i, hi⟩ ↦ le_iSup K i hi⟩
  suffices x ∈ closure (⋃ i, (K i : Set G)) → ∃ i, x ∈ K i by
    simpa only [closure_iUnion, closure_eq (K _)] using this
  refine fun hx ↦ closure_induction hx (fun _ ↦ mem_iUnion.1) ?_ ?_ ?_
  · exact hι.elim fun i ↦ ⟨i, (K i).one_mem⟩
  · rintro x y ⟨i, hi⟩ ⟨j, hj⟩
    rcases hK i j with ⟨k, hki, hkj⟩
    

Proof state:
case refine_2.intro.intro.intro.intro
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
hι : Nonempty ι
K : ι → Subgroup G
hK : Directed (fun x x_1 => x ≤ x_1) K
x✝ : G
hx : x✝ ∈ closure (⋃ i, ↑(K i))
x y : G
i : ι
hi : x ∈ K i
j : ι
hj : y ∈ K j
k : ι
hki : K i ≤ K k
hkj : K j ≤ K k
⊢ ∃ i, x * y ∈ K i

Next tactic:
exact ⟨k, mul_mem (hki hi) (hkj hj)⟩
@[to_additive]
theorem mem_iSup_of_directed {ι} [hι : Nonempty ι] {K : ι → Subgroup G} (hK : Directed (· ≤ ·) K)
    {x : G} : x ∈ (iSup K : Subgroup G) ↔ ∃ i, x ∈ K i := by
  refine ⟨?_, fun ⟨i, hi⟩ ↦ le_iSup K i hi⟩
  suffices x ∈ closure (⋃ i, (K i : Set G)) → ∃ i, x ∈ K i by
    simpa only [closure_iUnion, closure_eq (K _)] using this
  refine fun hx ↦ closure_induction hx (fun _ ↦ mem_iUnion.1) ?_ ?_ ?_
  · exact hι.elim fun i ↦ ⟨i, (K i).one_mem⟩
  · rintro x y ⟨i, hi⟩ ⟨j, hj⟩
    rcases hK i j with ⟨k, hki, hkj⟩
    exact ⟨k, mul_mem (hki hi) (hkj hj)⟩
  · 

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 : Set G
ι : Sort u_5
hι : Nonempty ι
K : ι → Subgroup G
hK : Directed (fun x x_1 => x ≤ x_1) K
x : G
hx : x ∈ closure (⋃ i, ↑(K i))
⊢ ∀ (x : G), (∃ i, x ∈ K i) → ∃ i, x⁻¹ ∈ K i

Next tactic:
rintro _ ⟨i, hi⟩
@[to_additive]
theorem mem_iSup_of_directed {ι} [hι : Nonempty ι] {K : ι → Subgroup G} (hK : Directed (· ≤ ·) K)
    {x : G} : x ∈ (iSup K : Subgroup G) ↔ ∃ i, x ∈ K i := by
  refine ⟨?_, fun ⟨i, hi⟩ ↦ le_iSup K i hi⟩
  suffices x ∈ closure (⋃ i, (K i : Set G)) → ∃ i, x ∈ K i by
    simpa only [closure_iUnion, closure_eq (K _)] using this
  refine fun hx ↦ closure_induction hx (fun _ ↦ mem_iUnion.1) ?_ ?_ ?_
  · exact hι.elim fun i ↦ ⟨i, (K i).one_mem⟩
  · rintro x y ⟨i, hi⟩ ⟨j, hj⟩
    rcases hK i j with ⟨k, hki, hkj⟩
    exact ⟨k, mul_mem (hki hi) (hkj hj)⟩
  · rintro _ ⟨i, hi⟩
    

Proof state:
case refine_3.intro
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
hι : Nonempty ι
K : ι → Subgroup G
hK : Directed (fun x x_1 => x ≤ x_1) K
x : G
hx : x ∈ closure (⋃ i, ↑(K i))
x✝ : G
i : ι
hi : x✝ ∈ K i
⊢ ∃ i, x✝⁻¹ ∈ K i

Next tactic:
exact ⟨i, inv_mem hi⟩
@[to_additive]
theorem coe_iSup_of_directed {ι} [Nonempty ι] {S : ι → Subgroup G} (hS : Directed (· ≤ ·) S) :
    ((⨆ i, S i : Subgroup G) : Set G) = ⋃ i, S i :=
  Set.ext 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 : Set G
ι : Sort u_5
inst✝ : Nonempty ι
S : ι → Subgroup G
hS : Directed (fun x x_1 => x ≤ x_1) S
x : G
⊢ x ∈ ↑(⨆ i, S i) ↔ x ∈ ⋃ i, ↑(S i)

Next tactic:
simp [mem_iSup_of_directed hS]
@[to_additive]
theorem mem_sSup_of_directedOn {K : Set (Subgroup G)} (Kne : K.Nonempty) (hK : DirectedOn (· ≤ ·) K)
    {x : G} : x ∈ sSup K ↔ ∃ s ∈ K, x ∈ 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
k : Set G
K : Set (Subgroup G)
Kne : Set.Nonempty K
hK : DirectedOn (fun x x_1 => x ≤ x_1) K
x : G
⊢ x ∈ sSup K ↔ ∃ s ∈ K, x ∈ s

Next tactic:
haveI : Nonempty K := Kne.to_subtype
@[to_additive]
theorem mem_sSup_of_directedOn {K : Set (Subgroup G)} (Kne : K.Nonempty) (hK : DirectedOn (· ≤ ·) K)
    {x : G} : x ∈ sSup K ↔ ∃ s ∈ K, x ∈ s := by
  haveI : Nonempty K := Kne.to_subtype
  

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
K : Set (Subgroup G)
Kne : Set.Nonempty K
hK : DirectedOn (fun x x_1 => x ≤ x_1) K
x : G
this : Nonempty ↑K
⊢ x ∈ sSup K ↔ ∃ s ∈ K, x ∈ s

Next tactic:
simp only [sSup_eq_iSup', mem_iSup_of_directed hK.directed_val, SetCoe.exists, Subtype.coe_mk,
    exists_prop]
/-- The preimage of a subgroup along a monoid homomorphism is a subgroup. -/
@[to_additive
      "The preimage of an `AddSubgroup` along an `AddMonoid` homomorphism
      is an `AddSubgroup`."]
def comap {N : Type*} [Group N] (f : G →* N) (H : Subgroup N) : Subgroup G :=
  { H.toSubmonoid.comap f with
    carrier := f ⁻¹' H
    inv_mem' := fun {a} ha => show f a⁻¹ ∈ 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 : Set G
N✝ : Type u_5
inst✝² : Group N✝
P : Type u_6
inst✝¹ : Group P
N : Type u_7
inst✝ : Group N
f : G →* N
H : Subgroup N
src✝ : Submonoid G := Submonoid.comap f H.toSubmonoid
a : G
ha :
  a ∈
    {
          toSubsemigroup :=
            { carrier := ⇑f ⁻¹' ↑H,
              mul_mem' := (_ : ∀ {a b : G}, a ∈ src✝.carrier → b ∈ src✝.carrier → a * b ∈ src✝.carrier) },
          one_mem' := (_ : 1 ∈ src✝.carrier) }.toSubsemigroup.carrier
⊢ f a⁻¹ ∈ H

Next tactic:
rw [f.map_inv]
/-- The preimage of a subgroup along a monoid homomorphism is a subgroup. -/
@[to_additive
      "The preimage of an `AddSubgroup` along an `AddMonoid` homomorphism
      is an `AddSubgroup`."]
def comap {N : Type*} [Group N] (f : G →* N) (H : Subgroup N) : Subgroup G :=
  { H.toSubmonoid.comap f with
    carrier := f ⁻¹' H
    inv_mem' := fun {a} ha => show f a⁻¹ ∈ H by rw [f.map_inv]; 

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
N✝ : Type u_5
inst✝² : Group N✝
P : Type u_6
inst✝¹ : Group P
N : Type u_7
inst✝ : Group N
f : G →* N
H : Subgroup N
src✝ : Submonoid G := Submonoid.comap f H.toSubmonoid
a : G
ha :
  a ∈
    {
          toSubsemigroup :=
            { carrier := ⇑f ⁻¹' ↑H,
              mul_mem' := (_ : ∀ {a b : G}, a ∈ src✝.carrier → b ∈ src✝.carrier → a * b ∈ src✝.carrier) },
          one_mem' := (_ : 1 ∈ src✝.carrier) }.toSubsemigroup.carrier
⊢ (f a)⁻¹ ∈ H

Next tactic:
exact H.inv_mem ha
@[to_additive (attr := simp)]
theorem comap_id (K : Subgroup N) : K.comap (MonoidHom.id _) = K := 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
N : Type u_5
inst✝¹ : Group N
P : Type u_6
inst✝ : Group P
K : Subgroup N
⊢ comap (MonoidHom.id N) K = K

Next tactic:
ext
@[to_additive (attr := simp)]
theorem comap_id (K : Subgroup N) : K.comap (MonoidHom.id _) = K := by
  ext
  

Proof state:
case h
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
N : Type u_5
inst✝¹ : Group N
P : Type u_6
inst✝ : Group P
K : Subgroup N
x✝ : N
⊢ x✝ ∈ comap (MonoidHom.id N) K ↔ x✝ ∈ K

Next tactic:
rfl
/-- The image of a subgroup along a monoid homomorphism is a subgroup. -/
@[to_additive
      "The image of an `AddSubgroup` along an `AddMonoid` homomorphism
      is an `AddSubgroup`."]
def map (f : G →* N) (H : Subgroup G) : Subgroup N :=
  { H.toSubmonoid.map f with
    carrier := f '' H
    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
k : Set G
N : Type u_5
inst✝¹ : Group N
P : Type u_6
inst✝ : Group P
f : G →* N
H : Subgroup G
src✝ : Submonoid N := Submonoid.map f H.toSubmonoid
⊢ ∀ {x : N},
    x ∈
        {
              toSubsemigroup :=
                { carrier := ⇑f '' ↑H,
                  mul_mem' := (_ : ∀ {a b : N}, a ∈ src✝.carrier → b ∈ src✝.carrier → a * b ∈ src✝.carrier) },
              one_mem' := (_ : 1 ∈ src✝.carrier) }.toSubsemigroup.carrier →
      x⁻¹ ∈
        {
              toSubsemigroup :=
                { carrier := ⇑f '' ↑H,
                  mul_mem' := (_ : ∀ {a b : N}, a ∈ src✝.carrier → b ∈ src✝.carrier → a * b ∈ src✝.carrier) },
              one_mem' := (_ : 1 ∈ src✝.carrier) }.toSubsemigroup.carrier

Next tactic:
rintro _ ⟨x, hx, rfl⟩
/-- The image of a subgroup along a monoid homomorphism is a subgroup. -/
@[to_additive
      "The image of an `AddSubgroup` along an `AddMonoid` homomorphism
      is an `AddSubgroup`."]
def map (f : G →* N) (H : Subgroup G) : Subgroup N :=
  { H.toSubmonoid.map f with
    carrier := f '' H
    inv_mem' := by
      rintro _ ⟨x, hx, rfl⟩
      

Proof state:
case intro.intro
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
N : Type u_5
inst✝¹ : Group N
P : Type u_6
inst✝ : Group P
f : G →* N
H : Subgroup G
src✝ : Submonoid N := Submonoid.map f H.toSubmonoid
x : G
hx : x ∈ ↑H
⊢ (f x)⁻¹ ∈
    {
          toSubsemigroup :=
            { carrier := ⇑f '' ↑H,
              mul_mem' := (_ : ∀ {a b : N}, a ∈ src✝.carrier → b ∈ src✝.carrier → a * b ∈ src✝.carrier) },
          one_mem' := (_ : 1 ∈ src✝.carrier) }.toSubsemigroup.carrier

Next tactic:
exact ⟨x⁻¹, H.inv_mem hx, f.map_inv x⟩
@[to_additive (attr := simp)]
theorem mem_map {f : G →* N} {K : Subgroup G} {y : N} : y ∈ K.map f ↔ ∃ x ∈ K, f 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 : Set G
N : Type u_5
inst✝¹ : Group N
P : Type u_6
inst✝ : Group P
f : G →* N
K : Subgroup G
y : N
⊢ y ∈ map f K ↔ ∃ x ∈ K, f x = y

Next tactic:
erw [mem_image_iff_bex]
@[to_additive (attr := simp)]
theorem mem_map {f : G →* N} {K : Subgroup G} {y : N} : y ∈ K.map f ↔ ∃ x ∈ K, f x = y := by
  erw [mem_image_iff_bex]; 

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
N : Type u_5
inst✝¹ : Group N
P : Type u_6
inst✝ : Group P
f : G →* N
K : Subgroup G
y : N
⊢ (∃ x, ∃ (_ : x ∈ ↑K), f x = y) ↔ ∃ x ∈ K, f x = y

Next tactic:
simp
@[to_additive (attr := simp)]
theorem map_one_eq_bot : K.map (1 : G →* N) = ⊥ :=
  eq_bot_iff.mpr <| 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
N : Type u_5
inst✝¹ : Group N
P : Type u_6
inst✝ : Group P
⊢ map 1 K ≤ ⊥

Next tactic:
rintro x ⟨y, _, rfl⟩