l3lab/ntp-mathlib huggingface dataset:
/-- Two morphisms in an exact sequence are exact on pseudoelements. -/
theorem pseudo_exact_of_exact {P Q R : C} {f : P ⟶ Q} {g : Q ⟶ R} (h : Exact f g) :
    (∀ a, g (f a) = 0) ∧ ∀ b, g b = 0 → ∃ a, f a = b :=
  ⟨fun a => by
    rw [← comp_apply, h.w]
    exact zero_apply _ _, fun b' =>
    Quotient.inductionOn b' fun b hb => by
      have hb' : b.hom ≫ g = 0 := (pseudoZero_iff _).1 hb
      -- By exactness, `b` factors through `im f = ker g` via some `c`.
      

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
P Q R : C
f : P ⟶ Q
g : Q ⟶ R
h : Exact f g
b' : Pseudoelement Q
b : Over Q
hb : pseudoApply g ⟦b⟧ = 0
hb' : b.hom ≫ g = 0
⊢ ∃ a, pseudoApply f a = ⟦b⟧

Next tactic:
obtain ⟨c, hc⟩ := KernelFork.IsLimit.lift' (isLimitImage f g h) _ hb'
/-- Two morphisms in an exact sequence are exact on pseudoelements. -/
theorem pseudo_exact_of_exact {P Q R : C} {f : P ⟶ Q} {g : Q ⟶ R} (h : Exact f g) :
    (∀ a, g (f a) = 0) ∧ ∀ b, g b = 0 → ∃ a, f a = b :=
  ⟨fun a => by
    rw [← comp_apply, h.w]
    exact zero_apply _ _, fun b' =>
    Quotient.inductionOn b' fun b hb => by
      have hb' : b.hom ≫ g = 0 := (pseudoZero_iff _).1 hb
      -- By exactness, `b` factors through `im f = ker g` via some `c`.
      obtain ⟨c, hc⟩ := KernelFork.IsLimit.lift' (isLimitImage f g h) _ hb'
      -- We compute the pullback of the map into the image and `c`.
      -- The pseudoelement induced by the first pullback map will be our preimage.
      

Proof state:
case mk
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
P Q R : C
f : P ⟶ Q
g : Q ⟶ R
h : Exact f g
b' : Pseudoelement Q
b : Over Q
hb : pseudoApply g ⟦b⟧ = 0
hb' : b.hom ≫ g = 0
c : (𝟭 C).obj b.left ⟶ (KernelFork.ofι (image.ι f) (_ : image.ι f ≫ g = 0)).pt
hc : c ≫ Fork.ι (KernelFork.ofι (image.ι f) (_ : image.ι f ≫ g = 0)) = b.hom
⊢ ∃ a, pseudoApply f a = ⟦b⟧

Next tactic:
use (pullback.fst : pullback (Abelian.factorThruImage f) c ⟶ P)
/-- Two morphisms in an exact sequence are exact on pseudoelements. -/
theorem pseudo_exact_of_exact {P Q R : C} {f : P ⟶ Q} {g : Q ⟶ R} (h : Exact f g) :
    (∀ a, g (f a) = 0) ∧ ∀ b, g b = 0 → ∃ a, f a = b :=
  ⟨fun a => by
    rw [← comp_apply, h.w]
    exact zero_apply _ _, fun b' =>
    Quotient.inductionOn b' fun b hb => by
      have hb' : b.hom ≫ g = 0 := (pseudoZero_iff _).1 hb
      -- By exactness, `b` factors through `im f = ker g` via some `c`.
      obtain ⟨c, hc⟩ := KernelFork.IsLimit.lift' (isLimitImage f g h) _ hb'
      -- We compute the pullback of the map into the image and `c`.
      -- The pseudoelement induced by the first pullback map will be our preimage.
      use (pullback.fst : pullback (Abelian.factorThruImage f) c ⟶ P)
      -- It remains to show that the image of this element under `f` is pseudo-equal to `b`.
      

