l3lab/ntp-mathlib huggingface dataset:
@[reassoc (attr := simp)]
theorem pullbackAssoc_inv_fst_fst [HasPullback ((pullback.snd : Z₁ ⟶ X₂) ≫ f₃) f₄]
    [HasPullback f₁ ((pullback.fst : Z₂ ⟶ X₂) ≫ f₂)] :
    (pullbackAssoc f₁ f₂ f₃ f₄).inv ≫ pullback.fst ≫ pullback.fst = pullback.fst := by
  trans l₁' ≫ pullback.fst
  rw [← Category.assoc]
  

Proof state:
C : Type u
inst✝⁷ : Category.{v, u} C
D : Type u₂
inst✝⁶ : Category.{v₂, u₂} D
W X Y Z X₁ X₂ X₃ Y₁ Y₂ : C
f₁ : X₁ ⟶ Y₁
f₂ : X₂ ⟶ Y₁
f₃ : X₂ ⟶ Y₂
f₄ : X₃ ⟶ Y₂
inst✝⁵ : HasPullback f₁ f₂
inst✝⁴ : HasPullback f₃ f₄
inst✝³ : HasPullback (pullback.snd ≫ sorryAx (sorryAx C true ⟶ Y₂) true) f₄
inst✝² : HasPullback f₁ (pullback.fst ≫ f₂)
inst✝¹ : HasPullback (pullback.snd ≫ f₃) f₄
inst✝ : HasPullback f₁ (pullback.fst ≫ f₂)
⊢ ((pullbackAssoc f₁ f₂ f₃ f₄).inv ≫ pullback.fst) ≫ pullback.fst =
    pullback.lift pullback.fst (pullback.snd ≫ pullback.fst)
        (_ : pullback.fst ≫ f₁ = (pullback.snd ≫ pullback.fst) ≫ f₂) ≫
      pullback.fst
C : Type u
inst✝⁷ : Category.{v, u} C
D : Type u₂
inst✝⁶ : Category.{v₂, u₂} D
W X Y Z X₁ X₂ X₃ Y₁ Y₂ : C
f₁ : X₁ ⟶ Y₁
f₂ : X₂ ⟶ Y₁
f₃ : X₂ ⟶ Y₂
f₄ : X₃ ⟶ Y₂
inst✝⁵ : HasPullback f₁ f₂
inst✝⁴ : HasPullback f₃ f₄
inst✝³ : HasPullback (pullback.snd ≫ sorryAx (sorryAx C true ⟶ Y₂) true) f₄
inst✝² : HasPullback f₁ (pullback.fst ≫ f₂)
inst✝¹ : HasPullback (pullback.snd ≫ f₃) f₄
inst✝ : HasPullback f₁ (pullback.fst ≫ f₂)
⊢ pullback.lift pullback.fst (pullback.snd ≫ pullback.fst)
        (_ : pullback.fst ≫ f₁ = (pullback.snd ≫ pullback.fst) ≫ f₂) ≫
      pullback.fst =
    pullback.fst

Next tactic:
congr 1
@[reassoc (attr := simp)]
theorem pullbackAssoc_inv_fst_fst [HasPullback ((pullback.snd : Z₁ ⟶ X₂) ≫ f₃) f₄]
    [HasPullback f₁ ((pullback.fst : Z₂ ⟶ X₂) ≫ f₂)] :
    (pullbackAssoc f₁ f₂ f₃ f₄).inv ≫ pullback.fst ≫ pullback.fst = pullback.fst := by
  trans l₁' ≫ pullback.fst
  rw [← Category.assoc]
  congr 1
  

Proof state:
case e_a
C : Type u
inst✝⁷ : Category.{v, u} C
D : Type u₂
inst✝⁶ : Category.{v₂, u₂} D
W X Y Z X₁ X₂ X₃ Y₁ Y₂ : C
f₁ : X₁ ⟶ Y₁
f₂ : X₂ ⟶ Y₁
f₃ : X₂ ⟶ Y₂
f₄ : X₃ ⟶ Y₂
inst✝⁵ : HasPullback f₁ f₂
inst✝⁴ : HasPullback f₃ f₄
inst✝³ : HasPullback (pullback.snd ≫ sorryAx (sorryAx C true ⟶ Y₂) true) f₄
inst✝² : HasPullback f₁ (pullback.fst ≫ f₂)
inst✝¹ : HasPullback (pullback.snd ≫ f₃) f₄
inst✝ : HasPullback f₁ (pullback.fst ≫ f₂)
⊢ (pullbackAssoc f₁ f₂ f₃ f₄).inv ≫ pullback.fst =
    pullback.lift pullback.fst (pullback.snd ≫ pullback.fst)
      (_ : pullback.fst ≫ f₁ = (pullback.snd ≫ pullback.fst) ≫ f₂)
C : Type u
inst✝⁷ : Category.{v, u} C
D : Type u₂
inst✝⁶ : Category.{v₂, u₂} D
W X Y Z X₁ X₂ X₃ Y₁ Y₂ : C
f₁ : X₁ ⟶ Y₁
f₂ : X₂ ⟶ Y₁
f₃ : X₂ ⟶ Y₂
f₄ : X₃ ⟶ Y₂
inst✝⁵ : HasPullback f₁ f₂
inst✝⁴ : HasPullback f₃ f₄
inst✝³ : HasPullback (pullback.snd ≫ sorryAx (sorryAx C true ⟶ Y₂) true) f₄
inst✝² : HasPullback f₁ (pullback.fst ≫ f₂)
inst✝¹ : HasPullback (pullback.snd ≫ f₃) f₄
inst✝ : HasPullback f₁ (pullback.fst ≫ f₂)
⊢ pullback.lift pullback.fst (pullback.snd ≫ pullback.fst)
        (_ : pullback.fst ≫ f₁ = (pullback.snd ≫ pullback.fst) ≫ f₂) ≫
      pullback.fst =
    pullback.fst

