l3lab/ntp-mathlib huggingface dataset:
instance semilatticeSup [SemilatticeSup α] : SemilatticeSup (WithTop α) :=
  { WithTop.partialOrder with
    sup := Option.map₂ (· ⊔ ·),
    le_sup_left := fun o₁ o₂ a ha => by
      rcases Option.mem_map₂_iff.1 ha with ⟨a, b, (rfl : _ = _), (rfl : _ = _), rfl⟩
      exact ⟨_, rfl, le_sup_left⟩,
    le_sup_right := fun o₁ o₂ a ha => by
      rcases Option.mem_map₂_iff.1 ha with ⟨a, b, (rfl : _ = _), (rfl : _ = _), rfl⟩
      exact ⟨_, rfl, le_sup_right⟩,
    sup_le := fun o₁ o₂ o₃ h₁ h₂ a ha => by
      cases ha
      rcases h₁ a rfl with ⟨b, ⟨⟩, ab⟩
      rcases h₂ a rfl with ⟨c, ⟨⟩, ac⟩
      

Proof state:
case refl.intro.intro.refl.intro.intro.refl
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : SemilatticeSup α
src✝ : PartialOrder (WithTop α) := partialOrder
a b : α
ab : b ≤ a
h₁ : Option.some b ≤ Option.some a
c : α
ac : c ≤ a
h₂ : Option.some c ≤ Option.some a
⊢ ∃ b_1, b_1 ∈ Option.some b ⊔ Option.some c ∧ b_1 ≤ a

Next tactic:
exact ⟨_, rfl, sup_le ab ac⟩
instance isTotal_le [LE α] [IsTotal α (· ≤ ·)] : IsTotal (WithTop α) (· ≤ ·) :=
  ⟨fun _ _ => by
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : LE α
inst✝ : IsTotal α fun x x_1 => x ≤ x_1
x✝¹ x✝ : WithTop α
⊢ x✝¹ ≤ x✝ ∨ x✝ ≤ x✝¹

Next tactic:
simp_rw [← toDual_le_toDual_iff]
instance isTotal_le [LE α] [IsTotal α (· ≤ ·)] : IsTotal (WithTop α) (· ≤ ·) :=
  ⟨fun _ _ => by
    simp_rw [← toDual_le_toDual_iff]
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : LE α
inst✝ : IsTotal α fun x x_1 => x ≤ x_1
x✝¹ x✝ : WithTop α
⊢ WithTop.toDual x✝ ≤ WithTop.toDual x✝¹ ∨ WithTop.toDual x✝¹ ≤ WithTop.toDual x✝

Next tactic:
exact total_of _ _ _
instance instWellFoundedGT [LT α] [WellFoundedGT α] : WellFoundedGT (WithTop α) where
  wf := ⟨fun a => by
    -- ideally, use RelHomClass.acc, but that is defined later
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : LT α
inst✝ : WellFoundedGT α
a : WithTop α
⊢ Acc (fun x x_1 => x > x_1) a

Next tactic:
have : Acc (· < ·) (WithTop.toDual a) := wellFounded_lt.apply _
instance instWellFoundedGT [LT α] [WellFoundedGT α] : WellFoundedGT (WithTop α) where
  wf := ⟨fun a => by
    -- ideally, use RelHomClass.acc, but that is defined later
    have : Acc (· < ·) (WithTop.toDual a) := wellFounded_lt.apply _
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : LT α
inst✝ : WellFoundedGT α
a : WithTop α
this : Acc (fun x x_1 => x < x_1) (WithTop.toDual a)
⊢ Acc (fun x x_1 => x > x_1) a

Next tactic:
revert this
instance instWellFoundedGT [LT α] [WellFoundedGT α] : WellFoundedGT (WithTop α) where
  wf := ⟨fun a => by
    -- ideally, use RelHomClass.acc, but that is defined later
    have : Acc (· < ·) (WithTop.toDual a) := wellFounded_lt.apply _
    revert this
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : LT α
inst✝ : WellFoundedGT α
a : WithTop α
⊢ Acc (fun x x_1 => x < x_1) (WithTop.toDual a) → Acc (fun x x_1 => x > x_1) a

Next tactic:
generalize ha : WithBot.toDual a = b
instance instWellFoundedGT [LT α] [WellFoundedGT α] : WellFoundedGT (WithTop α) where
  wf := ⟨fun a => by
    -- ideally, use RelHomClass.acc, but that is defined later
    have : Acc (· < ·) (WithTop.toDual a) := wellFounded_lt.apply _
    revert this
    generalize ha : WithBot.toDual a = b
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : LT α
inst✝ : WellFoundedGT α
a : WithTop α
b : WithTop αᵒᵈ
ha : WithBot.toDual a = b
⊢ Acc (fun x x_1 => x < x_1) b → Acc (fun x x_1 => x > x_1) a

Next tactic:
intro ac
instance instWellFoundedGT [LT α] [WellFoundedGT α] : WellFoundedGT (WithTop α) where
  wf := ⟨fun a => by
    -- ideally, use RelHomClass.acc, but that is defined later
    have : Acc (· < ·) (WithTop.toDual a) := wellFounded_lt.apply _
    revert this
    generalize ha : WithBot.toDual a = b
    intro ac
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : LT α
inst✝ : WellFoundedGT α
a : WithTop α
b : WithTop αᵒᵈ
ha : WithBot.toDual a = b
ac : Acc (fun x x_1 => x < x_1) b
⊢ Acc (fun x x_1 => x > x_1) a

Next tactic:
induction' ac with _ H IH generalizing a
instance instWellFoundedGT [LT α] [WellFoundedGT α] : WellFoundedGT (WithTop α) where
  wf := ⟨fun a => by
    -- ideally, use RelHomClass.acc, but that is defined later
    have : Acc (· < ·) (WithTop.toDual a) := wellFounded_lt.apply _
    revert this
    generalize ha : WithBot.toDual a = b
    intro ac
    induction' ac with _ H IH generalizing a
    

Proof state:
case intro
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : LT α
inst✝ : WellFoundedGT α
b x✝ : WithTop αᵒᵈ
H : ∀ (y : WithTop αᵒᵈ), y < x✝ → Acc (fun x x_1 => x < x_1) y
IH : ∀ (y : WithTop αᵒᵈ), y < x✝ → ∀ (a : WithTop α), WithBot.toDual a = y → Acc (fun x x_1 => x > x_1) a
a : WithTop α
ha : WithBot.toDual a = x✝
⊢ Acc (fun x x_1 => x > x_1) a

Next tactic:
subst ha
instance instWellFoundedGT [LT α] [WellFoundedGT α] : WellFoundedGT (WithTop α) where
  wf := ⟨fun a => by
    -- ideally, use RelHomClass.acc, but that is defined later
    have : Acc (· < ·) (WithTop.toDual a) := wellFounded_lt.apply _
    revert this
    generalize ha : WithBot.toDual a = b
    intro ac
    induction' ac with _ H IH generalizing a
    subst ha
    

Proof state:
case intro
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : LT α
inst✝ : WellFoundedGT α
b : WithTop αᵒᵈ
a : WithTop α
H : ∀ (y : WithTop αᵒᵈ), y < WithBot.toDual a → Acc (fun x x_1 => x < x_1) y
IH : ∀ (y : WithTop αᵒᵈ), y < WithBot.toDual a → ∀ (a : WithTop α), WithBot.toDual a = y → Acc (fun x x_1 => x > x_1) a
⊢ Acc (fun x x_1 => x > x_1) a

Next tactic:
exact ⟨_, fun a' h => IH (WithTop.toDual a') (toDual_lt_toDual.mpr h) _ rfl⟩
instance _root_.WithBot.instWellFoundedGT [LT α] [WellFoundedGT α] : WellFoundedGT (WithBot α) where
  wf := ⟨fun a => by
    -- ideally, use RelHomClass.acc, but that is defined later
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : LT α
inst✝ : WellFoundedGT α
a : WithBot α
⊢ Acc (fun x x_1 => x > x_1) a