Proof state:
case h
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
P Q R : C
f : P ⟶ Q
g : Q ⟶ R
h : Exact f g
b' : Pseudoelement Q
b : Over Q
hb : pseudoApply g ⟦b⟧ = 0
hb' : b.hom ≫ g = 0
c : (𝟭 C).obj b.left ⟶ (KernelFork.ofι (image.ι f) (_ : image.ι f ≫ g = 0)).pt
hc : c ≫ Fork.ι (KernelFork.ofι (image.ι f) (_ : image.ι f ≫ g = 0)) = b.hom
⊢ pseudoApply f (Quot.mk (PseudoEqual P) (Over.mk pullback.fst)) = ⟦b⟧

Next tactic:
apply Quotient.sound
/-- Two morphisms in an exact sequence are exact on pseudoelements. -/
theorem pseudo_exact_of_exact {P Q R : C} {f : P ⟶ Q} {g : Q ⟶ R} (h : Exact f g) :
    (∀ a, g (f a) = 0) ∧ ∀ b, g b = 0 → ∃ a, f a = b :=
  ⟨fun a => by
    rw [← comp_apply, h.w]
    exact zero_apply _ _, fun b' =>
    Quotient.inductionOn b' fun b hb => by
      have hb' : b.hom ≫ g = 0 := (pseudoZero_iff _).1 hb
      -- By exactness, `b` factors through `im f = ker g` via some `c`.
      obtain ⟨c, hc⟩ := KernelFork.IsLimit.lift' (isLimitImage f g h) _ hb'
      -- We compute the pullback of the map into the image and `c`.
      -- The pseudoelement induced by the first pullback map will be our preimage.
      use (pullback.fst : pullback (Abelian.factorThruImage f) c ⟶ P)
      -- It remains to show that the image of this element under `f` is pseudo-equal to `b`.
      apply Quotient.sound
      -- `pullback.snd` is an epimorphism because the map onto the image is!
      

Proof state:
case h.a
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
P Q R : C
f : P ⟶ Q
g : Q ⟶ R
h : Exact f g
b' : Pseudoelement Q
b : Over Q
hb : pseudoApply g ⟦b⟧ = 0
hb' : b.hom ≫ g = 0
c : (𝟭 C).obj b.left ⟶ (KernelFork.ofι (image.ι f) (_ : image.ι f ≫ g = 0)).pt
hc : c ≫ Fork.ι (KernelFork.ofι (image.ι f) (_ : image.ι f ≫ g = 0)) = b.hom
⊢ (fun g => app f g) (Over.mk pullback.fst) ≈ b

Next tactic:
refine'
        ⟨pullback (Abelian.factorThruImage f) c, 𝟙 _, pullback.snd, inferInstance, inferInstance, _⟩
/-- Two morphisms in an exact sequence are exact on pseudoelements. -/
theorem pseudo_exact_of_exact {P Q R : C} {f : P ⟶ Q} {g : Q ⟶ R} (h : Exact f g) :
    (∀ a, g (f a) = 0) ∧ ∀ b, g b = 0 → ∃ a, f a = b :=
  ⟨fun a => by
    rw [← comp_apply, h.w]
    exact zero_apply _ _, fun b' =>
    Quotient.inductionOn b' fun b hb => by
      have hb' : b.hom ≫ g = 0 := (pseudoZero_iff _).1 hb
      -- By exactness, `b` factors through `im f = ker g` via some `c`.
      obtain ⟨c, hc⟩ := KernelFork.IsLimit.lift' (isLimitImage f g h) _ hb'
      -- We compute the pullback of the map into the image and `c`.
      -- The pseudoelement induced by the first pullback map will be our preimage.
      use (pullback.fst : pullback (Abelian.factorThruImage f) c ⟶ P)
      -- It remains to show that the image of this element under `f` is pseudo-equal to `b`.
      apply Quotient.sound
      -- `pullback.snd` is an epimorphism because the map onto the image is!
      refine'
        ⟨pullback (Abelian.factorThruImage f) c, 𝟙 _, pullback.snd, inferInstance, inferInstance, _⟩
      -- Now we can verify that the diagram commutes.
      