Next tactic:
exact IsLimit.conePointUniqueUpToIso_inv_comp _ _ WalkingCospan.left
@[reassoc (attr := simp)]
theorem pullbackAssoc_inv_fst_fst [HasPullback ((pullback.snd : Z₁ ⟶ X₂) ≫ f₃) f₄]
    [HasPullback f₁ ((pullback.fst : Z₂ ⟶ X₂) ≫ f₂)] :
    (pullbackAssoc f₁ f₂ f₃ f₄).inv ≫ pullback.fst ≫ pullback.fst = pullback.fst := by
  trans l₁' ≫ pullback.fst
  rw [← Category.assoc]
  congr 1
  exact IsLimit.conePointUniqueUpToIso_inv_comp _ _ WalkingCospan.left
  

Proof state:
C : Type u
inst✝⁷ : Category.{v, u} C
D : Type u₂
inst✝⁶ : Category.{v₂, u₂} D
W X Y Z X₁ X₂ X₃ Y₁ Y₂ : C
f₁ : X₁ ⟶ Y₁
f₂ : X₂ ⟶ Y₁
f₃ : X₂ ⟶ Y₂
f₄ : X₃ ⟶ Y₂
inst✝⁵ : HasPullback f₁ f₂
inst✝⁴ : HasPullback f₃ f₄
inst✝³ : HasPullback (pullback.snd ≫ sorryAx (sorryAx C true ⟶ Y₂) true) f₄
inst✝² : HasPullback f₁ (pullback.fst ≫ f₂)
inst✝¹ : HasPullback (pullback.snd ≫ f₃) f₄
inst✝ : HasPullback f₁ (pullback.fst ≫ f₂)
⊢ pullback.lift pullback.fst (pullback.snd ≫ pullback.fst)
        (_ : pullback.fst ≫ f₁ = (pullback.snd ≫ pullback.fst) ≫ f₂) ≫
      pullback.fst =
    pullback.fst

Next tactic:
exact pullback.lift_fst _ _ _
@[reassoc (attr := simp)]
theorem pullbackAssoc_hom_fst [HasPullback ((pullback.snd : Z₁ ⟶ X₂) ≫ f₃) f₄]
    [HasPullback f₁ ((pullback.fst : Z₂ ⟶ X₂) ≫ f₂)] :
    (pullbackAssoc f₁ f₂ f₃ f₄).hom ≫ pullback.fst = pullback.fst ≫ pullback.fst := by
  

Proof state:
C : Type u
inst✝⁷ : Category.{v, u} C
D : Type u₂
inst✝⁶ : Category.{v₂, u₂} D
W X Y Z X₁ X₂ X₃ Y₁ Y₂ : C
f₁ : X₁ ⟶ Y₁
f₂ : X₂ ⟶ Y₁
f₃ : X₂ ⟶ Y₂
f₄ : X₃ ⟶ Y₂
inst✝⁵ : HasPullback f₁ f₂
inst✝⁴ : HasPullback f₃ f₄
inst✝³ : HasPullback (pullback.snd ≫ sorryAx (sorryAx C true ⟶ Y₂) true) f₄
inst✝² : HasPullback f₁ (pullback.fst ≫ f₂)
inst✝¹ : HasPullback (pullback.snd ≫ f₃) f₄
inst✝ : HasPullback f₁ (pullback.fst ≫ f₂)
⊢ (pullbackAssoc f₁ f₂ f₃ f₄).hom ≫ pullback.fst = pullback.fst ≫ pullback.fst

Next tactic:
rw [← Iso.eq_inv_comp, pullbackAssoc_inv_fst_fst]
@[reassoc (attr := simp)]
theorem pullbackAssoc_hom_snd_fst [HasPullback ((pullback.snd : Z₁ ⟶ X₂) ≫ f₃) f₄]
    [HasPullback f₁ ((pullback.fst : Z₂ ⟶ X₂) ≫ f₂)] : (pullbackAssoc f₁ f₂ f₃ f₄).hom ≫
    pullback.snd ≫ pullback.fst = pullback.fst ≫ pullback.snd := by
  

Proof state:
C : Type u
inst✝⁷ : Category.{v, u} C
D : Type u₂
inst✝⁶ : Category.{v₂, u₂} D
W X Y Z X₁ X₂ X₃ Y₁ Y₂ : C
f₁ : X₁ ⟶ Y₁
f₂ : X₂ ⟶ Y₁
f₃ : X₂ ⟶ Y₂
f₄ : X₃ ⟶ Y₂
inst✝⁵ : HasPullback f₁ f₂
inst✝⁴ : HasPullback f₃ f₄
inst✝³ : HasPullback (pullback.snd ≫ sorryAx (sorryAx C true ⟶ Y₂) true) f₄
inst✝² : HasPullback f₁ (pullback.fst ≫ f₂)
inst✝¹ : HasPullback (pullback.snd ≫ f₃) f₄
inst✝ : HasPullback f₁ (pullback.fst ≫ f₂)
⊢ (pullbackAssoc f₁ f₂ f₃ f₄).hom ≫ pullback.snd ≫ pullback.fst = pullback.fst ≫ pullback.snd

