l3lab/ntp-mathlib huggingface dataset:
@[to_additive]
theorem trivial_ker_iff_eq_one {f : G → H} (hf : IsGroupHom f) :
    ker f = trivial G ↔ ∀ x, f x = 1 → x = 1 := by
  rw [Set.ext_iff]; simp [ker];
    

Proof state:
G : Type u_1
H : Type u_2
A : Type u_3
a a₁ a₂ b c : G
inst✝¹ : Group G
inst✝ : Group H
f : G → H
hf : IsGroupHom f
⊢ (∀ (x : G), f x = 1 ↔ x = 1) ↔ ∀ (x : G), f x = 1 → x = 1

Next tactic:
exact ⟨fun h x hx => (h x).1 hx, fun h x => ⟨h x, fun hx => by rw [hx, hf.map_one]⟩⟩
@[to_additive]
theorem trivial_ker_iff_eq_one {f : G → H} (hf : IsGroupHom f) :
    ker f = trivial G ↔ ∀ x, f x = 1 → x = 1 := by
  rw [Set.ext_iff]; simp [ker];
    exact ⟨fun h x hx => (h x).1 hx, fun h x => ⟨h x, fun hx => by 

Proof state:
G : Type u_1
H : Type u_2
A : Type u_3
a a₁ a₂ b c : G
inst✝¹ : Group G
inst✝ : Group H
f : G → H
hf : IsGroupHom f
h : ∀ (x : G), f x = 1 → x = 1
x : G
hx : x = 1
⊢ f x = 1

Next tactic:
rw [hx, hf.map_one]
@[to_additive]
theorem closure_subset {s t : Set G} (ht : IsSubgroup t) (h : s ⊆ t) : closure s ⊆ t := fun a ha =>
  by 

Proof state:
G : Type u_1
H : Type u_2
A : Type u_3
a✝ a₁ a₂ b c : G
inst✝ : Group G
s✝ s t : Set G
ht : IsSubgroup t
h : s ⊆ t
a : G
ha : a ∈ closure s
⊢ a ∈ t

Next tactic:
induction ha
@[to_additive]
theorem closure_subset {s t : Set G} (ht : IsSubgroup t) (h : s ⊆ t) : closure s ⊆ t := fun a ha =>
  by induction ha <;> 

Proof state:
case basic
G : Type u_1
H : Type u_2
A : Type u_3
a✝² a₁ a₂ b c : G
inst✝ : Group G
s✝ s t : Set G
ht : IsSubgroup t
h : s ⊆ t
a a✝¹ : G
a✝ : a✝¹ ∈ s
⊢ a✝¹ ∈ t

Next tactic:
simp [h _, *, ht.one_mem, ht.mul_mem, IsSubgroup.inv_mem_iff]
@[to_additive]
theorem closure_subset {s t : Set G} (ht : IsSubgroup t) (h : s ⊆ t) : closure s ⊆ t := fun a ha =>
  by induction ha <;> 

Proof state:
case one
G : Type u_1
H : Type u_2
A : Type u_3
a✝ a₁ a₂ b c : G
inst✝ : Group G
s✝ s t : Set G
ht : IsSubgroup t
h : s ⊆ t
a : G
⊢ 1 ∈ t

Next tactic:
simp [h _, *, ht.one_mem, ht.mul_mem, IsSubgroup.inv_mem_iff]
@[to_additive]
theorem closure_subset {s t : Set G} (ht : IsSubgroup t) (h : s ⊆ t) : closure s ⊆ t := fun a ha =>
  by induction ha <;> 

Proof state:
case inv
G : Type u_1
H : Type u_2
A : Type u_3
a✝² a₁ a₂ b c : G
inst✝ : Group G
s✝ s t : Set G
ht : IsSubgroup t
h : s ⊆ t
a a✝¹ : G
a✝ : InClosure s a✝¹
a_ih✝ : a✝¹ ∈ t
⊢ a✝¹⁻¹ ∈ t

Next tactic:
simp [h _, *, ht.one_mem, ht.mul_mem, IsSubgroup.inv_mem_iff]
@[to_additive]
theorem closure_subset {s t : Set G} (ht : IsSubgroup t) (h : s ⊆ t) : closure s ⊆ t := fun a ha =>
  by induction ha <;> 

Proof state:
case mul
G : Type u_1
H : Type u_2
A : Type u_3
a✝³ a₁ a₂ b c : G
inst✝ : Group G
s✝ s t : Set G
ht : IsSubgroup t
h : s ⊆ t
a a✝² b✝ : G
a✝¹ : InClosure s a✝²
a✝ : InClosure s b✝
a_ih✝¹ : a✝² ∈ t
a_ih✝ : b✝ ∈ t
⊢ a✝² * b✝ ∈ t

