l3lab/ntp-mathlib huggingface dataset:
theorem hyperplane_separation_of_nmem (K : ProperCone ℝ E) {f : E →L[ℝ] F} {b : F}
    (disj : b ∉ K.map f) : ∃ y : F, adjoint f y ∈ K.dual ∧ ⟪y, b⟫_ℝ < 0 := by
  

Proof state:
E : Type u_1
inst✝⁵ : NormedAddCommGroup E
inst✝⁴ : InnerProductSpace ℝ E
inst✝³ : CompleteSpace E
F : Type u_2
inst✝² : NormedAddCommGroup F
inst✝¹ : InnerProductSpace ℝ F
inst✝ : CompleteSpace F
K : ProperCone ℝ E
f : E →L[ℝ] F
b : F
disj : b ∉ map f K
⊢ ∃ y, (adjoint f) y ∈ dual K ∧ inner y b < 0

Next tactic:
contrapose! disj
theorem hyperplane_separation_of_nmem (K : ProperCone ℝ E) {f : E →L[ℝ] F} {b : F}
    (disj : b ∉ K.map f) : ∃ y : F, adjoint f y ∈ K.dual ∧ ⟪y, b⟫_ℝ < 0 := by
  contrapose! disj; 

Proof state:
E : Type u_1
inst✝⁵ : NormedAddCommGroup E
inst✝⁴ : InnerProductSpace ℝ E
inst✝³ : CompleteSpace E
F : Type u_2
inst✝² : NormedAddCommGroup F
inst✝¹ : InnerProductSpace ℝ F
inst✝ : CompleteSpace F
K : ProperCone ℝ E
f : E →L[ℝ] F
b : F
disj : ∀ (y : F), (adjoint f) y ∈ dual K → 0 ≤ inner y b
⊢ b ∈ map f K

Next tactic:
rwa [K.hyperplane_separation]
/-- Given for all `a : α` a finset `t a` of `δ a`, then one can define the
finset `Fintype.piFinset t` of all functions taking values in `t a` for all `a`. This is the
analogue of `Finset.pi` where the base finset is `univ` (but formally they are not the same, as
there is an additional condition `i ∈ Finset.univ` in the `Finset.pi` definition). -/
def piFinset (t : ∀ a, Finset (δ a)) : Finset (∀ a, δ a) :=
  (Finset.univ.pi t).map ⟨fun f a => f a (mem_univ a), fun _ _ =>
    by 

Proof state:
α : Type u_1
inst✝¹ : DecidableEq α
inst✝ : Fintype α
δ : α → Type u_2
t : (a : α) → Finset (δ a)
x✝¹ x✝ : (a : α) → a ∈ univ → δ a
⊢ (fun f a => f a (_ : a ∈ univ)) x✝¹ = (fun f a => f a (_ : a ∈ univ)) x✝ → x✝¹ = x✝

Next tactic:
simp (config := {contextual := true}) [Function.funext_iff]
@[simp]
theorem mem_piFinset {t : ∀ a, Finset (δ a)} {f : ∀ a, δ a} : f ∈ piFinset t ↔ ∀ a, f a ∈ t a := by
  

Proof state:
α : Type u_1
inst✝¹ : DecidableEq α
inst✝ : Fintype α
δ : α → Type u_2
t : (a : α) → Finset (δ a)
f : (a : α) → δ a
⊢ f ∈ piFinset t ↔ ∀ (a : α), f a ∈ t a

Next tactic:
constructor
@[simp]
theorem mem_piFinset {t : ∀ a, Finset (δ a)} {f : ∀ a, δ a} : f ∈ piFinset t ↔ ∀ a, f a ∈ t a := by
  constructor
  · 

Proof state:
case mp
α : Type u_1
inst✝¹ : DecidableEq α
inst✝ : Fintype α
δ : α → Type u_2
t : (a : α) → Finset (δ a)
f : (a : α) → δ a
⊢ f ∈ piFinset t → ∀ (a : α), f a ∈ t a

Next tactic:
simp only [piFinset, mem_map, and_imp, forall_prop_of_true, exists_prop, mem_univ, exists_imp,
      mem_pi]
@[simp]
theorem mem_piFinset {t : ∀ a, Finset (δ a)} {f : ∀ a, δ a} : f ∈ piFinset t ↔ ∀ a, f a ∈ t a := by
  constructor
  · simp only [piFinset, mem_map, and_imp, forall_prop_of_true, exists_prop, mem_univ, exists_imp,
      mem_pi]
    