Next tactic:
trans l₂ ≫ pullback.fst
@[reassoc (attr := simp)]
theorem pullbackAssoc_hom_snd_fst [HasPullback ((pullback.snd : Z₁ ⟶ X₂) ≫ f₃) f₄]
    [HasPullback f₁ ((pullback.fst : Z₂ ⟶ X₂) ≫ f₂)] : (pullbackAssoc f₁ f₂ f₃ f₄).hom ≫
    pullback.snd ≫ pullback.fst = pullback.fst ≫ pullback.snd := by
  trans l₂ ≫ pullback.fst
  

Proof state:
C : Type u
inst✝⁷ : Category.{v, u} C
D : Type u₂
inst✝⁶ : Category.{v₂, u₂} D
W X Y Z X₁ X₂ X₃ Y₁ Y₂ : C
f₁ : X₁ ⟶ Y₁
f₂ : X₂ ⟶ Y₁
f₃ : X₂ ⟶ Y₂
f₄ : X₃ ⟶ Y₂
inst✝⁵ : HasPullback f₁ f₂
inst✝⁴ : HasPullback f₃ f₄
inst✝³ : HasPullback (pullback.snd ≫ sorryAx (sorryAx C true ⟶ Y₂) true) f₄
inst✝² : HasPullback f₁ (pullback.fst ≫ f₂)
inst✝¹ : HasPullback (pullback.snd ≫ f₃) f₄
inst✝ : HasPullback f₁ (pullback.fst ≫ f₂)
⊢ (pullbackAssoc f₁ f₂ f₃ f₄).hom ≫ pullback.snd ≫ pullback.fst =
    pullback.lift (pullback.fst ≫ pullback.snd) pullback.snd
        (_ : (pullback.fst ≫ pullback.snd) ≫ f₃ = pullback.snd ≫ f₄) ≫
      pullback.fst
C : Type u
inst✝⁷ : Category.{v, u} C
D : Type u₂
inst✝⁶ : Category.{v₂, u₂} D
W X Y Z X₁ X₂ X₃ Y₁ Y₂ : C
f₁ : X₁ ⟶ Y₁
f₂ : X₂ ⟶ Y₁
f₃ : X₂ ⟶ Y₂
f₄ : X₃ ⟶ Y₂
inst✝⁵ : HasPullback f₁ f₂
inst✝⁴ : HasPullback f₃ f₄
inst✝³ : HasPullback (pullback.snd ≫ sorryAx (sorryAx C true ⟶ Y₂) true) f₄
inst✝² : HasPullback f₁ (pullback.fst ≫ f₂)
inst✝¹ : HasPullback (pullback.snd ≫ f₃) f₄
inst✝ : HasPullback f₁ (pullback.fst ≫ f₂)
⊢ pullback.lift (pullback.fst ≫ pullback.snd) pullback.snd
        (_ : (pullback.fst ≫ pullback.snd) ≫ f₃ = pullback.snd ≫ f₄) ≫
      pullback.fst =
    pullback.fst ≫ pullback.snd

Next tactic:
rw [← Category.assoc]
@[reassoc (attr := simp)]
theorem pullbackAssoc_hom_snd_fst [HasPullback ((pullback.snd : Z₁ ⟶ X₂) ≫ f₃) f₄]
    [HasPullback f₁ ((pullback.fst : Z₂ ⟶ X₂) ≫ f₂)] : (pullbackAssoc f₁ f₂ f₃ f₄).hom ≫
    pullback.snd ≫ pullback.fst = pullback.fst ≫ pullback.snd := by
  trans l₂ ≫ pullback.fst
  rw [← Category.assoc]
  

Proof state:
C : Type u
inst✝⁷ : Category.{v, u} C
D : Type u₂
inst✝⁶ : Category.{v₂, u₂} D
W X Y Z X₁ X₂ X₃ Y₁ Y₂ : C
f₁ : X₁ ⟶ Y₁
f₂ : X₂ ⟶ Y₁
f₃ : X₂ ⟶ Y₂
f₄ : X₃ ⟶ Y₂
inst✝⁵ : HasPullback f₁ f₂
inst✝⁴ : HasPullback f₃ f₄
inst✝³ : HasPullback (pullback.snd ≫ sorryAx (sorryAx C true ⟶ Y₂) true) f₄
inst✝² : HasPullback f₁ (pullback.fst ≫ f₂)
inst✝¹ : HasPullback (pullback.snd ≫ f₃) f₄
inst✝ : HasPullback f₁ (pullback.fst ≫ f₂)
⊢ ((pullbackAssoc f₁ f₂ f₃ f₄).hom ≫ pullback.snd) ≫ pullback.fst =
    pullback.lift (pullback.fst ≫ pullback.snd) pullback.snd
        (_ : (pullback.fst ≫ pullback.snd) ≫ f₃ = pullback.snd ≫ f₄) ≫
      pullback.fst
C : Type u
inst✝⁷ : Category.{v, u} C
D : Type u₂
inst✝⁶ : Category.{v₂, u₂} D
W X Y Z X₁ X₂ X₃ Y₁ Y₂ : C
f₁ : X₁ ⟶ Y₁
f₂ : X₂ ⟶ Y₁
f₃ : X₂ ⟶ Y₂
f₄ : X₃ ⟶ Y₂
inst✝⁵ : HasPullback f₁ f₂
inst✝⁴ : HasPullback f₃ f₄
inst✝³ : HasPullback (pullback.snd ≫ sorryAx (sorryAx C true ⟶ Y₂) true) f₄
inst✝² : HasPullback f₁ (pullback.fst ≫ f₂)
inst✝¹ : HasPullback (pullback.snd ≫ f₃) f₄
inst✝ : HasPullback f₁ (pullback.fst ≫ f₂)
⊢ pullback.lift (pullback.fst ≫ pullback.snd) pullback.snd
        (_ : (pullback.fst ≫ pullback.snd) ≫ f₃ = pullback.snd ≫ f₄) ≫
      pullback.fst =
    pullback.fst ≫ pullback.snd