Next tactic:
have : Acc (· < ·) (WithBot.toDual a) := wellFounded_lt.apply _
instance _root_.WithBot.instWellFoundedGT [LT α] [WellFoundedGT α] : WellFoundedGT (WithBot α) where
  wf := ⟨fun a => by
    -- ideally, use RelHomClass.acc, but that is defined later
    have : Acc (· < ·) (WithBot.toDual a) := wellFounded_lt.apply _
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : LT α
inst✝ : WellFoundedGT α
a : WithBot α
this : Acc (fun x x_1 => x < x_1) (WithBot.toDual a)
⊢ Acc (fun x x_1 => x > x_1) a

Next tactic:
revert this
instance _root_.WithBot.instWellFoundedGT [LT α] [WellFoundedGT α] : WellFoundedGT (WithBot α) where
  wf := ⟨fun a => by
    -- ideally, use RelHomClass.acc, but that is defined later
    have : Acc (· < ·) (WithBot.toDual a) := wellFounded_lt.apply _
    revert this
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : LT α
inst✝ : WellFoundedGT α
a : WithBot α
⊢ Acc (fun x x_1 => x < x_1) (WithBot.toDual a) → Acc (fun x x_1 => x > x_1) a

Next tactic:
generalize ha : WithBot.toDual a = b
instance _root_.WithBot.instWellFoundedGT [LT α] [WellFoundedGT α] : WellFoundedGT (WithBot α) where
  wf := ⟨fun a => by
    -- ideally, use RelHomClass.acc, but that is defined later
    have : Acc (· < ·) (WithBot.toDual a) := wellFounded_lt.apply _
    revert this
    generalize ha : WithBot.toDual a = b
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : LT α
inst✝ : WellFoundedGT α
a : WithBot α
b : WithTop αᵒᵈ
ha : WithBot.toDual a = b
⊢ Acc (fun x x_1 => x < x_1) b → Acc (fun x x_1 => x > x_1) a