Proof state:
case mp
α : Type u_1
inst✝¹ : DecidableEq α
inst✝ : Fintype α
δ : α → Type u_2
t : (a : α) → Finset (δ a)
f : (a : α) → δ a
⊢ ∀ (x : (a : α) → a ∈ univ → δ a),
    (∀ (a : α), x a (_ : a ∈ univ) ∈ t a) →
      { toFun := fun f a => f a (_ : a ∈ univ),
              inj' :=
                (_ :
                  ∀ (x x_1 : (a : α) → a ∈ univ → δ a),
                    ((fun a => x a (_ : a ∈ univ)) = fun a => x_1 a (_ : a ∈ univ)) → x = x_1) }
            x =
          f →
        ∀ (a : α), f a ∈ t a

Next tactic:
rintro g hg hgf a
@[simp]
theorem mem_piFinset {t : ∀ a, Finset (δ a)} {f : ∀ a, δ a} : f ∈ piFinset t ↔ ∀ a, f a ∈ t a := by
  constructor
  · simp only [piFinset, mem_map, and_imp, forall_prop_of_true, exists_prop, mem_univ, exists_imp,
      mem_pi]
    rintro g hg hgf a
    

Proof state:
case mp
α : Type u_1
inst✝¹ : DecidableEq α
inst✝ : Fintype α
δ : α → Type u_2
t : (a : α) → Finset (δ a)
f : (a : α) → δ a
g : (a : α) → a ∈ univ → δ a
hg : ∀ (a : α), g a (_ : a ∈ univ) ∈ t a
hgf :
  { toFun := fun f a => f a (_ : a ∈ univ),
        inj' :=
          (_ :
            ∀ (x x_1 : (a : α) → a ∈ univ → δ a),
              ((fun a => x a (_ : a ∈ univ)) = fun a => x_1 a (_ : a ∈ univ)) → x = x_1) }
      g =
    f
a : α
⊢ f a ∈ t a

Next tactic:
rw [← hgf]
@[simp]
theorem mem_piFinset {t : ∀ a, Finset (δ a)} {f : ∀ a, δ a} : f ∈ piFinset t ↔ ∀ a, f a ∈ t a := by
  constructor
  · simp only [piFinset, mem_map, and_imp, forall_prop_of_true, exists_prop, mem_univ, exists_imp,
      mem_pi]
    rintro g hg hgf a
    rw [← hgf]
    

Proof state:
case mp
α : Type u_1
inst✝¹ : DecidableEq α
inst✝ : Fintype α
δ : α → Type u_2
t : (a : α) → Finset (δ a)
f : (a : α) → δ a
g : (a : α) → a ∈ univ → δ a
hg : ∀ (a : α), g a (_ : a ∈ univ) ∈ t a
hgf :
  { toFun := fun f a => f a (_ : a ∈ univ),
        inj' :=
          (_ :
            ∀ (x x_1 : (a : α) → a ∈ univ → δ a),
              ((fun a => x a (_ : a ∈ univ)) = fun a => x_1 a (_ : a ∈ univ)) → x = x_1) }
      g =
    f
a : α
⊢ { toFun := fun f a => f a (_ : a ∈ univ),
        inj' :=
          (_ :
            ∀ (x x_1 : (a : α) → a ∈ univ → δ a),
              ((fun a => x a (_ : a ∈ univ)) = fun a => x_1 a (_ : a ∈ univ)) → x = x_1) }
      g a ∈
    t a

Next tactic:
exact hg a
@[simp]
theorem mem_piFinset {t : ∀ a, Finset (δ a)} {f : ∀ a, δ a} : f ∈ piFinset t ↔ ∀ a, f a ∈ t a := by
  constructor
  · simp only [piFinset, mem_map, and_imp, forall_prop_of_true, exists_prop, mem_univ, exists_imp,
      mem_pi]
    rintro g hg hgf a
    rw [← hgf]
    exact hg a
  · 

Proof state:
case mpr
α : Type u_1
inst✝¹ : DecidableEq α
inst✝ : Fintype α
δ : α → Type u_2
t : (a : α) → Finset (δ a)
f : (a : α) → δ a
⊢ (∀ (a : α), f a ∈ t a) → f ∈ piFinset t