Next tactic:
congr 1
@[reassoc (attr := simp)]
theorem pullbackAssoc_hom_snd_fst [HasPullback ((pullback.snd : Z₁ ⟶ X₂) ≫ f₃) f₄]
    [HasPullback f₁ ((pullback.fst : Z₂ ⟶ X₂) ≫ f₂)] : (pullbackAssoc f₁ f₂ f₃ f₄).hom ≫
    pullback.snd ≫ pullback.fst = pullback.fst ≫ pullback.snd := by
  trans l₂ ≫ pullback.fst
  rw [← Category.assoc]
  congr 1
  

Proof state:
case e_a
C : Type u
inst✝⁷ : Category.{v, u} C
D : Type u₂
inst✝⁶ : Category.{v₂, u₂} D
W X Y Z X₁ X₂ X₃ Y₁ Y₂ : C
f₁ : X₁ ⟶ Y₁
f₂ : X₂ ⟶ Y₁
f₃ : X₂ ⟶ Y₂
f₄ : X₃ ⟶ Y₂
inst✝⁵ : HasPullback f₁ f₂
inst✝⁴ : HasPullback f₃ f₄
inst✝³ : HasPullback (pullback.snd ≫ sorryAx (sorryAx C true ⟶ Y₂) true) f₄
inst✝² : HasPullback f₁ (pullback.fst ≫ f₂)
inst✝¹ : HasPullback (pullback.snd ≫ f₃) f₄
inst✝ : HasPullback f₁ (pullback.fst ≫ f₂)
⊢ (pullbackAssoc f₁ f₂ f₃ f₄).hom ≫ pullback.snd =
    pullback.lift (pullback.fst ≫ pullback.snd) pullback.snd
      (_ : (pullback.fst ≫ pullback.snd) ≫ f₃ = pullback.snd ≫ f₄)
C : Type u
inst✝⁷ : Category.{v, u} C
D : Type u₂
inst✝⁶ : Category.{v₂, u₂} D
W X Y Z X₁ X₂ X₃ Y₁ Y₂ : C
f₁ : X₁ ⟶ Y₁
f₂ : X₂ ⟶ Y₁
f₃ : X₂ ⟶ Y₂
f₄ : X₃ ⟶ Y₂
inst✝⁵ : HasPullback f₁ f₂
inst✝⁴ : HasPullback f₃ f₄
inst✝³ : HasPullback (pullback.snd ≫ sorryAx (sorryAx C true ⟶ Y₂) true) f₄
inst✝² : HasPullback f₁ (pullback.fst ≫ f₂)
inst✝¹ : HasPullback (pullback.snd ≫ f₃) f₄
inst✝ : HasPullback f₁ (pullback.fst ≫ f₂)
⊢ pullback.lift (pullback.fst ≫ pullback.snd) pullback.snd
        (_ : (pullback.fst ≫ pullback.snd) ≫ f₃ = pullback.snd ≫ f₄) ≫
      pullback.fst =
    pullback.fst ≫ pullback.snd

Next tactic:
exact IsLimit.conePointUniqueUpToIso_hom_comp _ _ WalkingCospan.right
@[reassoc (attr := simp)]
theorem pullbackAssoc_hom_snd_fst [HasPullback ((pullback.snd : Z₁ ⟶ X₂) ≫ f₃) f₄]
    [HasPullback f₁ ((pullback.fst : Z₂ ⟶ X₂) ≫ f₂)] : (pullbackAssoc f₁ f₂ f₃ f₄).hom ≫
    pullback.snd ≫ pullback.fst = pullback.fst ≫ pullback.snd := by
  trans l₂ ≫ pullback.fst
  rw [← Category.assoc]
  congr 1
  exact IsLimit.conePointUniqueUpToIso_hom_comp _ _ WalkingCospan.right
  

Proof state:
C : Type u
inst✝⁷ : Category.{v, u} C
D : Type u₂
inst✝⁶ : Category.{v₂, u₂} D
W X Y Z X₁ X₂ X₃ Y₁ Y₂ : C
f₁ : X₁ ⟶ Y₁
f₂ : X₂ ⟶ Y₁
f₃ : X₂ ⟶ Y₂
f₄ : X₃ ⟶ Y₂
inst✝⁵ : HasPullback f₁ f₂
inst✝⁴ : HasPullback f₃ f₄
inst✝³ : HasPullback (pullback.snd ≫ sorryAx (sorryAx C true ⟶ Y₂) true) f₄
inst✝² : HasPullback f₁ (pullback.fst ≫ f₂)
inst✝¹ : HasPullback (pullback.snd ≫ f₃) f₄
inst✝ : HasPullback f₁ (pullback.fst ≫ f₂)
⊢ pullback.lift (pullback.fst ≫ pullback.snd) pullback.snd
        (_ : (pullback.fst ≫ pullback.snd) ≫ f₃ = pullback.snd ≫ f₄) ≫
      pullback.fst =
    pullback.fst ≫ pullback.snd

