l3lab/ntp-mathlib huggingface dataset:
/-- Given a morphism of short complexes `φ : S₁ ⟶ S₂` in an abelian category, if `S₁.g = 0`
(e.g when `S₁` is of the form `S₁.X₁ ⟶ S₁.X₂ ⟶ 0`) and both `S₂.f` and `S₂.g` are zero
(e.g when `S₂` is of the form `0 ⟶ S₂.X₂ ⟶ 0`), then `φ` is a quasi-isomorphism iff
the obvious short complex `S₁.X₂ ⟶ S₁.X₂ ⟶ S₂.X₂` is exact and `φ.τ₂` is an epi). -/
lemma quasiIso_iff_of_zeros' {S₁ S₂ : ShortComplex C} (φ : S₁ ⟶ S₂)
    (hg₁ : S₁.g = 0) (hf₂ : S₂.f = 0) (hg₂ : S₂.g = 0) :
    QuasiIso φ ↔
      (ShortComplex.mk S₁.f φ.τ₂ (by rw [← φ.comm₁₂, hf₂, comp_zero])).Exact ∧ Epi φ.τ₂ := by
  rw [← quasiIso_opMap_iff, quasiIso_iff_of_zeros]
  

Proof state:
C : Type u_1
D : Type u_2
inst✝² : Category.{u_3, u_1} C
inst✝¹ : Category.{?u.257008, u_2} D
inst✝ : Abelian C
S₁ S₂ : ShortComplex C
φ : S₁ ⟶ S₂
hg₁ : S₁.g = 0
hf₂ : S₂.f = 0
hg₂ : S₂.g = 0
⊢ Exact (mk (opMap φ).τ₂ (op S₁).g (_ : (opMap φ).τ₂ ≫ (op S₁).g = 0)) ∧ Mono (opMap φ).τ₂ ↔
    Exact (mk S₁.f φ.τ₂ (_ : S₁.f ≫ φ.τ₂ = 0)) ∧ Epi φ.τ₂
case hf₁
C : Type u_1
D : Type u_2
inst✝² : Category.{u_3, u_1} C
inst✝¹ : Category.{?u.257008, u_2} D
inst✝ : Abelian C
S₁ S₂ : ShortComplex C
φ : S₁ ⟶ S₂
hg₁ : S₁.g = 0
hf₂ : S₂.f = 0
hg₂ : S₂.g = 0
⊢ (op S₂).f = 0
case hg₁
C : Type u_1
D : Type u_2
inst✝² : Category.{u_3, u_1} C
inst✝¹ : Category.{?u.257008, u_2} D
inst✝ : Abelian C
S₁ S₂ : ShortComplex C
φ : S₁ ⟶ S₂
hg₁ : S₁.g = 0
hf₂ : S₂.f = 0
hg₂ : S₂.g = 0
⊢ (op S₂).g = 0
case hf₂
C : Type u_1
D : Type u_2
inst✝² : Category.{u_3, u_1} C
inst✝¹ : Category.{?u.257008, u_2} D
inst✝ : Abelian C
S₁ S₂ : ShortComplex C
φ : S₁ ⟶ S₂
hg₁ : S₁.g = 0
hf₂ : S₂.f = 0
hg₂ : S₂.g = 0
⊢ (op S₁).f = 0

Next tactic:
rotate_left
/-- Given a morphism of short complexes `φ : S₁ ⟶ S₂` in an abelian category, if `S₁.g = 0`
(e.g when `S₁` is of the form `S₁.X₁ ⟶ S₁.X₂ ⟶ 0`) and both `S₂.f` and `S₂.g` are zero
(e.g when `S₂` is of the form `0 ⟶ S₂.X₂ ⟶ 0`), then `φ` is a quasi-isomorphism iff
the obvious short complex `S₁.X₂ ⟶ S₁.X₂ ⟶ S₂.X₂` is exact and `φ.τ₂` is an epi). -/
lemma quasiIso_iff_of_zeros' {S₁ S₂ : ShortComplex C} (φ : S₁ ⟶ S₂)
    (hg₁ : S₁.g = 0) (hf₂ : S₂.f = 0) (hg₂ : S₂.g = 0) :
    QuasiIso φ ↔
      (ShortComplex.mk S₁.f φ.τ₂ (by rw [← φ.comm₁₂, hf₂, comp_zero])).Exact ∧ Epi φ.τ₂ := by
  rw [← quasiIso_opMap_iff, quasiIso_iff_of_zeros]
  rotate_left
  · 

Proof state:
case hf₁
C : Type u_1
D : Type u_2
inst✝² : Category.{u_3, u_1} C
inst✝¹ : Category.{?u.257008, u_2} D
inst✝ : Abelian C
S₁ S₂ : ShortComplex C
φ : S₁ ⟶ S₂
hg₁ : S₁.g = 0
hf₂ : S₂.f = 0
hg₂ : S₂.g = 0
⊢ (op S₂).f = 0

