l3lab/ntp-mathlib huggingface dataset:
/-- If `F` preserves the gluing, and reflects the pullback of `U i ⟶ glued` and `U j ⟶ glued`,
then `F` reflects the fact that `V_pullback_cone` is a pullback. -/
def vPullbackConeIsLimitOfMap (i j : D.J) [ReflectsLimit (cospan (D.ι i) (D.ι j)) F]
    (hc : IsLimit ((D.mapGlueData F).vPullbackCone i j)) : IsLimit (D.vPullbackCone i j) := by
  apply isLimitOfReflects F
  apply (isLimitMapConePullbackConeEquiv _ _).symm _
  let e :
    cospan (F.map (D.ι i)) (F.map (D.ι j)) ≅
      cospan ((D.mapGlueData F).ι i) ((D.mapGlueData F).ι j)
  exact
    NatIso.ofComponents
      (fun x => by
        cases x
        exacts [D.gluedIso F, Iso.refl _])
      (by rintro (_ | _) (_ | _) (_ | _ | _) <;> simp)
  apply IsLimit.postcomposeHomEquiv e _ _
  apply hc.ofIsoLimit
  refine' Cones.ext (Iso.refl _) _
  · rintro (_ | _ | _)
    change _ = _ ≫ (_ ≫ _) ≫ _
    all_goals 

Proof state:
case some.right
C : Type u₁
inst✝⁴ : Category.{v, u₁} C
C' : Type u₂
inst✝³ : Category.{v, u₂} C'
D : GlueData C
F : C ⥤ C'
H : (i j k : D.J) → PreservesLimit (cospan (f D i j) (f D i k)) F
inst✝² : HasMulticoequalizer (diagram D)
inst✝¹ : PreservesColimit (MultispanIndex.multispan (diagram D)) F
i j : D.J
inst✝ : ReflectsLimit (cospan (ι D i) (ι D j)) F
hc : IsLimit (vPullbackCone (mapGlueData D F) i j)
e : cospan (F.map (ι D i)) (F.map (ι D j)) ≅ cospan (ι (mapGlueData D F) i) (ι (mapGlueData D F) j) :=
  NatIso.ofComponents fun x =>
    Option.casesOn (motive := fun t =>
      x = t →
        ((cospan (F.map (ι D i)) (F.map (ι D j))).obj x ≅
          (cospan (ι (mapGlueData D F) i) (ι (mapGlueData D F) j)).obj x))
      x (fun h => (_ : none = x) ▸ gluedIso D F)
      (fun val h => (_ : some val = x) ▸ Iso.refl ((cospan (F.map (ι D i)) (F.map (ι D j))).obj (some val))) (_ : x = x)
⊢ (vPullbackCone (mapGlueData D F) i j).π.app (some WalkingPair.right) =
    (Iso.refl (vPullbackCone (mapGlueData D F) i j).pt).hom ≫
      ((Cones.postcompose e.hom).obj
              (PullbackCone.mk (F.map (f D i j)) (F.map (t D i j ≫ f D j i))
                (_ : F.map (f D i j) ≫ F.map (ι D i) = F.map (t D i j ≫ f D j i) ≫ F.map (ι D j)))).π.app
        (some WalkingPair.right)

Next tactic:
change _ = 𝟙 _ ≫ _ ≫ _
/-- If `F` preserves the gluing, and reflects the pullback of `U i ⟶ glued` and `U j ⟶ glued`,
then `F` reflects the fact that `V_pullback_cone` is a pullback. -/
def vPullbackConeIsLimitOfMap (i j : D.J) [ReflectsLimit (cospan (D.ι i) (D.ι j)) F]
    (hc : IsLimit ((D.mapGlueData F).vPullbackCone i j)) : IsLimit (D.vPullbackCone i j) := by
  apply isLimitOfReflects F
  apply (isLimitMapConePullbackConeEquiv _ _).symm _
  let e :
    cospan (F.map (D.ι i)) (F.map (D.ι j)) ≅
      cospan ((D.mapGlueData F).ι i) ((D.mapGlueData F).ι j)
  exact
    NatIso.ofComponents
      (fun x => by
        cases x
        exacts [D.gluedIso F, Iso.refl _])
      (by rintro (_ | _) (_ | _) (_ | _ | _) <;> simp)
  apply IsLimit.postcomposeHomEquiv e _ _
  apply hc.ofIsoLimit
  refine' Cones.ext (Iso.refl _) _
  · rintro (_ | _ | _)
    change _ = _ ≫ (_ ≫ _) ≫ _
    all_goals change _ = 𝟙 _ ≫ _ ≫ _; 