Next tactic:
exact pullback.lift_fst _ _ _
@[reassoc (attr := simp)]
theorem pullbackAssoc_hom_snd_snd [HasPullback ((pullback.snd : Z₁ ⟶ X₂) ≫ f₃) f₄]
    [HasPullback f₁ ((pullback.fst : Z₂ ⟶ X₂) ≫ f₂)] :
    (pullbackAssoc f₁ f₂ f₃ f₄).hom ≫ pullback.snd ≫ pullback.snd = pullback.snd := by
  

Proof state:
C : Type u
inst✝⁷ : Category.{v, u} C
D : Type u₂
inst✝⁶ : Category.{v₂, u₂} D
W X Y Z X₁ X₂ X₃ Y₁ Y₂ : C
f₁ : X₁ ⟶ Y₁
f₂ : X₂ ⟶ Y₁
f₃ : X₂ ⟶ Y₂
f₄ : X₃ ⟶ Y₂
inst✝⁵ : HasPullback f₁ f₂
inst✝⁴ : HasPullback f₃ f₄
inst✝³ : HasPullback (pullback.snd ≫ sorryAx (sorryAx C true ⟶ Y₂) true) f₄
inst✝² : HasPullback f₁ (pullback.fst ≫ f₂)
inst✝¹ : HasPullback (pullback.snd ≫ f₃) f₄
inst✝ : HasPullback f₁ (pullback.fst ≫ f₂)
⊢ (pullbackAssoc f₁ f₂ f₃ f₄).hom ≫ pullback.snd ≫ pullback.snd = pullback.snd

Next tactic:
trans l₂ ≫ pullback.snd
@[reassoc (attr := simp)]
theorem pullbackAssoc_hom_snd_snd [HasPullback ((pullback.snd : Z₁ ⟶ X₂) ≫ f₃) f₄]
    [HasPullback f₁ ((pullback.fst : Z₂ ⟶ X₂) ≫ f₂)] :
    (pullbackAssoc f₁ f₂ f₃ f₄).hom ≫ pullback.snd ≫ pullback.snd = pullback.snd := by
  trans l₂ ≫ pullback.snd
  

Proof state:
C : Type u
inst✝⁷ : Category.{v, u} C
D : Type u₂
inst✝⁶ : Category.{v₂, u₂} D
W X Y Z X₁ X₂ X₃ Y₁ Y₂ : C
f₁ : X₁ ⟶ Y₁
f₂ : X₂ ⟶ Y₁
f₃ : X₂ ⟶ Y₂
f₄ : X₃ ⟶ Y₂
inst✝⁵ : HasPullback f₁ f₂
inst✝⁴ : HasPullback f₃ f₄
inst✝³ : HasPullback (pullback.snd ≫ sorryAx (sorryAx C true ⟶ Y₂) true) f₄
inst✝² : HasPullback f₁ (pullback.fst ≫ f₂)
inst✝¹ : HasPullback (pullback.snd ≫ f₃) f₄
inst✝ : HasPullback f₁ (pullback.fst ≫ f₂)
⊢ (pullbackAssoc f₁ f₂ f₃ f₄).hom ≫ pullback.snd ≫ pullback.snd =
    pullback.lift (pullback.fst ≫ pullback.snd) pullback.snd
        (_ : (pullback.fst ≫ pullback.snd) ≫ f₃ = pullback.snd ≫ f₄) ≫
      pullback.snd
C : Type u
inst✝⁷ : Category.{v, u} C
D : Type u₂
inst✝⁶ : Category.{v₂, u₂} D
W X Y Z X₁ X₂ X₃ Y₁ Y₂ : C
f₁ : X₁ ⟶ Y₁
f₂ : X₂ ⟶ Y₁
f₃ : X₂ ⟶ Y₂
f₄ : X₃ ⟶ Y₂
inst✝⁵ : HasPullback f₁ f₂
inst✝⁴ : HasPullback f₃ f₄
inst✝³ : HasPullback (pullback.snd ≫ sorryAx (sorryAx C true ⟶ Y₂) true) f₄
inst✝² : HasPullback f₁ (pullback.fst ≫ f₂)
inst✝¹ : HasPullback (pullback.snd ≫ f₃) f₄
inst✝ : HasPullback f₁ (pullback.fst ≫ f₂)
⊢ pullback.lift (pullback.fst ≫ pullback.snd) pullback.snd
        (_ : (pullback.fst ≫ pullback.snd) ≫ f₃ = pullback.snd ≫ f₄) ≫
      pullback.snd =
    pullback.snd

Next tactic:
rw [← Category.assoc]
@[reassoc (attr := simp)]
theorem pullbackAssoc_hom_snd_snd [HasPullback ((pullback.snd : Z₁ ⟶ X₂) ≫ f₃) f₄]
    [HasPullback f₁ ((pullback.fst : Z₂ ⟶ X₂) ≫ f₂)] :
    (pullbackAssoc f₁ f₂ f₃ f₄).hom ≫ pullback.snd ≫ pullback.snd = pullback.snd := by
  trans l₂ ≫ pullback.snd
  rw [← Category.assoc]
  