Next tactic:
dsimp
/-- Given a morphism of short complexes `φ : S₁ ⟶ S₂` in an abelian category, if `S₁.g = 0`
(e.g when `S₁` is of the form `S₁.X₁ ⟶ S₁.X₂ ⟶ 0`) and both `S₂.f` and `S₂.g` are zero
(e.g when `S₂` is of the form `0 ⟶ S₂.X₂ ⟶ 0`), then `φ` is a quasi-isomorphism iff
the obvious short complex `S₁.X₂ ⟶ S₁.X₂ ⟶ S₂.X₂` is exact and `φ.τ₂` is an epi). -/
lemma quasiIso_iff_of_zeros' {S₁ S₂ : ShortComplex C} (φ : S₁ ⟶ S₂)
    (hg₁ : S₁.g = 0) (hf₂ : S₂.f = 0) (hg₂ : S₂.g = 0) :
    QuasiIso φ ↔
      (ShortComplex.mk S₁.f φ.τ₂ (by rw [← φ.comm₁₂, hf₂, comp_zero])).Exact ∧ Epi φ.τ₂ := by
  rw [← quasiIso_opMap_iff, quasiIso_iff_of_zeros]
  rotate_left
  · dsimp
    

Proof state:
case hf₁
C : Type u_1
D : Type u_2
inst✝² : Category.{u_3, u_1} C
inst✝¹ : Category.{?u.257008, u_2} D
inst✝ : Abelian C
S₁ S₂ : ShortComplex C
φ : S₁ ⟶ S₂
hg₁ : S₁.g = 0
hf₂ : S₂.f = 0
hg₂ : S₂.g = 0
⊢ S₂.g.op = 0

Next tactic:
rw [hg₂, op_zero]
/-- Given a morphism of short complexes `φ : S₁ ⟶ S₂` in an abelian category, if `S₁.g = 0`
(e.g when `S₁` is of the form `S₁.X₁ ⟶ S₁.X₂ ⟶ 0`) and both `S₂.f` and `S₂.g` are zero
(e.g when `S₂` is of the form `0 ⟶ S₂.X₂ ⟶ 0`), then `φ` is a quasi-isomorphism iff
the obvious short complex `S₁.X₂ ⟶ S₁.X₂ ⟶ S₂.X₂` is exact and `φ.τ₂` is an epi). -/
lemma quasiIso_iff_of_zeros' {S₁ S₂ : ShortComplex C} (φ : S₁ ⟶ S₂)
    (hg₁ : S₁.g = 0) (hf₂ : S₂.f = 0) (hg₂ : S₂.g = 0) :
    QuasiIso φ ↔
      (ShortComplex.mk S₁.f φ.τ₂ (by rw [← φ.comm₁₂, hf₂, comp_zero])).Exact ∧ Epi φ.τ₂ := by
  rw [← quasiIso_opMap_iff, quasiIso_iff_of_zeros]
  rotate_left
  · dsimp
    rw [hg₂, op_zero]
  · 

Proof state:
case hg₁
C : Type u_1
D : Type u_2
inst✝² : Category.{u_3, u_1} C
inst✝¹ : Category.{?u.257008, u_2} D
inst✝ : Abelian C
S₁ S₂ : ShortComplex C
φ : S₁ ⟶ S₂
hg₁ : S₁.g = 0
hf₂ : S₂.f = 0
hg₂ : S₂.g = 0
⊢ (op S₂).g = 0

Next tactic:
dsimp
/-- Given a morphism of short complexes `φ : S₁ ⟶ S₂` in an abelian category, if `S₁.g = 0`
(e.g when `S₁` is of the form `S₁.X₁ ⟶ S₁.X₂ ⟶ 0`) and both `S₂.f` and `S₂.g` are zero
(e.g when `S₂` is of the form `0 ⟶ S₂.X₂ ⟶ 0`), then `φ` is a quasi-isomorphism iff
the obvious short complex `S₁.X₂ ⟶ S₁.X₂ ⟶ S₂.X₂` is exact and `φ.τ₂` is an epi). -/
lemma quasiIso_iff_of_zeros' {S₁ S₂ : ShortComplex C} (φ : S₁ ⟶ S₂)
    (hg₁ : S₁.g = 0) (hf₂ : S₂.f = 0) (hg₂ : S₂.g = 0) :
    QuasiIso φ ↔
      (ShortComplex.mk S₁.f φ.τ₂ (by rw [← φ.comm₁₂, hf₂, comp_zero])).Exact ∧ Epi φ.τ₂ := by
  rw [← quasiIso_opMap_iff, quasiIso_iff_of_zeros]
  rotate_left
  · dsimp
    rw [hg₂, op_zero]
  · dsimp
    

Proof state:
case hg₁
C : Type u_1
D : Type u_2
inst✝² : Category.{u_3, u_1} C
inst✝¹ : Category.{?u.257008, u_2} D
inst✝ : Abelian C
S₁ S₂ : ShortComplex C
φ : S₁ ⟶ S₂
hg₁ : S₁.g = 0
hf₂ : S₂.f = 0
hg₂ : S₂.g = 0
⊢ S₂.f.op = 0

