l3lab/ntp-mathlib huggingface dataset:
theorem Preadditive.exact_of_iso_of_exact {A₁ B₁ C₁ A₂ B₂ C₂ : V} (f₁ : A₁ ⟶ B₁) (g₁ : B₁ ⟶ C₁)
    (f₂ : A₂ ⟶ B₂) (g₂ : B₂ ⟶ C₂) (α : Arrow.mk f₁ ≅ Arrow.mk f₂) (β : Arrow.mk g₁ ≅ Arrow.mk g₂)
    (p : α.hom.right = β.hom.left) (h : Exact f₁ g₁) : Exact f₂ g₂ := by
  rw [Preadditive.exact_iff_homology'_zero] at h ⊢
  rcases h with ⟨w₁, ⟨i⟩⟩
  suffices w₂ : f₂ ≫ g₂ = 0; exact ⟨w₂, ⟨(homology'.mapIso w₁ w₂ α β p).symm.trans i⟩⟩
  rw [← cancel_epi α.hom.left, ← cancel_mono β.inv.right, comp_zero, zero_comp, ← w₁]
  have eq₁ := β.inv.w
  

Proof state:
case w₂
V : Type u
inst✝⁵ : Category.{v, u} V
inst✝⁴ : HasImages V
inst✝³ : HasZeroObject V
inst✝² : Preadditive V
inst✝¹ : HasKernels V
inst✝ : HasCokernels V
A₁ B₁ C₁ A₂ B₂ C₂ : V
f₁ : A₁ ⟶ B₁
g₁ : B₁ ⟶ C₁
f₂ : A₂ ⟶ B₂
g₂ : B₂ ⟶ C₂
α : Arrow.mk f₁ ≅ Arrow.mk f₂
β : Arrow.mk g₁ ≅ Arrow.mk g₂
p : α.hom.right = β.hom.left
w₁ : f₁ ≫ g₁ = 0
i : homology' f₁ g₁ w₁ ≅ 0
eq₁ : (𝟭 V).map β.inv.left ≫ (Arrow.mk g₁).hom = (Arrow.mk g₂).hom ≫ (𝟭 V).map β.inv.right
⊢ (α.hom.left ≫ f₂ ≫ g₂) ≫ β.inv.right = f₁ ≫ g₁

Next tactic:
have eq₂ := α.hom.w
theorem Preadditive.exact_of_iso_of_exact {A₁ B₁ C₁ A₂ B₂ C₂ : V} (f₁ : A₁ ⟶ B₁) (g₁ : B₁ ⟶ C₁)
    (f₂ : A₂ ⟶ B₂) (g₂ : B₂ ⟶ C₂) (α : Arrow.mk f₁ ≅ Arrow.mk f₂) (β : Arrow.mk g₁ ≅ Arrow.mk g₂)
    (p : α.hom.right = β.hom.left) (h : Exact f₁ g₁) : Exact f₂ g₂ := by
  rw [Preadditive.exact_iff_homology'_zero] at h ⊢
  rcases h with ⟨w₁, ⟨i⟩⟩
  suffices w₂ : f₂ ≫ g₂ = 0; exact ⟨w₂, ⟨(homology'.mapIso w₁ w₂ α β p).symm.trans i⟩⟩
  rw [← cancel_epi α.hom.left, ← cancel_mono β.inv.right, comp_zero, zero_comp, ← w₁]
  have eq₁ := β.inv.w
  have eq₂ := α.hom.w
  

Proof state:
case w₂
V : Type u
inst✝⁵ : Category.{v, u} V
inst✝⁴ : HasImages V
inst✝³ : HasZeroObject V
inst✝² : Preadditive V
inst✝¹ : HasKernels V
inst✝ : HasCokernels V
A₁ B₁ C₁ A₂ B₂ C₂ : V
f₁ : A₁ ⟶ B₁
g₁ : B₁ ⟶ C₁
f₂ : A₂ ⟶ B₂
g₂ : B₂ ⟶ C₂
α : Arrow.mk f₁ ≅ Arrow.mk f₂
β : Arrow.mk g₁ ≅ Arrow.mk g₂
p : α.hom.right = β.hom.left
w₁ : f₁ ≫ g₁ = 0
i : homology' f₁ g₁ w₁ ≅ 0
eq₁ : (𝟭 V).map β.inv.left ≫ (Arrow.mk g₁).hom = (Arrow.mk g₂).hom ≫ (𝟭 V).map β.inv.right
eq₂ : (𝟭 V).map α.hom.left ≫ (Arrow.mk f₂).hom = (Arrow.mk f₁).hom ≫ (𝟭 V).map α.hom.right
⊢ (α.hom.left ≫ f₂ ≫ g₂) ≫ β.inv.right = f₁ ≫ g₁

Next tactic:
dsimp at eq₁ eq₂
theorem Preadditive.exact_of_iso_of_exact {A₁ B₁ C₁ A₂ B₂ C₂ : V} (f₁ : A₁ ⟶ B₁) (g₁ : B₁ ⟶ C₁)
    (f₂ : A₂ ⟶ B₂) (g₂ : B₂ ⟶ C₂) (α : Arrow.mk f₁ ≅ Arrow.mk f₂) (β : Arrow.mk g₁ ≅ Arrow.mk g₂)
    (p : α.hom.right = β.hom.left) (h : Exact f₁ g₁) : Exact f₂ g₂ := by
  rw [Preadditive.exact_iff_homology'_zero] at h ⊢
  rcases h with ⟨w₁, ⟨i⟩⟩
  suffices w₂ : f₂ ≫ g₂ = 0; exact ⟨w₂, ⟨(homology'.mapIso w₁ w₂ α β p).symm.trans i⟩⟩
  rw [← cancel_epi α.hom.left, ← cancel_mono β.inv.right, comp_zero, zero_comp, ← w₁]
  have eq₁ := β.inv.w
  have eq₂ := α.hom.w
  dsimp at eq₁ eq₂
  

Proof state:
case w₂
V : Type u
inst✝⁵ : Category.{v, u} V
inst✝⁴ : HasImages V
inst✝³ : HasZeroObject V
inst✝² : Preadditive V
inst✝¹ : HasKernels V
inst✝ : HasCokernels V
A₁ B₁ C₁ A₂ B₂ C₂ : V
f₁ : A₁ ⟶ B₁
g₁ : B₁ ⟶ C₁
f₂ : A₂ ⟶ B₂
g₂ : B₂ ⟶ C₂
α : Arrow.mk f₁ ≅ Arrow.mk f₂
β : Arrow.mk g₁ ≅ Arrow.mk g₂
p : α.hom.right = β.hom.left
w₁ : f₁ ≫ g₁ = 0
i : homology' f₁ g₁ w₁ ≅ 0
eq₁ : β.inv.left ≫ g₁ = g₂ ≫ β.inv.right
eq₂ : α.hom.left ≫ f₂ = f₁ ≫ α.hom.right
⊢ (α.hom.left ≫ f₂ ≫ g₂) ≫ β.inv.right = f₁ ≫ g₁

Next tactic:
simp only [Category.assoc, Category.assoc, ← eq₁, reassoc_of% eq₂, p,
    ← reassoc_of% (Arrow.comp_left β.hom β.inv), β.hom_inv_id, Arrow.id_left, Category.id_comp]
theorem Preadditive.exact_iff_exact_of_iso {A₁ B₁ C₁ A₂ B₂ C₂ : V} (f₁ : A₁ ⟶ B₁) (g₁ : B₁ ⟶ C₁)
    (f₂ : A₂ ⟶ B₂) (g₂ : B₂ ⟶ C₂) (α : Arrow.mk f₁ ≅ Arrow.mk f₂) (β : Arrow.mk g₁ ≅ Arrow.mk g₂)
    (p : α.hom.right = β.hom.left) : Exact f₁ g₁ ↔ Exact f₂ g₂ :=
  ⟨Preadditive.exact_of_iso_of_exact _ _ _ _ _ _ p,
    Preadditive.exact_of_iso_of_exact _ _ _ _ α.symm β.symm
      (by
        

Proof state:
V : Type u
inst✝⁵ : Category.{v, u} V
inst✝⁴ : HasImages V
inst✝³ : HasZeroObject V
inst✝² : Preadditive V
inst✝¹ : HasKernels V
inst✝ : HasCokernels V
A₁ B₁ C₁ A₂ B₂ C₂ : V
f₁ : A₁ ⟶ B₁
g₁ : B₁ ⟶ C₁
f₂ : A₂ ⟶ B₂
g₂ : B₂ ⟶ C₂
α : Arrow.mk f₁ ≅ Arrow.mk f₂
β : Arrow.mk g₁ ≅ Arrow.mk g₂
p : α.hom.right = β.hom.left
⊢ α.symm.hom.right = β.symm.hom.left

Next tactic:
rw [← cancel_mono α.hom.right]
theorem Preadditive.exact_iff_exact_of_iso {A₁ B₁ C₁ A₂ B₂ C₂ : V} (f₁ : A₁ ⟶ B₁) (g₁ : B₁ ⟶ C₁)
    (f₂ : A₂ ⟶ B₂) (g₂ : B₂ ⟶ C₂) (α : Arrow.mk f₁ ≅ Arrow.mk f₂) (β : Arrow.mk g₁ ≅ Arrow.mk g₂)
    (p : α.hom.right = β.hom.left) : Exact f₁ g₁ ↔ Exact f₂ g₂ :=
  ⟨Preadditive.exact_of_iso_of_exact _ _ _ _ _ _ p,
    Preadditive.exact_of_iso_of_exact _ _ _ _ α.symm β.symm
      (by
        rw [← cancel_mono α.hom.right]
        

Proof state:
V : Type u
inst✝⁵ : Category.{v, u} V
inst✝⁴ : HasImages V
inst✝³ : HasZeroObject V
inst✝² : Preadditive V
inst✝¹ : HasKernels V
inst✝ : HasCokernels V
A₁ B₁ C₁ A₂ B₂ C₂ : V
f₁ : A₁ ⟶ B₁
g₁ : B₁ ⟶ C₁
f₂ : A₂ ⟶ B₂
g₂ : B₂ ⟶ C₂
α : Arrow.mk f₁ ≅ Arrow.mk f₂
β : Arrow.mk g₁ ≅ Arrow.mk g₂
p : α.hom.right = β.hom.left
⊢ α.symm.hom.right ≫ α.hom.right = β.symm.hom.left ≫ α.hom.right

Next tactic:
simp only [Iso.symm_hom, ← Arrow.comp_right, α.inv_hom_id]
theorem Preadditive.exact_iff_exact_of_iso {A₁ B₁ C₁ A₂ B₂ C₂ : V} (f₁ : A₁ ⟶ B₁) (g₁ : B₁ ⟶ C₁)
    (f₂ : A₂ ⟶ B₂) (g₂ : B₂ ⟶ C₂) (α : Arrow.mk f₁ ≅ Arrow.mk f₂) (β : Arrow.mk g₁ ≅ Arrow.mk g₂)
    (p : α.hom.right = β.hom.left) : Exact f₁ g₁ ↔ Exact f₂ g₂ :=
  ⟨Preadditive.exact_of_iso_of_exact _ _ _ _ _ _ p,
    Preadditive.exact_of_iso_of_exact _ _ _ _ α.symm β.symm
      (by
        rw [← cancel_mono α.hom.right]
        simp only [Iso.symm_hom, ← Arrow.comp_right, α.inv_hom_id]
        

Proof state:
V : Type u
inst✝⁵ : Category.{v, u} V
inst✝⁴ : HasImages V
inst✝³ : HasZeroObject V
inst✝² : Preadditive V
inst✝¹ : HasKernels V
inst✝ : HasCokernels V
A₁ B₁ C₁ A₂ B₂ C₂ : V
f₁ : A₁ ⟶ B₁
g₁ : B₁ ⟶ C₁
f₂ : A₂ ⟶ B₂
g₂ : B₂ ⟶ C₂
α : Arrow.mk f₁ ≅ Arrow.mk f₂
β : Arrow.mk g₁ ≅ Arrow.mk g₂
p : α.hom.right = β.hom.left
⊢ (𝟙 (Arrow.mk f₂)).right = β.inv.left ≫ α.hom.right

Next tactic:
simp only [p, ← Arrow.comp_left, Arrow.id_right, Arrow.id_left, Iso.inv_hom_id]
theorem Preadditive.exact_iff_exact_of_iso {A₁ B₁ C₁ A₂ B₂ C₂ : V} (f₁ : A₁ ⟶ B₁) (g₁ : B₁ ⟶ C₁)
    (f₂ : A₂ ⟶ B₂) (g₂ : B₂ ⟶ C₂) (α : Arrow.mk f₁ ≅ Arrow.mk f₂) (β : Arrow.mk g₁ ≅ Arrow.mk g₂)
    (p : α.hom.right = β.hom.left) : Exact f₁ g₁ ↔ Exact f₂ g₂ :=
  ⟨Preadditive.exact_of_iso_of_exact _ _ _ _ _ _ p,
    Preadditive.exact_of_iso_of_exact _ _ _ _ α.symm β.symm
      (by
        rw [← cancel_mono α.hom.right]
        simp only [Iso.symm_hom, ← Arrow.comp_right, α.inv_hom_id]
        simp only [p, ← Arrow.comp_left, Arrow.id_right, Arrow.id_left, Iso.inv_hom_id]
        

Proof state:
V : Type u
inst✝⁵ : Category.{v, u} V
inst✝⁴ : HasImages V
inst✝³ : HasZeroObject V
inst✝² : Preadditive V
inst✝¹ : HasKernels V
inst✝ : HasCokernels V
A₁ B₁ C₁ A₂ B₂ C₂ : V
f₁ : A₁ ⟶ B₁
g₁ : B₁ ⟶ C₁
f₂ : A₂ ⟶ B₂
g₂ : B₂ ⟶ C₂
α : Arrow.mk f₁ ≅ Arrow.mk f₂
β : Arrow.mk g₁ ≅ Arrow.mk g₂
p : α.hom.right = β.hom.left
⊢ 𝟙 (Arrow.mk f₂).right = 𝟙 (Arrow.mk g₂).left

Next tactic:
rfl
theorem comp_eq_zero_of_image_eq_kernel {A B C : V} (f : A ⟶ B) (g : B ⟶ C)
    (p : imageSubobject f = kernelSubobject g) : f ≫ g = 0 := by
  

Proof state:
V : Type u
inst✝³ : Category.{v, u} V
inst✝² : HasImages V
inst✝¹ : HasZeroMorphisms V
inst✝ : HasKernels V
A B C : V
f : A ⟶ B
g : B ⟶ C
p : imageSubobject f = kernelSubobject g
⊢ f ≫ g = 0

Next tactic:
suffices Subobject.arrow (imageSubobject f) ≫ g = 0 by
    rw [← imageSubobject_arrow_comp f, Category.assoc, this, comp_zero]
theorem comp_eq_zero_of_image_eq_kernel {A B C : V} (f : A ⟶ B) (g : B ⟶ C)
    (p : imageSubobject f = kernelSubobject g) : f ≫ g = 0 := by
  suffices Subobject.arrow (imageSubobject f) ≫ g = 0 by
    

Proof state:
V : Type u
inst✝³ : Category.{v, u} V
inst✝² : HasImages V
inst✝¹ : HasZeroMorphisms V
inst✝ : HasKernels V
A B C : V
f : A ⟶ B
g : B ⟶ C
p : imageSubobject f = kernelSubobject g
this : Subobject.arrow (imageSubobject f) ≫ g = 0
⊢ f ≫ g = 0

Next tactic:
rw [← imageSubobject_arrow_comp f, Category.assoc, this, comp_zero]
theorem comp_eq_zero_of_image_eq_kernel {A B C : V} (f : A ⟶ B) (g : B ⟶ C)
    (p : imageSubobject f = kernelSubobject g) : f ≫ g = 0 := by
  suffices Subobject.arrow (imageSubobject f) ≫ g = 0 by
    rw [← imageSubobject_arrow_comp f, Category.assoc, this, comp_zero]
  

Proof state:
V : Type u
inst✝³ : Category.{v, u} V
inst✝² : HasImages V
inst✝¹ : HasZeroMorphisms V
inst✝ : HasKernels V
A B C : V
f : A ⟶ B
g : B ⟶ C
p : imageSubobject f = kernelSubobject g
⊢ Subobject.arrow (imageSubobject f) ≫ g = 0

Next tactic:
rw [p, kernelSubobject_arrow_comp]
theorem imageToKernel_isIso_of_image_eq_kernel {A B C : V} (f : A ⟶ B) (g : B ⟶ C)
    (p : imageSubobject f = kernelSubobject g) :
    IsIso (imageToKernel f g (comp_eq_zero_of_image_eq_kernel f g p)) := by
  

Proof state:
V : Type u
inst✝³ : Category.{v, u} V
inst✝² : HasImages V
inst✝¹ : HasZeroMorphisms V
inst✝ : HasKernels V
A B C : V
f : A ⟶ B
g : B ⟶ C
p : imageSubobject f = kernelSubobject g
⊢ IsIso (imageToKernel f g (_ : f ≫ g = 0))

Next tactic:
refine' ⟨⟨Subobject.ofLE _ _ p.ge, _⟩⟩
theorem imageToKernel_isIso_of_image_eq_kernel {A B C : V} (f : A ⟶ B) (g : B ⟶ C)
    (p : imageSubobject f = kernelSubobject g) :
    IsIso (imageToKernel f g (comp_eq_zero_of_image_eq_kernel f g p)) := by
  refine' ⟨⟨Subobject.ofLE _ _ p.ge, _⟩⟩
  

Proof state:
V : Type u
inst✝³ : Category.{v, u} V
inst✝² : HasImages V
inst✝¹ : HasZeroMorphisms V
inst✝ : HasKernels V
A B C : V
f : A ⟶ B
g : B ⟶ C
p : imageSubobject f = kernelSubobject g
⊢ imageToKernel f g (_ : f ≫ g = 0) ≫
        Subobject.ofLE (kernelSubobject g) (imageSubobject f) (_ : kernelSubobject g ≤ imageSubobject f) =
      𝟙 (Subobject.underlying.obj (imageSubobject f)) ∧
    Subobject.ofLE (kernelSubobject g) (imageSubobject f) (_ : kernelSubobject g ≤ imageSubobject f) ≫
        imageToKernel f g (_ : f ≫ g = 0) =
      𝟙 (Subobject.underlying.obj (kernelSubobject g))

Next tactic:
dsimp [imageToKernel]
theorem imageToKernel_isIso_of_image_eq_kernel {A B C : V} (f : A ⟶ B) (g : B ⟶ C)
    (p : imageSubobject f = kernelSubobject g) :
    IsIso (imageToKernel f g (comp_eq_zero_of_image_eq_kernel f g p)) := by
  refine' ⟨⟨Subobject.ofLE _ _ p.ge, _⟩⟩
  dsimp [imageToKernel]
  

Proof state:
V : Type u
inst✝³ : Category.{v, u} V
inst✝² : HasImages V
inst✝¹ : HasZeroMorphisms V
inst✝ : HasKernels V
A B C : V
f : A ⟶ B
g : B ⟶ C
p : imageSubobject f = kernelSubobject g
⊢ Subobject.ofLE (imageSubobject f) (kernelSubobject g) (_ : imageSubobject f ≤ kernelSubobject g) ≫
        Subobject.ofLE (kernelSubobject g) (imageSubobject f) (_ : kernelSubobject g ≤ imageSubobject f) =
      𝟙 (Subobject.underlying.obj (imageSubobject f)) ∧
    Subobject.ofLE (kernelSubobject g) (imageSubobject f) (_ : kernelSubobject g ≤ imageSubobject f) ≫
        Subobject.ofLE (imageSubobject f) (kernelSubobject g) (_ : imageSubobject f ≤ kernelSubobject g) =
      𝟙 (Subobject.underlying.obj (kernelSubobject g))

Next tactic:
simp only [Subobject.ofLE_comp_ofLE, Subobject.ofLE_refl, and_self]
theorem exact_of_image_eq_kernel {A B C : V} (f : A ⟶ B) (g : B ⟶ C)
    (p : imageSubobject f = kernelSubobject g) : Exact f g :=
  { w := comp_eq_zero_of_image_eq_kernel f g p
    epi := by
      

Proof state:
V : Type u
inst✝³ : Category.{v, u} V
inst✝² : HasImages V
inst✝¹ : HasZeroMorphisms V
inst✝ : HasKernels V
A B C : V
f : A ⟶ B
g : B ⟶ C
p : imageSubobject f = kernelSubobject g
⊢ Epi (imageToKernel f g (_ : f ≫ g = 0))

Next tactic:
haveI := imageToKernel_isIso_of_image_eq_kernel f g p
theorem exact_of_image_eq_kernel {A B C : V} (f : A ⟶ B) (g : B ⟶ C)
    (p : imageSubobject f = kernelSubobject g) : Exact f g :=
  { w := comp_eq_zero_of_image_eq_kernel f g p
    epi := by
      haveI := imageToKernel_isIso_of_image_eq_kernel f g p
      

Proof state:
V : Type u
inst✝³ : Category.{v, u} V
inst✝² : HasImages V
inst✝¹ : HasZeroMorphisms V
inst✝ : HasKernels V
A B C : V
f : A ⟶ B
g : B ⟶ C
p : imageSubobject f = kernelSubobject g
this : IsIso (imageToKernel f g (_ : f ≫ g = 0))
⊢ Epi (imageToKernel f g (_ : f ≫ g = 0))

Next tactic:
infer_instance
theorem exact_comp_hom_inv_comp (i : B ≅ D) (h : Exact f g) : Exact (f ≫ i.hom) (i.inv ≫ g) := by
  

Proof state:
V : Type u
inst✝³ : Category.{v, u} V
inst✝² : HasImages V
A B C D : V
f : A ⟶ B
g : B ⟶ C
h✝ : C ⟶ D
inst✝¹ : HasZeroMorphisms V
inst✝ : HasEqualizers V
i : B ≅ D
h : Exact f g
⊢ Exact (f ≫ i.hom) (i.inv ≫ g)

Next tactic:
refine' ⟨by simp [h.w], _⟩
theorem exact_comp_hom_inv_comp (i : B ≅ D) (h : Exact f g) : Exact (f ≫ i.hom) (i.inv ≫ g) := by
  refine' ⟨by 

Proof state:
V : Type u
inst✝³ : Category.{v, u} V
inst✝² : HasImages V
A B C D : V
f : A ⟶ B
g : B ⟶ C
h✝ : C ⟶ D
inst✝¹ : HasZeroMorphisms V
inst✝ : HasEqualizers V
i : B ≅ D
h : Exact f g
⊢ (f ≫ i.hom) ≫ i.inv ≫ g = 0

Next tactic:
simp [h.w]
theorem exact_comp_hom_inv_comp (i : B ≅ D) (h : Exact f g) : Exact (f ≫ i.hom) (i.inv ≫ g) := by
  refine' ⟨by simp [h.w], _⟩
  

Proof state:
V : Type u
inst✝³ : Category.{v, u} V
inst✝² : HasImages V
A B C D : V
f : A ⟶ B
g : B ⟶ C
h✝ : C ⟶ D
inst✝¹ : HasZeroMorphisms V
inst✝ : HasEqualizers V
i : B ≅ D
h : Exact f g
⊢ Epi (imageToKernel (f ≫ i.hom) (i.inv ≫ g) (_ : (f ≫ i.hom) ≫ i.inv ≫ g = 0))

Next tactic:
rw [imageToKernel_comp_hom_inv_comp]
theorem exact_comp_hom_inv_comp (i : B ≅ D) (h : Exact f g) : Exact (f ≫ i.hom) (i.inv ≫ g) := by
  refine' ⟨by simp [h.w], _⟩
  rw [imageToKernel_comp_hom_inv_comp]
  

Proof state:
V : Type u
inst✝³ : Category.{v, u} V
inst✝² : HasImages V
A B C D : V
f : A ⟶ B
g : B ⟶ C
h✝ : C ⟶ D
inst✝¹ : HasZeroMorphisms V
inst✝ : HasEqualizers V
i : B ≅ D
h : Exact f g
⊢ Epi ((imageSubobjectCompIso f i.hom).hom ≫ imageToKernel f g (_ : f ≫ g = 0) ≫ (kernelSubobjectIsoComp i.inv g).inv)

Next tactic:
haveI := h.epi
theorem exact_comp_hom_inv_comp (i : B ≅ D) (h : Exact f g) : Exact (f ≫ i.hom) (i.inv ≫ g) := by
  refine' ⟨by simp [h.w], _⟩
  rw [imageToKernel_comp_hom_inv_comp]
  haveI := h.epi
  

Proof state:
V : Type u
inst✝³ : Category.{v, u} V
inst✝² : HasImages V
A B C D : V
f : A ⟶ B
g : B ⟶ C
h✝ : C ⟶ D
inst✝¹ : HasZeroMorphisms V
inst✝ : HasEqualizers V
i : B ≅ D
h : Exact f g
this : Epi (imageToKernel f g (_ : f ≫ g = 0))
⊢ Epi ((imageSubobjectCompIso f i.hom).hom ≫ imageToKernel f g (_ : f ≫ g = 0) ≫ (kernelSubobjectIsoComp i.inv g).inv)

Next tactic:
infer_instance
theorem exact_comp_hom_inv_comp_iff (i : B ≅ D) : Exact (f ≫ i.hom) (i.inv ≫ g) ↔ Exact f g :=
  ⟨fun h => by 

Proof state:
V : Type u
inst✝³ : Category.{v, u} V
inst✝² : HasImages V
A B C D : V
f : A ⟶ B
g : B ⟶ C
h✝ : C ⟶ D
inst✝¹ : HasZeroMorphisms V
inst✝ : HasEqualizers V
i : B ≅ D
h : Exact (f ≫ i.hom) (i.inv ≫ g)
⊢ Exact f g

Next tactic:
simpa using exact_comp_inv_hom_comp i h
theorem exact_epi_comp (hgh : Exact g h) [Epi f] : Exact (f ≫ g) h := by
  

Proof state:
V : Type u
inst✝⁴ : Category.{v, u} V
inst✝³ : HasImages V
A B C D : V
f : A ⟶ B
g : B ⟶ C
h : C ⟶ D
inst✝² : HasZeroMorphisms V
inst✝¹ : HasEqualizers V
hgh : Exact g h
inst✝ : Epi f
⊢ Exact (f ≫ g) h

Next tactic:
refine' ⟨by simp [hgh.w], _⟩
theorem exact_epi_comp (hgh : Exact g h) [Epi f] : Exact (f ≫ g) h := by
  refine' ⟨by 

Proof state:
V : Type u
inst✝⁴ : Category.{v, u} V
inst✝³ : HasImages V
A B C D : V
f : A ⟶ B
g : B ⟶ C
h : C ⟶ D
inst✝² : HasZeroMorphisms V
inst✝¹ : HasEqualizers V
hgh : Exact g h
inst✝ : Epi f
⊢ (f ≫ g) ≫ h = 0

Next tactic:
simp [hgh.w]
theorem exact_epi_comp (hgh : Exact g h) [Epi f] : Exact (f ≫ g) h := by
  refine' ⟨by simp [hgh.w], _⟩
  

Proof state:
V : Type u
inst✝⁴ : Category.{v, u} V
inst✝³ : HasImages V
A B C D : V
f : A ⟶ B
g : B ⟶ C
h : C ⟶ D
inst✝² : HasZeroMorphisms V
inst✝¹ : HasEqualizers V
hgh : Exact g h
inst✝ : Epi f
⊢ Epi (imageToKernel (f ≫ g) h (_ : (f ≫ g) ≫ h = 0))

Next tactic:
rw [imageToKernel_comp_left]
theorem exact_epi_comp (hgh : Exact g h) [Epi f] : Exact (f ≫ g) h := by
  refine' ⟨by simp [hgh.w], _⟩
  rw [imageToKernel_comp_left]
  

Proof state:
V : Type u
inst✝⁴ : Category.{v, u} V
inst✝³ : HasImages V
A B C D : V
f : A ⟶ B
g : B ⟶ C
h : C ⟶ D
inst✝² : HasZeroMorphisms V
inst✝¹ : HasEqualizers V
hgh : Exact g h
inst✝ : Epi f
⊢ Epi
    (Subobject.ofLE (imageSubobject (f ≫ g)) (imageSubobject g) (_ : imageSubobject (f ≫ g) ≤ imageSubobject g) ≫
      imageToKernel g h ?w)
case w
V : Type u
inst✝⁴ : Category.{v, u} V
inst✝³ : HasImages V
A B C D : V
f : A ⟶ B
g : B ⟶ C
h : C ⟶ D
inst✝² : HasZeroMorphisms V
inst✝¹ : HasEqualizers V
hgh : Exact g h
inst✝ : Epi f
⊢ g ≫ h = 0

Next tactic:
haveI := hgh.epi
theorem exact_epi_comp (hgh : Exact g h) [Epi f] : Exact (f ≫ g) h := by
  refine' ⟨by simp [hgh.w], _⟩
  rw [imageToKernel_comp_left]
  haveI := hgh.epi
  

Proof state:
V : Type u
inst✝⁴ : Category.{v, u} V
inst✝³ : HasImages V
A B C D : V
f : A ⟶ B
g : B ⟶ C
h : C ⟶ D
inst✝² : HasZeroMorphisms V
inst✝¹ : HasEqualizers V
hgh : Exact g h
inst✝ : Epi f
this : Epi (imageToKernel g h (_ : g ≫ h = 0))
⊢ Epi
    (Subobject.ofLE (imageSubobject (f ≫ g)) (imageSubobject g) (_ : imageSubobject (f ≫ g) ≤ imageSubobject g) ≫
      imageToKernel g h ?w)
case w
V : Type u
inst✝⁴ : Category.{v, u} V
inst✝³ : HasImages V
A B C D : V
f : A ⟶ B
g : B ⟶ C
h : C ⟶ D
inst✝² : HasZeroMorphisms V
inst✝¹ : HasEqualizers V
hgh : Exact g h
inst✝ : Epi f
⊢ g ≫ h = 0

Next tactic:
infer_instance
@[simp]
theorem exact_iso_comp [IsIso f] : Exact (f ≫ g) h ↔ Exact g h :=
  ⟨fun w => by
    

Proof state:
V : Type u
inst✝⁴ : Category.{v, u} V
inst✝³ : HasImages V
A B C D : V
f : A ⟶ B
g : B ⟶ C
h : C ⟶ D
inst✝² : HasZeroMorphisms V
inst✝¹ : HasEqualizers V
inst✝ : IsIso f
w : Exact (f ≫ g) h
⊢ Exact g h

Next tactic:
rw [← IsIso.inv_hom_id_assoc f g]
@[simp]
theorem exact_iso_comp [IsIso f] : Exact (f ≫ g) h ↔ Exact g h :=
  ⟨fun w => by
    rw [← IsIso.inv_hom_id_assoc f g]
    

Proof state:
V : Type u
inst✝⁴ : Category.{v, u} V
inst✝³ : HasImages V
A B C D : V
f : A ⟶ B
g : B ⟶ C
h : C ⟶ D
inst✝² : HasZeroMorphisms V
inst✝¹ : HasEqualizers V
inst✝ : IsIso f
w : Exact (f ≫ g) h
⊢ Exact (inv f ≫ f ≫ g) h

Next tactic:
exact exact_epi_comp w
theorem exact_comp_mono (hfg : Exact f g) [Mono h] : Exact f (g ≫ h) := by
  

Proof state:
V : Type u
inst✝⁴ : Category.{v, u} V
inst✝³ : HasImages V
A B C D : V
f : A ⟶ B
g : B ⟶ C
h : C ⟶ D
inst✝² : HasZeroMorphisms V
inst✝¹ : HasEqualizers V
hfg : Exact f g
inst✝ : Mono h
⊢ Exact f (g ≫ h)

Next tactic:
refine' ⟨by simp [hfg.w_assoc], _⟩
theorem exact_comp_mono (hfg : Exact f g) [Mono h] : Exact f (g ≫ h) := by
  refine' ⟨by 

Proof state:
V : Type u
inst✝⁴ : Category.{v, u} V
inst✝³ : HasImages V
A B C D : V
f : A ⟶ B
g : B ⟶ C
h : C ⟶ D
inst✝² : HasZeroMorphisms V
inst✝¹ : HasEqualizers V
hfg : Exact f g
inst✝ : Mono h
⊢ f ≫ g ≫ h = 0

Next tactic:
simp [hfg.w_assoc]
theorem exact_comp_mono (hfg : Exact f g) [Mono h] : Exact f (g ≫ h) := by
  refine' ⟨by simp [hfg.w_assoc], _⟩
  

Proof state:
V : Type u
inst✝⁴ : Category.{v, u} V
inst✝³ : HasImages V
A B C D : V
f : A ⟶ B
g : B ⟶ C
h : C ⟶ D
inst✝² : HasZeroMorphisms V
inst✝¹ : HasEqualizers V
hfg : Exact f g
inst✝ : Mono h
⊢ Epi (imageToKernel f (g ≫ h) (_ : f ≫ g ≫ h = 0))

Next tactic:
rw [imageToKernel_comp_right f g h hfg.w]
theorem exact_comp_mono (hfg : Exact f g) [Mono h] : Exact f (g ≫ h) := by
  refine' ⟨by simp [hfg.w_assoc], _⟩
  rw [imageToKernel_comp_right f g h hfg.w]
  

Proof state:
V : Type u
inst✝⁴ : Category.{v, u} V
inst✝³ : HasImages V
A B C D : V
f : A ⟶ B
g : B ⟶ C
h : C ⟶ D
inst✝² : HasZeroMorphisms V
inst✝¹ : HasEqualizers V
hfg : Exact f g
inst✝ : Mono h
⊢ Epi
    (imageToKernel f g (_ : f ≫ g = 0) ≫
      Subobject.ofLE (kernelSubobject g) (kernelSubobject (g ≫ h)) (_ : kernelSubobject g ≤ kernelSubobject (g ≫ h)))

Next tactic:
haveI := hfg.epi
theorem exact_comp_mono (hfg : Exact f g) [Mono h] : Exact f (g ≫ h) := by
  refine' ⟨by simp [hfg.w_assoc], _⟩
  rw [imageToKernel_comp_right f g h hfg.w]
  haveI := hfg.epi
  

Proof state:
V : Type u
inst✝⁴ : Category.{v, u} V
inst✝³ : HasImages V
A B C D : V
f : A ⟶ B
g : B ⟶ C
h : C ⟶ D
inst✝² : HasZeroMorphisms V
inst✝¹ : HasEqualizers V
hfg : Exact f g
inst✝ : Mono h
this : Epi (imageToKernel f g (_ : f ≫ g = 0))
⊢ Epi
    (imageToKernel f g (_ : f ≫ g = 0) ≫
      Subobject.ofLE (kernelSubobject g) (kernelSubobject (g ≫ h)) (_ : kernelSubobject g ≤ kernelSubobject (g ≫ h)))

Next tactic:
infer_instance
/-- The dual of this lemma is only true when `V` is abelian, see `Abelian.exact_epi_comp_iff`. -/
theorem exact_comp_mono_iff [Mono h] : Exact f (g ≫ h) ↔ Exact f g := by
  

Proof state:
V : Type u
inst✝⁴ : Category.{v, u} V
inst✝³ : HasImages V
A B C D : V
f : A ⟶ B
g : B ⟶ C
h : C ⟶ D
inst✝² : HasZeroMorphisms V
inst✝¹ : HasEqualizers V
inst✝ : Mono h
⊢ Exact f (g ≫ h) ↔ Exact f g

Next tactic:
refine'
    ⟨fun hfg => ⟨zero_of_comp_mono h (by rw [Category.assoc, hfg.1]), _⟩, fun h =>
      exact_comp_mono h⟩
/-- The dual of this lemma is only true when `V` is abelian, see `Abelian.exact_epi_comp_iff`. -/
theorem exact_comp_mono_iff [Mono h] : Exact f (g ≫ h) ↔ Exact f g := by
  refine'
    ⟨fun hfg => ⟨zero_of_comp_mono h (by 

Proof state:
V : Type u
inst✝⁴ : Category.{v, u} V
inst✝³ : HasImages V
A B C D : V
f : A ⟶ B
g : B ⟶ C
h : C ⟶ D
inst✝² : HasZeroMorphisms V
inst✝¹ : HasEqualizers V
inst✝ : Mono h
hfg : Exact f (g ≫ h)
⊢ (f ≫ g) ≫ h = 0

Next tactic:
rw [Category.assoc, hfg.1]
/-- The dual of this lemma is only true when `V` is abelian, see `Abelian.exact_epi_comp_iff`. -/
theorem exact_comp_mono_iff [Mono h] : Exact f (g ≫ h) ↔ Exact f g := by
  refine'
    ⟨fun hfg => ⟨zero_of_comp_mono h (by rw [Category.assoc, hfg.1]), _⟩, fun h =>
      exact_comp_mono h⟩
  

Proof state:
V : Type u
inst✝⁴ : Category.{v, u} V
inst✝³ : HasImages V
A B C D : V
f : A ⟶ B
g : B ⟶ C
h : C ⟶ D
inst✝² : HasZeroMorphisms V
inst✝¹ : HasEqualizers V
inst✝ : Mono h
hfg : Exact f (g ≫ h)
⊢ Epi (imageToKernel f g (_ : f ≫ g = 0))

Next tactic:
rw [← (Iso.eq_comp_inv _).1 (imageToKernel_comp_mono _ _ h hfg.1)]
/-- The dual of this lemma is only true when `V` is abelian, see `Abelian.exact_epi_comp_iff`. -/
theorem exact_comp_mono_iff [Mono h] : Exact f (g ≫ h) ↔ Exact f g := by
  refine'
    ⟨fun hfg => ⟨zero_of_comp_mono h (by rw [Category.assoc, hfg.1]), _⟩, fun h =>
      exact_comp_mono h⟩
  rw [← (Iso.eq_comp_inv _).1 (imageToKernel_comp_mono _ _ h hfg.1)]
  

Proof state:
V : Type u
inst✝⁴ : Category.{v, u} V
inst✝³ : HasImages V
A B C D : V
f : A ⟶ B
g : B ⟶ C
h : C ⟶ D
inst✝² : HasZeroMorphisms V
inst✝¹ : HasEqualizers V
inst✝ : Mono h
hfg : Exact f (g ≫ h)
⊢ Epi
    (imageToKernel f (g ≫ h) (_ : f ≫ g ≫ h = 0) ≫
      (Subobject.isoOfEq (kernelSubobject (g ≫ h)) (kernelSubobject g)
          (_ : kernelSubobject (g ≫ h) = kernelSubobject g)).hom)

Next tactic:
haveI := hfg.2
/-- The dual of this lemma is only true when `V` is abelian, see `Abelian.exact_epi_comp_iff`. -/
theorem exact_comp_mono_iff [Mono h] : Exact f (g ≫ h) ↔ Exact f g := by
  refine'
    ⟨fun hfg => ⟨zero_of_comp_mono h (by rw [Category.assoc, hfg.1]), _⟩, fun h =>
      exact_comp_mono h⟩
  rw [← (Iso.eq_comp_inv _).1 (imageToKernel_comp_mono _ _ h hfg.1)]
  haveI := hfg.2; 

Proof state:
V : Type u
inst✝⁴ : Category.{v, u} V
inst✝³ : HasImages V
A B C D : V
f : A ⟶ B
g : B ⟶ C
h : C ⟶ D
inst✝² : HasZeroMorphisms V
inst✝¹ : HasEqualizers V
inst✝ : Mono h
hfg : Exact f (g ≫ h)
this : Epi (imageToKernel f (g ≫ h) (_ : f ≫ g ≫ h = 0))
⊢ Epi
    (imageToKernel f (g ≫ h) (_ : f ≫ g ≫ h = 0) ≫
      (Subobject.isoOfEq (kernelSubobject (g ≫ h)) (kernelSubobject g)
          (_ : kernelSubobject (g ≫ h) = kernelSubobject g)).hom)

Next tactic:
infer_instance
theorem exact_kernelSubobject_arrow : Exact (kernelSubobject f).arrow f := by
  

Proof state:
V : Type u
inst✝³ : Category.{v, u} V
inst✝² : HasImages V
A B C D : V
f : A ⟶ B
g : B ⟶ C
h : C ⟶ D
inst✝¹ : HasZeroMorphisms V
inst✝ : HasEqualizers V
⊢ Exact (Subobject.arrow (kernelSubobject f)) f

Next tactic:
refine' ⟨by simp, _⟩