Proof state:
C : Type u
inst✝⁷ : Category.{v, u} C
D : Type u₂
inst✝⁶ : Category.{v₂, u₂} D
W X Y Z X₁ X₂ X₃ Y₁ Y₂ : C
f₁ : X₁ ⟶ Y₁
f₂ : X₂ ⟶ Y₁
f₃ : X₂ ⟶ Y₂
f₄ : X₃ ⟶ Y₂
inst✝⁵ : HasPullback f₁ f₂
inst✝⁴ : HasPullback f₃ f₄
inst✝³ : HasPullback (pullback.snd ≫ sorryAx (sorryAx C true ⟶ Y₂) true) f₄
inst✝² : HasPullback f₁ (pullback.fst ≫ f₂)
inst✝¹ : HasPullback (pullback.snd ≫ f₃) f₄
inst✝ : HasPullback f₁ (pullback.fst ≫ f₂)
⊢ ((pullbackAssoc f₁ f₂ f₃ f₄).hom ≫ pullback.snd) ≫ pullback.snd =
    pullback.lift (pullback.fst ≫ pullback.snd) pullback.snd
        (_ : (pullback.fst ≫ pullback.snd) ≫ f₃ = pullback.snd ≫ f₄) ≫
      pullback.snd
C : Type u
inst✝⁷ : Category.{v, u} C
D : Type u₂
inst✝⁶ : Category.{v₂, u₂} D
W X Y Z X₁ X₂ X₃ Y₁ Y₂ : C
f₁ : X₁ ⟶ Y₁
f₂ : X₂ ⟶ Y₁
f₃ : X₂ ⟶ Y₂
f₄ : X₃ ⟶ Y₂
inst✝⁵ : HasPullback f₁ f₂
inst✝⁴ : HasPullback f₃ f₄
inst✝³ : HasPullback (pullback.snd ≫ sorryAx (sorryAx C true ⟶ Y₂) true) f₄
inst✝² : HasPullback f₁ (pullback.fst ≫ f₂)
inst✝¹ : HasPullback (pullback.snd ≫ f₃) f₄
inst✝ : HasPullback f₁ (pullback.fst ≫ f₂)
⊢ pullback.lift (pullback.fst ≫ pullback.snd) pullback.snd
        (_ : (pullback.fst ≫ pullback.snd) ≫ f₃ = pullback.snd ≫ f₄) ≫
      pullback.snd =
    pullback.snd

Next tactic:
congr 1
@[reassoc (attr := simp)]
theorem pullbackAssoc_hom_snd_snd [HasPullback ((pullback.snd : Z₁ ⟶ X₂) ≫ f₃) f₄]
    [HasPullback f₁ ((pullback.fst : Z₂ ⟶ X₂) ≫ f₂)] :
    (pullbackAssoc f₁ f₂ f₃ f₄).hom ≫ pullback.snd ≫ pullback.snd = pullback.snd := by
  trans l₂ ≫ pullback.snd
  rw [← Category.assoc]
  congr 1
  

Proof state:
case e_a
C : Type u
inst✝⁷ : Category.{v, u} C
D : Type u₂
inst✝⁶ : Category.{v₂, u₂} D
W X Y Z X₁ X₂ X₃ Y₁ Y₂ : C
f₁ : X₁ ⟶ Y₁
f₂ : X₂ ⟶ Y₁
f₃ : X₂ ⟶ Y₂
f₄ : X₃ ⟶ Y₂
inst✝⁵ : HasPullback f₁ f₂
inst✝⁴ : HasPullback f₃ f₄
inst✝³ : HasPullback (pullback.snd ≫ sorryAx (sorryAx C true ⟶ Y₂) true) f₄
inst✝² : HasPullback f₁ (pullback.fst ≫ f₂)
inst✝¹ : HasPullback (pullback.snd ≫ f₃) f₄
inst✝ : HasPullback f₁ (pullback.fst ≫ f₂)
⊢ (pullbackAssoc f₁ f₂ f₃ f₄).hom ≫ pullback.snd =
    pullback.lift (pullback.fst ≫ pullback.snd) pullback.snd
      (_ : (pullback.fst ≫ pullback.snd) ≫ f₃ = pullback.snd ≫ f₄)
C : Type u
inst✝⁷ : Category.{v, u} C
D : Type u₂
inst✝⁶ : Category.{v₂, u₂} D
W X Y Z X₁ X₂ X₃ Y₁ Y₂ : C
f₁ : X₁ ⟶ Y₁
f₂ : X₂ ⟶ Y₁
f₃ : X₂ ⟶ Y₂
f₄ : X₃ ⟶ Y₂
inst✝⁵ : HasPullback f₁ f₂
inst✝⁴ : HasPullback f₃ f₄
inst✝³ : HasPullback (pullback.snd ≫ sorryAx (sorryAx C true ⟶ Y₂) true) f₄
inst✝² : HasPullback f₁ (pullback.fst ≫ f₂)
inst✝¹ : HasPullback (pullback.snd ≫ f₃) f₄
inst✝ : HasPullback f₁ (pullback.fst ≫ f₂)
⊢ pullback.lift (pullback.fst ≫ pullback.snd) pullback.snd
        (_ : (pullback.fst ≫ pullback.snd) ≫ f₃ = pullback.snd ≫ f₄) ≫
      pullback.snd =
    pullback.snd

Next tactic:
exact IsLimit.conePointUniqueUpToIso_hom_comp _ _ WalkingCospan.right
@[reassoc (attr := simp)]
theorem pullbackAssoc_hom_snd_snd [HasPullback ((pullback.snd : Z₁ ⟶ X₂) ≫ f₃) f₄]
    [HasPullback f₁ ((pullback.fst : Z₂ ⟶ X₂) ≫ f₂)] :
    (pullbackAssoc f₁ f₂ f₃ f₄).hom ≫ pullback.snd ≫ pullback.snd = pullback.snd := by
  trans l₂ ≫ pullback.snd
  rw [← Category.assoc]
  congr 1
  exact IsLimit.conePointUniqueUpToIso_hom_comp _ _ WalkingCospan.right
  

