l3lab/ntp-mathlib huggingface dataset:
@[simp]
theorem cast_eq_zero [AddGroupWithOne α] [CharZero α] {n : ℤ} : (n : α) = 0 ↔ n = 0 :=
  ⟨fun h => by
    cases n
    · erw [Int.cast_ofNat] at h
      

Proof state:
case ofNat
α : Type u_1
β : Type u_2
inst✝¹ : AddGroupWithOne α
inst✝ : CharZero α
a✝ : ℕ
h : ↑a✝ = 0
⊢ ofNat a✝ = 0

Next tactic:
exact congr_arg _ (Nat.cast_eq_zero.1 h)
@[simp]
theorem cast_eq_zero [AddGroupWithOne α] [CharZero α] {n : ℤ} : (n : α) = 0 ↔ n = 0 :=
  ⟨fun h => by
    cases n
    · erw [Int.cast_ofNat] at h
      exact congr_arg _ (Nat.cast_eq_zero.1 h)
    · 

Proof state:
case negSucc
α : Type u_1
β : Type u_2
inst✝¹ : AddGroupWithOne α
inst✝ : CharZero α
a✝ : ℕ
h : ↑-[a✝+1] = 0
⊢ -[a✝+1] = 0

Next tactic:
rw [cast_negSucc, neg_eq_zero, Nat.cast_eq_zero] at h
@[simp]
theorem cast_eq_zero [AddGroupWithOne α] [CharZero α] {n : ℤ} : (n : α) = 0 ↔ n = 0 :=
  ⟨fun h => by
    cases n
    · erw [Int.cast_ofNat] at h
      exact congr_arg _ (Nat.cast_eq_zero.1 h)
    · rw [cast_negSucc, neg_eq_zero, Nat.cast_eq_zero] at h
      

Proof state:
case negSucc
α : Type u_1
β : Type u_2
inst✝¹ : AddGroupWithOne α
inst✝ : CharZero α
a✝ : ℕ
h : a✝ + 1 = 0
⊢ -[a✝+1] = 0

Next tactic:
contradiction
@[simp]
theorem cast_eq_zero [AddGroupWithOne α] [CharZero α] {n : ℤ} : (n : α) = 0 ↔ n = 0 :=
  ⟨fun h => by
    cases n
    · erw [Int.cast_ofNat] at h
      exact congr_arg _ (Nat.cast_eq_zero.1 h)
    · rw [cast_negSucc, neg_eq_zero, Nat.cast_eq_zero] at h
      contradiction,
    fun h => by 

Proof state:
α : Type u_1
β : Type u_2
inst✝¹ : AddGroupWithOne α
inst✝ : CharZero α
n : ℤ
h : n = 0
⊢ ↑n = 0

Next tactic:
rw [h, cast_zero]
@[simp, norm_cast]
theorem cast_inj [AddGroupWithOne α] [CharZero α] {m n : ℤ} : (m : α) = n ↔ m = n := by
  

Proof state:
α : Type u_1
β : Type u_2
inst✝¹ : AddGroupWithOne α
inst✝ : CharZero α
m n : ℤ
⊢ ↑m = ↑n ↔ m = n

Next tactic:
rw [← sub_eq_zero, ← cast_sub, cast_eq_zero, sub_eq_zero]
@[simp]
theorem cast_eq_one [AddGroupWithOne α] [CharZero α] {n : ℤ} : (n : α) = 1 ↔ n = 1 := by
  

Proof state:
α : Type u_1
β : Type u_2
inst✝¹ : AddGroupWithOne α
inst✝ : CharZero α
n : ℤ
⊢ ↑n = 1 ↔ n = 1

Next tactic:
rw [← cast_one, cast_inj]
@[simp, norm_cast]
theorem cast_div_charZero {k : Type*} [DivisionRing k] [CharZero k] {m n : ℤ} (n_dvd : n ∣ m) :
    ((m / n : ℤ) : k) = m / n := by
  

Proof state:
α : Type u_1
β : Type u_2
k : Type u_3
inst✝¹ : DivisionRing k
inst✝ : CharZero k
m n : ℤ
n_dvd : n ∣ m
⊢ ↑(m / n) = ↑m / ↑n

Next tactic:
rcases eq_or_ne n 0 with (rfl | hn)
@[simp, norm_cast]
theorem cast_div_charZero {k : Type*} [DivisionRing k] [CharZero k] {m n : ℤ} (n_dvd : n ∣ m) :
    ((m / n : ℤ) : k) = m / n := by
  rcases eq_or_ne n 0 with (rfl | hn)
  · 

Proof state:
case inl
α : Type u_1
β : Type u_2
k : Type u_3
inst✝¹ : DivisionRing k
inst✝ : CharZero k
m : ℤ
n_dvd : 0 ∣ m
⊢ ↑(m / 0) = ↑m / ↑0