Next tactic:
rw [hf₂, op_zero]
/-- Given a morphism of short complexes `φ : S₁ ⟶ S₂` in an abelian category, if `S₁.g = 0`
(e.g when `S₁` is of the form `S₁.X₁ ⟶ S₁.X₂ ⟶ 0`) and both `S₂.f` and `S₂.g` are zero
(e.g when `S₂` is of the form `0 ⟶ S₂.X₂ ⟶ 0`), then `φ` is a quasi-isomorphism iff
the obvious short complex `S₁.X₂ ⟶ S₁.X₂ ⟶ S₂.X₂` is exact and `φ.τ₂` is an epi). -/
lemma quasiIso_iff_of_zeros' {S₁ S₂ : ShortComplex C} (φ : S₁ ⟶ S₂)
    (hg₁ : S₁.g = 0) (hf₂ : S₂.f = 0) (hg₂ : S₂.g = 0) :
    QuasiIso φ ↔
      (ShortComplex.mk S₁.f φ.τ₂ (by rw [← φ.comm₁₂, hf₂, comp_zero])).Exact ∧ Epi φ.τ₂ := by
  rw [← quasiIso_opMap_iff, quasiIso_iff_of_zeros]
  rotate_left
  · dsimp
    rw [hg₂, op_zero]
  · dsimp
    rw [hf₂, op_zero]
  · 

Proof state:
case hf₂
C : Type u_1
D : Type u_2
inst✝² : Category.{u_3, u_1} C
inst✝¹ : Category.{?u.257008, u_2} D
inst✝ : Abelian C
S₁ S₂ : ShortComplex C
φ : S₁ ⟶ S₂
hg₁ : S₁.g = 0
hf₂ : S₂.f = 0
hg₂ : S₂.g = 0
⊢ (op S₁).f = 0

Next tactic:
dsimp
/-- Given a morphism of short complexes `φ : S₁ ⟶ S₂` in an abelian category, if `S₁.g = 0`
(e.g when `S₁` is of the form `S₁.X₁ ⟶ S₁.X₂ ⟶ 0`) and both `S₂.f` and `S₂.g` are zero
(e.g when `S₂` is of the form `0 ⟶ S₂.X₂ ⟶ 0`), then `φ` is a quasi-isomorphism iff
the obvious short complex `S₁.X₂ ⟶ S₁.X₂ ⟶ S₂.X₂` is exact and `φ.τ₂` is an epi). -/
lemma quasiIso_iff_of_zeros' {S₁ S₂ : ShortComplex C} (φ : S₁ ⟶ S₂)
    (hg₁ : S₁.g = 0) (hf₂ : S₂.f = 0) (hg₂ : S₂.g = 0) :
    QuasiIso φ ↔
      (ShortComplex.mk S₁.f φ.τ₂ (by rw [← φ.comm₁₂, hf₂, comp_zero])).Exact ∧ Epi φ.τ₂ := by
  rw [← quasiIso_opMap_iff, quasiIso_iff_of_zeros]
  rotate_left
  · dsimp
    rw [hg₂, op_zero]
  · dsimp
    rw [hf₂, op_zero]
  · dsimp
    

Proof state:
case hf₂
C : Type u_1
D : Type u_2
inst✝² : Category.{u_3, u_1} C
inst✝¹ : Category.{?u.257008, u_2} D
inst✝ : Abelian C
S₁ S₂ : ShortComplex C
φ : S₁ ⟶ S₂
hg₁ : S₁.g = 0
hf₂ : S₂.f = 0
hg₂ : S₂.g = 0
⊢ S₁.g.op = 0

Next tactic:
rw [hg₁, op_zero]
/-- Given a morphism of short complexes `φ : S₁ ⟶ S₂` in an abelian category, if `S₁.g = 0`
(e.g when `S₁` is of the form `S₁.X₁ ⟶ S₁.X₂ ⟶ 0`) and both `S₂.f` and `S₂.g` are zero
(e.g when `S₂` is of the form `0 ⟶ S₂.X₂ ⟶ 0`), then `φ` is a quasi-isomorphism iff
the obvious short complex `S₁.X₂ ⟶ S₁.X₂ ⟶ S₂.X₂` is exact and `φ.τ₂` is an epi). -/
lemma quasiIso_iff_of_zeros' {S₁ S₂ : ShortComplex C} (φ : S₁ ⟶ S₂)
    (hg₁ : S₁.g = 0) (hf₂ : S₂.f = 0) (hg₂ : S₂.g = 0) :
    QuasiIso φ ↔
      (ShortComplex.mk S₁.f φ.τ₂ (by rw [← φ.comm₁₂, hf₂, comp_zero])).Exact ∧ Epi φ.τ₂ := by
  rw [← quasiIso_opMap_iff, quasiIso_iff_of_zeros]
  rotate_left
  · dsimp
    rw [hg₂, op_zero]
  · dsimp
    rw [hf₂, op_zero]
  · dsimp
    rw [hg₁, op_zero]
  

