l3lab/ntp-mathlib huggingface dataset:
/-- We can turn any limit cone over a pair into a bilimit bicone. -/
def biconeIsBilimitOfColimitCoconeOfIsColimit {f : J → C} {t : Cocone (Discrete.functor f)}
    (ht : IsColimit t) : (Bicone.ofColimitCocone ht).IsBilimit :=
  isBilimitOfIsColimit _ <| IsColimit.ofIsoColimit ht <| Cocones.ext (Iso.refl _) <| by
    

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Preadditive C
J : Type
inst✝ : Fintype J
f : J → C
t : Cocone (Discrete.functor f)
ht : IsColimit t
⊢ ∀ (j : Discrete J), t.ι.app j ≫ (Iso.refl t.pt).hom = (Bicone.toCocone (Bicone.ofColimitCocone ht)).ι.app j

Next tactic:
rintro ⟨j⟩
/-- We can turn any limit cone over a pair into a bilimit bicone. -/
def biconeIsBilimitOfColimitCoconeOfIsColimit {f : J → C} {t : Cocone (Discrete.functor f)}
    (ht : IsColimit t) : (Bicone.ofColimitCocone ht).IsBilimit :=
  isBilimitOfIsColimit _ <| IsColimit.ofIsoColimit ht <| Cocones.ext (Iso.refl _) <| by
    rintro ⟨j⟩; 

Proof state:
case mk
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Preadditive C
J : Type
inst✝ : Fintype J
f : J → C
t : Cocone (Discrete.functor f)
ht : IsColimit t
j : J
⊢ t.ι.app { as := j } ≫ (Iso.refl t.pt).hom = (Bicone.toCocone (Bicone.ofColimitCocone ht)).ι.app { as := j }

Next tactic:
simp
/-- In a preadditive category, if the coproduct over `f : J → C` exists,
    then the biproduct over `f` exists. -/
theorem HasBiproduct.of_hasCoproduct {J : Type} [Finite J] (f : J → C) [HasCoproduct f] :
    HasBiproduct f := by
  

Proof state:
C : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : Preadditive C
J✝ : Type
inst✝² : Fintype J✝
J : Type
inst✝¹ : Finite J
f : J → C
inst✝ : HasCoproduct f
⊢ HasBiproduct f

Next tactic:
cases nonempty_fintype J
/-- In a preadditive category, if the coproduct over `f : J → C` exists,
    then the biproduct over `f` exists. -/
theorem HasBiproduct.of_hasCoproduct {J : Type} [Finite J] (f : J → C) [HasCoproduct f] :
    HasBiproduct f := by
  cases nonempty_fintype J;
    

Proof state:
case intro
C : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : Preadditive C
J✝ : Type
inst✝² : Fintype J✝
J : Type
inst✝¹ : Finite J
f : J → C
inst✝ : HasCoproduct f
val✝ : Fintype J
⊢ HasBiproduct f

Next tactic:
exact
      HasBiproduct.mk
        { bicone := _
          isBilimit := biconeIsBilimitOfColimitCoconeOfIsColimit (colimit.isColimit _) }
theorem biproduct.lift_eq {T : C} {g : ∀ j, T ⟶ f j} :
    biproduct.lift g = ∑ j, g j ≫ biproduct.ι f j := by
  

Proof state:
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : Preadditive C
J : Type
inst✝¹ : Fintype J
f : J → C
inst✝ : HasBiproduct f
T : C
g : (j : J) → T ⟶ f j
⊢ lift g = ∑ j : J, g j ≫ ι f j

Next tactic:
ext j
theorem biproduct.lift_eq {T : C} {g : ∀ j, T ⟶ f j} :
    biproduct.lift g = ∑ j, g j ≫ biproduct.ι f j := by
  ext j
  

Proof state:
case w
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : Preadditive C
J : Type
inst✝¹ : Fintype J
f : J → C
inst✝ : HasBiproduct f
T : C
g : (j : J) → T ⟶ f j
j : J
⊢ lift g ≫ π (fun b => f b) j = (∑ j : J, g j ≫ ι f j) ≫ π (fun b => f b) j

