l3lab/ntp-mathlib huggingface dataset:
/-- The circular order obtained from "looping around" a linear order.
See note [reducible non-instances]. -/
@[reducible]
def LinearOrder.toCircularOrder (α : Type*) [LinearOrder α] : CircularOrder α :=
  { PartialOrder.toCircularPartialOrder α with
    btw_total := fun a b c => by
      rcases le_total a b with hab | hba <;> rcases le_total b c with hbc | hcb <;>
        

Proof state:
case inl.inl
α : Type u_1
inst✝ : LinearOrder α
src✝ : CircularPartialOrder α := PartialOrder.toCircularPartialOrder α
a b c : α
hab : a ≤ b
hbc : b ≤ c
⊢ btw a b c ∨ btw c b a

Next tactic:
rcases le_total c a with hca | hac
/-- The circular order obtained from "looping around" a linear order.
See note [reducible non-instances]. -/
@[reducible]
def LinearOrder.toCircularOrder (α : Type*) [LinearOrder α] : CircularOrder α :=
  { PartialOrder.toCircularPartialOrder α with
    btw_total := fun a b c => by
      rcases le_total a b with hab | hba <;> rcases le_total b c with hbc | hcb <;>
        

Proof state:
case inl.inr
α : Type u_1
inst✝ : LinearOrder α
src✝ : CircularPartialOrder α := PartialOrder.toCircularPartialOrder α
a b c : α
hab : a ≤ b
hcb : c ≤ b
⊢ btw a b c ∨ btw c b a

Next tactic:
rcases le_total c a with hca | hac
/-- The circular order obtained from "looping around" a linear order.
See note [reducible non-instances]. -/
@[reducible]
def LinearOrder.toCircularOrder (α : Type*) [LinearOrder α] : CircularOrder α :=
  { PartialOrder.toCircularPartialOrder α with
    btw_total := fun a b c => by
      rcases le_total a b with hab | hba <;> rcases le_total b c with hbc | hcb <;>
        

Proof state:
case inr.inl
α : Type u_1
inst✝ : LinearOrder α
src✝ : CircularPartialOrder α := PartialOrder.toCircularPartialOrder α
a b c : α
hba : b ≤ a
hbc : b ≤ c
⊢ btw a b c ∨ btw c b a

Next tactic:
rcases le_total c a with hca | hac
/-- The circular order obtained from "looping around" a linear order.
See note [reducible non-instances]. -/
@[reducible]
def LinearOrder.toCircularOrder (α : Type*) [LinearOrder α] : CircularOrder α :=
  { PartialOrder.toCircularPartialOrder α with
    btw_total := fun a b c => by
      rcases le_total a b with hab | hba <;> rcases le_total b c with hbc | hcb <;>
        

Proof state:
case inr.inr
α : Type u_1
inst✝ : LinearOrder α
src✝ : CircularPartialOrder α := PartialOrder.toCircularPartialOrder α
a b c : α
hba : b ≤ a
hcb : c ≤ b
⊢ btw a b c ∨ btw c b a

Next tactic:
rcases le_total c a with hca | hac
/-- The circular order obtained from "looping around" a linear order.
See note [reducible non-instances]. -/
@[reducible]
def LinearOrder.toCircularOrder (α : Type*) [LinearOrder α] : CircularOrder α :=
  { PartialOrder.toCircularPartialOrder α with
    btw_total := fun a b c => by
      rcases le_total a b with hab | hba <;> rcases le_total b c with hbc | hcb <;>
        rcases le_total c a with hca | hac
      · 

Proof state:
case inl.inl.inl
α : Type u_1
inst✝ : LinearOrder α
src✝ : CircularPartialOrder α := PartialOrder.toCircularPartialOrder α
a b c : α
hab : a ≤ b
hbc : b ≤ c
hca : c ≤ a
⊢ btw a b c ∨ btw c b a

Next tactic:
exact Or.inl (Or.inl ⟨hab, hbc⟩)
/-- The circular order obtained from "looping around" a linear order.
See note [reducible non-instances]. -/
@[reducible]
def LinearOrder.toCircularOrder (α : Type*) [LinearOrder α] : CircularOrder α :=
  { PartialOrder.toCircularPartialOrder α with
    btw_total := fun a b c => by
      rcases le_total a b with hab | hba <;> rcases le_total b c with hbc | hcb <;>
        rcases le_total c a with hca | hac
      · exact Or.inl (Or.inl ⟨hab, hbc⟩)
      · 

Proof state:
case inl.inl.inr
α : Type u_1
inst✝ : LinearOrder α
src✝ : CircularPartialOrder α := PartialOrder.toCircularPartialOrder α
a b c : α
hab : a ≤ b
hbc : b ≤ c
hac : a ≤ c
⊢ btw a b c ∨ btw c b a

Next tactic:
exact Or.inl (Or.inl ⟨hab, hbc⟩)
/-- The circular order obtained from "looping around" a linear order.
See note [reducible non-instances]. -/
@[reducible]
def LinearOrder.toCircularOrder (α : Type*) [LinearOrder α] : CircularOrder α :=
  { PartialOrder.toCircularPartialOrder α with
    btw_total := fun a b c => by
      rcases le_total a b with hab | hba <;> rcases le_total b c with hbc | hcb <;>
        rcases le_total c a with hca | hac
      · exact Or.inl (Or.inl ⟨hab, hbc⟩)
      · exact Or.inl (Or.inl ⟨hab, hbc⟩)
      · 

Proof state:
case inl.inr.inl
α : Type u_1
inst✝ : LinearOrder α
src✝ : CircularPartialOrder α := PartialOrder.toCircularPartialOrder α
a b c : α
hab : a ≤ b
hcb : c ≤ b
hca : c ≤ a
⊢ btw a b c ∨ btw c b a

Next tactic:
exact Or.inl (Or.inr <| Or.inr ⟨hca, hab⟩)
/-- The circular order obtained from "looping around" a linear order.
See note [reducible non-instances]. -/
@[reducible]
def LinearOrder.toCircularOrder (α : Type*) [LinearOrder α] : CircularOrder α :=
  { PartialOrder.toCircularPartialOrder α with
    btw_total := fun a b c => by
      rcases le_total a b with hab | hba <;> rcases le_total b c with hbc | hcb <;>
        rcases le_total c a with hca | hac
      · exact Or.inl (Or.inl ⟨hab, hbc⟩)
      · exact Or.inl (Or.inl ⟨hab, hbc⟩)
      · exact Or.inl (Or.inr <| Or.inr ⟨hca, hab⟩)
      · 

Proof state:
case inl.inr.inr
α : Type u_1
inst✝ : LinearOrder α
src✝ : CircularPartialOrder α := PartialOrder.toCircularPartialOrder α
a b c : α
hab : a ≤ b
hcb : c ≤ b
hac : a ≤ c
⊢ btw a b c ∨ btw c b a

Next tactic:
exact Or.inr (Or.inr <| Or.inr ⟨hac, hcb⟩)
/-- The circular order obtained from "looping around" a linear order.
See note [reducible non-instances]. -/
@[reducible]
def LinearOrder.toCircularOrder (α : Type*) [LinearOrder α] : CircularOrder α :=
  { PartialOrder.toCircularPartialOrder α with
    btw_total := fun a b c => by
      rcases le_total a b with hab | hba <;> rcases le_total b c with hbc | hcb <;>
        rcases le_total c a with hca | hac
      · exact Or.inl (Or.inl ⟨hab, hbc⟩)
      · exact Or.inl (Or.inl ⟨hab, hbc⟩)
      · exact Or.inl (Or.inr <| Or.inr ⟨hca, hab⟩)
      · exact Or.inr (Or.inr <| Or.inr ⟨hac, hcb⟩)
      · 

Proof state:
case inr.inl.inl
α : Type u_1
inst✝ : LinearOrder α
src✝ : CircularPartialOrder α := PartialOrder.toCircularPartialOrder α
a b c : α
hba : b ≤ a
hbc : b ≤ c
hca : c ≤ a
⊢ btw a b c ∨ btw c b a

Next tactic:
exact Or.inl (Or.inr <| Or.inl ⟨hbc, hca⟩)
/-- The circular order obtained from "looping around" a linear order.
See note [reducible non-instances]. -/
@[reducible]
def LinearOrder.toCircularOrder (α : Type*) [LinearOrder α] : CircularOrder α :=
  { PartialOrder.toCircularPartialOrder α with
    btw_total := fun a b c => by
      rcases le_total a b with hab | hba <;> rcases le_total b c with hbc | hcb <;>
        rcases le_total c a with hca | hac
      · exact Or.inl (Or.inl ⟨hab, hbc⟩)
      · exact Or.inl (Or.inl ⟨hab, hbc⟩)
      · exact Or.inl (Or.inr <| Or.inr ⟨hca, hab⟩)
      · exact Or.inr (Or.inr <| Or.inr ⟨hac, hcb⟩)
      · exact Or.inl (Or.inr <| Or.inl ⟨hbc, hca⟩)
      · 

Proof state:
case inr.inl.inr
α : Type u_1
inst✝ : LinearOrder α
src✝ : CircularPartialOrder α := PartialOrder.toCircularPartialOrder α
a b c : α
hba : b ≤ a
hbc : b ≤ c
hac : a ≤ c
⊢ btw a b c ∨ btw c b a

Next tactic:
exact Or.inr (Or.inr <| Or.inl ⟨hba, hac⟩)
/-- The circular order obtained from "looping around" a linear order.
See note [reducible non-instances]. -/
@[reducible]
def LinearOrder.toCircularOrder (α : Type*) [LinearOrder α] : CircularOrder α :=
  { PartialOrder.toCircularPartialOrder α with
    btw_total := fun a b c => by
      rcases le_total a b with hab | hba <;> rcases le_total b c with hbc | hcb <;>
        rcases le_total c a with hca | hac
      · exact Or.inl (Or.inl ⟨hab, hbc⟩)
      · exact Or.inl (Or.inl ⟨hab, hbc⟩)
      · exact Or.inl (Or.inr <| Or.inr ⟨hca, hab⟩)
      · exact Or.inr (Or.inr <| Or.inr ⟨hac, hcb⟩)
      · exact Or.inl (Or.inr <| Or.inl ⟨hbc, hca⟩)
      · exact Or.inr (Or.inr <| Or.inl ⟨hba, hac⟩)
      · 

Proof state:
case inr.inr.inl
α : Type u_1
inst✝ : LinearOrder α
src✝ : CircularPartialOrder α := PartialOrder.toCircularPartialOrder α
a b c : α
hba : b ≤ a
hcb : c ≤ b
hca : c ≤ a
⊢ btw a b c ∨ btw c b a

Next tactic:
exact Or.inr (Or.inl ⟨hcb, hba⟩)
/-- The circular order obtained from "looping around" a linear order.
See note [reducible non-instances]. -/
@[reducible]
def LinearOrder.toCircularOrder (α : Type*) [LinearOrder α] : CircularOrder α :=
  { PartialOrder.toCircularPartialOrder α with
    btw_total := fun a b c => by
      rcases le_total a b with hab | hba <;> rcases le_total b c with hbc | hcb <;>
        rcases le_total c a with hca | hac
      · exact Or.inl (Or.inl ⟨hab, hbc⟩)
      · exact Or.inl (Or.inl ⟨hab, hbc⟩)
      · exact Or.inl (Or.inr <| Or.inr ⟨hca, hab⟩)
      · exact Or.inr (Or.inr <| Or.inr ⟨hac, hcb⟩)
      · exact Or.inl (Or.inr <| Or.inl ⟨hbc, hca⟩)
      · exact Or.inr (Or.inr <| Or.inl ⟨hba, hac⟩)
      · exact Or.inr (Or.inl ⟨hcb, hba⟩)
      · 

Proof state:
case inr.inr.inr
α : Type u_1
inst✝ : LinearOrder α
src✝ : CircularPartialOrder α := PartialOrder.toCircularPartialOrder α
a b c : α
hba : b ≤ a
hcb : c ≤ b
hac : a ≤ c
⊢ btw a b c ∨ btw c b a

Next tactic:
exact Or.inr (Or.inr <| Or.inl ⟨hba, hac⟩)
theorem image.fac : factorThruImage f ≫ image.ι f = f := by
  

Proof state:
G H : AddCommGroupCat
f : G ⟶ H
⊢ factorThruImage f ≫ ι f = f

Next tactic:
ext
theorem image.fac : factorThruImage f ≫ image.ι f = f := by
  ext
  

Proof state:
case w
G H : AddCommGroupCat
f : G ⟶ H
x✝ : ↑G
⊢ (factorThruImage f ≫ ι f) x✝ = f x✝

Next tactic:
rfl
/-- the universal property for the image factorisation -/
noncomputable def image.lift (F' : MonoFactorisation f) : image f ⟶ F'.I where
  toFun := (fun x => F'.e (Classical.indefiniteDescription _ x.2).1 : image f → F'.I)
  map_zero' := by
    

Proof state:
G H : AddCommGroupCat
f : G ⟶ H
F' : MonoFactorisation f
⊢ (fun x => F'.e ↑(Classical.indefiniteDescription (fun x_1 => f x_1 = ↑x) (_ : ↑x ∈ AddMonoidHom.range f))) 0 = 0

Next tactic:
haveI := F'.m_mono
/-- the universal property for the image factorisation -/
noncomputable def image.lift (F' : MonoFactorisation f) : image f ⟶ F'.I where
  toFun := (fun x => F'.e (Classical.indefiniteDescription _ x.2).1 : image f → F'.I)
  map_zero' := by
    haveI := F'.m_mono
    

Proof state:
G H : AddCommGroupCat
f : G ⟶ H
F' : MonoFactorisation f
this : Mono F'.m
⊢ (fun x => F'.e ↑(Classical.indefiniteDescription (fun x_1 => f x_1 = ↑x) (_ : ↑x ∈ AddMonoidHom.range f))) 0 = 0

Next tactic:
apply injective_of_mono F'.m
/-- the universal property for the image factorisation -/
noncomputable def image.lift (F' : MonoFactorisation f) : image f ⟶ F'.I where
  toFun := (fun x => F'.e (Classical.indefiniteDescription _ x.2).1 : image f → F'.I)
  map_zero' := by
    haveI := F'.m_mono
    apply injective_of_mono F'.m
    

Proof state:
case a
G H : AddCommGroupCat
f : G ⟶ H
F' : MonoFactorisation f
this : Mono F'.m
⊢ F'.m ((fun x => F'.e ↑(Classical.indefiniteDescription (fun x_1 => f x_1 = ↑x) (_ : ↑x ∈ AddMonoidHom.range f))) 0) =
    F'.m 0

Next tactic:
change (F'.e ≫ F'.m) _ = _
/-- the universal property for the image factorisation -/
noncomputable def image.lift (F' : MonoFactorisation f) : image f ⟶ F'.I where
  toFun := (fun x => F'.e (Classical.indefiniteDescription _ x.2).1 : image f → F'.I)
  map_zero' := by
    haveI := F'.m_mono
    apply injective_of_mono F'.m
    change (F'.e ≫ F'.m) _ = _
    

Proof state:
case a
G H : AddCommGroupCat
f : G ⟶ H
F' : MonoFactorisation f
this : Mono F'.m
⊢ (F'.e ≫ F'.m) ↑(Classical.indefiniteDescription (fun x => f x = ↑0) (_ : ↑0 ∈ AddMonoidHom.range f)) = F'.m 0

Next tactic:
rw [F'.fac, AddMonoidHom.map_zero]
/-- the universal property for the image factorisation -/
noncomputable def image.lift (F' : MonoFactorisation f) : image f ⟶ F'.I where
  toFun := (fun x => F'.e (Classical.indefiniteDescription _ x.2).1 : image f → F'.I)
  map_zero' := by
    haveI := F'.m_mono
    apply injective_of_mono F'.m
    change (F'.e ≫ F'.m) _ = _
    rw [F'.fac, AddMonoidHom.map_zero]
    

Proof state:
case a
G H : AddCommGroupCat
f : G ⟶ H
F' : MonoFactorisation f
this : Mono F'.m
⊢ f ↑(Classical.indefiniteDescription (fun x => f x = ↑0) (_ : ↑0 ∈ AddMonoidHom.range f)) = 0

Next tactic:
exact (Classical.indefiniteDescription (fun y => f y = 0) _).2
/-- the universal property for the image factorisation -/
noncomputable def image.lift (F' : MonoFactorisation f) : image f ⟶ F'.I where
  toFun := (fun x => F'.e (Classical.indefiniteDescription _ x.2).1 : image f → F'.I)
  map_zero' := by
    haveI := F'.m_mono
    apply injective_of_mono F'.m
    change (F'.e ≫ F'.m) _ = _
    rw [F'.fac, AddMonoidHom.map_zero]
    exact (Classical.indefiniteDescription (fun y => f y = 0) _).2
  map_add' := by
    

Proof state:
G H : AddCommGroupCat
f : G ⟶ H
F' : MonoFactorisation f
⊢ ∀ (x y : ↑(image f)),
    ZeroHom.toFun
        {
          toFun := fun x =>
            F'.e ↑(Classical.indefiniteDescription (fun x_1 => f x_1 = ↑x) (_ : ↑x ∈ AddMonoidHom.range f)),
          map_zero' :=
            (_ :
              (fun x => F'.e ↑(Classical.indefiniteDescription (fun x_1 => f x_1 = ↑x) (_ : ↑x ∈ AddMonoidHom.range f)))
                  0 =
                0) }
        (x + y) =
      ZeroHom.toFun
          {
            toFun := fun x =>
              F'.e ↑(Classical.indefiniteDescription (fun x_1 => f x_1 = ↑x) (_ : ↑x ∈ AddMonoidHom.range f)),
            map_zero' :=
              (_ :
                (fun x =>
                      F'.e ↑(Classical.indefiniteDescription (fun x_1 => f x_1 = ↑x) (_ : ↑x ∈ AddMonoidHom.range f)))
                    0 =
                  0) }
          x +
        ZeroHom.toFun
          {
            toFun := fun x =>
              F'.e ↑(Classical.indefiniteDescription (fun x_1 => f x_1 = ↑x) (_ : ↑x ∈ AddMonoidHom.range f)),
            map_zero' :=
              (_ :
                (fun x =>
                      F'.e ↑(Classical.indefiniteDescription (fun x_1 => f x_1 = ↑x) (_ : ↑x ∈ AddMonoidHom.range f)))
                    0 =
                  0) }
          y

Next tactic:
intro x y
/-- the universal property for the image factorisation -/
noncomputable def image.lift (F' : MonoFactorisation f) : image f ⟶ F'.I where
  toFun := (fun x => F'.e (Classical.indefiniteDescription _ x.2).1 : image f → F'.I)
  map_zero' := by
    haveI := F'.m_mono
    apply injective_of_mono F'.m
    change (F'.e ≫ F'.m) _ = _
    rw [F'.fac, AddMonoidHom.map_zero]
    exact (Classical.indefiniteDescription (fun y => f y = 0) _).2
  map_add' := by
    intro x y
    

Proof state:
G H : AddCommGroupCat
f : G ⟶ H
F' : MonoFactorisation f
x y : ↑(image f)
⊢ ZeroHom.toFun
      {
        toFun := fun x =>
          F'.e ↑(Classical.indefiniteDescription (fun x_1 => f x_1 = ↑x) (_ : ↑x ∈ AddMonoidHom.range f)),
        map_zero' :=
          (_ :
            (fun x => F'.e ↑(Classical.indefiniteDescription (fun x_1 => f x_1 = ↑x) (_ : ↑x ∈ AddMonoidHom.range f)))
                0 =
              0) }
      (x + y) =
    ZeroHom.toFun
        {
          toFun := fun x =>
            F'.e ↑(Classical.indefiniteDescription (fun x_1 => f x_1 = ↑x) (_ : ↑x ∈ AddMonoidHom.range f)),
          map_zero' :=
            (_ :
              (fun x => F'.e ↑(Classical.indefiniteDescription (fun x_1 => f x_1 = ↑x) (_ : ↑x ∈ AddMonoidHom.range f)))
                  0 =
                0) }
        x +
      ZeroHom.toFun
        {
          toFun := fun x =>
            F'.e ↑(Classical.indefiniteDescription (fun x_1 => f x_1 = ↑x) (_ : ↑x ∈ AddMonoidHom.range f)),
          map_zero' :=
            (_ :
              (fun x => F'.e ↑(Classical.indefiniteDescription (fun x_1 => f x_1 = ↑x) (_ : ↑x ∈ AddMonoidHom.range f)))
                  0 =
                0) }
        y

Next tactic:
haveI := F'.m_mono
/-- the universal property for the image factorisation -/
noncomputable def image.lift (F' : MonoFactorisation f) : image f ⟶ F'.I where
  toFun := (fun x => F'.e (Classical.indefiniteDescription _ x.2).1 : image f → F'.I)
  map_zero' := by
    haveI := F'.m_mono
    apply injective_of_mono F'.m
    change (F'.e ≫ F'.m) _ = _
    rw [F'.fac, AddMonoidHom.map_zero]
    exact (Classical.indefiniteDescription (fun y => f y = 0) _).2
  map_add' := by
    intro x y
    haveI := F'.m_mono
    

Proof state:
G H : AddCommGroupCat
f : G ⟶ H
F' : MonoFactorisation f
x y : ↑(image f)
this : Mono F'.m
⊢ ZeroHom.toFun
      {
        toFun := fun x =>
          F'.e ↑(Classical.indefiniteDescription (fun x_1 => f x_1 = ↑x) (_ : ↑x ∈ AddMonoidHom.range f)),
        map_zero' :=
          (_ :
            (fun x => F'.e ↑(Classical.indefiniteDescription (fun x_1 => f x_1 = ↑x) (_ : ↑x ∈ AddMonoidHom.range f)))
                0 =
              0) }
      (x + y) =
    ZeroHom.toFun
        {
          toFun := fun x =>
            F'.e ↑(Classical.indefiniteDescription (fun x_1 => f x_1 = ↑x) (_ : ↑x ∈ AddMonoidHom.range f)),
          map_zero' :=
            (_ :
              (fun x => F'.e ↑(Classical.indefiniteDescription (fun x_1 => f x_1 = ↑x) (_ : ↑x ∈ AddMonoidHom.range f)))
                  0 =
                0) }
        x +
      ZeroHom.toFun
        {
          toFun := fun x =>
            F'.e ↑(Classical.indefiniteDescription (fun x_1 => f x_1 = ↑x) (_ : ↑x ∈ AddMonoidHom.range f)),
          map_zero' :=
            (_ :
              (fun x => F'.e ↑(Classical.indefiniteDescription (fun x_1 => f x_1 = ↑x) (_ : ↑x ∈ AddMonoidHom.range f)))
                  0 =
                0) }
        y

Next tactic:
apply injective_of_mono F'.m
/-- the universal property for the image factorisation -/
noncomputable def image.lift (F' : MonoFactorisation f) : image f ⟶ F'.I where
  toFun := (fun x => F'.e (Classical.indefiniteDescription _ x.2).1 : image f → F'.I)
  map_zero' := by
    haveI := F'.m_mono
    apply injective_of_mono F'.m
    change (F'.e ≫ F'.m) _ = _
    rw [F'.fac, AddMonoidHom.map_zero]
    exact (Classical.indefiniteDescription (fun y => f y = 0) _).2
  map_add' := by
    intro x y
    haveI := F'.m_mono
    apply injective_of_mono F'.m
    

Proof state:
case a
G H : AddCommGroupCat
f : G ⟶ H
F' : MonoFactorisation f
x y : ↑(image f)
this : Mono F'.m
⊢ F'.m
      (ZeroHom.toFun
        {
          toFun := fun x =>
            F'.e ↑(Classical.indefiniteDescription (fun x_1 => f x_1 = ↑x) (_ : ↑x ∈ AddMonoidHom.range f)),
          map_zero' :=
            (_ :
              (fun x => F'.e ↑(Classical.indefiniteDescription (fun x_1 => f x_1 = ↑x) (_ : ↑x ∈ AddMonoidHom.range f)))
                  0 =
                0) }
        (x + y)) =
    F'.m
      (ZeroHom.toFun
          {
            toFun := fun x =>
              F'.e ↑(Classical.indefiniteDescription (fun x_1 => f x_1 = ↑x) (_ : ↑x ∈ AddMonoidHom.range f)),
            map_zero' :=
              (_ :
                (fun x =>
                      F'.e ↑(Classical.indefiniteDescription (fun x_1 => f x_1 = ↑x) (_ : ↑x ∈ AddMonoidHom.range f)))
                    0 =
                  0) }
          x +
        ZeroHom.toFun
          {
            toFun := fun x =>
              F'.e ↑(Classical.indefiniteDescription (fun x_1 => f x_1 = ↑x) (_ : ↑x ∈ AddMonoidHom.range f)),
            map_zero' :=
              (_ :
                (fun x =>
                      F'.e ↑(Classical.indefiniteDescription (fun x_1 => f x_1 = ↑x) (_ : ↑x ∈ AddMonoidHom.range f)))
                    0 =
                  0) }
          y)

Next tactic:
rw [AddMonoidHom.map_add]
/-- the universal property for the image factorisation -/
noncomputable def image.lift (F' : MonoFactorisation f) : image f ⟶ F'.I where
  toFun := (fun x => F'.e (Classical.indefiniteDescription _ x.2).1 : image f → F'.I)
  map_zero' := by
    haveI := F'.m_mono
    apply injective_of_mono F'.m
    change (F'.e ≫ F'.m) _ = _
    rw [F'.fac, AddMonoidHom.map_zero]
    exact (Classical.indefiniteDescription (fun y => f y = 0) _).2
  map_add' := by
    intro x y
    haveI := F'.m_mono
    apply injective_of_mono F'.m
    rw [AddMonoidHom.map_add]
    

Proof state:
case a
G H : AddCommGroupCat
f : G ⟶ H
F' : MonoFactorisation f
x y : ↑(image f)
this : Mono F'.m
⊢ F'.m
      (ZeroHom.toFun
        {
          toFun := fun x =>
            F'.e ↑(Classical.indefiniteDescription (fun x_1 => f x_1 = ↑x) (_ : ↑x ∈ AddMonoidHom.range f)),
          map_zero' :=
            (_ :
              (fun x => F'.e ↑(Classical.indefiniteDescription (fun x_1 => f x_1 = ↑x) (_ : ↑x ∈ AddMonoidHom.range f)))
                  0 =
                0) }
        (x + y)) =
    F'.m
        (ZeroHom.toFun
          {
            toFun := fun x =>
              F'.e ↑(Classical.indefiniteDescription (fun x_1 => f x_1 = ↑x) (_ : ↑x ∈ AddMonoidHom.range f)),
            map_zero' :=
              (_ :
                (fun x =>
                      F'.e ↑(Classical.indefiniteDescription (fun x_1 => f x_1 = ↑x) (_ : ↑x ∈ AddMonoidHom.range f)))
                    0 =
                  0) }
          x) +
      F'.m
        (ZeroHom.toFun
          {
            toFun := fun x =>
              F'.e ↑(Classical.indefiniteDescription (fun x_1 => f x_1 = ↑x) (_ : ↑x ∈ AddMonoidHom.range f)),
            map_zero' :=
              (_ :
                (fun x =>
                      F'.e ↑(Classical.indefiniteDescription (fun x_1 => f x_1 = ↑x) (_ : ↑x ∈ AddMonoidHom.range f)))
                    0 =
                  0) }
          y)

Next tactic:
change (F'.e ≫ F'.m) _ = (F'.e ≫ F'.m) _ + (F'.e ≫ F'.m) _
/-- the universal property for the image factorisation -/
noncomputable def image.lift (F' : MonoFactorisation f) : image f ⟶ F'.I where
  toFun := (fun x => F'.e (Classical.indefiniteDescription _ x.2).1 : image f → F'.I)
  map_zero' := by
    haveI := F'.m_mono
    apply injective_of_mono F'.m
    change (F'.e ≫ F'.m) _ = _
    rw [F'.fac, AddMonoidHom.map_zero]
    exact (Classical.indefiniteDescription (fun y => f y = 0) _).2
  map_add' := by
    intro x y
    haveI := F'.m_mono
    apply injective_of_mono F'.m
    rw [AddMonoidHom.map_add]
    change (F'.e ≫ F'.m) _ = (F'.e ≫ F'.m) _ + (F'.e ≫ F'.m) _
    

Proof state:
case a
G H : AddCommGroupCat
f : G ⟶ H
F' : MonoFactorisation f
x y : ↑(image f)
this : Mono F'.m
⊢ (F'.e ≫ F'.m) ↑(Classical.indefiniteDescription (fun x_1 => f x_1 = ↑(x + y)) (_ : ↑(x + y) ∈ AddMonoidHom.range f)) =
    (F'.e ≫ F'.m) ↑(Classical.indefiniteDescription (fun x_1 => f x_1 = ↑x) (_ : ↑x ∈ AddMonoidHom.range f)) +
      (F'.e ≫ F'.m) ↑(Classical.indefiniteDescription (fun x => f x = ↑y) (_ : ↑y ∈ AddMonoidHom.range f))

Next tactic:
rw [F'.fac]
/-- the universal property for the image factorisation -/
noncomputable def image.lift (F' : MonoFactorisation f) : image f ⟶ F'.I where
  toFun := (fun x => F'.e (Classical.indefiniteDescription _ x.2).1 : image f → F'.I)
  map_zero' := by
    haveI := F'.m_mono
    apply injective_of_mono F'.m
    change (F'.e ≫ F'.m) _ = _
    rw [F'.fac, AddMonoidHom.map_zero]
    exact (Classical.indefiniteDescription (fun y => f y = 0) _).2
  map_add' := by
    intro x y
    haveI := F'.m_mono
    apply injective_of_mono F'.m
    rw [AddMonoidHom.map_add]
    change (F'.e ≫ F'.m) _ = (F'.e ≫ F'.m) _ + (F'.e ≫ F'.m) _
    rw [F'.fac]
    

Proof state:
case a
G H : AddCommGroupCat
f : G ⟶ H
F' : MonoFactorisation f
x y : ↑(image f)
this : Mono F'.m
⊢ f ↑(Classical.indefiniteDescription (fun x_1 => f x_1 = ↑(x + y)) (_ : ↑(x + y) ∈ AddMonoidHom.range f)) =
    f ↑(Classical.indefiniteDescription (fun x_1 => f x_1 = ↑x) (_ : ↑x ∈ AddMonoidHom.range f)) +
      f ↑(Classical.indefiniteDescription (fun x => f x = ↑y) (_ : ↑y ∈ AddMonoidHom.range f))

Next tactic:
rw [(Classical.indefiniteDescription (fun z => f z = _) _).2]