Proof state:
C : Type u_1
D : Type u_2
inst✝² : Category.{u_3, u_1} C
inst✝¹ : Category.{?u.257008, u_2} D
inst✝ : Abelian C
S₁ S₂ : ShortComplex C
φ : S₁ ⟶ S₂
hg₁ : S₁.g = 0
hf₂ : S₂.f = 0
hg₂ : S₂.g = 0
⊢ Exact (mk (opMap φ).τ₂ (op S₁).g (_ : (opMap φ).τ₂ ≫ (op S₁).g = 0)) ∧ Mono (opMap φ).τ₂ ↔
    Exact (mk S₁.f φ.τ₂ (_ : S₁.f ≫ φ.τ₂ = 0)) ∧ Epi φ.τ₂

Next tactic:
rw [← exact_unop_iff]
/-- Given a morphism of short complexes `φ : S₁ ⟶ S₂` in an abelian category, if `S₁.g = 0`
(e.g when `S₁` is of the form `S₁.X₁ ⟶ S₁.X₂ ⟶ 0`) and both `S₂.f` and `S₂.g` are zero
(e.g when `S₂` is of the form `0 ⟶ S₂.X₂ ⟶ 0`), then `φ` is a quasi-isomorphism iff
the obvious short complex `S₁.X₂ ⟶ S₁.X₂ ⟶ S₂.X₂` is exact and `φ.τ₂` is an epi). -/
lemma quasiIso_iff_of_zeros' {S₁ S₂ : ShortComplex C} (φ : S₁ ⟶ S₂)
    (hg₁ : S₁.g = 0) (hf₂ : S₂.f = 0) (hg₂ : S₂.g = 0) :
    QuasiIso φ ↔
      (ShortComplex.mk S₁.f φ.τ₂ (by rw [← φ.comm₁₂, hf₂, comp_zero])).Exact ∧ Epi φ.τ₂ := by
  rw [← quasiIso_opMap_iff, quasiIso_iff_of_zeros]
  rotate_left
  · dsimp
    rw [hg₂, op_zero]
  · dsimp
    rw [hf₂, op_zero]
  · dsimp
    rw [hg₁, op_zero]
  rw [← exact_unop_iff]
  

Proof state:
C : Type u_1
D : Type u_2
inst✝² : Category.{u_3, u_1} C
inst✝¹ : Category.{?u.257008, u_2} D
inst✝ : Abelian C
S₁ S₂ : ShortComplex C
φ : S₁ ⟶ S₂
hg₁ : S₁.g = 0
hf₂ : S₂.f = 0
hg₂ : S₂.g = 0
⊢ Exact (unop (mk (opMap φ).τ₂ (op S₁).g (_ : (opMap φ).τ₂ ≫ (op S₁).g = 0))) ∧ Mono (opMap φ).τ₂ ↔
    Exact (mk S₁.f φ.τ₂ (_ : S₁.f ≫ φ.τ₂ = 0)) ∧ Epi φ.τ₂

Next tactic:
have : Mono φ.τ₂.op ↔ Epi φ.τ₂ :=
    ⟨fun _ => unop_epi_of_mono φ.τ₂.op, fun _ => op_mono_of_epi _⟩
/-- Given a morphism of short complexes `φ : S₁ ⟶ S₂` in an abelian category, if `S₁.g = 0`
(e.g when `S₁` is of the form `S₁.X₁ ⟶ S₁.X₂ ⟶ 0`) and both `S₂.f` and `S₂.g` are zero
(e.g when `S₂` is of the form `0 ⟶ S₂.X₂ ⟶ 0`), then `φ` is a quasi-isomorphism iff
the obvious short complex `S₁.X₂ ⟶ S₁.X₂ ⟶ S₂.X₂` is exact and `φ.τ₂` is an epi). -/
lemma quasiIso_iff_of_zeros' {S₁ S₂ : ShortComplex C} (φ : S₁ ⟶ S₂)
    (hg₁ : S₁.g = 0) (hf₂ : S₂.f = 0) (hg₂ : S₂.g = 0) :
    QuasiIso φ ↔
      (ShortComplex.mk S₁.f φ.τ₂ (by rw [← φ.comm₁₂, hf₂, comp_zero])).Exact ∧ Epi φ.τ₂ := by
  rw [← quasiIso_opMap_iff, quasiIso_iff_of_zeros]
  rotate_left
  · dsimp
    rw [hg₂, op_zero]
  · dsimp
    rw [hf₂, op_zero]
  · dsimp
    rw [hg₁, op_zero]
  rw [← exact_unop_iff]
  have : Mono φ.τ₂.op ↔ Epi φ.τ₂ :=
    ⟨fun _ => unop_epi_of_mono φ.τ₂.op, fun _ => op_mono_of_epi _⟩
  

Proof state:
C : Type u_1
D : Type u_2
inst✝² : Category.{u_3, u_1} C
inst✝¹ : Category.{?u.257008, u_2} D
inst✝ : Abelian C
S₁ S₂ : ShortComplex C
φ : S₁ ⟶ S₂
hg₁ : S₁.g = 0
hf₂ : S₂.f = 0
hg₂ : S₂.g = 0
this : Mono φ.τ₂.op ↔ Epi φ.τ₂
⊢ Exact (unop (mk (opMap φ).τ₂ (op S₁).g (_ : (opMap φ).τ₂ ≫ (op S₁).g = 0))) ∧ Mono (opMap φ).τ₂ ↔
    Exact (mk S₁.f φ.τ₂ (_ : S₁.f ≫ φ.τ₂ = 0)) ∧ Epi φ.τ₂