Proof state:
C : Type u
inst✝⁷ : Category.{v, u} C
D : Type u₂
inst✝⁶ : Category.{v₂, u₂} D
W X Y Z X₁ X₂ X₃ Y₁ Y₂ : C
f₁ : X₁ ⟶ Y₁
f₂ : X₂ ⟶ Y₁
f₃ : X₂ ⟶ Y₂
f₄ : X₃ ⟶ Y₂
inst✝⁵ : HasPullback f₁ f₂
inst✝⁴ : HasPullback f₃ f₄
inst✝³ : HasPullback (pullback.snd ≫ sorryAx (sorryAx C true ⟶ Y₂) true) f₄
inst✝² : HasPullback f₁ (pullback.fst ≫ f₂)
inst✝¹ : HasPullback (pullback.snd ≫ f₃) f₄
inst✝ : HasPullback f₁ (pullback.fst ≫ f₂)
⊢ pullback.lift (pullback.fst ≫ pullback.snd) pullback.snd
        (_ : (pullback.fst ≫ pullback.snd) ≫ f₃ = pullback.snd ≫ f₄) ≫
      pullback.snd =
    pullback.snd

Next tactic:
exact pullback.lift_snd _ _ _
@[reassoc (attr := simp)]
theorem pullbackAssoc_inv_fst_snd [HasPullback ((pullback.snd : Z₁ ⟶ X₂) ≫ f₃) f₄]
    [HasPullback f₁ ((pullback.fst : Z₂ ⟶ X₂) ≫ f₂)] :
    (pullbackAssoc f₁ f₂ f₃ f₄).inv ≫ pullback.fst ≫ pullback.snd = pullback.snd ≫ pullback.fst :=
  by 

Proof state:
C : Type u
inst✝⁷ : Category.{v, u} C
D : Type u₂
inst✝⁶ : Category.{v₂, u₂} D
W X Y Z X₁ X₂ X₃ Y₁ Y₂ : C
f₁ : X₁ ⟶ Y₁
f₂ : X₂ ⟶ Y₁
f₃ : X₂ ⟶ Y₂
f₄ : X₃ ⟶ Y₂
inst✝⁵ : HasPullback f₁ f₂
inst✝⁴ : HasPullback f₃ f₄
inst✝³ : HasPullback (pullback.snd ≫ sorryAx (sorryAx C true ⟶ Y₂) true) f₄
inst✝² : HasPullback f₁ (pullback.fst ≫ f₂)
inst✝¹ : HasPullback (pullback.snd ≫ f₃) f₄
inst✝ : HasPullback f₁ (pullback.fst ≫ f₂)
⊢ (pullbackAssoc f₁ f₂ f₃ f₄).inv ≫ pullback.fst ≫ pullback.snd = pullback.snd ≫ pullback.fst

Next tactic:
rw [Iso.inv_comp_eq, pullbackAssoc_hom_snd_fst]
@[reassoc (attr := simp)]
theorem pullbackAssoc_inv_snd [HasPullback ((pullback.snd : Z₁ ⟶ X₂) ≫ f₃) f₄]
    [HasPullback f₁ ((pullback.fst : Z₂ ⟶ X₂) ≫ f₂)] :
    (pullbackAssoc f₁ f₂ f₃ f₄).inv ≫ pullback.snd = pullback.snd ≫ pullback.snd := by
  

Proof state:
C : Type u
inst✝⁷ : Category.{v, u} C
D : Type u₂
inst✝⁶ : Category.{v₂, u₂} D
W X Y Z X₁ X₂ X₃ Y₁ Y₂ : C
f₁ : X₁ ⟶ Y₁
f₂ : X₂ ⟶ Y₁
f₃ : X₂ ⟶ Y₂
f₄ : X₃ ⟶ Y₂
inst✝⁵ : HasPullback f₁ f₂
inst✝⁴ : HasPullback f₃ f₄
inst✝³ : HasPullback (pullback.snd ≫ sorryAx (sorryAx C true ⟶ Y₂) true) f₄
inst✝² : HasPullback f₁ (pullback.fst ≫ f₂)
inst✝¹ : HasPullback (pullback.snd ≫ f₃) f₄
inst✝ : HasPullback f₁ (pullback.fst ≫ f₂)
⊢ (pullbackAssoc f₁ f₂ f₃ f₄).inv ≫ pullback.snd = pullback.snd ≫ pullback.snd

Next tactic:
rw [Iso.inv_comp_eq, pullbackAssoc_hom_snd_snd]
/-- `(X₁ ⨿[Z₁] X₂) ⨿[Z₂] X₃` is the pushout `(X₁ ⨿[Z₁] X₂) ×[X₂] (X₂ ⨿[Z₂] X₃)`. -/
def pushoutPushoutLeftIsPushout [HasPushout (g₃ ≫ f₂) g₄] :
    IsColimit
      (PushoutCocone.mk l₁' l₂' (show f₂ ≫ l₁' = f₃ ≫ l₂' from (pushout.inl_desc _ _ _).symm)) := by
  