Next tactic:
intro ac
instance _root_.WithBot.instWellFoundedGT [LT α] [WellFoundedGT α] : WellFoundedGT (WithBot α) where
  wf := ⟨fun a => by
    -- ideally, use RelHomClass.acc, but that is defined later
    have : Acc (· < ·) (WithBot.toDual a) := wellFounded_lt.apply _
    revert this
    generalize ha : WithBot.toDual a = b
    intro ac
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : LT α
inst✝ : WellFoundedGT α
a : WithBot α
b : WithTop αᵒᵈ
ha : WithBot.toDual a = b
ac : Acc (fun x x_1 => x < x_1) b
⊢ Acc (fun x x_1 => x > x_1) a

Next tactic:
induction' ac with _ H IH generalizing a
instance _root_.WithBot.instWellFoundedGT [LT α] [WellFoundedGT α] : WellFoundedGT (WithBot α) where
  wf := ⟨fun a => by
    -- ideally, use RelHomClass.acc, but that is defined later
    have : Acc (· < ·) (WithBot.toDual a) := wellFounded_lt.apply _
    revert this
    generalize ha : WithBot.toDual a = b
    intro ac
    induction' ac with _ H IH generalizing a
    

Proof state:
case intro
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : LT α
inst✝ : WellFoundedGT α
b x✝ : WithTop αᵒᵈ
H : ∀ (y : WithTop αᵒᵈ), y < x✝ → Acc (fun x x_1 => x < x_1) y
IH : ∀ (y : WithTop αᵒᵈ), y < x✝ → ∀ (a : WithBot α), WithBot.toDual a = y → Acc (fun x x_1 => x > x_1) a
a : WithBot α
ha : WithBot.toDual a = x✝
⊢ Acc (fun x x_1 => x > x_1) a

