l3lab/ntp-mathlib huggingface dataset:
instance : Mono (homologyCToK f g w) := by
  apply Pseudoelement.mono_of_zero_of_map_zero
  intro a ha
  obtain ⟨a, rfl⟩ := Pseudoelement.pseudo_surjective_of_epi (cokernel.π (kernel.lift g f w)) a
  apply_fun kernel.ι (cokernel.desc f g w) at ha
  simp only [← Pseudoelement.comp_apply, cokernel.π_desc, kernel.lift_ι,
    Pseudoelement.apply_zero] at ha
  simp only [Pseudoelement.comp_apply] at ha
  obtain ⟨b, hb⟩ : ∃ b, f b = _ := (Pseudoelement.pseudo_exact_of_exact (exact_cokernel f)).2 _ ha
  rsuffices ⟨c, rfl⟩ : ∃ c, kernel.lift g f w c = a
  · simp [← Pseudoelement.comp_apply]
  use b
  

Proof state:
case h
A : Type u
inst✝¹ : Category.{v, u} A
inst✝ : Abelian A
X Y Z : A
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
a : Pseudoelement (kernel g)
ha : Pseudoelement.pseudoApply (cokernel.π f) (Pseudoelement.pseudoApply (kernel.ι g) a) = 0
b : Pseudoelement X
hb : Pseudoelement.pseudoApply f b = Pseudoelement.pseudoApply (kernel.ι g) a
⊢ Pseudoelement.pseudoApply (kernel.lift g f w) b = a

Next tactic:
apply_fun kernel.ι g
instance : Mono (homologyCToK f g w) := by
  apply Pseudoelement.mono_of_zero_of_map_zero
  intro a ha
  obtain ⟨a, rfl⟩ := Pseudoelement.pseudo_surjective_of_epi (cokernel.π (kernel.lift g f w)) a
  apply_fun kernel.ι (cokernel.desc f g w) at ha
  simp only [← Pseudoelement.comp_apply, cokernel.π_desc, kernel.lift_ι,
    Pseudoelement.apply_zero] at ha
  simp only [Pseudoelement.comp_apply] at ha
  obtain ⟨b, hb⟩ : ∃ b, f b = _ := (Pseudoelement.pseudo_exact_of_exact (exact_cokernel f)).2 _ ha
  rsuffices ⟨c, rfl⟩ : ∃ c, kernel.lift g f w c = a
  · simp [← Pseudoelement.comp_apply]
  use b
  apply_fun kernel.ι g
  

Proof state:
case h
A : Type u
inst✝¹ : Category.{v, u} A
inst✝ : Abelian A
X Y Z : A
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
a : Pseudoelement (kernel g)
ha : Pseudoelement.pseudoApply (cokernel.π f) (Pseudoelement.pseudoApply (kernel.ι g) a) = 0
b : Pseudoelement X
hb : Pseudoelement.pseudoApply f b = Pseudoelement.pseudoApply (kernel.ι g) a
⊢ Pseudoelement.pseudoApply (kernel.ι g) (Pseudoelement.pseudoApply (kernel.lift g f w) b) =
    Pseudoelement.pseudoApply (kernel.ι g) a
case h.inj
A : Type u
inst✝¹ : Category.{v, u} A
inst✝ : Abelian A
X Y Z : A
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
a : Pseudoelement (kernel g)
ha : Pseudoelement.pseudoApply (cokernel.π f) (Pseudoelement.pseudoApply (kernel.ι g) a) = 0
b : Pseudoelement X
hb : Pseudoelement.pseudoApply f b = Pseudoelement.pseudoApply (kernel.ι g) a
⊢ Function.Injective (Pseudoelement.pseudoApply (kernel.ι g))

Next tactic:
swap
instance : Mono (homologyCToK f g w) := by
  apply Pseudoelement.mono_of_zero_of_map_zero
  intro a ha
  obtain ⟨a, rfl⟩ := Pseudoelement.pseudo_surjective_of_epi (cokernel.π (kernel.lift g f w)) a
  apply_fun kernel.ι (cokernel.desc f g w) at ha
  simp only [← Pseudoelement.comp_apply, cokernel.π_desc, kernel.lift_ι,
    Pseudoelement.apply_zero] at ha
  simp only [Pseudoelement.comp_apply] at ha
  obtain ⟨b, hb⟩ : ∃ b, f b = _ := (Pseudoelement.pseudo_exact_of_exact (exact_cokernel f)).2 _ ha
  rsuffices ⟨c, rfl⟩ : ∃ c, kernel.lift g f w c = a
  · simp [← Pseudoelement.comp_apply]
  use b
  apply_fun kernel.ι g
  swap; · 