Next tactic:
simp only [piFinset, mem_map, forall_prop_of_true, exists_prop, mem_univ, mem_pi]
@[simp]
theorem mem_piFinset {t : ∀ a, Finset (δ a)} {f : ∀ a, δ a} : f ∈ piFinset t ↔ ∀ a, f a ∈ t a := by
  constructor
  · simp only [piFinset, mem_map, and_imp, forall_prop_of_true, exists_prop, mem_univ, exists_imp,
      mem_pi]
    rintro g hg hgf a
    rw [← hgf]
    exact hg a
  · simp only [piFinset, mem_map, forall_prop_of_true, exists_prop, mem_univ, mem_pi]
    

Proof state:
case mpr
α : Type u_1
inst✝¹ : DecidableEq α
inst✝ : Fintype α
δ : α → Type u_2
t : (a : α) → Finset (δ a)
f : (a : α) → δ a
⊢ (∀ (a : α), f a ∈ t a) →
    ∃ a,
      (∀ (a_1 : α), a a_1 (_ : a_1 ∈ univ) ∈ t a_1) ∧
        { toFun := fun f a => f a (_ : a ∈ univ),
              inj' :=
                (_ :
                  ∀ (x x_1 : (a : α) → a ∈ univ → δ a),
                    ((fun a => x a (_ : a ∈ univ)) = fun a => x_1 a (_ : a ∈ univ)) → x = x_1) }
            a =
          f

Next tactic:
exact fun hf => ⟨fun a _ => f a, hf, rfl⟩
@[simp]
theorem coe_piFinset (t : ∀ a, Finset (δ a)) :
    (piFinset t : Set (∀ a, δ a)) = Set.pi Set.univ fun a => t a :=
  Set.ext fun x => by
    

Proof state:
α : Type u_1
inst✝¹ : DecidableEq α
inst✝ : Fintype α
δ : α → Type u_2
t : (a : α) → Finset (δ a)
x : (a : α) → δ a
⊢ x ∈ ↑(piFinset t) ↔ x ∈ Set.pi Set.univ fun a => ↑(t a)

Next tactic:
rw [Set.mem_univ_pi]
@[simp]
theorem coe_piFinset (t : ∀ a, Finset (δ a)) :
    (piFinset t : Set (∀ a, δ a)) = Set.pi Set.univ fun a => t a :=
  Set.ext fun x => by
    rw [Set.mem_univ_pi]
    

Proof state:
α : Type u_1
inst✝¹ : DecidableEq α
inst✝ : Fintype α
δ : α → Type u_2
t : (a : α) → Finset (δ a)
x : (a : α) → δ a
⊢ x ∈ ↑(piFinset t) ↔ ∀ (i : α), x i ∈ ↑(t i)

Next tactic:
exact Fintype.mem_piFinset
@[simp]
theorem piFinset_empty [Nonempty α] : piFinset (fun _ => ∅ : ∀ i, Finset (δ i)) = ∅ :=
  eq_empty_of_forall_not_mem fun _ => by 

Proof state:
α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : Fintype α
δ : α → Type u_2
inst✝ : Nonempty α
x✝ : (a : α) → δ a
⊢ x✝ ∉ piFinset fun x => ∅

Next tactic:
simp
@[simp]
theorem piFinset_singleton (f : ∀ i, δ i) : piFinset (fun i => {f i} : ∀ i, Finset (δ i)) = {f} :=
  ext fun _ => by 

Proof state:
α : Type u_1
inst✝¹ : DecidableEq α
inst✝ : Fintype α
δ : α → Type u_2
f x✝ : (a : α) → δ a
⊢ (x✝ ∈ piFinset fun i => {f i}) ↔ x✝ ∈ {f}

Next tactic:
simp only [Function.funext_iff, Fintype.mem_piFinset, mem_singleton]
/-- A dependent product of fintypes, indexed by a fintype, is a fintype. -/
instance Pi.fintype {α : Type*} {β : α → Type*} [DecidableEq α] [Fintype α]
    [∀ a, Fintype (β a)] : Fintype (∀ a, β a) :=
  ⟨Fintype.piFinset fun _ => univ, by 