Next tactic:
simp only [sum_comp, biproduct.ι_π, comp_dite, biproduct.lift_π, Category.assoc, comp_zero,
    Finset.sum_dite_eq', Finset.mem_univ, eqToHom_refl, Category.comp_id, if_true]
theorem biproduct.desc_eq {T : C} {g : ∀ j, f j ⟶ T} :
    biproduct.desc g = ∑ j, biproduct.π f j ≫ g j := by
  

Proof state:
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : Preadditive C
J : Type
inst✝¹ : Fintype J
f : J → C
inst✝ : HasBiproduct f
T : C
g : (j : J) → f j ⟶ T
⊢ desc g = ∑ j : J, π f j ≫ g j

Next tactic:
ext j
theorem biproduct.desc_eq {T : C} {g : ∀ j, f j ⟶ T} :
    biproduct.desc g = ∑ j, biproduct.π f j ≫ g j := by
  ext j
  

Proof state:
case w
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : Preadditive C
J : Type
inst✝¹ : Fintype J
f : J → C
inst✝ : HasBiproduct f
T : C
g : (j : J) → f j ⟶ T
j : J
⊢ ι (fun b => f b) j ≫ desc g = ι (fun b => f b) j ≫ ∑ j : J, π f j ≫ g j

Next tactic:
simp [comp_sum, biproduct.ι_π_assoc, dite_comp]
@[reassoc]
theorem biproduct.lift_desc {T U : C} {g : ∀ j, T ⟶ f j} {h : ∀ j, f j ⟶ U} :
    biproduct.lift g ≫ biproduct.desc h = ∑ j : J, g j ≫ h j := by
  

Proof state:
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : Preadditive C
J : Type
inst✝¹ : Fintype J
f : J → C
inst✝ : HasBiproduct f
T U : C
g : (j : J) → T ⟶ f j
h : (j : J) → f j ⟶ U
⊢ lift g ≫ desc h = ∑ j : J, g j ≫ h j

Next tactic:
simp [biproduct.lift_eq, biproduct.desc_eq, comp_sum, sum_comp, biproduct.ι_π_assoc, comp_dite,
    dite_comp]
theorem biproduct.map_eq [HasFiniteBiproducts C] {f g : J → C} {h : ∀ j, f j ⟶ g j} :
    biproduct.map h = ∑ j : J, biproduct.π f j ≫ h j ≫ biproduct.ι g j := by
  

Proof state:
C : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : Preadditive C
J : Type
inst✝² : Fintype J
f✝ : J → C
inst✝¹ : HasBiproduct f✝
inst✝ : HasFiniteBiproducts C
f g : J → C
h : (j : J) → f j ⟶ g j
⊢ map h = ∑ j : J, π f j ≫ h j ≫ ι g j

Next tactic:
ext
theorem biproduct.map_eq [HasFiniteBiproducts C] {f g : J → C} {h : ∀ j, f j ⟶ g j} :
    biproduct.map h = ∑ j : J, biproduct.π f j ≫ h j ≫ biproduct.ι g j := by
  ext
  

Proof state:
case w.w
C : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : Preadditive C
J : Type
inst✝² : Fintype J
f✝ : J → C
inst✝¹ : HasBiproduct f✝
inst✝ : HasFiniteBiproducts C
f g : J → C
h : (j : J) → f j ⟶ g j
j✝¹ j✝ : J
⊢ ι (fun b => f b) j✝ ≫ map h ≫ π (fun b => g b) j✝¹ =
    ι (fun b => f b) j✝ ≫ (∑ j : J, π f j ≫ h j ≫ ι g j) ≫ π (fun b => g b) j✝¹

Next tactic:
simp [biproduct.ι_π, biproduct.ι_π_assoc, comp_sum, sum_comp, comp_dite, dite_comp]
@[reassoc]
theorem biproduct.matrix_desc {K : Type} [Fintype K] [HasFiniteBiproducts C] {f : J → C} {g : K → C}
    (m : ∀ j k, f j ⟶ g k) {P} (x : ∀ k, g k ⟶ P) :
    biproduct.matrix m ≫ biproduct.desc x = biproduct.desc fun j => ∑ k, m j k ≫ x k := by
  

Proof state:
C : Type u
inst✝⁵ : Category.{v, u} C
inst✝⁴ : Preadditive C
J : Type
inst✝³ : Fintype J
f✝ : J → C
inst✝² : HasBiproduct f✝
K : Type
inst✝¹ : Fintype K
inst✝ : HasFiniteBiproducts C
f : J → C
g : K → C
m : (j : J) → (k : K) → f j ⟶ g k
P : C
x : (k : K) → g k ⟶ P
⊢ matrix m ≫ desc x = desc fun j => ∑ k : K, m j k ≫ x k

Next tactic:
ext
@[reassoc]
theorem biproduct.matrix_desc {K : Type} [Fintype K] [HasFiniteBiproducts C] {f : J → C} {g : K → C}
    (m : ∀ j k, f j ⟶ g k) {P} (x : ∀ k, g k ⟶ P) :
    biproduct.matrix m ≫ biproduct.desc x = biproduct.desc fun j => ∑ k, m j k ≫ x k := by
  ext
  

Proof state:
case w
C : Type u
inst✝⁵ : Category.{v, u} C
inst✝⁴ : Preadditive C
J : Type
inst✝³ : Fintype J
f✝ : J → C
inst✝² : HasBiproduct f✝
K : Type
inst✝¹ : Fintype K
inst✝ : HasFiniteBiproducts C
f : J → C
g : K → C
m : (j : J) → (k : K) → f j ⟶ g k
P : C
x : (k : K) → g k ⟶ P
j✝ : J
⊢ ι (fun j => f j) j✝ ≫ matrix m ≫ desc x = ι (fun j => f j) j✝ ≫ desc fun j => ∑ k : K, m j k ≫ x k

Next tactic:
simp [lift_desc]
@[reassoc]
theorem biproduct.lift_matrix {K : Type} [Fintype K] [HasFiniteBiproducts C] {f : J → C} {g : K → C}
    {P} (x : ∀ j, P ⟶ f j) (m : ∀ j k, f j ⟶ g k) :
    biproduct.lift x ≫ biproduct.matrix m = biproduct.lift fun k => ∑ j, x j ≫ m j k := by
  

Proof state:
C : Type u
inst✝⁵ : Category.{v, u} C
inst✝⁴ : Preadditive C
J : Type
inst✝³ : Fintype J
f✝ : J → C
inst✝² : HasBiproduct f✝
K : Type
inst✝¹ : Fintype K
inst✝ : HasFiniteBiproducts C
f : J → C
g : K → C
P : C
x : (j : J) → P ⟶ f j
m : (j : J) → (k : K) → f j ⟶ g k
⊢ lift x ≫ matrix m = lift fun k => ∑ j : J, x j ≫ m j k

Next tactic:
ext
@[reassoc]
theorem biproduct.lift_matrix {K : Type} [Fintype K] [HasFiniteBiproducts C] {f : J → C} {g : K → C}
    {P} (x : ∀ j, P ⟶ f j) (m : ∀ j k, f j ⟶ g k) :
    biproduct.lift x ≫ biproduct.matrix m = biproduct.lift fun k => ∑ j, x j ≫ m j k := by
  ext
  

Proof state:
case w
C : Type u
inst✝⁵ : Category.{v, u} C
inst✝⁴ : Preadditive C
J : Type
inst✝³ : Fintype J
f✝ : J → C
inst✝² : HasBiproduct f✝
K : Type
inst✝¹ : Fintype K
inst✝ : HasFiniteBiproducts C
f : J → C
g : K → C
P : C
x : (j : J) → P ⟶ f j
m : (j : J) → (k : K) → f j ⟶ g k
j✝ : K
⊢ (lift x ≫ matrix m) ≫ π (fun k => g k) j✝ = (lift fun k => ∑ j : J, x j ≫ m j k) ≫ π (fun k => g k) j✝

Next tactic:
simp [biproduct.lift_desc]
@[reassoc]
theorem biproduct.matrix_map {K : Type} [Fintype K] [HasFiniteBiproducts C] {f : J → C} {g : K → C}
    {h : K → C} (m : ∀ j k, f j ⟶ g k) (n : ∀ k, g k ⟶ h k) :
    biproduct.matrix m ≫ biproduct.map n = biproduct.matrix fun j k => m j k ≫ n k := by
  

Proof state:
C : Type u
inst✝⁵ : Category.{v, u} C
inst✝⁴ : Preadditive C
J : Type
inst✝³ : Fintype J
f✝ : J → C
inst✝² : HasBiproduct f✝
K : Type
inst✝¹ : Fintype K
inst✝ : HasFiniteBiproducts C
f : J → C
g h : K → C
m : (j : J) → (k : K) → f j ⟶ g k
n : (k : K) → g k ⟶ h k
⊢ matrix m ≫ map n = matrix fun j k => m j k ≫ n k

Next tactic:
ext
@[reassoc]
theorem biproduct.matrix_map {K : Type} [Fintype K] [HasFiniteBiproducts C] {f : J → C} {g : K → C}
    {h : K → C} (m : ∀ j k, f j ⟶ g k) (n : ∀ k, g k ⟶ h k) :
    biproduct.matrix m ≫ biproduct.map n = biproduct.matrix fun j k => m j k ≫ n k := by
  ext
  

Proof state:
case w.w
C : Type u
inst✝⁵ : Category.{v, u} C
inst✝⁴ : Preadditive C
J : Type
inst✝³ : Fintype J
f✝ : J → C
inst✝² : HasBiproduct f✝
K : Type
inst✝¹ : Fintype K
inst✝ : HasFiniteBiproducts C
f : J → C
g h : K → C
m : (j : J) → (k : K) → f j ⟶ g k
n : (k : K) → g k ⟶ h k
j✝¹ : K
j✝ : J
⊢ ι (fun j => f j) j✝ ≫ (matrix m ≫ map n) ≫ π (fun b => h b) j✝¹ =
    ι (fun j => f j) j✝ ≫ (matrix fun j k => m j k ≫ n k) ≫ π (fun b => h b) j✝¹

Next tactic:
simp
@[reassoc]
theorem biproduct.map_matrix {K : Type} [Fintype K] [HasFiniteBiproducts C] {f : J → C} {g : J → C}
    {h : K → C} (m : ∀ k, f k ⟶ g k) (n : ∀ j k, g j ⟶ h k) :
    biproduct.map m ≫ biproduct.matrix n = biproduct.matrix fun j k => m j ≫ n j k := by
  

Proof state:
C : Type u
inst✝⁵ : Category.{v, u} C
inst✝⁴ : Preadditive C
J : Type
inst✝³ : Fintype J
f✝ : J → C
inst✝² : HasBiproduct f✝
K : Type
inst✝¹ : Fintype K
inst✝ : HasFiniteBiproducts C
f g : J → C
h : K → C
m : (k : J) → f k ⟶ g k
n : (j : J) → (k : K) → g j ⟶ h k
⊢ map m ≫ matrix n = matrix fun j k => m j ≫ n j k

Next tactic:
ext
@[reassoc]
theorem biproduct.map_matrix {K : Type} [Fintype K] [HasFiniteBiproducts C] {f : J → C} {g : J → C}
    {h : K → C} (m : ∀ k, f k ⟶ g k) (n : ∀ j k, g j ⟶ h k) :
    biproduct.map m ≫ biproduct.matrix n = biproduct.matrix fun j k => m j ≫ n j k := by
  ext
  

Proof state:
case w.w
C : Type u
inst✝⁵ : Category.{v, u} C
inst✝⁴ : Preadditive C
J : Type
inst✝³ : Fintype J
f✝ : J → C
inst✝² : HasBiproduct f✝
K : Type
inst✝¹ : Fintype K
inst✝ : HasFiniteBiproducts C
f g : J → C
h : K → C
m : (k : J) → f k ⟶ g k
n : (j : J) → (k : K) → g j ⟶ h k
j✝¹ : K
j✝ : J
⊢ ι (fun b => f b) j✝ ≫ (map m ≫ matrix n) ≫ π (fun k => h k) j✝¹ =
    ι (fun b => f b) j✝ ≫ (matrix fun j k => m j ≫ n j k) ≫ π (fun k => h k) j✝¹

Next tactic:
simp
/-- Reindex a categorical biproduct via an equivalence of the index types. -/
@[simps]
def biproduct.reindex {β γ : Type} [Fintype β] [DecidableEq β] [DecidableEq γ] (ε : β ≃ γ)
    (f : γ → C) [HasBiproduct f] [HasBiproduct (f ∘ ε)] : ⨁ f ∘ ε ≅ ⨁ f
    where
  hom := biproduct.desc fun b => biproduct.ι f (ε b)
  inv := biproduct.lift fun b => biproduct.π f (ε b)
  hom_inv_id := by
    

Proof state:
C : Type u
inst✝⁷ : Category.{v, u} C
inst✝⁶ : Preadditive C
J : Type
inst✝⁵ : Fintype J
β γ : Type
inst✝⁴ : Fintype β
inst✝³ : DecidableEq β
inst✝² : DecidableEq γ
ε : β ≃ γ
f : γ → C
inst✝¹ : HasBiproduct f
inst✝ : HasBiproduct (f ∘ ⇑ε)
⊢ ((desc fun b => ι f (ε b)) ≫ lift fun b => π f (ε b)) = 𝟙 (⨁ f ∘ ⇑ε)

Next tactic:
ext b b'
/-- Reindex a categorical biproduct via an equivalence of the index types. -/
@[simps]
def biproduct.reindex {β γ : Type} [Fintype β] [DecidableEq β] [DecidableEq γ] (ε : β ≃ γ)
    (f : γ → C) [HasBiproduct f] [HasBiproduct (f ∘ ε)] : ⨁ f ∘ ε ≅ ⨁ f
    where
  hom := biproduct.desc fun b => biproduct.ι f (ε b)
  inv := biproduct.lift fun b => biproduct.π f (ε b)
  hom_inv_id := by
    ext b b'
    

Proof state:
case w.w
C : Type u
inst✝⁷ : Category.{v, u} C
inst✝⁶ : Preadditive C
J : Type
inst✝⁵ : Fintype J
β γ : Type
inst✝⁴ : Fintype β
inst✝³ : DecidableEq β
inst✝² : DecidableEq γ
ε : β ≃ γ
f : γ → C
inst✝¹ : HasBiproduct f
inst✝ : HasBiproduct (f ∘ ⇑ε)
b b' : β
⊢ ι (f ∘ ⇑ε) b' ≫ ((desc fun b => ι f (ε b)) ≫ lift fun b => π f (ε b)) ≫ π (f ∘ ⇑ε) b =
    ι (f ∘ ⇑ε) b' ≫ 𝟙 (⨁ f ∘ ⇑ε) ≫ π (f ∘ ⇑ε) b

Next tactic:
by_cases h : b' = b
/-- Reindex a categorical biproduct via an equivalence of the index types. -/
@[simps]
def biproduct.reindex {β γ : Type} [Fintype β] [DecidableEq β] [DecidableEq γ] (ε : β ≃ γ)
    (f : γ → C) [HasBiproduct f] [HasBiproduct (f ∘ ε)] : ⨁ f ∘ ε ≅ ⨁ f
    where
  hom := biproduct.desc fun b => biproduct.ι f (ε b)
  inv := biproduct.lift fun b => biproduct.π f (ε b)
  hom_inv_id := by
    ext b b'
    by_cases h : b' = b
    · 

Proof state:
case pos
C : Type u
inst✝⁷ : Category.{v, u} C
inst✝⁶ : Preadditive C
J : Type
inst✝⁵ : Fintype J
β γ : Type
inst✝⁴ : Fintype β
inst✝³ : DecidableEq β
inst✝² : DecidableEq γ
ε : β ≃ γ
f : γ → C
inst✝¹ : HasBiproduct f
inst✝ : HasBiproduct (f ∘ ⇑ε)
b b' : β
h : b' = b
⊢ ι (f ∘ ⇑ε) b' ≫ ((desc fun b => ι f (ε b)) ≫ lift fun b => π f (ε b)) ≫ π (f ∘ ⇑ε) b =
    ι (f ∘ ⇑ε) b' ≫ 𝟙 (⨁ f ∘ ⇑ε) ≫ π (f ∘ ⇑ε) b

Next tactic:
subst h
/-- Reindex a categorical biproduct via an equivalence of the index types. -/
@[simps]
def biproduct.reindex {β γ : Type} [Fintype β] [DecidableEq β] [DecidableEq γ] (ε : β ≃ γ)
    (f : γ → C) [HasBiproduct f] [HasBiproduct (f ∘ ε)] : ⨁ f ∘ ε ≅ ⨁ f
    where
  hom := biproduct.desc fun b => biproduct.ι f (ε b)
  inv := biproduct.lift fun b => biproduct.π f (ε b)
  hom_inv_id := by
    ext b b'
    by_cases h : b' = b
    · subst h; 

Proof state:
case pos
C : Type u
inst✝⁷ : Category.{v, u} C
inst✝⁶ : Preadditive C
J : Type
inst✝⁵ : Fintype J
β γ : Type
inst✝⁴ : Fintype β
inst✝³ : DecidableEq β
inst✝² : DecidableEq γ
ε : β ≃ γ
f : γ → C
inst✝¹ : HasBiproduct f
inst✝ : HasBiproduct (f ∘ ⇑ε)
b' : β
⊢ ι (f ∘ ⇑ε) b' ≫ ((desc fun b => ι f (ε b)) ≫ lift fun b => π f (ε b)) ≫ π (f ∘ ⇑ε) b' =
    ι (f ∘ ⇑ε) b' ≫ 𝟙 (⨁ f ∘ ⇑ε) ≫ π (f ∘ ⇑ε) b'

Next tactic:
simp
/-- Reindex a categorical biproduct via an equivalence of the index types. -/
@[simps]
def biproduct.reindex {β γ : Type} [Fintype β] [DecidableEq β] [DecidableEq γ] (ε : β ≃ γ)
    (f : γ → C) [HasBiproduct f] [HasBiproduct (f ∘ ε)] : ⨁ f ∘ ε ≅ ⨁ f
    where
  hom := biproduct.desc fun b => biproduct.ι f (ε b)
  inv := biproduct.lift fun b => biproduct.π f (ε b)
  hom_inv_id := by
    ext b b'
    by_cases h : b' = b
    · subst h; simp
    · 

Proof state:
case neg
C : Type u
inst✝⁷ : Category.{v, u} C
inst✝⁶ : Preadditive C
J : Type
inst✝⁵ : Fintype J
β γ : Type
inst✝⁴ : Fintype β
inst✝³ : DecidableEq β
inst✝² : DecidableEq γ
ε : β ≃ γ
f : γ → C
inst✝¹ : HasBiproduct f
inst✝ : HasBiproduct (f ∘ ⇑ε)
b b' : β
h : ¬b' = b
⊢ ι (f ∘ ⇑ε) b' ≫ ((desc fun b => ι f (ε b)) ≫ lift fun b => π f (ε b)) ≫ π (f ∘ ⇑ε) b =
    ι (f ∘ ⇑ε) b' ≫ 𝟙 (⨁ f ∘ ⇑ε) ≫ π (f ∘ ⇑ε) b

Next tactic:
have : ε b' ≠ ε b := by simp [h]
/-- Reindex a categorical biproduct via an equivalence of the index types. -/
@[simps]
def biproduct.reindex {β γ : Type} [Fintype β] [DecidableEq β] [DecidableEq γ] (ε : β ≃ γ)
    (f : γ → C) [HasBiproduct f] [HasBiproduct (f ∘ ε)] : ⨁ f ∘ ε ≅ ⨁ f
    where
  hom := biproduct.desc fun b => biproduct.ι f (ε b)
  inv := biproduct.lift fun b => biproduct.π f (ε b)
  hom_inv_id := by
    ext b b'
    by_cases h : b' = b
    · subst h; simp
    · have : ε b' ≠ ε b := by 

Proof state:
C : Type u
inst✝⁷ : Category.{v, u} C
inst✝⁶ : Preadditive C
J : Type
inst✝⁵ : Fintype J
β γ : Type
inst✝⁴ : Fintype β
inst✝³ : DecidableEq β
inst✝² : DecidableEq γ
ε : β ≃ γ
f : γ → C
inst✝¹ : HasBiproduct f
inst✝ : HasBiproduct (f ∘ ⇑ε)
b b' : β
h : ¬b' = b
⊢ ε b' ≠ ε b

Next tactic:
simp [h]
/-- Reindex a categorical biproduct via an equivalence of the index types. -/
@[simps]
def biproduct.reindex {β γ : Type} [Fintype β] [DecidableEq β] [DecidableEq γ] (ε : β ≃ γ)
    (f : γ → C) [HasBiproduct f] [HasBiproduct (f ∘ ε)] : ⨁ f ∘ ε ≅ ⨁ f
    where
  hom := biproduct.desc fun b => biproduct.ι f (ε b)
  inv := biproduct.lift fun b => biproduct.π f (ε b)
  hom_inv_id := by
    ext b b'
    by_cases h : b' = b
    · subst h; simp
    · have : ε b' ≠ ε b := by simp [h]
      

Proof state:
case neg
C : Type u
inst✝⁷ : Category.{v, u} C
inst✝⁶ : Preadditive C
J : Type
inst✝⁵ : Fintype J
β γ : Type
inst✝⁴ : Fintype β
inst✝³ : DecidableEq β
inst✝² : DecidableEq γ
ε : β ≃ γ
f : γ → C
inst✝¹ : HasBiproduct f
inst✝ : HasBiproduct (f ∘ ⇑ε)
b b' : β
h : ¬b' = b
this : ε b' ≠ ε b
⊢ ι (f ∘ ⇑ε) b' ≫ ((desc fun b => ι f (ε b)) ≫ lift fun b => π f (ε b)) ≫ π (f ∘ ⇑ε) b =
    ι (f ∘ ⇑ε) b' ≫ 𝟙 (⨁ f ∘ ⇑ε) ≫ π (f ∘ ⇑ε) b

Next tactic:
simp [biproduct.ι_π_ne _ h, biproduct.ι_π_ne _ this]
/-- Reindex a categorical biproduct via an equivalence of the index types. -/
@[simps]
def biproduct.reindex {β γ : Type} [Fintype β] [DecidableEq β] [DecidableEq γ] (ε : β ≃ γ)
    (f : γ → C) [HasBiproduct f] [HasBiproduct (f ∘ ε)] : ⨁ f ∘ ε ≅ ⨁ f
    where
  hom := biproduct.desc fun b => biproduct.ι f (ε b)
  inv := biproduct.lift fun b => biproduct.π f (ε b)
  hom_inv_id := by
    ext b b'
    by_cases h : b' = b
    · subst h; simp
    · have : ε b' ≠ ε b := by simp [h]
      simp [biproduct.ι_π_ne _ h, biproduct.ι_π_ne _ this]
  inv_hom_id := by
    

Proof state:
C : Type u
inst✝⁷ : Category.{v, u} C
inst✝⁶ : Preadditive C
J : Type
inst✝⁵ : Fintype J
β γ : Type
inst✝⁴ : Fintype β
inst✝³ : DecidableEq β
inst✝² : DecidableEq γ
ε : β ≃ γ
f : γ → C
inst✝¹ : HasBiproduct f
inst✝ : HasBiproduct (f ∘ ⇑ε)
⊢ ((lift fun b => π f (ε b)) ≫ desc fun b => ι f (ε b)) = 𝟙 (⨁ f)

Next tactic:
ext g g'
/-- Reindex a categorical biproduct via an equivalence of the index types. -/
@[simps]
def biproduct.reindex {β γ : Type} [Fintype β] [DecidableEq β] [DecidableEq γ] (ε : β ≃ γ)
    (f : γ → C) [HasBiproduct f] [HasBiproduct (f ∘ ε)] : ⨁ f ∘ ε ≅ ⨁ f
    where
  hom := biproduct.desc fun b => biproduct.ι f (ε b)
  inv := biproduct.lift fun b => biproduct.π f (ε b)
  hom_inv_id := by
    ext b b'
    by_cases h : b' = b
    · subst h; simp
    · have : ε b' ≠ ε b := by simp [h]
      simp [biproduct.ι_π_ne _ h, biproduct.ι_π_ne _ this]
  inv_hom_id := by
    ext g g'
    

Proof state:
case w.w
C : Type u
inst✝⁷ : Category.{v, u} C
inst✝⁶ : Preadditive C
J : Type
inst✝⁵ : Fintype J
β γ : Type
inst✝⁴ : Fintype β
inst✝³ : DecidableEq β
inst✝² : DecidableEq γ
ε : β ≃ γ
f : γ → C
inst✝¹ : HasBiproduct f
inst✝ : HasBiproduct (f ∘ ⇑ε)
g g' : γ
⊢ ι f g' ≫ ((lift fun b => π f (ε b)) ≫ desc fun b => ι f (ε b)) ≫ π f g = ι f g' ≫ 𝟙 (⨁ f) ≫ π f g

Next tactic:
by_cases h : g' = g
/-- Reindex a categorical biproduct via an equivalence of the index types. -/
@[simps]
def biproduct.reindex {β γ : Type} [Fintype β] [DecidableEq β] [DecidableEq γ] (ε : β ≃ γ)
    (f : γ → C) [HasBiproduct f] [HasBiproduct (f ∘ ε)] : ⨁ f ∘ ε ≅ ⨁ f
    where
  hom := biproduct.desc fun b => biproduct.ι f (ε b)
  inv := biproduct.lift fun b => biproduct.π f (ε b)
  hom_inv_id := by
    ext b b'
    by_cases h : b' = b
    · subst h; simp
    · have : ε b' ≠ ε b := by simp [h]
      simp [biproduct.ι_π_ne _ h, biproduct.ι_π_ne _ this]
  inv_hom_id := by
    ext g g'
    by_cases h : g' = g <;>
      

Proof state:
case pos
C : Type u
inst✝⁷ : Category.{v, u} C
inst✝⁶ : Preadditive C
J : Type
inst✝⁵ : Fintype J
β γ : Type
inst✝⁴ : Fintype β
inst✝³ : DecidableEq β
inst✝² : DecidableEq γ
ε : β ≃ γ
f : γ → C
inst✝¹ : HasBiproduct f
inst✝ : HasBiproduct (f ∘ ⇑ε)
g g' : γ
h : g' = g
⊢ ι f g' ≫ ((lift fun b => π f (ε b)) ≫ desc fun b => ι f (ε b)) ≫ π f g = ι f g' ≫ 𝟙 (⨁ f) ≫ π f g

Next tactic:
simp [Preadditive.sum_comp, Preadditive.comp_sum, biproduct.lift_desc,
        biproduct.ι_π, biproduct.ι_π_assoc, comp_dite, Equiv.apply_eq_iff_eq_symm_apply,
        Finset.sum_dite_eq' Finset.univ (ε.symm g') _, h]