Next tactic:
tauto
/-- If `S` is an exact short complex and `f : S.X₂ ⟶ J` is a morphism to an injective object `J`
such that `S.f ≫ f = 0`, this is a morphism `φ : S.X₃ ⟶ J` such that `S.g ≫ φ = f`. -/
noncomputable def Exact.descToInjective
    (hS : S.Exact) {J : C} (f : S.X₂ ⟶ J) [Injective J] (hf : S.f ≫ f = 0) :
    S.X₃ ⟶ J := by
  

Proof state:
C : Type u_1
D : Type u_2
inst✝³ : Category.{?u.264701, u_1} C
inst✝² : Category.{?u.264705, u_2} D
inst✝¹ : Abelian C
S : ShortComplex C
hS : Exact S
J : C
f : S.X₂ ⟶ J
inst✝ : Injective J
hf : S.f ≫ f = 0
⊢ S.X₃ ⟶ J

Next tactic:
have := hS.mono_fromOpcycles
/-- If `S` is an exact short complex and `f : S.X₂ ⟶ J` is a morphism to an injective object `J`
such that `S.f ≫ f = 0`, this is a morphism `φ : S.X₃ ⟶ J` such that `S.g ≫ φ = f`. -/
noncomputable def Exact.descToInjective
    (hS : S.Exact) {J : C} (f : S.X₂ ⟶ J) [Injective J] (hf : S.f ≫ f = 0) :
    S.X₃ ⟶ J := by
  have := hS.mono_fromOpcycles
  

Proof state:
C : Type u_1
D : Type u_2
inst✝³ : Category.{?u.264701, u_1} C
inst✝² : Category.{?u.264705, u_2} D
inst✝¹ : Abelian C
S : ShortComplex C
hS : Exact S
J : C
f : S.X₂ ⟶ J
inst✝ : Injective J
hf : S.f ≫ f = 0
this : Mono (fromOpcycles S)
⊢ S.X₃ ⟶ J

Next tactic:
exact Injective.factorThru (S.descOpcycles f hf) S.fromOpcycles
@[reassoc (attr := simp, nolint unusedHavesSuffices)]
lemma Exact.comp_descToInjective
    (hS : S.Exact) {J : C} (f : S.X₂ ⟶ J) [Injective J] (hf : S.f ≫ f = 0) :
    S.g ≫ hS.descToInjective f hf = f := by
  

Proof state:
C : Type u_1
D : Type u_2
inst✝³ : Category.{u_3, u_1} C
inst✝² : Category.{?u.265704, u_2} D
inst✝¹ : Abelian C
S : ShortComplex C
hS : Exact S
J : C
f : S.X₂ ⟶ J
inst✝ : Injective J
hf : S.f ≫ f = 0
⊢ S.g ≫ descToInjective hS f hf = f

Next tactic:
have := hS.mono_fromOpcycles
@[reassoc (attr := simp, nolint unusedHavesSuffices)]
lemma Exact.comp_descToInjective
    (hS : S.Exact) {J : C} (f : S.X₂ ⟶ J) [Injective J] (hf : S.f ≫ f = 0) :
    S.g ≫ hS.descToInjective f hf = f := by
  have := hS.mono_fromOpcycles
  

Proof state:
C : Type u_1
D : Type u_2
inst✝³ : Category.{u_3, u_1} C
inst✝² : Category.{?u.265704, u_2} D
inst✝¹ : Abelian C
S : ShortComplex C
hS : Exact S
J : C
f : S.X₂ ⟶ J
inst✝ : Injective J
hf : S.f ≫ f = 0
this : Mono (fromOpcycles S)
⊢ S.g ≫ descToInjective hS f hf = f

Next tactic:
dsimp [descToInjective]
@[reassoc (attr := simp, nolint unusedHavesSuffices)]
lemma Exact.comp_descToInjective
    (hS : S.Exact) {J : C} (f : S.X₂ ⟶ J) [Injective J] (hf : S.f ≫ f = 0) :
    S.g ≫ hS.descToInjective f hf = f := by
  have := hS.mono_fromOpcycles
  dsimp [descToInjective]
  

Proof state:
C : Type u_1
D : Type u_2
inst✝³ : Category.{u_3, u_1} C
inst✝² : Category.{?u.265704, u_2} D
inst✝¹ : Abelian C
S : ShortComplex C
hS : Exact S
J : C
f : S.X₂ ⟶ J
inst✝ : Injective J
hf : S.f ≫ f = 0
this : Mono (fromOpcycles S)
⊢ S.g ≫ Injective.factorThru (descOpcycles S f hf) (fromOpcycles S) = f

