l3lab/ntp-mathlib huggingface dataset:
/-- When `f : X ⟶ Y` and `P : Subobject Y`,
`P.Factors f` expresses that there exists a factorisation of `f` through `P`.
Given `h : P.Factors f`, you can recover the morphism as `P.factorThru f h`.
-/
def Factors {X Y : C} (P : Subobject Y) (f : X ⟶ Y) : Prop :=
  Quotient.liftOn' P (fun P => P.Factors f)
    (by
      

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
X✝ Y✝ Z : C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
X Y : C
P : Subobject Y
f : X ⟶ Y
⊢ ∀ (a b : MonoOver Y), Setoid.r a b → (fun P => MonoOver.Factors P f) a = (fun P => MonoOver.Factors P f) b

Next tactic:
rintro P Q ⟨h⟩
/-- When `f : X ⟶ Y` and `P : Subobject Y`,
`P.Factors f` expresses that there exists a factorisation of `f` through `P`.
Given `h : P.Factors f`, you can recover the morphism as `P.factorThru f h`.
-/
def Factors {X Y : C} (P : Subobject Y) (f : X ⟶ Y) : Prop :=
  Quotient.liftOn' P (fun P => P.Factors f)
    (by
      rintro P Q ⟨h⟩
      

Proof state:
case intro
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
X✝ Y✝ Z : C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
X Y : C
P✝ : Subobject Y
f : X ⟶ Y
P Q : MonoOver Y
h : P ≅ Q
⊢ (fun P => MonoOver.Factors P f) P = (fun P => MonoOver.Factors P f) Q

Next tactic:
apply propext
/-- When `f : X ⟶ Y` and `P : Subobject Y`,
`P.Factors f` expresses that there exists a factorisation of `f` through `P`.
Given `h : P.Factors f`, you can recover the morphism as `P.factorThru f h`.
-/
def Factors {X Y : C} (P : Subobject Y) (f : X ⟶ Y) : Prop :=
  Quotient.liftOn' P (fun P => P.Factors f)
    (by
      rintro P Q ⟨h⟩
      apply propext
      

Proof state:
case intro.a
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
X✝ Y✝ Z : C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
X Y : C
P✝ : Subobject Y
f : X ⟶ Y
P Q : MonoOver Y
h : P ≅ Q
⊢ (fun P => MonoOver.Factors P f) P ↔ (fun P => MonoOver.Factors P f) Q

Next tactic:
constructor
/-- When `f : X ⟶ Y` and `P : Subobject Y`,
`P.Factors f` expresses that there exists a factorisation of `f` through `P`.
Given `h : P.Factors f`, you can recover the morphism as `P.factorThru f h`.
-/
def Factors {X Y : C} (P : Subobject Y) (f : X ⟶ Y) : Prop :=
  Quotient.liftOn' P (fun P => P.Factors f)
    (by
      rintro P Q ⟨h⟩
      apply propext
      constructor
      · 

Proof state:
case intro.a.mp
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
X✝ Y✝ Z : C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
X Y : C
P✝ : Subobject Y
f : X ⟶ Y
P Q : MonoOver Y
h : P ≅ Q
⊢ (fun P => MonoOver.Factors P f) P → (fun P => MonoOver.Factors P f) Q

Next tactic:
rintro ⟨i, w⟩
/-- When `f : X ⟶ Y` and `P : Subobject Y`,
`P.Factors f` expresses that there exists a factorisation of `f` through `P`.
Given `h : P.Factors f`, you can recover the morphism as `P.factorThru f h`.
-/
def Factors {X Y : C} (P : Subobject Y) (f : X ⟶ Y) : Prop :=
  Quotient.liftOn' P (fun P => P.Factors f)
    (by
      rintro P Q ⟨h⟩
      apply propext
      constructor
      · rintro ⟨i, w⟩
        

Proof state:
case intro.a.mp.intro
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
X✝ Y✝ Z : C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
X Y : C
P✝ : Subobject Y
f : X ⟶ Y
P Q : MonoOver Y
h : P ≅ Q
i : X ⟶ P.obj.left
w : i ≫ MonoOver.arrow P = f
⊢ MonoOver.Factors Q f

Next tactic:
exact ⟨i ≫ h.hom.left, by erw [Category.assoc, Over.w h.hom, w]⟩
/-- When `f : X ⟶ Y` and `P : Subobject Y`,
`P.Factors f` expresses that there exists a factorisation of `f` through `P`.
Given `h : P.Factors f`, you can recover the morphism as `P.factorThru f h`.
-/
def Factors {X Y : C} (P : Subobject Y) (f : X ⟶ Y) : Prop :=
  Quotient.liftOn' P (fun P => P.Factors f)
    (by
      rintro P Q ⟨h⟩
      apply propext
      constructor
      · rintro ⟨i, w⟩
        exact ⟨i ≫ h.hom.left, by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
X✝ Y✝ Z : C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
X Y : C
P✝ : Subobject Y
f : X ⟶ Y
P Q : MonoOver Y
h : P ≅ Q
i : X ⟶ P.obj.left
w : i ≫ MonoOver.arrow P = f
⊢ (i ≫ h.hom.left) ≫ MonoOver.arrow Q = f

Next tactic:
erw [Category.assoc, Over.w h.hom, w]
/-- When `f : X ⟶ Y` and `P : Subobject Y`,
`P.Factors f` expresses that there exists a factorisation of `f` through `P`.
Given `h : P.Factors f`, you can recover the morphism as `P.factorThru f h`.
-/
def Factors {X Y : C} (P : Subobject Y) (f : X ⟶ Y) : Prop :=
  Quotient.liftOn' P (fun P => P.Factors f)
    (by
      rintro P Q ⟨h⟩
      apply propext
      constructor
      · rintro ⟨i, w⟩
        exact ⟨i ≫ h.hom.left, by erw [Category.assoc, Over.w h.hom, w]⟩
      · 

Proof state:
case intro.a.mpr
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
X✝ Y✝ Z : C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
X Y : C
P✝ : Subobject Y
f : X ⟶ Y
P Q : MonoOver Y
h : P ≅ Q
⊢ (fun P => MonoOver.Factors P f) Q → (fun P => MonoOver.Factors P f) P

Next tactic:
rintro ⟨i, w⟩
/-- When `f : X ⟶ Y` and `P : Subobject Y`,
`P.Factors f` expresses that there exists a factorisation of `f` through `P`.
Given `h : P.Factors f`, you can recover the morphism as `P.factorThru f h`.
-/
def Factors {X Y : C} (P : Subobject Y) (f : X ⟶ Y) : Prop :=
  Quotient.liftOn' P (fun P => P.Factors f)
    (by
      rintro P Q ⟨h⟩
      apply propext
      constructor
      · rintro ⟨i, w⟩
        exact ⟨i ≫ h.hom.left, by erw [Category.assoc, Over.w h.hom, w]⟩
      · rintro ⟨i, w⟩
        

Proof state:
case intro.a.mpr.intro
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
X✝ Y✝ Z : C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
X Y : C
P✝ : Subobject Y
f : X ⟶ Y
P Q : MonoOver Y
h : P ≅ Q
i : X ⟶ Q.obj.left
w : i ≫ MonoOver.arrow Q = f
⊢ MonoOver.Factors P f

Next tactic:
exact ⟨i ≫ h.inv.left, by erw [Category.assoc, Over.w h.inv, w]⟩
/-- When `f : X ⟶ Y` and `P : Subobject Y`,
`P.Factors f` expresses that there exists a factorisation of `f` through `P`.
Given `h : P.Factors f`, you can recover the morphism as `P.factorThru f h`.
-/
def Factors {X Y : C} (P : Subobject Y) (f : X ⟶ Y) : Prop :=
  Quotient.liftOn' P (fun P => P.Factors f)
    (by
      rintro P Q ⟨h⟩
      apply propext
      constructor
      · rintro ⟨i, w⟩
        exact ⟨i ≫ h.hom.left, by erw [Category.assoc, Over.w h.hom, w]⟩
      · rintro ⟨i, w⟩
        exact ⟨i ≫ h.inv.left, by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
X✝ Y✝ Z : C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
X Y : C
P✝ : Subobject Y
f : X ⟶ Y
P Q : MonoOver Y
h : P ≅ Q
i : X ⟶ Q.obj.left
w : i ≫ MonoOver.arrow Q = f
⊢ (i ≫ h.inv.left) ≫ MonoOver.arrow P = f

Next tactic:
erw [Category.assoc, Over.w h.inv, w]
theorem mk_factors_self (f : X ⟶ Y) [Mono f] : (mk f).Factors f :=
  ⟨𝟙 _, by 

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
X Y Z : C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
f : X ⟶ Y
inst✝ : Mono f
⊢ 𝟙 X ≫ MonoOver.arrow (MonoOver.mk' f) = f

Next tactic:
simp
theorem factors_self {X : C} (P : Subobject X) : P.Factors P.arrow :=
  (factors_iff _ _).mpr ⟨𝟙 (P : C), by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
X✝ Y Z : C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
X : C
P : Subobject X
⊢ 𝟙 (underlying.obj P) ≫ MonoOver.arrow (representative.obj P) = arrow P

Next tactic:
simp
theorem factors_of_factors_right {X Y Z : C} {P : Subobject Z} (f : X ⟶ Y) {g : Y ⟶ Z}
    (h : P.Factors g) : P.Factors (f ≫ g) := by
  

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
X✝ Y✝ Z✝ : C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
X Y Z : C
P : Subobject Z
f : X ⟶ Y
g : Y ⟶ Z
h : Factors P g
⊢ Factors P (f ≫ g)

Next tactic:
induction' P using Quotient.ind' with P
theorem factors_of_factors_right {X Y Z : C} {P : Subobject Z} (f : X ⟶ Y) {g : Y ⟶ Z}
    (h : P.Factors g) : P.Factors (f ≫ g) := by
  induction' P using Quotient.ind' with P
  

Proof state:
case h
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
X✝ Y✝ Z✝ : C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
X Y Z : C
f : X ⟶ Y
g : Y ⟶ Z
P : MonoOver Z
h : Factors (Quotient.mk'' P) g
⊢ Factors (Quotient.mk'' P) (f ≫ g)

Next tactic:
obtain ⟨g, rfl⟩ := h
theorem factors_of_factors_right {X Y Z : C} {P : Subobject Z} (f : X ⟶ Y) {g : Y ⟶ Z}
    (h : P.Factors g) : P.Factors (f ≫ g) := by
  induction' P using Quotient.ind' with P
  obtain ⟨g, rfl⟩ := h
  

Proof state:
case h.intro
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
X✝ Y✝ Z✝ : C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
X Y Z : C
f : X ⟶ Y
P : MonoOver Z
g : Y ⟶ P.obj.left
⊢ Factors (Quotient.mk'' P) (f ≫ g ≫ MonoOver.arrow P)

Next tactic:
exact ⟨f ≫ g, by simp⟩
theorem factors_of_factors_right {X Y Z : C} {P : Subobject Z} (f : X ⟶ Y) {g : Y ⟶ Z}
    (h : P.Factors g) : P.Factors (f ≫ g) := by
  induction' P using Quotient.ind' with P
  obtain ⟨g, rfl⟩ := h
  exact ⟨f ≫ g, by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
X✝ Y✝ Z✝ : C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
X Y Z : C
f : X ⟶ Y
P : MonoOver Z
g : Y ⟶ P.obj.left
⊢ (f ≫ g) ≫ MonoOver.arrow P = f ≫ g ≫ MonoOver.arrow P

Next tactic:
simp
theorem factors_zero [HasZeroMorphisms C] {X Y : C} {P : Subobject Y} : P.Factors (0 : X ⟶ Y) :=
  (factors_iff _ _).mpr ⟨0, by 

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
X✝ Y✝ Z : C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
inst✝ : HasZeroMorphisms C
X Y : C
P : Subobject Y
⊢ 0 ≫ MonoOver.arrow (representative.obj P) = 0

Next tactic:
simp
theorem factors_of_le {Y Z : C} {P Q : Subobject Y} (f : Z ⟶ Y) (h : P ≤ Q) :
    P.Factors f → Q.Factors f := by
  

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
X Y✝ Z✝ : C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
Y Z : C
P Q : Subobject Y
f : Z ⟶ Y
h : P ≤ Q
⊢ Factors P f → Factors Q f

Next tactic:
simp only [factors_iff]
theorem factors_of_le {Y Z : C} {P Q : Subobject Y} (f : Z ⟶ Y) (h : P ≤ Q) :
    P.Factors f → Q.Factors f := by
  simp only [factors_iff]
  

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
X Y✝ Z✝ : C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
Y Z : C
P Q : Subobject Y
f : Z ⟶ Y
h : P ≤ Q
⊢ MonoOver.Factors (representative.obj P) f → MonoOver.Factors (representative.obj Q) f

Next tactic:
exact fun ⟨u, hu⟩ => ⟨u ≫ ofLE _ _ h, by simp [← hu]⟩
theorem factors_of_le {Y Z : C} {P Q : Subobject Y} (f : Z ⟶ Y) (h : P ≤ Q) :
    P.Factors f → Q.Factors f := by
  simp only [factors_iff]
  exact fun ⟨u, hu⟩ => ⟨u ≫ ofLE _ _ h, by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
X Y✝ Z✝ : C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
Y Z : C
P Q : Subobject Y
f : Z ⟶ Y
h : P ≤ Q
x✝ : MonoOver.Factors (representative.obj P) f
u : Z ⟶ (representative.obj P).obj.left
hu : u ≫ MonoOver.arrow (representative.obj P) = f
⊢ (u ≫ ofLE P Q h) ≫ MonoOver.arrow (representative.obj Q) = f

Next tactic:
simp [← hu]
@[simp]
theorem factorThru_self {X : C} (P : Subobject X) (h) : P.factorThru P.arrow h = 𝟙 (P : C) := by
  

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
X✝ Y Z : C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
X : C
P : Subobject X
h : Factors P (arrow P)
⊢ factorThru P (arrow P) h = 𝟙 (underlying.obj P)

Next tactic:
ext
@[simp]
theorem factorThru_self {X : C} (P : Subobject X) (h) : P.factorThru P.arrow h = 𝟙 (P : C) := by
  ext
  

Proof state:
case h
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
X✝ Y Z : C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
X : C
P : Subobject X
h : Factors P (arrow P)
⊢ factorThru P (arrow P) h ≫ arrow P = 𝟙 (underlying.obj P) ≫ arrow P

Next tactic:
simp
@[simp]
theorem factorThru_mk_self (f : X ⟶ Y) [Mono f] :
    (mk f).factorThru f (mk_factors_self f) = (underlyingIso f).inv := by
  

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
X Y Z : C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
f : X ⟶ Y
inst✝ : Mono f
⊢ factorThru (mk f) f (_ : Factors (mk f) f) = (underlyingIso f).inv

Next tactic:
ext
@[simp]
theorem factorThru_mk_self (f : X ⟶ Y) [Mono f] :
    (mk f).factorThru f (mk_factors_self f) = (underlyingIso f).inv := by
  ext
  

Proof state:
case h
C : Type u₁
inst✝² : Category.{v₁, u₁} C
X Y Z : C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
f : X ⟶ Y
inst✝ : Mono f
⊢ factorThru (mk f) f (_ : Factors (mk f) f) ≫ arrow (mk f) = (underlyingIso f).inv ≫ arrow (mk f)

Next tactic:
simp
@[simp]
theorem factorThru_comp_arrow {X Y : C} {P : Subobject Y} (f : X ⟶ P) (h) :
    P.factorThru (f ≫ P.arrow) h = f := by
  

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
X✝ Y✝ Z : C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
X Y : C
P : Subobject Y
f : X ⟶ underlying.obj P
h : Factors P (f ≫ arrow P)
⊢ factorThru P (f ≫ arrow P) h = f

Next tactic:
ext
@[simp]
theorem factorThru_comp_arrow {X Y : C} {P : Subobject Y} (f : X ⟶ P) (h) :
    P.factorThru (f ≫ P.arrow) h = f := by
  ext
  

Proof state:
case h
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
X✝ Y✝ Z : C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
X Y : C
P : Subobject Y
f : X ⟶ underlying.obj P
h : Factors P (f ≫ arrow P)
⊢ factorThru P (f ≫ arrow P) h ≫ arrow P = f ≫ arrow P

Next tactic:
simp
@[simp]
theorem factorThru_eq_zero [HasZeroMorphisms C] {X Y : C} {P : Subobject Y} {f : X ⟶ Y}
    {h : Factors P f} : P.factorThru f h = 0 ↔ f = 0 := by
  

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
X✝ Y✝ Z : C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
inst✝ : HasZeroMorphisms C
X Y : C
P : Subobject Y
f : X ⟶ Y
h : Factors P f
⊢ factorThru P f h = 0 ↔ f = 0

Next tactic:
fconstructor
@[simp]
theorem factorThru_eq_zero [HasZeroMorphisms C] {X Y : C} {P : Subobject Y} {f : X ⟶ Y}
    {h : Factors P f} : P.factorThru f h = 0 ↔ f = 0 := by
  fconstructor
  · 

Proof state:
case mp
C : Type u₁
inst✝² : Category.{v₁, u₁} C
X✝ Y✝ Z : C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
inst✝ : HasZeroMorphisms C
X Y : C
P : Subobject Y
f : X ⟶ Y
h : Factors P f
⊢ factorThru P f h = 0 → f = 0

Next tactic:
intro w
@[simp]
theorem factorThru_eq_zero [HasZeroMorphisms C] {X Y : C} {P : Subobject Y} {f : X ⟶ Y}
    {h : Factors P f} : P.factorThru f h = 0 ↔ f = 0 := by
  fconstructor
  · intro w
    

Proof state:
case mp
C : Type u₁
inst✝² : Category.{v₁, u₁} C
X✝ Y✝ Z : C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
inst✝ : HasZeroMorphisms C
X Y : C
P : Subobject Y
f : X ⟶ Y
h : Factors P f
w : factorThru P f h = 0
⊢ f = 0

Next tactic:
replace w := w =≫ P.arrow
@[simp]
theorem factorThru_eq_zero [HasZeroMorphisms C] {X Y : C} {P : Subobject Y} {f : X ⟶ Y}
    {h : Factors P f} : P.factorThru f h = 0 ↔ f = 0 := by
  fconstructor
  · intro w
    replace w := w =≫ P.arrow
    

Proof state:
case mp
C : Type u₁
inst✝² : Category.{v₁, u₁} C
X✝ Y✝ Z : C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
inst✝ : HasZeroMorphisms C
X Y : C
P : Subobject Y
f : X ⟶ Y
h : Factors P f
w : factorThru P f h ≫ arrow P = 0 ≫ arrow P
⊢ f = 0

Next tactic:
simpa using w
@[simp]
theorem factorThru_eq_zero [HasZeroMorphisms C] {X Y : C} {P : Subobject Y} {f : X ⟶ Y}
    {h : Factors P f} : P.factorThru f h = 0 ↔ f = 0 := by
  fconstructor
  · intro w
    replace w := w =≫ P.arrow
    simpa using w
  · 

Proof state:
case mpr
C : Type u₁
inst✝² : Category.{v₁, u₁} C
X✝ Y✝ Z : C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
inst✝ : HasZeroMorphisms C
X Y : C
P : Subobject Y
f : X ⟶ Y
h : Factors P f
⊢ f = 0 → factorThru P f h = 0

Next tactic:
rintro rfl
@[simp]
theorem factorThru_eq_zero [HasZeroMorphisms C] {X Y : C} {P : Subobject Y} {f : X ⟶ Y}
    {h : Factors P f} : P.factorThru f h = 0 ↔ f = 0 := by
  fconstructor
  · intro w
    replace w := w =≫ P.arrow
    simpa using w
  · rintro rfl
    

Proof state:
case mpr
C : Type u₁
inst✝² : Category.{v₁, u₁} C
X✝ Y✝ Z : C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
inst✝ : HasZeroMorphisms C
X Y : C
P : Subobject Y
h : Factors P 0
⊢ factorThru P 0 h = 0

Next tactic:
ext
@[simp]
theorem factorThru_eq_zero [HasZeroMorphisms C] {X Y : C} {P : Subobject Y} {f : X ⟶ Y}
    {h : Factors P f} : P.factorThru f h = 0 ↔ f = 0 := by
  fconstructor
  · intro w
    replace w := w =≫ P.arrow
    simpa using w
  · rintro rfl
    ext
    

Proof state:
case mpr.h
C : Type u₁
inst✝² : Category.{v₁, u₁} C
X✝ Y✝ Z : C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
inst✝ : HasZeroMorphisms C
X Y : C
P : Subobject Y
h : Factors P 0
⊢ factorThru P 0 h ≫ arrow P = 0 ≫ arrow P

Next tactic:
simp
theorem factorThru_right {X Y Z : C} {P : Subobject Z} (f : X ⟶ Y) (g : Y ⟶ Z) (h : P.Factors g) :
    f ≫ P.factorThru g h = P.factorThru (f ≫ g) (factors_of_factors_right f h) := by
  

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
X✝ Y✝ Z✝ : C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
X Y Z : C
P : Subobject Z
f : X ⟶ Y
g : Y ⟶ Z
h : Factors P g
⊢ f ≫ factorThru P g h = factorThru P (f ≫ g) (_ : Factors P (f ≫ g))

Next tactic:
apply (cancel_mono P.arrow).mp
theorem factorThru_right {X Y Z : C} {P : Subobject Z} (f : X ⟶ Y) (g : Y ⟶ Z) (h : P.Factors g) :
    f ≫ P.factorThru g h = P.factorThru (f ≫ g) (factors_of_factors_right f h) := by
  apply (cancel_mono P.arrow).mp
  

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
X✝ Y✝ Z✝ : C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
X Y Z : C
P : Subobject Z
f : X ⟶ Y
g : Y ⟶ Z
h : Factors P g
⊢ (f ≫ factorThru P g h) ≫ arrow P = factorThru P (f ≫ g) (_ : Factors P (f ≫ g)) ≫ arrow P

Next tactic:
simp
@[simp]
theorem factorThru_zero [HasZeroMorphisms C] {X Y : C} {P : Subobject Y}
    (h : P.Factors (0 : X ⟶ Y)) : P.factorThru 0 h = 0 := by 

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
X✝ Y✝ Z : C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
inst✝ : HasZeroMorphisms C
X Y : C
P : Subobject Y
h : Factors P 0
⊢ factorThru P 0 h = 0

Next tactic:
simp
theorem factorThru_ofLE {Y Z : C} {P Q : Subobject Y} {f : Z ⟶ Y} (h : P ≤ Q) (w : P.Factors f) :
    Q.factorThru f (factors_of_le f h w) = P.factorThru f w ≫ ofLE P Q h := by
  

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
X Y✝ Z✝ : C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
Y Z : C
P Q : Subobject Y
f : Z ⟶ Y
h : P ≤ Q
w : Factors P f
⊢ factorThru Q f (_ : Factors Q f) = factorThru P f w ≫ ofLE P Q h

Next tactic:
ext
theorem factorThru_ofLE {Y Z : C} {P Q : Subobject Y} {f : Z ⟶ Y} (h : P ≤ Q) (w : P.Factors f) :
    Q.factorThru f (factors_of_le f h w) = P.factorThru f w ≫ ofLE P Q h := by
  ext
  

Proof state:
case h
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
X Y✝ Z✝ : C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
Y Z : C
P Q : Subobject Y
f : Z ⟶ Y
h : P ≤ Q
w : Factors P f
⊢ factorThru Q f (_ : Factors Q f) ≫ arrow Q = (factorThru P f w ≫ ofLE P Q h) ≫ arrow Q

Next tactic:
simp
theorem factors_add {X Y : C} {P : Subobject Y} (f g : X ⟶ Y) (wf : P.Factors f)
    (wg : P.Factors g) : P.Factors (f + g) :=
  (factors_iff _ _).mpr ⟨P.factorThru f wf + P.factorThru g wg, by 

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
X✝ Y✝ Z : C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
inst✝ : Preadditive C
X Y : C
P : Subobject Y
f g : X ⟶ Y
wf : Factors P f
wg : Factors P g
⊢ (factorThru P f wf + factorThru P g wg) ≫ MonoOver.arrow (representative.obj P) = f + g

Next tactic:
simp
theorem factorThru_add {X Y : C} {P : Subobject Y} (f g : X ⟶ Y) (w : P.Factors (f + g))
    (wf : P.Factors f) (wg : P.Factors g) :
    P.factorThru (f + g) w = P.factorThru f wf + P.factorThru g wg := by
  

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
X✝ Y✝ Z : C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
inst✝ : Preadditive C
X Y : C
P : Subobject Y
f g : X ⟶ Y
w : Factors P (f + g)
wf : Factors P f
wg : Factors P g
⊢ factorThru P (f + g) w = factorThru P f wf + factorThru P g wg

Next tactic:
ext
theorem factorThru_add {X Y : C} {P : Subobject Y} (f g : X ⟶ Y) (w : P.Factors (f + g))
    (wf : P.Factors f) (wg : P.Factors g) :
    P.factorThru (f + g) w = P.factorThru f wf + P.factorThru g wg := by
  ext
  

Proof state:
case h
C : Type u₁
inst✝² : Category.{v₁, u₁} C
X✝ Y✝ Z : C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
inst✝ : Preadditive C
X Y : C
P : Subobject Y
f g : X ⟶ Y
w : Factors P (f + g)
wf : Factors P f
wg : Factors P g
⊢ factorThru P (f + g) w ≫ arrow P = (factorThru P f wf + factorThru P g wg) ≫ arrow P

Next tactic:
simp
theorem factors_left_of_factors_add {X Y : C} {P : Subobject Y} (f g : X ⟶ Y)
    (w : P.Factors (f + g)) (wg : P.Factors g) : P.Factors f :=
  (factors_iff _ _).mpr ⟨P.factorThru (f + g) w - P.factorThru g wg, by 

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
X✝ Y✝ Z : C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
inst✝ : Preadditive C
X Y : C
P : Subobject Y
f g : X ⟶ Y
w : Factors P (f + g)
wg : Factors P g
⊢ (factorThru P (f + g) w - factorThru P g wg) ≫ MonoOver.arrow (representative.obj P) = f

Next tactic:
simp
@[simp]
theorem factorThru_add_sub_factorThru_right {X Y : C} {P : Subobject Y} (f g : X ⟶ Y)
    (w : P.Factors (f + g)) (wg : P.Factors g) :
    P.factorThru (f + g) w - P.factorThru g wg =
      P.factorThru f (factors_left_of_factors_add f g w wg) := by
  

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
X✝ Y✝ Z : C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
inst✝ : Preadditive C
X Y : C
P : Subobject Y
f g : X ⟶ Y
w : Factors P (f + g)
wg : Factors P g
⊢ factorThru P (f + g) w - factorThru P g wg = factorThru P f (_ : Factors P f)

Next tactic:
ext
@[simp]
theorem factorThru_add_sub_factorThru_right {X Y : C} {P : Subobject Y} (f g : X ⟶ Y)
    (w : P.Factors (f + g)) (wg : P.Factors g) :
    P.factorThru (f + g) w - P.factorThru g wg =
      P.factorThru f (factors_left_of_factors_add f g w wg) := by
  ext
  

Proof state:
case h
C : Type u₁
inst✝² : Category.{v₁, u₁} C
X✝ Y✝ Z : C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
inst✝ : Preadditive C
X Y : C
P : Subobject Y
f g : X ⟶ Y
w : Factors P (f + g)
wg : Factors P g
⊢ (factorThru P (f + g) w - factorThru P g wg) ≫ arrow P = factorThru P f (_ : Factors P f) ≫ arrow P

Next tactic:
simp
theorem factors_right_of_factors_add {X Y : C} {P : Subobject Y} (f g : X ⟶ Y)
    (w : P.Factors (f + g)) (wf : P.Factors f) : P.Factors g :=
  (factors_iff _ _).mpr ⟨P.factorThru (f + g) w - P.factorThru f wf, by 

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
X✝ Y✝ Z : C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
inst✝ : Preadditive C
X Y : C
P : Subobject Y
f g : X ⟶ Y
w : Factors P (f + g)
wf : Factors P f
⊢ (factorThru P (f + g) w - factorThru P f wf) ≫ MonoOver.arrow (representative.obj P) = g

Next tactic:
simp
@[simp]
theorem factorThru_add_sub_factorThru_left {X Y : C} {P : Subobject Y} (f g : X ⟶ Y)
    (w : P.Factors (f + g)) (wf : P.Factors f) :
    P.factorThru (f + g) w - P.factorThru f wf =
      P.factorThru g (factors_right_of_factors_add f g w wf) := by
  

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
X✝ Y✝ Z : C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
inst✝ : Preadditive C
X Y : C
P : Subobject Y
f g : X ⟶ Y
w : Factors P (f + g)
wf : Factors P f
⊢ factorThru P (f + g) w - factorThru P f wf = factorThru P g (_ : Factors P g)

Next tactic:
ext
@[simp]
theorem factorThru_add_sub_factorThru_left {X Y : C} {P : Subobject Y} (f g : X ⟶ Y)
    (w : P.Factors (f + g)) (wf : P.Factors f) :
    P.factorThru (f + g) w - P.factorThru f wf =
      P.factorThru g (factors_right_of_factors_add f g w wf) := by
  ext
  

Proof state:
case h
C : Type u₁
inst✝² : Category.{v₁, u₁} C
X✝ Y✝ Z : C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
inst✝ : Preadditive C
X Y : C
P : Subobject Y
f g : X ⟶ Y
w : Factors P (f + g)
wf : Factors P f
⊢ (factorThru P (f + g) w - factorThru P f wf) ≫ arrow P = factorThru P g (_ : Factors P g) ≫ arrow P

Next tactic:
simp
lemma shortExact_of_iso (e : S₁ ≅ S₂) (h : S₁.ShortExact) : S₂.ShortExact where
  exact := exact_of_iso e h.exact
  mono_f := by
    

Proof state:
C : Type u_1
D : Type u_2
inst✝³ : Category.{u_3, u_1} C
inst✝² : Category.{?u.1418, u_2} D
inst✝¹ : HasZeroMorphisms C
inst✝ : HasZeroMorphisms D
S S₁ S₂ : ShortComplex C
e : S₁ ≅ S₂
h : ShortExact S₁
⊢ Mono S₂.f

Next tactic:
suffices Mono (S₂.f ≫ e.inv.τ₂) by
      exact mono_of_mono _ e.inv.τ₂
lemma shortExact_of_iso (e : S₁ ≅ S₂) (h : S₁.ShortExact) : S₂.ShortExact where
  exact := exact_of_iso e h.exact
  mono_f := by
    suffices Mono (S₂.f ≫ e.inv.τ₂) by
      

Proof state:
C : Type u_1
D : Type u_2
inst✝³ : Category.{u_3, u_1} C
inst✝² : Category.{?u.1418, u_2} D
inst✝¹ : HasZeroMorphisms C
inst✝ : HasZeroMorphisms D
S S₁ S₂ : ShortComplex C
e : S₁ ≅ S₂
h : ShortExact S₁
this : Mono (S₂.f ≫ e.inv.τ₂)
⊢ Mono S₂.f

Next tactic:
exact mono_of_mono _ e.inv.τ₂