Next tactic:
subst ha
instance _root_.WithBot.instWellFoundedGT [LT α] [WellFoundedGT α] : WellFoundedGT (WithBot α) where
  wf := ⟨fun a => by
    -- ideally, use RelHomClass.acc, but that is defined later
    have : Acc (· < ·) (WithBot.toDual a) := wellFounded_lt.apply _
    revert this
    generalize ha : WithBot.toDual a = b
    intro ac
    induction' ac with _ H IH generalizing a
    subst ha
    

Proof state:
case intro
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : LT α
inst✝ : WellFoundedGT α
b : WithTop αᵒᵈ
a : WithBot α
H : ∀ (y : WithTop αᵒᵈ), y < WithBot.toDual a → Acc (fun x x_1 => x < x_1) y
IH : ∀ (y : WithTop αᵒᵈ), y < WithBot.toDual a → ∀ (a : WithBot α), WithBot.toDual a = y → Acc (fun x x_1 => x > x_1) a
⊢ Acc (fun x x_1 => x > x_1) a

Next tactic:
exact ⟨_, fun a' h => IH (WithBot.toDual a') (toDual_lt_toDual.mpr h) _ rfl⟩
instance trichotomous.lt [Preorder α] [IsTrichotomous α (· < ·)] :
    IsTrichotomous (WithTop α) (· < ·) :=
  ⟨by
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : Preorder α
inst✝ : IsTrichotomous α fun x x_1 => x < x_1
⊢ ∀ (a b : WithTop α), a < b ∨ a = b ∨ b < a

Next tactic:
rintro (a | a) (b | b)
instance trichotomous.lt [Preorder α] [IsTrichotomous α (· < ·)] :
    IsTrichotomous (WithTop α) (· < ·) :=
  ⟨by
    rintro (a | a) (b | b)
    · 

Proof state:
case none.none
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : Preorder α
inst✝ : IsTrichotomous α fun x x_1 => x < x_1
⊢ none < none ∨ none = none ∨ none < none

Next tactic:
simp
instance trichotomous.lt [Preorder α] [IsTrichotomous α (· < ·)] :
    IsTrichotomous (WithTop α) (· < ·) :=
  ⟨by
    rintro (a | a) (b | b)
    · simp
    · 

Proof state:
case none.some
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : Preorder α
inst✝ : IsTrichotomous α fun x x_1 => x < x_1
b : α
⊢ none < Option.some b ∨ none = Option.some b ∨ Option.some b < none

Next tactic:
simp
instance trichotomous.lt [Preorder α] [IsTrichotomous α (· < ·)] :
    IsTrichotomous (WithTop α) (· < ·) :=
  ⟨by
    rintro (a | a) (b | b)
    · simp
    · simp
    · 

Proof state:
case some.none
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : Preorder α
inst✝ : IsTrichotomous α fun x x_1 => x < x_1
a : α
⊢ Option.some a < none ∨ Option.some a = none ∨ none < Option.some a

Next tactic:
simp
instance trichotomous.lt [Preorder α] [IsTrichotomous α (· < ·)] :
    IsTrichotomous (WithTop α) (· < ·) :=
  ⟨by
    rintro (a | a) (b | b)
    · simp
    · simp
    · simp
    · 

Proof state:
case some.some
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : Preorder α
inst✝ : IsTrichotomous α fun x x_1 => x < x_1
a b : α
⊢ Option.some a < Option.some b ∨ Option.some a = Option.some b ∨ Option.some b < Option.some a

Next tactic:
simpa [some_eq_coe, IsTrichotomous, coe_eq_coe] using @trichotomous α (· < ·) _ a b
instance trichotomous.gt [Preorder α] [IsTrichotomous α (· > ·)] :
    IsTrichotomous (WithTop α) (· > ·) :=
  ⟨by
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : Preorder α
inst✝ : IsTrichotomous α fun x x_1 => x > x_1
⊢ ∀ (a b : WithTop α), a > b ∨ a = b ∨ b > a

