l3lab/ntp-mathlib huggingface dataset:
/-- 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
    rw [← cancel_mono (piComparison _ _), assoc, assoc, assoc, IsIso.inv_hom_id, comp_id]
    

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₁) ≫ piComparison (shiftFunctor C 1) fun j => (T j).obj₁) =
    (Pi.lift fun j => (φ j).hom₃) ≫ Pi.map fun j => (T j).mor₃

Next tactic:
aesop_cat
/-- The triangle `productTriangle T` satisfies the universal property of the categorical
product of the triangles `T`. -/
def productTriangle.isLimitFan : IsLimit (productTriangle.fan T) :=
  mkFanLimit _ (fun s => productTriangle.lift T s.proj) (fun s j => 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₁
s : Fan T
j : J
⊢ (fun s => lift T (Fan.proj s)) s ≫ Fan.proj (fan T) j = Fan.proj s j

Next tactic:
aesop_cat
/-- The triangle `productTriangle T` satisfies the universal property of the categorical
product of the triangles `T`. -/
def productTriangle.isLimitFan : IsLimit (productTriangle.fan T) :=
  mkFanLimit _ (fun s => productTriangle.lift T s.proj) (fun s j => by aesop_cat) (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₁
⊢ ∀ (s : Fan T) (m : s.pt ⟶ (fan T).pt),
    (∀ (j : J), m ≫ Fan.proj (fan T) j = Fan.proj s j) → m = (fun s => lift T (Fan.proj s)) s

Next tactic:
intro s m hm
/-- The triangle `productTriangle T` satisfies the universal property of the categorical
product of the triangles `T`. -/
def productTriangle.isLimitFan : IsLimit (productTriangle.fan T) :=
  mkFanLimit _ (fun s => productTriangle.lift T s.proj) (fun s j => by aesop_cat) (by
    intro s m hm
    

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₁
s : Fan T
m : s.pt ⟶ (fan T).pt
hm : ∀ (j : J), m ≫ Fan.proj (fan T) j = Fan.proj s j
⊢ m = (fun s => lift T (Fan.proj s)) s

Next tactic:
ext1
/-- The triangle `productTriangle T` satisfies the universal property of the categorical
product of the triangles `T`. -/
def productTriangle.isLimitFan : IsLimit (productTriangle.fan T) :=
  mkFanLimit _ (fun s => productTriangle.lift T s.proj) (fun s j => by aesop_cat) (by
    intro s m hm
    ext1
    

Proof state:
case h₁
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₁
s : Fan T
m : s.pt ⟶ (fan T).pt
hm : ∀ (j : J), m ≫ Fan.proj (fan T) j = Fan.proj s j
⊢ m.hom₁ = ((fun s => lift T (Fan.proj s)) s).hom₁
case h₂
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₁
s : Fan T
m : s.pt ⟶ (fan T).pt
hm : ∀ (j : J), m ≫ Fan.proj (fan T) j = Fan.proj s j
⊢ m.hom₂ = ((fun s => lift T (Fan.proj s)) s).hom₂
case h₃
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₁
s : Fan T
m : s.pt ⟶ (fan T).pt
hm : ∀ (j : J), m ≫ Fan.proj (fan T) j = Fan.proj s j
⊢ m.hom₃ = ((fun s => lift T (Fan.proj s)) s).hom₃

Next tactic:
all_goals
      exact Pi.hom_ext _ _ (fun j => (by simp [← hm]))
/-- The triangle `productTriangle T` satisfies the universal property of the categorical
product of the triangles `T`. -/
def productTriangle.isLimitFan : IsLimit (productTriangle.fan T) :=
  mkFanLimit _ (fun s => productTriangle.lift T s.proj) (fun s j => by aesop_cat) (by
    intro s m hm
    ext1
    all_goals
      

Proof state:
case h₁
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₁
s : Fan T
m : s.pt ⟶ (fan T).pt
hm : ∀ (j : J), m ≫ Fan.proj (fan T) j = Fan.proj s j
⊢ m.hom₁ = ((fun s => lift T (Fan.proj s)) s).hom₁

Next tactic:
exact Pi.hom_ext _ _ (fun j => (by simp [← hm]))
/-- The triangle `productTriangle T` satisfies the universal property of the categorical
product of the triangles `T`. -/
def productTriangle.isLimitFan : IsLimit (productTriangle.fan T) :=
  mkFanLimit _ (fun s => productTriangle.lift T s.proj) (fun s j => by aesop_cat) (by
    intro s m hm
    ext1
    all_goals
      exact Pi.hom_ext _ _ (fun j => (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₁
s : Fan T
m : s.pt ⟶ (fan T).pt
hm : ∀ (j : J), m ≫ Fan.proj (fan T) j = Fan.proj s j
j : J
⊢ m.hom₁ ≫ Pi.π (fun j => (T j).obj₁) j = ((fun s => lift T (Fan.proj s)) s).hom₁ ≫ Pi.π (fun j => (T j).obj₁) j

Next tactic:
simp [← hm]
/-- The triangle `productTriangle T` satisfies the universal property of the categorical
product of the triangles `T`. -/
def productTriangle.isLimitFan : IsLimit (productTriangle.fan T) :=
  mkFanLimit _ (fun s => productTriangle.lift T s.proj) (fun s j => by aesop_cat) (by
    intro s m hm
    ext1
    all_goals
      

Proof state:
case h₂
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₁
s : Fan T
m : s.pt ⟶ (fan T).pt
hm : ∀ (j : J), m ≫ Fan.proj (fan T) j = Fan.proj s j
⊢ m.hom₂ = ((fun s => lift T (Fan.proj s)) s).hom₂

Next tactic:
exact Pi.hom_ext _ _ (fun j => (by simp [← hm]))
/-- The triangle `productTriangle T` satisfies the universal property of the categorical
product of the triangles `T`. -/
def productTriangle.isLimitFan : IsLimit (productTriangle.fan T) :=
  mkFanLimit _ (fun s => productTriangle.lift T s.proj) (fun s j => by aesop_cat) (by
    intro s m hm
    ext1
    all_goals
      exact Pi.hom_ext _ _ (fun j => (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₁
s : Fan T
m : s.pt ⟶ (fan T).pt
hm : ∀ (j : J), m ≫ Fan.proj (fan T) j = Fan.proj s j
j : J
⊢ m.hom₂ ≫ Pi.π (fun j => (T j).obj₂) j = ((fun s => lift T (Fan.proj s)) s).hom₂ ≫ Pi.π (fun j => (T j).obj₂) j

Next tactic:
simp [← hm]
/-- The triangle `productTriangle T` satisfies the universal property of the categorical
product of the triangles `T`. -/
def productTriangle.isLimitFan : IsLimit (productTriangle.fan T) :=
  mkFanLimit _ (fun s => productTriangle.lift T s.proj) (fun s j => by aesop_cat) (by
    intro s m hm
    ext1
    all_goals
      

Proof state:
case h₃
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₁
s : Fan T
m : s.pt ⟶ (fan T).pt
hm : ∀ (j : J), m ≫ Fan.proj (fan T) j = Fan.proj s j
⊢ m.hom₃ = ((fun s => lift T (Fan.proj s)) s).hom₃

Next tactic:
exact Pi.hom_ext _ _ (fun j => (by simp [← hm]))
/-- The triangle `productTriangle T` satisfies the universal property of the categorical
product of the triangles `T`. -/
def productTriangle.isLimitFan : IsLimit (productTriangle.fan T) :=
  mkFanLimit _ (fun s => productTriangle.lift T s.proj) (fun s j => by aesop_cat) (by
    intro s m hm
    ext1
    all_goals
      exact Pi.hom_ext _ _ (fun j => (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₁
s : Fan T
m : s.pt ⟶ (fan T).pt
hm : ∀ (j : J), m ≫ Fan.proj (fan T) j = Fan.proj s j
j : J
⊢ m.hom₃ ≫ Pi.π (fun j => (T j).obj₃) j = ((fun s => lift T (Fan.proj s)) s).hom₃ ≫ Pi.π (fun j => (T j).obj₃) j

Next tactic:
simp [← hm]
lemma productTriangle.zero₃₁ [HasZeroMorphisms C]
    (h : ∀ j, (T j).mor₃ ≫ (T j).mor₁⟦(1 : ℤ)⟧' = 0) :
    (productTriangle T).mor₃ ≫ (productTriangle T).mor₁⟦1⟧' = 0 := 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₁
inst✝ : HasZeroMorphisms C
h : ∀ (j : J), (T j).mor₃ ≫ (shiftFunctor C 1).map (T j).mor₁ = 0
⊢ (productTriangle T).mor₃ ≫ (shiftFunctor C 1).map (productTriangle T).mor₁ = 0

Next tactic:
have : HasProduct (fun j => (T j).obj₂⟦(1 : ℤ)⟧) :=
    ⟨_, isLimitFanMkObjOfIsLimit (shiftFunctor C (1 : ℤ)) _ _
      (productIsProduct (fun j => (T j).obj₂))⟩
lemma productTriangle.zero₃₁ [HasZeroMorphisms C]
    (h : ∀ j, (T j).mor₃ ≫ (T j).mor₁⟦(1 : ℤ)⟧' = 0) :
    (productTriangle T).mor₃ ≫ (productTriangle T).mor₁⟦1⟧' = 0 := by
  have : HasProduct (fun j => (T j).obj₂⟦(1 : ℤ)⟧) :=
    ⟨_, isLimitFanMkObjOfIsLimit (shiftFunctor C (1 : ℤ)) _ _
      (productIsProduct (fun j => (T j).obj₂))⟩
  

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₁
inst✝ : HasZeroMorphisms C
h : ∀ (j : J), (T j).mor₃ ≫ (shiftFunctor C 1).map (T j).mor₁ = 0
this : HasProduct fun j => (shiftFunctor C 1).obj (T j).obj₂
⊢ (productTriangle T).mor₃ ≫ (shiftFunctor C 1).map (productTriangle T).mor₁ = 0

Next tactic:
dsimp
lemma productTriangle.zero₃₁ [HasZeroMorphisms C]
    (h : ∀ j, (T j).mor₃ ≫ (T j).mor₁⟦(1 : ℤ)⟧' = 0) :
    (productTriangle T).mor₃ ≫ (productTriangle T).mor₁⟦1⟧' = 0 := by
  have : HasProduct (fun j => (T j).obj₂⟦(1 : ℤ)⟧) :=
    ⟨_, isLimitFanMkObjOfIsLimit (shiftFunctor C (1 : ℤ)) _ _
      (productIsProduct (fun j => (T j).obj₂))⟩
  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₁
inst✝ : HasZeroMorphisms C
h : ∀ (j : J), (T j).mor₃ ≫ (shiftFunctor C 1).map (T j).mor₁ = 0
this : HasProduct fun j => (shiftFunctor C 1).obj (T j).obj₂
⊢ ((Pi.map fun j => (T j).mor₃) ≫ inv (piComparison (shiftFunctor C 1) fun j => (T j).obj₁)) ≫
      (shiftFunctor C 1).map (Pi.map fun j => (T j).mor₁) =
    0

Next tactic:
change _ ≫ (Pi.lift (fun j => Pi.π _ j ≫ (T j).mor₁))⟦(1 : ℤ)⟧' = 0
lemma productTriangle.zero₃₁ [HasZeroMorphisms C]
    (h : ∀ j, (T j).mor₃ ≫ (T j).mor₁⟦(1 : ℤ)⟧' = 0) :
    (productTriangle T).mor₃ ≫ (productTriangle T).mor₁⟦1⟧' = 0 := by
  have : HasProduct (fun j => (T j).obj₂⟦(1 : ℤ)⟧) :=
    ⟨_, isLimitFanMkObjOfIsLimit (shiftFunctor C (1 : ℤ)) _ _
      (productIsProduct (fun j => (T j).obj₂))⟩
  dsimp
  change _ ≫ (Pi.lift (fun j => Pi.π _ j ≫ (T j).mor₁))⟦(1 : ℤ)⟧' = 0
  

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₁
inst✝ : HasZeroMorphisms C
h : ∀ (j : J), (T j).mor₃ ≫ (shiftFunctor C 1).map (T j).mor₁ = 0
this : HasProduct fun j => (shiftFunctor C 1).obj (T j).obj₂
⊢ ((Pi.map fun j => (T j).mor₃) ≫ inv (piComparison (shiftFunctor C 1) fun j => (T j).obj₁)) ≫
      (shiftFunctor C 1).map (Pi.lift fun j => Pi.π (fun j => (T j).obj₁) j ≫ (T j).mor₁) =
    0

Next tactic:
rw [assoc, ← cancel_mono (piComparison _ _), zero_comp, assoc, assoc]
lemma productTriangle.zero₃₁ [HasZeroMorphisms C]
    (h : ∀ j, (T j).mor₃ ≫ (T j).mor₁⟦(1 : ℤ)⟧' = 0) :
    (productTriangle T).mor₃ ≫ (productTriangle T).mor₁⟦1⟧' = 0 := by
  have : HasProduct (fun j => (T j).obj₂⟦(1 : ℤ)⟧) :=
    ⟨_, isLimitFanMkObjOfIsLimit (shiftFunctor C (1 : ℤ)) _ _
      (productIsProduct (fun j => (T j).obj₂))⟩
  dsimp
  change _ ≫ (Pi.lift (fun j => Pi.π _ j ≫ (T j).mor₁))⟦(1 : ℤ)⟧' = 0
  rw [assoc, ← cancel_mono (piComparison _ _), zero_comp, assoc, 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₁
inst✝ : HasZeroMorphisms C
h : ∀ (j : J), (T j).mor₃ ≫ (shiftFunctor C 1).map (T j).mor₁ = 0
this : HasProduct fun j => (shiftFunctor C 1).obj (T j).obj₂
⊢ ((Pi.map fun j => (T j).mor₃) ≫
      inv (piComparison (shiftFunctor C 1) fun j => (T j).obj₁) ≫
        (shiftFunctor C 1).map (Pi.lift fun j => Pi.π (fun j => (T j).obj₁) j ≫ (T j).mor₁) ≫
          piComparison (shiftFunctor C 1) fun j => (T j).obj₂) =
    0

Next tactic:
ext j
lemma productTriangle.zero₃₁ [HasZeroMorphisms C]
    (h : ∀ j, (T j).mor₃ ≫ (T j).mor₁⟦(1 : ℤ)⟧' = 0) :
    (productTriangle T).mor₃ ≫ (productTriangle T).mor₁⟦1⟧' = 0 := by
  have : HasProduct (fun j => (T j).obj₂⟦(1 : ℤ)⟧) :=
    ⟨_, isLimitFanMkObjOfIsLimit (shiftFunctor C (1 : ℤ)) _ _
      (productIsProduct (fun j => (T j).obj₂))⟩
  dsimp
  change _ ≫ (Pi.lift (fun j => Pi.π _ j ≫ (T j).mor₁))⟦(1 : ℤ)⟧' = 0
  rw [assoc, ← cancel_mono (piComparison _ _), zero_comp, assoc, assoc]
  ext j
  

Proof state:
case h
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₁
inst✝ : HasZeroMorphisms C
h : ∀ (j : J), (T j).mor₃ ≫ (shiftFunctor C 1).map (T j).mor₁ = 0
this : 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.lift fun j => Pi.π (fun j => (T j).obj₁) j ≫ (T j).mor₁) ≫
            piComparison (shiftFunctor C 1) fun j => (T j).obj₂) ≫
      Pi.π (fun b => (shiftFunctor C 1).obj (T b).obj₂) j =
    0 ≫ Pi.π (fun b => (shiftFunctor C 1).obj (T b).obj₂) j

Next tactic:
simp only [map_lift_piComparison, assoc, limit.lift_π, Fan.mk_π_app, zero_comp,
    Functor.map_comp, ← piComparison_comp_π_assoc, IsIso.inv_hom_id_assoc,
    limMap_π_assoc, Discrete.natTrans_app, h j, comp_zero]
theorem nadd_def (a b : Ordinal) :
    a ♯ b = max (blsub.{u, u} a fun a' _ => a' ♯ b) (blsub.{u, u} b fun b' _ => a ♯ b') := by
  

Proof state:
a✝ b✝ c a b : Ordinal.{u}
⊢ a ♯ b = max (blsub a fun a' x => a' ♯ b) (blsub b fun b' x => a ♯ b')

Next tactic:
rw [nadd]
theorem lt_nadd_iff : a < b ♯ c ↔ (∃ b' < b, a ≤ b' ♯ c) ∨ ∃ c' < c, a ≤ b ♯ c' := by
  

Proof state:
a b c : Ordinal.{u}
⊢ a < b ♯ c ↔ (∃ b' < b, a ≤ b' ♯ c) ∨ ∃ c' < c, a ≤ b ♯ c'

Next tactic:
rw [nadd_def]
theorem lt_nadd_iff : a < b ♯ c ↔ (∃ b' < b, a ≤ b' ♯ c) ∨ ∃ c' < c, a ≤ b ♯ c' := by
  rw [nadd_def]
  

Proof state:
a b c : Ordinal.{u}
⊢ a < max (blsub b fun a' x => a' ♯ c) (blsub c fun b' x => b ♯ b') ↔ (∃ b' < b, a ≤ b' ♯ c) ∨ ∃ c' < c, a ≤ b ♯ c'

Next tactic:
simp [lt_blsub_iff]
theorem nadd_le_iff : b ♯ c ≤ a ↔ (∀ b' < b, b' ♯ c < a) ∧ ∀ c' < c, b ♯ c' < a := by
  

Proof state:
a b c : Ordinal.{u}
⊢ b ♯ c ≤ a ↔ (∀ b' < b, b' ♯ c < a) ∧ ∀ c' < c, b ♯ c' < a

Next tactic:
rw [nadd_def]
theorem nadd_le_iff : b ♯ c ≤ a ↔ (∀ b' < b, b' ♯ c < a) ∧ ∀ c' < c, b ♯ c' < a := by
  rw [nadd_def]
  

Proof state:
a b c : Ordinal.{u}
⊢ max (blsub b fun a' x => a' ♯ c) (blsub c fun b' x => b ♯ b') ≤ a ↔ (∀ b' < b, b' ♯ c < a) ∧ ∀ c' < c, b ♯ c' < a

Next tactic:
simp [blsub_le_iff]
theorem nadd_le_nadd_left (h : b ≤ c) (a) : a ♯ b ≤ a ♯ c := by
  

Proof state:
a✝ b c : Ordinal.{u}
h : b ≤ c
a : Ordinal.{u}
⊢ a ♯ b ≤ a ♯ c

Next tactic:
rcases lt_or_eq_of_le h with (h | rfl)
theorem nadd_le_nadd_left (h : b ≤ c) (a) : a ♯ b ≤ a ♯ c := by
  rcases lt_or_eq_of_le h with (h | rfl)
  · 

Proof state:
case inl
a✝ b c : Ordinal.{u}
h✝ : b ≤ c
a : Ordinal.{u}
h : b < c
⊢ a ♯ b ≤ a ♯ c

Next tactic:
exact (nadd_lt_nadd_left h a).le
theorem nadd_le_nadd_left (h : b ≤ c) (a) : a ♯ b ≤ a ♯ c := by
  rcases lt_or_eq_of_le h with (h | rfl)
  · exact (nadd_lt_nadd_left h a).le
  · 

Proof state:
case inr
a✝ b a : Ordinal.{u}
h : b ≤ b
⊢ a ♯ b ≤ a ♯ b

Next tactic:
exact le_rfl
theorem nadd_le_nadd_right (h : b ≤ c) (a) : b ♯ a ≤ c ♯ a := by
  

Proof state:
a✝ b c : Ordinal.{u}
h : b ≤ c
a : Ordinal.{u}
⊢ b ♯ a ≤ c ♯ a

Next tactic:
rcases lt_or_eq_of_le h with (h | rfl)
theorem nadd_le_nadd_right (h : b ≤ c) (a) : b ♯ a ≤ c ♯ a := by
  rcases lt_or_eq_of_le h with (h | rfl)
  · 

Proof state:
case inl
a✝ b c : Ordinal.{u}
h✝ : b ≤ c
a : Ordinal.{u}
h : b < c
⊢ b ♯ a ≤ c ♯ a

Next tactic:
exact (nadd_lt_nadd_right h a).le
theorem nadd_le_nadd_right (h : b ≤ c) (a) : b ♯ a ≤ c ♯ a := by
  rcases lt_or_eq_of_le h with (h | rfl)
  · exact (nadd_lt_nadd_right h a).le
  · 

Proof state:
case inr
a✝ b a : Ordinal.{u}
h : b ≤ b
⊢ b ♯ a ≤ b ♯ a

Next tactic:
exact le_rfl
theorem nadd_comm : ∀ a b, a ♯ b = b ♯ a
  | a, b => by
    

Proof state:
a✝ b✝ c : Ordinal.{u}
a b : Ordinal.{u_1}
⊢ a ♯ b = b ♯ a

Next tactic:
rw [nadd_def, nadd_def, max_comm]
theorem nadd_comm : ∀ a b, a ♯ b = b ♯ a
  | a, b => by
    rw [nadd_def, nadd_def, max_comm]
    

Proof state:
a✝ b✝ c : Ordinal.{u}
a b : Ordinal.{u_1}
⊢ max (blsub b fun b' x => a ♯ b') (blsub a fun a' x => a' ♯ b) =
    max (blsub b fun a' x => a' ♯ a) (blsub a fun b' x => b ♯ b')

Next tactic:
congr
theorem nadd_comm : ∀ a b, a ♯ b = b ♯ a
  | a, b => by
    rw [nadd_def, nadd_def, max_comm]
    congr <;> 

Proof state:
case e_a.e_f
a✝ b✝ c : Ordinal.{u}
a b : Ordinal.{u_1}
⊢ (fun b' x => a ♯ b') = fun a' x => a' ♯ a

Next tactic:
ext
theorem nadd_comm : ∀ a b, a ♯ b = b ♯ a
  | a, b => by
    rw [nadd_def, nadd_def, max_comm]
    congr <;> 

Proof state:
case e_a.e_f
a✝ b✝ c : Ordinal.{u}
a b : Ordinal.{u_1}
⊢ (fun a' x => a' ♯ b) = fun b' x => b ♯ b'

Next tactic:
ext
theorem nadd_comm : ∀ a b, a ♯ b = b ♯ a
  | a, b => by
    rw [nadd_def, nadd_def, max_comm]
    congr <;> ext <;> 

Proof state:
case e_a.e_f.h.h
a✝ b✝ c : Ordinal.{u}
a b x✝¹ : Ordinal.{u_1}
x✝ : x✝¹ < b
⊢ a ♯ x✝¹ = x✝¹ ♯ a

Next tactic:
apply nadd_comm
theorem nadd_comm : ∀ a b, a ♯ b = b ♯ a
  | a, b => by
    rw [nadd_def, nadd_def, max_comm]
    congr <;> ext <;> 

Proof state:
case e_a.e_f.h.h
a✝ b✝ c : Ordinal.{u}
a b x✝¹ : Ordinal.{u_1}
x✝ : x✝¹ < a
⊢ x✝¹ ♯ b = b ♯ x✝¹

Next tactic:
apply nadd_comm
theorem blsub_nadd_of_mono {f : ∀ c < a ♯ b, Ordinal.{max u v}}
    (hf : ∀ {i j} (hi hj), i ≤ j → f i hi ≤ f j hj) :
    -- Porting note: needed to add universe hint blsub.{u,v} in the line below
    blsub.{u,v} _ f =
      max (blsub.{u, v} a fun a' ha' => f (a' ♯ b) <| nadd_lt_nadd_right ha' b)
        (blsub.{u, v} b fun b' hb' => f (a ♯ b') <| nadd_lt_nadd_left hb' a) := by
  

Proof state:
a b c : Ordinal.{u}
f : (c : Ordinal.{u}) → c < a ♯ b → Ordinal.{max u v}
hf : ∀ {i j : Ordinal.{u}} (hi : i < a ♯ b) (hj : j < a ♯ b), i ≤ j → f i hi ≤ f j hj
⊢ blsub (a ♯ b) f =
    max (blsub a fun a' ha' => f (a' ♯ b) (_ : a' ♯ b < a ♯ b)) (blsub b fun b' hb' => f (a ♯ b') (_ : a ♯ b' < a ♯ b))

Next tactic:
apply (blsub_le_iff.2 fun i h => _).antisymm (max_le _ _)
theorem blsub_nadd_of_mono {f : ∀ c < a ♯ b, Ordinal.{max u v}}
    (hf : ∀ {i j} (hi hj), i ≤ j → f i hi ≤ f j hj) :
    -- Porting note: needed to add universe hint blsub.{u,v} in the line below
    blsub.{u,v} _ f =
      max (blsub.{u, v} a fun a' ha' => f (a' ♯ b) <| nadd_lt_nadd_right ha' b)
        (blsub.{u, v} b fun b' hb' => f (a ♯ b') <| nadd_lt_nadd_left hb' a) := by
  apply (blsub_le_iff.2 fun i h => _).antisymm (max_le _ _)
  

Proof state:
a b c : Ordinal.{u}
f : (c : Ordinal.{u}) → c < a ♯ b → Ordinal.{max u v}
hf : ∀ {i j : Ordinal.{u}} (hi : i < a ♯ b) (hj : j < a ♯ b), i ≤ j → f i hi ≤ f j hj
⊢ ∀ (i : Ordinal.{u}) (h : i < a ♯ b),
    f i h <
      max (blsub a fun a' ha' => f (a' ♯ b) (_ : a' ♯ b < a ♯ b))
        (blsub b fun b' hb' => f (a ♯ b') (_ : a ♯ b' < a ♯ b))
a b c : Ordinal.{u}
f : (c : Ordinal.{u}) → c < a ♯ b → Ordinal.{max u v}
hf : ∀ {i j : Ordinal.{u}} (hi : i < a ♯ b) (hj : j < a ♯ b), i ≤ j → f i hi ≤ f j hj
⊢ (blsub a fun a' ha' => f (a' ♯ b) (_ : a' ♯ b < a ♯ b)) ≤ blsub (a ♯ b) f
a b c : Ordinal.{u}
f : (c : Ordinal.{u}) → c < a ♯ b → Ordinal.{max u v}
hf : ∀ {i j : Ordinal.{u}} (hi : i < a ♯ b) (hj : j < a ♯ b), i ≤ j → f i hi ≤ f j hj
⊢ (blsub b fun b' hb' => f (a ♯ b') (_ : a ♯ b' < a ♯ b)) ≤ blsub (a ♯ b) f

Next tactic:
intro i h
theorem blsub_nadd_of_mono {f : ∀ c < a ♯ b, Ordinal.{max u v}}
    (hf : ∀ {i j} (hi hj), i ≤ j → f i hi ≤ f j hj) :
    -- Porting note: needed to add universe hint blsub.{u,v} in the line below
    blsub.{u,v} _ f =
      max (blsub.{u, v} a fun a' ha' => f (a' ♯ b) <| nadd_lt_nadd_right ha' b)
        (blsub.{u, v} b fun b' hb' => f (a ♯ b') <| nadd_lt_nadd_left hb' a) := by
  apply (blsub_le_iff.2 fun i h => _).antisymm (max_le _ _)
  intro i h
  · 

Proof state:
a b c : Ordinal.{u}
f : (c : Ordinal.{u}) → c < a ♯ b → Ordinal.{max u v}
hf : ∀ {i j : Ordinal.{u}} (hi : i < a ♯ b) (hj : j < a ♯ b), i ≤ j → f i hi ≤ f j hj
i : Ordinal.{u}
h : i < a ♯ b
⊢ f i h <
    max (blsub a fun a' ha' => f (a' ♯ b) (_ : a' ♯ b < a ♯ b)) (blsub b fun b' hb' => f (a ♯ b') (_ : a ♯ b' < a ♯ b))

Next tactic:
rcases lt_nadd_iff.1 h with (⟨a', ha', hi⟩ | ⟨b', hb', hi⟩)