/-- Reindex a categorical biproduct via an equivalence of the index types. -/
@[simps]
def biproduct.reindex {β γ : Type} [Fintype β] [DecidableEq β] [DecidableEq γ] (ε : β ≃ γ)
    (f : γ → C) [HasBiproduct f] [HasBiproduct (f ∘ ε)] : ⨁ f ∘ ε ≅ ⨁ f
    where
  hom := biproduct.desc fun b => biproduct.ι f (ε b)
  inv := biproduct.lift fun b => biproduct.π f (ε b)
  hom_inv_id := by
    ext b b'
    by_cases h : b' = b
    · subst h; simp
    · have : ε b' ≠ ε b := by simp [h]
      simp [biproduct.ι_π_ne _ h, biproduct.ι_π_ne _ this]
  inv_hom_id := by
    ext g g'
    by_cases h : g' = g <;>
      

Proof state:
case neg
C : Type u
inst✝⁷ : Category.{v, u} C
inst✝⁶ : Preadditive C
J : Type
inst✝⁵ : Fintype J
β γ : Type
inst✝⁴ : Fintype β
inst✝³ : DecidableEq β
inst✝² : DecidableEq γ
ε : β ≃ γ
f : γ → C
inst✝¹ : HasBiproduct f
inst✝ : HasBiproduct (f ∘ ⇑ε)
g g' : γ
h : ¬g' = g
⊢ ι f g' ≫ ((lift fun b => π f (ε b)) ≫ desc fun b => ι f (ε b)) ≫ π f g = ι f g' ≫ 𝟙 (⨁ f) ≫ π f g