Next tactic:
simp [Int.ediv_zero]
@[simp, norm_cast]
theorem cast_div_charZero {k : Type*} [DivisionRing k] [CharZero k] {m n : ℤ} (n_dvd : n ∣ m) :
    ((m / n : ℤ) : k) = m / n := by
  rcases eq_or_ne n 0 with (rfl | hn)
  · simp [Int.ediv_zero]
  · 

Proof state:
case inr
α : Type u_1
β : Type u_2
k : Type u_3
inst✝¹ : DivisionRing k
inst✝ : CharZero k
m n : ℤ
n_dvd : n ∣ m
hn : n ≠ 0
⊢ ↑(m / n) = ↑m / ↑n

Next tactic:
exact cast_div n_dvd (cast_ne_zero.mpr hn)
@[simp, norm_cast]
theorem cast_div_ofNat_charZero {k : Type*} [DivisionRing k] [CharZero k] {m n : ℕ}
    (n_dvd : n ∣ m) : (((m : ℤ) / (n : ℤ) : ℤ) : k) = m / n := by
  

Proof state:
α : Type u_1
β : Type u_2
k : Type u_3
inst✝¹ : DivisionRing k
inst✝ : CharZero k
m n : ℕ
n_dvd : n ∣ m
⊢ ↑(↑m / ↑n) = ↑m / ↑n

Next tactic:
rw [cast_div_charZero (Int.ofNat_dvd.mpr n_dvd), cast_ofNat, cast_ofNat]
theorem mul_of_commute {p q : S} (h : Commute p q) (h₁ : IsIdempotentElem p)
    (h₂ : IsIdempotentElem q) : IsIdempotentElem (p * q) := by
  

Proof state:
M : Type u_1
N : Type u_2
S : Type u_3
M₀ : Type u_4
M₁ : Type u_5
R : Type u_6
G : Type u_7
G₀ : Type u_8
inst✝⁷ : Mul M
inst✝⁶ : Monoid N
inst✝⁵ : Semigroup S
inst✝⁴ : MulZeroClass M₀
inst✝³ : MulOneClass M₁
inst✝² : NonAssocRing R
inst✝¹ : Group G
inst✝ : CancelMonoidWithZero G₀
p q : S
h : Commute p q
h₁ : IsIdempotentElem p
h₂ : IsIdempotentElem q
⊢ IsIdempotentElem (p * q)

Next tactic:
rw [IsIdempotentElem, mul_assoc, ← mul_assoc q, ← h.eq, mul_assoc p, h₂.eq, ← mul_assoc, h₁.eq]
theorem one_sub {p : R} (h : IsIdempotentElem p) : IsIdempotentElem (1 - p) := by
  

Proof state:
M : Type u_1
N : Type u_2
S : Type u_3
M₀ : Type u_4
M₁ : Type u_5
R : Type u_6
G : Type u_7
G₀ : Type u_8
inst✝⁷ : Mul M
inst✝⁶ : Monoid N
inst✝⁵ : Semigroup S
inst✝⁴ : MulZeroClass M₀
inst✝³ : MulOneClass M₁
inst✝² : NonAssocRing R
inst✝¹ : Group G
inst✝ : CancelMonoidWithZero G₀
p : R
h : IsIdempotentElem p
⊢ IsIdempotentElem (1 - p)

Next tactic:
rw [IsIdempotentElem, mul_sub, mul_one, sub_mul, one_mul, h.eq, sub_self, sub_zero]
theorem pow {p : N} (n : ℕ) (h : IsIdempotentElem p) : IsIdempotentElem (p ^ n) :=
  Nat.recOn n ((pow_zero p).symm ▸ one) fun n _ =>
    show p ^ n.succ * p ^ n.succ = p ^ n.succ by
      

Proof state:
M : Type u_1
N : Type u_2
S : Type u_3
M₀ : Type u_4
M₁ : Type u_5
R : Type u_6
G : Type u_7
G₀ : Type u_8
inst✝⁷ : Mul M
inst✝⁶ : Monoid N
inst✝⁵ : Semigroup S
inst✝⁴ : MulZeroClass M₀
inst✝³ : MulOneClass M₁
inst✝² : NonAssocRing R
inst✝¹ : Group G
inst✝ : CancelMonoidWithZero G₀
p : N
n✝ : ℕ
h : IsIdempotentElem p
n : ℕ
x✝ : IsIdempotentElem (p ^ n)
⊢ p ^ Nat.succ n * p ^ Nat.succ n = p ^ Nat.succ n

Next tactic:
conv_rhs => rw [← h.eq]
theorem pow {p : N} (n : ℕ) (h : IsIdempotentElem p) : IsIdempotentElem (p ^ n) :=
  Nat.recOn n ((pow_zero p).symm ▸ one) fun n _ =>
    show p ^ n.succ * p ^ n.succ = p ^ n.succ by
      conv_rhs => 