Proof state:
case h.inj
A : Type u
inst✝¹ : Category.{v, u} A
inst✝ : Abelian A
X Y Z : A
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
a : Pseudoelement (kernel g)
ha : Pseudoelement.pseudoApply (cokernel.π f) (Pseudoelement.pseudoApply (kernel.ι g) a) = 0
b : Pseudoelement X
hb : Pseudoelement.pseudoApply f b = Pseudoelement.pseudoApply (kernel.ι g) a
⊢ Function.Injective (Pseudoelement.pseudoApply (kernel.ι g))

Next tactic:
apply Pseudoelement.pseudo_injective_of_mono
instance : Mono (homologyCToK f g w) := by
  apply Pseudoelement.mono_of_zero_of_map_zero
  intro a ha
  obtain ⟨a, rfl⟩ := Pseudoelement.pseudo_surjective_of_epi (cokernel.π (kernel.lift g f w)) a
  apply_fun kernel.ι (cokernel.desc f g w) at ha
  simp only [← Pseudoelement.comp_apply, cokernel.π_desc, kernel.lift_ι,
    Pseudoelement.apply_zero] at ha
  simp only [Pseudoelement.comp_apply] at ha
  obtain ⟨b, hb⟩ : ∃ b, f b = _ := (Pseudoelement.pseudo_exact_of_exact (exact_cokernel f)).2 _ ha
  rsuffices ⟨c, rfl⟩ : ∃ c, kernel.lift g f w c = a
  · simp [← Pseudoelement.comp_apply]
  use b
  apply_fun kernel.ι g
  swap; · apply Pseudoelement.pseudo_injective_of_mono
  

Proof state:
case h
A : Type u
inst✝¹ : Category.{v, u} A
inst✝ : Abelian A
X Y Z : A
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
a : Pseudoelement (kernel g)
ha : Pseudoelement.pseudoApply (cokernel.π f) (Pseudoelement.pseudoApply (kernel.ι g) a) = 0
b : Pseudoelement X
hb : Pseudoelement.pseudoApply f b = Pseudoelement.pseudoApply (kernel.ι g) a
⊢ Pseudoelement.pseudoApply (kernel.ι g) (Pseudoelement.pseudoApply (kernel.lift g f w) b) =
    Pseudoelement.pseudoApply (kernel.ι g) a

Next tactic:
simpa [← Pseudoelement.comp_apply]
instance : Epi (homologyCToK f g w) := by
  

Proof state:
A : Type u
inst✝¹ : Category.{v, u} A
inst✝ : Abelian A
X Y Z : A
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
⊢ Epi (homologyCToK f g w)

Next tactic:
apply Pseudoelement.epi_of_pseudo_surjective
instance : Epi (homologyCToK f g w) := by
  apply Pseudoelement.epi_of_pseudo_surjective
  

Proof state:
case a
A : Type u
inst✝¹ : Category.{v, u} A
inst✝ : Abelian A
X Y Z : A
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
⊢ Function.Surjective (Pseudoelement.pseudoApply (homologyCToK f g w))

Next tactic:
intro a
instance : Epi (homologyCToK f g w) := by
  apply Pseudoelement.epi_of_pseudo_surjective
  intro a
  

Proof state:
case a
A : Type u
inst✝¹ : Category.{v, u} A
inst✝ : Abelian A
X Y Z : A
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
a : Pseudoelement (homologyK f g w)
⊢ ∃ a_1, Pseudoelement.pseudoApply (homologyCToK f g w) a_1 = a

Next tactic:
let b := kernel.ι (cokernel.desc f g w) a
instance : Epi (homologyCToK f g w) := by
  apply Pseudoelement.epi_of_pseudo_surjective
  intro a
  let b := kernel.ι (cokernel.desc f g w) a
  

