l3lab/ntp-mathlib huggingface dataset:
theorem map_smul (f : F) (c : ZMod n) (x : M) : f (c • x) = c • f x := by
  rw [← ZMod.int_cast_zmod_cast c]
  

Proof state:
n : ℕ
M : Type u_1
M₁ : Type u_2
F : Type u_3
S : Type u_4
inst✝⁶ : AddCommGroup M
inst✝⁵ : AddCommGroup M₁
inst✝⁴ : AddMonoidHomClass F M M₁
inst✝³ : Module (ZMod n) M
inst✝² : Module (ZMod n) M₁
inst✝¹ : SetLike S M
inst✝ : AddSubgroupClass S M
x✝ : M
K : S
f : F
c : ZMod n
x : M
⊢ f (↑↑c • x) = ↑↑c • f x

Next tactic:
exact map_int_cast_smul f _ _ c x
theorem smul_mem (hx : x ∈ K) (c : ZMod n) : c • x ∈ K := by
  

Proof state:
n : ℕ
M : Type u_1
M₁ : Type u_2
F : Type u_3
S : Type u_4
inst✝⁶ : AddCommGroup M
inst✝⁵ : AddCommGroup M₁
inst✝⁴ : AddMonoidHomClass F M M₁
inst✝³ : Module (ZMod n) M
inst✝² : Module (ZMod n) M₁
inst✝¹ : SetLike S M
inst✝ : AddSubgroupClass S M
x : M
K : S
hx : x ∈ K
c : ZMod n
⊢ c • x ∈ K

Next tactic:
rw [← ZMod.int_cast_zmod_cast c, ← zsmul_eq_smul_cast]
theorem smul_mem (hx : x ∈ K) (c : ZMod n) : c • x ∈ K := by
  rw [← ZMod.int_cast_zmod_cast c, ← zsmul_eq_smul_cast]
  

Proof state:
n : ℕ
M : Type u_1
M₁ : Type u_2
F : Type u_3
S : Type u_4
inst✝⁶ : AddCommGroup M
inst✝⁵ : AddCommGroup M₁
inst✝⁴ : AddMonoidHomClass F M M₁
inst✝³ : Module (ZMod n) M
inst✝² : Module (ZMod n) M₁
inst✝¹ : SetLike S M
inst✝ : AddSubgroupClass S M
x : M
K : S
hx : x ∈ K
c : ZMod n
⊢ ↑c • x ∈ K