Proof state:
case h.a
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
P Q R : C
f : P ⟶ Q
g : Q ⟶ R
h : Exact f g
b' : Pseudoelement Q
b : Over Q
hb : pseudoApply g ⟦b⟧ = 0
hb' : b.hom ≫ g = 0
c : (𝟭 C).obj b.left ⟶ (KernelFork.ofι (image.ι f) (_ : image.ι f ≫ g = 0)).pt
hc : c ≫ Fork.ι (KernelFork.ofι (image.ι f) (_ : image.ι f ≫ g = 0)) = b.hom
⊢ 𝟙 (pullback (Abelian.factorThruImage f) c) ≫ ((fun g => app f g) (Over.mk pullback.fst)).hom = pullback.snd ≫ b.hom

Next tactic:
calc
        𝟙 (pullback (Abelian.factorThruImage f) c) ≫ pullback.fst ≫ f = pullback.fst ≫ f :=
          Category.id_comp _
        _ = pullback.fst ≫ Abelian.factorThruImage f ≫ kernel.ι (cokernel.π f) := by
          rw [Abelian.image.fac]
        _ = (pullback.snd ≫ c) ≫ kernel.ι (cokernel.π f) := by
          rw [← Category.assoc, pullback.condition]
        _ = pullback.snd ≫ b.hom := by
          rw [Category.assoc]
          congr
/-- Two morphisms in an exact sequence are exact on pseudoelements. -/
theorem pseudo_exact_of_exact {P Q R : C} {f : P ⟶ Q} {g : Q ⟶ R} (h : Exact f g) :
    (∀ a, g (f a) = 0) ∧ ∀ b, g b = 0 → ∃ a, f a = b :=
  ⟨fun a => by
    rw [← comp_apply, h.w]
    exact zero_apply _ _, fun b' =>
    Quotient.inductionOn b' fun b hb => by
      have hb' : b.hom ≫ g = 0 := (pseudoZero_iff _).1 hb
      -- By exactness, `b` factors through `im f = ker g` via some `c`.
      obtain ⟨c, hc⟩ := KernelFork.IsLimit.lift' (isLimitImage f g h) _ hb'
      -- We compute the pullback of the map into the image and `c`.
      -- The pseudoelement induced by the first pullback map will be our preimage.
      use (pullback.fst : pullback (Abelian.factorThruImage f) c ⟶ P)
      -- It remains to show that the image of this element under `f` is pseudo-equal to `b`.
      apply Quotient.sound
      -- `pullback.snd` is an epimorphism because the map onto the image is!
      refine'
        ⟨pullback (Abelian.factorThruImage f) c, 𝟙 _, pullback.snd, inferInstance, inferInstance, _⟩
      -- Now we can verify that the diagram commutes.
      calc
        𝟙 (pullback (Abelian.factorThruImage f) c) ≫ pullback.fst ≫ f = pullback.fst ≫ f :=
          Category.id_comp _
        _ = pullback.fst ≫ Abelian.factorThruImage f ≫ kernel.ι (cokernel.π f) := by
          

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
P Q R : C
f : P ⟶ Q
g : Q ⟶ R
h : Exact f g
b' : Pseudoelement Q
b : Over Q
hb : pseudoApply g ⟦b⟧ = 0
hb' : b.hom ≫ g = 0
c : (𝟭 C).obj b.left ⟶ (KernelFork.ofι (image.ι f) (_ : image.ι f ≫ g = 0)).pt
hc : c ≫ Fork.ι (KernelFork.ofι (image.ι f) (_ : image.ι f ≫ g = 0)) = b.hom
⊢ pullback.fst ≫ f = pullback.fst ≫ Abelian.factorThruImage f ≫ kernel.ι (cokernel.π f)

