l3lab/ntp-mathlib huggingface dataset:
theorem IsLowerSet.exists_subset_ball (hs : IsLowerSet s) (hx : x ∈ closure s) (hδ : 0 < δ) :
    ∃ y, closedBall y (δ / 4) ⊆ closedBall x δ ∧ closedBall y (δ / 4) ⊆ interior s := by
  refine' ⟨x - const _ (3 / 4 * δ), closedBall_subset_closedBall' _, _⟩
  · rw [dist_self_sub_left]
    refine' (add_le_add_left (pi_norm_const_le <| 3 / 4 * δ) _).trans_eq _
    simp only [norm_mul, norm_div, Real.norm_eq_abs, gt_iff_lt, zero_lt_three, abs_of_pos,
      zero_lt_four, abs_of_pos hδ]
    ring
  obtain ⟨y, hy, hxy⟩ := Metric.mem_closure_iff.1 hx _ (div_pos hδ zero_lt_four)
  refine' fun z hz => hs.mem_interior_of_forall_lt (subset_closure hy) fun i => _
  rw [mem_closedBall, dist_eq_norm'] at hz
  rw [dist_eq_norm] at hxy
  

Proof state:
case refine'_2.intro.intro
α : Type u_1
ι : Type u_2
inst✝ : Fintype ι
s : Set (ι → ℝ)
x y✝ : ι → ℝ
δ : ℝ
hs : IsLowerSet s
hx : x ∈ closure s
hδ : 0 < δ
y : ι → ℝ
hy : y ∈ s
hxy : ‖x - y‖ < δ / 4
z : ι → ℝ
hz : ‖x - const ι (3 / 4 * δ) - z‖ ≤ δ / 4
i : ι
⊢ z i < y i

Next tactic:
replace hxy := (norm_le_pi_norm _ i).trans hxy.le
theorem IsLowerSet.exists_subset_ball (hs : IsLowerSet s) (hx : x ∈ closure s) (hδ : 0 < δ) :
    ∃ y, closedBall y (δ / 4) ⊆ closedBall x δ ∧ closedBall y (δ / 4) ⊆ interior s := by
  refine' ⟨x - const _ (3 / 4 * δ), closedBall_subset_closedBall' _, _⟩
  · rw [dist_self_sub_left]
    refine' (add_le_add_left (pi_norm_const_le <| 3 / 4 * δ) _).trans_eq _
    simp only [norm_mul, norm_div, Real.norm_eq_abs, gt_iff_lt, zero_lt_three, abs_of_pos,
      zero_lt_four, abs_of_pos hδ]
    ring
  obtain ⟨y, hy, hxy⟩ := Metric.mem_closure_iff.1 hx _ (div_pos hδ zero_lt_four)
  refine' fun z hz => hs.mem_interior_of_forall_lt (subset_closure hy) fun i => _
  rw [mem_closedBall, dist_eq_norm'] at hz
  rw [dist_eq_norm] at hxy
  replace hxy := (norm_le_pi_norm _ i).trans hxy.le
  

Proof state:
case refine'_2.intro.intro
α : Type u_1
ι : Type u_2
inst✝ : Fintype ι
s : Set (ι → ℝ)
x y✝ : ι → ℝ
δ : ℝ
hs : IsLowerSet s
hx : x ∈ closure s
hδ : 0 < δ
y : ι → ℝ
hy : y ∈ s
z : ι → ℝ
hz : ‖x - const ι (3 / 4 * δ) - z‖ ≤ δ / 4
i : ι
hxy : ‖(x - y) i‖ ≤ δ / 4
⊢ z i < y i

Next tactic:
replace hz := (norm_le_pi_norm _ i).trans hz
theorem IsLowerSet.exists_subset_ball (hs : IsLowerSet s) (hx : x ∈ closure s) (hδ : 0 < δ) :
    ∃ y, closedBall y (δ / 4) ⊆ closedBall x δ ∧ closedBall y (δ / 4) ⊆ interior s := by
  refine' ⟨x - const _ (3 / 4 * δ), closedBall_subset_closedBall' _, _⟩
  · rw [dist_self_sub_left]
    refine' (add_le_add_left (pi_norm_const_le <| 3 / 4 * δ) _).trans_eq _
    simp only [norm_mul, norm_div, Real.norm_eq_abs, gt_iff_lt, zero_lt_three, abs_of_pos,
      zero_lt_four, abs_of_pos hδ]
    ring
  obtain ⟨y, hy, hxy⟩ := Metric.mem_closure_iff.1 hx _ (div_pos hδ zero_lt_four)
  refine' fun z hz => hs.mem_interior_of_forall_lt (subset_closure hy) fun i => _
  rw [mem_closedBall, dist_eq_norm'] at hz
  rw [dist_eq_norm] at hxy
  replace hxy := (norm_le_pi_norm _ i).trans hxy.le
  replace hz := (norm_le_pi_norm _ i).trans hz
  

Proof state:
case refine'_2.intro.intro
α : Type u_1
ι : Type u_2
inst✝ : Fintype ι
s : Set (ι → ℝ)
x y✝ : ι → ℝ
δ : ℝ
hs : IsLowerSet s
hx : x ∈ closure s
hδ : 0 < δ
y : ι → ℝ
hy : y ∈ s
z : ι → ℝ
i : ι
hxy : ‖(x - y) i‖ ≤ δ / 4
hz : ‖(x - const ι (3 / 4 * δ) - z) i‖ ≤ δ / 4
⊢ z i < y i

Next tactic:
dsimp at hxy hz
theorem IsLowerSet.exists_subset_ball (hs : IsLowerSet s) (hx : x ∈ closure s) (hδ : 0 < δ) :
    ∃ y, closedBall y (δ / 4) ⊆ closedBall x δ ∧ closedBall y (δ / 4) ⊆ interior s := by
  refine' ⟨x - const _ (3 / 4 * δ), closedBall_subset_closedBall' _, _⟩
  · rw [dist_self_sub_left]
    refine' (add_le_add_left (pi_norm_const_le <| 3 / 4 * δ) _).trans_eq _
    simp only [norm_mul, norm_div, Real.norm_eq_abs, gt_iff_lt, zero_lt_three, abs_of_pos,
      zero_lt_four, abs_of_pos hδ]
    ring
  obtain ⟨y, hy, hxy⟩ := Metric.mem_closure_iff.1 hx _ (div_pos hδ zero_lt_four)
  refine' fun z hz => hs.mem_interior_of_forall_lt (subset_closure hy) fun i => _
  rw [mem_closedBall, dist_eq_norm'] at hz
  rw [dist_eq_norm] at hxy
  replace hxy := (norm_le_pi_norm _ i).trans hxy.le
  replace hz := (norm_le_pi_norm _ i).trans hz
  dsimp at hxy hz
  

Proof state:
case refine'_2.intro.intro
α : Type u_1
ι : Type u_2
inst✝ : Fintype ι
s : Set (ι → ℝ)
x y✝ : ι → ℝ
δ : ℝ
hs : IsLowerSet s
hx : x ∈ closure s
hδ : 0 < δ
y : ι → ℝ
hy : y ∈ s
z : ι → ℝ
i : ι
hxy : |x i - y i| ≤ δ / 4
hz : |x i - 3 / 4 * δ - z i| ≤ δ / 4
⊢ z i < y i

Next tactic:
rw [abs_sub_le_iff] at hxy hz
theorem IsLowerSet.exists_subset_ball (hs : IsLowerSet s) (hx : x ∈ closure s) (hδ : 0 < δ) :
    ∃ y, closedBall y (δ / 4) ⊆ closedBall x δ ∧ closedBall y (δ / 4) ⊆ interior s := by
  refine' ⟨x - const _ (3 / 4 * δ), closedBall_subset_closedBall' _, _⟩
  · rw [dist_self_sub_left]
    refine' (add_le_add_left (pi_norm_const_le <| 3 / 4 * δ) _).trans_eq _
    simp only [norm_mul, norm_div, Real.norm_eq_abs, gt_iff_lt, zero_lt_three, abs_of_pos,
      zero_lt_four, abs_of_pos hδ]
    ring
  obtain ⟨y, hy, hxy⟩ := Metric.mem_closure_iff.1 hx _ (div_pos hδ zero_lt_four)
  refine' fun z hz => hs.mem_interior_of_forall_lt (subset_closure hy) fun i => _
  rw [mem_closedBall, dist_eq_norm'] at hz
  rw [dist_eq_norm] at hxy
  replace hxy := (norm_le_pi_norm _ i).trans hxy.le
  replace hz := (norm_le_pi_norm _ i).trans hz
  dsimp at hxy hz
  rw [abs_sub_le_iff] at hxy hz
  

Proof state:
case refine'_2.intro.intro
α : Type u_1
ι : Type u_2
inst✝ : Fintype ι
s : Set (ι → ℝ)
x y✝ : ι → ℝ
δ : ℝ
hs : IsLowerSet s
hx : x ∈ closure s
hδ : 0 < δ
y : ι → ℝ
hy : y ∈ s
z : ι → ℝ
i : ι
hxy : x i - y i ≤ δ / 4 ∧ y i - x i ≤ δ / 4
hz : x i - 3 / 4 * δ - z i ≤ δ / 4 ∧ z i - (x i - 3 / 4 * δ) ≤ δ / 4
⊢ z i < y i

Next tactic:
linarith
/-- No point making this an instance, as it requires `i`. -/
theorem hasKernels [PreservesFiniteLimits G] : HasKernels C :=
  { has_limit := fun f => by
      

Proof state:
C : Type u₁
inst✝⁵ : Category.{v, u₁} C
inst✝⁴ : Preadditive C
D : Type u₂
inst✝³ : Category.{v, u₂} D
inst✝² : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝¹ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
inst✝ : PreservesFiniteLimits G
X✝ Y✝ : C
f : X✝ ⟶ Y✝
⊢ HasKernel f

Next tactic:
have := NatIso.naturality_1 i f
/-- No point making this an instance, as it requires `i`. -/
theorem hasKernels [PreservesFiniteLimits G] : HasKernels C :=
  { has_limit := fun f => by
      have := NatIso.naturality_1 i f
      

Proof state:
C : Type u₁
inst✝⁵ : Category.{v, u₁} C
inst✝⁴ : Preadditive C
D : Type u₂
inst✝³ : Category.{v, u₂} D
inst✝² : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝¹ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
inst✝ : PreservesFiniteLimits G
X✝ Y✝ : C
f : X✝ ⟶ Y✝
this : i.inv.app X✝ ≫ (F ⋙ G).map f ≫ i.hom.app Y✝ = (𝟭 C).map f
⊢ HasKernel f

Next tactic:
simp? at this says
        simp only [Functor.id_obj, Functor.comp_obj, Functor.comp_map, Functor.id_map] at this
/-- No point making this an instance, as it requires `i`. -/
theorem hasKernels [PreservesFiniteLimits G] : HasKernels C :=
  { has_limit := fun f => by
      have := NatIso.naturality_1 i f
      simp? at this says
        

Proof state:
C : Type u₁
inst✝⁵ : Category.{v, u₁} C
inst✝⁴ : Preadditive C
D : Type u₂
inst✝³ : Category.{v, u₂} D
inst✝² : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝¹ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
inst✝ : PreservesFiniteLimits G
X✝ Y✝ : C
f : X✝ ⟶ Y✝
this : i.inv.app X✝ ≫ (F ⋙ G).map f ≫ i.hom.app Y✝ = (𝟭 C).map f
⊢ HasKernel f

Next tactic:
simp only [Functor.id_obj, Functor.comp_obj, Functor.comp_map, Functor.id_map] at this
/-- No point making this an instance, as it requires `i`. -/
theorem hasKernels [PreservesFiniteLimits G] : HasKernels C :=
  { has_limit := fun f => by
      have := NatIso.naturality_1 i f
      simp? at this says
        simp only [Functor.id_obj, Functor.comp_obj, Functor.comp_map, Functor.id_map] at this
      

Proof state:
C : Type u₁
inst✝⁵ : Category.{v, u₁} C
inst✝⁴ : Preadditive C
D : Type u₂
inst✝³ : Category.{v, u₂} D
inst✝² : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝¹ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
inst✝ : PreservesFiniteLimits G
X✝ Y✝ : C
f : X✝ ⟶ Y✝
this : i.inv.app X✝ ≫ G.map (F.map f) ≫ i.hom.app Y✝ = f
⊢ HasKernel f

Next tactic:
rw [← this]
/-- No point making this an instance, as it requires `i`. -/
theorem hasKernels [PreservesFiniteLimits G] : HasKernels C :=
  { has_limit := fun f => by
      have := NatIso.naturality_1 i f
      simp? at this says
        simp only [Functor.id_obj, Functor.comp_obj, Functor.comp_map, Functor.id_map] at this
      rw [← this]
      

Proof state:
C : Type u₁
inst✝⁵ : Category.{v, u₁} C
inst✝⁴ : Preadditive C
D : Type u₂
inst✝³ : Category.{v, u₂} D
inst✝² : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝¹ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
inst✝ : PreservesFiniteLimits G
X✝ Y✝ : C
f : X✝ ⟶ Y✝
this : i.inv.app X✝ ≫ G.map (F.map f) ≫ i.hom.app Y✝ = f
⊢ HasKernel (i.inv.app X✝ ≫ G.map (F.map f) ≫ i.hom.app Y✝)

Next tactic:
haveI : HasKernel (G.map (F.map f) ≫ i.hom.app _) := Limits.hasKernel_comp_mono _ _
/-- No point making this an instance, as it requires `i`. -/
theorem hasKernels [PreservesFiniteLimits G] : HasKernels C :=
  { has_limit := fun f => by
      have := NatIso.naturality_1 i f
      simp? at this says
        simp only [Functor.id_obj, Functor.comp_obj, Functor.comp_map, Functor.id_map] at this
      rw [← this]
      haveI : HasKernel (G.map (F.map f) ≫ i.hom.app _) := Limits.hasKernel_comp_mono _ _
      

Proof state:
C : Type u₁
inst✝⁵ : Category.{v, u₁} C
inst✝⁴ : Preadditive C
D : Type u₂
inst✝³ : Category.{v, u₂} D
inst✝² : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝¹ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
inst✝ : PreservesFiniteLimits G
X✝ Y✝ : C
f : X✝ ⟶ Y✝
this✝ : i.inv.app X✝ ≫ G.map (F.map f) ≫ i.hom.app Y✝ = f
this : HasKernel (G.map (F.map f) ≫ i.hom.app Y✝)
⊢ HasKernel (i.inv.app X✝ ≫ G.map (F.map f) ≫ i.hom.app Y✝)

Next tactic:
apply Limits.hasKernel_iso_comp
/-- No point making this an instance, as it requires `i` and `adj`. -/
theorem hasCokernels : HasCokernels C :=
  { has_colimit := fun f => by
      

Proof state:
C : Type u₁
inst✝⁴ : Category.{v, u₁} C
inst✝³ : Preadditive C
D : Type u₂
inst✝² : Category.{v, u₂} D
inst✝¹ : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
X✝ Y✝ : C
f : X✝ ⟶ Y✝
⊢ HasCokernel f

Next tactic:
have : PreservesColimits G := adj.leftAdjointPreservesColimits
/-- No point making this an instance, as it requires `i` and `adj`. -/
theorem hasCokernels : HasCokernels C :=
  { has_colimit := fun f => by
      have : PreservesColimits G := adj.leftAdjointPreservesColimits
      

Proof state:
C : Type u₁
inst✝⁴ : Category.{v, u₁} C
inst✝³ : Preadditive C
D : Type u₂
inst✝² : Category.{v, u₂} D
inst✝¹ : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
X✝ Y✝ : C
f : X✝ ⟶ Y✝
this : PreservesColimits G
⊢ HasCokernel f

Next tactic:
have := NatIso.naturality_1 i f
/-- No point making this an instance, as it requires `i` and `adj`. -/
theorem hasCokernels : HasCokernels C :=
  { has_colimit := fun f => by
      have : PreservesColimits G := adj.leftAdjointPreservesColimits
      have := NatIso.naturality_1 i f
      

Proof state:
C : Type u₁
inst✝⁴ : Category.{v, u₁} C
inst✝³ : Preadditive C
D : Type u₂
inst✝² : Category.{v, u₂} D
inst✝¹ : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
X✝ Y✝ : C
f : X✝ ⟶ Y✝
this✝ : PreservesColimits G
this : i.inv.app X✝ ≫ (F ⋙ G).map f ≫ i.hom.app Y✝ = (𝟭 C).map f
⊢ HasCokernel f

Next tactic:
simp? at this says
        simp only [Functor.id_obj, Functor.comp_obj, Functor.comp_map, Functor.id_map] at this
/-- No point making this an instance, as it requires `i` and `adj`. -/
theorem hasCokernels : HasCokernels C :=
  { has_colimit := fun f => by
      have : PreservesColimits G := adj.leftAdjointPreservesColimits
      have := NatIso.naturality_1 i f
      simp? at this says
        

Proof state:
C : Type u₁
inst✝⁴ : Category.{v, u₁} C
inst✝³ : Preadditive C
D : Type u₂
inst✝² : Category.{v, u₂} D
inst✝¹ : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
X✝ Y✝ : C
f : X✝ ⟶ Y✝
this✝ : PreservesColimits G
this : i.inv.app X✝ ≫ (F ⋙ G).map f ≫ i.hom.app Y✝ = (𝟭 C).map f
⊢ HasCokernel f

Next tactic:
simp only [Functor.id_obj, Functor.comp_obj, Functor.comp_map, Functor.id_map] at this
/-- No point making this an instance, as it requires `i` and `adj`. -/
theorem hasCokernels : HasCokernels C :=
  { has_colimit := fun f => by
      have : PreservesColimits G := adj.leftAdjointPreservesColimits
      have := NatIso.naturality_1 i f
      simp? at this says
        simp only [Functor.id_obj, Functor.comp_obj, Functor.comp_map, Functor.id_map] at this
      

Proof state:
C : Type u₁
inst✝⁴ : Category.{v, u₁} C
inst✝³ : Preadditive C
D : Type u₂
inst✝² : Category.{v, u₂} D
inst✝¹ : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
X✝ Y✝ : C
f : X✝ ⟶ Y✝
this✝ : PreservesColimits G
this : i.inv.app X✝ ≫ G.map (F.map f) ≫ i.hom.app Y✝ = f
⊢ HasCokernel f

Next tactic:
rw [← this]
/-- No point making this an instance, as it requires `i` and `adj`. -/
theorem hasCokernels : HasCokernels C :=
  { has_colimit := fun f => by
      have : PreservesColimits G := adj.leftAdjointPreservesColimits
      have := NatIso.naturality_1 i f
      simp? at this says
        simp only [Functor.id_obj, Functor.comp_obj, Functor.comp_map, Functor.id_map] at this
      rw [← this]
      

Proof state:
C : Type u₁
inst✝⁴ : Category.{v, u₁} C
inst✝³ : Preadditive C
D : Type u₂
inst✝² : Category.{v, u₂} D
inst✝¹ : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
X✝ Y✝ : C
f : X✝ ⟶ Y✝
this✝ : PreservesColimits G
this : i.inv.app X✝ ≫ G.map (F.map f) ≫ i.hom.app Y✝ = f
⊢ HasCokernel (i.inv.app X✝ ≫ G.map (F.map f) ≫ i.hom.app Y✝)

Next tactic:
haveI : HasCokernel (G.map (F.map f) ≫ i.hom.app _) := Limits.hasCokernel_comp_iso _ _
/-- No point making this an instance, as it requires `i` and `adj`. -/
theorem hasCokernels : HasCokernels C :=
  { has_colimit := fun f => by
      have : PreservesColimits G := adj.leftAdjointPreservesColimits
      have := NatIso.naturality_1 i f
      simp? at this says
        simp only [Functor.id_obj, Functor.comp_obj, Functor.comp_map, Functor.id_map] at this
      rw [← this]
      haveI : HasCokernel (G.map (F.map f) ≫ i.hom.app _) := Limits.hasCokernel_comp_iso _ _
      

Proof state:
C : Type u₁
inst✝⁴ : Category.{v, u₁} C
inst✝³ : Preadditive C
D : Type u₂
inst✝² : Category.{v, u₂} D
inst✝¹ : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
X✝ Y✝ : C
f : X✝ ⟶ Y✝
this✝¹ : PreservesColimits G
this✝ : i.inv.app X✝ ≫ G.map (F.map f) ≫ i.hom.app Y✝ = f
this : HasCokernel (G.map (F.map f) ≫ i.hom.app Y✝)
⊢ HasCokernel (i.inv.app X✝ ≫ G.map (F.map f) ≫ i.hom.app Y✝)

Next tactic:
apply Limits.hasCokernel_epi_comp
/-- Auxiliary construction for `coimageIsoImage` -/
def cokernelIso {X Y : C} (f : X ⟶ Y) : G.obj (cokernel (F.map f)) ≅ cokernel f := by
  -- We have to write an explicit `PreservesColimits` type here,
  -- as `leftAdjointPreservesColimits` has universe variables.
  

Proof state:
C : Type u₁
inst✝⁵ : Category.{v, u₁} C
inst✝⁴ : Preadditive C
D : Type u₂
inst✝³ : Category.{v, u₂} D
inst✝² : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝¹ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
inst✝ : HasCokernels C
X Y : C
f : X ⟶ Y
⊢ G.obj (cokernel (F.map f)) ≅ cokernel f

Next tactic:
have : PreservesColimits G := adj.leftAdjointPreservesColimits
/-- Auxiliary construction for `coimageIsoImage` -/
def cokernelIso {X Y : C} (f : X ⟶ Y) : G.obj (cokernel (F.map f)) ≅ cokernel f := by
  -- We have to write an explicit `PreservesColimits` type here,
  -- as `leftAdjointPreservesColimits` has universe variables.
  have : PreservesColimits G := adj.leftAdjointPreservesColimits
  -- porting note: the next `have` has been added, otherwise some instance were not found
  

Proof state:
C : Type u₁
inst✝⁵ : Category.{v, u₁} C
inst✝⁴ : Preadditive C
D : Type u₂
inst✝³ : Category.{v, u₂} D
inst✝² : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝¹ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
inst✝ : HasCokernels C
X Y : C
f : X ⟶ Y
this : PreservesColimits G
⊢ G.obj (cokernel (F.map f)) ≅ cokernel f

Next tactic:
have : ∀ (X' Y' : C) (f' : X' ⟶ Y'), HasCokernel f' := inferInstance
/-- Auxiliary construction for `coimageIsoImage` -/
def cokernelIso {X Y : C} (f : X ⟶ Y) : G.obj (cokernel (F.map f)) ≅ cokernel f := by
  -- We have to write an explicit `PreservesColimits` type here,
  -- as `leftAdjointPreservesColimits` has universe variables.
  have : PreservesColimits G := adj.leftAdjointPreservesColimits
  -- porting note: the next `have` has been added, otherwise some instance were not found
  have : ∀ (X' Y' : C) (f' : X' ⟶ Y'), HasCokernel f' := inferInstance
  

Proof state:
C : Type u₁
inst✝⁵ : Category.{v, u₁} C
inst✝⁴ : Preadditive C
D : Type u₂
inst✝³ : Category.{v, u₂} D
inst✝² : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝¹ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
inst✝ : HasCokernels C
X Y : C
f : X ⟶ Y
this✝ : PreservesColimits G
this : ∀ (X' Y' : C) (f' : X' ⟶ Y'), HasCokernel f'
⊢ G.obj (cokernel (F.map f)) ≅ cokernel f

Next tactic:
calc
    G.obj (cokernel (F.map f)) ≅ cokernel (G.map (F.map f)) :=
      (asIso (cokernelComparison _ G)).symm
    _ ≅ cokernel (i.hom.app X ≫ f ≫ i.inv.app Y) := cokernelIsoOfEq (NatIso.naturality_2 i f).symm
    _ ≅ cokernel (f ≫ i.inv.app Y) := cokernelEpiComp (i.hom.app X) (f ≫ i.inv.app Y)
    _ ≅ cokernel f := cokernelCompIsIso f (i.inv.app Y)
/-- Auxiliary construction for `coimageIsoImage` -/
def coimageIsoImageAux {X Y : C} (f : X ⟶ Y) :
    kernel (G.map (cokernel.π (F.map f))) ≅ kernel (cokernel.π f) := by
  

Proof state:
C : Type u₁
inst✝⁷ : Category.{v, u₁} C
inst✝⁶ : Preadditive C
D : Type u₂
inst✝⁵ : Category.{v, u₂} D
inst✝⁴ : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝³ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
inst✝² : HasCokernels C
inst✝¹ : HasKernels C
inst✝ : PreservesFiniteLimits G
X Y : C
f : X ⟶ Y
⊢ kernel (G.map (cokernel.π (F.map f))) ≅ kernel (cokernel.π f)

Next tactic:
have : PreservesColimits G := adj.leftAdjointPreservesColimits
/-- Auxiliary construction for `coimageIsoImage` -/
def coimageIsoImageAux {X Y : C} (f : X ⟶ Y) :
    kernel (G.map (cokernel.π (F.map f))) ≅ kernel (cokernel.π f) := by
  have : PreservesColimits G := adj.leftAdjointPreservesColimits
  -- porting note: the next `have` has been added, otherwise some instance were not found
  

Proof state:
C : Type u₁
inst✝⁷ : Category.{v, u₁} C
inst✝⁶ : Preadditive C
D : Type u₂
inst✝⁵ : Category.{v, u₂} D
inst✝⁴ : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝³ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
inst✝² : HasCokernels C
inst✝¹ : HasKernels C
inst✝ : PreservesFiniteLimits G
X Y : C
f : X ⟶ Y
this : PreservesColimits G
⊢ kernel (G.map (cokernel.π (F.map f))) ≅ kernel (cokernel.π f)

Next tactic:
have : ∀ (X' Y' : C) (f' : X' ⟶ Y'), HasCokernel f' := inferInstance
/-- Auxiliary construction for `coimageIsoImage` -/
def coimageIsoImageAux {X Y : C} (f : X ⟶ Y) :
    kernel (G.map (cokernel.π (F.map f))) ≅ kernel (cokernel.π f) := by
  have : PreservesColimits G := adj.leftAdjointPreservesColimits
  -- porting note: the next `have` has been added, otherwise some instance were not found
  have : ∀ (X' Y' : C) (f' : X' ⟶ Y'), HasCokernel f' := inferInstance
  

Proof state:
C : Type u₁
inst✝⁷ : Category.{v, u₁} C
inst✝⁶ : Preadditive C
D : Type u₂
inst✝⁵ : Category.{v, u₂} D
inst✝⁴ : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝³ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
inst✝² : HasCokernels C
inst✝¹ : HasKernels C
inst✝ : PreservesFiniteLimits G
X Y : C
f : X ⟶ Y
this✝ : PreservesColimits G
this : ∀ (X' Y' : C) (f' : X' ⟶ Y'), HasCokernel f'
⊢ kernel (G.map (cokernel.π (F.map f))) ≅ kernel (cokernel.π f)

Next tactic:
calc
    kernel (G.map (cokernel.π (F.map f))) ≅
        kernel (cokernel.π (G.map (F.map f)) ≫ cokernelComparison (F.map f) G) :=
      kernelIsoOfEq (π_comp_cokernelComparison _ _).symm
    _ ≅ kernel (cokernel.π (G.map (F.map f))) := (kernelCompMono _ _)
    _ ≅ kernel (cokernel.π (_ ≫ f ≫ _) ≫ (cokernelIsoOfEq _).hom) :=
      (kernelIsoOfEq (π_comp_cokernelIsoOfEq_hom (NatIso.naturality_2 i f)).symm)
    _ ≅ kernel (cokernel.π (_ ≫ f ≫ _)) := (kernelCompMono _ _)
    _ ≅ kernel (cokernel.π (f ≫ i.inv.app Y) ≫ (cokernelEpiComp (i.hom.app X) _).inv) :=
      (kernelIsoOfEq (by simp only [cokernel.π_desc, cokernelEpiComp_inv]))
    _ ≅ kernel (cokernel.π (f ≫ _)) := (kernelCompMono _ _)
    _ ≅ kernel (inv (i.inv.app Y) ≫ cokernel.π f ≫ (cokernelCompIsIso f (i.inv.app Y)).inv) :=
      (kernelIsoOfEq
        (by simp only [cokernel.π_desc, cokernelCompIsIso_inv, Iso.hom_inv_id_app_assoc,
          NatIso.inv_inv_app]))
    _ ≅ kernel (cokernel.π f ≫ _) := (kernelIsIsoComp _ _)
    _ ≅ kernel (cokernel.π f) := kernelCompMono _ _
/-- Auxiliary construction for `coimageIsoImage` -/
def coimageIsoImageAux {X Y : C} (f : X ⟶ Y) :
    kernel (G.map (cokernel.π (F.map f))) ≅ kernel (cokernel.π f) := by
  have : PreservesColimits G := adj.leftAdjointPreservesColimits
  -- porting note: the next `have` has been added, otherwise some instance were not found
  have : ∀ (X' Y' : C) (f' : X' ⟶ Y'), HasCokernel f' := inferInstance
  calc
    kernel (G.map (cokernel.π (F.map f))) ≅
        kernel (cokernel.π (G.map (F.map f)) ≫ cokernelComparison (F.map f) G) :=
      kernelIsoOfEq (π_comp_cokernelComparison _ _).symm
    _ ≅ kernel (cokernel.π (G.map (F.map f))) := (kernelCompMono _ _)
    _ ≅ kernel (cokernel.π (_ ≫ f ≫ _) ≫ (cokernelIsoOfEq _).hom) :=
      (kernelIsoOfEq (π_comp_cokernelIsoOfEq_hom (NatIso.naturality_2 i f)).symm)
    _ ≅ kernel (cokernel.π (_ ≫ f ≫ _)) := (kernelCompMono _ _)
    _ ≅ kernel (cokernel.π (f ≫ i.inv.app Y) ≫ (cokernelEpiComp (i.hom.app X) _).inv) :=
      (kernelIsoOfEq (by 

Proof state:
C : Type u₁
inst✝⁷ : Category.{v, u₁} C
inst✝⁶ : Preadditive C
D : Type u₂
inst✝⁵ : Category.{v, u₂} D
inst✝⁴ : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝³ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
inst✝² : HasCokernels C
inst✝¹ : HasKernels C
inst✝ : PreservesFiniteLimits G
X Y : C
f : X ⟶ Y
this✝ : PreservesColimits G
this : ∀ (X' Y' : C) (f' : X' ⟶ Y'), HasCokernel f'
⊢ cokernel.π (i.hom.app X ≫ f ≫ i.inv.app Y) =
    cokernel.π (f ≫ i.inv.app Y) ≫ (cokernelEpiComp (i.hom.app X) (f ≫ i.inv.app Y)).inv

Next tactic:
simp only [cokernel.π_desc, cokernelEpiComp_inv]