Proof state:
C : Type u
inst✝⁴ : Category.{v, u} C
D : Type u₂
inst✝³ : Category.{v₂, u₂} D
W X Y Z X₁ X₂ X₃ Z₁ Z₂ : C
g₁ : Z₁ ⟶ X₁
g₂ : Z₁ ⟶ X₂
g₃ : Z₂ ⟶ X₂
g₄ : Z₂ ⟶ X₃
inst✝² : HasPushout g₁ g₂
inst✝¹ : HasPushout g₃ g₄
inst✝ : HasPushout (g₃ ≫ pushout.inr) g₄
⊢ IsColimit
    (PushoutCocone.mk pushout.inl
      (pushout.desc (pushout.inr ≫ pushout.inl) pushout.inr (_ : g₃ ≫ pushout.inr ≫ pushout.inl = g₄ ≫ pushout.inr))
      (_ :
        pushout.inr ≫ pushout.inl =
          pushout.inl ≫
            pushout.desc (pushout.inr ≫ pushout.inl) pushout.inr
              (_ : g₃ ≫ pushout.inr ≫ pushout.inl = g₄ ≫ pushout.inr)))

Next tactic:
apply PushoutCocone.flipIsColimit
/-- `(X₁ ⨿[Z₁] X₂) ⨿[Z₂] X₃` is the pushout `(X₁ ⨿[Z₁] X₂) ×[X₂] (X₂ ⨿[Z₂] X₃)`. -/
def pushoutPushoutLeftIsPushout [HasPushout (g₃ ≫ f₂) g₄] :
    IsColimit
      (PushoutCocone.mk l₁' l₂' (show f₂ ≫ l₁' = f₃ ≫ l₂' from (pushout.inl_desc _ _ _).symm)) := by
  apply PushoutCocone.flipIsColimit
  

Proof state:
case t
C : Type u
inst✝⁴ : Category.{v, u} C
D : Type u₂
inst✝³ : Category.{v₂, u₂} D
W X Y Z X₁ X₂ X₃ Z₁ Z₂ : C
g₁ : Z₁ ⟶ X₁
g₂ : Z₁ ⟶ X₂
g₃ : Z₂ ⟶ X₂
g₄ : Z₂ ⟶ X₃
inst✝² : HasPushout g₁ g₂
inst✝¹ : HasPushout g₃ g₄
inst✝ : HasPushout (g₃ ≫ pushout.inr) g₄
⊢ IsColimit
    (PushoutCocone.mk
      (pushout.desc (pushout.inr ≫ pushout.inl) pushout.inr (_ : g₃ ≫ pushout.inr ≫ pushout.inl = g₄ ≫ pushout.inr))
      pushout.inl
      (_ :
        pushout.inl ≫
            pushout.desc (pushout.inr ≫ pushout.inl) pushout.inr
              (_ : g₃ ≫ pushout.inr ≫ pushout.inl = g₄ ≫ pushout.inr) =
          pushout.inr ≫ pushout.inl))

Next tactic:
apply rightSquareIsPushout
/-- `(X₁ ⨿[Z₁] X₂) ⨿[Z₂] X₃` is the pushout `(X₁ ⨿[Z₁] X₂) ×[X₂] (X₂ ⨿[Z₂] X₃)`. -/
def pushoutPushoutLeftIsPushout [HasPushout (g₃ ≫ f₂) g₄] :
    IsColimit
      (PushoutCocone.mk l₁' l₂' (show f₂ ≫ l₁' = f₃ ≫ l₂' from (pushout.inl_desc _ _ _).symm)) := by
  apply PushoutCocone.flipIsColimit
  apply rightSquareIsPushout
  · 

Proof state:
case t.H
C : Type u
inst✝⁴ : Category.{v, u} C
D : Type u₂
inst✝³ : Category.{v₂, u₂} D
W X Y Z X₁ X₂ X₃ Z₁ Z₂ : C
g₁ : Z₁ ⟶ X₁
g₂ : Z₁ ⟶ X₂
g₃ : Z₂ ⟶ X₂
g₄ : Z₂ ⟶ X₃
inst✝² : HasPushout g₁ g₂
inst✝¹ : HasPushout g₃ g₄
inst✝ : HasPushout (g₃ ≫ pushout.inr) g₄
⊢ IsColimit (PushoutCocone.mk ?t.g₁ pushout.inl ?t.h₁)

Next tactic:
apply PushoutCocone.flipIsColimit
/-- `(X₁ ⨿[Z₁] X₂) ⨿[Z₂] X₃` is the pushout `(X₁ ⨿[Z₁] X₂) ×[X₂] (X₂ ⨿[Z₂] X₃)`. -/
def pushoutPushoutLeftIsPushout [HasPushout (g₃ ≫ f₂) g₄] :
    IsColimit
      (PushoutCocone.mk l₁' l₂' (show f₂ ≫ l₁' = f₃ ≫ l₂' from (pushout.inl_desc _ _ _).symm)) := by
  apply PushoutCocone.flipIsColimit
  apply rightSquareIsPushout
  · apply PushoutCocone.flipIsColimit
    

Proof state:
case t.H.t
C : Type u
inst✝⁴ : Category.{v, u} C
D : Type u₂
inst✝³ : Category.{v₂, u₂} D
W X Y Z X₁ X₂ X₃ Z₁ Z₂ : C
g₁ : Z₁ ⟶ X₁
g₂ : Z₁ ⟶ X₂
g₃ : Z₂ ⟶ X₂
g₄ : Z₂ ⟶ X₃
inst✝² : HasPushout g₁ g₂
inst✝¹ : HasPushout g₃ g₄
inst✝ : HasPushout (g₃ ≫ pushout.inr) g₄
⊢ IsColimit (PushoutCocone.mk pushout.inl ?t.g₁ (_ : ?t.f₁ ≫ pushout.inl = ?t.i₁ ≫ ?t.g₁))

Next tactic:
exact pushoutIsPushout _ _