l3lab/ntp-mathlib huggingface dataset:
@[to_additive (attr := simp)]
theorem range_one : (1 : G →* N).range = ⊥ :=
  SetLike.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
N : Type u_5
P : Type u_6
inst✝¹ : Group N
inst✝ : Group P
K : Subgroup G
x : N
⊢ x ∈ range 1 ↔ x ∈ ⊥

Next tactic:
simpa using @comm _ (· = ·) _ 1 x
@[to_additive (attr := simp)]
theorem _root_.Subgroup.subtype_range (H : Subgroup G) : H.subtype.range = 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
N : Type u_5
P : Type u_6
inst✝¹ : Group N
inst✝ : Group P
K H : Subgroup G
⊢ range (Subgroup.subtype H) = H

Next tactic:
rw [range_eq_map, ← SetLike.coe_set_eq, coe_map, Subgroup.coeSubtype]
@[to_additive (attr := simp)]
theorem _root_.Subgroup.subtype_range (H : Subgroup G) : H.subtype.range = H := by
  rw [range_eq_map, ← SetLike.coe_set_eq, coe_map, Subgroup.coeSubtype]
  

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
N : Type u_5
P : Type u_6
inst✝¹ : Group N
inst✝ : Group P
K H : Subgroup G
⊢ Subtype.val '' ↑⊤ = ↑H

Next tactic:
ext
@[to_additive (attr := simp)]
theorem _root_.Subgroup.subtype_range (H : Subgroup G) : H.subtype.range = H := by
  rw [range_eq_map, ← SetLike.coe_set_eq, coe_map, Subgroup.coeSubtype]
  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
N : Type u_5
P : Type u_6
inst✝¹ : Group N
inst✝ : Group P
K H : Subgroup G
x✝ : G
⊢ x✝ ∈ Subtype.val '' ↑⊤ ↔ x✝ ∈ ↑H

Next tactic:
simp
@[to_additive]
theorem subgroupOf_range_eq_of_le {G₁ G₂ : Type*} [Group G₁] [Group G₂] {K : Subgroup G₂}
    (f : G₁ →* G₂) (h : f.range ≤ K) :
    f.range.subgroupOf K = (f.codRestrict K fun x => h ⟨x, rfl⟩).range := 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
N : Type u_5
P : Type u_6
inst✝³ : Group N
inst✝² : Group P
K✝ : Subgroup G
G₁ : Type u_7
G₂ : Type u_8
inst✝¹ : Group G₁
inst✝ : Group G₂
K : Subgroup G₂
f : G₁ →* G₂
h : range f ≤ K
⊢ subgroupOf (range f) K = range (codRestrict f K (_ : ∀ (x : G₁), f x ∈ K))

Next tactic:
ext k
@[to_additive]
theorem subgroupOf_range_eq_of_le {G₁ G₂ : Type*} [Group G₁] [Group G₂] {K : Subgroup G₂}
    (f : G₁ →* G₂) (h : f.range ≤ K) :
    f.range.subgroupOf K = (f.codRestrict K fun x => h ⟨x, rfl⟩).range := by
  ext k
  

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
N : Type u_5
P : Type u_6
inst✝³ : Group N
inst✝² : Group P
K✝ : Subgroup G
G₁ : Type u_7
G₂ : Type u_8
inst✝¹ : Group G₁
inst✝ : Group G₂
K : Subgroup G₂
f : G₁ →* G₂
h : range f ≤ K
k : ↥K
⊢ k ∈ subgroupOf (range f) K ↔ k ∈ range (codRestrict f K (_ : ∀ (x : G₁), f x ∈ K))