Proof state:
case some.right
C : Type u₁
inst✝⁴ : Category.{v, u₁} C
C' : Type u₂
inst✝³ : Category.{v, u₂} C'
D : GlueData C
F : C ⥤ C'
H : (i j k : D.J) → PreservesLimit (cospan (f D i j) (f D i k)) F
inst✝² : HasMulticoequalizer (diagram D)
inst✝¹ : PreservesColimit (MultispanIndex.multispan (diagram D)) F
i j : D.J
inst✝ : ReflectsLimit (cospan (ι D i) (ι D j)) F
hc : IsLimit (vPullbackCone (mapGlueData D F) i j)
e : cospan (F.map (ι D i)) (F.map (ι D j)) ≅ cospan (ι (mapGlueData D F) i) (ι (mapGlueData D F) j) :=
  NatIso.ofComponents fun x =>
    Option.casesOn (motive := fun t =>
      x = t →
        ((cospan (F.map (ι D i)) (F.map (ι D j))).obj x ≅
          (cospan (ι (mapGlueData D F) i) (ι (mapGlueData D F) j)).obj x))
      x (fun h => (_ : none = x) ▸ gluedIso D F)
      (fun val h => (_ : some val = x) ▸ Iso.refl ((cospan (F.map (ι D i)) (F.map (ι D j))).obj (some val))) (_ : x = x)
⊢ (vPullbackCone (mapGlueData D F) i j).π.app (some WalkingPair.right) =
    𝟙 (((Functor.const WalkingCospan).obj (vPullbackCone (mapGlueData D F) i j).pt).obj (some WalkingPair.right)) ≫
      (PullbackCone.mk (F.map (f D i j)) (F.map (t D i j ≫ f D j i))
                (_ : F.map (f D i j) ≫ F.map (ι D i) = F.map (t D i j ≫ f D j i) ≫ F.map (ι D j))).π.app
          (some WalkingPair.right) ≫
        e.hom.app (some WalkingPair.right)

Next tactic:
aesop_cat
/-- If there is a forgetful functor into `Type` that preserves enough (co)limits, then `D.ι` will
be jointly surjective. -/
theorem ι_jointly_surjective (F : C ⥤ Type v) [PreservesColimit D.diagram.multispan F]
    [∀ i j k : D.J, PreservesLimit (cospan (D.f i j) (D.f i k)) F] (x : F.obj D.glued) :
    ∃ (i : _) (y : F.obj (D.U i)), F.map (D.ι i) y = x := by
  

Proof state:
C : Type u₁
inst✝⁵ : Category.{v, u₁} C
C' : Type u₂
inst✝⁴ : Category.{v, u₂} C'
D : GlueData C
F✝ : C ⥤ C'
H : (i j k : D.J) → PreservesLimit (cospan (f D i j) (f D i k)) F✝
inst✝³ : HasMulticoequalizer (diagram D)
inst✝² : PreservesColimit (MultispanIndex.multispan (diagram D)) F✝
F : C ⥤ Type v
inst✝¹ : PreservesColimit (MultispanIndex.multispan (diagram D)) F
inst✝ : (i j k : D.J) → PreservesLimit (cospan (f D i j) (f D i k)) F
x : F.obj (glued D)
⊢ ∃ i y, F.map (ι D i) y = x

Next tactic:
let e := D.gluedIso F
/-- If there is a forgetful functor into `Type` that preserves enough (co)limits, then `D.ι` will
be jointly surjective. -/
theorem ι_jointly_surjective (F : C ⥤ Type v) [PreservesColimit D.diagram.multispan F]
    [∀ i j k : D.J, PreservesLimit (cospan (D.f i j) (D.f i k)) F] (x : F.obj D.glued) :
    ∃ (i : _) (y : F.obj (D.U i)), F.map (D.ι i) y = x := by
  let e := D.gluedIso F
  

Proof state:
C : Type u₁
inst✝⁵ : Category.{v, u₁} C
C' : Type u₂
inst✝⁴ : Category.{v, u₂} C'
D : GlueData C
F✝ : C ⥤ C'
H : (i j k : D.J) → PreservesLimit (cospan (f D i j) (f D i k)) F✝
inst✝³ : HasMulticoequalizer (diagram D)
inst✝² : PreservesColimit (MultispanIndex.multispan (diagram D)) F✝
F : C ⥤ Type v
inst✝¹ : PreservesColimit (MultispanIndex.multispan (diagram D)) F
inst✝ : (i j k : D.J) → PreservesLimit (cospan (f D i j) (f D i k)) F
x : F.obj (glued D)
e : F.obj (glued D) ≅ glued (mapGlueData D F) := gluedIso D F
⊢ ∃ i y, F.map (ι D i) y = x

