l3lab/ntp-mathlib huggingface dataset:
/-- Auxiliary definition for `HasCokernels SemiNormedGroupCat`. -/
noncomputable
def isColimitCokernelCocone {X Y : SemiNormedGroupCat.{u}} (f : X ⟶ Y) :
    IsColimit (cokernelCocone f) :=
  isColimitAux _ (cokernelLift f)
    (fun s => by
      ext
      apply NormedAddGroupHom.lift_mk f.range
      

Proof state:
case h.hf
X Y : SemiNormedGroupCat
f : X ⟶ Y
s : CokernelCofork f
x✝ : ↑((parallelPair f 0).obj WalkingParallelPair.one)
⊢ ∀ s_1 ∈ NormedAddGroupHom.range f, (Cofork.π s) s_1 = 0

Next tactic:
rintro _ ⟨b, rfl⟩
/-- Auxiliary definition for `HasCokernels SemiNormedGroupCat`. -/
noncomputable
def isColimitCokernelCocone {X Y : SemiNormedGroupCat.{u}} (f : X ⟶ Y) :
    IsColimit (cokernelCocone f) :=
  isColimitAux _ (cokernelLift f)
    (fun s => by
      ext
      apply NormedAddGroupHom.lift_mk f.range
      rintro _ ⟨b, rfl⟩
      

Proof state:
case h.hf.intro
X Y : SemiNormedGroupCat
f : X ⟶ Y
s : CokernelCofork f
x✝ : ↑((parallelPair f 0).obj WalkingParallelPair.one)
b : ↑X
⊢ (Cofork.π s) ((NormedAddGroupHom.toAddMonoidHom f) b) = 0

Next tactic:
change (f ≫ s.π) b = 0
/-- Auxiliary definition for `HasCokernels SemiNormedGroupCat`. -/
noncomputable
def isColimitCokernelCocone {X Y : SemiNormedGroupCat.{u}} (f : X ⟶ Y) :
    IsColimit (cokernelCocone f) :=
  isColimitAux _ (cokernelLift f)
    (fun s => by
      ext
      apply NormedAddGroupHom.lift_mk f.range
      rintro _ ⟨b, rfl⟩
      change (f ≫ s.π) b = 0
      

Proof state:
case h.hf.intro
X Y : SemiNormedGroupCat
f : X ⟶ Y
s : CokernelCofork f
x✝ : ↑((parallelPair f 0).obj WalkingParallelPair.one)
b : ↑X
⊢ (f ≫ Cofork.π s) b = 0

Next tactic:
simp
/-- Auxiliary definition for `HasCokernels SemiNormedGroupCat`. -/
noncomputable
def isColimitCokernelCocone {X Y : SemiNormedGroupCat.{u}} (f : X ⟶ Y) :
    IsColimit (cokernelCocone f) :=
  isColimitAux _ (cokernelLift f)
    (fun s => by
      ext
      apply NormedAddGroupHom.lift_mk f.range
      rintro _ ⟨b, rfl⟩
      change (f ≫ s.π) b = 0
      simp
      -- This used to be the end of the proof before leanprover/lean4#2644
      

Proof state:
case h.hf.intro
X Y : SemiNormedGroupCat
f : X ⟶ Y
s : CokernelCofork f
x✝ : ↑((parallelPair f 0).obj WalkingParallelPair.one)
b : ↑X
⊢ 0 b = 0

Next tactic:
erw [zero_apply]
example : HasCokernels SemiNormedGroupCat := by 

Proof state:
⊢ HasCokernels SemiNormedGroupCat

Next tactic:
infer_instance
/-- Descend to the explicit cokernel. -/
noncomputable
def explicitCokernelDesc {X Y Z : SemiNormedGroupCat.{u}} {f : X ⟶ Y} {g : Y ⟶ Z} (w : f ≫ g = 0) :
    explicitCokernel f ⟶ Z :=
  (isColimitCokernelCocone f).desc (Cofork.ofπ g (by 

Proof state:
X Y Z : SemiNormedGroupCat
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
⊢ f ≫ g = 0 ≫ g

Next tactic:
simp [w]
@[simp, reassoc]
theorem comp_explicitCokernelπ {X Y : SemiNormedGroupCat.{u}} (f : X ⟶ Y) :
    f ≫ explicitCokernelπ f = 0 := by
  

Proof state:
X Y : SemiNormedGroupCat
f : X ⟶ Y
⊢ f ≫ explicitCokernelπ f = 0

Next tactic:
convert (cokernelCocone f).w WalkingParallelPairHom.left
@[simp, reassoc]
theorem comp_explicitCokernelπ {X Y : SemiNormedGroupCat.{u}} (f : X ⟶ Y) :
    f ≫ explicitCokernelπ f = 0 := by
  convert (cokernelCocone f).w WalkingParallelPairHom.left
  

Proof state:
case h.e'_3.h
X Y : SemiNormedGroupCat
f : X ⟶ Y
e_1✝ :
  (X ⟶ explicitCokernel f) =
    ((parallelPair f 0).obj WalkingParallelPair.zero ⟶
      ((Functor.const WalkingParallelPair).obj (cokernelCocone f).pt).obj WalkingParallelPair.one)
⊢ 0 = (cokernelCocone f).ι.app WalkingParallelPair.zero

Next tactic:
simp
@[simp]
theorem explicitCokernelπ_apply_dom_eq_zero {X Y : SemiNormedGroupCat.{u}} {f : X ⟶ Y} (x : X) :
    (explicitCokernelπ f) (f x) = 0 :=
  show (f ≫ explicitCokernelπ f) x = 0 by 

Proof state:
X Y : SemiNormedGroupCat
f : X ⟶ Y
x : ↑X
⊢ (f ≫ explicitCokernelπ f) x = 0

Next tactic:
rw [comp_explicitCokernelπ]
@[simp]
theorem explicitCokernelπ_apply_dom_eq_zero {X Y : SemiNormedGroupCat.{u}} {f : X ⟶ Y} (x : X) :
    (explicitCokernelπ f) (f x) = 0 :=
  show (f ≫ explicitCokernelπ f) x = 0 by rw [comp_explicitCokernelπ]; 

Proof state:
X Y : SemiNormedGroupCat
f : X ⟶ Y
x : ↑X
⊢ 0 x = 0

Next tactic:
rfl
@[simp]
theorem explicitCokernelπ_desc_apply {X Y Z : SemiNormedGroupCat.{u}} {f : X ⟶ Y} {g : Y ⟶ Z}
    {cond : f ≫ g = 0} (x : Y) : explicitCokernelDesc cond (explicitCokernelπ f x) = g x :=
  show (explicitCokernelπ f ≫ explicitCokernelDesc cond) x = g x by 

Proof state:
X Y Z : SemiNormedGroupCat
f : X ⟶ Y
g : Y ⟶ Z
cond : f ≫ g = 0
x : ↑Y
⊢ (explicitCokernelπ f ≫ explicitCokernelDesc cond) x = g x

Next tactic:
rw [explicitCokernelπ_desc]
theorem explicitCokernelDesc_unique {X Y Z : SemiNormedGroupCat.{u}} {f : X ⟶ Y} {g : Y ⟶ Z}
    (w : f ≫ g = 0) (e : explicitCokernel f ⟶ Z) (he : explicitCokernelπ f ≫ e = g) :
    e = explicitCokernelDesc w := by
  

Proof state:
X Y Z : SemiNormedGroupCat
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
e : explicitCokernel f ⟶ Z
he : explicitCokernelπ f ≫ e = g
⊢ e = explicitCokernelDesc w

Next tactic:
apply (isColimitCokernelCocone f).uniq (Cofork.ofπ g (by simp [w]))
theorem explicitCokernelDesc_unique {X Y Z : SemiNormedGroupCat.{u}} {f : X ⟶ Y} {g : Y ⟶ Z}
    (w : f ≫ g = 0) (e : explicitCokernel f ⟶ Z) (he : explicitCokernelπ f ≫ e = g) :
    e = explicitCokernelDesc w := by
  apply (isColimitCokernelCocone f).uniq (Cofork.ofπ g (by 

Proof state:
X Y Z : SemiNormedGroupCat
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
e : explicitCokernel f ⟶ Z
he : explicitCokernelπ f ≫ e = g
⊢ f ≫ g = 0 ≫ g

Next tactic:
simp [w]
theorem explicitCokernelDesc_unique {X Y Z : SemiNormedGroupCat.{u}} {f : X ⟶ Y} {g : Y ⟶ Z}
    (w : f ≫ g = 0) (e : explicitCokernel f ⟶ Z) (he : explicitCokernelπ f ≫ e = g) :
    e = explicitCokernelDesc w := by
  apply (isColimitCokernelCocone f).uniq (Cofork.ofπ g (by simp [w]))
  

Proof state:
case x
X Y Z : SemiNormedGroupCat
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
e : explicitCokernel f ⟶ Z
he : explicitCokernelπ f ≫ e = g
⊢ ∀ (j : WalkingParallelPair), (cokernelCocone f).ι.app j ≫ e = (Cofork.ofπ g (_ : f ≫ g = 0 ≫ g)).ι.app j

Next tactic:
rintro (_ | _)
theorem explicitCokernelDesc_unique {X Y Z : SemiNormedGroupCat.{u}} {f : X ⟶ Y} {g : Y ⟶ Z}
    (w : f ≫ g = 0) (e : explicitCokernel f ⟶ Z) (he : explicitCokernelπ f ≫ e = g) :
    e = explicitCokernelDesc w := by
  apply (isColimitCokernelCocone f).uniq (Cofork.ofπ g (by simp [w]))
  rintro (_ | _)
  · 

Proof state:
case x.zero
X Y Z : SemiNormedGroupCat
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
e : explicitCokernel f ⟶ Z
he : explicitCokernelπ f ≫ e = g
⊢ (cokernelCocone f).ι.app WalkingParallelPair.zero ≫ e =
    (Cofork.ofπ g (_ : f ≫ g = 0 ≫ g)).ι.app WalkingParallelPair.zero

Next tactic:
convert w.symm
theorem explicitCokernelDesc_unique {X Y Z : SemiNormedGroupCat.{u}} {f : X ⟶ Y} {g : Y ⟶ Z}
    (w : f ≫ g = 0) (e : explicitCokernel f ⟶ Z) (he : explicitCokernelπ f ≫ e = g) :
    e = explicitCokernelDesc w := by
  apply (isColimitCokernelCocone f).uniq (Cofork.ofπ g (by simp [w]))
  rintro (_ | _)
  · convert w.symm
    

Proof state:
case h.e'_2.h
X Y Z : SemiNormedGroupCat
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
e : explicitCokernel f ⟶ Z
he : explicitCokernelπ f ≫ e = g
e_1✝ : ((parallelPair f 0).obj WalkingParallelPair.zero ⟶ (Cofork.ofπ g (_ : f ≫ g = 0 ≫ g)).pt) = (X ⟶ Z)
⊢ (cokernelCocone f).ι.app WalkingParallelPair.zero ≫ e = 0

Next tactic:
simp
theorem explicitCokernelDesc_unique {X Y Z : SemiNormedGroupCat.{u}} {f : X ⟶ Y} {g : Y ⟶ Z}
    (w : f ≫ g = 0) (e : explicitCokernel f ⟶ Z) (he : explicitCokernelπ f ≫ e = g) :
    e = explicitCokernelDesc w := by
  apply (isColimitCokernelCocone f).uniq (Cofork.ofπ g (by simp [w]))
  rintro (_ | _)
  · convert w.symm
    simp
  · 

Proof state:
case x.one
X Y Z : SemiNormedGroupCat
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
e : explicitCokernel f ⟶ Z
he : explicitCokernelπ f ≫ e = g
⊢ (cokernelCocone f).ι.app WalkingParallelPair.one ≫ e =
    (Cofork.ofπ g (_ : f ≫ g = 0 ≫ g)).ι.app WalkingParallelPair.one

Next tactic:
exact he
theorem explicitCokernelDesc_comp_eq_desc {X Y Z W : SemiNormedGroupCat.{u}} {f : X ⟶ Y} {g : Y ⟶ Z}
    -- Porting note: renamed `cond` to `cond'` to avoid
    -- failed to rewrite using equation theorems for 'cond'
    {h : Z ⟶ W} {cond' : f ≫ g = 0} :
    explicitCokernelDesc cond' ≫ h =
      explicitCokernelDesc
        (show f ≫ g ≫ h = 0 by 

Proof state:
X Y Z W : SemiNormedGroupCat
f : X ⟶ Y
g : Y ⟶ Z
h : Z ⟶ W
cond' : f ≫ g = 0
⊢ f ≫ g ≫ h = 0

Next tactic:
rw [← CategoryTheory.Category.assoc, cond', Limits.zero_comp]
theorem explicitCokernelDesc_comp_eq_desc {X Y Z W : SemiNormedGroupCat.{u}} {f : X ⟶ Y} {g : Y ⟶ Z}
    -- Porting note: renamed `cond` to `cond'` to avoid
    -- failed to rewrite using equation theorems for 'cond'
    {h : Z ⟶ W} {cond' : f ≫ g = 0} :
    explicitCokernelDesc cond' ≫ h =
      explicitCokernelDesc
        (show f ≫ g ≫ h = 0 by rw [← CategoryTheory.Category.assoc, cond', Limits.zero_comp]) := by
  

Proof state:
X Y Z W : SemiNormedGroupCat
f : X ⟶ Y
g : Y ⟶ Z
h : Z ⟶ W
cond' : f ≫ g = 0
⊢ explicitCokernelDesc cond' ≫ h = explicitCokernelDesc (_ : f ≫ g ≫ h = 0)

Next tactic:
refine' explicitCokernelDesc_unique _ _ _
theorem explicitCokernelDesc_comp_eq_desc {X Y Z W : SemiNormedGroupCat.{u}} {f : X ⟶ Y} {g : Y ⟶ Z}
    -- Porting note: renamed `cond` to `cond'` to avoid
    -- failed to rewrite using equation theorems for 'cond'
    {h : Z ⟶ W} {cond' : f ≫ g = 0} :
    explicitCokernelDesc cond' ≫ h =
      explicitCokernelDesc
        (show f ≫ g ≫ h = 0 by rw [← CategoryTheory.Category.assoc, cond', Limits.zero_comp]) := by
  refine' explicitCokernelDesc_unique _ _ _
  

Proof state:
X Y Z W : SemiNormedGroupCat
f : X ⟶ Y
g : Y ⟶ Z
h : Z ⟶ W
cond' : f ≫ g = 0
⊢ explicitCokernelπ f ≫ explicitCokernelDesc cond' ≫ h = g ≫ h

Next tactic:
rw [← CategoryTheory.Category.assoc, explicitCokernelπ_desc]
@[ext]
theorem explicitCokernel_hom_ext {X Y Z : SemiNormedGroupCat.{u}} {f : X ⟶ Y}
    (e₁ e₂ : explicitCokernel f ⟶ Z) (h : explicitCokernelπ f ≫ e₁ = explicitCokernelπ f ≫ e₂) :
    e₁ = e₂ := by
  

Proof state:
X Y Z : SemiNormedGroupCat
f : X ⟶ Y
e₁ e₂ : explicitCokernel f ⟶ Z
h : explicitCokernelπ f ≫ e₁ = explicitCokernelπ f ≫ e₂
⊢ e₁ = e₂

Next tactic:
let g : Y ⟶ Z := explicitCokernelπ f ≫ e₂
@[ext]
theorem explicitCokernel_hom_ext {X Y Z : SemiNormedGroupCat.{u}} {f : X ⟶ Y}
    (e₁ e₂ : explicitCokernel f ⟶ Z) (h : explicitCokernelπ f ≫ e₁ = explicitCokernelπ f ≫ e₂) :
    e₁ = e₂ := by
  let g : Y ⟶ Z := explicitCokernelπ f ≫ e₂
  

Proof state:
X Y Z : SemiNormedGroupCat
f : X ⟶ Y
e₁ e₂ : explicitCokernel f ⟶ Z
h : explicitCokernelπ f ≫ e₁ = explicitCokernelπ f ≫ e₂
g : Y ⟶ Z := explicitCokernelπ f ≫ e₂
⊢ e₁ = e₂

Next tactic:
have w : f ≫ g = 0 := by simp
@[ext]
theorem explicitCokernel_hom_ext {X Y Z : SemiNormedGroupCat.{u}} {f : X ⟶ Y}
    (e₁ e₂ : explicitCokernel f ⟶ Z) (h : explicitCokernelπ f ≫ e₁ = explicitCokernelπ f ≫ e₂) :
    e₁ = e₂ := by
  let g : Y ⟶ Z := explicitCokernelπ f ≫ e₂
  have w : f ≫ g = 0 := by 

Proof state:
X Y Z : SemiNormedGroupCat
f : X ⟶ Y
e₁ e₂ : explicitCokernel f ⟶ Z
h : explicitCokernelπ f ≫ e₁ = explicitCokernelπ f ≫ e₂
g : Y ⟶ Z := explicitCokernelπ f ≫ e₂
⊢ f ≫ g = 0

Next tactic:
simp
@[ext]
theorem explicitCokernel_hom_ext {X Y Z : SemiNormedGroupCat.{u}} {f : X ⟶ Y}
    (e₁ e₂ : explicitCokernel f ⟶ Z) (h : explicitCokernelπ f ≫ e₁ = explicitCokernelπ f ≫ e₂) :
    e₁ = e₂ := by
  let g : Y ⟶ Z := explicitCokernelπ f ≫ e₂
  have w : f ≫ g = 0 := by simp
  

Proof state:
X Y Z : SemiNormedGroupCat
f : X ⟶ Y
e₁ e₂ : explicitCokernel f ⟶ Z
h : explicitCokernelπ f ≫ e₁ = explicitCokernelπ f ≫ e₂
g : Y ⟶ Z := explicitCokernelπ f ≫ e₂
w : f ≫ g = 0
⊢ e₁ = e₂

Next tactic:
have : e₂ = explicitCokernelDesc w := by apply explicitCokernelDesc_unique; rfl
@[ext]
theorem explicitCokernel_hom_ext {X Y Z : SemiNormedGroupCat.{u}} {f : X ⟶ Y}
    (e₁ e₂ : explicitCokernel f ⟶ Z) (h : explicitCokernelπ f ≫ e₁ = explicitCokernelπ f ≫ e₂) :
    e₁ = e₂ := by
  let g : Y ⟶ Z := explicitCokernelπ f ≫ e₂
  have w : f ≫ g = 0 := by simp
  have : e₂ = explicitCokernelDesc w := by 

Proof state:
X Y Z : SemiNormedGroupCat
f : X ⟶ Y
e₁ e₂ : explicitCokernel f ⟶ Z
h : explicitCokernelπ f ≫ e₁ = explicitCokernelπ f ≫ e₂
g : Y ⟶ Z := explicitCokernelπ f ≫ e₂
w : f ≫ g = 0
⊢ e₂ = explicitCokernelDesc w

Next tactic:
apply explicitCokernelDesc_unique
@[ext]
theorem explicitCokernel_hom_ext {X Y Z : SemiNormedGroupCat.{u}} {f : X ⟶ Y}
    (e₁ e₂ : explicitCokernel f ⟶ Z) (h : explicitCokernelπ f ≫ e₁ = explicitCokernelπ f ≫ e₂) :
    e₁ = e₂ := by
  let g : Y ⟶ Z := explicitCokernelπ f ≫ e₂
  have w : f ≫ g = 0 := by simp
  have : e₂ = explicitCokernelDesc w := by apply explicitCokernelDesc_unique; 

Proof state:
case he
X Y Z : SemiNormedGroupCat
f : X ⟶ Y
e₁ e₂ : explicitCokernel f ⟶ Z
h : explicitCokernelπ f ≫ e₁ = explicitCokernelπ f ≫ e₂
g : Y ⟶ Z := explicitCokernelπ f ≫ e₂
w : f ≫ g = 0
⊢ explicitCokernelπ f ≫ e₂ = g

Next tactic:
rfl
@[ext]
theorem explicitCokernel_hom_ext {X Y Z : SemiNormedGroupCat.{u}} {f : X ⟶ Y}
    (e₁ e₂ : explicitCokernel f ⟶ Z) (h : explicitCokernelπ f ≫ e₁ = explicitCokernelπ f ≫ e₂) :
    e₁ = e₂ := by
  let g : Y ⟶ Z := explicitCokernelπ f ≫ e₂
  have w : f ≫ g = 0 := by simp
  have : e₂ = explicitCokernelDesc w := by apply explicitCokernelDesc_unique; rfl
  

Proof state:
X Y Z : SemiNormedGroupCat
f : X ⟶ Y
e₁ e₂ : explicitCokernel f ⟶ Z
h : explicitCokernelπ f ≫ e₁ = explicitCokernelπ f ≫ e₂
g : Y ⟶ Z := explicitCokernelπ f ≫ e₂
w : f ≫ g = 0
this : e₂ = explicitCokernelDesc w
⊢ e₁ = e₂

Next tactic:
rw [this]
@[ext]
theorem explicitCokernel_hom_ext {X Y Z : SemiNormedGroupCat.{u}} {f : X ⟶ Y}
    (e₁ e₂ : explicitCokernel f ⟶ Z) (h : explicitCokernelπ f ≫ e₁ = explicitCokernelπ f ≫ e₂) :
    e₁ = e₂ := by
  let g : Y ⟶ Z := explicitCokernelπ f ≫ e₂
  have w : f ≫ g = 0 := by simp
  have : e₂ = explicitCokernelDesc w := by apply explicitCokernelDesc_unique; rfl
  rw [this]
  

Proof state:
X Y Z : SemiNormedGroupCat
f : X ⟶ Y
e₁ e₂ : explicitCokernel f ⟶ Z
h : explicitCokernelπ f ≫ e₁ = explicitCokernelπ f ≫ e₂
g : Y ⟶ Z := explicitCokernelπ f ≫ e₂
w : f ≫ g = 0
this : e₂ = explicitCokernelDesc w
⊢ e₁ = explicitCokernelDesc w

Next tactic:
apply explicitCokernelDesc_unique
@[ext]
theorem explicitCokernel_hom_ext {X Y Z : SemiNormedGroupCat.{u}} {f : X ⟶ Y}
    (e₁ e₂ : explicitCokernel f ⟶ Z) (h : explicitCokernelπ f ≫ e₁ = explicitCokernelπ f ≫ e₂) :
    e₁ = e₂ := by
  let g : Y ⟶ Z := explicitCokernelπ f ≫ e₂
  have w : f ≫ g = 0 := by simp
  have : e₂ = explicitCokernelDesc w := by apply explicitCokernelDesc_unique; rfl
  rw [this]
  apply explicitCokernelDesc_unique
  

Proof state:
case he
X Y Z : SemiNormedGroupCat
f : X ⟶ Y
e₁ e₂ : explicitCokernel f ⟶ Z
h : explicitCokernelπ f ≫ e₁ = explicitCokernelπ f ≫ e₂
g : Y ⟶ Z := explicitCokernelπ f ≫ e₂
w : f ≫ g = 0
this : e₂ = explicitCokernelDesc w
⊢ explicitCokernelπ f ≫ e₁ = g

Next tactic:
exact h
instance explicitCokernelπ.epi {X Y : SemiNormedGroupCat.{u}} {f : X ⟶ Y} :
    Epi (explicitCokernelπ f) := by
  

Proof state:
X Y : SemiNormedGroupCat
f : X ⟶ Y
⊢ Epi (explicitCokernelπ f)

Next tactic:
constructor
instance explicitCokernelπ.epi {X Y : SemiNormedGroupCat.{u}} {f : X ⟶ Y} :
    Epi (explicitCokernelπ f) := by
  constructor
  

Proof state:
case left_cancellation
X Y : SemiNormedGroupCat
f : X ⟶ Y
⊢ ∀ {Z : SemiNormedGroupCat} (g h : explicitCokernel f ⟶ Z), explicitCokernelπ f ≫ g = explicitCokernelπ f ≫ h → g = h

Next tactic:
intro Z g h H
instance explicitCokernelπ.epi {X Y : SemiNormedGroupCat.{u}} {f : X ⟶ Y} :
    Epi (explicitCokernelπ f) := by
  constructor
  intro Z g h H
  

Proof state:
case left_cancellation
X Y : SemiNormedGroupCat
f : X ⟶ Y
Z : SemiNormedGroupCat
g h : explicitCokernel f ⟶ Z
H : explicitCokernelπ f ≫ g = explicitCokernelπ f ≫ h
⊢ g = h

Next tactic:
ext x
instance explicitCokernelπ.epi {X Y : SemiNormedGroupCat.{u}} {f : X ⟶ Y} :
    Epi (explicitCokernelπ f) := by
  constructor
  intro Z g h H
  ext x
  -- Porting note: no longer needed
  -- obtain ⟨x, hx⟩ := explicitCokernelπ_surjective (explicitCokernelπ f x)
  -- change (explicitCokernelπ f ≫ g) _ = _
  

Proof state:
case left_cancellation.h.h
X Y : SemiNormedGroupCat
f : X ⟶ Y
Z : SemiNormedGroupCat
g h : explicitCokernel f ⟶ Z
H : explicitCokernelπ f ≫ g = explicitCokernelπ f ≫ h
x : ↑Y
⊢ (explicitCokernelπ f ≫ g) x = (explicitCokernelπ f ≫ h) x

Next tactic:
rw [H]
theorem explicitCokernelDesc_normNoninc {X Y Z : SemiNormedGroupCat.{u}} {f : X ⟶ Y} {g : Y ⟶ Z}
    {cond : f ≫ g = 0} (hg : g.NormNoninc) : (explicitCokernelDesc cond).NormNoninc := by
  

Proof state:
X Y Z : SemiNormedGroupCat
f : X ⟶ Y
g : Y ⟶ Z
cond : f ≫ g = 0
hg : NormedAddGroupHom.NormNoninc g
⊢ NormedAddGroupHom.NormNoninc (explicitCokernelDesc cond)

Next tactic:
refine' NormedAddGroupHom.NormNoninc.normNoninc_iff_norm_le_one.2 _
theorem explicitCokernelDesc_normNoninc {X Y Z : SemiNormedGroupCat.{u}} {f : X ⟶ Y} {g : Y ⟶ Z}
    {cond : f ≫ g = 0} (hg : g.NormNoninc) : (explicitCokernelDesc cond).NormNoninc := by
  refine' NormedAddGroupHom.NormNoninc.normNoninc_iff_norm_le_one.2 _
  

Proof state:
X Y Z : SemiNormedGroupCat
f : X ⟶ Y
g : Y ⟶ Z
cond : f ≫ g = 0
hg : NormedAddGroupHom.NormNoninc g
⊢ ‖explicitCokernelDesc cond‖ ≤ 1

Next tactic:
rw [← NNReal.coe_one]
theorem explicitCokernelDesc_normNoninc {X Y Z : SemiNormedGroupCat.{u}} {f : X ⟶ Y} {g : Y ⟶ Z}
    {cond : f ≫ g = 0} (hg : g.NormNoninc) : (explicitCokernelDesc cond).NormNoninc := by
  refine' NormedAddGroupHom.NormNoninc.normNoninc_iff_norm_le_one.2 _
  rw [← NNReal.coe_one]
  

Proof state:
X Y Z : SemiNormedGroupCat
f : X ⟶ Y
g : Y ⟶ Z
cond : f ≫ g = 0
hg : NormedAddGroupHom.NormNoninc g
⊢ ‖explicitCokernelDesc cond‖ ≤ ↑1

Next tactic:
exact
    explicitCokernelDesc_norm_le_of_norm_le cond 1
      (NormedAddGroupHom.NormNoninc.normNoninc_iff_norm_le_one.1 hg)
theorem explicitCokernelDesc_comp_eq_zero {X Y Z W : SemiNormedGroupCat.{u}} {f : X ⟶ Y} {g : Y ⟶ Z}
    {h : Z ⟶ W} (cond : f ≫ g = 0) (cond2 : g ≫ h = 0) : explicitCokernelDesc cond ≫ h = 0 := by
  

Proof state:
X Y Z W : SemiNormedGroupCat
f : X ⟶ Y
g : Y ⟶ Z
h : Z ⟶ W
cond : f ≫ g = 0
cond2 : g ≫ h = 0
⊢ explicitCokernelDesc cond ≫ h = 0

Next tactic:
rw [← cancel_epi (explicitCokernelπ f), ← Category.assoc, explicitCokernelπ_desc]
theorem explicitCokernelDesc_comp_eq_zero {X Y Z W : SemiNormedGroupCat.{u}} {f : X ⟶ Y} {g : Y ⟶ Z}
    {h : Z ⟶ W} (cond : f ≫ g = 0) (cond2 : g ≫ h = 0) : explicitCokernelDesc cond ≫ h = 0 := by
  rw [← cancel_epi (explicitCokernelπ f), ← Category.assoc, explicitCokernelπ_desc]
  

Proof state:
X Y Z W : SemiNormedGroupCat
f : X ⟶ Y
g : Y ⟶ Z
h : Z ⟶ W
cond : f ≫ g = 0
cond2 : g ≫ h = 0
⊢ g ≫ h = explicitCokernelπ f ≫ 0

Next tactic:
simp [cond2]
@[simp]
theorem explicitCokernelIso_hom_π {X Y : SemiNormedGroupCat.{u}} (f : X ⟶ Y) :
    explicitCokernelπ f ≫ (explicitCokernelIso f).hom = cokernel.π _ := by
  

Proof state:
X Y : SemiNormedGroupCat
f : X ⟶ Y
⊢ explicitCokernelπ f ≫ (explicitCokernelIso f).hom = cokernel.π f

Next tactic:
simp [explicitCokernelπ, explicitCokernelIso, IsColimit.coconePointUniqueUpToIso]
@[simp]
theorem explicitCokernelIso_inv_π {X Y : SemiNormedGroupCat.{u}} (f : X ⟶ Y) :
    cokernel.π f ≫ (explicitCokernelIso f).inv = explicitCokernelπ f := by
  

Proof state:
X Y : SemiNormedGroupCat
f : X ⟶ Y
⊢ cokernel.π f ≫ (explicitCokernelIso f).inv = explicitCokernelπ f

Next tactic:
simp [explicitCokernelπ, explicitCokernelIso]
@[simp]
theorem explicitCokernelIso_hom_desc {X Y Z : SemiNormedGroupCat.{u}} {f : X ⟶ Y} {g : Y ⟶ Z}
    (w : f ≫ g = 0) :
    (explicitCokernelIso f).hom ≫ cokernel.desc f g w = explicitCokernelDesc w := by
  

Proof state:
X Y Z : SemiNormedGroupCat
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
⊢ (explicitCokernelIso f).hom ≫ cokernel.desc f g w = explicitCokernelDesc w

Next tactic:
ext1
@[simp]
theorem explicitCokernelIso_hom_desc {X Y Z : SemiNormedGroupCat.{u}} {f : X ⟶ Y} {g : Y ⟶ Z}
    (w : f ≫ g = 0) :
    (explicitCokernelIso f).hom ≫ cokernel.desc f g w = explicitCokernelDesc w := by
  ext1
  

Proof state:
case h
X Y Z : SemiNormedGroupCat
f : X ⟶ Y
g : Y ⟶ Z
w : f ≫ g = 0
⊢ explicitCokernelπ f ≫ (explicitCokernelIso f).hom ≫ cokernel.desc f g w = explicitCokernelπ f ≫ explicitCokernelDesc w

Next tactic:
simp [explicitCokernelDesc, explicitCokernelπ, explicitCokernelIso,
    IsColimit.coconePointUniqueUpToIso]
/-- A special case of `CategoryTheory.Limits.cokernel.map` adapted to `explicitCokernel`. -/
noncomputable def explicitCokernel.map {A B C D : SemiNormedGroupCat.{u}}
    {fab : A ⟶ B} {fbd : B ⟶ D} {fac : A ⟶ C} {fcd : C ⟶ D} (h : fab ≫ fbd = fac ≫ fcd) :
    explicitCokernel fab ⟶ explicitCokernel fcd :=
  @explicitCokernelDesc _ _ _ fab (fbd ≫ explicitCokernelπ _) <| by 

Proof state:
A B C D : SemiNormedGroupCat
fab : A ⟶ B
fbd : B ⟶ D
fac : A ⟶ C
fcd : C ⟶ D
h : fab ≫ fbd = fac ≫ fcd
⊢ fab ≫ fbd ≫ explicitCokernelπ fcd = 0

Next tactic:
simp [reassoc_of% h]
/-- A special case of `CategoryTheory.Limits.cokernel.map_desc` adapted to `explicitCokernel`. -/
theorem ExplicitCoker.map_desc {A B C D B' D' : SemiNormedGroupCat.{u}}
    {fab : A ⟶ B} {fbd : B ⟶ D} {fac : A ⟶ C} {fcd : C ⟶ D} {h : fab ≫ fbd = fac ≫ fcd}
    {fbb' : B ⟶ B'} {fdd' : D ⟶ D'} {condb : fab ≫ fbb' = 0} {condd : fcd ≫ fdd' = 0} {g : B' ⟶ D'}
    (h' : fbb' ≫ g = fbd ≫ fdd') :
    explicitCokernelDesc condb ≫ g = explicitCokernel.map h ≫ explicitCokernelDesc condd := by
  

Proof state:
A B C D B' D' : SemiNormedGroupCat
fab : A ⟶ B
fbd : B ⟶ D
fac : A ⟶ C
fcd : C ⟶ D
h : fab ≫ fbd = fac ≫ fcd
fbb' : B ⟶ B'
fdd' : D ⟶ D'
condb : fab ≫ fbb' = 0
condd : fcd ≫ fdd' = 0
g : B' ⟶ D'
h' : fbb' ≫ g = fbd ≫ fdd'
⊢ explicitCokernelDesc condb ≫ g = explicitCokernel.map h ≫ explicitCokernelDesc condd

Next tactic:
delta explicitCokernel.map
/-- A special case of `CategoryTheory.Limits.cokernel.map_desc` adapted to `explicitCokernel`. -/
theorem ExplicitCoker.map_desc {A B C D B' D' : SemiNormedGroupCat.{u}}
    {fab : A ⟶ B} {fbd : B ⟶ D} {fac : A ⟶ C} {fcd : C ⟶ D} {h : fab ≫ fbd = fac ≫ fcd}
    {fbb' : B ⟶ B'} {fdd' : D ⟶ D'} {condb : fab ≫ fbb' = 0} {condd : fcd ≫ fdd' = 0} {g : B' ⟶ D'}
    (h' : fbb' ≫ g = fbd ≫ fdd') :
    explicitCokernelDesc condb ≫ g = explicitCokernel.map h ≫ explicitCokernelDesc condd := by
  delta explicitCokernel.map
  

Proof state:
A B C D B' D' : SemiNormedGroupCat
fab : A ⟶ B
fbd : B ⟶ D
fac : A ⟶ C
fcd : C ⟶ D
h : fab ≫ fbd = fac ≫ fcd
fbb' : B ⟶ B'
fdd' : D ⟶ D'
condb : fab ≫ fbb' = 0
condd : fcd ≫ fdd' = 0
g : B' ⟶ D'
h' : fbb' ≫ g = fbd ≫ fdd'
⊢ explicitCokernelDesc condb ≫ g =
    explicitCokernelDesc (_ : fab ≫ fbd ≫ explicitCokernelπ fcd = 0) ≫ explicitCokernelDesc condd

Next tactic:
simp [← cancel_epi (explicitCokernelπ fab), ← Category.assoc, explicitCokernelπ_desc, h']
theorem exists_mem_multiset_dvd {s : Multiset α} : p ∣ s.prod → ∃ a ∈ s, p ∣ a :=
  Multiset.induction_on s (fun h => (hp.not_dvd_one h).elim) fun a s ih h =>
    have : p ∣ a * s.prod := by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
p : α
hp : Prime p
s✝ : Multiset α
a : α
s : Multiset α
ih : p ∣ Multiset.prod s → ∃ a ∈ s, p ∣ a
h : p ∣ Multiset.prod (a ::ₘ s)
⊢ p ∣ a * Multiset.prod s

Next tactic:
simpa using h
theorem exists_mem_multiset_map_dvd {s : Multiset β} {f : β → α} :
    p ∣ (s.map f).prod → ∃ a ∈ s, p ∣ f a := fun h => by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
p : α
hp : Prime p
s : Multiset β
f : β → α
h : p ∣ Multiset.prod (Multiset.map f s)
⊢ ∃ a ∈ s, p ∣ f a

Next tactic:
simpa only [exists_prop, Multiset.mem_map, exists_exists_and_eq_and] using
    hp.exists_mem_multiset_dvd h