Next tactic:
rw [Abelian.image.fac]
/-- Two morphisms in an exact sequence are exact on pseudoelements. -/
theorem pseudo_exact_of_exact {P Q R : C} {f : P ⟶ Q} {g : Q ⟶ R} (h : Exact f g) :
    (∀ a, g (f a) = 0) ∧ ∀ b, g b = 0 → ∃ a, f a = b :=
  ⟨fun a => by
    rw [← comp_apply, h.w]
    exact zero_apply _ _, fun b' =>
    Quotient.inductionOn b' fun b hb => by
      have hb' : b.hom ≫ g = 0 := (pseudoZero_iff _).1 hb
      -- By exactness, `b` factors through `im f = ker g` via some `c`.
      obtain ⟨c, hc⟩ := KernelFork.IsLimit.lift' (isLimitImage f g h) _ hb'
      -- We compute the pullback of the map into the image and `c`.
      -- The pseudoelement induced by the first pullback map will be our preimage.
      use (pullback.fst : pullback (Abelian.factorThruImage f) c ⟶ P)
      -- It remains to show that the image of this element under `f` is pseudo-equal to `b`.
      apply Quotient.sound
      -- `pullback.snd` is an epimorphism because the map onto the image is!
      refine'
        ⟨pullback (Abelian.factorThruImage f) c, 𝟙 _, pullback.snd, inferInstance, inferInstance, _⟩
      -- Now we can verify that the diagram commutes.
      calc
        𝟙 (pullback (Abelian.factorThruImage f) c) ≫ pullback.fst ≫ f = pullback.fst ≫ f :=
          Category.id_comp _
        _ = pullback.fst ≫ Abelian.factorThruImage f ≫ kernel.ι (cokernel.π f) := by
          rw [Abelian.image.fac]
        _ = (pullback.snd ≫ c) ≫ kernel.ι (cokernel.π f) := by
          

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
P Q R : C
f : P ⟶ Q
g : Q ⟶ R
h : Exact f g
b' : Pseudoelement Q
b : Over Q
hb : pseudoApply g ⟦b⟧ = 0
hb' : b.hom ≫ g = 0
c : (𝟭 C).obj b.left ⟶ (KernelFork.ofι (image.ι f) (_ : image.ι f ≫ g = 0)).pt
hc : c ≫ Fork.ι (KernelFork.ofι (image.ι f) (_ : image.ι f ≫ g = 0)) = b.hom
⊢ pullback.fst ≫ Abelian.factorThruImage f ≫ kernel.ι (cokernel.π f) = (pullback.snd ≫ c) ≫ kernel.ι (cokernel.π f)

Next tactic:
rw [← Category.assoc, pullback.condition]
/-- Two morphisms in an exact sequence are exact on pseudoelements. -/
theorem pseudo_exact_of_exact {P Q R : C} {f : P ⟶ Q} {g : Q ⟶ R} (h : Exact f g) :
    (∀ a, g (f a) = 0) ∧ ∀ b, g b = 0 → ∃ a, f a = b :=
  ⟨fun a => by
    rw [← comp_apply, h.w]
    exact zero_apply _ _, fun b' =>
    Quotient.inductionOn b' fun b hb => by
      have hb' : b.hom ≫ g = 0 := (pseudoZero_iff _).1 hb
      -- By exactness, `b` factors through `im f = ker g` via some `c`.
      obtain ⟨c, hc⟩ := KernelFork.IsLimit.lift' (isLimitImage f g h) _ hb'
      -- We compute the pullback of the map into the image and `c`.
      -- The pseudoelement induced by the first pullback map will be our preimage.
      use (pullback.fst : pullback (Abelian.factorThruImage f) c ⟶ P)
      -- It remains to show that the image of this element under `f` is pseudo-equal to `b`.
      apply Quotient.sound
      -- `pullback.snd` is an epimorphism because the map onto the image is!
      refine'
        ⟨pullback (Abelian.factorThruImage f) c, 𝟙 _, pullback.snd, inferInstance, inferInstance, _⟩
      -- Now we can verify that the diagram commutes.
      calc
        𝟙 (pullback (Abelian.factorThruImage f) c) ≫ pullback.fst ≫ f = pullback.fst ≫ f :=
          Category.id_comp _
        _ = pullback.fst ≫ Abelian.factorThruImage f ≫ kernel.ι (cokernel.π f) := by
          rw [Abelian.image.fac]
        _ = (pullback.snd ≫ c) ≫ kernel.ι (cokernel.π f) := by
          rw [← Category.assoc, pullback.condition]
        _ = pullback.snd ≫ b.hom := by
          

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
P Q R : C
f : P ⟶ Q
g : Q ⟶ R
h : Exact f g
b' : Pseudoelement Q
b : Over Q
hb : pseudoApply g ⟦b⟧ = 0
hb' : b.hom ≫ g = 0
c : (𝟭 C).obj b.left ⟶ (KernelFork.ofι (image.ι f) (_ : image.ι f ≫ g = 0)).pt
hc : c ≫ Fork.ι (KernelFork.ofι (image.ι f) (_ : image.ι f ≫ g = 0)) = b.hom
⊢ (pullback.snd ≫ c) ≫ kernel.ι (cokernel.π f) = pullback.snd ≫ b.hom