Next tactic:
obtain ⟨i, y, eq⟩ := (D.mapGlueData F).types_ι_jointly_surjective (e.hom x)
/-- If there is a forgetful functor into `Type` that preserves enough (co)limits, then `D.ι` will
be jointly surjective. -/
theorem ι_jointly_surjective (F : C ⥤ Type v) [PreservesColimit D.diagram.multispan F]
    [∀ i j k : D.J, PreservesLimit (cospan (D.f i j) (D.f i k)) F] (x : F.obj D.glued) :
    ∃ (i : _) (y : F.obj (D.U i)), F.map (D.ι i) y = x := by
  let e := D.gluedIso F
  obtain ⟨i, y, eq⟩ := (D.mapGlueData F).types_ι_jointly_surjective (e.hom x)
  

Proof state:
case intro.intro
C : Type u₁
inst✝⁵ : Category.{v, u₁} C
C' : Type u₂
inst✝⁴ : Category.{v, u₂} C'
D : GlueData C
F✝ : C ⥤ C'
H : (i j k : D.J) → PreservesLimit (cospan (f D i j) (f D i k)) F✝
inst✝³ : HasMulticoequalizer (diagram D)
inst✝² : PreservesColimit (MultispanIndex.multispan (diagram D)) F✝
F : C ⥤ Type v
inst✝¹ : PreservesColimit (MultispanIndex.multispan (diagram D)) F
inst✝ : (i j k : D.J) → PreservesLimit (cospan (f D i j) (f D i k)) F
x : F.obj (glued D)
e : F.obj (glued D) ≅ glued (mapGlueData D F) := gluedIso D F
i : (mapGlueData D F).J
y : U (mapGlueData D F) i
eq : ι (mapGlueData D F) i y = e.hom x
⊢ ∃ i y, F.map (ι D i) y = x

Next tactic:
replace eq := congr_arg e.inv eq
/-- If there is a forgetful functor into `Type` that preserves enough (co)limits, then `D.ι` will
be jointly surjective. -/
theorem ι_jointly_surjective (F : C ⥤ Type v) [PreservesColimit D.diagram.multispan F]
    [∀ i j k : D.J, PreservesLimit (cospan (D.f i j) (D.f i k)) F] (x : F.obj D.glued) :
    ∃ (i : _) (y : F.obj (D.U i)), F.map (D.ι i) y = x := by
  let e := D.gluedIso F
  obtain ⟨i, y, eq⟩ := (D.mapGlueData F).types_ι_jointly_surjective (e.hom x)
  replace eq := congr_arg e.inv eq
  

Proof state:
case intro.intro
C : Type u₁
inst✝⁵ : Category.{v, u₁} C
C' : Type u₂
inst✝⁴ : Category.{v, u₂} C'
D : GlueData C
F✝ : C ⥤ C'
H : (i j k : D.J) → PreservesLimit (cospan (f D i j) (f D i k)) F✝
inst✝³ : HasMulticoequalizer (diagram D)
inst✝² : PreservesColimit (MultispanIndex.multispan (diagram D)) F✝
F : C ⥤ Type v
inst✝¹ : PreservesColimit (MultispanIndex.multispan (diagram D)) F
inst✝ : (i j k : D.J) → PreservesLimit (cospan (f D i j) (f D i k)) F
x : F.obj (glued D)
e : F.obj (glued D) ≅ glued (mapGlueData D F) := gluedIso D F
i : (mapGlueData D F).J
y : U (mapGlueData D F) i
eq : e.inv (ι (mapGlueData D F) i y) = e.inv (e.hom x)
⊢ ∃ i y, F.map (ι D i) y = x

Next tactic:
change ((D.mapGlueData F).ι i ≫ e.inv) y = (e.hom ≫ e.inv) x at eq
/-- If there is a forgetful functor into `Type` that preserves enough (co)limits, then `D.ι` will
be jointly surjective. -/
theorem ι_jointly_surjective (F : C ⥤ Type v) [PreservesColimit D.diagram.multispan F]
    [∀ i j k : D.J, PreservesLimit (cospan (D.f i j) (D.f i k)) F] (x : F.obj D.glued) :
    ∃ (i : _) (y : F.obj (D.U i)), F.map (D.ι i) y = x := by
  let e := D.gluedIso F
  obtain ⟨i, y, eq⟩ := (D.mapGlueData F).types_ι_jointly_surjective (e.hom x)
  replace eq := congr_arg e.inv eq
  change ((D.mapGlueData F).ι i ≫ e.inv) y = (e.hom ≫ e.inv) x at eq
  

