l3lab/ntp-mathlib huggingface dataset:
/-- Given

X₁ - f₁ -> X₂ - f₂ -> X₃
|          |          |
i₁         i₂         i₃
∨          ∨          ∨
Y₁ - g₁ -> Y₂ - g₂ -> Y₃

Then the big square is a pullback if both the small squares are.
-/
def bigSquareIsPullback (H : IsLimit (PullbackCone.mk _ _ h₂))
    (H' : IsLimit (PullbackCone.mk _ _ h₁)) :
    IsLimit
      (PullbackCone.mk _ _
        (show i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃ by
          rw [← Category.assoc, h₁, Category.assoc, h₂, Category.assoc])) := by
  fapply PullbackCone.isLimitAux'
  intro s
  have : (s.fst ≫ g₁) ≫ g₂ = s.snd ≫ i₃ := by rw [← s.condition, Category.assoc]
  

Proof state:
case create
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₂ Y₃ : C
f₁ : X₁ ⟶ X₂
f₂ : X₂ ⟶ X₃
g₁ : Y₁ ⟶ Y₂
g₂ : Y₂ ⟶ Y₃
i₁ : X₁ ⟶ Y₁
i₂ : X₂ ⟶ Y₂
i₃ : X₃ ⟶ Y₃
h₁ : i₁ ≫ g₁ = f₁ ≫ i₂
h₂ : i₂ ≫ g₂ = f₂ ≫ i₃
H : IsLimit (PullbackCone.mk i₂ f₂ h₂)
H' : IsLimit (PullbackCone.mk i₁ f₁ h₁)
s : PullbackCone (g₁ ≫ g₂) i₃
this : (PullbackCone.fst s ≫ g₁) ≫ g₂ = PullbackCone.snd s ≫ i₃
⊢ { l //
    l ≫ PullbackCone.fst (PullbackCone.mk i₁ (f₁ ≫ f₂) (_ : i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃)) = PullbackCone.fst s ∧
      l ≫ PullbackCone.snd (PullbackCone.mk i₁ (f₁ ≫ f₂) (_ : i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃)) = PullbackCone.snd s ∧
        ∀ {m : s.pt ⟶ (PullbackCone.mk i₁ (f₁ ≫ f₂) (_ : i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃)).pt},
          m ≫ PullbackCone.fst (PullbackCone.mk i₁ (f₁ ≫ f₂) (_ : i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃)) = PullbackCone.fst s →
            m ≫ PullbackCone.snd (PullbackCone.mk i₁ (f₁ ≫ f₂) (_ : i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃)) =
                PullbackCone.snd s →
              m = l }

Next tactic:
rcases PullbackCone.IsLimit.lift' H (s.fst ≫ g₁) s.snd this with ⟨l₁, hl₁, hl₁'⟩
/-- Given

X₁ - f₁ -> X₂ - f₂ -> X₃
|          |          |
i₁         i₂         i₃
∨          ∨          ∨
Y₁ - g₁ -> Y₂ - g₂ -> Y₃

Then the big square is a pullback if both the small squares are.
-/
def bigSquareIsPullback (H : IsLimit (PullbackCone.mk _ _ h₂))
    (H' : IsLimit (PullbackCone.mk _ _ h₁)) :
    IsLimit
      (PullbackCone.mk _ _
        (show i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃ by
          rw [← Category.assoc, h₁, Category.assoc, h₂, Category.assoc])) := by
  fapply PullbackCone.isLimitAux'
  intro s
  have : (s.fst ≫ g₁) ≫ g₂ = s.snd ≫ i₃ := by rw [← s.condition, Category.assoc]
  rcases PullbackCone.IsLimit.lift' H (s.fst ≫ g₁) s.snd this with ⟨l₁, hl₁, hl₁'⟩
  

Proof state:
case create.mk.intro
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₂ Y₃ : C
f₁ : X₁ ⟶ X₂
f₂ : X₂ ⟶ X₃
g₁ : Y₁ ⟶ Y₂
g₂ : Y₂ ⟶ Y₃
i₁ : X₁ ⟶ Y₁
i₂ : X₂ ⟶ Y₂
i₃ : X₃ ⟶ Y₃
h₁ : i₁ ≫ g₁ = f₁ ≫ i₂
h₂ : i₂ ≫ g₂ = f₂ ≫ i₃
H : IsLimit (PullbackCone.mk i₂ f₂ h₂)
H' : IsLimit (PullbackCone.mk i₁ f₁ h₁)
s : PullbackCone (g₁ ≫ g₂) i₃
this : (PullbackCone.fst s ≫ g₁) ≫ g₂ = PullbackCone.snd s ≫ i₃
l₁ : s.pt ⟶ (PullbackCone.mk i₂ f₂ h₂).pt
hl₁ : l₁ ≫ PullbackCone.fst (PullbackCone.mk i₂ f₂ h₂) = PullbackCone.fst s ≫ g₁
hl₁' : l₁ ≫ PullbackCone.snd (PullbackCone.mk i₂ f₂ h₂) = PullbackCone.snd s
⊢ { l //
    l ≫ PullbackCone.fst (PullbackCone.mk i₁ (f₁ ≫ f₂) (_ : i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃)) = PullbackCone.fst s ∧
      l ≫ PullbackCone.snd (PullbackCone.mk i₁ (f₁ ≫ f₂) (_ : i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃)) = PullbackCone.snd s ∧
        ∀ {m : s.pt ⟶ (PullbackCone.mk i₁ (f₁ ≫ f₂) (_ : i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃)).pt},
          m ≫ PullbackCone.fst (PullbackCone.mk i₁ (f₁ ≫ f₂) (_ : i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃)) = PullbackCone.fst s →
            m ≫ PullbackCone.snd (PullbackCone.mk i₁ (f₁ ≫ f₂) (_ : i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃)) =
                PullbackCone.snd s →
              m = l }

Next tactic:
rcases PullbackCone.IsLimit.lift' H' s.fst l₁ hl₁.symm with ⟨l₂, hl₂, hl₂'⟩
/-- Given

X₁ - f₁ -> X₂ - f₂ -> X₃
|          |          |
i₁         i₂         i₃
∨          ∨          ∨
Y₁ - g₁ -> Y₂ - g₂ -> Y₃

Then the big square is a pullback if both the small squares are.
-/
def bigSquareIsPullback (H : IsLimit (PullbackCone.mk _ _ h₂))
    (H' : IsLimit (PullbackCone.mk _ _ h₁)) :
    IsLimit
      (PullbackCone.mk _ _
        (show i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃ by
          rw [← Category.assoc, h₁, Category.assoc, h₂, Category.assoc])) := by
  fapply PullbackCone.isLimitAux'
  intro s
  have : (s.fst ≫ g₁) ≫ g₂ = s.snd ≫ i₃ := by rw [← s.condition, Category.assoc]
  rcases PullbackCone.IsLimit.lift' H (s.fst ≫ g₁) s.snd this with ⟨l₁, hl₁, hl₁'⟩
  rcases PullbackCone.IsLimit.lift' H' s.fst l₁ hl₁.symm with ⟨l₂, hl₂, hl₂'⟩
  

Proof state:
case create.mk.intro.mk.intro
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₂ Y₃ : C
f₁ : X₁ ⟶ X₂
f₂ : X₂ ⟶ X₃
g₁ : Y₁ ⟶ Y₂
g₂ : Y₂ ⟶ Y₃
i₁ : X₁ ⟶ Y₁
i₂ : X₂ ⟶ Y₂
i₃ : X₃ ⟶ Y₃
h₁ : i₁ ≫ g₁ = f₁ ≫ i₂
h₂ : i₂ ≫ g₂ = f₂ ≫ i₃
H : IsLimit (PullbackCone.mk i₂ f₂ h₂)
H' : IsLimit (PullbackCone.mk i₁ f₁ h₁)
s : PullbackCone (g₁ ≫ g₂) i₃
this : (PullbackCone.fst s ≫ g₁) ≫ g₂ = PullbackCone.snd s ≫ i₃
l₁ : s.pt ⟶ (PullbackCone.mk i₂ f₂ h₂).pt
hl₁ : l₁ ≫ PullbackCone.fst (PullbackCone.mk i₂ f₂ h₂) = PullbackCone.fst s ≫ g₁
hl₁' : l₁ ≫ PullbackCone.snd (PullbackCone.mk i₂ f₂ h₂) = PullbackCone.snd s
l₂ : s.pt ⟶ (PullbackCone.mk i₁ f₁ h₁).pt
hl₂ : l₂ ≫ PullbackCone.fst (PullbackCone.mk i₁ f₁ h₁) = PullbackCone.fst s
hl₂' : l₂ ≫ PullbackCone.snd (PullbackCone.mk i₁ f₁ h₁) = l₁
⊢ { l //
    l ≫ PullbackCone.fst (PullbackCone.mk i₁ (f₁ ≫ f₂) (_ : i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃)) = PullbackCone.fst s ∧
      l ≫ PullbackCone.snd (PullbackCone.mk i₁ (f₁ ≫ f₂) (_ : i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃)) = PullbackCone.snd s ∧
        ∀ {m : s.pt ⟶ (PullbackCone.mk i₁ (f₁ ≫ f₂) (_ : i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃)).pt},
          m ≫ PullbackCone.fst (PullbackCone.mk i₁ (f₁ ≫ f₂) (_ : i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃)) = PullbackCone.fst s →
            m ≫ PullbackCone.snd (PullbackCone.mk i₁ (f₁ ≫ f₂) (_ : i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃)) =
                PullbackCone.snd s →
              m = l }

Next tactic:
use l₂
/-- Given

X₁ - f₁ -> X₂ - f₂ -> X₃
|          |          |
i₁         i₂         i₃
∨          ∨          ∨
Y₁ - g₁ -> Y₂ - g₂ -> Y₃

Then the big square is a pullback if both the small squares are.
-/
def bigSquareIsPullback (H : IsLimit (PullbackCone.mk _ _ h₂))
    (H' : IsLimit (PullbackCone.mk _ _ h₁)) :
    IsLimit
      (PullbackCone.mk _ _
        (show i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃ by
          rw [← Category.assoc, h₁, Category.assoc, h₂, Category.assoc])) := by
  fapply PullbackCone.isLimitAux'
  intro s
  have : (s.fst ≫ g₁) ≫ g₂ = s.snd ≫ i₃ := by rw [← s.condition, Category.assoc]
  rcases PullbackCone.IsLimit.lift' H (s.fst ≫ g₁) s.snd this with ⟨l₁, hl₁, hl₁'⟩
  rcases PullbackCone.IsLimit.lift' H' s.fst l₁ hl₁.symm with ⟨l₂, hl₂, hl₂'⟩
  use l₂
  

Proof state:
case property
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₂ Y₃ : C
f₁ : X₁ ⟶ X₂
f₂ : X₂ ⟶ X₃
g₁ : Y₁ ⟶ Y₂
g₂ : Y₂ ⟶ Y₃
i₁ : X₁ ⟶ Y₁
i₂ : X₂ ⟶ Y₂
i₃ : X₃ ⟶ Y₃
h₁ : i₁ ≫ g₁ = f₁ ≫ i₂
h₂ : i₂ ≫ g₂ = f₂ ≫ i₃
H : IsLimit (PullbackCone.mk i₂ f₂ h₂)
H' : IsLimit (PullbackCone.mk i₁ f₁ h₁)
s : PullbackCone (g₁ ≫ g₂) i₃
this : (PullbackCone.fst s ≫ g₁) ≫ g₂ = PullbackCone.snd s ≫ i₃
l₁ : s.pt ⟶ (PullbackCone.mk i₂ f₂ h₂).pt
hl₁ : l₁ ≫ PullbackCone.fst (PullbackCone.mk i₂ f₂ h₂) = PullbackCone.fst s ≫ g₁
hl₁' : l₁ ≫ PullbackCone.snd (PullbackCone.mk i₂ f₂ h₂) = PullbackCone.snd s
l₂ : s.pt ⟶ (PullbackCone.mk i₁ f₁ h₁).pt
hl₂ : l₂ ≫ PullbackCone.fst (PullbackCone.mk i₁ f₁ h₁) = PullbackCone.fst s
hl₂' : l₂ ≫ PullbackCone.snd (PullbackCone.mk i₁ f₁ h₁) = l₁
⊢ l₂ ≫ PullbackCone.fst (PullbackCone.mk i₁ (f₁ ≫ f₂) (_ : i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃)) = PullbackCone.fst s ∧
    l₂ ≫ PullbackCone.snd (PullbackCone.mk i₁ (f₁ ≫ f₂) (_ : i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃)) = PullbackCone.snd s ∧
      ∀ {m : s.pt ⟶ (PullbackCone.mk i₁ (f₁ ≫ f₂) (_ : i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃)).pt},
        m ≫ PullbackCone.fst (PullbackCone.mk i₁ (f₁ ≫ f₂) (_ : i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃)) = PullbackCone.fst s →
          m ≫ PullbackCone.snd (PullbackCone.mk i₁ (f₁ ≫ f₂) (_ : i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃)) = PullbackCone.snd s →
            m = l₂

Next tactic:
use hl₂
/-- Given

X₁ - f₁ -> X₂ - f₂ -> X₃
|          |          |
i₁         i₂         i₃
∨          ∨          ∨
Y₁ - g₁ -> Y₂ - g₂ -> Y₃

Then the big square is a pullback if both the small squares are.
-/
def bigSquareIsPullback (H : IsLimit (PullbackCone.mk _ _ h₂))
    (H' : IsLimit (PullbackCone.mk _ _ h₁)) :
    IsLimit
      (PullbackCone.mk _ _
        (show i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃ by
          rw [← Category.assoc, h₁, Category.assoc, h₂, Category.assoc])) := by
  fapply PullbackCone.isLimitAux'
  intro s
  have : (s.fst ≫ g₁) ≫ g₂ = s.snd ≫ i₃ := by rw [← s.condition, Category.assoc]
  rcases PullbackCone.IsLimit.lift' H (s.fst ≫ g₁) s.snd this with ⟨l₁, hl₁, hl₁'⟩
  rcases PullbackCone.IsLimit.lift' H' s.fst l₁ hl₁.symm with ⟨l₂, hl₂, hl₂'⟩
  use l₂
  use hl₂
  

Proof state:
case right
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₂ Y₃ : C
f₁ : X₁ ⟶ X₂
f₂ : X₂ ⟶ X₃
g₁ : Y₁ ⟶ Y₂
g₂ : Y₂ ⟶ Y₃
i₁ : X₁ ⟶ Y₁
i₂ : X₂ ⟶ Y₂
i₃ : X₃ ⟶ Y₃
h₁ : i₁ ≫ g₁ = f₁ ≫ i₂
h₂ : i₂ ≫ g₂ = f₂ ≫ i₃
H : IsLimit (PullbackCone.mk i₂ f₂ h₂)
H' : IsLimit (PullbackCone.mk i₁ f₁ h₁)
s : PullbackCone (g₁ ≫ g₂) i₃
this : (PullbackCone.fst s ≫ g₁) ≫ g₂ = PullbackCone.snd s ≫ i₃
l₁ : s.pt ⟶ (PullbackCone.mk i₂ f₂ h₂).pt
hl₁ : l₁ ≫ PullbackCone.fst (PullbackCone.mk i₂ f₂ h₂) = PullbackCone.fst s ≫ g₁
hl₁' : l₁ ≫ PullbackCone.snd (PullbackCone.mk i₂ f₂ h₂) = PullbackCone.snd s
l₂ : s.pt ⟶ (PullbackCone.mk i₁ f₁ h₁).pt
hl₂ : l₂ ≫ PullbackCone.fst (PullbackCone.mk i₁ f₁ h₁) = PullbackCone.fst s
hl₂' : l₂ ≫ PullbackCone.snd (PullbackCone.mk i₁ f₁ h₁) = l₁
⊢ l₂ ≫ PullbackCone.snd (PullbackCone.mk i₁ (f₁ ≫ f₂) (_ : i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃)) = PullbackCone.snd s ∧
    ∀ {m : s.pt ⟶ (PullbackCone.mk i₁ (f₁ ≫ f₂) (_ : i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃)).pt},
      m ≫ PullbackCone.fst (PullbackCone.mk i₁ (f₁ ≫ f₂) (_ : i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃)) = PullbackCone.fst s →
        m ≫ PullbackCone.snd (PullbackCone.mk i₁ (f₁ ≫ f₂) (_ : i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃)) = PullbackCone.snd s →
          m = l₂

Next tactic:
use
    show l₂ ≫ f₁ ≫ f₂ = s.snd by
      rw [← hl₁', ← hl₂', Category.assoc]
      rfl
/-- Given

X₁ - f₁ -> X₂ - f₂ -> X₃
|          |          |
i₁         i₂         i₃
∨          ∨          ∨
Y₁ - g₁ -> Y₂ - g₂ -> Y₃

Then the big square is a pullback if both the small squares are.
-/
def bigSquareIsPullback (H : IsLimit (PullbackCone.mk _ _ h₂))
    (H' : IsLimit (PullbackCone.mk _ _ h₁)) :
    IsLimit
      (PullbackCone.mk _ _
        (show i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃ by
          rw [← Category.assoc, h₁, Category.assoc, h₂, Category.assoc])) := by
  fapply PullbackCone.isLimitAux'
  intro s
  have : (s.fst ≫ g₁) ≫ g₂ = s.snd ≫ i₃ := by rw [← s.condition, Category.assoc]
  rcases PullbackCone.IsLimit.lift' H (s.fst ≫ g₁) s.snd this with ⟨l₁, hl₁, hl₁'⟩
  rcases PullbackCone.IsLimit.lift' H' s.fst l₁ hl₁.symm with ⟨l₂, hl₂, hl₂'⟩
  use l₂
  use hl₂
  use
    show l₂ ≫ f₁ ≫ f₂ = s.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₂ Y₃ : C
f₁ : X₁ ⟶ X₂
f₂ : X₂ ⟶ X₃
g₁ : Y₁ ⟶ Y₂
g₂ : Y₂ ⟶ Y₃
i₁ : X₁ ⟶ Y₁
i₂ : X₂ ⟶ Y₂
i₃ : X₃ ⟶ Y₃
h₁ : i₁ ≫ g₁ = f₁ ≫ i₂
h₂ : i₂ ≫ g₂ = f₂ ≫ i₃
H : IsLimit (PullbackCone.mk i₂ f₂ h₂)
H' : IsLimit (PullbackCone.mk i₁ f₁ h₁)
s : PullbackCone (g₁ ≫ g₂) i₃
this : (PullbackCone.fst s ≫ g₁) ≫ g₂ = PullbackCone.snd s ≫ i₃
l₁ : s.pt ⟶ (PullbackCone.mk i₂ f₂ h₂).pt
hl₁ : l₁ ≫ PullbackCone.fst (PullbackCone.mk i₂ f₂ h₂) = PullbackCone.fst s ≫ g₁
hl₁' : l₁ ≫ PullbackCone.snd (PullbackCone.mk i₂ f₂ h₂) = PullbackCone.snd s
l₂ : s.pt ⟶ (PullbackCone.mk i₁ f₁ h₁).pt
hl₂ : l₂ ≫ PullbackCone.fst (PullbackCone.mk i₁ f₁ h₁) = PullbackCone.fst s
hl₂' : l₂ ≫ PullbackCone.snd (PullbackCone.mk i₁ f₁ h₁) = l₁
⊢ l₂ ≫ f₁ ≫ f₂ = PullbackCone.snd s

Next tactic:
rw [← hl₁', ← hl₂', Category.assoc]
/-- Given

X₁ - f₁ -> X₂ - f₂ -> X₃
|          |          |
i₁         i₂         i₃
∨          ∨          ∨
Y₁ - g₁ -> Y₂ - g₂ -> Y₃

Then the big square is a pullback if both the small squares are.
-/
def bigSquareIsPullback (H : IsLimit (PullbackCone.mk _ _ h₂))
    (H' : IsLimit (PullbackCone.mk _ _ h₁)) :
    IsLimit
      (PullbackCone.mk _ _
        (show i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃ by
          rw [← Category.assoc, h₁, Category.assoc, h₂, Category.assoc])) := by
  fapply PullbackCone.isLimitAux'
  intro s
  have : (s.fst ≫ g₁) ≫ g₂ = s.snd ≫ i₃ := by rw [← s.condition, Category.assoc]
  rcases PullbackCone.IsLimit.lift' H (s.fst ≫ g₁) s.snd this with ⟨l₁, hl₁, hl₁'⟩
  rcases PullbackCone.IsLimit.lift' H' s.fst l₁ hl₁.symm with ⟨l₂, hl₂, hl₂'⟩
  use l₂
  use hl₂
  use
    show l₂ ≫ f₁ ≫ f₂ = s.snd by
      rw [← hl₁', ← hl₂', 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₂ Y₃ : C
f₁ : X₁ ⟶ X₂
f₂ : X₂ ⟶ X₃
g₁ : Y₁ ⟶ Y₂
g₂ : Y₂ ⟶ Y₃
i₁ : X₁ ⟶ Y₁
i₂ : X₂ ⟶ Y₂
i₃ : X₃ ⟶ Y₃
h₁ : i₁ ≫ g₁ = f₁ ≫ i₂
h₂ : i₂ ≫ g₂ = f₂ ≫ i₃
H : IsLimit (PullbackCone.mk i₂ f₂ h₂)
H' : IsLimit (PullbackCone.mk i₁ f₁ h₁)
s : PullbackCone (g₁ ≫ g₂) i₃
this : (PullbackCone.fst s ≫ g₁) ≫ g₂ = PullbackCone.snd s ≫ i₃
l₁ : s.pt ⟶ (PullbackCone.mk i₂ f₂ h₂).pt
hl₁ : l₁ ≫ PullbackCone.fst (PullbackCone.mk i₂ f₂ h₂) = PullbackCone.fst s ≫ g₁
hl₁' : l₁ ≫ PullbackCone.snd (PullbackCone.mk i₂ f₂ h₂) = PullbackCone.snd s
l₂ : s.pt ⟶ (PullbackCone.mk i₁ f₁ h₁).pt
hl₂ : l₂ ≫ PullbackCone.fst (PullbackCone.mk i₁ f₁ h₁) = PullbackCone.fst s
hl₂' : l₂ ≫ PullbackCone.snd (PullbackCone.mk i₁ f₁ h₁) = l₁
⊢ l₂ ≫ f₁ ≫ f₂ = l₂ ≫ PullbackCone.snd (PullbackCone.mk i₁ f₁ h₁) ≫ PullbackCone.snd (PullbackCone.mk i₂ f₂ h₂)

Next tactic:
rfl
/-- Given

X₁ - f₁ -> X₂ - f₂ -> X₃
|          |          |
i₁         i₂         i₃
∨          ∨          ∨
Y₁ - g₁ -> Y₂ - g₂ -> Y₃

Then the big square is a pullback if both the small squares are.
-/
def bigSquareIsPullback (H : IsLimit (PullbackCone.mk _ _ h₂))
    (H' : IsLimit (PullbackCone.mk _ _ h₁)) :
    IsLimit
      (PullbackCone.mk _ _
        (show i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃ by
          rw [← Category.assoc, h₁, Category.assoc, h₂, Category.assoc])) := by
  fapply PullbackCone.isLimitAux'
  intro s
  have : (s.fst ≫ g₁) ≫ g₂ = s.snd ≫ i₃ := by rw [← s.condition, Category.assoc]
  rcases PullbackCone.IsLimit.lift' H (s.fst ≫ g₁) s.snd this with ⟨l₁, hl₁, hl₁'⟩
  rcases PullbackCone.IsLimit.lift' H' s.fst l₁ hl₁.symm with ⟨l₂, hl₂, hl₂'⟩
  use l₂
  use hl₂
  use
    show l₂ ≫ f₁ ≫ f₂ = s.snd by
      rw [← hl₁', ← hl₂', Category.assoc]
      rfl
  

Proof state:
case right
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₂ Y₃ : C
f₁ : X₁ ⟶ X₂
f₂ : X₂ ⟶ X₃
g₁ : Y₁ ⟶ Y₂
g₂ : Y₂ ⟶ Y₃
i₁ : X₁ ⟶ Y₁
i₂ : X₂ ⟶ Y₂
i₃ : X₃ ⟶ Y₃
h₁ : i₁ ≫ g₁ = f₁ ≫ i₂
h₂ : i₂ ≫ g₂ = f₂ ≫ i₃
H : IsLimit (PullbackCone.mk i₂ f₂ h₂)
H' : IsLimit (PullbackCone.mk i₁ f₁ h₁)
s : PullbackCone (g₁ ≫ g₂) i₃
this : (PullbackCone.fst s ≫ g₁) ≫ g₂ = PullbackCone.snd s ≫ i₃
l₁ : s.pt ⟶ (PullbackCone.mk i₂ f₂ h₂).pt
hl₁ : l₁ ≫ PullbackCone.fst (PullbackCone.mk i₂ f₂ h₂) = PullbackCone.fst s ≫ g₁
hl₁' : l₁ ≫ PullbackCone.snd (PullbackCone.mk i₂ f₂ h₂) = PullbackCone.snd s
l₂ : s.pt ⟶ (PullbackCone.mk i₁ f₁ h₁).pt
hl₂ : l₂ ≫ PullbackCone.fst (PullbackCone.mk i₁ f₁ h₁) = PullbackCone.fst s
hl₂' : l₂ ≫ PullbackCone.snd (PullbackCone.mk i₁ f₁ h₁) = l₁
⊢ ∀ {m : s.pt ⟶ (PullbackCone.mk i₁ (f₁ ≫ f₂) (_ : i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃)).pt},
    m ≫ PullbackCone.fst (PullbackCone.mk i₁ (f₁ ≫ f₂) (_ : i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃)) = PullbackCone.fst s →
      m ≫ PullbackCone.snd (PullbackCone.mk i₁ (f₁ ≫ f₂) (_ : i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃)) = PullbackCone.snd s →
        m = l₂

Next tactic:
intro m hm₁ hm₂
/-- Given

X₁ - f₁ -> X₂ - f₂ -> X₃
|          |          |
i₁         i₂         i₃
∨          ∨          ∨
Y₁ - g₁ -> Y₂ - g₂ -> Y₃

Then the big square is a pullback if both the small squares are.
-/
def bigSquareIsPullback (H : IsLimit (PullbackCone.mk _ _ h₂))
    (H' : IsLimit (PullbackCone.mk _ _ h₁)) :
    IsLimit
      (PullbackCone.mk _ _
        (show i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃ by
          rw [← Category.assoc, h₁, Category.assoc, h₂, Category.assoc])) := by
  fapply PullbackCone.isLimitAux'
  intro s
  have : (s.fst ≫ g₁) ≫ g₂ = s.snd ≫ i₃ := by rw [← s.condition, Category.assoc]
  rcases PullbackCone.IsLimit.lift' H (s.fst ≫ g₁) s.snd this with ⟨l₁, hl₁, hl₁'⟩
  rcases PullbackCone.IsLimit.lift' H' s.fst l₁ hl₁.symm with ⟨l₂, hl₂, hl₂'⟩
  use l₂
  use hl₂
  use
    show l₂ ≫ f₁ ≫ f₂ = s.snd by
      rw [← hl₁', ← hl₂', Category.assoc]
      rfl
  intro m hm₁ hm₂
  

Proof state:
case right
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₂ Y₃ : C
f₁ : X₁ ⟶ X₂
f₂ : X₂ ⟶ X₃
g₁ : Y₁ ⟶ Y₂
g₂ : Y₂ ⟶ Y₃
i₁ : X₁ ⟶ Y₁
i₂ : X₂ ⟶ Y₂
i₃ : X₃ ⟶ Y₃
h₁ : i₁ ≫ g₁ = f₁ ≫ i₂
h₂ : i₂ ≫ g₂ = f₂ ≫ i₃
H : IsLimit (PullbackCone.mk i₂ f₂ h₂)
H' : IsLimit (PullbackCone.mk i₁ f₁ h₁)
s : PullbackCone (g₁ ≫ g₂) i₃
this : (PullbackCone.fst s ≫ g₁) ≫ g₂ = PullbackCone.snd s ≫ i₃
l₁ : s.pt ⟶ (PullbackCone.mk i₂ f₂ h₂).pt
hl₁ : l₁ ≫ PullbackCone.fst (PullbackCone.mk i₂ f₂ h₂) = PullbackCone.fst s ≫ g₁
hl₁' : l₁ ≫ PullbackCone.snd (PullbackCone.mk i₂ f₂ h₂) = PullbackCone.snd s
l₂ : s.pt ⟶ (PullbackCone.mk i₁ f₁ h₁).pt
hl₂ : l₂ ≫ PullbackCone.fst (PullbackCone.mk i₁ f₁ h₁) = PullbackCone.fst s
hl₂' : l₂ ≫ PullbackCone.snd (PullbackCone.mk i₁ f₁ h₁) = l₁
m : s.pt ⟶ (PullbackCone.mk i₁ (f₁ ≫ f₂) (_ : i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃)).pt
hm₁ : m ≫ PullbackCone.fst (PullbackCone.mk i₁ (f₁ ≫ f₂) (_ : i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃)) = PullbackCone.fst s
hm₂ : m ≫ PullbackCone.snd (PullbackCone.mk i₁ (f₁ ≫ f₂) (_ : i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃)) = PullbackCone.snd s
⊢ m = l₂

Next tactic:
apply PullbackCone.IsLimit.hom_ext H'
/-- Given

X₁ - f₁ -> X₂ - f₂ -> X₃
|          |          |
i₁         i₂         i₃
∨          ∨          ∨
Y₁ - g₁ -> Y₂ - g₂ -> Y₃

Then the big square is a pullback if both the small squares are.
-/
def bigSquareIsPullback (H : IsLimit (PullbackCone.mk _ _ h₂))
    (H' : IsLimit (PullbackCone.mk _ _ h₁)) :
    IsLimit
      (PullbackCone.mk _ _
        (show i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃ by
          rw [← Category.assoc, h₁, Category.assoc, h₂, Category.assoc])) := by
  fapply PullbackCone.isLimitAux'
  intro s
  have : (s.fst ≫ g₁) ≫ g₂ = s.snd ≫ i₃ := by rw [← s.condition, Category.assoc]
  rcases PullbackCone.IsLimit.lift' H (s.fst ≫ g₁) s.snd this with ⟨l₁, hl₁, hl₁'⟩
  rcases PullbackCone.IsLimit.lift' H' s.fst l₁ hl₁.symm with ⟨l₂, hl₂, hl₂'⟩
  use l₂
  use hl₂
  use
    show l₂ ≫ f₁ ≫ f₂ = s.snd by
      rw [← hl₁', ← hl₂', Category.assoc]
      rfl
  intro m hm₁ hm₂
  apply PullbackCone.IsLimit.hom_ext H'
  · 

Proof state:
case right.h₀
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₂ Y₃ : C
f₁ : X₁ ⟶ X₂
f₂ : X₂ ⟶ X₃
g₁ : Y₁ ⟶ Y₂
g₂ : Y₂ ⟶ Y₃
i₁ : X₁ ⟶ Y₁
i₂ : X₂ ⟶ Y₂
i₃ : X₃ ⟶ Y₃
h₁ : i₁ ≫ g₁ = f₁ ≫ i₂
h₂ : i₂ ≫ g₂ = f₂ ≫ i₃
H : IsLimit (PullbackCone.mk i₂ f₂ h₂)
H' : IsLimit (PullbackCone.mk i₁ f₁ h₁)
s : PullbackCone (g₁ ≫ g₂) i₃
this : (PullbackCone.fst s ≫ g₁) ≫ g₂ = PullbackCone.snd s ≫ i₃
l₁ : s.pt ⟶ (PullbackCone.mk i₂ f₂ h₂).pt
hl₁ : l₁ ≫ PullbackCone.fst (PullbackCone.mk i₂ f₂ h₂) = PullbackCone.fst s ≫ g₁
hl₁' : l₁ ≫ PullbackCone.snd (PullbackCone.mk i₂ f₂ h₂) = PullbackCone.snd s
l₂ : s.pt ⟶ (PullbackCone.mk i₁ f₁ h₁).pt
hl₂ : l₂ ≫ PullbackCone.fst (PullbackCone.mk i₁ f₁ h₁) = PullbackCone.fst s
hl₂' : l₂ ≫ PullbackCone.snd (PullbackCone.mk i₁ f₁ h₁) = l₁
m : s.pt ⟶ (PullbackCone.mk i₁ (f₁ ≫ f₂) (_ : i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃)).pt
hm₁ : m ≫ PullbackCone.fst (PullbackCone.mk i₁ (f₁ ≫ f₂) (_ : i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃)) = PullbackCone.fst s
hm₂ : m ≫ PullbackCone.snd (PullbackCone.mk i₁ (f₁ ≫ f₂) (_ : i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃)) = PullbackCone.snd s
⊢ m ≫ PullbackCone.fst (PullbackCone.mk i₁ f₁ h₁) = l₂ ≫ PullbackCone.fst (PullbackCone.mk i₁ f₁ h₁)

Next tactic:
erw [hm₁, hl₂]
/-- Given

X₁ - f₁ -> X₂ - f₂ -> X₃
|          |          |
i₁         i₂         i₃
∨          ∨          ∨
Y₁ - g₁ -> Y₂ - g₂ -> Y₃

Then the big square is a pullback if both the small squares are.
-/
def bigSquareIsPullback (H : IsLimit (PullbackCone.mk _ _ h₂))
    (H' : IsLimit (PullbackCone.mk _ _ h₁)) :
    IsLimit
      (PullbackCone.mk _ _
        (show i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃ by
          rw [← Category.assoc, h₁, Category.assoc, h₂, Category.assoc])) := by
  fapply PullbackCone.isLimitAux'
  intro s
  have : (s.fst ≫ g₁) ≫ g₂ = s.snd ≫ i₃ := by rw [← s.condition, Category.assoc]
  rcases PullbackCone.IsLimit.lift' H (s.fst ≫ g₁) s.snd this with ⟨l₁, hl₁, hl₁'⟩
  rcases PullbackCone.IsLimit.lift' H' s.fst l₁ hl₁.symm with ⟨l₂, hl₂, hl₂'⟩
  use l₂
  use hl₂
  use
    show l₂ ≫ f₁ ≫ f₂ = s.snd by
      rw [← hl₁', ← hl₂', Category.assoc]
      rfl
  intro m hm₁ hm₂
  apply PullbackCone.IsLimit.hom_ext H'
  · erw [hm₁, hl₂]
  · 

Proof state:
case right.h₁
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₂ Y₃ : C
f₁ : X₁ ⟶ X₂
f₂ : X₂ ⟶ X₃
g₁ : Y₁ ⟶ Y₂
g₂ : Y₂ ⟶ Y₃
i₁ : X₁ ⟶ Y₁
i₂ : X₂ ⟶ Y₂
i₃ : X₃ ⟶ Y₃
h₁ : i₁ ≫ g₁ = f₁ ≫ i₂
h₂ : i₂ ≫ g₂ = f₂ ≫ i₃
H : IsLimit (PullbackCone.mk i₂ f₂ h₂)
H' : IsLimit (PullbackCone.mk i₁ f₁ h₁)
s : PullbackCone (g₁ ≫ g₂) i₃
this : (PullbackCone.fst s ≫ g₁) ≫ g₂ = PullbackCone.snd s ≫ i₃
l₁ : s.pt ⟶ (PullbackCone.mk i₂ f₂ h₂).pt
hl₁ : l₁ ≫ PullbackCone.fst (PullbackCone.mk i₂ f₂ h₂) = PullbackCone.fst s ≫ g₁
hl₁' : l₁ ≫ PullbackCone.snd (PullbackCone.mk i₂ f₂ h₂) = PullbackCone.snd s
l₂ : s.pt ⟶ (PullbackCone.mk i₁ f₁ h₁).pt
hl₂ : l₂ ≫ PullbackCone.fst (PullbackCone.mk i₁ f₁ h₁) = PullbackCone.fst s
hl₂' : l₂ ≫ PullbackCone.snd (PullbackCone.mk i₁ f₁ h₁) = l₁
m : s.pt ⟶ (PullbackCone.mk i₁ (f₁ ≫ f₂) (_ : i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃)).pt
hm₁ : m ≫ PullbackCone.fst (PullbackCone.mk i₁ (f₁ ≫ f₂) (_ : i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃)) = PullbackCone.fst s
hm₂ : m ≫ PullbackCone.snd (PullbackCone.mk i₁ (f₁ ≫ f₂) (_ : i₁ ≫ g₁ ≫ g₂ = (f₁ ≫ f₂) ≫ i₃)) = PullbackCone.snd s
⊢ m ≫ PullbackCone.snd (PullbackCone.mk i₁ f₁ h₁) = l₂ ≫ PullbackCone.snd (PullbackCone.mk i₁ f₁ h₁)

Next tactic:
apply PullbackCone.IsLimit.hom_ext H