Next tactic:
rw [Category.assoc]
/-- Two morphisms in an exact sequence are exact on pseudoelements. -/
theorem pseudo_exact_of_exact {P Q R : C} {f : P ⟶ Q} {g : Q ⟶ R} (h : Exact f g) :
    (∀ a, g (f a) = 0) ∧ ∀ b, g b = 0 → ∃ a, f a = b :=
  ⟨fun a => by
    rw [← comp_apply, h.w]
    exact zero_apply _ _, fun b' =>
    Quotient.inductionOn b' fun b hb => by
      have hb' : b.hom ≫ g = 0 := (pseudoZero_iff _).1 hb
      -- By exactness, `b` factors through `im f = ker g` via some `c`.
      obtain ⟨c, hc⟩ := KernelFork.IsLimit.lift' (isLimitImage f g h) _ hb'
      -- We compute the pullback of the map into the image and `c`.
      -- The pseudoelement induced by the first pullback map will be our preimage.
      use (pullback.fst : pullback (Abelian.factorThruImage f) c ⟶ P)
      -- It remains to show that the image of this element under `f` is pseudo-equal to `b`.
      apply Quotient.sound
      -- `pullback.snd` is an epimorphism because the map onto the image is!
      refine'
        ⟨pullback (Abelian.factorThruImage f) c, 𝟙 _, pullback.snd, inferInstance, inferInstance, _⟩
      -- Now we can verify that the diagram commutes.
      calc
        𝟙 (pullback (Abelian.factorThruImage f) c) ≫ pullback.fst ≫ f = pullback.fst ≫ f :=
          Category.id_comp _
        _ = pullback.fst ≫ Abelian.factorThruImage f ≫ kernel.ι (cokernel.π f) := by
          rw [Abelian.image.fac]
        _ = (pullback.snd ≫ c) ≫ kernel.ι (cokernel.π f) := by
          rw [← Category.assoc, pullback.condition]
        _ = pullback.snd ≫ b.hom := by
          rw [Category.assoc]
          

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
P Q R : C
f : P ⟶ Q
g : Q ⟶ R
h : Exact f g
b' : Pseudoelement Q
b : Over Q
hb : pseudoApply g ⟦b⟧ = 0
hb' : b.hom ≫ g = 0
c : (𝟭 C).obj b.left ⟶ (KernelFork.ofι (image.ι f) (_ : image.ι f ≫ g = 0)).pt
hc : c ≫ Fork.ι (KernelFork.ofι (image.ι f) (_ : image.ι f ≫ g = 0)) = b.hom
⊢ pullback.snd ≫ c ≫ kernel.ι (cokernel.π f) = pullback.snd ≫ b.hom

Next tactic:
congr
theorem apply_eq_zero_of_comp_eq_zero {P Q R : C} (f : Q ⟶ R) (a : P ⟶ Q) : a ≫ f = 0 → f a = 0 :=
  fun h => by 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
P Q R : C
f : Q ⟶ R
a : P ⟶ Q
h : a ≫ f = 0
⊢ pseudoApply f (Quot.mk (PseudoEqual Q) (Over.mk a)) = 0