Next tactic:
simp [h _, *, ht.one_mem, ht.mul_mem, IsSubgroup.inv_mem_iff]
@[to_additive]
theorem exists_list_of_mem_closure {s : Set G} {a : G} (h : a ∈ closure s) :
    ∃ l : List G, (∀ x ∈ l, x ∈ s ∨ x⁻¹ ∈ s) ∧ l.prod = a :=
  InClosure.recOn h (fun {x} hxs => ⟨[x], List.forall_mem_singleton.2 <| Or.inl hxs, one_mul _⟩)
    ⟨[], List.forall_mem_nil _, rfl⟩
    (fun {x} _ ⟨L, HL1, HL2⟩ =>
      ⟨L.reverse.map Inv.inv, fun x hx =>
        let ⟨y, hy1, hy2⟩ := List.exists_of_mem_map hx
        hy2 ▸ Or.imp id (by 

Proof state:
G : Type u_1
H : Type u_2
A : Type u_3
a✝ a₁ a₂ b c : G
inst✝ : Group G
s✝ s : Set G
a : G
h : a ∈ closure s
x✝² : G
x✝¹ : InClosure s x✝²
x✝ : ∃ l, (∀ x ∈ l, x ∈ s ∨ x⁻¹ ∈ s) ∧ List.prod l = x✝²
L : List G
HL1 : ∀ x ∈ L, x ∈ s ∨ x⁻¹ ∈ s
HL2 : List.prod L = x✝²
x : G
hx : x ∈ List.map Inv.inv (List.reverse L)
y : G
hy1 : y ∈ List.reverse L
hy2 : y⁻¹ = x
⊢ y ∈ s → y⁻¹⁻¹ ∈ s

Next tactic:
rw [inv_inv]
@[to_additive]
theorem exists_list_of_mem_closure {s : Set G} {a : G} (h : a ∈ closure s) :
    ∃ l : List G, (∀ x ∈ l, x ∈ s ∨ x⁻¹ ∈ s) ∧ l.prod = a :=
  InClosure.recOn h (fun {x} hxs => ⟨[x], List.forall_mem_singleton.2 <| Or.inl hxs, one_mul _⟩)
    ⟨[], List.forall_mem_nil _, rfl⟩
    (fun {x} _ ⟨L, HL1, HL2⟩ =>
      ⟨L.reverse.map Inv.inv, fun x hx =>
        let ⟨y, hy1, hy2⟩ := List.exists_of_mem_map hx
        hy2 ▸ Or.imp id (by rw [inv_inv]; 

Proof state:
G : Type u_1
H : Type u_2
A : Type u_3
a✝ a₁ a₂ b c : G
inst✝ : Group G
s✝ s : Set G
a : G
h : a ∈ closure s
x✝² : G
x✝¹ : InClosure s x✝²
x✝ : ∃ l, (∀ x ∈ l, x ∈ s ∨ x⁻¹ ∈ s) ∧ List.prod l = x✝²
L : List G
HL1 : ∀ x ∈ L, x ∈ s ∨ x⁻¹ ∈ s
HL2 : List.prod L = x✝²
x : G
hx : x ∈ List.map Inv.inv (List.reverse L)
y : G
hy1 : y ∈ List.reverse L
hy2 : y⁻¹ = x
⊢ y ∈ s → y ∈ s

Next tactic:
exact id
@[to_additive]
theorem exists_list_of_mem_closure {s : Set G} {a : G} (h : a ∈ closure s) :
    ∃ l : List G, (∀ x ∈ l, x ∈ s ∨ x⁻¹ ∈ s) ∧ l.prod = a :=
  InClosure.recOn h (fun {x} hxs => ⟨[x], List.forall_mem_singleton.2 <| Or.inl hxs, one_mul _⟩)
    ⟨[], List.forall_mem_nil _, rfl⟩
    (fun {x} _ ⟨L, HL1, HL2⟩ =>
      ⟨L.reverse.map Inv.inv, fun x hx =>
        let ⟨y, hy1, hy2⟩ := List.exists_of_mem_map hx
        hy2 ▸ Or.imp id (by rw [inv_inv]; exact id) (HL1 _ <| List.mem_reverse.1 hy1).symm,
        HL2 ▸
          List.recOn L inv_one.symm fun hd tl ih => by
            

Proof state:
G : Type u_1
H : Type u_2
A : Type u_3
a✝ a₁ a₂ b c : G
inst✝ : Group G
s✝ s : Set G
a : G
h : a ∈ closure s
x : G
x✝¹ : InClosure s x
x✝ : ∃ l, (∀ x ∈ l, x ∈ s ∨ x⁻¹ ∈ s) ∧ List.prod l = x
L : List G
HL1 : ∀ x ∈ L, x ∈ s ∨ x⁻¹ ∈ s
HL2 : List.prod L = x
hd : G
tl : List G
ih : List.prod (List.map Inv.inv (List.reverse tl)) = (List.prod tl)⁻¹
⊢ List.prod (List.map Inv.inv (List.reverse (hd :: tl))) = (List.prod (hd :: tl))⁻¹

Next tactic:
rw [List.reverse_cons, List.map_append, List.prod_append, ih, List.map_singleton,
              List.prod_cons, List.prod_nil, mul_one, List.prod_cons, mul_inv_rev]
@[to_additive]
theorem exists_list_of_mem_closure {s : Set G} {a : G} (h : a ∈ closure s) :
    ∃ l : List G, (∀ x ∈ l, x ∈ s ∨ x⁻¹ ∈ s) ∧ l.prod = a :=
  InClosure.recOn h (fun {x} hxs => ⟨[x], List.forall_mem_singleton.2 <| Or.inl hxs, one_mul _⟩)
    ⟨[], List.forall_mem_nil _, rfl⟩
    (fun {x} _ ⟨L, HL1, HL2⟩ =>
      ⟨L.reverse.map Inv.inv, fun x hx =>
        let ⟨y, hy1, hy2⟩ := List.exists_of_mem_map hx
        hy2 ▸ Or.imp id (by rw [inv_inv]; exact id) (HL1 _ <| List.mem_reverse.1 hy1).symm,
        HL2 ▸
          List.recOn L inv_one.symm fun hd tl ih => by
            rw [List.reverse_cons, List.map_append, List.prod_append, ih, List.map_singleton,
              List.prod_cons, List.prod_nil, mul_one, List.prod_cons, mul_inv_rev]⟩)
    fun {x y} _ _ ⟨L1, HL1, HL2⟩ ⟨L2, HL3, HL4⟩ =>
    ⟨L1 ++ L2, List.forall_mem_append.2 ⟨HL1, HL3⟩, by 

Proof state:
G : Type u_1
H : Type u_2
A : Type u_3
a✝ a₁ a₂ b c : G
inst✝ : Group G
s✝ s : Set G
a : G
h : a ∈ closure s
x y : G
x✝³ : InClosure s x
x✝² : InClosure s y
x✝¹ : ∃ l, (∀ x ∈ l, x ∈ s ∨ x⁻¹ ∈ s) ∧ List.prod l = x
x✝ : ∃ l, (∀ x ∈ l, x ∈ s ∨ x⁻¹ ∈ s) ∧ List.prod l = y
L1 : List G
HL1 : ∀ x ∈ L1, x ∈ s ∨ x⁻¹ ∈ s
HL2 : List.prod L1 = x
L2 : List G
HL3 : ∀ x ∈ L2, x ∈ s ∨ x⁻¹ ∈ s
HL4 : List.prod L2 = y
⊢ List.prod (L1 ++ L2) = x * y

Next tactic:
rw [List.prod_append, HL2, HL4]
@[to_additive]
theorem image_closure [Group H] {f : G → H} (hf : IsGroupHom f) (s : Set G) :
    f '' closure s = closure (f '' s) :=
  le_antisymm
    (by
      

Proof state:
G : Type u_1
H : Type u_2
A : Type u_3
a a₁ a₂ b c : G
inst✝¹ : Group G
s✝ : Set G
inst✝ : Group H
f : G → H
hf : IsGroupHom f
s : Set G
⊢ f '' closure s ≤ closure (f '' s)

Next tactic:
rintro _ ⟨x, hx, rfl⟩
@[to_additive]
theorem image_closure [Group H] {f : G → H} (hf : IsGroupHom f) (s : Set G) :
    f '' closure s = closure (f '' s) :=
  le_antisymm
    (by
      rintro _ ⟨x, hx, rfl⟩
      

Proof state:
case intro.intro
G : Type u_1
H : Type u_2
A : Type u_3
a a₁ a₂ b c : G
inst✝¹ : Group G
s✝ : Set G
inst✝ : Group H
f : G → H
hf : IsGroupHom f
s : Set G
x : G
hx : x ∈ closure s
⊢ f x ∈ closure (f '' s)

Next tactic:
exact InClosure.recOn hx
        (by intros _ ha; exact subset_closure (mem_image_of_mem f ha))
        (by
          rw [hf.map_one]
          apply IsSubmonoid.one_mem (closure.isSubgroup _).toIsSubmonoid)
        (by
          intros _ _
          rw [hf.map_inv]
          apply IsSubgroup.inv_mem (closure.isSubgroup _))
        (by
          intros _ _ _ _ ha hb
          rw [hf.map_mul]
          exact (closure.isSubgroup (f '' s)).toIsSubmonoid.mul_mem ha hb)
@[to_additive]
theorem image_closure [Group H] {f : G → H} (hf : IsGroupHom f) (s : Set G) :
    f '' closure s = closure (f '' s) :=
  le_antisymm
    (by
      rintro _ ⟨x, hx, rfl⟩
      exact InClosure.recOn hx
        (by 

Proof state:
G : Type u_1
H : Type u_2
A : Type u_3
a a₁ a₂ b c : G
inst✝¹ : Group G
s✝ : Set G
inst✝ : Group H
f : G → H
hf : IsGroupHom f
s : Set G
x : G
hx : x ∈ closure s
⊢ ∀ {a : G}, a ∈ s → f a ∈ closure (f '' s)

Next tactic:
intros _ ha
@[to_additive]
theorem image_closure [Group H] {f : G → H} (hf : IsGroupHom f) (s : Set G) :
    f '' closure s = closure (f '' s) :=
  le_antisymm
    (by
      rintro _ ⟨x, hx, rfl⟩
      exact InClosure.recOn hx
        (by intros _ ha; 

Proof state:
G : Type u_1
H : Type u_2
A : Type u_3
a a₁ a₂ b c : G
inst✝¹ : Group G
s✝ : Set G
inst✝ : Group H
f : G → H
hf : IsGroupHom f
s : Set G
x : G
hx : x ∈ closure s
a✝ : G
ha : a✝ ∈ s
⊢ f a✝ ∈ closure (f '' s)

Next tactic:
exact subset_closure (mem_image_of_mem f ha)
@[to_additive]
theorem image_closure [Group H] {f : G → H} (hf : IsGroupHom f) (s : Set G) :
    f '' closure s = closure (f '' s) :=
  le_antisymm
    (by
      rintro _ ⟨x, hx, rfl⟩
      exact InClosure.recOn hx
        (by intros _ ha; exact subset_closure (mem_image_of_mem f ha))
        (by
          

Proof state:
G : Type u_1
H : Type u_2
A : Type u_3
a a₁ a₂ b c : G
inst✝¹ : Group G
s✝ : Set G
inst✝ : Group H
f : G → H
hf : IsGroupHom f
s : Set G
x : G
hx : x ∈ closure s
⊢ f 1 ∈ closure (f '' s)

Next tactic:
rw [hf.map_one]
@[to_additive]
theorem image_closure [Group H] {f : G → H} (hf : IsGroupHom f) (s : Set G) :
    f '' closure s = closure (f '' s) :=
  le_antisymm
    (by
      rintro _ ⟨x, hx, rfl⟩
      exact InClosure.recOn hx
        (by intros _ ha; exact subset_closure (mem_image_of_mem f ha))
        (by
          rw [hf.map_one]
          

Proof state:
G : Type u_1
H : Type u_2
A : Type u_3
a a₁ a₂ b c : G
inst✝¹ : Group G
s✝ : Set G
inst✝ : Group H
f : G → H
hf : IsGroupHom f
s : Set G
x : G
hx : x ∈ closure s
⊢ 1 ∈ closure (f '' s)

Next tactic:
apply IsSubmonoid.one_mem (closure.isSubgroup _).toIsSubmonoid
@[to_additive]
theorem image_closure [Group H] {f : G → H} (hf : IsGroupHom f) (s : Set G) :
    f '' closure s = closure (f '' s) :=
  le_antisymm
    (by
      rintro _ ⟨x, hx, rfl⟩
      exact InClosure.recOn hx
        (by intros _ ha; exact subset_closure (mem_image_of_mem f ha))
        (by
          rw [hf.map_one]
          apply IsSubmonoid.one_mem (closure.isSubgroup _).toIsSubmonoid)
        (by
          

Proof state:
G : Type u_1
H : Type u_2
A : Type u_3
a a₁ a₂ b c : G
inst✝¹ : Group G
s✝ : Set G
inst✝ : Group H
f : G → H
hf : IsGroupHom f
s : Set G
x : G
hx : x ∈ closure s
⊢ ∀ {a : G}, InClosure s a → f a ∈ closure (f '' s) → f a⁻¹ ∈ closure (f '' s)

Next tactic:
intros _ _
@[to_additive]
theorem image_closure [Group H] {f : G → H} (hf : IsGroupHom f) (s : Set G) :
    f '' closure s = closure (f '' s) :=
  le_antisymm
    (by
      rintro _ ⟨x, hx, rfl⟩
      exact InClosure.recOn hx
        (by intros _ ha; exact subset_closure (mem_image_of_mem f ha))
        (by
          rw [hf.map_one]
          apply IsSubmonoid.one_mem (closure.isSubgroup _).toIsSubmonoid)
        (by
          intros _ _
          

Proof state:
G : Type u_1
H : Type u_2
A : Type u_3
a a₁ a₂ b c : G
inst✝¹ : Group G
s✝ : Set G
inst✝ : Group H
f : G → H
hf : IsGroupHom f
s : Set G
x : G
hx : x ∈ closure s
a✝¹ : G
a✝ : InClosure s a✝¹
⊢ f a✝¹ ∈ closure (f '' s) → f a✝¹⁻¹ ∈ closure (f '' s)

Next tactic:
rw [hf.map_inv]
@[to_additive]
theorem image_closure [Group H] {f : G → H} (hf : IsGroupHom f) (s : Set G) :
    f '' closure s = closure (f '' s) :=
  le_antisymm
    (by
      rintro _ ⟨x, hx, rfl⟩
      exact InClosure.recOn hx
        (by intros _ ha; exact subset_closure (mem_image_of_mem f ha))
        (by
          rw [hf.map_one]
          apply IsSubmonoid.one_mem (closure.isSubgroup _).toIsSubmonoid)
        (by
          intros _ _
          rw [hf.map_inv]
          

Proof state:
G : Type u_1
H : Type u_2
A : Type u_3
a a₁ a₂ b c : G
inst✝¹ : Group G
s✝ : Set G
inst✝ : Group H
f : G → H
hf : IsGroupHom f
s : Set G
x : G
hx : x ∈ closure s
a✝¹ : G
a✝ : InClosure s a✝¹
⊢ f a✝¹ ∈ closure (f '' s) → (f a✝¹)⁻¹ ∈ closure (f '' s)

Next tactic:
apply IsSubgroup.inv_mem (closure.isSubgroup _)
@[to_additive]
theorem image_closure [Group H] {f : G → H} (hf : IsGroupHom f) (s : Set G) :
    f '' closure s = closure (f '' s) :=
  le_antisymm
    (by
      rintro _ ⟨x, hx, rfl⟩
      exact InClosure.recOn hx
        (by intros _ ha; exact subset_closure (mem_image_of_mem f ha))
        (by
          rw [hf.map_one]
          apply IsSubmonoid.one_mem (closure.isSubgroup _).toIsSubmonoid)
        (by
          intros _ _
          rw [hf.map_inv]
          apply IsSubgroup.inv_mem (closure.isSubgroup _))
        (by
          

Proof state:
G : Type u_1
H : Type u_2
A : Type u_3
a a₁ a₂ b c : G
inst✝¹ : Group G
s✝ : Set G
inst✝ : Group H
f : G → H
hf : IsGroupHom f
s : Set G
x : G
hx : x ∈ closure s
⊢ ∀ {a b : G},
    InClosure s a → InClosure s b → f a ∈ closure (f '' s) → f b ∈ closure (f '' s) → f (a * b) ∈ closure (f '' s)

Next tactic:
intros _ _ _ _ ha hb
@[to_additive]
theorem image_closure [Group H] {f : G → H} (hf : IsGroupHom f) (s : Set G) :
    f '' closure s = closure (f '' s) :=
  le_antisymm
    (by
      rintro _ ⟨x, hx, rfl⟩
      exact InClosure.recOn hx
        (by intros _ ha; exact subset_closure (mem_image_of_mem f ha))
        (by
          rw [hf.map_one]
          apply IsSubmonoid.one_mem (closure.isSubgroup _).toIsSubmonoid)
        (by
          intros _ _
          rw [hf.map_inv]
          apply IsSubgroup.inv_mem (closure.isSubgroup _))
        (by
          intros _ _ _ _ ha hb
          

Proof state:
G : Type u_1
H : Type u_2
A : Type u_3
a a₁ a₂ b c : G
inst✝¹ : Group G
s✝ : Set G
inst✝ : Group H
f : G → H
hf : IsGroupHom f
s : Set G
x : G
hx : x ∈ closure s
a✝² b✝ : G
a✝¹ : InClosure s a✝²
a✝ : InClosure s b✝
ha : f a✝² ∈ closure (f '' s)
hb : f b✝ ∈ closure (f '' s)
⊢ f (a✝² * b✝) ∈ closure (f '' s)

Next tactic:
rw [hf.map_mul]
@[to_additive]
theorem image_closure [Group H] {f : G → H} (hf : IsGroupHom f) (s : Set G) :
    f '' closure s = closure (f '' s) :=
  le_antisymm
    (by
      rintro _ ⟨x, hx, rfl⟩
      exact InClosure.recOn hx
        (by intros _ ha; exact subset_closure (mem_image_of_mem f ha))
        (by
          rw [hf.map_one]
          apply IsSubmonoid.one_mem (closure.isSubgroup _).toIsSubmonoid)
        (by
          intros _ _
          rw [hf.map_inv]
          apply IsSubgroup.inv_mem (closure.isSubgroup _))
        (by
          intros _ _ _ _ ha hb
          rw [hf.map_mul]
          

Proof state:
G : Type u_1
H : Type u_2
A : Type u_3
a a₁ a₂ b c : G
inst✝¹ : Group G
s✝ : Set G
inst✝ : Group H
f : G → H
hf : IsGroupHom f
s : Set G
x : G
hx : x ∈ closure s
a✝² b✝ : G
a✝¹ : InClosure s a✝²
a✝ : InClosure s b✝
ha : f a✝² ∈ closure (f '' s)
hb : f b✝ ∈ closure (f '' s)
⊢ f a✝² * f b✝ ∈ closure (f '' s)

Next tactic:
exact (closure.isSubgroup (f '' s)).toIsSubmonoid.mul_mem ha hb
@[to_additive]
theorem mem_closure_union_iff {G : Type*} [CommGroup G] {s t : Set G} {x : G} :
    x ∈ closure (s ∪ t) ↔ ∃ y ∈ closure s, ∃ z ∈ closure t, y * z = x := by
  

Proof state:
G✝ : Type u_1
H : Type u_2
A : Type u_3
a a₁ a₂ b c : G✝
inst✝¹ : Group G✝
s✝ : Set G✝
G : Type u_4
inst✝ : CommGroup G
s t : Set G
x : G
⊢ x ∈ closure (s ∪ t) ↔ ∃ y ∈ closure s, ∃ z ∈ closure t, y * z = x

Next tactic:
simp only [closure_eq_mclosure, Monoid.mem_closure_union_iff, exists_prop, preimage_union]
@[to_additive]
theorem mem_closure_union_iff {G : Type*} [CommGroup G] {s t : Set G} {x : G} :
    x ∈ closure (s ∪ t) ↔ ∃ y ∈ closure s, ∃ z ∈ closure t, y * z = x := by
  simp only [closure_eq_mclosure, Monoid.mem_closure_union_iff, exists_prop, preimage_union];
  

Proof state:
G✝ : Type u_1
H : Type u_2
A : Type u_3
a a₁ a₂ b c : G✝
inst✝¹ : Group G✝
s✝ : Set G✝
G : Type u_4
inst✝ : CommGroup G
s t : Set G
x : G
⊢ (∃ y,
      (∃ y_1 ∈ Monoid.Closure s, ∃ z ∈ Monoid.Closure t, y_1 * z = y) ∧
        ∃ z, (∃ y ∈ Monoid.Closure (Inv.inv ⁻¹' s), ∃ z_1 ∈ Monoid.Closure (Inv.inv ⁻¹' t), y * z_1 = z) ∧ y * z = x) ↔
    ∃ y,
      (∃ y_1 ∈ Monoid.Closure s, ∃ z ∈ Monoid.Closure (Inv.inv ⁻¹' s), y_1 * z = y) ∧
        ∃ z, (∃ y ∈ Monoid.Closure t, ∃ z_1 ∈ Monoid.Closure (Inv.inv ⁻¹' t), y * z_1 = z) ∧ y * z = x

Next tactic:
constructor
@[to_additive]
theorem mem_closure_union_iff {G : Type*} [CommGroup G] {s t : Set G} {x : G} :
    x ∈ closure (s ∪ t) ↔ ∃ y ∈ closure s, ∃ z ∈ closure t, y * z = x := by
  simp only [closure_eq_mclosure, Monoid.mem_closure_union_iff, exists_prop, preimage_union];
  constructor
  · 

Proof state:
case mp
G✝ : Type u_1
H : Type u_2
A : Type u_3
a a₁ a₂ b c : G✝
inst✝¹ : Group G✝
s✝ : Set G✝
G : Type u_4
inst✝ : CommGroup G
s t : Set G
x : G
⊢ (∃ y,
      (∃ y_1 ∈ Monoid.Closure s, ∃ z ∈ Monoid.Closure t, y_1 * z = y) ∧
        ∃ z, (∃ y ∈ Monoid.Closure (Inv.inv ⁻¹' s), ∃ z_1 ∈ Monoid.Closure (Inv.inv ⁻¹' t), y * z_1 = z) ∧ y * z = x) →
    ∃ y,
      (∃ y_1 ∈ Monoid.Closure s, ∃ z ∈ Monoid.Closure (Inv.inv ⁻¹' s), y_1 * z = y) ∧
        ∃ z, (∃ y ∈ Monoid.Closure t, ∃ z_1 ∈ Monoid.Closure (Inv.inv ⁻¹' t), y * z_1 = z) ∧ y * z = x

Next tactic:
rintro ⟨_, ⟨ys, hys, yt, hyt, rfl⟩, _, ⟨zs, hzs, zt, hzt, rfl⟩, rfl⟩
@[to_additive]
theorem mem_closure_union_iff {G : Type*} [CommGroup G] {s t : Set G} {x : G} :
    x ∈ closure (s ∪ t) ↔ ∃ y ∈ closure s, ∃ z ∈ closure t, y * z = x := by
  simp only [closure_eq_mclosure, Monoid.mem_closure_union_iff, exists_prop, preimage_union];
  constructor
  · rintro ⟨_, ⟨ys, hys, yt, hyt, rfl⟩, _, ⟨zs, hzs, zt, hzt, rfl⟩, rfl⟩
    

Proof state:
case mp.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro
G✝ : Type u_1
H : Type u_2
A : Type u_3
a a₁ a₂ b c : G✝
inst✝¹ : Group G✝
s✝ : Set G✝
G : Type u_4
inst✝ : CommGroup G
s t : Set G
ys : G
hys : ys ∈ Monoid.Closure s
yt : G
hyt : yt ∈ Monoid.Closure t
zs : G
hzs : zs ∈ Monoid.Closure (Inv.inv ⁻¹' s)
zt : G
hzt : zt ∈ Monoid.Closure (Inv.inv ⁻¹' t)
⊢ ∃ y,
    (∃ y_1 ∈ Monoid.Closure s, ∃ z ∈ Monoid.Closure (Inv.inv ⁻¹' s), y_1 * z = y) ∧
      ∃ z, (∃ y ∈ Monoid.Closure t, ∃ z_1 ∈ Monoid.Closure (Inv.inv ⁻¹' t), y * z_1 = z) ∧ y * z = ys * yt * (zs * zt)

Next tactic:
refine' ⟨_, ⟨_, hys, _, hzs, rfl⟩, _, ⟨_, hyt, _, hzt, rfl⟩, _⟩
@[to_additive]
theorem mem_closure_union_iff {G : Type*} [CommGroup G] {s t : Set G} {x : G} :
    x ∈ closure (s ∪ t) ↔ ∃ y ∈ closure s, ∃ z ∈ closure t, y * z = x := by
  simp only [closure_eq_mclosure, Monoid.mem_closure_union_iff, exists_prop, preimage_union];
  constructor
  · rintro ⟨_, ⟨ys, hys, yt, hyt, rfl⟩, _, ⟨zs, hzs, zt, hzt, rfl⟩, rfl⟩
    refine' ⟨_, ⟨_, hys, _, hzs, rfl⟩, _, ⟨_, hyt, _, hzt, rfl⟩, _⟩
    

Proof state:
case mp.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro
G✝ : Type u_1
H : Type u_2
A : Type u_3
a a₁ a₂ b c : G✝
inst✝¹ : Group G✝
s✝ : Set G✝
G : Type u_4
inst✝ : CommGroup G
s t : Set G
ys : G
hys : ys ∈ Monoid.Closure s
yt : G
hyt : yt ∈ Monoid.Closure t
zs : G
hzs : zs ∈ Monoid.Closure (Inv.inv ⁻¹' s)
zt : G
hzt : zt ∈ Monoid.Closure (Inv.inv ⁻¹' t)
⊢ ys * zs * (yt * zt) = ys * yt * (zs * zt)

Next tactic:
rw [mul_assoc, mul_assoc, mul_left_comm zs]
@[to_additive]
theorem mem_closure_union_iff {G : Type*} [CommGroup G] {s t : Set G} {x : G} :
    x ∈ closure (s ∪ t) ↔ ∃ y ∈ closure s, ∃ z ∈ closure t, y * z = x := by
  simp only [closure_eq_mclosure, Monoid.mem_closure_union_iff, exists_prop, preimage_union];
  constructor
  · rintro ⟨_, ⟨ys, hys, yt, hyt, rfl⟩, _, ⟨zs, hzs, zt, hzt, rfl⟩, rfl⟩
    refine' ⟨_, ⟨_, hys, _, hzs, rfl⟩, _, ⟨_, hyt, _, hzt, rfl⟩, _⟩
    rw [mul_assoc, mul_assoc, mul_left_comm zs]
  · 

Proof state:
case mpr
G✝ : Type u_1
H : Type u_2
A : Type u_3
a a₁ a₂ b c : G✝
inst✝¹ : Group G✝
s✝ : Set G✝
G : Type u_4
inst✝ : CommGroup G
s t : Set G
x : G
⊢ (∃ y,
      (∃ y_1 ∈ Monoid.Closure s, ∃ z ∈ Monoid.Closure (Inv.inv ⁻¹' s), y_1 * z = y) ∧
        ∃ z, (∃ y ∈ Monoid.Closure t, ∃ z_1 ∈ Monoid.Closure (Inv.inv ⁻¹' t), y * z_1 = z) ∧ y * z = x) →
    ∃ y,
      (∃ y_1 ∈ Monoid.Closure s, ∃ z ∈ Monoid.Closure t, y_1 * z = y) ∧
        ∃ z, (∃ y ∈ Monoid.Closure (Inv.inv ⁻¹' s), ∃ z_1 ∈ Monoid.Closure (Inv.inv ⁻¹' t), y * z_1 = z) ∧ y * z = x

Next tactic:
rintro ⟨_, ⟨ys, hys, zs, hzs, rfl⟩, _, ⟨yt, hyt, zt, hzt, rfl⟩, rfl⟩
@[to_additive]
theorem mem_closure_union_iff {G : Type*} [CommGroup G] {s t : Set G} {x : G} :
    x ∈ closure (s ∪ t) ↔ ∃ y ∈ closure s, ∃ z ∈ closure t, y * z = x := by
  simp only [closure_eq_mclosure, Monoid.mem_closure_union_iff, exists_prop, preimage_union];
  constructor
  · rintro ⟨_, ⟨ys, hys, yt, hyt, rfl⟩, _, ⟨zs, hzs, zt, hzt, rfl⟩, rfl⟩
    refine' ⟨_, ⟨_, hys, _, hzs, rfl⟩, _, ⟨_, hyt, _, hzt, rfl⟩, _⟩
    rw [mul_assoc, mul_assoc, mul_left_comm zs]
  · rintro ⟨_, ⟨ys, hys, zs, hzs, rfl⟩, _, ⟨yt, hyt, zt, hzt, rfl⟩, rfl⟩
    

Proof state:
case mpr.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro
G✝ : Type u_1
H : Type u_2
A : Type u_3
a a₁ a₂ b c : G✝
inst✝¹ : Group G✝
s✝ : Set G✝
G : Type u_4
inst✝ : CommGroup G
s t : Set G
ys : G
hys : ys ∈ Monoid.Closure s
zs : G
hzs : zs ∈ Monoid.Closure (Inv.inv ⁻¹' s)
yt : G
hyt : yt ∈ Monoid.Closure t
zt : G
hzt : zt ∈ Monoid.Closure (Inv.inv ⁻¹' t)
⊢ ∃ y,
    (∃ y_1 ∈ Monoid.Closure s, ∃ z ∈ Monoid.Closure t, y_1 * z = y) ∧
      ∃ z,
        (∃ y ∈ Monoid.Closure (Inv.inv ⁻¹' s), ∃ z_1 ∈ Monoid.Closure (Inv.inv ⁻¹' t), y * z_1 = z) ∧
          y * z = ys * zs * (yt * zt)

Next tactic:
refine' ⟨_, ⟨ys, hys, yt, hyt, rfl⟩, _, ⟨zs, hzs, zt, hzt, rfl⟩, _⟩
@[to_additive]
theorem mem_closure_union_iff {G : Type*} [CommGroup G] {s t : Set G} {x : G} :
    x ∈ closure (s ∪ t) ↔ ∃ y ∈ closure s, ∃ z ∈ closure t, y * z = x := by
  simp only [closure_eq_mclosure, Monoid.mem_closure_union_iff, exists_prop, preimage_union];
  constructor
  · rintro ⟨_, ⟨ys, hys, yt, hyt, rfl⟩, _, ⟨zs, hzs, zt, hzt, rfl⟩, rfl⟩
    refine' ⟨_, ⟨_, hys, _, hzs, rfl⟩, _, ⟨_, hyt, _, hzt, rfl⟩, _⟩
    rw [mul_assoc, mul_assoc, mul_left_comm zs]
  · rintro ⟨_, ⟨ys, hys, zs, hzs, rfl⟩, _, ⟨yt, hyt, zt, hzt, rfl⟩, rfl⟩
    refine' ⟨_, ⟨ys, hys, yt, hyt, rfl⟩, _, ⟨zs, hzs, zt, hzt, rfl⟩, _⟩
    

Proof state:
case mpr.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro
G✝ : Type u_1
H : Type u_2
A : Type u_3
a a₁ a₂ b c : G✝
inst✝¹ : Group G✝
s✝ : Set G✝
G : Type u_4
inst✝ : CommGroup G
s t : Set G
ys : G
hys : ys ∈ Monoid.Closure s
zs : G
hzs : zs ∈ Monoid.Closure (Inv.inv ⁻¹' s)
yt : G
hyt : yt ∈ Monoid.Closure t
zt : G
hzt : zt ∈ Monoid.Closure (Inv.inv ⁻¹' t)
⊢ ys * yt * (zs * zt) = ys * zs * (yt * zt)

Next tactic:
rw [mul_assoc, mul_assoc, mul_left_comm yt]
@[to_additive]
theorem trivial_eq_closure : trivial G = Group.closure ∅ :=
  Subset.antisymm (by 

Proof state:
G : Type u_1
H : Type u_2
A : Type u_3
a a₁ a₂ b c : G
inst✝ : Group G
⊢ trivial G ⊆ Group.closure ∅

Next tactic:
simp [Set.subset_def, (Group.closure.isSubgroup _).one_mem]
@[to_additive]
theorem trivial_eq_closure : trivial G = Group.closure ∅ :=
  Subset.antisymm (by simp [Set.subset_def, (Group.closure.isSubgroup _).one_mem])
    (Group.closure_subset trivial_normal.toIsSubgroup <| by 

Proof state:
G : Type u_1
H : Type u_2
A : Type u_3
a a₁ a₂ b c : G
inst✝ : Group G
⊢ ∅ ⊆ trivial G

Next tactic:
simp
theorem conjugatesOf_subset {t : Set G} (ht : IsNormalSubgroup t) {a : G} (h : a ∈ t) :
    conjugatesOf a ⊆ t := fun x hc => by
  

Proof state:
G : Type u_1
H : Type u_2
A : Type u_3
a✝ a₁ a₂ b c : G
s : Set G
inst✝ : Group G
t : Set G
ht : IsNormalSubgroup t
a : G
h : a ∈ t
x : G
hc : x ∈ conjugatesOf a
⊢ x ∈ t

Next tactic:
obtain ⟨c, w⟩ := isConj_iff.1 hc