Proof state:
case intro.intro
C : Type u₁
inst✝⁵ : Category.{v, u₁} C
C' : Type u₂
inst✝⁴ : Category.{v, u₂} C'
D : GlueData C
F✝ : C ⥤ C'
H : (i j k : D.J) → PreservesLimit (cospan (f D i j) (f D i k)) F✝
inst✝³ : HasMulticoequalizer (diagram D)
inst✝² : PreservesColimit (MultispanIndex.multispan (diagram D)) F✝
F : C ⥤ Type v
inst✝¹ : PreservesColimit (MultispanIndex.multispan (diagram D)) F
inst✝ : (i j k : D.J) → PreservesLimit (cospan (f D i j) (f D i k)) F
x : F.obj (glued D)
e : F.obj (glued D) ≅ glued (mapGlueData D F) := gluedIso D F
i : (mapGlueData D F).J
y : U (mapGlueData D F) i
eq : (ι (mapGlueData D F) i ≫ e.inv) y = (e.hom ≫ e.inv) x
⊢ ∃ i y, F.map (ι D i) y = x

Next tactic:
rw [e.hom_inv_id, D.ι_gluedIso_inv] at eq
/-- If there is a forgetful functor into `Type` that preserves enough (co)limits, then `D.ι` will
be jointly surjective. -/
theorem ι_jointly_surjective (F : C ⥤ Type v) [PreservesColimit D.diagram.multispan F]
    [∀ i j k : D.J, PreservesLimit (cospan (D.f i j) (D.f i k)) F] (x : F.obj D.glued) :
    ∃ (i : _) (y : F.obj (D.U i)), F.map (D.ι i) y = x := by
  let e := D.gluedIso F
  obtain ⟨i, y, eq⟩ := (D.mapGlueData F).types_ι_jointly_surjective (e.hom x)
  replace eq := congr_arg e.inv eq
  change ((D.mapGlueData F).ι i ≫ e.inv) y = (e.hom ≫ e.inv) x at eq
  rw [e.hom_inv_id, D.ι_gluedIso_inv] at eq
  

Proof state:
case intro.intro
C : Type u₁
inst✝⁵ : Category.{v, u₁} C
C' : Type u₂
inst✝⁴ : Category.{v, u₂} C'
D : GlueData C
F✝ : C ⥤ C'
H : (i j k : D.J) → PreservesLimit (cospan (f D i j) (f D i k)) F✝
inst✝³ : HasMulticoequalizer (diagram D)
inst✝² : PreservesColimit (MultispanIndex.multispan (diagram D)) F✝
F : C ⥤ Type v
inst✝¹ : PreservesColimit (MultispanIndex.multispan (diagram D)) F
inst✝ : (i j k : D.J) → PreservesLimit (cospan (f D i j) (f D i k)) F
x : F.obj (glued D)
e : F.obj (glued D) ≅ glued (mapGlueData D F) := gluedIso D F
i : (mapGlueData D F).J
y : U (mapGlueData D F) i
eq : F.map (ι D i) y = 𝟙 (F.obj (glued D)) x
⊢ ∃ i y, F.map (ι D i) y = x

Next tactic:
exact ⟨i, y, eq⟩
protected theorem Sorted.gt_of_ge [PartialOrder α] {l : List α} (h₁ : l.Sorted (· ≥ ·))
    (h₂ : l.Nodup) : l.Sorted (· > ·) :=
  h₁.imp₂ (fun _ _ => lt_of_le_of_ne) <| by 

Proof state:
α : Type uu
r : α → α → Prop
a : α
l✝ : List α
inst✝ : PartialOrder α
l : List α
h₁ : Sorted (fun x x_1 => x ≥ x_1) l
h₂ : Nodup l
⊢ Pairwise (fun x x_1 => x_1 ≠ x) l

Next tactic:
simp_rw [ne_comm]
protected theorem Sorted.gt_of_ge [PartialOrder α] {l : List α} (h₁ : l.Sorted (· ≥ ·))
    (h₂ : l.Nodup) : l.Sorted (· > ·) :=
  h₁.imp₂ (fun _ _ => lt_of_le_of_ne) <| by simp_rw [ne_comm]; 

Proof state:
α : Type uu
r : α → α → Prop
a : α
l✝ : List α
inst✝ : PartialOrder α
l : List α
h₁ : Sorted (fun x x_1 => x ≥ x_1) l
h₂ : Nodup l
⊢ Pairwise (fun x x_1 => x ≠ x_1) l

Next tactic:
exact h₂
theorem Sorted.head!_le [Inhabited α] [Preorder α] {a : α} {l : List α} (h : Sorted (· < ·) l)
    (ha : a ∈ l) : l.head! ≤ a := by
  

Proof state:
α : Type uu
r : α → α → Prop
a✝ : α
l✝ : List α
inst✝¹ : Inhabited α
inst✝ : Preorder α
a : α
l : List α
h : Sorted (fun x x_1 => x < x_1) l
ha : a ∈ l
⊢ head! l ≤ a

