[GOAL]
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
Y Z : C
f : Z ⟶ Y
I : InjectiveResolution Y
J : InjectiveResolution Z
⊢ HomologicalComplex.Hom.f J.ι 0 ≫ descFZero f I J ≫ HomologicalComplex.d I.cocomplex 0 1 = 0
[PROOFSTEP]
simp [← Category.assoc, descFZero]
[GOAL]
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
Y Z : C
f : Z ⟶ Y
I : InjectiveResolution Y
J : InjectiveResolution Z
⊢ HomologicalComplex.d J.cocomplex 0 1 ≫ descFOne f I J = descFZero f I J ≫ HomologicalComplex.d I.cocomplex 0 1
[PROOFSTEP]
simp [descFZero, descFOne]
[GOAL]
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
Y Z : C
I : InjectiveResolution Y
J : InjectiveResolution Z
n : ℕ
g : HomologicalComplex.X J.cocomplex n ⟶ HomologicalComplex.X I.cocomplex n
g' : HomologicalComplex.X J.cocomplex (n + 1) ⟶ HomologicalComplex.X I.cocomplex (n + 1)
w : HomologicalComplex.d J.cocomplex n (n + 1) ≫ g' = g ≫ HomologicalComplex.d I.cocomplex n (n + 1)
⊢ HomologicalComplex.d J.cocomplex n (n + 1) ≫ g' ≫ HomologicalComplex.d I.cocomplex (n + 1) (n + 2) = 0
[PROOFSTEP]
simp [← Category.assoc, w]
[GOAL]
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
Y Z : C
I : InjectiveResolution Y
J : InjectiveResolution Z
n : ℕ
g : HomologicalComplex.X J.cocomplex n ⟶ HomologicalComplex.X I.cocomplex n
g' : HomologicalComplex.X J.cocomplex (n + 1) ⟶ HomologicalComplex.X I.cocomplex (n + 1)
w : HomologicalComplex.d J.cocomplex n (n + 1) ≫ g' = g ≫ HomologicalComplex.d I.cocomplex n (n + 1)
⊢ HomologicalComplex.d J.cocomplex (n + 1) (n + 2) ≫
      Exact.desc (g' ≫ HomologicalComplex.d I.cocomplex (n + 1) (n + 2)) (HomologicalComplex.d J.cocomplex n (n + 1))
        (HomologicalComplex.d J.cocomplex (n + 1) (n + 2))
        (_ :
          Exact (HomologicalComplex.d J.cocomplex (n + 1) (n + 2)).op (HomologicalComplex.d J.cocomplex n (n + 1)).op)
        (_ : HomologicalComplex.d J.cocomplex n (n + 1) ≫ g' ≫ HomologicalComplex.d I.cocomplex (n + 1) (n + 2) = 0) =
    g' ≫ HomologicalComplex.d I.cocomplex (n + 1) (n + 2)
[PROOFSTEP]
simp
[GOAL]
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
Y Z : C
f : Z ⟶ Y
I : InjectiveResolution Y
J : InjectiveResolution Z
⊢ J.ι ≫ desc f I J = (CochainComplex.single₀ C).map f ≫ I.ι
[PROOFSTEP]
ext
[GOAL]
case h
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
Y Z : C
f : Z ⟶ Y
I : InjectiveResolution Y
J : InjectiveResolution Z
⊢ HomologicalComplex.Hom.f (J.ι ≫ desc f I J) 0 = HomologicalComplex.Hom.f ((CochainComplex.single₀ C).map f ≫ I.ι) 0
[PROOFSTEP]
simp [desc, descFOne, descFZero]
[GOAL]
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
Y Z : C
I : InjectiveResolution Y
J : InjectiveResolution Z
f : I.cocomplex ⟶ J.cocomplex
comm : I.ι ≫ f = 0
⊢ HomologicalComplex.d I.cocomplex 0 1 ≫
      (HomologicalComplex.Hom.f f 1 - descHomotopyZeroZero f comm ≫ HomologicalComplex.d J.cocomplex 0 1) =
    0
[PROOFSTEP]
simp [descHomotopyZeroZero, ← Category.assoc]
[GOAL]
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
Y Z : C
I : InjectiveResolution Y
J : InjectiveResolution Z
f : I.cocomplex ⟶ J.cocomplex
n : ℕ
g : HomologicalComplex.X I.cocomplex (n + 1) ⟶ HomologicalComplex.X J.cocomplex n
g' : HomologicalComplex.X I.cocomplex (n + 2) ⟶ HomologicalComplex.X J.cocomplex (n + 1)
w :
  HomologicalComplex.Hom.f f (n + 1) =
    HomologicalComplex.d I.cocomplex (n + 1) (n + 2) ≫ g' + g ≫ HomologicalComplex.d J.cocomplex n (n + 1)
⊢ HomologicalComplex.d I.cocomplex (n + 1) (n + 2) ≫
      (HomologicalComplex.Hom.f f (n + 2) - g' ≫ HomologicalComplex.d J.cocomplex (n + 1) (n + 2)) =
    0
[PROOFSTEP]
simp [Preadditive.comp_sub, ← Category.assoc, Preadditive.sub_comp,
  show I.cocomplex.d (n + 1) (n + 2) ≫ g' = f.f (n + 1) - g ≫ J.cocomplex.d n (n + 1)
    by
    rw [w]
    simp only [add_sub_cancel]]
[GOAL]
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
Y Z : C
I : InjectiveResolution Y
J : InjectiveResolution Z
f : I.cocomplex ⟶ J.cocomplex
n : ℕ
g : HomologicalComplex.X I.cocomplex (n + 1) ⟶ HomologicalComplex.X J.cocomplex n
g' : HomologicalComplex.X I.cocomplex (n + 2) ⟶ HomologicalComplex.X J.cocomplex (n + 1)
w :
  HomologicalComplex.Hom.f f (n + 1) =
    HomologicalComplex.d I.cocomplex (n + 1) (n + 2) ≫ g' + g ≫ HomologicalComplex.d J.cocomplex n (n + 1)
⊢ HomologicalComplex.d I.cocomplex (n + 1) (n + 2) ≫ g' =
    HomologicalComplex.Hom.f f (n + 1) - g ≫ HomologicalComplex.d J.cocomplex n (n + 1)
[PROOFSTEP]
rw [w]
[GOAL]
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
Y Z : C
I : InjectiveResolution Y
J : InjectiveResolution Z
f : I.cocomplex ⟶ J.cocomplex
n : ℕ
g : HomologicalComplex.X I.cocomplex (n + 1) ⟶ HomologicalComplex.X J.cocomplex n
g' : HomologicalComplex.X I.cocomplex (n + 2) ⟶ HomologicalComplex.X J.cocomplex (n + 1)
w :
  HomologicalComplex.Hom.f f (n + 1) =
    HomologicalComplex.d I.cocomplex (n + 1) (n + 2) ≫ g' + g ≫ HomologicalComplex.d J.cocomplex n (n + 1)
⊢ HomologicalComplex.d I.cocomplex (n + 1) (n + 2) ≫ g' =
    HomologicalComplex.d I.cocomplex (n + 1) (n + 2) ≫ g' + g ≫ HomologicalComplex.d J.cocomplex n (n + 1) -
      g ≫ HomologicalComplex.d J.cocomplex n (n + 1)
[PROOFSTEP]
simp only [add_sub_cancel]
[GOAL]
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
Y Z : C
I : InjectiveResolution Y
J : InjectiveResolution Z
f : I.cocomplex ⟶ J.cocomplex
comm : I.ι ≫ f = 0
⊢ HomologicalComplex.Hom.f f 0 = HomologicalComplex.d I.cocomplex 0 1 ≫ descHomotopyZeroZero f comm
[PROOFSTEP]
simp [descHomotopyZeroZero]
[GOAL]
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
Y Z : C
I : InjectiveResolution Y
J : InjectiveResolution Z
f : I.cocomplex ⟶ J.cocomplex
comm : I.ι ≫ f = 0
⊢ HomologicalComplex.Hom.f f 1 =
    descHomotopyZeroZero f comm ≫ HomologicalComplex.d J.cocomplex 0 1 +
      HomologicalComplex.d I.cocomplex 1 2 ≫ descHomotopyZeroOne f comm
[PROOFSTEP]
simp [descHomotopyZeroOne]
[GOAL]
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
Y Z : C
I : InjectiveResolution Y
J : InjectiveResolution Z
f : I.cocomplex ⟶ J.cocomplex
comm : I.ι ≫ f = 0
n : ℕ
x✝ :
  (f_1 : HomologicalComplex.X I.cocomplex (n + 1) ⟶ HomologicalComplex.X J.cocomplex n) ×'
    (f' : HomologicalComplex.X I.cocomplex (n + 2) ⟶ HomologicalComplex.X J.cocomplex (n + 1)) ×'
      HomologicalComplex.Hom.f f (n + 1) =
        f_1 ≫ HomologicalComplex.d J.cocomplex n (n + 1) + HomologicalComplex.d I.cocomplex (n + 1) (n + 2) ≫ f'
g : HomologicalComplex.X I.cocomplex (n + 1) ⟶ HomologicalComplex.X J.cocomplex n
g' : HomologicalComplex.X I.cocomplex (n + 2) ⟶ HomologicalComplex.X J.cocomplex (n + 1)
w :
  HomologicalComplex.Hom.f f (n + 1) =
    g ≫ HomologicalComplex.d J.cocomplex n (n + 1) + HomologicalComplex.d I.cocomplex (n + 1) (n + 2) ≫ g'
⊢ HomologicalComplex.Hom.f f (n + 1) =
    HomologicalComplex.d I.cocomplex (n + 1) (n + 2) ≫ g' + g ≫ HomologicalComplex.d J.cocomplex n (n + 1)
[PROOFSTEP]
simp only [w, add_comm]
[GOAL]
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
Y Z : C
I : InjectiveResolution Y
J : InjectiveResolution Z
f : I.cocomplex ⟶ J.cocomplex
comm : I.ι ≫ f = 0
n : ℕ
x✝ :
  (f_1 : HomologicalComplex.X I.cocomplex (n + 1) ⟶ HomologicalComplex.X J.cocomplex n) ×'
    (f' : HomologicalComplex.X I.cocomplex (n + 2) ⟶ HomologicalComplex.X J.cocomplex (n + 1)) ×'
      HomologicalComplex.Hom.f f (n + 1) =
        f_1 ≫ HomologicalComplex.d J.cocomplex n (n + 1) + HomologicalComplex.d I.cocomplex (n + 1) (n + 2) ≫ f'
g : HomologicalComplex.X I.cocomplex (n + 1) ⟶ HomologicalComplex.X J.cocomplex n
g' : HomologicalComplex.X I.cocomplex (n + 2) ⟶ HomologicalComplex.X J.cocomplex (n + 1)
w :
  HomologicalComplex.Hom.f f (n + 1) =
    g ≫ HomologicalComplex.d J.cocomplex n (n + 1) + HomologicalComplex.d I.cocomplex (n + 1) (n + 2) ≫ g'
⊢ HomologicalComplex.Hom.f f (n + 2) =
    { fst := g, snd := { fst := g', snd := w } }.snd.fst ≫ HomologicalComplex.d J.cocomplex (n + 1) (n + 2) +
      HomologicalComplex.d I.cocomplex (n + 2) (n + 3) ≫
        descHomotopyZeroSucc f n g g'
          (_ :
            HomologicalComplex.Hom.f f (n + 1) =
              HomologicalComplex.d I.cocomplex (n + 1) (n + 2) ≫ g' + g ≫ HomologicalComplex.d J.cocomplex n (n + 1))
[PROOFSTEP]
simp [descHomotopyZeroSucc, w]
[GOAL]
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
Y Z : C
f : Y ⟶ Z
I : InjectiveResolution Y
J : InjectiveResolution Z
g h : I.cocomplex ⟶ J.cocomplex
g_comm : I.ι ≫ g = (CochainComplex.single₀ C).map f ≫ J.ι
h_comm : I.ι ≫ h = (CochainComplex.single₀ C).map f ≫ J.ι
⊢ I.ι ≫ (g - h) = 0
[PROOFSTEP]
simp [g_comm, h_comm]
[GOAL]
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
X : C
I : InjectiveResolution X
⊢ Homotopy (desc (𝟙 X) I I) (𝟙 I.cocomplex)
[PROOFSTEP]
apply descHomotopy (𝟙 X)
[GOAL]
case g_comm
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
X : C
I : InjectiveResolution X
⊢ I.ι ≫ desc (𝟙 X) I I = (CochainComplex.single₀ C).map (𝟙 X) ≫ I.ι
[PROOFSTEP]
simp
[GOAL]
case h_comm
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
X : C
I : InjectiveResolution X
⊢ I.ι ≫ 𝟙 I.cocomplex = (CochainComplex.single₀ C).map (𝟙 X) ≫ I.ι
[PROOFSTEP]
simp
[GOAL]
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
X Y Z : C
f : X ⟶ Y
g : Y ⟶ Z
I : InjectiveResolution X
J : InjectiveResolution Y
K : InjectiveResolution Z
⊢ Homotopy (desc (f ≫ g) K I) (desc f J I ≫ desc g K J)
[PROOFSTEP]
apply descHomotopy (f ≫ g)
[GOAL]
case g_comm
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
X Y Z : C
f : X ⟶ Y
g : Y ⟶ Z
I : InjectiveResolution X
J : InjectiveResolution Y
K : InjectiveResolution Z
⊢ I.ι ≫ desc (f ≫ g) K I = (CochainComplex.single₀ C).map (f ≫ g) ≫ K.ι
[PROOFSTEP]
simp
[GOAL]
case h_comm
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
X Y Z : C
f : X ⟶ Y
g : Y ⟶ Z
I : InjectiveResolution X
J : InjectiveResolution Y
K : InjectiveResolution Z
⊢ I.ι ≫ desc f J I ≫ desc g K J = (CochainComplex.single₀ C).map (f ≫ g) ≫ K.ι
[PROOFSTEP]
simp
[GOAL]
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
X : C
I J : InjectiveResolution X
⊢ Homotopy (desc (𝟙 X ≫ 𝟙 X) I I) (𝟙 I.cocomplex)
[PROOFSTEP]
simpa [Category.id_comp] using descIdHomotopy _ _
[GOAL]
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
X : C
I J : InjectiveResolution X
⊢ Homotopy (desc (𝟙 X ≫ 𝟙 X) J J) (𝟙 J.cocomplex)
[PROOFSTEP]
simpa [Category.id_comp] using descIdHomotopy _ _
[GOAL]
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
X : C
I J : InjectiveResolution X
⊢ I.ι ≫ (homotopyEquiv I J).hom = J.ι
[PROOFSTEP]
simp [homotopyEquiv]
[GOAL]
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
X : C
I J : InjectiveResolution X
⊢ J.ι ≫ (homotopyEquiv I J).inv = I.ι
[PROOFSTEP]
simp [homotopyEquiv]
[GOAL]
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : HasInjectiveResolutions C
X : C
⊢ { obj := fun X => (HomotopyCategory.quotient C (ComplexShape.up ℕ)).obj (injectiveResolution X),
          map := fun {X Y} f => (HomotopyCategory.quotient C (ComplexShape.up ℕ)).map (injectiveResolution.desc f) }.map
      (𝟙 X) =
    𝟙
      ({ obj := fun X => (HomotopyCategory.quotient C (ComplexShape.up ℕ)).obj (injectiveResolution X),
            map := fun {X Y} f =>
              (HomotopyCategory.quotient C (ComplexShape.up ℕ)).map (injectiveResolution.desc f) }.obj
        X)
[PROOFSTEP]
rw [← (HomotopyCategory.quotient _ _).map_id]
[GOAL]
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : HasInjectiveResolutions C
X : C
⊢ { obj := fun X => (HomotopyCategory.quotient C (ComplexShape.up ℕ)).obj (injectiveResolution X),
          map := fun {X Y} f => (HomotopyCategory.quotient C (ComplexShape.up ℕ)).map (injectiveResolution.desc f) }.map
      (𝟙 X) =
    (HomotopyCategory.quotient C (ComplexShape.up ℕ)).map (𝟙 (injectiveResolution X))
[PROOFSTEP]
apply HomotopyCategory.eq_of_homotopy
[GOAL]
case h
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : HasInjectiveResolutions C
X : C
⊢ Homotopy (injectiveResolution.desc (𝟙 X)) (𝟙 (injectiveResolution X))
[PROOFSTEP]
apply InjectiveResolution.descIdHomotopy
[GOAL]
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : HasInjectiveResolutions C
X✝ Y✝ Z✝ : C
f : X✝ ⟶ Y✝
g : Y✝ ⟶ Z✝
⊢ { obj := fun X => (HomotopyCategory.quotient C (ComplexShape.up ℕ)).obj (injectiveResolution X),
          map := fun {X Y} f => (HomotopyCategory.quotient C (ComplexShape.up ℕ)).map (injectiveResolution.desc f) }.map
      (f ≫ g) =
    { obj := fun X => (HomotopyCategory.quotient C (ComplexShape.up ℕ)).obj (injectiveResolution X),
            map := fun {X Y} f =>
              (HomotopyCategory.quotient C (ComplexShape.up ℕ)).map (injectiveResolution.desc f) }.map
        f ≫
      { obj := fun X => (HomotopyCategory.quotient C (ComplexShape.up ℕ)).obj (injectiveResolution X),
            map := fun {X Y} f =>
              (HomotopyCategory.quotient C (ComplexShape.up ℕ)).map (injectiveResolution.desc f) }.map
        g
[PROOFSTEP]
rw [← (HomotopyCategory.quotient _ _).map_comp]
[GOAL]
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : HasInjectiveResolutions C
X✝ Y✝ Z✝ : C
f : X✝ ⟶ Y✝
g : Y✝ ⟶ Z✝
⊢ { obj := fun X => (HomotopyCategory.quotient C (ComplexShape.up ℕ)).obj (injectiveResolution X),
          map := fun {X Y} f => (HomotopyCategory.quotient C (ComplexShape.up ℕ)).map (injectiveResolution.desc f) }.map
      (f ≫ g) =
    (HomotopyCategory.quotient C (ComplexShape.up ℕ)).map (injectiveResolution.desc f ≫ injectiveResolution.desc g)
[PROOFSTEP]
apply HomotopyCategory.eq_of_homotopy
[GOAL]
case h
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : HasInjectiveResolutions C
X✝ Y✝ Z✝ : C
f : X✝ ⟶ Y✝
g : Y✝ ⟶ Z✝
⊢ Homotopy (injectiveResolution.desc (f ≫ g)) (injectiveResolution.desc f ≫ injectiveResolution.desc g)
[PROOFSTEP]
apply InjectiveResolution.descCompHomotopy
[GOAL]
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : EnoughInjectives C
X Y : C
f : X ⟶ Y
⊢ f ≫ d f = 0
[PROOFSTEP]
simp
[GOAL]
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : EnoughInjectives C
X Y : C
f : X ⟶ Y
⊢ (kernel.ι (d f) ≫ cokernel.π f) ≫ ι (cokernel f) = 0
[PROOFSTEP]
rw [Category.assoc, kernel.condition]
[GOAL]
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : EnoughInjectives C
Z : C
⊢ Injective.ι Z ≫ HomologicalComplex.d (ofCocomplex Z) 0 1 =
    HomologicalComplex.d ((CochainComplex.single₀ C).obj Z) 0 1 ≫ 0
[PROOFSTEP]
simp only [ofCocomplex_d, eq_self_iff_true, eqToHom_refl, Category.comp_id, dite_eq_ite, if_true, comp_zero]
[GOAL]
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : EnoughInjectives C
Z : C
⊢ Injective.ι Z ≫
      (CochainComplex.mkAux (under Z) (syzygies (Injective.ι Z)) (syzygies (d (Injective.ι Z))) (d (Injective.ι Z))
          (d (d (Injective.ι Z)))
          (_ :
            { fst := under Z, snd := { fst := syzygies (Injective.ι Z), snd := d (Injective.ι Z) } }.snd.snd ≫
                {
                      fst :=
                        syzygies
                          { fst := under Z,
                                snd := { fst := syzygies (Injective.ι Z), snd := d (Injective.ι Z) } }.2.snd,
                      snd :=
                        {
                          fst :=
                            d
                              { fst := under Z,
                                    snd := { fst := syzygies (Injective.ι Z), snd := d (Injective.ι Z) } }.2.snd,
                          snd :=
                            (_ :
                              { fst := under Z,
                                        snd := { fst := syzygies (Injective.ι Z), snd := d (Injective.ι Z) } }.2.snd ≫
                                  d
                                    { fst := under Z,
                                          snd := { fst := syzygies (Injective.ι Z), snd := d (Injective.ι Z) } }.2.snd =
                                0) } }.snd.fst =
              0)
          (fun t =>
            { fst := syzygies t.snd.snd.snd.snd.fst,
              snd :=
                { fst := d t.snd.snd.snd.snd.fst, snd := (_ : t.snd.snd.snd.snd.fst ≫ d t.snd.snd.snd.snd.fst = 0) } })
          0).d₀ =
    0
[PROOFSTEP]
exact (exact_f_d (Injective.ι Z)).w
[GOAL]
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : EnoughInjectives C
Z : C
n : ℕ
⊢ Exact (HomologicalComplex.d (ofCocomplex Z) 0 (0 + 1)) (HomologicalComplex.d (ofCocomplex Z) (0 + 1) (0 + 2))
[PROOFSTEP]
simp
[GOAL]
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : EnoughInjectives C
Z : C
n : ℕ
⊢ Exact
    (CochainComplex.mkAux (under Z) (syzygies (Injective.ι Z)) (syzygies (d (Injective.ι Z))) (d (Injective.ι Z))
        (d (d (Injective.ι Z)))
        (_ :
          { fst := under Z, snd := { fst := syzygies (Injective.ι Z), snd := d (Injective.ι Z) } }.snd.snd ≫
              {
                    fst :=
                      syzygies
                        { fst := under Z, snd := { fst := syzygies (Injective.ι Z), snd := d (Injective.ι Z) } }.2.snd,
                    snd :=
                      {
                        fst :=
                          d
                            { fst := under Z,
                                  snd := { fst := syzygies (Injective.ι Z), snd := d (Injective.ι Z) } }.2.snd,
                        snd :=
                          (_ :
                            { fst := under Z,
                                      snd := { fst := syzygies (Injective.ι Z), snd := d (Injective.ι Z) } }.2.snd ≫
                                d
                                  { fst := under Z,
                                        snd := { fst := syzygies (Injective.ι Z), snd := d (Injective.ι Z) } }.2.snd =
                              0) } }.snd.fst =
            0)
        (fun t =>
          { fst := syzygies t.snd.snd.snd.snd.fst,
            snd :=
              { fst := d t.snd.snd.snd.snd.fst, snd := (_ : t.snd.snd.snd.snd.fst ≫ d t.snd.snd.snd.snd.fst = 0) } })
        0).d₀
    (CochainComplex.mkAux (under Z) (syzygies (Injective.ι Z)) (syzygies (d (Injective.ι Z))) (d (Injective.ι Z))
        (d (d (Injective.ι Z)))
        (_ :
          { fst := under Z, snd := { fst := syzygies (Injective.ι Z), snd := d (Injective.ι Z) } }.snd.snd ≫
              {
                    fst :=
                      syzygies
                        { fst := under Z, snd := { fst := syzygies (Injective.ι Z), snd := d (Injective.ι Z) } }.2.snd,
                    snd :=
                      {
                        fst :=
                          d
                            { fst := under Z,
                                  snd := { fst := syzygies (Injective.ι Z), snd := d (Injective.ι Z) } }.2.snd,
                        snd :=
                          (_ :
                            { fst := under Z,
                                      snd := { fst := syzygies (Injective.ι Z), snd := d (Injective.ι Z) } }.2.snd ≫
                                d
                                  { fst := under Z,
                                        snd := { fst := syzygies (Injective.ι Z), snd := d (Injective.ι Z) } }.2.snd =
                              0) } }.snd.fst =
            0)
        (fun t =>
          { fst := syzygies t.snd.snd.snd.snd.fst,
            snd :=
              { fst := d t.snd.snd.snd.snd.fst, snd := (_ : t.snd.snd.snd.snd.fst ≫ d t.snd.snd.snd.snd.fst = 0) } })
        (0 + 1)).d₀
[PROOFSTEP]
apply exact_f_d
[GOAL]
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : EnoughInjectives C
Z : C
n m : ℕ
⊢ Exact (HomologicalComplex.d (ofCocomplex Z) (m + 1) (m + 1 + 1))
    (HomologicalComplex.d (ofCocomplex Z) (m + 1 + 1) (m + 1 + 2))
[PROOFSTEP]
simp only [ofCocomplex_X, ComplexShape.up_Rel, not_true, ofCocomplex_d, eqToHom_refl, Category.comp_id, dite_eq_ite,
  ite_true]
[GOAL]
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : EnoughInjectives C
Z : C
n m : ℕ
⊢ Exact
    (CochainComplex.mkAux (under Z) (syzygies (Injective.ι Z)) (syzygies (d (Injective.ι Z))) (d (Injective.ι Z))
        (d (d (Injective.ι Z)))
        (_ :
          { fst := under Z, snd := { fst := syzygies (Injective.ι Z), snd := d (Injective.ι Z) } }.snd.snd ≫
              {
                    fst :=
                      syzygies
                        { fst := under Z, snd := { fst := syzygies (Injective.ι Z), snd := d (Injective.ι Z) } }.2.snd,
                    snd :=
                      {
                        fst :=
                          d
                            { fst := under Z,
                                  snd := { fst := syzygies (Injective.ι Z), snd := d (Injective.ι Z) } }.2.snd,
                        snd :=
                          (_ :
                            { fst := under Z,
                                      snd := { fst := syzygies (Injective.ι Z), snd := d (Injective.ι Z) } }.2.snd ≫
                                d
                                  { fst := under Z,
                                        snd := { fst := syzygies (Injective.ι Z), snd := d (Injective.ι Z) } }.2.snd =
                              0) } }.snd.fst =
            0)
        (fun t =>
          { fst := syzygies t.snd.snd.snd.snd.fst,
            snd :=
              { fst := d t.snd.snd.snd.snd.fst, snd := (_ : t.snd.snd.snd.snd.fst ≫ d t.snd.snd.snd.snd.fst = 0) } })
        (m + 1)).d₀
    (if m + 1 + 1 + 1 = m + 1 + 2 then
      (CochainComplex.mkAux (under Z) (syzygies (Injective.ι Z)) (syzygies (d (Injective.ι Z))) (d (Injective.ι Z))
          (d (d (Injective.ι Z)))
          (_ :
            { fst := under Z, snd := { fst := syzygies (Injective.ι Z), snd := d (Injective.ι Z) } }.snd.snd ≫
                {
                      fst :=
                        syzygies
                          { fst := under Z,
                                snd := { fst := syzygies (Injective.ι Z), snd := d (Injective.ι Z) } }.2.snd,
                      snd :=
                        {
                          fst :=
                            d
                              { fst := under Z,
                                    snd := { fst := syzygies (Injective.ι Z), snd := d (Injective.ι Z) } }.2.snd,
                          snd :=
                            (_ :
                              { fst := under Z,
                                        snd := { fst := syzygies (Injective.ι Z), snd := d (Injective.ι Z) } }.2.snd ≫
                                  d
                                    { fst := under Z,
                                          snd := { fst := syzygies (Injective.ι Z), snd := d (Injective.ι Z) } }.2.snd =
                                0) } }.snd.fst =
              0)
          (fun t =>
            { fst := syzygies t.snd.snd.snd.snd.fst,
              snd :=
                { fst := d t.snd.snd.snd.snd.fst, snd := (_ : t.snd.snd.snd.snd.fst ≫ d t.snd.snd.snd.snd.fst = 0) } })
          (m + 1 + 1)).d₀
    else 0)
[PROOFSTEP]
erw [if_pos (c := m + 1 + 1 + 1 = m + 2 + 1) rfl]
[GOAL]
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : EnoughInjectives C
Z : C
n m : ℕ
⊢ Exact
    (CochainComplex.mkAux (under Z) (syzygies (Injective.ι Z)) (syzygies (d (Injective.ι Z))) (d (Injective.ι Z))
        (d (d (Injective.ι Z)))
        (_ :
          { fst := under Z, snd := { fst := syzygies (Injective.ι Z), snd := d (Injective.ι Z) } }.snd.snd ≫
              {
                    fst :=
                      syzygies
                        { fst := under Z, snd := { fst := syzygies (Injective.ι Z), snd := d (Injective.ι Z) } }.2.snd,
                    snd :=
                      {
                        fst :=
                          d
                            { fst := under Z,
                                  snd := { fst := syzygies (Injective.ι Z), snd := d (Injective.ι Z) } }.2.snd,
                        snd :=
                          (_ :
                            { fst := under Z,
                                      snd := { fst := syzygies (Injective.ι Z), snd := d (Injective.ι Z) } }.2.snd ≫
                                d
                                  { fst := under Z,
                                        snd := { fst := syzygies (Injective.ι Z), snd := d (Injective.ι Z) } }.2.snd =
                              0) } }.snd.fst =
            0)
        (fun t =>
          { fst := syzygies t.snd.snd.snd.snd.fst,
            snd :=
              { fst := d t.snd.snd.snd.snd.fst, snd := (_ : t.snd.snd.snd.snd.fst ≫ d t.snd.snd.snd.snd.fst = 0) } })
        (m + 1)).d₀
    (CochainComplex.mkAux (under Z) (syzygies (Injective.ι Z)) (syzygies (d (Injective.ι Z))) (d (Injective.ι Z))
        (d (d (Injective.ι Z)))
        (_ :
          { fst := under Z, snd := { fst := syzygies (Injective.ι Z), snd := d (Injective.ι Z) } }.snd.snd ≫
              {
                    fst :=
                      syzygies
                        { fst := under Z, snd := { fst := syzygies (Injective.ι Z), snd := d (Injective.ι Z) } }.2.snd,
                    snd :=
                      {
                        fst :=
                          d
                            { fst := under Z,
                                  snd := { fst := syzygies (Injective.ι Z), snd := d (Injective.ι Z) } }.2.snd,
                        snd :=
                          (_ :
                            { fst := under Z,
                                      snd := { fst := syzygies (Injective.ι Z), snd := d (Injective.ι Z) } }.2.snd ≫
                                d
                                  { fst := under Z,
                                        snd := { fst := syzygies (Injective.ι Z), snd := d (Injective.ι Z) } }.2.snd =
                              0) } }.snd.fst =
            0)
        (fun t =>
          { fst := syzygies t.snd.snd.snd.snd.fst,
            snd :=
              { fst := d t.snd.snd.snd.snd.fst, snd := (_ : t.snd.snd.snd.snd.fst ≫ d t.snd.snd.snd.snd.fst = 0) } })
        (m + 1 + 1)).d₀
[PROOFSTEP]
apply exact_f_d
[GOAL]
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : EnoughInjectives C
Z : C
n : ℕ
x✝ :
  (f : HomologicalComplex.X ((CochainComplex.single₀ C).obj Z) n ⟶ HomologicalComplex.X (ofCocomplex Z) n) ×'
    (f' :
      HomologicalComplex.X ((CochainComplex.single₀ C).obj Z) (n + 1) ⟶ HomologicalComplex.X (ofCocomplex Z) (n + 1)) ×'
      f ≫ HomologicalComplex.d (ofCocomplex Z) n (n + 1) =
        HomologicalComplex.d ((CochainComplex.single₀ C).obj Z) n (n + 1) ≫ f'
⊢ (f'' :
    HomologicalComplex.X ((CochainComplex.single₀ C).obj Z) (n + 2) ⟶ HomologicalComplex.X (ofCocomplex Z) (n + 2)) ×'
    x✝.snd.fst ≫ HomologicalComplex.d (ofCocomplex Z) (n + 1) (n + 2) =
      HomologicalComplex.d ((CochainComplex.single₀ C).obj Z) (n + 1) (n + 2) ≫ f''
[PROOFSTEP]
use 0
[GOAL]
case snd
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : EnoughInjectives C
Z : C
n : ℕ
x✝ :
  (f : HomologicalComplex.X ((CochainComplex.single₀ C).obj Z) n ⟶ HomologicalComplex.X (ofCocomplex Z) n) ×'
    (f' :
      HomologicalComplex.X ((CochainComplex.single₀ C).obj Z) (n + 1) ⟶ HomologicalComplex.X (ofCocomplex Z) (n + 1)) ×'
      f ≫ HomologicalComplex.d (ofCocomplex Z) n (n + 1) =
        HomologicalComplex.d ((CochainComplex.single₀ C).obj Z) n (n + 1) ≫ f'
⊢ x✝.snd.fst ≫ HomologicalComplex.d (ofCocomplex Z) (n + 1) (n + 2) =
    HomologicalComplex.d ((CochainComplex.single₀ C).obj Z) (n + 1) (n + 2) ≫ 0
[PROOFSTEP]
apply HasZeroObject.from_zero_ext
[GOAL]
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : EnoughInjectives C
Z : C
⊢ ∀ (n : ℕ), Injective (HomologicalComplex.X (ofCocomplex Z) n)
[PROOFSTEP]
rintro (_ | _ | _ | n)
[GOAL]
case zero
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : EnoughInjectives C
Z : C
⊢ Injective (HomologicalComplex.X (ofCocomplex Z) Nat.zero)
[PROOFSTEP]
apply Injective.injective_under
[GOAL]
case succ.zero
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : EnoughInjectives C
Z : C
⊢ Injective (HomologicalComplex.X (ofCocomplex Z) (Nat.succ Nat.zero))
[PROOFSTEP]
apply Injective.injective_under
[GOAL]
case succ.succ.zero
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : EnoughInjectives C
Z : C
⊢ Injective (HomologicalComplex.X (ofCocomplex Z) (Nat.succ (Nat.succ Nat.zero)))
[PROOFSTEP]
apply Injective.injective_under
[GOAL]
case succ.succ.succ
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : EnoughInjectives C
Z : C
n : ℕ
⊢ Injective (HomologicalComplex.X (ofCocomplex Z) (Nat.succ (Nat.succ (Nat.succ n))))
[PROOFSTEP]
apply Injective.injective_under
[GOAL]
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : EnoughInjectives C
Z : C
⊢ Exact
    (HomologicalComplex.Hom.f
      (CochainComplex.mkHom ((CochainComplex.single₀ C).obj Z) (ofCocomplex Z) (Injective.ι Z) 0
        (_ :
          Injective.ι Z ≫ HomologicalComplex.d (ofCocomplex Z) 0 1 =
            HomologicalComplex.d ((CochainComplex.single₀ C).obj Z) 0 1 ≫ 0)
        fun n x =>
        { fst := 0,
          snd :=
            (_ :
              x.snd.fst ≫ HomologicalComplex.d (ofCocomplex Z) (n + 1) (n + 2) =
                HomologicalComplex.d ((CochainComplex.single₀ C).obj Z) (n + 1) (n + 2) ≫ 0) })
      0)
    (HomologicalComplex.d (ofCocomplex Z) 0 1)
[PROOFSTEP]
simpa using exact_f_d (Injective.ι Z)


[GOAL]
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : Abelian C
inst✝¹ : HasLimits C
inst✝ : EnoughInjectives C
G : C
hG : IsSeparator G
⊢ ∃ G, Injective G ∧ IsCoseparator G
[PROOFSTEP]
haveI : WellPowered C := wellPowered_of_isDetector G hG.isDetector
[GOAL]
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : Abelian C
inst✝¹ : HasLimits C
inst✝ : EnoughInjectives C
G : C
hG : IsSeparator G
this : WellPowered C
⊢ ∃ G, Injective G ∧ IsCoseparator G
[PROOFSTEP]
haveI : HasProductsOfShape (Subobject (op G)) C := hasProductsOfShape_of_small _ _
[GOAL]
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : Abelian C
inst✝¹ : HasLimits C
inst✝ : EnoughInjectives C
G : C
hG : IsSeparator G
this✝ : WellPowered C
this : HasProductsOfShape (Subobject (op G)) C
⊢ ∃ G, Injective G ∧ IsCoseparator G
[PROOFSTEP]
let T : C := Injective.under (piObj fun P : Subobject (op G) => unop P)
[GOAL]
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : Abelian C
inst✝¹ : HasLimits C
inst✝ : EnoughInjectives C
G : C
hG : IsSeparator G
this✝ : WellPowered C
this : HasProductsOfShape (Subobject (op G)) C
T : C := Injective.under (∏ fun P => (Subobject.underlying.obj P).unop)
⊢ ∃ G, Injective G ∧ IsCoseparator G
[PROOFSTEP]
refine' ⟨T, inferInstance, (Preadditive.isCoseparator_iff _).2 fun X Y f hf => _⟩
[GOAL]
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : Abelian C
inst✝¹ : HasLimits C
inst✝ : EnoughInjectives C
G : C
hG : IsSeparator G
this✝ : WellPowered C
this : HasProductsOfShape (Subobject (op G)) C
T : C := Injective.under (∏ fun P => (Subobject.underlying.obj P).unop)
X Y : C
f : X ⟶ Y
hf : ∀ (h : Y ⟶ T), f ≫ h = 0
⊢ f = 0
[PROOFSTEP]
refine' (Preadditive.isSeparator_iff _).1 hG _ fun h => _
[GOAL]
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : Abelian C
inst✝¹ : HasLimits C
inst✝ : EnoughInjectives C
G : C
hG : IsSeparator G
this✝ : WellPowered C
this : HasProductsOfShape (Subobject (op G)) C
T : C := Injective.under (∏ fun P => (Subobject.underlying.obj P).unop)
X Y : C
f : X ⟶ Y
hf : ∀ (h : Y ⟶ T), f ≫ h = 0
h : G ⟶ X
⊢ h ≫ f = 0
[PROOFSTEP]
suffices hh : factorThruImage (h ≫ f) = 0
[GOAL]
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : Abelian C
inst✝¹ : HasLimits C
inst✝ : EnoughInjectives C
G : C
hG : IsSeparator G
this✝ : WellPowered C
this : HasProductsOfShape (Subobject (op G)) C
T : C := Injective.under (∏ fun P => (Subobject.underlying.obj P).unop)
X Y : C
f : X ⟶ Y
hf : ∀ (h : Y ⟶ T), f ≫ h = 0
h : G ⟶ X
hh : factorThruImage (h ≫ f) = 0
⊢ h ≫ f = 0
[PROOFSTEP]
rw [← Limits.image.fac (h ≫ f), hh, zero_comp]
[GOAL]
case hh
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : Abelian C
inst✝¹ : HasLimits C
inst✝ : EnoughInjectives C
G : C
hG : IsSeparator G
this✝ : WellPowered C
this : HasProductsOfShape (Subobject (op G)) C
T : C := Injective.under (∏ fun P => (Subobject.underlying.obj P).unop)
X Y : C
f : X ⟶ Y
hf : ∀ (h : Y ⟶ T), f ≫ h = 0
h : G ⟶ X
⊢ factorThruImage (h ≫ f) = 0
[PROOFSTEP]
let R := Subobject.mk (factorThruImage (h ≫ f)).op
[GOAL]
case hh
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : Abelian C
inst✝¹ : HasLimits C
inst✝ : EnoughInjectives C
G : C
hG : IsSeparator G
this✝ : WellPowered C
this : HasProductsOfShape (Subobject (op G)) C
T : C := Injective.under (∏ fun P => (Subobject.underlying.obj P).unop)
X Y : C
f : X ⟶ Y
hf : ∀ (h : Y ⟶ T), f ≫ h = 0
h : G ⟶ X
R : Subobject (op G) := Subobject.mk (factorThruImage (h ≫ f)).op
⊢ factorThruImage (h ≫ f) = 0
[PROOFSTEP]
let q₁ : image (h ≫ f) ⟶ unop R := (Subobject.underlyingIso (factorThruImage (h ≫ f)).op).unop.hom
[GOAL]
case hh
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : Abelian C
inst✝¹ : HasLimits C
inst✝ : EnoughInjectives C
G : C
hG : IsSeparator G
this✝ : WellPowered C
this : HasProductsOfShape (Subobject (op G)) C
T : C := Injective.under (∏ fun P => (Subobject.underlying.obj P).unop)
X Y : C
f : X ⟶ Y
hf : ∀ (h : Y ⟶ T), f ≫ h = 0
h : G ⟶ X
R : Subobject (op G) := Subobject.mk (factorThruImage (h ≫ f)).op
q₁ : image (h ≫ f) ⟶ (Subobject.underlying.obj R).unop :=
  (Iso.unop (Subobject.underlyingIso (factorThruImage (h ≫ f)).op)).hom
⊢ factorThruImage (h ≫ f) = 0
[PROOFSTEP]
let q₂ : unop (R : Cᵒᵖ) ⟶ piObj fun P : Subobject (op G) => unop P :=
  section_ (Pi.π (fun P : Subobject (op G) => (unop P : C)) R)
[GOAL]
case hh
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : Abelian C
inst✝¹ : HasLimits C
inst✝ : EnoughInjectives C
G : C
hG : IsSeparator G
this✝ : WellPowered C
this : HasProductsOfShape (Subobject (op G)) C
T : C := Injective.under (∏ fun P => (Subobject.underlying.obj P).unop)
X Y : C
f : X ⟶ Y
hf : ∀ (h : Y ⟶ T), f ≫ h = 0
h : G ⟶ X
R : Subobject (op G) := Subobject.mk (factorThruImage (h ≫ f)).op
q₁ : image (h ≫ f) ⟶ (Subobject.underlying.obj R).unop :=
  (Iso.unop (Subobject.underlyingIso (factorThruImage (h ≫ f)).op)).hom
q₂ : (Subobject.underlying.obj R).unop ⟶ ∏ fun P => (Subobject.underlying.obj P).unop :=
  section_ (Pi.π (fun P => (Subobject.underlying.obj P).unop) R)
⊢ factorThruImage (h ≫ f) = 0
[PROOFSTEP]
let q : image (h ≫ f) ⟶ T := q₁ ≫ q₂ ≫ Injective.ι _
[GOAL]
case hh
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : Abelian C
inst✝¹ : HasLimits C
inst✝ : EnoughInjectives C
G : C
hG : IsSeparator G
this✝ : WellPowered C
this : HasProductsOfShape (Subobject (op G)) C
T : C := Injective.under (∏ fun P => (Subobject.underlying.obj P).unop)
X Y : C
f : X ⟶ Y
hf : ∀ (h : Y ⟶ T), f ≫ h = 0
h : G ⟶ X
R : Subobject (op G) := Subobject.mk (factorThruImage (h ≫ f)).op
q₁ : image (h ≫ f) ⟶ (Subobject.underlying.obj R).unop :=
  (Iso.unop (Subobject.underlyingIso (factorThruImage (h ≫ f)).op)).hom
q₂ : (Subobject.underlying.obj R).unop ⟶ ∏ fun P => (Subobject.underlying.obj P).unop :=
  section_ (Pi.π (fun P => (Subobject.underlying.obj P).unop) R)
q : image (h ≫ f) ⟶ T := q₁ ≫ q₂ ≫ Injective.ι (∏ fun P => (Subobject.underlying.obj P).unop)
⊢ factorThruImage (h ≫ f) = 0
[PROOFSTEP]
exact
  zero_of_comp_mono q
    (by
      rw [← Injective.comp_factorThru q (Limits.image.ι (h ≫ f)), Limits.image.fac_assoc, Category.assoc, hf,
        comp_zero])
[GOAL]
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : Abelian C
inst✝¹ : HasLimits C
inst✝ : EnoughInjectives C
G : C
hG : IsSeparator G
this✝ : WellPowered C
this : HasProductsOfShape (Subobject (op G)) C
T : C := Injective.under (∏ fun P => (Subobject.underlying.obj P).unop)
X Y : C
f : X ⟶ Y
hf : ∀ (h : Y ⟶ T), f ≫ h = 0
h : G ⟶ X
R : Subobject (op G) := Subobject.mk (factorThruImage (h ≫ f)).op
q₁ : image (h ≫ f) ⟶ (Subobject.underlying.obj R).unop :=
  (Iso.unop (Subobject.underlyingIso (factorThruImage (h ≫ f)).op)).hom
q₂ : (Subobject.underlying.obj R).unop ⟶ ∏ fun P => (Subobject.underlying.obj P).unop :=
  section_ (Pi.π (fun P => (Subobject.underlying.obj P).unop) R)
q : image (h ≫ f) ⟶ T := q₁ ≫ q₂ ≫ Injective.ι (∏ fun P => (Subobject.underlying.obj P).unop)
⊢ factorThruImage (h ≫ f) ≫ q = 0
[PROOFSTEP]
rw [← Injective.comp_factorThru q (Limits.image.ι (h ≫ f)), Limits.image.fac_assoc, Category.assoc, hf, comp_zero]
[GOAL]
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : Abelian C
inst✝¹ : HasColimits C
inst✝ : EnoughProjectives C
G : C
hG : IsCoseparator G
⊢ ∃ G, Projective G ∧ IsSeparator G
[PROOFSTEP]
obtain ⟨T, hT₁, hT₂⟩ := has_injective_coseparator (op G) ((isSeparator_op_iff _).2 hG)
[GOAL]
case intro.intro
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : Abelian C
inst✝¹ : HasColimits C
inst✝ : EnoughProjectives C
G : C
hG : IsCoseparator G
T : Cᵒᵖ
hT₁ : Injective T
hT₂ : IsCoseparator T
⊢ ∃ G, Projective G ∧ IsSeparator G
[PROOFSTEP]
exact ⟨unop T, inferInstance, (isSeparator_unop_iff _).2 hT₂⟩