Next tactic:
rintro (a | a) (b | b)
instance trichotomous.gt [Preorder α] [IsTrichotomous α (· > ·)] :
    IsTrichotomous (WithTop α) (· > ·) :=
  ⟨by
    rintro (a | a) (b | b)
    · 

Proof state:
case none.none
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : Preorder α
inst✝ : IsTrichotomous α fun x x_1 => x > x_1
⊢ none > none ∨ none = none ∨ none > none

Next tactic:
simp
instance trichotomous.gt [Preorder α] [IsTrichotomous α (· > ·)] :
    IsTrichotomous (WithTop α) (· > ·) :=
  ⟨by
    rintro (a | a) (b | b)
    · simp
    · 

Proof state:
case none.some
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : Preorder α
inst✝ : IsTrichotomous α fun x x_1 => x > x_1
b : α
⊢ none > Option.some b ∨ none = Option.some b ∨ Option.some b > none

Next tactic:
simp
instance trichotomous.gt [Preorder α] [IsTrichotomous α (· > ·)] :
    IsTrichotomous (WithTop α) (· > ·) :=
  ⟨by
    rintro (a | a) (b | b)
    · simp
    · simp
    · 

Proof state:
case some.none
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : Preorder α
inst✝ : IsTrichotomous α fun x x_1 => x > x_1
a : α
⊢ Option.some a > none ∨ Option.some a = none ∨ none > Option.some a

Next tactic:
simp
instance trichotomous.gt [Preorder α] [IsTrichotomous α (· > ·)] :
    IsTrichotomous (WithTop α) (· > ·) :=
  ⟨by
    rintro (a | a) (b | b)
    · simp
    · simp
    · simp
    · 

Proof state:
case some.some
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : Preorder α
inst✝ : IsTrichotomous α fun x x_1 => x > x_1
a b : α
⊢ Option.some a > Option.some b ∨ Option.some a = Option.some b ∨ Option.some b > Option.some a

Next tactic:
simpa [some_eq_coe, IsTrichotomous, coe_eq_coe] using @trichotomous α (· > ·) _ a b
theorem imageMonoFactorisation_e' {X Y : C} (f : X ⟶ Y) :
    (imageMonoFactorisation f).e = cokernel.π _ ≫ Abelian.coimageImageComparison f := by
  

Proof state:
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : Preadditive C
inst✝¹ : HasKernels C
inst✝ : HasCokernels C
X Y : C
f : X ⟶ Y
⊢ (imageMonoFactorisation f).e = cokernel.π (kernel.ι f) ≫ coimageImageComparison f

Next tactic:
dsimp
theorem imageMonoFactorisation_e' {X Y : C} (f : X ⟶ Y) :
    (imageMonoFactorisation f).e = cokernel.π _ ≫ Abelian.coimageImageComparison f := by
  dsimp
  

Proof state:
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : Preadditive C
inst✝¹ : HasKernels C
inst✝ : HasCokernels C
X Y : C
f : X ⟶ Y
⊢ kernel.lift (cokernel.π f) f (_ : f ≫ cokernel.π f = 0) = cokernel.π (kernel.ι f) ≫ coimageImageComparison f

Next tactic:
ext
theorem imageMonoFactorisation_e' {X Y : C} (f : X ⟶ Y) :
    (imageMonoFactorisation f).e = cokernel.π _ ≫ Abelian.coimageImageComparison f := by
  dsimp
  ext
  

Proof state:
case h
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : Preadditive C
inst✝¹ : HasKernels C
inst✝ : HasCokernels C
X Y : C
f : X ⟶ Y
⊢ kernel.lift (cokernel.π f) f (_ : f ≫ cokernel.π f = 0) ≫ equalizer.ι (cokernel.π f) 0 =
    (cokernel.π (kernel.ι f) ≫ coimageImageComparison f) ≫ equalizer.ι (cokernel.π f) 0

Next tactic:
simp only [Abelian.coimageImageComparison, imageMonoFactorisation_e, Category.assoc,
    cokernel.π_desc_assoc]