Proof state:
M : Type u_1
N : Type u_2
S : Type u_3
M₀ : Type u_4
M₁ : Type u_5
R : Type u_6
G : Type u_7
G₀ : Type u_8
inst✝⁷ : Mul M
inst✝⁶ : Monoid N
inst✝⁵ : Semigroup S
inst✝⁴ : MulZeroClass M₀
inst✝³ : MulOneClass M₁
inst✝² : NonAssocRing R
inst✝¹ : Group G
inst✝ : CancelMonoidWithZero G₀
p : N
n✝ : ℕ
h : IsIdempotentElem p
n : ℕ
x✝ : IsIdempotentElem (p ^ n)
| p ^ Nat.succ n

Next tactic:
rw [← h.eq]
theorem pow {p : N} (n : ℕ) (h : IsIdempotentElem p) : IsIdempotentElem (p ^ n) :=
  Nat.recOn n ((pow_zero p).symm ▸ one) fun n _ =>
    show p ^ n.succ * p ^ n.succ = p ^ n.succ by
      conv_rhs => rw [← h.eq] --Porting note: was `nth_rw 3 [← h.eq]`
      

Proof state:
M : Type u_1
N : Type u_2
S : Type u_3
M₀ : Type u_4
M₁ : Type u_5
R : Type u_6
G : Type u_7
G₀ : Type u_8
inst✝⁷ : Mul M
inst✝⁶ : Monoid N
inst✝⁵ : Semigroup S
inst✝⁴ : MulZeroClass M₀
inst✝³ : MulOneClass M₁
inst✝² : NonAssocRing R
inst✝¹ : Group G
inst✝ : CancelMonoidWithZero G₀
p : N
n✝ : ℕ
h : IsIdempotentElem p
n : ℕ
x✝ : IsIdempotentElem (p ^ n)
⊢ p ^ Nat.succ n * p ^ Nat.succ n = (p * p) ^ Nat.succ n