Next tactic:
exact zsmul_mem hx c
/-- The `Bicone` used in order to obtain the existence of
the biproduct of a functor `J ⥤ Karoubi C` when the category `C` is additive. -/
@[simps]
def bicone [HasFiniteBiproducts C] {J : Type} [Finite J] (F : J → Karoubi C) : Bicone F where
  pt :=
    { X := biproduct fun j => (F j).X
      p := biproduct.map fun j => (F j).p
      idem := by
        

Proof state:
C : Type u_1
inst✝³ : Category.{v, u_1} C
inst✝² : Preadditive C
inst✝¹ : HasFiniteBiproducts C
J : Type
inst✝ : Finite J
F : J → Karoubi C
⊢ ((biproduct.map fun j => (F j).p) ≫ biproduct.map fun j => (F j).p) = biproduct.map fun j => (F j).p

Next tactic:
ext
/-- The `Bicone` used in order to obtain the existence of
the biproduct of a functor `J ⥤ Karoubi C` when the category `C` is additive. -/
@[simps]
def bicone [HasFiniteBiproducts C] {J : Type} [Finite J] (F : J → Karoubi C) : Bicone F where
  pt :=
    { X := biproduct fun j => (F j).X
      p := biproduct.map fun j => (F j).p
      idem := by
        ext
        

Proof state:
case w.w
C : Type u_1
inst✝³ : Category.{v, u_1} C
inst✝² : Preadditive C
inst✝¹ : HasFiniteBiproducts C
J : Type
inst✝ : Finite J
F : J → Karoubi C
j✝¹ j✝ : J
⊢ biproduct.ι (fun j => (F j).X) j✝ ≫
      ((biproduct.map fun j => (F j).p) ≫ biproduct.map fun j => (F j).p) ≫ biproduct.π (fun j => (F j).X) j✝¹ =
    biproduct.ι (fun j => (F j).X) j✝ ≫ (biproduct.map fun j => (F j).p) ≫ biproduct.π (fun j => (F j).X) j✝¹

Next tactic:
simp only [assoc, biproduct.map_π, biproduct.map_π_assoc, idem]
/-- The `Bicone` used in order to obtain the existence of
the biproduct of a functor `J ⥤ Karoubi C` when the category `C` is additive. -/
@[simps]
def bicone [HasFiniteBiproducts C] {J : Type} [Finite J] (F : J → Karoubi C) : Bicone F where
  pt :=
    { X := biproduct fun j => (F j).X
      p := biproduct.map fun j => (F j).p
      idem := by
        ext
        simp only [assoc, biproduct.map_π, biproduct.map_π_assoc, idem] }
  π j :=
    { f := (biproduct.map fun j => (F j).p) ≫ Bicone.π _ j
      comm := by
        

Proof state:
C : Type u_1
inst✝³ : Category.{v, u_1} C
inst✝² : Preadditive C
inst✝¹ : HasFiniteBiproducts C
J : Type
inst✝ : Finite J
F : J → Karoubi C
j : J
⊢ (biproduct.map fun j => (F j).p) ≫ Bicone.π (biproduct.bicone fun j => (F j).X) j =
    (mk (⨁ fun j => (F j).X) (biproduct.map fun j => (F j).p)).p ≫
      ((biproduct.map fun j => (F j).p) ≫ Bicone.π (biproduct.bicone fun j => (F j).X) j) ≫ (F j).p

Next tactic:
simp only [assoc, biproduct.bicone_π, biproduct.map_π, biproduct.map_π_assoc, (F j).idem]
/-- The `Bicone` used in order to obtain the existence of
the biproduct of a functor `J ⥤ Karoubi C` when the category `C` is additive. -/
@[simps]
def bicone [HasFiniteBiproducts C] {J : Type} [Finite J] (F : J → Karoubi C) : Bicone F where
  pt :=
    { X := biproduct fun j => (F j).X
      p := biproduct.map fun j => (F j).p
      idem := by
        ext
        simp only [assoc, biproduct.map_π, biproduct.map_π_assoc, idem] }
  π j :=
    { f := (biproduct.map fun j => (F j).p) ≫ Bicone.π _ j
      comm := by
        simp only [assoc, biproduct.bicone_π, biproduct.map_π, biproduct.map_π_assoc, (F j).idem] }
  ι j :=
    { f := biproduct.ι (fun j => (F j).X) j ≫ biproduct.map fun j => (F j).p
      comm := by 

Proof state:
C : Type u_1
inst✝³ : Category.{v, u_1} C
inst✝² : Preadditive C
inst✝¹ : HasFiniteBiproducts C
J : Type
inst✝ : Finite J
F : J → Karoubi C
j : J
⊢ (biproduct.ι (fun j => (F j).X) j ≫ biproduct.map fun j => (F j).p) =
    (F j).p ≫
      (biproduct.ι (fun j => (F j).X) j ≫ biproduct.map fun j => (F j).p) ≫
        (mk (⨁ fun j => (F j).X) (biproduct.map fun j => (F j).p)).p

Next tactic:
simp only [biproduct.ι_map, assoc, idem_assoc]
/-- The `Bicone` used in order to obtain the existence of
the biproduct of a functor `J ⥤ Karoubi C` when the category `C` is additive. -/
@[simps]
def bicone [HasFiniteBiproducts C] {J : Type} [Finite J] (F : J → Karoubi C) : Bicone F where
  pt :=
    { X := biproduct fun j => (F j).X
      p := biproduct.map fun j => (F j).p
      idem := by
        ext
        simp only [assoc, biproduct.map_π, biproduct.map_π_assoc, idem] }
  π j :=
    { f := (biproduct.map fun j => (F j).p) ≫ Bicone.π _ j
      comm := by
        simp only [assoc, biproduct.bicone_π, biproduct.map_π, biproduct.map_π_assoc, (F j).idem] }
  ι j :=
    { f := biproduct.ι (fun j => (F j).X) j ≫ biproduct.map fun j => (F j).p
      comm := by simp only [biproduct.ι_map, assoc, idem_assoc] }
  ι_π j j' := by
    

Proof state:
C : Type u_1
inst✝³ : Category.{v, u_1} C
inst✝² : Preadditive C
inst✝¹ : HasFiniteBiproducts C
J : Type
inst✝ : Finite J
F : J → Karoubi C
j j' : J
⊢ (fun j => Hom.mk (biproduct.ι (fun j => (F j).X) j ≫ biproduct.map fun j => (F j).p)) j ≫
      (fun j => Hom.mk ((biproduct.map fun j => (F j).p) ≫ Bicone.π (biproduct.bicone fun j => (F j).X) j)) j' =
    if h : j = j' then eqToHom (_ : F j = F j') else 0

Next tactic:
split_ifs with h
/-- The `Bicone` used in order to obtain the existence of
the biproduct of a functor `J ⥤ Karoubi C` when the category `C` is additive. -/
@[simps]
def bicone [HasFiniteBiproducts C] {J : Type} [Finite J] (F : J → Karoubi C) : Bicone F where
  pt :=
    { X := biproduct fun j => (F j).X
      p := biproduct.map fun j => (F j).p
      idem := by
        ext
        simp only [assoc, biproduct.map_π, biproduct.map_π_assoc, idem] }
  π j :=
    { f := (biproduct.map fun j => (F j).p) ≫ Bicone.π _ j
      comm := by
        simp only [assoc, biproduct.bicone_π, biproduct.map_π, biproduct.map_π_assoc, (F j).idem] }
  ι j :=
    { f := biproduct.ι (fun j => (F j).X) j ≫ biproduct.map fun j => (F j).p
      comm := by simp only [biproduct.ι_map, assoc, idem_assoc] }
  ι_π j j' := by
    split_ifs with h
    · 

Proof state:
case pos
C : Type u_1
inst✝³ : Category.{v, u_1} C
inst✝² : Preadditive C
inst✝¹ : HasFiniteBiproducts C
J : Type
inst✝ : Finite J
F : J → Karoubi C
j j' : J
h : j = j'
⊢ (fun j => Hom.mk (biproduct.ι (fun j => (F j).X) j ≫ biproduct.map fun j => (F j).p)) j ≫
      (fun j => Hom.mk ((biproduct.map fun j => (F j).p) ≫ Bicone.π (biproduct.bicone fun j => (F j).X) j)) j' =
    eqToHom (_ : F j = F j')

Next tactic:
subst h
/-- The `Bicone` used in order to obtain the existence of
the biproduct of a functor `J ⥤ Karoubi C` when the category `C` is additive. -/
@[simps]
def bicone [HasFiniteBiproducts C] {J : Type} [Finite J] (F : J → Karoubi C) : Bicone F where
  pt :=
    { X := biproduct fun j => (F j).X
      p := biproduct.map fun j => (F j).p
      idem := by
        ext
        simp only [assoc, biproduct.map_π, biproduct.map_π_assoc, idem] }
  π j :=
    { f := (biproduct.map fun j => (F j).p) ≫ Bicone.π _ j
      comm := by
        simp only [assoc, biproduct.bicone_π, biproduct.map_π, biproduct.map_π_assoc, (F j).idem] }
  ι j :=
    { f := biproduct.ι (fun j => (F j).X) j ≫ biproduct.map fun j => (F j).p
      comm := by simp only [biproduct.ι_map, assoc, idem_assoc] }
  ι_π j j' := by
    split_ifs with h
    · subst h
      

Proof state:
case pos
C : Type u_1
inst✝³ : Category.{v, u_1} C
inst✝² : Preadditive C
inst✝¹ : HasFiniteBiproducts C
J : Type
inst✝ : Finite J
F : J → Karoubi C
j : J
⊢ (fun j => Hom.mk (biproduct.ι (fun j => (F j).X) j ≫ biproduct.map fun j => (F j).p)) j ≫
      (fun j => Hom.mk ((biproduct.map fun j => (F j).p) ≫ Bicone.π (biproduct.bicone fun j => (F j).X) j)) j =
    eqToHom (_ : F j = F j)

Next tactic:
simp only [biproduct.ι_map, biproduct.bicone_π, biproduct.map_π, eqToHom_refl,
        id_eq, hom_ext_iff, comp_f, assoc, bicone_ι_π_self_assoc, idem]
/-- The `Bicone` used in order to obtain the existence of
the biproduct of a functor `J ⥤ Karoubi C` when the category `C` is additive. -/
@[simps]
def bicone [HasFiniteBiproducts C] {J : Type} [Finite J] (F : J → Karoubi C) : Bicone F where
  pt :=
    { X := biproduct fun j => (F j).X
      p := biproduct.map fun j => (F j).p
      idem := by
        ext
        simp only [assoc, biproduct.map_π, biproduct.map_π_assoc, idem] }
  π j :=
    { f := (biproduct.map fun j => (F j).p) ≫ Bicone.π _ j
      comm := by
        simp only [assoc, biproduct.bicone_π, biproduct.map_π, biproduct.map_π_assoc, (F j).idem] }
  ι j :=
    { f := biproduct.ι (fun j => (F j).X) j ≫ biproduct.map fun j => (F j).p
      comm := by simp only [biproduct.ι_map, assoc, idem_assoc] }
  ι_π j j' := by
    split_ifs with h
    · subst h
      simp only [biproduct.ι_map, biproduct.bicone_π, biproduct.map_π, eqToHom_refl,
        id_eq, hom_ext_iff, comp_f, assoc, bicone_ι_π_self_assoc, idem]
    · 

Proof state:
case neg
C : Type u_1
inst✝³ : Category.{v, u_1} C
inst✝² : Preadditive C
inst✝¹ : HasFiniteBiproducts C
J : Type
inst✝ : Finite J
F : J → Karoubi C
j j' : J
h : ¬j = j'
⊢ (fun j => Hom.mk (biproduct.ι (fun j => (F j).X) j ≫ biproduct.map fun j => (F j).p)) j ≫
      (fun j => Hom.mk ((biproduct.map fun j => (F j).p) ≫ Bicone.π (biproduct.bicone fun j => (F j).X) j)) j' =
    0

Next tactic:
dsimp
/-- The `Bicone` used in order to obtain the existence of
the biproduct of a functor `J ⥤ Karoubi C` when the category `C` is additive. -/
@[simps]
def bicone [HasFiniteBiproducts C] {J : Type} [Finite J] (F : J → Karoubi C) : Bicone F where
  pt :=
    { X := biproduct fun j => (F j).X
      p := biproduct.map fun j => (F j).p
      idem := by
        ext
        simp only [assoc, biproduct.map_π, biproduct.map_π_assoc, idem] }
  π j :=
    { f := (biproduct.map fun j => (F j).p) ≫ Bicone.π _ j
      comm := by
        simp only [assoc, biproduct.bicone_π, biproduct.map_π, biproduct.map_π_assoc, (F j).idem] }
  ι j :=
    { f := biproduct.ι (fun j => (F j).X) j ≫ biproduct.map fun j => (F j).p
      comm := by simp only [biproduct.ι_map, assoc, idem_assoc] }
  ι_π j j' := by
    split_ifs with h
    · subst h
      simp only [biproduct.ι_map, biproduct.bicone_π, biproduct.map_π, eqToHom_refl,
        id_eq, hom_ext_iff, comp_f, assoc, bicone_ι_π_self_assoc, idem]
    · dsimp
      

Proof state:
case neg
C : Type u_1
inst✝³ : Category.{v, u_1} C
inst✝² : Preadditive C
inst✝¹ : HasFiniteBiproducts C
J : Type
inst✝ : Finite J
F : J → Karoubi C
j j' : J
h : ¬j = j'
⊢ Hom.mk (biproduct.ι (fun j => (F j).X) j ≫ biproduct.map fun j => (F j).p) ≫
      Hom.mk ((biproduct.map fun j => (F j).p) ≫ biproduct.π (fun j => (F j).X) j') =
    Hom.mk 0

Next tactic:
simp only [hom_ext_iff, biproduct.ι_map, biproduct.map_π, comp_f, assoc, ne_eq,
        biproduct.ι_π_ne_assoc _ h, comp_zero, zero_comp]
theorem karoubi_hasFiniteBiproducts [HasFiniteBiproducts C] : HasFiniteBiproducts (Karoubi C) :=
  { out := fun n =>
      { has_biproduct := fun F => by
          

Proof state:
C : Type u_1
inst✝² : Category.{v, u_1} C
inst✝¹ : Preadditive C
inst✝ : HasFiniteBiproducts C
n : ℕ
F : Fin n → Karoubi C
⊢ HasBiproduct F

Next tactic:
apply hasBiproduct_of_total (Biproducts.bicone F)
theorem karoubi_hasFiniteBiproducts [HasFiniteBiproducts C] : HasFiniteBiproducts (Karoubi C) :=
  { out := fun n =>
      { has_biproduct := fun F => by
          apply hasBiproduct_of_total (Biproducts.bicone F)
          

Proof state:
C : Type u_1
inst✝² : Category.{v, u_1} C
inst✝¹ : Preadditive C
inst✝ : HasFiniteBiproducts C
n : ℕ
F : Fin n → Karoubi C
⊢ (Finset.sum Finset.univ fun j => Bicone.π (Biproducts.bicone F) j ≫ Bicone.ι (Biproducts.bicone F) j) =
    𝟙 (Biproducts.bicone F).pt

Next tactic:
simp only [hom_ext_iff]
theorem karoubi_hasFiniteBiproducts [HasFiniteBiproducts C] : HasFiniteBiproducts (Karoubi C) :=
  { out := fun n =>
      { has_biproduct := fun F => by
          apply hasBiproduct_of_total (Biproducts.bicone F)
          simp only [hom_ext_iff]
          

Proof state:
C : Type u_1
inst✝² : Category.{v, u_1} C
inst✝¹ : Preadditive C
inst✝ : HasFiniteBiproducts C
n : ℕ
F : Fin n → Karoubi C
⊢ (Finset.sum Finset.univ fun j => Bicone.π (Biproducts.bicone F) j ≫ Bicone.ι (Biproducts.bicone F) j).f =
    (𝟙 (Biproducts.bicone F).pt).f

Next tactic:
refine' biproduct.hom_ext' _ _ (fun j => _)
theorem karoubi_hasFiniteBiproducts [HasFiniteBiproducts C] : HasFiniteBiproducts (Karoubi C) :=
  { out := fun n =>
      { has_biproduct := fun F => by
          apply hasBiproduct_of_total (Biproducts.bicone F)
          simp only [hom_ext_iff]
          refine' biproduct.hom_ext' _ _ (fun j => _)
          

Proof state:
C : Type u_1
inst✝² : Category.{v, u_1} C
inst✝¹ : Preadditive C
inst✝ : HasFiniteBiproducts C
n : ℕ
F : Fin n → Karoubi C
j : Fin n
⊢ biproduct.ι (fun j => (F j).X) j ≫
      (Finset.sum Finset.univ fun j => Bicone.π (Biproducts.bicone F) j ≫ Bicone.ι (Biproducts.bicone F) j).f =
    biproduct.ι (fun j => (F j).X) j ≫ (𝟙 (Biproducts.bicone F).pt).f

Next tactic:
simp only [Biproducts.bicone_pt_X, sum_hom, comp_f, Biproducts.bicone_π_f,
            biproduct.bicone_π, biproduct.map_π, Biproducts.bicone_ι_f, biproduct.ι_map, assoc,
            idem_assoc, id_eq, Biproducts.bicone_pt_p, comp_sum]
theorem karoubi_hasFiniteBiproducts [HasFiniteBiproducts C] : HasFiniteBiproducts (Karoubi C) :=
  { out := fun n =>
      { has_biproduct := fun F => by
          apply hasBiproduct_of_total (Biproducts.bicone F)
          simp only [hom_ext_iff]
          refine' biproduct.hom_ext' _ _ (fun j => _)
          simp only [Biproducts.bicone_pt_X, sum_hom, comp_f, Biproducts.bicone_π_f,
            biproduct.bicone_π, biproduct.map_π, Biproducts.bicone_ι_f, biproduct.ι_map, assoc,
            idem_assoc, id_eq, Biproducts.bicone_pt_p, comp_sum]
          

Proof state:
C : Type u_1
inst✝² : Category.{v, u_1} C
inst✝¹ : Preadditive C
inst✝ : HasFiniteBiproducts C
n : ℕ
F : Fin n → Karoubi C
j : Fin n
⊢ (Finset.sum Finset.univ fun j_1 =>
      biproduct.ι (fun j => (F j).X) j ≫
        biproduct.π (fun b => (F b).X) j_1 ≫ (F j_1).p ≫ biproduct.ι (fun j => (F j).X) j_1) =
    (F j).p ≫ biproduct.ι (fun j => (F j).X) j

Next tactic:
rw [Finset.sum_eq_single j]
theorem karoubi_hasFiniteBiproducts [HasFiniteBiproducts C] : HasFiniteBiproducts (Karoubi C) :=
  { out := fun n =>
      { has_biproduct := fun F => by
          apply hasBiproduct_of_total (Biproducts.bicone F)
          simp only [hom_ext_iff]
          refine' biproduct.hom_ext' _ _ (fun j => _)
          simp only [Biproducts.bicone_pt_X, sum_hom, comp_f, Biproducts.bicone_π_f,
            biproduct.bicone_π, biproduct.map_π, Biproducts.bicone_ι_f, biproduct.ι_map, assoc,
            idem_assoc, id_eq, Biproducts.bicone_pt_p, comp_sum]
          rw [Finset.sum_eq_single j]
          · 

Proof state:
C : Type u_1
inst✝² : Category.{v, u_1} C
inst✝¹ : Preadditive C
inst✝ : HasFiniteBiproducts C
n : ℕ
F : Fin n → Karoubi C
j : Fin n
⊢ biproduct.ι (fun j => (F j).X) j ≫ biproduct.π (fun b => (F b).X) j ≫ (F j).p ≫ biproduct.ι (fun j => (F j).X) j =
    (F j).p ≫ biproduct.ι (fun j => (F j).X) j

Next tactic:
simp only [bicone_ι_π_self_assoc]
theorem karoubi_hasFiniteBiproducts [HasFiniteBiproducts C] : HasFiniteBiproducts (Karoubi C) :=
  { out := fun n =>
      { has_biproduct := fun F => by
          apply hasBiproduct_of_total (Biproducts.bicone F)
          simp only [hom_ext_iff]
          refine' biproduct.hom_ext' _ _ (fun j => _)
          simp only [Biproducts.bicone_pt_X, sum_hom, comp_f, Biproducts.bicone_π_f,
            biproduct.bicone_π, biproduct.map_π, Biproducts.bicone_ι_f, biproduct.ι_map, assoc,
            idem_assoc, id_eq, Biproducts.bicone_pt_p, comp_sum]
          rw [Finset.sum_eq_single j]
          · simp only [bicone_ι_π_self_assoc]
          · 

Proof state:
case h₀
C : Type u_1
inst✝² : Category.{v, u_1} C
inst✝¹ : Preadditive C
inst✝ : HasFiniteBiproducts C
n : ℕ
F : Fin n → Karoubi C
j : Fin n
⊢ ∀ b ∈ Finset.univ,
    b ≠ j →
      biproduct.ι (fun j => (F j).X) j ≫ biproduct.π (fun b => (F b).X) b ≫ (F b).p ≫ biproduct.ι (fun j => (F j).X) b =
        0

Next tactic:
intro b _ hb
theorem karoubi_hasFiniteBiproducts [HasFiniteBiproducts C] : HasFiniteBiproducts (Karoubi C) :=
  { out := fun n =>
      { has_biproduct := fun F => by
          apply hasBiproduct_of_total (Biproducts.bicone F)
          simp only [hom_ext_iff]
          refine' biproduct.hom_ext' _ _ (fun j => _)
          simp only [Biproducts.bicone_pt_X, sum_hom, comp_f, Biproducts.bicone_π_f,
            biproduct.bicone_π, biproduct.map_π, Biproducts.bicone_ι_f, biproduct.ι_map, assoc,
            idem_assoc, id_eq, Biproducts.bicone_pt_p, comp_sum]
          rw [Finset.sum_eq_single j]
          · simp only [bicone_ι_π_self_assoc]
          · intro b _ hb
            

Proof state:
case h₀
C : Type u_1
inst✝² : Category.{v, u_1} C
inst✝¹ : Preadditive C
inst✝ : HasFiniteBiproducts C
n : ℕ
F : Fin n → Karoubi C
j b : Fin n
a✝ : b ∈ Finset.univ
hb : b ≠ j
⊢ biproduct.ι (fun j => (F j).X) j ≫ biproduct.π (fun b => (F b).X) b ≫ (F b).p ≫ biproduct.ι (fun j => (F j).X) b = 0

Next tactic:
simp only [biproduct.ι_π_ne_assoc _ hb.symm, zero_comp]
theorem karoubi_hasFiniteBiproducts [HasFiniteBiproducts C] : HasFiniteBiproducts (Karoubi C) :=
  { out := fun n =>
      { has_biproduct := fun F => by
          apply hasBiproduct_of_total (Biproducts.bicone F)
          simp only [hom_ext_iff]
          refine' biproduct.hom_ext' _ _ (fun j => _)
          simp only [Biproducts.bicone_pt_X, sum_hom, comp_f, Biproducts.bicone_π_f,
            biproduct.bicone_π, biproduct.map_π, Biproducts.bicone_ι_f, biproduct.ι_map, assoc,
            idem_assoc, id_eq, Biproducts.bicone_pt_p, comp_sum]
          rw [Finset.sum_eq_single j]
          · simp only [bicone_ι_π_self_assoc]
          · intro b _ hb
            simp only [biproduct.ι_π_ne_assoc _ hb.symm, zero_comp]
          · 

Proof state:
case h₁
C : Type u_1
inst✝² : Category.{v, u_1} C
inst✝¹ : Preadditive C
inst✝ : HasFiniteBiproducts C
n : ℕ
F : Fin n → Karoubi C
j : Fin n
⊢ j ∉ Finset.univ →
    biproduct.ι (fun j => (F j).X) j ≫ biproduct.π (fun b => (F b).X) j ≫ (F j).p ≫ biproduct.ι (fun j => (F j).X) j = 0

Next tactic:
intro hj
theorem karoubi_hasFiniteBiproducts [HasFiniteBiproducts C] : HasFiniteBiproducts (Karoubi C) :=
  { out := fun n =>
      { has_biproduct := fun F => by
          apply hasBiproduct_of_total (Biproducts.bicone F)
          simp only [hom_ext_iff]
          refine' biproduct.hom_ext' _ _ (fun j => _)
          simp only [Biproducts.bicone_pt_X, sum_hom, comp_f, Biproducts.bicone_π_f,
            biproduct.bicone_π, biproduct.map_π, Biproducts.bicone_ι_f, biproduct.ι_map, assoc,
            idem_assoc, id_eq, Biproducts.bicone_pt_p, comp_sum]
          rw [Finset.sum_eq_single j]
          · simp only [bicone_ι_π_self_assoc]
          · intro b _ hb
            simp only [biproduct.ι_π_ne_assoc _ hb.symm, zero_comp]
          · intro hj
            

Proof state:
case h₁
C : Type u_1
inst✝² : Category.{v, u_1} C
inst✝¹ : Preadditive C
inst✝ : HasFiniteBiproducts C
n : ℕ
F : Fin n → Karoubi C
j : Fin n
hj : j ∉ Finset.univ
⊢ biproduct.ι (fun j => (F j).X) j ≫ biproduct.π (fun b => (F b).X) j ≫ (F j).p ≫ biproduct.ι (fun j => (F j).X) j = 0

Next tactic:
simp only [Finset.mem_univ, not_true] at hj
instance (P : Karoubi C) : HasBinaryBiproduct P P.complement :=
  hasBinaryBiproduct_of_total
    { pt := P.X
      fst := P.decompId_p
      snd := P.complement.decompId_p
      inl := P.decompId_i
      inr := P.complement.decompId_i
      inl_fst := P.decompId.symm
      inl_snd := by
        

Proof state:
C : Type u_1
inst✝¹ : Category.{v, u_1} C
inst✝ : Preadditive C
P : Karoubi C
⊢ decompId_i P ≫ decompId_p (complement P) = 0

Next tactic:
simp only [instAddCommGroupHom_zero, hom_ext_iff, complement_X, comp_f,
          decompId_i_f, decompId_p_f, complement_p, comp_sub, comp_id, idem, sub_self]
instance (P : Karoubi C) : HasBinaryBiproduct P P.complement :=
  hasBinaryBiproduct_of_total
    { pt := P.X
      fst := P.decompId_p
      snd := P.complement.decompId_p
      inl := P.decompId_i
      inr := P.complement.decompId_i
      inl_fst := P.decompId.symm
      inl_snd := by
        simp only [instAddCommGroupHom_zero, hom_ext_iff, complement_X, comp_f,
          decompId_i_f, decompId_p_f, complement_p, comp_sub, comp_id, idem, sub_self]
      inr_fst := by
        

Proof state:
C : Type u_1
inst✝¹ : Category.{v, u_1} C
inst✝ : Preadditive C
P : Karoubi C
⊢ decompId_i (complement P) ≫ decompId_p P = 0

Next tactic:
simp only [instAddCommGroupHom_zero, hom_ext_iff, complement_X, comp_f,
          decompId_i_f, complement_p, decompId_p_f, sub_comp, id_comp, idem, sub_self]
instance (P : Karoubi C) : HasBinaryBiproduct P P.complement :=
  hasBinaryBiproduct_of_total
    { pt := P.X
      fst := P.decompId_p
      snd := P.complement.decompId_p
      inl := P.decompId_i
      inr := P.complement.decompId_i
      inl_fst := P.decompId.symm
      inl_snd := by
        simp only [instAddCommGroupHom_zero, hom_ext_iff, complement_X, comp_f,
          decompId_i_f, decompId_p_f, complement_p, comp_sub, comp_id, idem, sub_self]
      inr_fst := by
        simp only [instAddCommGroupHom_zero, hom_ext_iff, complement_X, comp_f,
          decompId_i_f, complement_p, decompId_p_f, sub_comp, id_comp, idem, sub_self]
      inr_snd := P.complement.decompId.symm }
    (by
      

Proof state:
C : Type u_1
inst✝¹ : Category.{v, u_1} C
inst✝ : Preadditive C
P : Karoubi C
⊢ (BinaryBicone.mk (mk P.X (𝟙 P.X)) (decompId_p P) (decompId_p (complement P)) (decompId_i P)
            (decompId_i (complement P))).fst ≫
        (BinaryBicone.mk (mk P.X (𝟙 P.X)) (decompId_p P) (decompId_p (complement P)) (decompId_i P)
            (decompId_i (complement P))).inl +
      (BinaryBicone.mk (mk P.X (𝟙 P.X)) (decompId_p P) (decompId_p (complement P)) (decompId_i P)
            (decompId_i (complement P))).snd ≫
        (BinaryBicone.mk (mk P.X (𝟙 P.X)) (decompId_p P) (decompId_p (complement P)) (decompId_i P)
            (decompId_i (complement P))).inr =
    𝟙
      (BinaryBicone.mk (mk P.X (𝟙 P.X)) (decompId_p P) (decompId_p (complement P)) (decompId_i P)
          (decompId_i (complement P))).pt

Next tactic:
simp only [id_eq, complement_X, comp_f,
        decompId_i_f, decompId_p_f, complement_p, instAddCommGroupHom_add, idem,
        comp_sub, comp_id, sub_comp, id_comp, sub_self, sub_zero, add_sub_cancel'_right]
/-- A formal direct factor `P : Karoubi C` of an object `P.X : C` in a
preadditive category is actually a direct factor of the image `(toKaroubi C).obj P.X`
of `P.X` in the category `Karoubi C` -/
def decomposition (P : Karoubi C) : P ⊞ P.complement ≅ (toKaroubi _).obj P.X where
  hom := biprod.desc P.decompId_i P.complement.decompId_i
  inv := biprod.lift P.decompId_p P.complement.decompId_p
  hom_inv_id := by
    

Proof state:
C : Type u_1
inst✝¹ : Category.{v, u_1} C
inst✝ : Preadditive C
P : Karoubi C
⊢ biprod.desc (decompId_i P) (decompId_i (complement P)) ≫ biprod.lift (decompId_p P) (decompId_p (complement P)) =
    𝟙 (P ⊞ complement P)

Next tactic:
apply biprod.hom_ext'