Proof state:
α✝ : Type u_1
α : Type u_2
β : α → Type u_3
inst✝² : DecidableEq α
inst✝¹ : Fintype α
inst✝ : (a : α) → Fintype (β a)
⊢ ∀ (x : (a : α) → β a), x ∈ Fintype.piFinset fun x => univ

Next tactic:
simp
noncomputable instance _root_.Function.Embedding.fintype {α β} [Fintype α] [Fintype β] :
  Fintype (α ↪ β) :=
  by 

Proof state:
α✝ : Type u_1
α : Type ?u.19016
β : Type ?u.19019
inst✝¹ : Fintype α
inst✝ : Fintype β
⊢ Fintype (α ↪ β)

Next tactic:
classical. exact Fintype.ofEquiv _ (Equiv.subtypeInjectiveEquivEmbedding α β)
noncomputable instance _root_.Function.Embedding.fintype {α β} [Fintype α] [Fintype β] :
  Fintype (α ↪ β) :=
  by classical. 

Proof state:
α✝ : Type u_1
α : Type ?u.19016
β : Type ?u.19019
inst✝¹ : Fintype α
inst✝ : Fintype β
⊢ Fintype (α ↪ β)

Next tactic:
exact Fintype.ofEquiv _ (Equiv.subtypeInjectiveEquivEmbedding α β)
@[simp]
theorem Finset.univ_pi_univ {α : Type*} {β : α → Type*} [DecidableEq α] [Fintype α]
    [∀ a, Fintype (β a)] :
    (Finset.univ.pi fun a : α => (Finset.univ : Finset (β a))) = Finset.univ := by
  

Proof state:
α✝ : Type u_1
α : Type u_2
β : α → Type u_3
inst✝² : DecidableEq α
inst✝¹ : Fintype α
inst✝ : (a : α) → Fintype (β a)
⊢ (pi univ fun a => univ) = univ

Next tactic:
ext
@[simp]
theorem Finset.univ_pi_univ {α : Type*} {β : α → Type*} [DecidableEq α] [Fintype α]
    [∀ a, Fintype (β a)] :
    (Finset.univ.pi fun a : α => (Finset.univ : Finset (β a))) = Finset.univ := by
  ext; 

Proof state:
case a
α✝ : Type u_1
α : Type u_2
β : α → Type u_3
inst✝² : DecidableEq α
inst✝¹ : Fintype α
inst✝ : (a : α) → Fintype (β a)
a✝ : (a : α) → a ∈ univ → β a
⊢ (a✝ ∈ pi univ fun a => univ) ↔ a✝ ∈ univ

Next tactic:
simp
lemma Fin.mem_piFinset_succ_iff {n : ℕ} {α : Fin (n + 1) → Type*} (p : (i : Fin (n + 1)) → α i)
    (S : (i : Fin (n + 1)) → Finset (α i)) :
    p ∈ Fintype.piFinset S ↔ p 0 ∈ S 0 ∧ Fin.tail p ∈ Fintype.piFinset (Fin.tail S) := by
  

Proof state:
α✝ : Type u_1
n : ℕ
α : Fin (n + 1) → Type u_2
p : (i : Fin (n + 1)) → α i
S : (i : Fin (n + 1)) → Finset (α i)
⊢ p ∈ Fintype.piFinset S ↔ p 0 ∈ S 0 ∧ tail p ∈ Fintype.piFinset (tail S)

Next tactic:
simp only [Fintype.mem_piFinset, forall_fin_succ, Fin.tail]
lemma Fin.cons_mem_piFinset_cons_iff {n : ℕ} {α : Fin (n + 1) → Type*}
    (x : α 0) (xs : (i : Fin n) → α i.succ)
    (S₀ : Finset (α 0)) (Sᵢ : (i : Fin n) → Finset (α i.succ)) :
    Fin.cons x xs ∈ Fintype.piFinset (Fin.cons S₀ Sᵢ) ↔ x ∈ S₀ ∧ xs ∈ Fintype.piFinset Sᵢ := by
  

Proof state:
α✝ : Type u_1
n : ℕ
α : Fin (n + 1) → Type u_2
x : α 0
xs : (i : Fin n) → α (succ i)
S₀ : Finset (α 0)
Sᵢ : (i : Fin n) → Finset (α (succ i))
⊢ cons x xs ∈ Fintype.piFinset (cons S₀ Sᵢ) ↔ x ∈ S₀ ∧ xs ∈ Fintype.piFinset Sᵢ