Next tactic:
rw [← List.cons_head!_tail (List.ne_nil_of_mem ha)] at h ha
theorem Sorted.head!_le [Inhabited α] [Preorder α] {a : α} {l : List α} (h : Sorted (· < ·) l)
    (ha : a ∈ l) : l.head! ≤ a := by
  rw [← List.cons_head!_tail (List.ne_nil_of_mem ha)] at h ha
  

Proof state:
α : Type uu
r : α → α → Prop
a✝ : α
l✝ : List α
inst✝¹ : Inhabited α
inst✝ : Preorder α
a : α
l : List α
h : Sorted (fun x x_1 => x < x_1) (head! l :: List.tail l)
ha : a ∈ head! l :: List.tail l
⊢ head! l ≤ a

Next tactic:
cases ha
theorem Sorted.head!_le [Inhabited α] [Preorder α] {a : α} {l : List α} (h : Sorted (· < ·) l)
    (ha : a ∈ l) : l.head! ≤ a := by
  rw [← List.cons_head!_tail (List.ne_nil_of_mem ha)] at h ha
  cases ha
  · 

Proof state:
case head
α : Type uu
r : α → α → Prop
a : α
l✝ : List α
inst✝¹ : Inhabited α
inst✝ : Preorder α
l : List α
h : Sorted (fun x x_1 => x < x_1) (head! l :: List.tail l)
⊢ head! l ≤ head! l

Next tactic:
exact le_rfl
theorem Sorted.head!_le [Inhabited α] [Preorder α] {a : α} {l : List α} (h : Sorted (· < ·) l)
    (ha : a ∈ l) : l.head! ≤ a := by
  rw [← List.cons_head!_tail (List.ne_nil_of_mem ha)] at h ha
  cases ha
  · exact le_rfl
  · 

Proof state:
case tail
α : Type uu
r : α → α → Prop
a✝¹ : α
l✝ : List α
inst✝¹ : Inhabited α
inst✝ : Preorder α
a : α
l : List α
h : Sorted (fun x x_1 => x < x_1) (head! l :: List.tail l)
a✝ : Mem a (List.tail l)
⊢ head! l ≤ a