Next tactic:
simp only [← p_fromOpcycles, assoc, Injective.comp_factorThru, p_descOpcycles]
/-- If `S` is an exact short complex and `f : P ⟶ S.X₂` is a morphism from a projective object `P`
such that `f ≫ S.g = 0`, this is a morphism `φ : P ⟶ S.X₁` such that `φ ≫ S.f = f`. -/
noncomputable def Exact.liftFromProjective
    (hS : S.Exact) {P : C} (f : P ⟶ S.X₂) [Projective P] (hf : f ≫ S.g = 0) :
    P ⟶ S.X₁ := by
  

Proof state:
C : Type u_1
D : Type u_2
inst✝³ : Category.{?u.267718, u_1} C
inst✝² : Category.{?u.267722, u_2} D
inst✝¹ : Abelian C
S : ShortComplex C
hS : Exact S
P : C
f : P ⟶ S.X₂
inst✝ : Projective P
hf : f ≫ S.g = 0
⊢ P ⟶ S.X₁

Next tactic:
have := hS.epi_toCycles
/-- If `S` is an exact short complex and `f : P ⟶ S.X₂` is a morphism from a projective object `P`
such that `f ≫ S.g = 0`, this is a morphism `φ : P ⟶ S.X₁` such that `φ ≫ S.f = f`. -/
noncomputable def Exact.liftFromProjective
    (hS : S.Exact) {P : C} (f : P ⟶ S.X₂) [Projective P] (hf : f ≫ S.g = 0) :
    P ⟶ S.X₁ := by
  have := hS.epi_toCycles
  

Proof state:
C : Type u_1
D : Type u_2
inst✝³ : Category.{?u.267718, u_1} C
inst✝² : Category.{?u.267722, u_2} D
inst✝¹ : Abelian C
S : ShortComplex C
hS : Exact S
P : C
f : P ⟶ S.X₂
inst✝ : Projective P
hf : f ≫ S.g = 0
this : Epi (toCycles S)
⊢ P ⟶ S.X₁

Next tactic:
exact Projective.factorThru (S.liftCycles f hf) S.toCycles
@[reassoc (attr := simp, nolint unusedHavesSuffices)]
lemma Exact.liftFromProjective_comp
    (hS : S.Exact) {P : C} (f : P ⟶ S.X₂) [Projective P] (hf : f ≫ S.g = 0) :
    hS.liftFromProjective f hf ≫ S.f = f := by
  

Proof state:
C : Type u_1
D : Type u_2
inst✝³ : Category.{u_3, u_1} C
inst✝² : Category.{?u.268717, u_2} D
inst✝¹ : Abelian C
S : ShortComplex C
hS : Exact S
P : C
f : P ⟶ S.X₂
inst✝ : Projective P
hf : f ≫ S.g = 0
⊢ liftFromProjective hS f hf ≫ S.f = f

Next tactic:
have := hS.epi_toCycles
@[reassoc (attr := simp, nolint unusedHavesSuffices)]
lemma Exact.liftFromProjective_comp
    (hS : S.Exact) {P : C} (f : P ⟶ S.X₂) [Projective P] (hf : f ≫ S.g = 0) :
    hS.liftFromProjective f hf ≫ S.f = f := by
  have := hS.epi_toCycles
  

Proof state:
C : Type u_1
D : Type u_2
inst✝³ : Category.{u_3, u_1} C
inst✝² : Category.{?u.268717, u_2} D
inst✝¹ : Abelian C
S : ShortComplex C
hS : Exact S
P : C
f : P ⟶ S.X₂
inst✝ : Projective P
hf : f ≫ S.g = 0
this : Epi (toCycles S)
⊢ liftFromProjective hS f hf ≫ S.f = f

Next tactic:
dsimp [liftFromProjective]
@[reassoc (attr := simp, nolint unusedHavesSuffices)]
lemma Exact.liftFromProjective_comp
    (hS : S.Exact) {P : C} (f : P ⟶ S.X₂) [Projective P] (hf : f ≫ S.g = 0) :
    hS.liftFromProjective f hf ≫ S.f = f := by
  have := hS.epi_toCycles
  dsimp [liftFromProjective]
  

Proof state:
C : Type u_1
D : Type u_2
inst✝³ : Category.{u_3, u_1} C
inst✝² : Category.{?u.268717, u_2} D
inst✝¹ : Abelian C
S : ShortComplex C
hS : Exact S
P : C
f : P ⟶ S.X₂
inst✝ : Projective P
hf : f ≫ S.g = 0
this : Epi (toCycles S)
⊢ Projective.factorThru (liftCycles S f hf) (toCycles S) ≫ S.f = f

Next tactic:
rw [← toCycles_i, Projective.factorThru_comp_assoc, liftCycles_i]
instance : F.PreservesMonomorphisms where
  preserves {X Y} f hf := by
    

Proof state:
C : Type u_1
D : Type u_2
inst✝⁷ : Category.{?u.271372, u_1} C
inst✝⁶ : Category.{?u.271376, u_2} D
F : C ⥤ D
inst✝⁵ : Preadditive C
inst✝⁴ : Preadditive D
inst✝³ : HasZeroObject C
inst✝² : HasZeroObject D
inst✝¹ : PreservesZeroMorphisms F
inst✝ : PreservesHomology F
X Y : C
f : X ⟶ Y
hf : Mono f
⊢ Mono (F.map f)