Next tactic:
simp [Preadditive.sum_comp, Preadditive.comp_sum, biproduct.lift_desc,
        biproduct.ι_π, biproduct.ι_π_assoc, comp_dite, Equiv.apply_eq_iff_eq_symm_apply,
        Finset.sum_dite_eq' Finset.univ (ε.symm g') _, h]
/-- In a preadditive category, we can construct a binary biproduct for `X Y : C` from
any binary bicone `b` satisfying `total : b.fst ≫ b.inl + b.snd ≫ b.inr = 𝟙 b.X`.

(That is, such a bicone is a limit cone and a colimit cocone.)
-/
def isBinaryBilimitOfTotal {X Y : C} (b : BinaryBicone X Y)
    (total : b.fst ≫ b.inl + b.snd ≫ b.inr = 𝟙 b.pt) : b.IsBilimit where
  isLimit :=
    { lift := fun s =>
      (BinaryFan.fst s ≫ b.inl : s.pt ⟶ b.pt) + (BinaryFan.snd s ≫ b.inr : s.pt ⟶ b.pt)
      uniq := fun s m h => by
        have reassoced (j : WalkingPair) {W : C} (h' : _ ⟶ W) :
          m ≫ b.toCone.π.app ⟨j⟩ ≫ h' = s.π.app ⟨j⟩ ≫ h' := by
            rw [← Category.assoc, eq_whisker (h ⟨j⟩)]
        erw [← Category.comp_id m, ← total, comp_add, reassoced WalkingPair.left,
          reassoced WalkingPair.right]
      fac := fun s j => by 

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Preadditive C
J : Type
inst✝ : Fintype J
X Y : C
b : BinaryBicone X Y
total : b.fst ≫ b.inl + b.snd ≫ b.inr = 𝟙 b.pt
s : Cone (pair X Y)
j : Discrete WalkingPair
⊢ (fun s => BinaryFan.fst s ≫ b.inl + BinaryFan.snd s ≫ b.inr) s ≫ (BinaryBicone.toCone b).π.app j = s.π.app j

Next tactic:
rcases j with ⟨⟨⟩⟩
/-- In a preadditive category, we can construct a binary biproduct for `X Y : C` from
any binary bicone `b` satisfying `total : b.fst ≫ b.inl + b.snd ≫ b.inr = 𝟙 b.X`.

(That is, such a bicone is a limit cone and a colimit cocone.)
-/
def isBinaryBilimitOfTotal {X Y : C} (b : BinaryBicone X Y)
    (total : b.fst ≫ b.inl + b.snd ≫ b.inr = 𝟙 b.pt) : b.IsBilimit where
  isLimit :=
    { lift := fun s =>
      (BinaryFan.fst s ≫ b.inl : s.pt ⟶ b.pt) + (BinaryFan.snd s ≫ b.inr : s.pt ⟶ b.pt)
      uniq := fun s m h => by
        have reassoced (j : WalkingPair) {W : C} (h' : _ ⟶ W) :
          m ≫ b.toCone.π.app ⟨j⟩ ≫ h' = s.π.app ⟨j⟩ ≫ h' := by
            rw [← Category.assoc, eq_whisker (h ⟨j⟩)]
        erw [← Category.comp_id m, ← total, comp_add, reassoced WalkingPair.left,
          reassoced WalkingPair.right]
      fac := fun s j => by rcases j with ⟨⟨⟩⟩ <;> 

Proof state:
case mk.left
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Preadditive C
J : Type
inst✝ : Fintype J
X Y : C
b : BinaryBicone X Y
total : b.fst ≫ b.inl + b.snd ≫ b.inr = 𝟙 b.pt
s : Cone (pair X Y)
⊢ (fun s => BinaryFan.fst s ≫ b.inl + BinaryFan.snd s ≫ b.inr) s ≫
      (BinaryBicone.toCone b).π.app { as := WalkingPair.left } =
    s.π.app { as := WalkingPair.left }

Next tactic:
simp