Next tactic:
exact le_of_lt (rel_of_sorted_cons h a (by assumption))
theorem Sorted.head!_le [Inhabited α] [Preorder α] {a : α} {l : List α} (h : Sorted (· < ·) l)
    (ha : a ∈ l) : l.head! ≤ a := by
  rw [← List.cons_head!_tail (List.ne_nil_of_mem ha)] at h ha
  cases ha
  · exact le_rfl
  · exact le_of_lt (rel_of_sorted_cons h a (by 

Proof state:
α : Type uu
r : α → α → Prop
a✝¹ : α
l✝ : List α
inst✝¹ : Inhabited α
inst✝ : Preorder α
a : α
l : List α
h : Sorted (fun x x_1 => x < x_1) (head! l :: List.tail l)
a✝ : Mem a (List.tail l)
⊢ a ∈ List.tail l

Next tactic:
assumption
theorem Sorted.le_head! [Inhabited α] [Preorder α] {a : α} {l : List α} (h : Sorted (· > ·) l)
    (ha : a ∈ l) : a ≤ l.head! := by
  

Proof state:
α : Type uu
r : α → α → Prop
a✝ : α
l✝ : List α
inst✝¹ : Inhabited α
inst✝ : Preorder α
a : α
l : List α
h : Sorted (fun x x_1 => x > x_1) l
ha : a ∈ l
⊢ a ≤ head! l

Next tactic:
rw [← List.cons_head!_tail (List.ne_nil_of_mem ha)] at h ha
theorem Sorted.le_head! [Inhabited α] [Preorder α] {a : α} {l : List α} (h : Sorted (· > ·) l)
    (ha : a ∈ l) : a ≤ l.head! := by
  rw [← List.cons_head!_tail (List.ne_nil_of_mem ha)] at h ha
  

Proof state:
α : Type uu
r : α → α → Prop
a✝ : α
l✝ : List α
inst✝¹ : Inhabited α
inst✝ : Preorder α
a : α
l : List α
h : Sorted (fun x x_1 => x > x_1) (head! l :: List.tail l)
ha : a ∈ head! l :: List.tail l
⊢ a ≤ head! l

Next tactic:
cases ha
theorem Sorted.le_head! [Inhabited α] [Preorder α] {a : α} {l : List α} (h : Sorted (· > ·) l)
    (ha : a ∈ l) : a ≤ l.head! := by
  rw [← List.cons_head!_tail (List.ne_nil_of_mem ha)] at h ha
  cases ha
  · 

Proof state:
case head
α : Type uu
r : α → α → Prop
a : α
l✝ : List α
inst✝¹ : Inhabited α
inst✝ : Preorder α
l : List α
h : Sorted (fun x x_1 => x > x_1) (head! l :: List.tail l)
⊢ head! l ≤ head! l

Next tactic:
exact le_rfl
theorem Sorted.le_head! [Inhabited α] [Preorder α] {a : α} {l : List α} (h : Sorted (· > ·) l)
    (ha : a ∈ l) : a ≤ l.head! := by
  rw [← List.cons_head!_tail (List.ne_nil_of_mem ha)] at h ha
  cases ha
  · exact le_rfl
  · 

Proof state:
case tail
α : Type uu
r : α → α → Prop
a✝¹ : α
l✝ : List α
inst✝¹ : Inhabited α
inst✝ : Preorder α
a : α
l : List α
h : Sorted (fun x x_1 => x > x_1) (head! l :: List.tail l)
a✝ : Mem a (List.tail l)
⊢ a ≤ head! l

Next tactic:
exact le_of_lt (rel_of_sorted_cons h a (by assumption))
theorem Sorted.le_head! [Inhabited α] [Preorder α] {a : α} {l : List α} (h : Sorted (· > ·) l)
    (ha : a ∈ l) : a ≤ l.head! := by
  rw [← List.cons_head!_tail (List.ne_nil_of_mem ha)] at h ha
  cases ha
  · exact le_rfl
  · exact le_of_lt (rel_of_sorted_cons h a (by 

Proof state:
α : Type uu
r : α → α → Prop
a✝¹ : α
l✝ : List α
inst✝¹ : Inhabited α
inst✝ : Preorder α
a : α
l : List α
h : Sorted (fun x x_1 => x > x_1) (head! l :: List.tail l)
a✝ : Mem a (List.tail l)
⊢ a ∈ List.tail l

Next tactic:
assumption
theorem eq_of_perm_of_sorted [IsAntisymm α r] {l₁ l₂ : List α} (p : l₁ ~ l₂) (s₁ : Sorted r l₁)
    (s₂ : Sorted r l₂) : l₁ = l₂ := by
  

Proof state:
α : Type uu
r : α → α → Prop
a : α
l : List α
inst✝ : IsAntisymm α r
l₁ l₂ : List α
p : l₁ ~ l₂
s₁ : Sorted r l₁
s₂ : Sorted r l₂
⊢ l₁ = l₂

Next tactic:
induction' s₁ with a l₁ h₁ s₁ IH generalizing l₂
theorem eq_of_perm_of_sorted [IsAntisymm α r] {l₁ l₂ : List α} (p : l₁ ~ l₂) (s₁ : Sorted r l₁)
    (s₂ : Sorted r l₂) : l₁ = l₂ := by
  induction' s₁ with a l₁ h₁ s₁ IH generalizing l₂
  · 

Proof state:
case nil
α : Type uu
r : α → α → Prop
a : α
l : List α
inst✝ : IsAntisymm α r
l₁ l₂ : List α
p : [] ~ l₂
s₂ : Sorted r l₂
⊢ [] = l₂

Next tactic:
exact p.nil_eq
theorem eq_of_perm_of_sorted [IsAntisymm α r] {l₁ l₂ : List α} (p : l₁ ~ l₂) (s₁ : Sorted r l₁)
    (s₂ : Sorted r l₂) : l₁ = l₂ := by
  induction' s₁ with a l₁ h₁ s₁ IH generalizing l₂
  · exact p.nil_eq
  · 

Proof state:
case cons
α : Type uu
r : α → α → Prop
a✝ : α
l : List α
inst✝ : IsAntisymm α r
l₁✝ : List α
a : α
l₁ : List α
h₁ : ∀ a' ∈ l₁, r a a'
s₁ : Pairwise r l₁
IH : ∀ {l₂ : List α}, l₁ ~ l₂ → Sorted r l₂ → l₁ = l₂
l₂ : List α
p : a :: l₁ ~ l₂
s₂ : Sorted r l₂
⊢ a :: l₁ = l₂

Next tactic:
have : a ∈ l₂ := p.subset (mem_cons_self _ _)
theorem eq_of_perm_of_sorted [IsAntisymm α r] {l₁ l₂ : List α} (p : l₁ ~ l₂) (s₁ : Sorted r l₁)
    (s₂ : Sorted r l₂) : l₁ = l₂ := by
  induction' s₁ with a l₁ h₁ s₁ IH generalizing l₂
  · exact p.nil_eq
  · have : a ∈ l₂ := p.subset (mem_cons_self _ _)
    

Proof state:
case cons
α : Type uu
r : α → α → Prop
a✝ : α
l : List α
inst✝ : IsAntisymm α r
l₁✝ : List α
a : α
l₁ : List α
h₁ : ∀ a' ∈ l₁, r a a'
s₁ : Pairwise r l₁
IH : ∀ {l₂ : List α}, l₁ ~ l₂ → Sorted r l₂ → l₁ = l₂
l₂ : List α
p : a :: l₁ ~ l₂
s₂ : Sorted r l₂
this : a ∈ l₂
⊢ a :: l₁ = l₂

Next tactic:
rcases mem_split this with ⟨u₂, v₂, rfl⟩
theorem eq_of_perm_of_sorted [IsAntisymm α r] {l₁ l₂ : List α} (p : l₁ ~ l₂) (s₁ : Sorted r l₁)
    (s₂ : Sorted r l₂) : l₁ = l₂ := by
  induction' s₁ with a l₁ h₁ s₁ IH generalizing l₂
  · exact p.nil_eq
  · have : a ∈ l₂ := p.subset (mem_cons_self _ _)
    rcases mem_split this with ⟨u₂, v₂, rfl⟩
    

Proof state:
case cons.intro.intro
α : Type uu
r : α → α → Prop
a✝ : α
l : List α
inst✝ : IsAntisymm α r
l₁✝ : List α
a : α
l₁ : List α
h₁ : ∀ a' ∈ l₁, r a a'
s₁ : Pairwise r l₁
IH : ∀ {l₂ : List α}, l₁ ~ l₂ → Sorted r l₂ → l₁ = l₂
u₂ v₂ : List α
p : a :: l₁ ~ u₂ ++ a :: v₂
s₂ : Sorted r (u₂ ++ a :: v₂)
this : a ∈ u₂ ++ a :: v₂
⊢ a :: l₁ = u₂ ++ a :: v₂

Next tactic:
have p' := (perm_cons a).1 (p.trans perm_middle)
theorem eq_of_perm_of_sorted [IsAntisymm α r] {l₁ l₂ : List α} (p : l₁ ~ l₂) (s₁ : Sorted r l₁)
    (s₂ : Sorted r l₂) : l₁ = l₂ := by
  induction' s₁ with a l₁ h₁ s₁ IH generalizing l₂
  · exact p.nil_eq
  · have : a ∈ l₂ := p.subset (mem_cons_self _ _)
    rcases mem_split this with ⟨u₂, v₂, rfl⟩
    have p' := (perm_cons a).1 (p.trans perm_middle)
    

Proof state:
case cons.intro.intro
α : Type uu
r : α → α → Prop
a✝ : α
l : List α
inst✝ : IsAntisymm α r
l₁✝ : List α
a : α
l₁ : List α
h₁ : ∀ a' ∈ l₁, r a a'
s₁ : Pairwise r l₁
IH : ∀ {l₂ : List α}, l₁ ~ l₂ → Sorted r l₂ → l₁ = l₂
u₂ v₂ : List α
p : a :: l₁ ~ u₂ ++ a :: v₂
s₂ : Sorted r (u₂ ++ a :: v₂)
this : a ∈ u₂ ++ a :: v₂
p' : l₁ ~ u₂ ++ v₂
⊢ a :: l₁ = u₂ ++ a :: v₂

Next tactic:
obtain rfl := IH p' (s₂.sublist <| by simp)
theorem eq_of_perm_of_sorted [IsAntisymm α r] {l₁ l₂ : List α} (p : l₁ ~ l₂) (s₁ : Sorted r l₁)
    (s₂ : Sorted r l₂) : l₁ = l₂ := by
  induction' s₁ with a l₁ h₁ s₁ IH generalizing l₂
  · exact p.nil_eq
  · have : a ∈ l₂ := p.subset (mem_cons_self _ _)
    rcases mem_split this with ⟨u₂, v₂, rfl⟩
    have p' := (perm_cons a).1 (p.trans perm_middle)
    obtain rfl := IH p' (s₂.sublist <| by 

Proof state:
α : Type uu
r : α → α → Prop
a✝ : α
l : List α
inst✝ : IsAntisymm α r
l₁✝ : List α
a : α
l₁ : List α
h₁ : ∀ a' ∈ l₁, r a a'
s₁ : Pairwise r l₁
IH : ∀ {l₂ : List α}, l₁ ~ l₂ → Sorted r l₂ → l₁ = l₂
u₂ v₂ : List α
p : a :: l₁ ~ u₂ ++ a :: v₂
s₂ : Sorted r (u₂ ++ a :: v₂)
this : a ∈ u₂ ++ a :: v₂
p' : l₁ ~ u₂ ++ v₂
⊢ u₂ ++ v₂ <+ u₂ ++ a :: v₂

Next tactic:
simp
theorem eq_of_perm_of_sorted [IsAntisymm α r] {l₁ l₂ : List α} (p : l₁ ~ l₂) (s₁ : Sorted r l₁)
    (s₂ : Sorted r l₂) : l₁ = l₂ := by
  induction' s₁ with a l₁ h₁ s₁ IH generalizing l₂
  · exact p.nil_eq
  · have : a ∈ l₂ := p.subset (mem_cons_self _ _)
    rcases mem_split this with ⟨u₂, v₂, rfl⟩
    have p' := (perm_cons a).1 (p.trans perm_middle)
    obtain rfl := IH p' (s₂.sublist <| by simp)
    

Proof state:
case cons.intro.intro
α : Type uu
r : α → α → Prop
a✝ : α
l : List α
inst✝ : IsAntisymm α r
l₁ : List α
a : α
u₂ v₂ : List α
s₂ : Sorted r (u₂ ++ a :: v₂)
this : a ∈ u₂ ++ a :: v₂
h₁ : ∀ a' ∈ u₂ ++ v₂, r a a'
s₁ : Pairwise r (u₂ ++ v₂)
IH : ∀ {l₂ : List α}, u₂ ++ v₂ ~ l₂ → Sorted r l₂ → u₂ ++ v₂ = l₂
p : a :: (u₂ ++ v₂) ~ u₂ ++ a :: v₂
p' : u₂ ++ v₂ ~ u₂ ++ v₂
⊢ a :: (u₂ ++ v₂) = u₂ ++ a :: v₂

Next tactic:
change a :: u₂ ++ v₂ = u₂ ++ ([a] ++ v₂)
theorem eq_of_perm_of_sorted [IsAntisymm α r] {l₁ l₂ : List α} (p : l₁ ~ l₂) (s₁ : Sorted r l₁)
    (s₂ : Sorted r l₂) : l₁ = l₂ := by
  induction' s₁ with a l₁ h₁ s₁ IH generalizing l₂
  · exact p.nil_eq
  · have : a ∈ l₂ := p.subset (mem_cons_self _ _)
    rcases mem_split this with ⟨u₂, v₂, rfl⟩
    have p' := (perm_cons a).1 (p.trans perm_middle)
    obtain rfl := IH p' (s₂.sublist <| by simp)
    change a :: u₂ ++ v₂ = u₂ ++ ([a] ++ v₂)
    

Proof state:
case cons.intro.intro
α : Type uu
r : α → α → Prop
a✝ : α
l : List α
inst✝ : IsAntisymm α r
l₁ : List α
a : α
u₂ v₂ : List α
s₂ : Sorted r (u₂ ++ a :: v₂)
this : a ∈ u₂ ++ a :: v₂
h₁ : ∀ a' ∈ u₂ ++ v₂, r a a'
s₁ : Pairwise r (u₂ ++ v₂)
IH : ∀ {l₂ : List α}, u₂ ++ v₂ ~ l₂ → Sorted r l₂ → u₂ ++ v₂ = l₂
p : a :: (u₂ ++ v₂) ~ u₂ ++ a :: v₂
p' : u₂ ++ v₂ ~ u₂ ++ v₂
⊢ a :: u₂ ++ v₂ = u₂ ++ ([a] ++ v₂)

Next tactic:
rw [← append_assoc]
theorem eq_of_perm_of_sorted [IsAntisymm α r] {l₁ l₂ : List α} (p : l₁ ~ l₂) (s₁ : Sorted r l₁)
    (s₂ : Sorted r l₂) : l₁ = l₂ := by
  induction' s₁ with a l₁ h₁ s₁ IH generalizing l₂
  · exact p.nil_eq
  · have : a ∈ l₂ := p.subset (mem_cons_self _ _)
    rcases mem_split this with ⟨u₂, v₂, rfl⟩
    have p' := (perm_cons a).1 (p.trans perm_middle)
    obtain rfl := IH p' (s₂.sublist <| by simp)
    change a :: u₂ ++ v₂ = u₂ ++ ([a] ++ v₂)
    rw [← append_assoc]
    

Proof state:
case cons.intro.intro
α : Type uu
r : α → α → Prop
a✝ : α
l : List α
inst✝ : IsAntisymm α r
l₁ : List α
a : α
u₂ v₂ : List α
s₂ : Sorted r (u₂ ++ a :: v₂)
this : a ∈ u₂ ++ a :: v₂
h₁ : ∀ a' ∈ u₂ ++ v₂, r a a'
s₁ : Pairwise r (u₂ ++ v₂)
IH : ∀ {l₂ : List α}, u₂ ++ v₂ ~ l₂ → Sorted r l₂ → u₂ ++ v₂ = l₂
p : a :: (u₂ ++ v₂) ~ u₂ ++ a :: v₂
p' : u₂ ++ v₂ ~ u₂ ++ v₂
⊢ a :: u₂ ++ v₂ = u₂ ++ [a] ++ v₂

Next tactic:
congr