Next tactic:
rw [← sq, ← sq, ← pow_mul, ← pow_mul']
theorem pow_succ_eq {p : N} (n : ℕ) (h : IsIdempotentElem p) : p ^ (n + 1) = p :=
  Nat.recOn n ((Nat.zero_add 1).symm ▸ pow_one p) fun n ih => by 

Proof state:
M : Type u_1
N : Type u_2
S : Type u_3
M₀ : Type u_4
M₁ : Type u_5
R : Type u_6
G : Type u_7
G₀ : Type u_8
inst✝⁷ : Mul M
inst✝⁶ : Monoid N
inst✝⁵ : Semigroup S
inst✝⁴ : MulZeroClass M₀
inst✝³ : MulOneClass M₁
inst✝² : NonAssocRing R
inst✝¹ : Group G
inst✝ : CancelMonoidWithZero G₀
p : N
n✝ : ℕ
h : IsIdempotentElem p
n : ℕ
ih : p ^ (n + 1) = p
⊢ p ^ (Nat.succ n + 1) = p

Next tactic:
rw [pow_succ, ih, h.eq]
@[simp]
theorem iff_eq_zero_or_one {p : G₀} : IsIdempotentElem p ↔ p = 0 ∨ p = 1 := by
  

Proof state:
M : Type u_1
N : Type u_2
S : Type u_3
M₀ : Type u_4
M₁ : Type u_5
R : Type u_6
G : Type u_7
G₀ : Type u_8
inst✝⁷ : Mul M
inst✝⁶ : Monoid N
inst✝⁵ : Semigroup S
inst✝⁴ : MulZeroClass M₀
inst✝³ : MulOneClass M₁
inst✝² : NonAssocRing R
inst✝¹ : Group G
inst✝ : CancelMonoidWithZero G₀
p : G₀
⊢ IsIdempotentElem p ↔ p = 0 ∨ p = 1

Next tactic:
refine'
    Iff.intro (fun h => or_iff_not_imp_left.mpr fun hp => _) fun h =>
      h.elim (fun hp => hp.symm ▸ zero) fun hp => hp.symm ▸ one
@[simp]
theorem iff_eq_zero_or_one {p : G₀} : IsIdempotentElem p ↔ p = 0 ∨ p = 1 := by
  refine'
    Iff.intro (fun h => or_iff_not_imp_left.mpr fun hp => _) fun h =>
      h.elim (fun hp => hp.symm ▸ zero) fun hp => hp.symm ▸ one
  

Proof state:
M : Type u_1
N : Type u_2
S : Type u_3
M₀ : Type u_4
M₁ : Type u_5
R : Type u_6
G : Type u_7
G₀ : Type u_8
inst✝⁷ : Mul M
inst✝⁶ : Monoid N
inst✝⁵ : Semigroup S
inst✝⁴ : MulZeroClass M₀
inst✝³ : MulOneClass M₁
inst✝² : NonAssocRing R
inst✝¹ : Group G
inst✝ : CancelMonoidWithZero G₀
p : G₀
h : IsIdempotentElem p
hp : ¬p = 0
⊢ p = 1

Next tactic:
exact mul_left_cancel₀ hp (h.trans (mul_one p).symm)
@[simps]
def Triangle.isoMk (A B : Triangle C)
    (iso₁ : A.obj₁ ≅ B.obj₁) (iso₂ : A.obj₂ ≅ B.obj₂) (iso₃ : A.obj₃ ≅ B.obj₃)
    (comm₁ : A.mor₁ ≫ iso₂.hom = iso₁.hom ≫ B.mor₁ := by aesop_cat)
    (comm₂ : A.mor₂ ≫ iso₃.hom = iso₂.hom ≫ B.mor₂ := by aesop_cat)
    (comm₃ : A.mor₃ ≫ iso₁.hom⟦1⟧' = iso₃.hom ≫ B.mor₃ := by aesop_cat) : A ≅ B where
  hom := Triangle.homMk _ _ iso₁.hom iso₂.hom iso₃.hom comm₁ comm₂ comm₃
  inv := Triangle.homMk _ _ iso₁.inv iso₂.inv iso₃.inv
    (by 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasShift C ℤ
T₁ T₂ T₃ A B : Triangle C
iso₁ : A.obj₁ ≅ B.obj₁
iso₂ : A.obj₂ ≅ B.obj₂
iso₃ : A.obj₃ ≅ B.obj₃
comm₁ : autoParam (A.mor₁ ≫ iso₂.hom = iso₁.hom ≫ B.mor₁) _auto✝
comm₂ : autoParam (A.mor₂ ≫ iso₃.hom = iso₂.hom ≫ B.mor₂) _auto✝
comm₃ : autoParam (A.mor₃ ≫ (shiftFunctor C 1).map iso₁.hom = iso₃.hom ≫ B.mor₃) _auto✝
⊢ B.mor₁ ≫ iso₂.inv = iso₁.inv ≫ A.mor₁

Next tactic:
simp only [← cancel_mono iso₂.hom, assoc, Iso.inv_hom_id, comp_id,
      comm₁, Iso.inv_hom_id_assoc]
@[simps]
def Triangle.isoMk (A B : Triangle C)
    (iso₁ : A.obj₁ ≅ B.obj₁) (iso₂ : A.obj₂ ≅ B.obj₂) (iso₃ : A.obj₃ ≅ B.obj₃)
    (comm₁ : A.mor₁ ≫ iso₂.hom = iso₁.hom ≫ B.mor₁ := by aesop_cat)
    (comm₂ : A.mor₂ ≫ iso₃.hom = iso₂.hom ≫ B.mor₂ := by aesop_cat)
    (comm₃ : A.mor₃ ≫ iso₁.hom⟦1⟧' = iso₃.hom ≫ B.mor₃ := by aesop_cat) : A ≅ B where
  hom := Triangle.homMk _ _ iso₁.hom iso₂.hom iso₃.hom comm₁ comm₂ comm₃
  inv := Triangle.homMk _ _ iso₁.inv iso₂.inv iso₃.inv
    (by simp only [← cancel_mono iso₂.hom, assoc, Iso.inv_hom_id, comp_id,
      comm₁, Iso.inv_hom_id_assoc])
    (by 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasShift C ℤ
T₁ T₂ T₃ A B : Triangle C
iso₁ : A.obj₁ ≅ B.obj₁
iso₂ : A.obj₂ ≅ B.obj₂
iso₃ : A.obj₃ ≅ B.obj₃
comm₁ : autoParam (A.mor₁ ≫ iso₂.hom = iso₁.hom ≫ B.mor₁) _auto✝
comm₂ : autoParam (A.mor₂ ≫ iso₃.hom = iso₂.hom ≫ B.mor₂) _auto✝
comm₃ : autoParam (A.mor₃ ≫ (shiftFunctor C 1).map iso₁.hom = iso₃.hom ≫ B.mor₃) _auto✝
⊢ B.mor₂ ≫ iso₃.inv = iso₂.inv ≫ A.mor₂

Next tactic:
simp only [← cancel_mono iso₃.hom, assoc, Iso.inv_hom_id, comp_id,
      comm₂, Iso.inv_hom_id_assoc]
@[simps]
def Triangle.isoMk (A B : Triangle C)
    (iso₁ : A.obj₁ ≅ B.obj₁) (iso₂ : A.obj₂ ≅ B.obj₂) (iso₃ : A.obj₃ ≅ B.obj₃)
    (comm₁ : A.mor₁ ≫ iso₂.hom = iso₁.hom ≫ B.mor₁ := by aesop_cat)
    (comm₂ : A.mor₂ ≫ iso₃.hom = iso₂.hom ≫ B.mor₂ := by aesop_cat)
    (comm₃ : A.mor₃ ≫ iso₁.hom⟦1⟧' = iso₃.hom ≫ B.mor₃ := by aesop_cat) : A ≅ B where
  hom := Triangle.homMk _ _ iso₁.hom iso₂.hom iso₃.hom comm₁ comm₂ comm₃
  inv := Triangle.homMk _ _ iso₁.inv iso₂.inv iso₃.inv
    (by simp only [← cancel_mono iso₂.hom, assoc, Iso.inv_hom_id, comp_id,
      comm₁, Iso.inv_hom_id_assoc])
    (by simp only [← cancel_mono iso₃.hom, assoc, Iso.inv_hom_id, comp_id,
      comm₂, Iso.inv_hom_id_assoc])
    (by 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasShift C ℤ
T₁ T₂ T₃ A B : Triangle C
iso₁ : A.obj₁ ≅ B.obj₁
iso₂ : A.obj₂ ≅ B.obj₂
iso₃ : A.obj₃ ≅ B.obj₃
comm₁ : autoParam (A.mor₁ ≫ iso₂.hom = iso₁.hom ≫ B.mor₁) _auto✝
comm₂ : autoParam (A.mor₂ ≫ iso₃.hom = iso₂.hom ≫ B.mor₂) _auto✝
comm₃ : autoParam (A.mor₃ ≫ (shiftFunctor C 1).map iso₁.hom = iso₃.hom ≫ B.mor₃) _auto✝
⊢ B.mor₃ ≫ (shiftFunctor C 1).map iso₁.inv = iso₃.inv ≫ A.mor₃

Next tactic:
simp only [← cancel_mono (iso₁.hom⟦(1 : ℤ)⟧'), Category.assoc, comm₃,
      Iso.inv_hom_id_assoc, ← Functor.map_comp, Iso.inv_hom_id,
      Functor.map_id, Category.comp_id]
lemma Triangle.isIso_of_isIsos {A B : Triangle C} (f : A ⟶ B)
    (h₁ : IsIso f.hom₁) (h₂ : IsIso f.hom₂) (h₃ : IsIso f.hom₃) : IsIso f := by
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasShift C ℤ
T₁ T₂ T₃ A B : Triangle C
f : A ⟶ B
h₁ : IsIso f.hom₁
h₂ : IsIso f.hom₂
h₃ : IsIso f.hom₃
⊢ IsIso f

Next tactic:
let e := Triangle.isoMk A B (asIso f.hom₁) (asIso f.hom₂) (asIso f.hom₃)
    (by simp) (by simp) (by simp)
lemma Triangle.isIso_of_isIsos {A B : Triangle C} (f : A ⟶ B)
    (h₁ : IsIso f.hom₁) (h₂ : IsIso f.hom₂) (h₃ : IsIso f.hom₃) : IsIso f := by
  let e := Triangle.isoMk A B (asIso f.hom₁) (asIso f.hom₂) (asIso f.hom₃)
    (by 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasShift C ℤ
T₁ T₂ T₃ A B : Triangle C
f : A ⟶ B
h₁ : IsIso f.hom₁
h₂ : IsIso f.hom₂
h₃ : IsIso f.hom₃
⊢ A.mor₁ ≫ (asIso f.hom₂).hom = (asIso f.hom₁).hom ≫ B.mor₁

Next tactic:
simp
lemma Triangle.isIso_of_isIsos {A B : Triangle C} (f : A ⟶ B)
    (h₁ : IsIso f.hom₁) (h₂ : IsIso f.hom₂) (h₃ : IsIso f.hom₃) : IsIso f := by
  let e := Triangle.isoMk A B (asIso f.hom₁) (asIso f.hom₂) (asIso f.hom₃)
    (by simp) (by 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasShift C ℤ
T₁ T₂ T₃ A B : Triangle C
f : A ⟶ B
h₁ : IsIso f.hom₁
h₂ : IsIso f.hom₂
h₃ : IsIso f.hom₃
⊢ A.mor₂ ≫ (asIso f.hom₃).hom = (asIso f.hom₂).hom ≫ B.mor₂

Next tactic:
simp
lemma Triangle.isIso_of_isIsos {A B : Triangle C} (f : A ⟶ B)
    (h₁ : IsIso f.hom₁) (h₂ : IsIso f.hom₂) (h₃ : IsIso f.hom₃) : IsIso f := by
  let e := Triangle.isoMk A B (asIso f.hom₁) (asIso f.hom₂) (asIso f.hom₃)
    (by simp) (by simp) (by 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasShift C ℤ
T₁ T₂ T₃ A B : Triangle C
f : A ⟶ B
h₁ : IsIso f.hom₁
h₂ : IsIso f.hom₂
h₃ : IsIso f.hom₃
⊢ A.mor₃ ≫ (shiftFunctor C 1).map (asIso f.hom₁).hom = (asIso f.hom₃).hom ≫ B.mor₃

Next tactic:
simp
lemma Triangle.isIso_of_isIsos {A B : Triangle C} (f : A ⟶ B)
    (h₁ : IsIso f.hom₁) (h₂ : IsIso f.hom₂) (h₃ : IsIso f.hom₃) : IsIso f := by
  let e := Triangle.isoMk A B (asIso f.hom₁) (asIso f.hom₂) (asIso f.hom₃)
    (by simp) (by simp) (by simp)
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasShift C ℤ
T₁ T₂ T₃ A B : Triangle C
f : A ⟶ B
h₁ : IsIso f.hom₁
h₂ : IsIso f.hom₂
h₃ : IsIso f.hom₃
e : A ≅ B := isoMk A B (asIso f.hom₁) (asIso f.hom₂) (asIso f.hom₃)
⊢ IsIso f

Next tactic:
exact (inferInstance : IsIso e.hom)
lemma Triangle.eqToHom_hom₁ {A B : Triangle C} (h : A = B) :
    (eqToHom h).hom₁ = eqToHom (by 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasShift C ℤ
T₁ T₂ T₃ A B : Triangle C
h : A = B
⊢ A.obj₁ = B.obj₁

Next tactic:
subst h
lemma Triangle.eqToHom_hom₁ {A B : Triangle C} (h : A = B) :
    (eqToHom h).hom₁ = eqToHom (by subst h; 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasShift C ℤ
T₁ T₂ T₃ A : Triangle C
⊢ A.obj₁ = A.obj₁

Next tactic:
rfl
lemma Triangle.eqToHom_hom₁ {A B : Triangle C} (h : A = B) :
    (eqToHom h).hom₁ = eqToHom (by subst h; rfl) := by 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasShift C ℤ
T₁ T₂ T₃ A B : Triangle C
h : A = B
⊢ (eqToHom h).hom₁ = eqToHom (_ : A.obj₁ = B.obj₁)

Next tactic:
subst h
lemma Triangle.eqToHom_hom₁ {A B : Triangle C} (h : A = B) :
    (eqToHom h).hom₁ = eqToHom (by subst h; rfl) := by subst h; 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasShift C ℤ
T₁ T₂ T₃ A : Triangle C
⊢ (eqToHom (_ : A = A)).hom₁ = eqToHom (_ : A.obj₁ = A.obj₁)

Next tactic:
rfl
lemma Triangle.eqToHom_hom₂ {A B : Triangle C} (h : A = B) :
    (eqToHom h).hom₂ = eqToHom (by 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasShift C ℤ
T₁ T₂ T₃ A B : Triangle C
h : A = B
⊢ A.obj₂ = B.obj₂

Next tactic:
subst h
lemma Triangle.eqToHom_hom₂ {A B : Triangle C} (h : A = B) :
    (eqToHom h).hom₂ = eqToHom (by subst h; 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasShift C ℤ
T₁ T₂ T₃ A : Triangle C
⊢ A.obj₂ = A.obj₂

Next tactic:
rfl
lemma Triangle.eqToHom_hom₂ {A B : Triangle C} (h : A = B) :
    (eqToHom h).hom₂ = eqToHom (by subst h; rfl) := by 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasShift C ℤ
T₁ T₂ T₃ A B : Triangle C
h : A = B
⊢ (eqToHom h).hom₂ = eqToHom (_ : A.obj₂ = B.obj₂)

Next tactic:
subst h
lemma Triangle.eqToHom_hom₂ {A B : Triangle C} (h : A = B) :
    (eqToHom h).hom₂ = eqToHom (by subst h; rfl) := by subst h; 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasShift C ℤ
T₁ T₂ T₃ A : Triangle C
⊢ (eqToHom (_ : A = A)).hom₂ = eqToHom (_ : A.obj₂ = A.obj₂)

Next tactic:
rfl
lemma Triangle.eqToHom_hom₃ {A B : Triangle C} (h : A = B) :
    (eqToHom h).hom₃ = eqToHom (by 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasShift C ℤ
T₁ T₂ T₃ A B : Triangle C
h : A = B
⊢ A.obj₃ = B.obj₃

Next tactic:
subst h
lemma Triangle.eqToHom_hom₃ {A B : Triangle C} (h : A = B) :
    (eqToHom h).hom₃ = eqToHom (by subst h; 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasShift C ℤ
T₁ T₂ T₃ A : Triangle C
⊢ A.obj₃ = A.obj₃

Next tactic:
rfl
lemma Triangle.eqToHom_hom₃ {A B : Triangle C} (h : A = B) :
    (eqToHom h).hom₃ = eqToHom (by subst h; rfl) := by 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasShift C ℤ
T₁ T₂ T₃ A B : Triangle C
h : A = B
⊢ (eqToHom h).hom₃ = eqToHom (_ : A.obj₃ = B.obj₃)

Next tactic:
subst h
lemma Triangle.eqToHom_hom₃ {A B : Triangle C} (h : A = B) :
    (eqToHom h).hom₃ = eqToHom (by subst h; rfl) := by subst h; 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasShift C ℤ
T₁ T₂ T₃ A : Triangle C
⊢ (eqToHom (_ : A = A)).hom₃ = eqToHom (_ : A.obj₃ = A.obj₃)

Next tactic:
rfl
/-- The canonical isomorphism of triangles
`binaryProductTriangle X₁ X₂ ≅ binaryBiproductTriangle X₁ X₂`. -/
@[simps!]
def binaryProductTriangleIsoBinaryBiproductTriangle
    (X₁ X₂ : C) [HasZeroMorphisms C] [HasBinaryBiproduct X₁ X₂] :
    binaryProductTriangle X₁ X₂ ≅ binaryBiproductTriangle X₁ X₂ :=
  Triangle.isoMk _ _ (Iso.refl _) (biprod.isoProd X₁ X₂).symm (Iso.refl _)
    (by 

Proof state:
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : HasShift C ℤ
T₁ T₂ T₃ : Triangle C
X₁ X₂ : C
inst✝¹ : HasZeroMorphisms C
inst✝ : HasBinaryBiproduct X₁ X₂
⊢ (binaryProductTriangle X₁ X₂).mor₁ ≫ (biprod.isoProd X₁ X₂).symm.hom =
    (Iso.refl (binaryProductTriangle X₁ X₂).obj₁).hom ≫ (binaryBiproductTriangle X₁ X₂).mor₁

Next tactic:
aesop_cat
/-- The canonical isomorphism of triangles
`binaryProductTriangle X₁ X₂ ≅ binaryBiproductTriangle X₁ X₂`. -/
@[simps!]
def binaryProductTriangleIsoBinaryBiproductTriangle
    (X₁ X₂ : C) [HasZeroMorphisms C] [HasBinaryBiproduct X₁ X₂] :
    binaryProductTriangle X₁ X₂ ≅ binaryBiproductTriangle X₁ X₂ :=
  Triangle.isoMk _ _ (Iso.refl _) (biprod.isoProd X₁ X₂).symm (Iso.refl _)
    (by aesop_cat) (by 

Proof state:
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : HasShift C ℤ
T₁ T₂ T₃ : Triangle C
X₁ X₂ : C
inst✝¹ : HasZeroMorphisms C
inst✝ : HasBinaryBiproduct X₁ X₂
⊢ (binaryProductTriangle X₁ X₂).mor₂ ≫ (Iso.refl (binaryProductTriangle X₁ X₂).obj₃).hom =
    (biprod.isoProd X₁ X₂).symm.hom ≫ (binaryBiproductTriangle X₁ X₂).mor₂

Next tactic:
aesop_cat
/-- The canonical isomorphism of triangles
`binaryProductTriangle X₁ X₂ ≅ binaryBiproductTriangle X₁ X₂`. -/
@[simps!]
def binaryProductTriangleIsoBinaryBiproductTriangle
    (X₁ X₂ : C) [HasZeroMorphisms C] [HasBinaryBiproduct X₁ X₂] :
    binaryProductTriangle X₁ X₂ ≅ binaryBiproductTriangle X₁ X₂ :=
  Triangle.isoMk _ _ (Iso.refl _) (biprod.isoProd X₁ X₂).symm (Iso.refl _)
    (by aesop_cat) (by aesop_cat) (by 

Proof state:
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : HasShift C ℤ
T₁ T₂ T₃ : Triangle C
X₁ X₂ : C
inst✝¹ : HasZeroMorphisms C
inst✝ : HasBinaryBiproduct X₁ X₂
⊢ (binaryProductTriangle X₁ X₂).mor₃ ≫ (shiftFunctor C 1).map (Iso.refl (binaryProductTriangle X₁ X₂).obj₁).hom =
    (Iso.refl (binaryProductTriangle X₁ X₂).obj₃).hom ≫ (binaryBiproductTriangle X₁ X₂).mor₃

Next tactic:
aesop_cat
/-- A projection from the product of a family of triangles. -/
@[simps]
def productTriangle.π (j : J) :
    productTriangle T ⟶ T j where
  hom₁ := Pi.π _ j
  hom₂ := Pi.π _ j
  hom₃ := Pi.π _ j
  comm₃ := by
    

Proof state:
C : Type u
inst✝⁵ : Category.{v, u} C
inst✝⁴ : HasShift C ℤ
T₁ T₂ T₃ : Triangle C
J : Type u_1
T : J → Triangle C
inst✝³ : HasProduct fun j => (T j).obj₁
inst✝² : HasProduct fun j => (T j).obj₂
inst✝¹ : HasProduct fun j => (T j).obj₃
inst✝ : HasProduct fun j => (shiftFunctor C 1).obj (T j).obj₁
j : J
⊢ (productTriangle T).mor₃ ≫ (shiftFunctor C 1).map (Pi.π (fun j => (T j).obj₁) j) =
    Pi.π (fun j => (T j).obj₃) j ≫ (T j).mor₃

Next tactic:
dsimp
/-- A projection from the product of a family of triangles. -/
@[simps]
def productTriangle.π (j : J) :
    productTriangle T ⟶ T j where
  hom₁ := Pi.π _ j
  hom₂ := Pi.π _ j
  hom₃ := Pi.π _ j
  comm₃ := by
    dsimp
    

Proof state:
C : Type u
inst✝⁵ : Category.{v, u} C
inst✝⁴ : HasShift C ℤ
T₁ T₂ T₃ : Triangle C
J : Type u_1
T : J → Triangle C
inst✝³ : HasProduct fun j => (T j).obj₁
inst✝² : HasProduct fun j => (T j).obj₂
inst✝¹ : HasProduct fun j => (T j).obj₃
inst✝ : HasProduct fun j => (shiftFunctor C 1).obj (T j).obj₁
j : J
⊢ ((Pi.map fun j => (T j).mor₃) ≫ inv (piComparison (shiftFunctor C 1) fun j => (T j).obj₁)) ≫
      (shiftFunctor C 1).map (Pi.π (fun j => (T j).obj₁) j) =
    Pi.π (fun j => (T j).obj₃) j ≫ (T j).mor₃

Next tactic:
rw [← piComparison_comp_π, assoc, IsIso.inv_hom_id_assoc]
/-- A projection from the product of a family of triangles. -/
@[simps]
def productTriangle.π (j : J) :
    productTriangle T ⟶ T j where
  hom₁ := Pi.π _ j
  hom₂ := Pi.π _ j
  hom₃ := Pi.π _ j
  comm₃ := by
    dsimp
    rw [← piComparison_comp_π, assoc, IsIso.inv_hom_id_assoc]
    

Proof state:
C : Type u
inst✝⁵ : Category.{v, u} C
inst✝⁴ : HasShift C ℤ
T₁ T₂ T₃ : Triangle C
J : Type u_1
T : J → Triangle C
inst✝³ : HasProduct fun j => (T j).obj₁
inst✝² : HasProduct fun j => (T j).obj₂
inst✝¹ : HasProduct fun j => (T j).obj₃
inst✝ : HasProduct fun j => (shiftFunctor C 1).obj (T j).obj₁
j : J
⊢ (Pi.map fun j => (T j).mor₃) ≫ Pi.π (fun b => (shiftFunctor C 1).obj (T b).obj₁) j =
    Pi.π (fun j => (T j).obj₃) j ≫ (T j).mor₃

Next tactic:
simp only [limMap_π, Discrete.natTrans_app]
/-- A family of morphisms `T' ⟶ T j` lifts to a morphism `T' ⟶ productTriangle T`. -/
@[simps]
def productTriangle.lift {T' : Triangle C} (φ : ∀ j, T' ⟶ T j) :
    T' ⟶ productTriangle T where
  hom₁ := Pi.lift (fun j => (φ j).hom₁)
  hom₂ := Pi.lift (fun j => (φ j).hom₂)
  hom₃ := Pi.lift (fun j => (φ j).hom₃)
  comm₃ := by
    

Proof state:
C : Type u
inst✝⁵ : Category.{v, u} C
inst✝⁴ : HasShift C ℤ
T₁ T₂ T₃ : Triangle C
J : Type u_1
T : J → Triangle C
inst✝³ : HasProduct fun j => (T j).obj₁
inst✝² : HasProduct fun j => (T j).obj₂
inst✝¹ : HasProduct fun j => (T j).obj₃
inst✝ : HasProduct fun j => (shiftFunctor C 1).obj (T j).obj₁
T' : Triangle C
φ : (j : J) → T' ⟶ T j
⊢ T'.mor₃ ≫ (shiftFunctor C 1).map (Pi.lift fun j => (φ j).hom₁) =
    (Pi.lift fun j => (φ j).hom₃) ≫ (productTriangle T).mor₃

Next tactic:
dsimp
/-- A family of morphisms `T' ⟶ T j` lifts to a morphism `T' ⟶ productTriangle T`. -/
@[simps]
def productTriangle.lift {T' : Triangle C} (φ : ∀ j, T' ⟶ T j) :
    T' ⟶ productTriangle T where
  hom₁ := Pi.lift (fun j => (φ j).hom₁)
  hom₂ := Pi.lift (fun j => (φ j).hom₂)
  hom₃ := Pi.lift (fun j => (φ j).hom₃)
  comm₃ := by
    dsimp
    

Proof state:
C : Type u
inst✝⁵ : Category.{v, u} C
inst✝⁴ : HasShift C ℤ
T₁ T₂ T₃ : Triangle C
J : Type u_1
T : J → Triangle C
inst✝³ : HasProduct fun j => (T j).obj₁
inst✝² : HasProduct fun j => (T j).obj₂
inst✝¹ : HasProduct fun j => (T j).obj₃
inst✝ : HasProduct fun j => (shiftFunctor C 1).obj (T j).obj₁
T' : Triangle C
φ : (j : J) → T' ⟶ T j
⊢ T'.mor₃ ≫ (shiftFunctor C 1).map (Pi.lift fun j => (φ j).hom₁) =
    (Pi.lift fun j => (φ j).hom₃) ≫
      (Pi.map fun j => (T j).mor₃) ≫ inv (piComparison (shiftFunctor C 1) fun j => (T j).obj₁)

Next tactic:
rw [← cancel_mono (piComparison _ _), assoc, assoc, assoc, IsIso.inv_hom_id, comp_id]