Proof state:
case a
A : Type u
inst✝¹ : Category.{v, u} A
inst✝ : Abelian A
X Y Z : A
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
a : Pseudoelement (homologyK f g w)
b : Pseudoelement (cokernel f) := Pseudoelement.pseudoApply (kernel.ι (cokernel.desc f g w)) a
⊢ ∃ a_1, Pseudoelement.pseudoApply (homologyCToK f g w) a_1 = a

Next tactic:
obtain ⟨c, hc⟩ : ∃ c, cokernel.π f c = b
instance : Epi (homologyCToK f g w) := by
  apply Pseudoelement.epi_of_pseudo_surjective
  intro a
  let b := kernel.ι (cokernel.desc f g w) a
  obtain ⟨c, hc⟩ : ∃ c, cokernel.π f c = b
  

Proof state:
A : Type u
inst✝¹ : Category.{v, u} A
inst✝ : Abelian A
X Y Z : A
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
a : Pseudoelement (homologyK f g w)
b : Pseudoelement (cokernel f) := Pseudoelement.pseudoApply (kernel.ι (cokernel.desc f g w)) a
⊢ ∃ c, Pseudoelement.pseudoApply (cokernel.π f) c = b
case a.intro
A : Type u
inst✝¹ : Category.{v, u} A
inst✝ : Abelian A
X Y Z : A
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
a : Pseudoelement (homologyK f g w)
b : Pseudoelement (cokernel f) := Pseudoelement.pseudoApply (kernel.ι (cokernel.desc f g w)) a
c : Pseudoelement Y
hc : Pseudoelement.pseudoApply (cokernel.π f) c = b
⊢ ∃ a_1, Pseudoelement.pseudoApply (homologyCToK f g w) a_1 = a

Next tactic:
apply Pseudoelement.pseudo_surjective_of_epi (cokernel.π f)
instance : Epi (homologyCToK f g w) := by
  apply Pseudoelement.epi_of_pseudo_surjective
  intro a
  let b := kernel.ι (cokernel.desc f g w) a
  obtain ⟨c, hc⟩ : ∃ c, cokernel.π f c = b
  apply Pseudoelement.pseudo_surjective_of_epi (cokernel.π f)
  

Proof state:
case a.intro
A : Type u
inst✝¹ : Category.{v, u} A
inst✝ : Abelian A
X Y Z : A
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
a : Pseudoelement (homologyK f g w)
b : Pseudoelement (cokernel f) := Pseudoelement.pseudoApply (kernel.ι (cokernel.desc f g w)) a
c : Pseudoelement Y
hc : Pseudoelement.pseudoApply (cokernel.π f) c = b
⊢ ∃ a_1, Pseudoelement.pseudoApply (homologyCToK f g w) a_1 = a

Next tactic:
have : g c = 0 := by
    rw [show g = cokernel.π f ≫ cokernel.desc f g w by simp, Pseudoelement.comp_apply, hc]
    simp [← Pseudoelement.comp_apply]
instance : Epi (homologyCToK f g w) := by
  apply Pseudoelement.epi_of_pseudo_surjective
  intro a
  let b := kernel.ι (cokernel.desc f g w) a
  obtain ⟨c, hc⟩ : ∃ c, cokernel.π f c = b
  apply Pseudoelement.pseudo_surjective_of_epi (cokernel.π f)
  have : g c = 0 := by
    

Proof state:
A : Type u
inst✝¹ : Category.{v, u} A
inst✝ : Abelian A
X Y Z : A
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
a : Pseudoelement (homologyK f g w)
b : Pseudoelement (cokernel f) := Pseudoelement.pseudoApply (kernel.ι (cokernel.desc f g w)) a
c : Pseudoelement Y
hc : Pseudoelement.pseudoApply (cokernel.π f) c = b
⊢ Pseudoelement.pseudoApply g c = 0