Next tactic:
simp_rw [Fin.mem_piFinset_succ_iff, cons_zero, tail_cons]
lemma Fin.mem_piFinset_succ_iff' {n : ℕ} {α : Fin (n + 1) → Type*} (p : (i : Fin (n + 1)) → α i)
    (S : (i : Fin (n + 1)) → Finset (α i)) :
    p ∈ Fintype.piFinset S ↔
      Fin.init p ∈ Fintype.piFinset (Fin.init S) ∧ p (Fin.last n) ∈ S (Fin.last n) := by
  

Proof state:
α✝ : Type u_1
n : ℕ
α : Fin (n + 1) → Type u_2
p : (i : Fin (n + 1)) → α i
S : (i : Fin (n + 1)) → Finset (α i)
⊢ p ∈ Fintype.piFinset S ↔ init p ∈ Fintype.piFinset (init S) ∧ p (last n) ∈ S (last n)

Next tactic:
simp only [Fintype.mem_piFinset, forall_fin_succ', Fin.init]
lemma Fin.snoc_mem_piFinset_snoc_iff {n : ℕ} {α : Fin (n + 1) → Type*}
    (xs : (i : Fin n) → α i.castSucc) (x : α (.last n))
    (Sᵢ : (i : Fin n) → Finset (α i.castSucc)) (Sₙ : Finset (α <| .last n)) :
    Fin.snoc xs x ∈ Fintype.piFinset (Fin.snoc Sᵢ Sₙ) ↔ xs ∈ Fintype.piFinset Sᵢ ∧ x ∈ Sₙ := by
  

Proof state:
α✝ : Type u_1
n : ℕ
α : Fin (n + 1) → Type u_2
xs : (i : Fin n) → α (castSucc i)
x : α (last n)
Sᵢ : (i : Fin n) → Finset (α (castSucc i))
Sₙ : Finset (α (last n))
⊢ snoc xs x ∈ Fintype.piFinset (snoc Sᵢ Sₙ) ↔ xs ∈ Fintype.piFinset Sᵢ ∧ x ∈ Sₙ

Next tactic:
simp_rw [Fin.mem_piFinset_succ_iff', init_snoc, snoc_last]
/--
The equivalence between the ulift of the explicit limit cone of a functor `K` and the explicit limit
cone of `K ⋙ uliftFunctor`.
-/
def sectionsEquiv {J : Type u} [Category.{u, u} J] (K : J ⥤ Type u) :
    uliftFunctor.{v, u}.obj (Functor.sections K) ≃
      (Functor.sections (K ⋙ uliftFunctor.{v, u})) where
  toFun := fun ⟨u, hu⟩ => ⟨fun j => ⟨u j⟩, fun f => by 

Proof state:
J : Type u
inst✝ : Category.{u, u} J
K : J ⥤ Type u
x✝ : uliftFunctor.{v, u}.obj ↑(Functor.sections K)
u : (j : J) → K.obj j
hu : u ∈ Functor.sections K
j✝ j'✝ : J
f : j✝ ⟶ j'✝
⊢ (K ⋙ uliftFunctor.{v, u}).map f ((fun j => { down := u j }) j✝) = (fun j => { down := u j }) j'✝

Next tactic:
simp [hu f]
/--
The equivalence between the ulift of the explicit limit cone of a functor `K` and the explicit limit
cone of `K ⋙ uliftFunctor`.
-/
def sectionsEquiv {J : Type u} [Category.{u, u} J] (K : J ⥤ Type u) :
    uliftFunctor.{v, u}.obj (Functor.sections K) ≃
      (Functor.sections (K ⋙ uliftFunctor.{v, u})) where
  toFun := fun ⟨u, hu⟩ => ⟨fun j => ⟨u j⟩, fun f => by simp [hu f]⟩
  invFun := fun ⟨u, hu⟩ => ⟨fun j => (u j).down, fun f => by 

Proof state:
J : Type u
inst✝ : Category.{u, u} J
K : J ⥤ Type u
x✝ : ↑(Functor.sections (K ⋙ uliftFunctor.{v, u}))
u : (j : J) → (K ⋙ uliftFunctor.{v, u}).obj j
hu : u ∈ Functor.sections (K ⋙ uliftFunctor.{v, u})
j✝ j'✝ : J
f : j✝ ⟶ j'✝
⊢ K.map f ((fun j => (u j).down) j✝) = (fun j => (u j).down) j'✝

Next tactic:
simp [← hu f]
/--
The equivalence between the ulift of the explicit limit cone of a functor `K` and the explicit limit
cone of `K ⋙ uliftFunctor`.
-/
def sectionsEquiv {J : Type u} [Category.{u, u} J] (K : J ⥤ Type u) :
    uliftFunctor.{v, u}.obj (Functor.sections K) ≃
      (Functor.sections (K ⋙ uliftFunctor.{v, u})) where
  toFun := fun ⟨u, hu⟩ => ⟨fun j => ⟨u j⟩, fun f => by simp [hu f]⟩
  invFun := fun ⟨u, hu⟩ => ⟨fun j => (u j).down, fun f => by simp [← hu f]⟩
  left_inv _ := by 

Proof state:
J : Type u
inst✝ : Category.{u, u} J
K : J ⥤ Type u
x✝ : uliftFunctor.{v, u}.obj ↑(Functor.sections K)
⊢ (fun x =>
        match x with
        | { val := u, property := hu } =>
          {
            down :=
              { val := fun j => (u j).down,
                property := (_ : ∀ {j j' : J} (f : j ⟶ j'), K.map f (u j).down = (u j').down) } })
      ((fun x =>
          match x with
          | { down := { val := u, property := hu } } =>
            { val := fun j => { down := u j },
              property := (_ : ∀ {j j' : J} (f : j ⟶ j'), { down := K.map f (u j) } = { down := u j' }) })
        x✝) =
    x✝

Next tactic:
apply ULift.ext
/--
The equivalence between the ulift of the explicit limit cone of a functor `K` and the explicit limit
cone of `K ⋙ uliftFunctor`.
-/
def sectionsEquiv {J : Type u} [Category.{u, u} J] (K : J ⥤ Type u) :
    uliftFunctor.{v, u}.obj (Functor.sections K) ≃
      (Functor.sections (K ⋙ uliftFunctor.{v, u})) where
  toFun := fun ⟨u, hu⟩ => ⟨fun j => ⟨u j⟩, fun f => by simp [hu f]⟩
  invFun := fun ⟨u, hu⟩ => ⟨fun j => (u j).down, fun f => by simp [← hu f]⟩
  left_inv _ := by apply ULift.ext; 

Proof state:
case h
J : Type u
inst✝ : Category.{u, u} J
K : J ⥤ Type u
x✝ : uliftFunctor.{v, u}.obj ↑(Functor.sections K)
⊢ ((fun x =>
          match x with
          | { val := u, property := hu } =>
            {
              down :=
                { val := fun j => (u j).down,
                  property := (_ : ∀ {j j' : J} (f : j ⟶ j'), K.map f (u j).down = (u j').down) } })
        ((fun x =>
            match x with
            | { down := { val := u, property := hu } } =>
              { val := fun j => { down := u j },
                property := (_ : ∀ {j j' : J} (f : j ⟶ j'), { down := K.map f (u j) } = { down := u j' }) })
          x✝)).down =
    x✝.down

Next tactic:
ext
/--
The equivalence between the ulift of the explicit limit cone of a functor `K` and the explicit limit
cone of `K ⋙ uliftFunctor`.
-/
def sectionsEquiv {J : Type u} [Category.{u, u} J] (K : J ⥤ Type u) :
    uliftFunctor.{v, u}.obj (Functor.sections K) ≃
      (Functor.sections (K ⋙ uliftFunctor.{v, u})) where
  toFun := fun ⟨u, hu⟩ => ⟨fun j => ⟨u j⟩, fun f => by simp [hu f]⟩
  invFun := fun ⟨u, hu⟩ => ⟨fun j => (u j).down, fun f => by simp [← hu f]⟩
  left_inv _ := by apply ULift.ext; ext; 

Proof state:
case h.a.h
J : Type u
inst✝ : Category.{u, u} J
K : J ⥤ Type u
x✝¹ : uliftFunctor.{v, u}.obj ↑(Functor.sections K)
x✝ : J
⊢ ↑((fun x =>
              match x with
              | { val := u, property := hu } =>
                {
                  down :=
                    { val := fun j => (u j).down,
                      property := (_ : ∀ {j j' : J} (f : j ⟶ j'), K.map f (u j).down = (u j').down) } })
            ((fun x =>
                match x with
                | { down := { val := u, property := hu } } =>
                  { val := fun j => { down := u j },
                    property := (_ : ∀ {j j' : J} (f : j ⟶ j'), { down := K.map f (u j) } = { down := u j' }) })
              x✝¹)).down
      x✝ =
    ↑x✝¹.down x✝

Next tactic:
rfl
/--
The equivalence between the ulift of the explicit limit cone of a functor `K` and the explicit limit
cone of `K ⋙ uliftFunctor`.
-/
def sectionsEquiv {J : Type u} [Category.{u, u} J] (K : J ⥤ Type u) :
    uliftFunctor.{v, u}.obj (Functor.sections K) ≃
      (Functor.sections (K ⋙ uliftFunctor.{v, u})) where
  toFun := fun ⟨u, hu⟩ => ⟨fun j => ⟨u j⟩, fun f => by simp [hu f]⟩
  invFun := fun ⟨u, hu⟩ => ⟨fun j => (u j).down, fun f => by simp [← hu f]⟩
  left_inv _ := by apply ULift.ext; ext; rfl
  right_inv _ := by 

Proof state:
J : Type u
inst✝ : Category.{u, u} J
K : J ⥤ Type u
x✝ : ↑(Functor.sections (K ⋙ uliftFunctor.{v, u}))
⊢ (fun x =>
        match x with
        | { down := { val := u, property := hu } } =>
          { val := fun j => { down := u j },
            property := (_ : ∀ {j j' : J} (f : j ⟶ j'), { down := K.map f (u j) } = { down := u j' }) })
      ((fun x =>
          match x with
          | { val := u, property := hu } =>
            {
              down :=
                { val := fun j => (u j).down,
                  property := (_ : ∀ {j j' : J} (f : j ⟶ j'), K.map f (u j).down = (u j').down) } })
        x✝) =
    x✝

Next tactic:
ext
/--
The equivalence between the ulift of the explicit limit cone of a functor `K` and the explicit limit
cone of `K ⋙ uliftFunctor`.
-/
def sectionsEquiv {J : Type u} [Category.{u, u} J] (K : J ⥤ Type u) :
    uliftFunctor.{v, u}.obj (Functor.sections K) ≃
      (Functor.sections (K ⋙ uliftFunctor.{v, u})) where
  toFun := fun ⟨u, hu⟩ => ⟨fun j => ⟨u j⟩, fun f => by simp [hu f]⟩
  invFun := fun ⟨u, hu⟩ => ⟨fun j => (u j).down, fun f => by simp [← hu f]⟩
  left_inv _ := by apply ULift.ext; ext; rfl
  right_inv _ := by ext; 

Proof state:
case a.h
J : Type u
inst✝ : Category.{u, u} J
K : J ⥤ Type u
x✝¹ : ↑(Functor.sections (K ⋙ uliftFunctor.{v, u}))
x✝ : J
⊢ ↑((fun x =>
            match x with
            | { down := { val := u, property := hu } } =>
              { val := fun j => { down := u j },
                property := (_ : ∀ {j j' : J} (f : j ⟶ j'), { down := K.map f (u j) } = { down := u j' }) })
          ((fun x =>
              match x with
              | { val := u, property := hu } =>
                {
                  down :=
                    { val := fun j => (u j).down,
                      property := (_ : ∀ {j j' : J} (f : j ⟶ j'), K.map f (u j).down = (u j').down) } })
            x✝¹))
      x✝ =
    ↑x✝¹ x✝

Next tactic:
rfl
/--
The equivalence between `K.sections` and `(K ⋙ uliftFunctor.{v, u}).sections`. This is used to show
that `uliftFunctor` preserves limits that are too possibly too large to exist in the source
category.
-/
def sectionsEquiv' {J : Type*} [Category J] (K : J ⥤ Type u) :
    K.sections ≃ (K ⋙ uliftFunctor.{v, u}).sections where
  toFun := fun ⟨u, hu⟩ => ⟨fun j => ⟨u j⟩, fun f => by 

Proof state:
J : Type u_1
inst✝ : Category.{?u.4639, u_1} J
K : J ⥤ Type u
x✝ : ↑(Functor.sections K)
u : (j : J) → K.obj j
hu : u ∈ Functor.sections K
j✝ j'✝ : J
f : j✝ ⟶ j'✝
⊢ (K ⋙ uliftFunctor.{v, u}).map f ((fun j => { down := u j }) j✝) = (fun j => { down := u j }) j'✝

Next tactic:
simp [hu f]
/--
The equivalence between `K.sections` and `(K ⋙ uliftFunctor.{v, u}).sections`. This is used to show
that `uliftFunctor` preserves limits that are too possibly too large to exist in the source
category.
-/
def sectionsEquiv' {J : Type*} [Category J] (K : J ⥤ Type u) :
    K.sections ≃ (K ⋙ uliftFunctor.{v, u}).sections where
  toFun := fun ⟨u, hu⟩ => ⟨fun j => ⟨u j⟩, fun f => by simp [hu f]⟩
  invFun := fun ⟨u, hu⟩ => ⟨fun j => (u j).down, @fun j j' f => by 

Proof state:
J : Type u_1
inst✝ : Category.{?u.4639, u_1} J
K : J ⥤ Type u
x✝ : ↑(Functor.sections (K ⋙ uliftFunctor.{v, u}))
u : (j : J) → (K ⋙ uliftFunctor.{v, u}).obj j
hu : u ∈ Functor.sections (K ⋙ uliftFunctor.{v, u})
j j' : J
f : j ⟶ j'
⊢ K.map f ((fun j => (u j).down) j) = (fun j => (u j).down) j'

Next tactic:
simp [← hu f]
/--
The equivalence between `K.sections` and `(K ⋙ uliftFunctor.{v, u}).sections`. This is used to show
that `uliftFunctor` preserves limits that are too possibly too large to exist in the source
category.
-/
def sectionsEquiv' {J : Type*} [Category J] (K : J ⥤ Type u) :
    K.sections ≃ (K ⋙ uliftFunctor.{v, u}).sections where
  toFun := fun ⟨u, hu⟩ => ⟨fun j => ⟨u j⟩, fun f => by simp [hu f]⟩
  invFun := fun ⟨u, hu⟩ => ⟨fun j => (u j).down, @fun j j' f => by simp [← hu f]⟩
  left_inv _ := by 

Proof state:
J : Type u_1
inst✝ : Category.{?u.4639, u_1} J
K : J ⥤ Type u
x✝ : ↑(Functor.sections K)
⊢ (fun x =>
        match x with
        | { val := u, property := hu } =>
          { val := fun j => (u j).down, property := (_ : ∀ (j j' : J) (f : j ⟶ j'), K.map f (u j).down = (u j').down) })
      ((fun x =>
          match x with
          | { val := u, property := hu } =>
            { val := fun j => { down := u j },
              property := (_ : ∀ {j j' : J} (f : j ⟶ j'), { down := K.map f (u j) } = { down := u j' }) })
        x✝) =
    x✝

Next tactic:
ext
/--
The equivalence between `K.sections` and `(K ⋙ uliftFunctor.{v, u}).sections`. This is used to show
that `uliftFunctor` preserves limits that are too possibly too large to exist in the source
category.
-/
def sectionsEquiv' {J : Type*} [Category J] (K : J ⥤ Type u) :
    K.sections ≃ (K ⋙ uliftFunctor.{v, u}).sections where
  toFun := fun ⟨u, hu⟩ => ⟨fun j => ⟨u j⟩, fun f => by simp [hu f]⟩
  invFun := fun ⟨u, hu⟩ => ⟨fun j => (u j).down, @fun j j' f => by simp [← hu f]⟩
  left_inv _ := by ext; 

Proof state:
case a.h
J : Type u_1
inst✝ : Category.{?u.4639, u_1} J
K : J ⥤ Type u
x✝¹ : ↑(Functor.sections K)
x✝ : J
⊢ ↑((fun x =>
            match x with
            | { val := u, property := hu } =>
              { val := fun j => (u j).down,
                property := (_ : ∀ (j j' : J) (f : j ⟶ j'), K.map f (u j).down = (u j').down) })
          ((fun x =>
              match x with
              | { val := u, property := hu } =>
                { val := fun j => { down := u j },
                  property := (_ : ∀ {j j' : J} (f : j ⟶ j'), { down := K.map f (u j) } = { down := u j' }) })
            x✝¹))
      x✝ =
    ↑x✝¹ x✝

Next tactic:
rfl