/-- If the coimage-image comparison morphism for a morphism `f` is an isomorphism,
we obtain an image factorisation of `f`. -/
def imageFactorisation {X Y : C} (f : X ⟶ Y) [IsIso (Abelian.coimageImageComparison f)] :
    ImageFactorisation f where
  F := imageMonoFactorisation f
  isImage :=
    { lift := fun F => inv (Abelian.coimageImageComparison f) ≫ cokernel.desc _ F.e F.kernel_ι_comp
      lift_fac := fun F => by
        

Proof state:
C : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : Preadditive C
inst✝² : HasKernels C
inst✝¹ : HasCokernels C
X Y : C
f : X ⟶ Y
inst✝ : IsIso (coimageImageComparison f)
F : MonoFactorisation f
⊢ (fun F => inv (coimageImageComparison f) ≫ cokernel.desc (kernel.ι f) F.e (_ : kernel.ι f ≫ F.e = 0)) F ≫ F.m =
    (imageMonoFactorisation f).m

Next tactic:
rw [imageMonoFactorisation_m]
/-- If the coimage-image comparison morphism for a morphism `f` is an isomorphism,
we obtain an image factorisation of `f`. -/
def imageFactorisation {X Y : C} (f : X ⟶ Y) [IsIso (Abelian.coimageImageComparison f)] :
    ImageFactorisation f where
  F := imageMonoFactorisation f
  isImage :=
    { lift := fun F => inv (Abelian.coimageImageComparison f) ≫ cokernel.desc _ F.e F.kernel_ι_comp
      lift_fac := fun F => by
        rw [imageMonoFactorisation_m]
        

Proof state:
C : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : Preadditive C
inst✝² : HasKernels C
inst✝¹ : HasCokernels C
X Y : C
f : X ⟶ Y
inst✝ : IsIso (coimageImageComparison f)
F : MonoFactorisation f
⊢ (fun F => inv (coimageImageComparison f) ≫ cokernel.desc (kernel.ι f) F.e (_ : kernel.ι f ≫ F.e = 0)) F ≫ F.m =
    kernel.ι (cokernel.π f)

Next tactic:
simp only [Category.assoc]
/-- If the coimage-image comparison morphism for a morphism `f` is an isomorphism,
we obtain an image factorisation of `f`. -/
def imageFactorisation {X Y : C} (f : X ⟶ Y) [IsIso (Abelian.coimageImageComparison f)] :
    ImageFactorisation f where
  F := imageMonoFactorisation f
  isImage :=
    { lift := fun F => inv (Abelian.coimageImageComparison f) ≫ cokernel.desc _ F.e F.kernel_ι_comp
      lift_fac := fun F => by
        rw [imageMonoFactorisation_m]
        simp only [Category.assoc]
        

Proof state:
C : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : Preadditive C
inst✝² : HasKernels C
inst✝¹ : HasCokernels C
X Y : C
f : X ⟶ Y
inst✝ : IsIso (coimageImageComparison f)
F : MonoFactorisation f
⊢ inv (coimageImageComparison f) ≫ cokernel.desc (kernel.ι f) F.e (_ : kernel.ι f ≫ F.e = 0) ≫ F.m =
    kernel.ι (cokernel.π f)

Next tactic:
rw [IsIso.inv_comp_eq]
/-- If the coimage-image comparison morphism for a morphism `f` is an isomorphism,
we obtain an image factorisation of `f`. -/
def imageFactorisation {X Y : C} (f : X ⟶ Y) [IsIso (Abelian.coimageImageComparison f)] :
    ImageFactorisation f where
  F := imageMonoFactorisation f
  isImage :=
    { lift := fun F => inv (Abelian.coimageImageComparison f) ≫ cokernel.desc _ F.e F.kernel_ι_comp
      lift_fac := fun F => by
        rw [imageMonoFactorisation_m]
        simp only [Category.assoc]
        rw [IsIso.inv_comp_eq]
        

Proof state:
C : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : Preadditive C
inst✝² : HasKernels C
inst✝¹ : HasCokernels C
X Y : C
f : X ⟶ Y
inst✝ : IsIso (coimageImageComparison f)
F : MonoFactorisation f
⊢ cokernel.desc (kernel.ι f) F.e (_ : kernel.ι f ≫ F.e = 0) ≫ F.m = coimageImageComparison f ≫ kernel.ι (cokernel.π f)

Next tactic:
ext
/-- If the coimage-image comparison morphism for a morphism `f` is an isomorphism,
we obtain an image factorisation of `f`. -/
def imageFactorisation {X Y : C} (f : X ⟶ Y) [IsIso (Abelian.coimageImageComparison f)] :
    ImageFactorisation f where
  F := imageMonoFactorisation f
  isImage :=
    { lift := fun F => inv (Abelian.coimageImageComparison f) ≫ cokernel.desc _ F.e F.kernel_ι_comp
      lift_fac := fun F => by
        rw [imageMonoFactorisation_m]
        simp only [Category.assoc]
        rw [IsIso.inv_comp_eq]
        ext
        

Proof state:
case h
C : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : Preadditive C
inst✝² : HasKernels C
inst✝¹ : HasCokernels C
X Y : C
f : X ⟶ Y
inst✝ : IsIso (coimageImageComparison f)
F : MonoFactorisation f
⊢ coequalizer.π (kernel.ι f) 0 ≫ cokernel.desc (kernel.ι f) F.e (_ : kernel.ι f ≫ F.e = 0) ≫ F.m =
    coequalizer.π (kernel.ι f) 0 ≫ coimageImageComparison f ≫ kernel.ι (cokernel.π f)

Next tactic:
simp
instance [HasZeroObject C] {X Y : C} (f : X ⟶ Y) [Mono f]
    [IsIso (Abelian.coimageImageComparison f)] : IsIso (imageMonoFactorisation f).e := by
  

Proof state:
C : Type u
inst✝⁶ : Category.{v, u} C
inst✝⁵ : Preadditive C
inst✝⁴ : HasKernels C
inst✝³ : HasCokernels C
inst✝² : HasZeroObject C
X Y : C
f : X ⟶ Y
inst✝¹ : Mono f
inst✝ : IsIso (coimageImageComparison f)
⊢ IsIso (imageMonoFactorisation f).e

Next tactic:
rw [imageMonoFactorisation_e']
instance [HasZeroObject C] {X Y : C} (f : X ⟶ Y) [Mono f]
    [IsIso (Abelian.coimageImageComparison f)] : IsIso (imageMonoFactorisation f).e := by
  rw [imageMonoFactorisation_e']
  

Proof state:
C : Type u
inst✝⁶ : Category.{v, u} C
inst✝⁵ : Preadditive C
inst✝⁴ : HasKernels C
inst✝³ : HasCokernels C
inst✝² : HasZeroObject C
X Y : C
f : X ⟶ Y
inst✝¹ : Mono f
inst✝ : IsIso (coimageImageComparison f)
⊢ IsIso (cokernel.π (kernel.ι f) ≫ coimageImageComparison f)

Next tactic:
exact IsIso.comp_isIso
instance [HasZeroObject C] {X Y : C} (f : X ⟶ Y) [Epi f] : IsIso (imageMonoFactorisation f).m := by
  

Proof state:
C : Type u
inst✝⁵ : Category.{v, u} C
inst✝⁴ : Preadditive C
inst✝³ : HasKernels C
inst✝² : HasCokernels C
inst✝¹ : HasZeroObject C
X Y : C
f : X ⟶ Y
inst✝ : Epi f
⊢ IsIso (imageMonoFactorisation f).m

Next tactic:
dsimp
instance [HasZeroObject C] {X Y : C} (f : X ⟶ Y) [Epi f] : IsIso (imageMonoFactorisation f).m := by
  dsimp
  

Proof state:
C : Type u
inst✝⁵ : Category.{v, u} C
inst✝⁴ : Preadditive C
inst✝³ : HasKernels C
inst✝² : HasCokernels C
inst✝¹ : HasZeroObject C
X Y : C
f : X ⟶ Y
inst✝ : Epi f
⊢ IsIso (kernel.ι (cokernel.π f))

Next tactic:
infer_instance
/-- A category with finite products in which coimage-image comparisons are all isomorphisms
is a normal mono category.
-/
def normalMonoCategory : NormalMonoCategory C where
  normalMonoOfMono f m :=
    { Z := _
      g := cokernel.π f
      w := by 

Proof state:
C : Type u
inst✝⁵ : Category.{v, u} C
inst✝⁴ : Preadditive C
inst✝³ : HasKernels C
inst✝² : HasCokernels C
inst✝¹ : ∀ {X Y : C} (f : X ⟶ Y), IsIso (coimageImageComparison f)
inst✝ : HasFiniteProducts C
X✝ Y✝ : C
f : X✝ ⟶ Y✝
m : Mono f
⊢ f ≫ cokernel.π f = 0

Next tactic:
simp
/-- A category with finite products in which coimage-image comparisons are all isomorphisms
is a normal mono category.
-/
def normalMonoCategory : NormalMonoCategory C where
  normalMonoOfMono f m :=
    { Z := _
      g := cokernel.π f
      w := by simp
      isLimit := by
        

Proof state:
C : Type u
inst✝⁵ : Category.{v, u} C
inst✝⁴ : Preadditive C
inst✝³ : HasKernels C
inst✝² : HasCokernels C
inst✝¹ : ∀ {X Y : C} (f : X ⟶ Y), IsIso (coimageImageComparison f)
inst✝ : HasFiniteProducts C
X✝ Y✝ : C
f : X✝ ⟶ Y✝
m : Mono f
⊢ IsLimit (KernelFork.ofι f (_ : f ≫ cokernel.π f = 0))

Next tactic:
haveI : Limits.HasImages C := hasImages
/-- A category with finite products in which coimage-image comparisons are all isomorphisms
is a normal mono category.
-/
def normalMonoCategory : NormalMonoCategory C where
  normalMonoOfMono f m :=
    { Z := _
      g := cokernel.π f
      w := by simp
      isLimit := by
        haveI : Limits.HasImages C := hasImages
        

Proof state:
C : Type u
inst✝⁵ : Category.{v, u} C
inst✝⁴ : Preadditive C
inst✝³ : HasKernels C
inst✝² : HasCokernels C
inst✝¹ : ∀ {X Y : C} (f : X ⟶ Y), IsIso (coimageImageComparison f)
inst✝ : HasFiniteProducts C
X✝ Y✝ : C
f : X✝ ⟶ Y✝
m : Mono f
this : HasImages C
⊢ IsLimit (KernelFork.ofι f (_ : f ≫ cokernel.π f = 0))

Next tactic:
haveI : HasEqualizers C := Preadditive.hasEqualizers_of_hasKernels
/-- A category with finite products in which coimage-image comparisons are all isomorphisms
is a normal mono category.
-/
def normalMonoCategory : NormalMonoCategory C where
  normalMonoOfMono f m :=
    { Z := _
      g := cokernel.π f
      w := by simp
      isLimit := by
        haveI : Limits.HasImages C := hasImages
        haveI : HasEqualizers C := Preadditive.hasEqualizers_of_hasKernels
        

Proof state:
C : Type u
inst✝⁵ : Category.{v, u} C
inst✝⁴ : Preadditive C
inst✝³ : HasKernels C
inst✝² : HasCokernels C
inst✝¹ : ∀ {X Y : C} (f : X ⟶ Y), IsIso (coimageImageComparison f)
inst✝ : HasFiniteProducts C
X✝ Y✝ : C
f : X✝ ⟶ Y✝
m : Mono f
this✝ : HasImages C
this : HasEqualizers C
⊢ IsLimit (KernelFork.ofι f (_ : f ≫ cokernel.π f = 0))

Next tactic:
haveI : HasZeroObject C := Limits.hasZeroObject_of_hasFiniteBiproducts _