Next tactic:
rw [show g = cokernel.π f ≫ cokernel.desc f g w by simp, Pseudoelement.comp_apply, hc]
instance : Epi (homologyCToK f g w) := by
  apply Pseudoelement.epi_of_pseudo_surjective
  intro a
  let b := kernel.ι (cokernel.desc f g w) a
  obtain ⟨c, hc⟩ : ∃ c, cokernel.π f c = b
  apply Pseudoelement.pseudo_surjective_of_epi (cokernel.π f)
  have : g c = 0 := by
    rw [show g = cokernel.π f ≫ cokernel.desc f g w by 

Proof state:
A : Type u
inst✝¹ : Category.{v, u} A
inst✝ : Abelian A
X Y Z : A
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
a : Pseudoelement (homologyK f g w)
b : Pseudoelement (cokernel f) := Pseudoelement.pseudoApply (kernel.ι (cokernel.desc f g w)) a
c : Pseudoelement Y
hc : Pseudoelement.pseudoApply (cokernel.π f) c = b
⊢ g = cokernel.π f ≫ cokernel.desc f g w

Next tactic:
simp
instance : Epi (homologyCToK f g w) := by
  apply Pseudoelement.epi_of_pseudo_surjective
  intro a
  let b := kernel.ι (cokernel.desc f g w) a
  obtain ⟨c, hc⟩ : ∃ c, cokernel.π f c = b
  apply Pseudoelement.pseudo_surjective_of_epi (cokernel.π f)
  have : g c = 0 := by
    rw [show g = cokernel.π f ≫ cokernel.desc f g w by simp, Pseudoelement.comp_apply, hc]
    

Proof state:
A : Type u
inst✝¹ : Category.{v, u} A
inst✝ : Abelian A
X Y Z : A
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
a : Pseudoelement (homologyK f g w)
b : Pseudoelement (cokernel f) := Pseudoelement.pseudoApply (kernel.ι (cokernel.desc f g w)) a
c : Pseudoelement Y
hc : Pseudoelement.pseudoApply (cokernel.π f) c = b
⊢ Pseudoelement.pseudoApply (cokernel.desc f g w) b = 0

Next tactic:
simp [← Pseudoelement.comp_apply]
instance : Epi (homologyCToK f g w) := by
  apply Pseudoelement.epi_of_pseudo_surjective
  intro a
  let b := kernel.ι (cokernel.desc f g w) a
  obtain ⟨c, hc⟩ : ∃ c, cokernel.π f c = b
  apply Pseudoelement.pseudo_surjective_of_epi (cokernel.π f)
  have : g c = 0 := by
    rw [show g = cokernel.π f ≫ cokernel.desc f g w by simp, Pseudoelement.comp_apply, hc]
    simp [← Pseudoelement.comp_apply]
  

Proof state:
case a.intro
A : Type u
inst✝¹ : Category.{v, u} A
inst✝ : Abelian A
X Y Z : A
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
a : Pseudoelement (homologyK f g w)
b : Pseudoelement (cokernel f) := Pseudoelement.pseudoApply (kernel.ι (cokernel.desc f g w)) a
c : Pseudoelement Y
hc : Pseudoelement.pseudoApply (cokernel.π f) c = b
this : Pseudoelement.pseudoApply g c = 0
⊢ ∃ a_1, Pseudoelement.pseudoApply (homologyCToK f g w) a_1 = a

Next tactic:
obtain ⟨d, hd⟩ : ∃ d, kernel.ι g d = c := by
    apply (Pseudoelement.pseudo_exact_of_exact exact_kernel_ι).2 _ this
instance : Epi (homologyCToK f g w) := by
  apply Pseudoelement.epi_of_pseudo_surjective
  intro a
  let b := kernel.ι (cokernel.desc f g w) a
  obtain ⟨c, hc⟩ : ∃ c, cokernel.π f c = b
  apply Pseudoelement.pseudo_surjective_of_epi (cokernel.π f)
  have : g c = 0 := by
    rw [show g = cokernel.π f ≫ cokernel.desc f g w by simp, Pseudoelement.comp_apply, hc]
    simp [← Pseudoelement.comp_apply]
  obtain ⟨d, hd⟩ : ∃ d, kernel.ι g d = c := by
    

Proof state:
A : Type u
inst✝¹ : Category.{v, u} A
inst✝ : Abelian A
X Y Z : A
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
a : Pseudoelement (homologyK f g w)
b : Pseudoelement (cokernel f) := Pseudoelement.pseudoApply (kernel.ι (cokernel.desc f g w)) a
c : Pseudoelement Y
hc : Pseudoelement.pseudoApply (cokernel.π f) c = b
this : Pseudoelement.pseudoApply g c = 0
⊢ ∃ d, Pseudoelement.pseudoApply (kernel.ι g) d = c

Next tactic:
apply (Pseudoelement.pseudo_exact_of_exact exact_kernel_ι).2 _ this
instance : Epi (homologyCToK f g w) := by
  apply Pseudoelement.epi_of_pseudo_surjective
  intro a
  let b := kernel.ι (cokernel.desc f g w) a
  obtain ⟨c, hc⟩ : ∃ c, cokernel.π f c = b
  apply Pseudoelement.pseudo_surjective_of_epi (cokernel.π f)
  have : g c = 0 := by
    rw [show g = cokernel.π f ≫ cokernel.desc f g w by simp, Pseudoelement.comp_apply, hc]
    simp [← Pseudoelement.comp_apply]
  obtain ⟨d, hd⟩ : ∃ d, kernel.ι g d = c := by
    apply (Pseudoelement.pseudo_exact_of_exact exact_kernel_ι).2 _ this
  

Proof state:
case a.intro.intro
A : Type u
inst✝¹ : Category.{v, u} A
inst✝ : Abelian A
X Y Z : A
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
a : Pseudoelement (homologyK f g w)
b : Pseudoelement (cokernel f) := Pseudoelement.pseudoApply (kernel.ι (cokernel.desc f g w)) a
c : Pseudoelement Y
hc : Pseudoelement.pseudoApply (cokernel.π f) c = b
this : Pseudoelement.pseudoApply g c = 0
d : Pseudoelement (kernel g)
hd : Pseudoelement.pseudoApply (kernel.ι g) d = c
⊢ ∃ a_1, Pseudoelement.pseudoApply (homologyCToK f g w) a_1 = a

Next tactic:
use cokernel.π (kernel.lift g f w) d
instance : Epi (homologyCToK f g w) := by
  apply Pseudoelement.epi_of_pseudo_surjective
  intro a
  let b := kernel.ι (cokernel.desc f g w) a
  obtain ⟨c, hc⟩ : ∃ c, cokernel.π f c = b
  apply Pseudoelement.pseudo_surjective_of_epi (cokernel.π f)
  have : g c = 0 := by
    rw [show g = cokernel.π f ≫ cokernel.desc f g w by simp, Pseudoelement.comp_apply, hc]
    simp [← Pseudoelement.comp_apply]
  obtain ⟨d, hd⟩ : ∃ d, kernel.ι g d = c := by
    apply (Pseudoelement.pseudo_exact_of_exact exact_kernel_ι).2 _ this
  use cokernel.π (kernel.lift g f w) d
  

Proof state:
case h
A : Type u
inst✝¹ : Category.{v, u} A
inst✝ : Abelian A
X Y Z : A
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
a : Pseudoelement (homologyK f g w)
b : Pseudoelement (cokernel f) := Pseudoelement.pseudoApply (kernel.ι (cokernel.desc f g w)) a
c : Pseudoelement Y
hc : Pseudoelement.pseudoApply (cokernel.π f) c = b
this : Pseudoelement.pseudoApply g c = 0
d : Pseudoelement (kernel g)
hd : Pseudoelement.pseudoApply (kernel.ι g) d = c
⊢ Pseudoelement.pseudoApply (homologyCToK f g w) (Pseudoelement.pseudoApply (cokernel.π (kernel.lift g f w)) d) = a

Next tactic:
apply_fun kernel.ι (cokernel.desc f g w)
instance : Epi (homologyCToK f g w) := by
  apply Pseudoelement.epi_of_pseudo_surjective
  intro a
  let b := kernel.ι (cokernel.desc f g w) a
  obtain ⟨c, hc⟩ : ∃ c, cokernel.π f c = b
  apply Pseudoelement.pseudo_surjective_of_epi (cokernel.π f)
  have : g c = 0 := by
    rw [show g = cokernel.π f ≫ cokernel.desc f g w by simp, Pseudoelement.comp_apply, hc]
    simp [← Pseudoelement.comp_apply]
  obtain ⟨d, hd⟩ : ∃ d, kernel.ι g d = c := by
    apply (Pseudoelement.pseudo_exact_of_exact exact_kernel_ι).2 _ this
  use cokernel.π (kernel.lift g f w) d
  apply_fun kernel.ι (cokernel.desc f g w)
  

Proof state:
case h
A : Type u
inst✝¹ : Category.{v, u} A
inst✝ : Abelian A
X Y Z : A
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
a : Pseudoelement (homologyK f g w)
b : Pseudoelement (cokernel f) := Pseudoelement.pseudoApply (kernel.ι (cokernel.desc f g w)) a
c : Pseudoelement Y
hc : Pseudoelement.pseudoApply (cokernel.π f) c = b
this : Pseudoelement.pseudoApply g c = 0
d : Pseudoelement (kernel g)
hd : Pseudoelement.pseudoApply (kernel.ι g) d = c
⊢ Pseudoelement.pseudoApply (kernel.ι (cokernel.desc f g w))
      (Pseudoelement.pseudoApply (homologyCToK f g w) (Pseudoelement.pseudoApply (cokernel.π (kernel.lift g f w)) d)) =
    Pseudoelement.pseudoApply (kernel.ι (cokernel.desc f g w)) a
case h.inj
A : Type u
inst✝¹ : Category.{v, u} A
inst✝ : Abelian A
X Y Z : A
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
a : Pseudoelement (homologyK f g w)
b : Pseudoelement (cokernel f) := Pseudoelement.pseudoApply (kernel.ι (cokernel.desc f g w)) a
c : Pseudoelement Y
hc : Pseudoelement.pseudoApply (cokernel.π f) c = b
this : Pseudoelement.pseudoApply g c = 0
d : Pseudoelement (kernel g)
hd : Pseudoelement.pseudoApply (kernel.ι g) d = c
⊢ Function.Injective (Pseudoelement.pseudoApply (kernel.ι (cokernel.desc f g w)))

Next tactic:
swap
instance : Epi (homologyCToK f g w) := by
  apply Pseudoelement.epi_of_pseudo_surjective
  intro a
  let b := kernel.ι (cokernel.desc f g w) a
  obtain ⟨c, hc⟩ : ∃ c, cokernel.π f c = b
  apply Pseudoelement.pseudo_surjective_of_epi (cokernel.π f)
  have : g c = 0 := by
    rw [show g = cokernel.π f ≫ cokernel.desc f g w by simp, Pseudoelement.comp_apply, hc]
    simp [← Pseudoelement.comp_apply]
  obtain ⟨d, hd⟩ : ∃ d, kernel.ι g d = c := by
    apply (Pseudoelement.pseudo_exact_of_exact exact_kernel_ι).2 _ this
  use cokernel.π (kernel.lift g f w) d
  apply_fun kernel.ι (cokernel.desc f g w)
  swap
  · 

Proof state:
case h.inj
A : Type u
inst✝¹ : Category.{v, u} A
inst✝ : Abelian A
X Y Z : A
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
a : Pseudoelement (homologyK f g w)
b : Pseudoelement (cokernel f) := Pseudoelement.pseudoApply (kernel.ι (cokernel.desc f g w)) a
c : Pseudoelement Y
hc : Pseudoelement.pseudoApply (cokernel.π f) c = b
this : Pseudoelement.pseudoApply g c = 0
d : Pseudoelement (kernel g)
hd : Pseudoelement.pseudoApply (kernel.ι g) d = c
⊢ Function.Injective (Pseudoelement.pseudoApply (kernel.ι (cokernel.desc f g w)))

Next tactic:
apply Pseudoelement.pseudo_injective_of_mono
instance : Epi (homologyCToK f g w) := by
  apply Pseudoelement.epi_of_pseudo_surjective
  intro a
  let b := kernel.ι (cokernel.desc f g w) a
  obtain ⟨c, hc⟩ : ∃ c, cokernel.π f c = b
  apply Pseudoelement.pseudo_surjective_of_epi (cokernel.π f)
  have : g c = 0 := by
    rw [show g = cokernel.π f ≫ cokernel.desc f g w by simp, Pseudoelement.comp_apply, hc]
    simp [← Pseudoelement.comp_apply]
  obtain ⟨d, hd⟩ : ∃ d, kernel.ι g d = c := by
    apply (Pseudoelement.pseudo_exact_of_exact exact_kernel_ι).2 _ this
  use cokernel.π (kernel.lift g f w) d
  apply_fun kernel.ι (cokernel.desc f g w)
  swap
  · apply Pseudoelement.pseudo_injective_of_mono
  

Proof state:
case h
A : Type u
inst✝¹ : Category.{v, u} A
inst✝ : Abelian A
X Y Z : A
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
a : Pseudoelement (homologyK f g w)
b : Pseudoelement (cokernel f) := Pseudoelement.pseudoApply (kernel.ι (cokernel.desc f g w)) a
c : Pseudoelement Y
hc : Pseudoelement.pseudoApply (cokernel.π f) c = b
this : Pseudoelement.pseudoApply g c = 0
d : Pseudoelement (kernel g)
hd : Pseudoelement.pseudoApply (kernel.ι g) d = c
⊢ Pseudoelement.pseudoApply (kernel.ι (cokernel.desc f g w))
      (Pseudoelement.pseudoApply (homologyCToK f g w) (Pseudoelement.pseudoApply (cokernel.π (kernel.lift g f w)) d)) =
    Pseudoelement.pseudoApply (kernel.ι (cokernel.desc f g w)) a

Next tactic:
simp only [← Pseudoelement.comp_apply, cokernel.π_desc, kernel.lift_ι]
instance : Epi (homologyCToK f g w) := by
  apply Pseudoelement.epi_of_pseudo_surjective
  intro a
  let b := kernel.ι (cokernel.desc f g w) a
  obtain ⟨c, hc⟩ : ∃ c, cokernel.π f c = b
  apply Pseudoelement.pseudo_surjective_of_epi (cokernel.π f)
  have : g c = 0 := by
    rw [show g = cokernel.π f ≫ cokernel.desc f g w by simp, Pseudoelement.comp_apply, hc]
    simp [← Pseudoelement.comp_apply]
  obtain ⟨d, hd⟩ : ∃ d, kernel.ι g d = c := by
    apply (Pseudoelement.pseudo_exact_of_exact exact_kernel_ι).2 _ this
  use cokernel.π (kernel.lift g f w) d
  apply_fun kernel.ι (cokernel.desc f g w)
  swap
  · apply Pseudoelement.pseudo_injective_of_mono
  simp only [← Pseudoelement.comp_apply, cokernel.π_desc, kernel.lift_ι]
  

Proof state:
case h
A : Type u
inst✝¹ : Category.{v, u} A
inst✝ : Abelian A
X Y Z : A
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
a : Pseudoelement (homologyK f g w)
b : Pseudoelement (cokernel f) := Pseudoelement.pseudoApply (kernel.ι (cokernel.desc f g w)) a
c : Pseudoelement Y
hc : Pseudoelement.pseudoApply (cokernel.π f) c = b
this : Pseudoelement.pseudoApply g c = 0
d : Pseudoelement (kernel g)
hd : Pseudoelement.pseudoApply (kernel.ι g) d = c
⊢ Pseudoelement.pseudoApply (kernel.ι g ≫ cokernel.π f) d = Pseudoelement.pseudoApply (kernel.ι (cokernel.desc f g w)) a

Next tactic:
simp only [Pseudoelement.comp_apply, hd, hc]
@[reassoc (attr := simp)]
theorem π'_desc' {W : A} (e : kernel g ⟶ W) (he : kernel.lift g f w ≫ e = 0) :
    π' f g w ≫ desc' f g w e he = e := by
  

Proof state:
A : Type u
inst✝¹ : Category.{v, u} A
inst✝ : Abelian A
X Y Z : A
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
W : A
e : kernel g ⟶ W
he : kernel.lift g f w ≫ e = 0
⊢ π' f g w ≫ desc' f g w e he = e

Next tactic:
dsimp [π', desc']
@[reassoc (attr := simp)]
theorem π'_desc' {W : A} (e : kernel g ⟶ W) (he : kernel.lift g f w ≫ e = 0) :
    π' f g w ≫ desc' f g w e he = e := by
  dsimp [π', desc']
  

Proof state:
A : Type u
inst✝¹ : Category.{v, u} A
inst✝ : Abelian A
X Y Z : A
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
W : A
e : kernel g ⟶ W
he : kernel.lift g f w ≫ e = 0
⊢ (cokernel.π (kernel.lift g f w) ≫ (homology'IsoCokernelLift f g w).inv) ≫
      (homology'IsoCokernelLift f g w).hom ≫ cokernel.desc (kernel.lift g f w) e he =
    e

Next tactic:
simp
@[reassoc (attr := simp)]
theorem lift_ι {W : A} (e : W ⟶ cokernel f) (he : e ≫ cokernel.desc f g w = 0) :
    lift f g w e he ≫ ι _ _ _ = e := by
  

Proof state:
A : Type u
inst✝¹ : Category.{v, u} A
inst✝ : Abelian A
X Y Z : A
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
W : A
e : W ⟶ cokernel f
he : e ≫ cokernel.desc f g w = 0
⊢ lift f g w e he ≫ ι f g w = e

Next tactic:
dsimp [ι, lift]
@[reassoc (attr := simp)]
theorem lift_ι {W : A} (e : W ⟶ cokernel f) (he : e ≫ cokernel.desc f g w = 0) :
    lift f g w e he ≫ ι _ _ _ = e := by
  dsimp [ι, lift]
  

Proof state:
A : Type u
inst✝¹ : Category.{v, u} A
inst✝ : Abelian A
X Y Z : A
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
W : A
e : W ⟶ cokernel f
he : e ≫ cokernel.desc f g w = 0
⊢ (kernel.lift (cokernel.desc f g w) e he ≫ (homology'IsoKernelDesc f g w).inv) ≫
      (homology'IsoKernelDesc f g w).hom ≫ kernel.ι (cokernel.desc f g w) =
    e

Next tactic:
simp
@[reassoc (attr := simp)]
theorem condition_π' : kernel.lift g f w ≫ π' f g w = 0 := by
  

Proof state:
A : Type u
inst✝¹ : Category.{v, u} A
inst✝ : Abelian A
X Y Z : A
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
⊢ kernel.lift g f w ≫ π' f g w = 0

Next tactic:
dsimp [π']
@[reassoc (attr := simp)]
theorem condition_π' : kernel.lift g f w ≫ π' f g w = 0 := by
  dsimp [π']
  

Proof state:
A : Type u
inst✝¹ : Category.{v, u} A
inst✝ : Abelian A
X Y Z : A
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
⊢ kernel.lift g f w ≫ cokernel.π (kernel.lift g f w) ≫ (homology'IsoCokernelLift f g w).inv = 0

Next tactic:
simp
@[reassoc (attr := simp)]
theorem condition_ι : ι f g w ≫ cokernel.desc f g w = 0 := by
  

Proof state:
A : Type u
inst✝¹ : Category.{v, u} A
inst✝ : Abelian A
X Y Z : A
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
⊢ ι f g w ≫ cokernel.desc f g w = 0

Next tactic:
dsimp [ι]
@[reassoc (attr := simp)]
theorem condition_ι : ι f g w ≫ cokernel.desc f g w = 0 := by
  dsimp [ι]
  

Proof state:
A : Type u
inst✝¹ : Category.{v, u} A
inst✝ : Abelian A
X Y Z : A
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
⊢ ((homology'IsoKernelDesc f g w).hom ≫ kernel.ι (cokernel.desc f g w)) ≫ cokernel.desc f g w = 0

Next tactic:
simp
@[ext]
theorem hom_from_ext {W : A} (a b : homology' f g w ⟶ W)
    (h : π' f g w ≫ a = π' f g w ≫ b) : a = b := by
  

Proof state:
A : Type u
inst✝¹ : Category.{v, u} A
inst✝ : Abelian A
X Y Z : A
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
W : A
a b : homology' f g w ⟶ W
h : π' f g w ≫ a = π' f g w ≫ b
⊢ a = b

Next tactic:
dsimp [π'] at h
@[ext]
theorem hom_from_ext {W : A} (a b : homology' f g w ⟶ W)
    (h : π' f g w ≫ a = π' f g w ≫ b) : a = b := by
  dsimp [π'] at h
  

Proof state:
A : Type u
inst✝¹ : Category.{v, u} A
inst✝ : Abelian A
X Y Z : A
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
W : A
a b : homology' f g w ⟶ W
h :
  (cokernel.π (kernel.lift g f w) ≫ (homology'IsoCokernelLift f g w).inv) ≫ a =
    (cokernel.π (kernel.lift g f w) ≫ (homology'IsoCokernelLift f g w).inv) ≫ b
⊢ a = b

Next tactic:
apply_fun fun e => (homology'IsoCokernelLift f g w).inv ≫ e