Next tactic:
refine' exists_congr _
@[to_additive]
theorem subgroupOf_range_eq_of_le {G₁ G₂ : Type*} [Group G₁] [Group G₂] {K : Subgroup G₂}
    (f : G₁ →* G₂) (h : f.range ≤ K) :
    f.range.subgroupOf K = (f.codRestrict K fun x => h ⟨x, rfl⟩).range := by
  ext k
  refine' exists_congr _
  

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
N : Type u_5
P : Type u_6
inst✝³ : Group N
inst✝² : Group P
K✝ : Subgroup G
G₁ : Type u_7
G₂ : Type u_8
inst✝¹ : Group G₁
inst✝ : Group G₂
K : Subgroup G₂
f : G₁ →* G₂
h : range f ≤ K
k : ↥K
⊢ ∀ (a : G₁), f a = (Subgroup.subtype K) k ↔ (codRestrict f K (_ : ∀ (x : G₁), f x ∈ K)) a = k

Next tactic:
simp [Subtype.ext_iff]
/-- Computable alternative to `MonoidHom.ofInjective`. -/
@[to_additive "Computable alternative to `AddMonoidHom.ofInjective`."]
def ofLeftInverse {f : G →* N} {g : N →* G} (h : Function.LeftInverse g f) : G ≃* f.range :=
  { f.rangeRestrict with
    toFun := f.rangeRestrict
    invFun := g ∘ f.range.subtype
    left_inv := h
    right_inv := 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
N : Type u_5
P : Type u_6
inst✝¹ : Group N
inst✝ : Group P
K : Subgroup G
f : G →* N
g : N →* G
h : LeftInverse ⇑g ⇑f
src✝ : G →* ↥(range f) := rangeRestrict f
⊢ Function.RightInverse (⇑g ∘ ⇑(Subgroup.subtype (range f))) ⇑(rangeRestrict f)

Next tactic:
rintro ⟨x, y, rfl⟩
/-- Computable alternative to `MonoidHom.ofInjective`. -/
@[to_additive "Computable alternative to `AddMonoidHom.ofInjective`."]
def ofLeftInverse {f : G →* N} {g : N →* G} (h : Function.LeftInverse g f) : G ≃* f.range :=
  { f.rangeRestrict with
    toFun := f.rangeRestrict
    invFun := g ∘ f.range.subtype
    left_inv := h
    right_inv := by
      rintro ⟨x, y, rfl⟩
      

Proof state:
case mk.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
N : Type u_5
P : Type u_6
inst✝¹ : Group N
inst✝ : Group P
K : Subgroup G
f : G →* N
g : N →* G
h : LeftInverse ⇑g ⇑f
src✝ : G →* ↥(range f) := rangeRestrict f
y : G
⊢ (rangeRestrict f) ((⇑g ∘ ⇑(Subgroup.subtype (range f))) { val := f y, property := (_ : ∃ y_1, f y_1 = f y) }) =
    { val := f y, property := (_ : ∃ y_1, f y_1 = f y) }

Next tactic:
apply Subtype.ext
/-- Computable alternative to `MonoidHom.ofInjective`. -/
@[to_additive "Computable alternative to `AddMonoidHom.ofInjective`."]
def ofLeftInverse {f : G →* N} {g : N →* G} (h : Function.LeftInverse g f) : G ≃* f.range :=
  { f.rangeRestrict with
    toFun := f.rangeRestrict
    invFun := g ∘ f.range.subtype
    left_inv := h
    right_inv := by
      rintro ⟨x, y, rfl⟩
      apply Subtype.ext
      

Proof state:
case mk.intro.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
N : Type u_5
P : Type u_6
inst✝¹ : Group N
inst✝ : Group P
K : Subgroup G
f : G →* N
g : N →* G
h : LeftInverse ⇑g ⇑f
src✝ : G →* ↥(range f) := rangeRestrict f
y : G
⊢ ↑((rangeRestrict f) ((⇑g ∘ ⇑(Subgroup.subtype (range f))) { val := f y, property := (_ : ∃ y_1, f y_1 = f y) })) =
    ↑{ val := f y, property := (_ : ∃ y_1, f y_1 = f y) }

Next tactic:
rw [coe_rangeRestrict, Function.comp_apply, Subgroup.coeSubtype, Subtype.coe_mk, h]
/-- The range of an injective group homomorphism is isomorphic to its domain. -/
@[to_additive "The range of an injective additive group homomorphism is isomorphic to its
domain."]
noncomputable def ofInjective {f : G →* N} (hf : Function.Injective f) : G ≃* f.range :=
  MulEquiv.ofBijective (f.codRestrict f.range fun x => ⟨x, rfl⟩)
    ⟨fun x y h => hf (Subtype.ext_iff.mp 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
N : Type u_5
P : Type u_6
inst✝¹ : Group N
inst✝ : Group P
K : Subgroup G
f : G →* N
hf : Injective ⇑f
⊢ Surjective ⇑(codRestrict f (range f) (_ : ∀ (x : G), ∃ y, f y = f x))

Next tactic:
rintro ⟨x, y, rfl⟩
/-- The range of an injective group homomorphism is isomorphic to its domain. -/
@[to_additive "The range of an injective additive group homomorphism is isomorphic to its
domain."]
noncomputable def ofInjective {f : G →* N} (hf : Function.Injective f) : G ≃* f.range :=
  MulEquiv.ofBijective (f.codRestrict f.range fun x => ⟨x, rfl⟩)
    ⟨fun x y h => hf (Subtype.ext_iff.mp h), by
      rintro ⟨x, y, rfl⟩
      

Proof state:
case mk.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
N : Type u_5
P : Type u_6
inst✝¹ : Group N
inst✝ : Group P
K : Subgroup G
f : G →* N
hf : Injective ⇑f
y : G
⊢ ∃ a,
    (codRestrict f (range f) (_ : ∀ (x : G), ∃ y, f y = f x)) a = { val := f y, property := (_ : ∃ y_1, f y_1 = f y) }

Next tactic:
exact ⟨y, rfl⟩
/-- The multiplicative kernel of a monoid homomorphism is the subgroup of elements `x : G` such that
`f x = 1` -/
@[to_additive
      "The additive kernel of an `AddMonoid` homomorphism is the `AddSubgroup` of elements
      such that `f x = 0`"]
def ker (f : G →* M) : Subgroup G :=
  { MonoidHom.mker f with
    inv_mem' := fun {x} (hx : f x = 1) =>
      calc
        f x⁻¹ = f x * f 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
N : Type u_5
P : Type u_6
inst✝² : Group N
inst✝¹ : Group P
K : Subgroup G
M : Type u_7
inst✝ : MulOneClass M
f : G →* M
src✝ : Submonoid G := mker f
x : G
hx : f x = 1
⊢ f x⁻¹ = f x * f x⁻¹

Next tactic:
rw [hx, one_mul]
/-- The multiplicative kernel of a monoid homomorphism is the subgroup of elements `x : G` such that
`f x = 1` -/
@[to_additive
      "The additive kernel of an `AddMonoid` homomorphism is the `AddSubgroup` of elements
      such that `f x = 0`"]
def ker (f : G →* M) : Subgroup G :=
  { MonoidHom.mker f with
    inv_mem' := fun {x} (hx : f x = 1) =>
      calc
        f x⁻¹ = f x * f x⁻¹ := by rw [hx, one_mul]
        _ = 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
N : Type u_5
P : Type u_6
inst✝² : Group N
inst✝¹ : Group P
K : Subgroup G
M : Type u_7
inst✝ : MulOneClass M
f : G →* M
src✝ : Submonoid G := mker f
x : G
hx : f x = 1
⊢ f x * f x⁻¹ = 1

Next tactic:
rw [← map_mul, mul_inv_self, map_one]
@[to_additive (attr := simp)]
theorem ker_toHomUnits {M} [Monoid M] (f : G →* M) : f.toHomUnits.ker = f.ker := 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
N : Type u_5
P : Type u_6
inst✝³ : Group N
inst✝² : Group P
K : Subgroup G
M✝ : Type u_7
inst✝¹ : MulOneClass M✝
M : Type u_8
inst✝ : Monoid M
f : G →* M
⊢ ker (toHomUnits f) = ker f

Next tactic:
ext x
@[to_additive (attr := simp)]
theorem ker_toHomUnits {M} [Monoid M] (f : G →* M) : f.toHomUnits.ker = f.ker := by
  ext x
  

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
N : Type u_5
P : Type u_6
inst✝³ : Group N
inst✝² : Group P
K : Subgroup G
M✝ : Type u_7
inst✝¹ : MulOneClass M✝
M : Type u_8
inst✝ : Monoid M
f : G →* M
x : G
⊢ x ∈ ker (toHomUnits f) ↔ x ∈ ker f

Next tactic:
simp [mem_ker, Units.ext_iff]
@[to_additive]
theorem eq_iff (f : G →* M) {x y : G} : f x = f y ↔ y⁻¹ * x ∈ f.ker := 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
N : Type u_5
P : Type u_6
inst✝² : Group N
inst✝¹ : Group P
K : Subgroup G
M : Type u_7
inst✝ : MulOneClass M
f : G →* M
x y : G
⊢ f x = f y ↔ y⁻¹ * x ∈ ker f

Next tactic:
constructor
@[to_additive]
theorem eq_iff (f : G →* M) {x y : G} : f x = f y ↔ y⁻¹ * x ∈ f.ker := by
  constructor <;> 

Proof state:
case mp
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
N : Type u_5
P : Type u_6
inst✝² : Group N
inst✝¹ : Group P
K : Subgroup G
M : Type u_7
inst✝ : MulOneClass M
f : G →* M
x y : G
⊢ f x = f y → y⁻¹ * x ∈ ker f

Next tactic:
intro h
@[to_additive]
theorem eq_iff (f : G →* M) {x y : G} : f x = f y ↔ y⁻¹ * x ∈ f.ker := by
  constructor <;> 

Proof state:
case mpr
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
N : Type u_5
P : Type u_6
inst✝² : Group N
inst✝¹ : Group P
K : Subgroup G
M : Type u_7
inst✝ : MulOneClass M
f : G →* M
x y : G
⊢ y⁻¹ * x ∈ ker f → f x = f y

Next tactic:
intro h
@[to_additive]
theorem eq_iff (f : G →* M) {x y : G} : f x = f y ↔ y⁻¹ * x ∈ f.ker := by
  constructor <;> intro h
  · 

Proof state:
case mp
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
N : Type u_5
P : Type u_6
inst✝² : Group N
inst✝¹ : Group P
K : Subgroup G
M : Type u_7
inst✝ : MulOneClass M
f : G →* M
x y : G
h : f x = f y
⊢ y⁻¹ * x ∈ ker f

Next tactic:
rw [mem_ker, map_mul, h, ← map_mul, inv_mul_self, map_one]
@[to_additive]
theorem eq_iff (f : G →* M) {x y : G} : f x = f y ↔ y⁻¹ * x ∈ f.ker := by
  constructor <;> intro h
  · rw [mem_ker, map_mul, h, ← map_mul, inv_mul_self, map_one]
  · 

Proof state:
case mpr
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
N : Type u_5
P : Type u_6
inst✝² : Group N
inst✝¹ : Group P
K : Subgroup G
M : Type u_7
inst✝ : MulOneClass M
f : G →* M
x y : G
h : y⁻¹ * x ∈ ker f
⊢ f x = f y

Next tactic:
rw [← one_mul x, ← mul_inv_self y, mul_assoc, map_mul, f.mem_ker.1 h, mul_one]
@[to_additive]
theorem ker_eq_bot_iff (f : G →* M) : f.ker = ⊥ ↔ Function.Injective f :=
  ⟨fun h x y hxy => 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
N : Type u_5
P : Type u_6
inst✝² : Group N
inst✝¹ : Group P
K : Subgroup G
M : Type u_7
inst✝ : MulOneClass M
f : G →* M
h : ker f = ⊥
x y : G
hxy : f x = f y
⊢ x = y

Next tactic:
rwa [eq_iff, h, mem_bot, inv_mul_eq_one, eq_comm] at hxy
@[to_additive]
theorem ker_prodMap {G' : Type*} {N' : Type*} [Group G'] [Group N'] (f : G →* N) (g : G' →* N') :
    (prodMap f g).ker = f.ker.prod g.ker := 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
N : Type u_5
P : Type u_6
inst✝⁴ : Group N
inst✝³ : Group P
K : Subgroup G
M : Type u_7
inst✝² : MulOneClass M
G' : Type u_8
N' : Type u_9
inst✝¹ : Group G'
inst✝ : Group N'
f : G →* N
g : G' →* N'
⊢ ker (prodMap f g) = prod (ker f) (ker g)

Next tactic:
rw [← comap_bot, ← comap_bot, ← comap_bot, ← prodMap_comap_prod, bot_prod_bot]
@[to_additive]
theorem range_le_ker_iff (f : G →* G') (g : G' →* G'') : f.range ≤ g.ker ↔ g.comp f = 1 :=
  ⟨fun h => ext fun x => h ⟨x, rfl⟩, 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
N : Type u_5
P : Type u_6
inst✝² : Group N
inst✝¹ : Group P
K : Subgroup G
M : Type u_7
inst✝ : MulOneClass M
f : G →* G'
g : G' →* G''
⊢ comp g f = 1 → range f ≤ ker g

Next tactic:
rintro h _ ⟨y, rfl⟩
@[to_additive]
theorem range_le_ker_iff (f : G →* G') (g : G' →* G'') : f.range ≤ g.ker ↔ g.comp f = 1 :=
  ⟨fun h => ext fun x => h ⟨x, rfl⟩, by rintro h _ ⟨y, rfl⟩; 

Proof state:
case 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
N : Type u_5
P : Type u_6
inst✝² : Group N
inst✝¹ : Group P
K : Subgroup G
M : Type u_7
inst✝ : MulOneClass M
f : G →* G'
g : G' →* G''
h : comp g f = 1
y : G
⊢ f y ∈ ker g

Next tactic:
exact FunLike.congr_fun h y
@[to_additive]
instance (priority := 100) normal_ker (f : G →* M) : f.ker.Normal :=
  ⟨fun x hx 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
N : Type u_5
P : Type u_6
inst✝² : Group N
inst✝¹ : Group P
K : Subgroup G
M : Type u_7
inst✝ : MulOneClass M
f : G →* M
x : G
hx : x ∈ ker f
y : G
⊢ y * x * y⁻¹ ∈ ker f

Next tactic:
rw [mem_ker, map_mul, map_mul, f.mem_ker.1 hx, mul_one, map_mul_eq_one f (mul_inv_self y)]
@[to_additive]
theorem closure_preimage_le (f : G →* N) (s : Set N) : closure (f ⁻¹' s) ≤ (closure s).comap f :=
  (closure_le _).2 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
N : Type u_5
P : Type u_6
inst✝¹ : Group N
inst✝ : Group P
K : Subgroup G
f : G →* N
s : Set N
x : G
hx : x ∈ ⇑f ⁻¹' s
⊢ x ∈ ↑(comap f (closure s))

Next tactic:
rw [SetLike.mem_coe, mem_comap]
@[to_additive]
theorem closure_preimage_le (f : G →* N) (s : Set N) : closure (f ⁻¹' s) ≤ (closure s).comap f :=
  (closure_le _).2 fun x hx => by rw [SetLike.mem_coe, mem_comap]; 

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
N : Type u_5
P : Type u_6
inst✝¹ : Group N
inst✝ : Group P
K : Subgroup G
f : G →* N
s : Set N
x : G
hx : x ∈ ⇑f ⁻¹' s
⊢ f x ∈ closure s

Next tactic:
exact subset_closure hx
@[to_additive]
theorem Normal.map {H : Subgroup G} (h : H.Normal) (f : G →* N) (hf : Function.Surjective f) :
    (H.map f).Normal := 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
N : Type u_5
inst✝ : Group N
H✝ H : Subgroup G
h : Normal H
f : G →* N
hf : Surjective ⇑f
⊢ Normal (Subgroup.map f H)

Next tactic:
rw [← normalizer_eq_top, ← top_le_iff, ← f.range_top_of_surjective hf, f.range_eq_map, ←
    normalizer_eq_top.2 h]
@[to_additive]
theorem Normal.map {H : Subgroup G} (h : H.Normal) (f : G →* N) (hf : Function.Surjective f) :
    (H.map f).Normal := by
  rw [← normalizer_eq_top, ← top_le_iff, ← f.range_top_of_surjective hf, f.range_eq_map, ←
    normalizer_eq_top.2 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
N : Type u_5
inst✝ : Group N
H✝ H : Subgroup G
h : Normal H
f : G →* N
hf : Surjective ⇑f
⊢ Subgroup.map f (normalizer H) ≤ normalizer (Subgroup.map f H)

Next tactic:
exact le_normalizer_map _
@[to_additive]
theorem map_eq_bot_iff_of_injective {f : G →* N} (hf : Function.Injective f) :
    H.map f = ⊥ ↔ 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
N : Type u_5
inst✝ : Group N
H : Subgroup G
f : G →* N
hf : Injective ⇑f
⊢ map f H = ⊥ ↔ H = ⊥

Next tactic:
rw [map_eq_bot_iff, f.ker_eq_bot_iff.mpr hf, le_bot_iff]
@[to_additive]
theorem map_comap_eq (H : Subgroup N) : map f (comap f H) = f.range ⊓ H :=
  SetLike.ext' <| 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
N : Type u_5
inst✝ : Group N
f : G →* N
H : Subgroup N
⊢ ↑(map f (comap f H)) = ↑(range f ⊓ H)

Next tactic:
rw [coe_map, coe_comap, Set.image_preimage_eq_inter_range, coe_inf, coe_range, Set.inter_comm]
@[to_additive]
theorem comap_map_eq (H : Subgroup G) : comap f (map f H) = H ⊔ f.ker := 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
N : Type u_5
inst✝ : Group N
f : G →* N
H : Subgroup G
⊢ comap f (map f H) = H ⊔ ker f

Next tactic:
refine' le_antisymm _ (sup_le (le_comap_map _ _) (ker_le_comap _ _))
@[to_additive]
theorem comap_map_eq (H : Subgroup G) : comap f (map f H) = H ⊔ f.ker := by
  refine' le_antisymm _ (sup_le (le_comap_map _ _) (ker_le_comap _ _))
  

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
N : Type u_5
inst✝ : Group N
f : G →* N
H : Subgroup G
⊢ comap f (map f H) ≤ H ⊔ ker f

Next tactic:
intro x hx
@[to_additive]
theorem comap_map_eq (H : Subgroup G) : comap f (map f H) = H ⊔ f.ker := by
  refine' le_antisymm _ (sup_le (le_comap_map _ _) (ker_le_comap _ _))
  intro x hx; 

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
N : Type u_5
inst✝ : Group N
f : G →* N
H : Subgroup G
x : G
hx : x ∈ comap f (map f H)
⊢ x ∈ H ⊔ ker f

Next tactic:
simp only [exists_prop, mem_map, mem_comap] at hx
@[to_additive]
theorem comap_map_eq (H : Subgroup G) : comap f (map f H) = H ⊔ f.ker := by
  refine' le_antisymm _ (sup_le (le_comap_map _ _) (ker_le_comap _ _))
  intro x hx; simp only [exists_prop, mem_map, mem_comap] at hx
  

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
N : Type u_5
inst✝ : Group N
f : G →* N
H : Subgroup G
x : G
hx : ∃ x_1 ∈ H, f x_1 = f x
⊢ x ∈ H ⊔ ker f

Next tactic:
rcases hx with ⟨y, hy, hy'⟩
@[to_additive]
theorem comap_map_eq (H : Subgroup G) : comap f (map f H) = H ⊔ f.ker := by
  refine' le_antisymm _ (sup_le (le_comap_map _ _) (ker_le_comap _ _))
  intro x hx; simp only [exists_prop, mem_map, mem_comap] at hx
  rcases hx with ⟨y, hy, hy'⟩
  

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
N : Type u_5
inst✝ : Group N
f : G →* N
H : Subgroup G
x y : G
hy : y ∈ H
hy' : f y = f x
⊢ x ∈ H ⊔ ker f

Next tactic:
rw [← mul_inv_cancel_left y x]
@[to_additive]
theorem comap_map_eq (H : Subgroup G) : comap f (map f H) = H ⊔ f.ker := by
  refine' le_antisymm _ (sup_le (le_comap_map _ _) (ker_le_comap _ _))
  intro x hx; simp only [exists_prop, mem_map, mem_comap] at hx
  rcases hx with ⟨y, hy, hy'⟩
  rw [← mul_inv_cancel_left y x]
  

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
N : Type u_5
inst✝ : Group N
f : G →* N
H : Subgroup G
x y : G
hy : y ∈ H
hy' : f y = f x
⊢ y * (y⁻¹ * x) ∈ H ⊔ ker f

Next tactic:
exact mul_mem_sup hy (by simp [mem_ker, hy'])
@[to_additive]
theorem comap_map_eq (H : Subgroup G) : comap f (map f H) = H ⊔ f.ker := by
  refine' le_antisymm _ (sup_le (le_comap_map _ _) (ker_le_comap _ _))
  intro x hx; simp only [exists_prop, mem_map, mem_comap] at hx
  rcases hx with ⟨y, hy, hy'⟩
  rw [← mul_inv_cancel_left y x]
  exact mul_mem_sup hy (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
N : Type u_5
inst✝ : Group N
f : G →* N
H : Subgroup G
x y : G
hy : y ∈ H
hy' : f y = f x
⊢ y⁻¹ * x ∈ ker f

Next tactic:
simp [mem_ker, hy']
@[to_additive]
theorem map_comap_eq_self {f : G →* N} {H : Subgroup N} (h : H ≤ f.range) : map f (comap f 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
N : Type u_5
inst✝ : Group N
f✝ f : G →* N
H : Subgroup N
h : H ≤ range f
⊢ map f (comap f H) = H

Next tactic:
rwa [map_comap_eq, inf_eq_right]
@[to_additive]
theorem comap_lt_comap_of_surjective {f : G →* N} {K L : Subgroup N} (hf : Function.Surjective f) :
    K.comap f < L.comap f ↔ K < L := 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
N : Type u_5
inst✝ : Group N
f✝ f : G →* N
K L : Subgroup N
hf : Surjective ⇑f
⊢ comap f K < comap f L ↔ K < L

Next tactic:
simp_rw [lt_iff_le_not_le, comap_le_comap_of_surjective hf]
@[to_additive]
theorem comap_injective {f : G →* N} (h : Function.Surjective f) : Function.Injective (comap f) :=
  fun K L => 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
N : Type u_5
inst✝ : Group N
f✝ f : G →* N
h : Surjective ⇑f
K L : Subgroup N
⊢ comap f K = comap f L → K = L

Next tactic:
simp only [le_antisymm_iff, comap_le_comap_of_surjective h, imp_self]
@[to_additive]
theorem comap_map_eq_self {f : G →* N} {H : Subgroup G} (h : f.ker ≤ H) : comap f (map f 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
N : Type u_5
inst✝ : Group N
f✝ f : G →* N
H : Subgroup G
h : ker f ≤ H
⊢ comap f (map f H) = H

Next tactic:
rwa [comap_map_eq, sup_eq_left]