Next tactic:
simp [over_coe_def, pseudoApply_mk', Over.coe_hom, h]
/-- If two morphisms are exact on pseudoelements, they are exact. -/
theorem exact_of_pseudo_exact {P Q R : C} (f : P ⟶ Q) (g : Q ⟶ R) :
    ((∀ a, g (f a) = 0) ∧ ∀ b, g b = 0 → ∃ a, f a = b) → Exact f g :=
  fun ⟨h₁, h₂⟩ => (Abelian.exact_iff _ _).2
    ⟨zero_morphism_ext _ fun a => by 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
P Q R : C
f : P ⟶ Q
g : Q ⟶ R
x✝ :
  (∀ (a : Pseudoelement P), pseudoApply g (pseudoApply f a) = 0) ∧
    ∀ (b : Pseudoelement Q), pseudoApply g b = 0 → ∃ a, pseudoApply f a = b
h₁ : ∀ (a : Pseudoelement P), pseudoApply g (pseudoApply f a) = 0
h₂ : ∀ (b : Pseudoelement Q), pseudoApply g b = 0 → ∃ a, pseudoApply f a = b
a : Pseudoelement P
⊢ pseudoApply (f ≫ g) a = 0

Next tactic:
rw [comp_apply, h₁ a]
/-- If two morphisms are exact on pseudoelements, they are exact. -/
theorem exact_of_pseudo_exact {P Q R : C} (f : P ⟶ Q) (g : Q ⟶ R) :
    ((∀ a, g (f a) = 0) ∧ ∀ b, g b = 0 → ∃ a, f a = b) → Exact f g :=
  fun ⟨h₁, h₂⟩ => (Abelian.exact_iff _ _).2
    ⟨zero_morphism_ext _ fun a => by rw [comp_apply, h₁ a], by
      -- If we apply `g` to the pseudoelement induced by its kernel, we get 0 (of course!).
      

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
P Q R : C
f : P ⟶ Q
g : Q ⟶ R
x✝ :
  (∀ (a : Pseudoelement P), pseudoApply g (pseudoApply f a) = 0) ∧
    ∀ (b : Pseudoelement Q), pseudoApply g b = 0 → ∃ a, pseudoApply f a = b
h₁ : ∀ (a : Pseudoelement P), pseudoApply g (pseudoApply f a) = 0
h₂ : ∀ (b : Pseudoelement Q), pseudoApply g b = 0 → ∃ a, pseudoApply f a = b
⊢ kernel.ι g ≫ cokernel.π f = 0

Next tactic:
have : g (kernel.ι g) = 0 := apply_eq_zero_of_comp_eq_zero _ _ (kernel.condition _)
/-- If two morphisms are exact on pseudoelements, they are exact. -/
theorem exact_of_pseudo_exact {P Q R : C} (f : P ⟶ Q) (g : Q ⟶ R) :
    ((∀ a, g (f a) = 0) ∧ ∀ b, g b = 0 → ∃ a, f a = b) → Exact f g :=
  fun ⟨h₁, h₂⟩ => (Abelian.exact_iff _ _).2
    ⟨zero_morphism_ext _ fun a => by rw [comp_apply, h₁ a], by
      -- If we apply `g` to the pseudoelement induced by its kernel, we get 0 (of course!).
      have : g (kernel.ι g) = 0 := apply_eq_zero_of_comp_eq_zero _ _ (kernel.condition _)
      -- By pseudo-exactness, we get a preimage.
      

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
P Q R : C
f : P ⟶ Q
g : Q ⟶ R
x✝ :
  (∀ (a : Pseudoelement P), pseudoApply g (pseudoApply f a) = 0) ∧
    ∀ (b : Pseudoelement Q), pseudoApply g b = 0 → ∃ a, pseudoApply f a = b
h₁ : ∀ (a : Pseudoelement P), pseudoApply g (pseudoApply f a) = 0
h₂ : ∀ (b : Pseudoelement Q), pseudoApply g b = 0 → ∃ a, pseudoApply f a = b
this : pseudoApply g (Quot.mk (PseudoEqual Q) (Over.mk (kernel.ι g))) = 0
⊢ kernel.ι g ≫ cokernel.π f = 0

Next tactic:
obtain ⟨a', ha⟩ := h₂ _ this
/-- If two morphisms are exact on pseudoelements, they are exact. -/
theorem exact_of_pseudo_exact {P Q R : C} (f : P ⟶ Q) (g : Q ⟶ R) :
    ((∀ a, g (f a) = 0) ∧ ∀ b, g b = 0 → ∃ a, f a = b) → Exact f g :=
  fun ⟨h₁, h₂⟩ => (Abelian.exact_iff _ _).2
    ⟨zero_morphism_ext _ fun a => by rw [comp_apply, h₁ a], by
      -- If we apply `g` to the pseudoelement induced by its kernel, we get 0 (of course!).
      have : g (kernel.ι g) = 0 := apply_eq_zero_of_comp_eq_zero _ _ (kernel.condition _)
      -- By pseudo-exactness, we get a preimage.
      obtain ⟨a', ha⟩ := h₂ _ this
      

Proof state:
case intro
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
P Q R : C
f : P ⟶ Q
g : Q ⟶ R
x✝ :
  (∀ (a : Pseudoelement P), pseudoApply g (pseudoApply f a) = 0) ∧
    ∀ (b : Pseudoelement Q), pseudoApply g b = 0 → ∃ a, pseudoApply f a = b
h₁ : ∀ (a : Pseudoelement P), pseudoApply g (pseudoApply f a) = 0
h₂ : ∀ (b : Pseudoelement Q), pseudoApply g b = 0 → ∃ a, pseudoApply f a = b
this : pseudoApply g (Quot.mk (PseudoEqual Q) (Over.mk (kernel.ι g))) = 0
a' : Pseudoelement P
ha : pseudoApply f a' = Quot.mk (PseudoEqual Q) (Over.mk (kernel.ι g))
⊢ kernel.ι g ≫ cokernel.π f = 0

Next tactic:
obtain ⟨a, ha'⟩ := Quotient.exists_rep a'
/-- If two morphisms are exact on pseudoelements, they are exact. -/
theorem exact_of_pseudo_exact {P Q R : C} (f : P ⟶ Q) (g : Q ⟶ R) :
    ((∀ a, g (f a) = 0) ∧ ∀ b, g b = 0 → ∃ a, f a = b) → Exact f g :=
  fun ⟨h₁, h₂⟩ => (Abelian.exact_iff _ _).2
    ⟨zero_morphism_ext _ fun a => by rw [comp_apply, h₁ a], by
      -- If we apply `g` to the pseudoelement induced by its kernel, we get 0 (of course!).
      have : g (kernel.ι g) = 0 := apply_eq_zero_of_comp_eq_zero _ _ (kernel.condition _)
      -- By pseudo-exactness, we get a preimage.
      obtain ⟨a', ha⟩ := h₂ _ this
      obtain ⟨a, ha'⟩ := Quotient.exists_rep a'
      

Proof state:
case intro.intro
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
P Q R : C
f : P ⟶ Q
g : Q ⟶ R
x✝ :
  (∀ (a : Pseudoelement P), pseudoApply g (pseudoApply f a) = 0) ∧
    ∀ (b : Pseudoelement Q), pseudoApply g b = 0 → ∃ a, pseudoApply f a = b
h₁ : ∀ (a : Pseudoelement P), pseudoApply g (pseudoApply f a) = 0
h₂ : ∀ (b : Pseudoelement Q), pseudoApply g b = 0 → ∃ a, pseudoApply f a = b
this : pseudoApply g (Quot.mk (PseudoEqual Q) (Over.mk (kernel.ι g))) = 0
a' : Pseudoelement P
ha : pseudoApply f a' = Quot.mk (PseudoEqual Q) (Over.mk (kernel.ι g))
a : Over P
ha' : ⟦a⟧ = a'
⊢ kernel.ι g ≫ cokernel.π f = 0

Next tactic:
rw [← ha'] at ha
/-- If two morphisms are exact on pseudoelements, they are exact. -/
theorem exact_of_pseudo_exact {P Q R : C} (f : P ⟶ Q) (g : Q ⟶ R) :
    ((∀ a, g (f a) = 0) ∧ ∀ b, g b = 0 → ∃ a, f a = b) → Exact f g :=
  fun ⟨h₁, h₂⟩ => (Abelian.exact_iff _ _).2
    ⟨zero_morphism_ext _ fun a => by rw [comp_apply, h₁ a], by
      -- If we apply `g` to the pseudoelement induced by its kernel, we get 0 (of course!).
      have : g (kernel.ι g) = 0 := apply_eq_zero_of_comp_eq_zero _ _ (kernel.condition _)
      -- By pseudo-exactness, we get a preimage.
      obtain ⟨a', ha⟩ := h₂ _ this
      obtain ⟨a, ha'⟩ := Quotient.exists_rep a'
      rw [← ha'] at ha
      

Proof state:
case intro.intro
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
P Q R : C
f : P ⟶ Q
g : Q ⟶ R
x✝ :
  (∀ (a : Pseudoelement P), pseudoApply g (pseudoApply f a) = 0) ∧
    ∀ (b : Pseudoelement Q), pseudoApply g b = 0 → ∃ a, pseudoApply f a = b
h₁ : ∀ (a : Pseudoelement P), pseudoApply g (pseudoApply f a) = 0
h₂ : ∀ (b : Pseudoelement Q), pseudoApply g b = 0 → ∃ a, pseudoApply f a = b
this : pseudoApply g (Quot.mk (PseudoEqual Q) (Over.mk (kernel.ι g))) = 0
a' : Pseudoelement P
a : Over P
ha : pseudoApply f ⟦a⟧ = Quot.mk (PseudoEqual Q) (Over.mk (kernel.ι g))
ha' : ⟦a⟧ = a'
⊢ kernel.ι g ≫ cokernel.π f = 0

Next tactic:
obtain ⟨Z, r, q, _, eq, comm⟩ := Quotient.exact ha
/-- If two morphisms are exact on pseudoelements, they are exact. -/
theorem exact_of_pseudo_exact {P Q R : C} (f : P ⟶ Q) (g : Q ⟶ R) :
    ((∀ a, g (f a) = 0) ∧ ∀ b, g b = 0 → ∃ a, f a = b) → Exact f g :=
  fun ⟨h₁, h₂⟩ => (Abelian.exact_iff _ _).2
    ⟨zero_morphism_ext _ fun a => by rw [comp_apply, h₁ a], by
      -- If we apply `g` to the pseudoelement induced by its kernel, we get 0 (of course!).
      have : g (kernel.ι g) = 0 := apply_eq_zero_of_comp_eq_zero _ _ (kernel.condition _)
      -- By pseudo-exactness, we get a preimage.
      obtain ⟨a', ha⟩ := h₂ _ this
      obtain ⟨a, ha'⟩ := Quotient.exists_rep a'
      rw [← ha'] at ha
      obtain ⟨Z, r, q, _, eq, comm⟩ := Quotient.exact ha
      -- Consider the pullback of `kernel.ι (cokernel.π f)` and `kernel.ι g`.
      -- The commutative diagram given by the pseudo-equality `f a = b` induces
      -- a cone over this pullback, so we get a factorization `z`.
      

Proof state:
case intro.intro.intro.intro.intro.intro.intro
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
P Q R : C
f : P ⟶ Q
g : Q ⟶ R
x✝ :
  (∀ (a : Pseudoelement P), pseudoApply g (pseudoApply f a) = 0) ∧
    ∀ (b : Pseudoelement Q), pseudoApply g b = 0 → ∃ a, pseudoApply f a = b
h₁ : ∀ (a : Pseudoelement P), pseudoApply g (pseudoApply f a) = 0
h₂ : ∀ (b : Pseudoelement Q), pseudoApply g b = 0 → ∃ a, pseudoApply f a = b
this : pseudoApply g (Quot.mk (PseudoEqual Q) (Over.mk (kernel.ι g))) = 0
a' : Pseudoelement P
a : Over P
ha : pseudoApply f ⟦a⟧ = Quot.mk (PseudoEqual Q) (Over.mk (kernel.ι g))
ha' : ⟦a⟧ = a'
Z : C
r : Z ⟶ ((fun g => app f g) a).left
q : Z ⟶ (Over.mk (kernel.ι g)).left
w✝ : Epi r
eq : Epi q
comm : r ≫ ((fun g => app f g) a).hom = q ≫ (Over.mk (kernel.ι g)).hom
⊢ kernel.ι g ≫ cokernel.π f = 0

Next tactic:
obtain ⟨z, _, hz₂⟩ := @pullback.lift' _ _ _ _ _ _ (kernel.ι (cokernel.π f)) (kernel.ι g) _
        (r ≫ a.hom ≫ Abelian.factorThruImage f) q (by
          simp only [Category.assoc, Abelian.image.fac]
          exact comm)