Next tactic:
let S := ShortComplex.mk (0 : X ⟶ X) f zero_comp
instance : F.PreservesMonomorphisms where
  preserves {X Y} f hf := by
    let S := ShortComplex.mk (0 : X ⟶ X) f zero_comp
    

Proof state:
C : Type u_1
D : Type u_2
inst✝⁷ : Category.{?u.271372, u_1} C
inst✝⁶ : Category.{?u.271376, u_2} D
F : C ⥤ D
inst✝⁵ : Preadditive C
inst✝⁴ : Preadditive D
inst✝³ : HasZeroObject C
inst✝² : HasZeroObject D
inst✝¹ : PreservesZeroMorphisms F
inst✝ : PreservesHomology F
X Y : C
f : X ⟶ Y
hf : Mono f
S : ShortComplex C := ShortComplex.mk 0 f (_ : 0 ≫ f = 0)
⊢ Mono (F.map f)

Next tactic:
exact ((S.map F).exact_iff_mono (by simp)).1
      (((S.exact_iff_mono rfl).2 hf).map F)
instance : F.PreservesMonomorphisms where
  preserves {X Y} f hf := by
    let S := ShortComplex.mk (0 : X ⟶ X) f zero_comp
    exact ((S.map F).exact_iff_mono (by 

Proof state:
C : Type u_1
D : Type u_2
inst✝⁷ : Category.{?u.271372, u_1} C
inst✝⁶ : Category.{?u.271376, u_2} D
F : C ⥤ D
inst✝⁵ : Preadditive C
inst✝⁴ : Preadditive D
inst✝³ : HasZeroObject C
inst✝² : HasZeroObject D
inst✝¹ : PreservesZeroMorphisms F
inst✝ : PreservesHomology F
X Y : C
f : X ⟶ Y
hf : Mono f
S : ShortComplex C := ShortComplex.mk 0 f (_ : 0 ≫ f = 0)
⊢ (ShortComplex.map S F).f = 0

Next tactic:
simp
instance [Faithful F] [CategoryWithHomology C] : F.ReflectsMonomorphisms where
  reflects {X Y} f hf := by
    

Proof state:
C : Type u_1
D : Type u_2
inst✝⁹ : Category.{?u.272940, u_1} C
inst✝⁸ : Category.{?u.272944, u_2} D
F : C ⥤ D
inst✝⁷ : Preadditive C
inst✝⁶ : Preadditive D
inst✝⁵ : HasZeroObject C
inst✝⁴ : HasZeroObject D
inst✝³ : PreservesZeroMorphisms F
inst✝² : PreservesHomology F
inst✝¹ : Faithful F
inst✝ : CategoryWithHomology C
X Y : C
f : X ⟶ Y
hf : Mono (F.map f)
⊢ Mono f

Next tactic:
let S := ShortComplex.mk (0 : X ⟶ X) f zero_comp
instance [Faithful F] [CategoryWithHomology C] : F.ReflectsMonomorphisms where
  reflects {X Y} f hf := by
    let S := ShortComplex.mk (0 : X ⟶ X) f zero_comp
    

Proof state:
C : Type u_1
D : Type u_2
inst✝⁹ : Category.{?u.272940, u_1} C
inst✝⁸ : Category.{?u.272944, u_2} D
F : C ⥤ D
inst✝⁷ : Preadditive C
inst✝⁶ : Preadditive D
inst✝⁵ : HasZeroObject C
inst✝⁴ : HasZeroObject D
inst✝³ : PreservesZeroMorphisms F
inst✝² : PreservesHomology F
inst✝¹ : Faithful F
inst✝ : CategoryWithHomology C
X Y : C
f : X ⟶ Y
hf : Mono (F.map f)
S : ShortComplex C := ShortComplex.mk 0 f (_ : 0 ≫ f = 0)
⊢ Mono f

Next tactic:
exact (S.exact_iff_mono rfl).1
      ((ShortComplex.exact_map_iff_of_faithful S F).1
      (((S.map F).exact_iff_mono (by simp)).2 hf))
instance [Faithful F] [CategoryWithHomology C] : F.ReflectsMonomorphisms where
  reflects {X Y} f hf := by
    let S := ShortComplex.mk (0 : X ⟶ X) f zero_comp
    exact (S.exact_iff_mono rfl).1
      ((ShortComplex.exact_map_iff_of_faithful S F).1
      (((S.map F).exact_iff_mono (by 

Proof state:
C : Type u_1
D : Type u_2
inst✝⁹ : Category.{?u.272940, u_1} C
inst✝⁸ : Category.{?u.272944, u_2} D
F : C ⥤ D
inst✝⁷ : Preadditive C
inst✝⁶ : Preadditive D
inst✝⁵ : HasZeroObject C
inst✝⁴ : HasZeroObject D
inst✝³ : PreservesZeroMorphisms F
inst✝² : PreservesHomology F
inst✝¹ : Faithful F
inst✝ : CategoryWithHomology C
X Y : C
f : X ⟶ Y
hf : Mono (F.map f)
S : ShortComplex C := ShortComplex.mk 0 f (_ : 0 ≫ f = 0)
⊢ (ShortComplex.map S F).f = 0

Next tactic:
simp
instance : F.PreservesEpimorphisms where
  preserves {X Y} f hf := by
    

Proof state:
C : Type u_1
D : Type u_2
inst✝⁷ : Category.{?u.276181, u_1} C
inst✝⁶ : Category.{?u.276185, u_2} D
F : C ⥤ D
inst✝⁵ : Preadditive C
inst✝⁴ : Preadditive D
inst✝³ : HasZeroObject C
inst✝² : HasZeroObject D
inst✝¹ : PreservesZeroMorphisms F
inst✝ : PreservesHomology F
X Y : C
f : X ⟶ Y
hf : Epi f
⊢ Epi (F.map f)

Next tactic:
let S := ShortComplex.mk f (0 : Y ⟶ Y) comp_zero
instance : F.PreservesEpimorphisms where
  preserves {X Y} f hf := by
    let S := ShortComplex.mk f (0 : Y ⟶ Y) comp_zero
    

Proof state:
C : Type u_1
D : Type u_2
inst✝⁷ : Category.{?u.276181, u_1} C
inst✝⁶ : Category.{?u.276185, u_2} D
F : C ⥤ D
inst✝⁵ : Preadditive C
inst✝⁴ : Preadditive D
inst✝³ : HasZeroObject C
inst✝² : HasZeroObject D
inst✝¹ : PreservesZeroMorphisms F
inst✝ : PreservesHomology F
X Y : C
f : X ⟶ Y
hf : Epi f
S : ShortComplex C := ShortComplex.mk f 0 (_ : f ≫ 0 = 0)
⊢ Epi (F.map f)

Next tactic:
exact ((S.map F).exact_iff_epi (by simp)).1
      (((S.exact_iff_epi rfl).2 hf).map F)
instance : F.PreservesEpimorphisms where
  preserves {X Y} f hf := by
    let S := ShortComplex.mk f (0 : Y ⟶ Y) comp_zero
    exact ((S.map F).exact_iff_epi (by 

Proof state:
C : Type u_1
D : Type u_2
inst✝⁷ : Category.{?u.276181, u_1} C
inst✝⁶ : Category.{?u.276185, u_2} D
F : C ⥤ D
inst✝⁵ : Preadditive C
inst✝⁴ : Preadditive D
inst✝³ : HasZeroObject C
inst✝² : HasZeroObject D
inst✝¹ : PreservesZeroMorphisms F
inst✝ : PreservesHomology F
X Y : C
f : X ⟶ Y
hf : Epi f
S : ShortComplex C := ShortComplex.mk f 0 (_ : f ≫ 0 = 0)
⊢ (ShortComplex.map S F).g = 0

Next tactic:
simp
instance [Faithful F] [CategoryWithHomology C] : F.ReflectsEpimorphisms where
  reflects {X Y} f hf := by
    

Proof state:
C : Type u_1
D : Type u_2
inst✝⁹ : Category.{?u.277757, u_1} C
inst✝⁸ : Category.{?u.277761, u_2} D
F : C ⥤ D
inst✝⁷ : Preadditive C
inst✝⁶ : Preadditive D
inst✝⁵ : HasZeroObject C
inst✝⁴ : HasZeroObject D
inst✝³ : PreservesZeroMorphisms F
inst✝² : PreservesHomology F
inst✝¹ : Faithful F
inst✝ : CategoryWithHomology C
X Y : C
f : X ⟶ Y
hf : Epi (F.map f)
⊢ Epi f

Next tactic:
let S := ShortComplex.mk f (0 : Y ⟶ Y) comp_zero
instance [Faithful F] [CategoryWithHomology C] : F.ReflectsEpimorphisms where
  reflects {X Y} f hf := by
    let S := ShortComplex.mk f (0 : Y ⟶ Y) comp_zero
    

Proof state:
C : Type u_1
D : Type u_2
inst✝⁹ : Category.{?u.277757, u_1} C
inst✝⁸ : Category.{?u.277761, u_2} D
F : C ⥤ D
inst✝⁷ : Preadditive C
inst✝⁶ : Preadditive D
inst✝⁵ : HasZeroObject C
inst✝⁴ : HasZeroObject D
inst✝³ : PreservesZeroMorphisms F
inst✝² : PreservesHomology F
inst✝¹ : Faithful F
inst✝ : CategoryWithHomology C
X Y : C
f : X ⟶ Y
hf : Epi (F.map f)
S : ShortComplex C := ShortComplex.mk f 0 (_ : f ≫ 0 = 0)
⊢ Epi f

Next tactic:
exact (S.exact_iff_epi rfl).1
      ((ShortComplex.exact_map_iff_of_faithful S F).1
      (((S.map F).exact_iff_epi (by simp)).2 hf))