l3lab/ntp-mathlib huggingface dataset:
theorem HasBasis.nhds' {l : Filter α} {p : ι → Prop} {s : ι → Set α} (h : HasBasis l p s) :
    HasBasis (𝓝 l) p fun i => { l' | s i ∈ l' } := by 

Proof state:
ι : Sort u_1
α : Type u_2
β : Type u_3
X : Type u_4
Y : Type u_5
l : Filter α
p : ι → Prop
s : ι → Set α
h : HasBasis l p s
⊢ HasBasis (𝓝 l) p fun i => {l' | s i ∈ l'}

Next tactic:
simpa only [Iic_principal] using h.nhds
@[simp]
theorem nhds_bot : 𝓝 (⊥ : Filter α) = pure ⊥ := by
  

Proof state:
ι : Sort u_1
α : Type u_2
β : Type u_3
X : Type u_4
Y : Type u_5
⊢ 𝓝 ⊥ = pure ⊥

Next tactic:
simp [nhds_eq, (· ∘ ·), lift'_bot monotone_principal.Iic]
@[simp]
theorem nhds_top : 𝓝 (⊤ : Filter α) = ⊤ := by 

Proof state:
ι : Sort u_1
α : Type u_2
β : Type u_3
X : Type u_4
Y : Type u_5
⊢ 𝓝 ⊤ = ⊤

Next tactic:
simp [nhds_eq]
@[simp]
theorem nhds_pure (x : α) : 𝓝 (pure x : Filter α) = 𝓟 {⊥, pure x} := by
  

Proof state:
ι : Sort u_1
α : Type u_2
β : Type u_3
X : Type u_4
Y : Type u_5
x : α
⊢ 𝓝 (pure x) = 𝓟 {⊥, pure x}

Next tactic:
rw [← principal_singleton, nhds_principal, principal_singleton, Iic_pure]
@[simp]
theorem nhds_iInf (f : ι → Filter α) : 𝓝 (⨅ i, f i) = ⨅ i, 𝓝 (f i) := by
  

Proof state:
ι : Sort u_1
α : Type u_2
β : Type u_3
X : Type u_4
Y : Type u_5
f : ι → Filter α
⊢ 𝓝 (⨅ i, f i) = ⨅ i, 𝓝 (f i)

Next tactic:
simp only [nhds_eq]
@[simp]
theorem nhds_iInf (f : ι → Filter α) : 𝓝 (⨅ i, f i) = ⨅ i, 𝓝 (f i) := by
  simp only [nhds_eq]
  

Proof state:
ι : Sort u_1
α : Type u_2
β : Type u_3
X : Type u_4
Y : Type u_5
f : ι → Filter α
⊢ Filter.lift' (⨅ i, f i) (Iic ∘ 𝓟) = ⨅ i, Filter.lift' (f i) (Iic ∘ 𝓟)

Next tactic:
apply lift'_iInf_of_map_univ
@[simp]
theorem nhds_iInf (f : ι → Filter α) : 𝓝 (⨅ i, f i) = ⨅ i, 𝓝 (f i) := by
  simp only [nhds_eq]
  apply lift'_iInf_of_map_univ <;> 

Proof state:
case hg
ι : Sort u_1
α : Type u_2
β : Type u_3
X : Type u_4
Y : Type u_5
f : ι → Filter α
⊢ ∀ {s t : Set α}, (Iic ∘ 𝓟) (s ∩ t) = (Iic ∘ 𝓟) s ∩ (Iic ∘ 𝓟) t

Next tactic:
simp
@[simp]
theorem nhds_iInf (f : ι → Filter α) : 𝓝 (⨅ i, f i) = ⨅ i, 𝓝 (f i) := by
  simp only [nhds_eq]
  apply lift'_iInf_of_map_univ <;> 

Proof state:
case hg'
ι : Sort u_1
α : Type u_2
β : Type u_3
X : Type u_4
Y : Type u_5
f : ι → Filter α
⊢ (Iic ∘ 𝓟) univ = univ

Next tactic:
simp
@[simp]
theorem nhds_inf (l₁ l₂ : Filter α) : 𝓝 (l₁ ⊓ l₂) = 𝓝 l₁ ⊓ 𝓝 l₂ := by
  

Proof state:
ι : Sort u_1
α : Type u_2
β : Type u_3
X : Type u_4
Y : Type u_5
l₁ l₂ : Filter α
⊢ 𝓝 (l₁ ⊓ l₂) = 𝓝 l₁ ⊓ 𝓝 l₂

Next tactic:
simpa only [iInf_bool_eq] using nhds_iInf fun b => cond b l₁ l₂
theorem sInter_nhds (l : Filter α) : ⋂₀ { s | s ∈ 𝓝 l } = Iic l := by
  

Proof state:
ι : Sort u_1
α : Type u_2
β : Type u_3
X : Type u_4
Y : Type u_5
l : Filter α
⊢ ⋂₀ {s | s ∈ 𝓝 l} = Iic l

Next tactic:
simp_rw [nhds_eq, (· ∘ ·), sInter_lift'_sets monotone_principal.Iic, Iic, le_principal_iff,
    ← setOf_forall, ← Filter.le_def]
@[simp]
theorem nhds_mono {l₁ l₂ : Filter α} : 𝓝 l₁ ≤ 𝓝 l₂ ↔ l₁ ≤ l₂ := by
  

Proof state:
ι : Sort u_1
α : Type u_2
β : Type u_3
X : Type u_4
Y : Type u_5
l₁ l₂ : Filter α
⊢ 𝓝 l₁ ≤ 𝓝 l₂ ↔ l₁ ≤ l₂

Next tactic:
refine' ⟨fun h => _, fun h => monotone_nhds h⟩
@[simp]
theorem nhds_mono {l₁ l₂ : Filter α} : 𝓝 l₁ ≤ 𝓝 l₂ ↔ l₁ ≤ l₂ := by
  refine' ⟨fun h => _, fun h => monotone_nhds h⟩
  

Proof state:
ι : Sort u_1
α : Type u_2
β : Type u_3
X : Type u_4
Y : Type u_5
l₁ l₂ : Filter α
h : 𝓝 l₁ ≤ 𝓝 l₂
⊢ l₁ ≤ l₂

Next tactic:
rw [← Iic_subset_Iic, ← sInter_nhds, ← sInter_nhds]
@[simp]
theorem nhds_mono {l₁ l₂ : Filter α} : 𝓝 l₁ ≤ 𝓝 l₂ ↔ l₁ ≤ l₂ := by
  refine' ⟨fun h => _, fun h => monotone_nhds h⟩
  rw [← Iic_subset_Iic, ← sInter_nhds, ← sInter_nhds]
  

Proof state:
ι : Sort u_1
α : Type u_2
β : Type u_3
X : Type u_4
Y : Type u_5
l₁ l₂ : Filter α
h : 𝓝 l₁ ≤ 𝓝 l₂
⊢ ⋂₀ {s | s ∈ 𝓝 l₁} ⊆ ⋂₀ {s | s ∈ 𝓝 l₂}

Next tactic:
exact sInter_subset_sInter h
protected theorem mem_interior {s : Set (Filter α)} {l : Filter α} :
    l ∈ interior s ↔ ∃ t ∈ l, Iic (𝓟 t) ⊆ s := by 

Proof state:
ι : Sort u_1
α : Type u_2
β : Type u_3
X : Type u_4
Y : Type u_5
s : Set (Filter α)
l : Filter α
⊢ l ∈ interior s ↔ ∃ t ∈ l, Iic (𝓟 t) ⊆ s

Next tactic:
rw [mem_interior_iff_mem_nhds, mem_nhds_iff]
protected theorem mem_closure {s : Set (Filter α)} {l : Filter α} :
    l ∈ closure s ↔ ∀ t ∈ l, ∃ l' ∈ s, t ∈ l' := by
  

Proof state:
ι : Sort u_1
α : Type u_2
β : Type u_3
X : Type u_4
Y : Type u_5
s : Set (Filter α)
l : Filter α
⊢ l ∈ closure s ↔ ∀ t ∈ l, ∃ l' ∈ s, t ∈ l'

Next tactic:
simp only [closure_eq_compl_interior_compl, Filter.mem_interior, mem_compl_iff, not_exists,
    not_forall, Classical.not_not, exists_prop, not_and, and_comm, subset_def, mem_Iic,
    le_principal_iff]
@[simp]
protected theorem closure_singleton (l : Filter α) : closure {l} = Ici l := by
  

Proof state:
ι : Sort u_1
α : Type u_2
β : Type u_3
X : Type u_4
Y : Type u_5
l : Filter α
⊢ closure {l} = Ici l

Next tactic:
ext l'
@[simp]
protected theorem closure_singleton (l : Filter α) : closure {l} = Ici l := by
  ext l'
  

Proof state:
case h
ι : Sort u_1
α : Type u_2
β : Type u_3
X : Type u_4
Y : Type u_5
l l' : Filter α
⊢ l' ∈ closure {l} ↔ l' ∈ Ici l

Next tactic:
simp [Filter.mem_closure, Filter.le_def]
@[simp]
theorem specializes_iff_le {l₁ l₂ : Filter α} : l₁ ⤳ l₂ ↔ l₁ ≤ l₂ := by
  

Proof state:
ι : Sort u_1
α : Type u_2
β : Type u_3
X : Type u_4
Y : Type u_5
l₁ l₂ : Filter α
⊢ l₁ ⤳ l₂ ↔ l₁ ≤ l₂

Next tactic:
simp only [specializes_iff_closure_subset, Filter.closure_singleton, Ici_subset_Ici]
theorem nhds_atTop [Preorder α] : 𝓝 atTop = ⨅ x : α, 𝓟 (Iic (𝓟 (Ici x))) := by
  

Proof state:
ι : Sort u_1
α : Type u_2
β : Type u_3
X : Type u_4
Y : Type u_5
inst✝ : Preorder α
⊢ 𝓝 atTop = ⨅ x, 𝓟 (Iic (𝓟 (Ici x)))

Next tactic:
simp only [atTop, nhds_iInf, nhds_principal]
protected theorem tendsto_nhds_atTop_iff [Preorder β] {l : Filter α} {f : α → Filter β} :
    Tendsto f l (𝓝 atTop) ↔ ∀ y, ∀ᶠ a in l, Ici y ∈ f a := by
  

Proof state:
ι : Sort u_1
α : Type u_2
β : Type u_3
X : Type u_4
Y : Type u_5
inst✝ : Preorder β
l : Filter α
f : α → Filter β
⊢ Tendsto f l (𝓝 atTop) ↔ ∀ (y : β), ∀ᶠ (a : α) in l, Ici y ∈ f a

Next tactic:
simp only [nhds_atTop, tendsto_iInf, tendsto_principal, mem_Iic, le_principal_iff]
theorem nhds_nhds (x : X) :
    𝓝 (𝓝 x) = ⨅ (s : Set X) (_ : IsOpen s) (_ : x ∈ s), 𝓟 (Iic (𝓟 s)) := by
  

Proof state:
ι : Sort u_1
α : Type u_2
β : Type u_3
X : Type u_4
Y : Type u_5
inst✝ : TopologicalSpace X
x : X
⊢ 𝓝 (𝓝 x) = ⨅ s, ⨅ (_ : IsOpen s), ⨅ (_ : x ∈ s), 𝓟 (Iic (𝓟 s))

Next tactic:
simp only [(nhds_basis_opens x).nhds.eq_biInf, iInf_and, @iInf_comm _ (_ ∈ _)]
theorem inducing_nhds : Inducing (𝓝 : X → Filter X) :=
  inducing_iff_nhds.2 fun x =>
    (nhds_def' _).trans <| by
      

Proof state:
ι : Sort u_1
α : Type u_2
β : Type u_3
X : Type u_4
Y : Type u_5
inst✝ : TopologicalSpace X
x : X
⊢ ⨅ s, ⨅ (_ : IsOpen s), ⨅ (_ : x ∈ s), 𝓟 s = comap 𝓝 (𝓝 (𝓝 x))

Next tactic:
simp (config := { contextual := true }) only [nhds_nhds, comap_iInf, comap_principal,
        Iic_principal, preimage_setOf_eq, ← mem_interior_iff_mem_nhds, setOf_mem_eq,
        IsOpen.interior_eq]
theorem TotalSpace.mk_cast {x x' : B} (h : x = x') (b : E x) :
    .mk' F x' (cast (congr_arg E h) b) = TotalSpace.mk x b := by 

Proof state:
B : Type u_1
F : Type u_2
E : B → Type u_3
x x' : B
h : x = x'
b : E x
⊢ mk' F x' (cast (_ : E x = E x') b) = { proj := x, snd := b }

Next tactic:
subst h
theorem TotalSpace.mk_cast {x x' : B} (h : x = x') (b : E x) :
    .mk' F x' (cast (congr_arg E h) b) = TotalSpace.mk x b := by subst h; 

Proof state:
B : Type u_1
F : Type u_2
E : B → Type u_3
x : B
b : E x
⊢ mk' F x (cast (_ : E x = E x) b) = { proj := x, snd := b }

Next tactic:
rfl
@[simp 1001, mfld_simps 1001]
theorem TotalSpace.mk_inj {b : B} {y y' : E b} : mk' F b y = mk' F b y' ↔ y = y' := by
  

Proof state:
B : Type u_1
F : Type u_2
E : B → Type u_3
b : B
y y' : E b
⊢ mk' F b y = mk' F b y' ↔ y = y'

Next tactic:
simp [TotalSpace.ext_iff]
@[simp]
theorem TotalSpace.range_mk (b : B) : range ((↑) : E b → TotalSpace F E) = π F E ⁻¹' {b} := by
  

Proof state:
B : Type u_1
F : Type u_2
E : B → Type u_3
b : B
⊢ range (mk b) = proj ⁻¹' {b}

Next tactic:
apply Subset.antisymm
@[simp]
theorem TotalSpace.range_mk (b : B) : range ((↑) : E b → TotalSpace F E) = π F E ⁻¹' {b} := by
  apply Subset.antisymm
  · 

Proof state:
case h₁
B : Type u_1
F : Type u_2
E : B → Type u_3
b : B
⊢ range (mk b) ⊆ proj ⁻¹' {b}

Next tactic:
rintro _ ⟨x, rfl⟩
@[simp]
theorem TotalSpace.range_mk (b : B) : range ((↑) : E b → TotalSpace F E) = π F E ⁻¹' {b} := by
  apply Subset.antisymm
  · rintro _ ⟨x, rfl⟩
    

Proof state:
case h₁.intro
B : Type u_1
F : Type u_2
E : B → Type u_3
b : B
x : E b
⊢ { proj := b, snd := x } ∈ proj ⁻¹' {b}

Next tactic:
rfl
@[simp]
theorem TotalSpace.range_mk (b : B) : range ((↑) : E b → TotalSpace F E) = π F E ⁻¹' {b} := by
  apply Subset.antisymm
  · rintro _ ⟨x, rfl⟩
    rfl
  · 

Proof state:
case h₂
B : Type u_1
F : Type u_2
E : B → Type u_3
b : B
⊢ proj ⁻¹' {b} ⊆ range (mk b)

Next tactic:
rintro ⟨_, x⟩ rfl
@[simp]
theorem TotalSpace.range_mk (b : B) : range ((↑) : E b → TotalSpace F E) = π F E ⁻¹' {b} := by
  apply Subset.antisymm
  · rintro _ ⟨x, rfl⟩
    rfl
  · rintro ⟨_, x⟩ rfl
    

Proof state:
case h₂.mk
B : Type u_1
F : Type u_2
E : B → Type u_3
proj✝ : B
x : E proj✝
⊢ { proj := proj✝, snd := x } ∈ range (mk { proj := proj✝, snd := x }.proj)

Next tactic:
exact ⟨x, rfl⟩
/-- Constructs an equivalence between linear orders from an order isomorphism between them. -/
@[simps]
def Iso.mk {α β : LinOrd.{u}} (e : α ≃o β) : α ≅ β where
  hom := (e : OrderHom _ _)
  inv := (e.symm : OrderHom _ _)
  hom_inv_id := by
    

Proof state:
α β : LinOrd
e : ↑α ≃o ↑β
⊢ ↑e ≫ ↑(OrderIso.symm e) = 𝟙 α

Next tactic:
ext x
/-- Constructs an equivalence between linear orders from an order isomorphism between them. -/
@[simps]
def Iso.mk {α β : LinOrd.{u}} (e : α ≃o β) : α ≅ β where
  hom := (e : OrderHom _ _)
  inv := (e.symm : OrderHom _ _)
  hom_inv_id := by
    ext x
    

Proof state:
case w
α β : LinOrd
e : ↑α ≃o ↑β
x : (forget LinOrd).obj α
⊢ (↑e ≫ ↑(OrderIso.symm e)) x = (𝟙 α) x

Next tactic:
exact e.symm_apply_apply x
/-- Constructs an equivalence between linear orders from an order isomorphism between them. -/
@[simps]
def Iso.mk {α β : LinOrd.{u}} (e : α ≃o β) : α ≅ β where
  hom := (e : OrderHom _ _)
  inv := (e.symm : OrderHom _ _)
  hom_inv_id := by
    ext x
    exact e.symm_apply_apply x
  inv_hom_id := by
    

Proof state:
α β : LinOrd
e : ↑α ≃o ↑β
⊢ ↑(OrderIso.symm e) ≫ ↑e = 𝟙 β

Next tactic:
ext x
/-- Constructs an equivalence between linear orders from an order isomorphism between them. -/
@[simps]
def Iso.mk {α β : LinOrd.{u}} (e : α ≃o β) : α ≅ β where
  hom := (e : OrderHom _ _)
  inv := (e.symm : OrderHom _ _)
  hom_inv_id := by
    ext x
    exact e.symm_apply_apply x
  inv_hom_id := by
    ext x
    

Proof state:
case w
α β : LinOrd
e : ↑α ≃o ↑β
x : (forget LinOrd).obj β
⊢ (↑(OrderIso.symm e) ≫ ↑e) x = (𝟙 β) x

Next tactic:
exact e.apply_symm_apply x
@[simp]
lemma productEquiv_symm_apply_π (x : ∀ j, F j) (j : J) :
    Pi.π F j ((productEquiv F).symm x) = x j := by
  

Proof state:
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : ConcreteCategory C
J : Type w
F : J → C
inst✝¹ : HasProduct F
inst✝ : PreservesLimit (Discrete.functor F) (forget C)
x : (j : J) → (forget C).obj (F j)
j : J
⊢ (Pi.π F j) ((productEquiv F).symm x) = x j

Next tactic:
rw [← productEquiv_apply_apply, Equiv.apply_symm_apply]
@[simp]
lemma prodEquiv_symm_apply_fst (x : X₁ × X₂) :
    (Limits.prod.fst : X₁ ⨯ X₂ ⟶ X₁) ((prodEquiv X₁ X₂).symm x) = x.1 := by
  

Proof state:
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : ConcreteCategory C
X₁ X₂ : C
inst✝¹ : HasBinaryProduct X₁ X₂
inst✝ : PreservesLimit (pair X₁ X₂) (forget C)
x : (forget C).obj X₁ × (forget C).obj X₂
⊢ prod.fst ((prodEquiv X₁ X₂).symm x) = x.1

Next tactic:
obtain ⟨y, rfl⟩ := (prodEquiv X₁ X₂).surjective x
@[simp]
lemma prodEquiv_symm_apply_fst (x : X₁ × X₂) :
    (Limits.prod.fst : X₁ ⨯ X₂ ⟶ X₁) ((prodEquiv X₁ X₂).symm x) = x.1 := by
  obtain ⟨y, rfl⟩ := (prodEquiv X₁ X₂).surjective x
  

Proof state:
case intro
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : ConcreteCategory C
X₁ X₂ : C
inst✝¹ : HasBinaryProduct X₁ X₂
inst✝ : PreservesLimit (pair X₁ X₂) (forget C)
y : (forget C).obj (X₁ ⨯ X₂)
⊢ prod.fst ((prodEquiv X₁ X₂).symm ((prodEquiv X₁ X₂) y)) = ((prodEquiv X₁ X₂) y).1

Next tactic:
simp
@[simp]
lemma prodEquiv_symm_apply_snd (x : X₁ × X₂) :
    (Limits.prod.snd : X₁ ⨯ X₂ ⟶ X₂) ((prodEquiv X₁ X₂).symm x) = x.2 := by
  

Proof state:
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : ConcreteCategory C
X₁ X₂ : C
inst✝¹ : HasBinaryProduct X₁ X₂
inst✝ : PreservesLimit (pair X₁ X₂) (forget C)
x : (forget C).obj X₁ × (forget C).obj X₂
⊢ prod.snd ((prodEquiv X₁ X₂).symm x) = x.2

Next tactic:
obtain ⟨y, rfl⟩ := (prodEquiv X₁ X₂).surjective x
@[simp]
lemma prodEquiv_symm_apply_snd (x : X₁ × X₂) :
    (Limits.prod.snd : X₁ ⨯ X₂ ⟶ X₂) ((prodEquiv X₁ X₂).symm x) = x.2 := by
  obtain ⟨y, rfl⟩ := (prodEquiv X₁ X₂).surjective x
  

Proof state:
case intro
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : ConcreteCategory C
X₁ X₂ : C
inst✝¹ : HasBinaryProduct X₁ X₂
inst✝ : PreservesLimit (pair X₁ X₂) (forget C)
y : (forget C).obj (X₁ ⨯ X₂)
⊢ prod.snd ((prodEquiv X₁ X₂).symm ((prodEquiv X₁ X₂) y)) = ((prodEquiv X₁ X₂) y).2

Next tactic:
simp
lemma pullbackMk_surjective (x : (forget C).obj (pullback f₁ f₂)) :
    ∃ (x₁ : X₁) (x₂ : X₂) (h : f₁ x₁ = f₂ x₂), x = pullbackMk f₁ f₂ x₁ x₂ h := by
  

Proof state:
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : ConcreteCategory C
X₁ X₂ S : C
f₁ : X₁ ⟶ S
f₂ : X₂ ⟶ S
inst✝¹ : HasPullback f₁ f₂
inst✝ : PreservesLimit (cospan f₁ f₂) (forget C)
x : (forget C).obj (pullback f₁ f₂)
⊢ ∃ x₁ x₂, ∃ (h : f₁ x₁ = f₂ x₂), x = pullbackMk f₁ f₂ x₁ x₂ h

Next tactic:
obtain ⟨⟨⟨x₁, x₂⟩, h⟩, rfl⟩ := (pullbackEquiv f₁ f₂).symm.surjective x
lemma pullbackMk_surjective (x : (forget C).obj (pullback f₁ f₂)) :
    ∃ (x₁ : X₁) (x₂ : X₂) (h : f₁ x₁ = f₂ x₂), x = pullbackMk f₁ f₂ x₁ x₂ h := by
  obtain ⟨⟨⟨x₁, x₂⟩, h⟩, rfl⟩ := (pullbackEquiv f₁ f₂).symm.surjective x
  

Proof state:
case intro.mk.mk
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : ConcreteCategory C
X₁ X₂ S : C
f₁ : X₁ ⟶ S
f₂ : X₂ ⟶ S
inst✝¹ : HasPullback f₁ f₂
inst✝ : PreservesLimit (cospan f₁ f₂) (forget C)
x₁ : (forget C).obj X₁
x₂ : (forget C).obj X₂
h : f₁ (x₁, x₂).1 = f₂ (x₁, x₂).2
⊢ ∃ x₁_1 x₂_1,
    ∃ (h_1 : f₁ x₁_1 = f₂ x₂_1),
      (pullbackEquiv f₁ f₂).symm { val := (x₁, x₂), property := h } = pullbackMk f₁ f₂ x₁_1 x₂_1 h_1

Next tactic:
exact ⟨x₁, x₂, h, rfl⟩
theorem widePullback_ext {B : C} {ι : Type w} {X : ι → C} (f : ∀ j : ι, X j ⟶ B)
    [HasWidePullback B X f] [PreservesLimit (wideCospan B X f) (forget C)]
    (x y : ↑(widePullback B X f)) (h₀ : base f x = base f y) (h : ∀ j, π f j x = π f j y) :
    x = y := by
  

Proof state:
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : ConcreteCategory C
B : C
ι : Type w
X : ι → C
f : (j : ι) → X j ⟶ B
inst✝¹ : HasWidePullback B X f
inst✝ : PreservesLimit (wideCospan B X f) (forget C)
x y : (forget C).obj (widePullback B X f)
h₀ : (base f) x = (base f) y
h : ∀ (j : ι), (π f j) x = (π f j) y
⊢ x = y

Next tactic:
apply Concrete.limit_ext
theorem widePullback_ext {B : C} {ι : Type w} {X : ι → C} (f : ∀ j : ι, X j ⟶ B)
    [HasWidePullback B X f] [PreservesLimit (wideCospan B X f) (forget C)]
    (x y : ↑(widePullback B X f)) (h₀ : base f x = base f y) (h : ∀ j, π f j x = π f j y) :
    x = y := by
  apply Concrete.limit_ext
  

Proof state:
case a
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : ConcreteCategory C
B : C
ι : Type w
X : ι → C
f : (j : ι) → X j ⟶ B
inst✝¹ : HasWidePullback B X f
inst✝ : PreservesLimit (wideCospan B X f) (forget C)
x y : (forget C).obj (widePullback B X f)
h₀ : (base f) x = (base f) y
h : ∀ (j : ι), (π f j) x = (π f j) y
⊢ ∀ (j : WidePullbackShape ι), (limit.π (wideCospan B X f) j) x = (limit.π (wideCospan B X f) j) y

Next tactic:
rintro (_ | j)
theorem widePullback_ext {B : C} {ι : Type w} {X : ι → C} (f : ∀ j : ι, X j ⟶ B)
    [HasWidePullback B X f] [PreservesLimit (wideCospan B X f) (forget C)]
    (x y : ↑(widePullback B X f)) (h₀ : base f x = base f y) (h : ∀ j, π f j x = π f j y) :
    x = y := by
  apply Concrete.limit_ext
  rintro (_ | j)
  · 

Proof state:
case a.none
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : ConcreteCategory C
B : C
ι : Type w
X : ι → C
f : (j : ι) → X j ⟶ B
inst✝¹ : HasWidePullback B X f
inst✝ : PreservesLimit (wideCospan B X f) (forget C)
x y : (forget C).obj (widePullback B X f)
h₀ : (base f) x = (base f) y
h : ∀ (j : ι), (π f j) x = (π f j) y
⊢ (limit.π (wideCospan B X f) none) x = (limit.π (wideCospan B X f) none) y

Next tactic:
exact h₀
theorem widePullback_ext {B : C} {ι : Type w} {X : ι → C} (f : ∀ j : ι, X j ⟶ B)
    [HasWidePullback B X f] [PreservesLimit (wideCospan B X f) (forget C)]
    (x y : ↑(widePullback B X f)) (h₀ : base f x = base f y) (h : ∀ j, π f j x = π f j y) :
    x = y := by
  apply Concrete.limit_ext
  rintro (_ | j)
  · exact h₀
  · 

Proof state:
case a.some
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : ConcreteCategory C
B : C
ι : Type w
X : ι → C
f : (j : ι) → X j ⟶ B
inst✝¹ : HasWidePullback B X f
inst✝ : PreservesLimit (wideCospan B X f) (forget C)
x y : (forget C).obj (widePullback B X f)
h₀ : (base f) x = (base f) y
h : ∀ (j : ι), (π f j) x = (π f j) y
j : ι
⊢ (limit.π (wideCospan B X f) (some j)) x = (limit.π (wideCospan B X f) (some j)) y

Next tactic:
apply h
theorem widePullback_ext' {B : C} {ι : Type w} [Nonempty ι] {X : ι → C}
    (f : ∀ j : ι, X j ⟶ B) [HasWidePullback.{w} B X f]
    [PreservesLimit (wideCospan B X f) (forget C)] (x y : ↑(widePullback B X f))
    (h : ∀ j, π f j x = π f j y) : x = y := by
  

Proof state:
C : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : ConcreteCategory C
B : C
ι : Type w
inst✝² : Nonempty ι
X : ι → C
f : (j : ι) → X j ⟶ B
inst✝¹ : HasWidePullback B X f
inst✝ : PreservesLimit (wideCospan B X f) (forget C)
x y : (forget C).obj (widePullback B X f)
h : ∀ (j : ι), (π f j) x = (π f j) y
⊢ x = y

Next tactic:
apply Concrete.widePullback_ext _ _ _ _ h
theorem widePullback_ext' {B : C} {ι : Type w} [Nonempty ι] {X : ι → C}
    (f : ∀ j : ι, X j ⟶ B) [HasWidePullback.{w} B X f]
    [PreservesLimit (wideCospan B X f) (forget C)] (x y : ↑(widePullback B X f))
    (h : ∀ j, π f j x = π f j y) : x = y := by
  apply Concrete.widePullback_ext _ _ _ _ h
  

Proof state:
C : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : ConcreteCategory C
B : C
ι : Type w
inst✝² : Nonempty ι
X : ι → C
f : (j : ι) → X j ⟶ B
inst✝¹ : HasWidePullback B X f
inst✝ : PreservesLimit (wideCospan B X f) (forget C)
x y : (forget C).obj (widePullback B X f)
h : ∀ (j : ι), (π f j) x = (π f j) y
⊢ (base f) x = (base f) y

Next tactic:
inhabit ι
theorem widePullback_ext' {B : C} {ι : Type w} [Nonempty ι] {X : ι → C}
    (f : ∀ j : ι, X j ⟶ B) [HasWidePullback.{w} B X f]
    [PreservesLimit (wideCospan B X f) (forget C)] (x y : ↑(widePullback B X f))
    (h : ∀ j, π f j x = π f j y) : x = y := by
  apply Concrete.widePullback_ext _ _ _ _ h
  inhabit ι
  

Proof state:
C : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : ConcreteCategory C
B : C
ι : Type w
inst✝² : Nonempty ι
X : ι → C
f : (j : ι) → X j ⟶ B
inst✝¹ : HasWidePullback B X f
inst✝ : PreservesLimit (wideCospan B X f) (forget C)
x y : (forget C).obj (widePullback B X f)
h : ∀ (j : ι), (π f j) x = (π f j) y
inhabited_h : Inhabited ι
⊢ (base f) x = (base f) y

Next tactic:
simp only [← π_arrow f default, comp_apply, h]
theorem multiequalizer_ext {I : MulticospanIndex.{w} C} [HasMultiequalizer I]
    [PreservesLimit I.multicospan (forget C)] (x y : ↑(multiequalizer I))
    (h : ∀ t : I.L, Multiequalizer.ι I t x = Multiequalizer.ι I t y) : x = y := by
  

Proof state:
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : ConcreteCategory C
I : MulticospanIndex C
inst✝¹ : HasMultiequalizer I
inst✝ : PreservesLimit (MulticospanIndex.multicospan I) (forget C)
x y : (forget C).obj (multiequalizer I)
h : ∀ (t : I.L), (Multiequalizer.ι I t) x = (Multiequalizer.ι I t) y
⊢ x = y

Next tactic:
apply Concrete.limit_ext
theorem multiequalizer_ext {I : MulticospanIndex.{w} C} [HasMultiequalizer I]
    [PreservesLimit I.multicospan (forget C)] (x y : ↑(multiequalizer I))
    (h : ∀ t : I.L, Multiequalizer.ι I t x = Multiequalizer.ι I t y) : x = y := by
  apply Concrete.limit_ext
  

Proof state:
case a
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : ConcreteCategory C
I : MulticospanIndex C
inst✝¹ : HasMultiequalizer I
inst✝ : PreservesLimit (MulticospanIndex.multicospan I) (forget C)
x y : (forget C).obj (multiequalizer I)
h : ∀ (t : I.L), (Multiequalizer.ι I t) x = (Multiequalizer.ι I t) y
⊢ ∀ (j : WalkingMulticospan I.fstTo I.sndTo),
    (limit.π (MulticospanIndex.multicospan I) j) x = (limit.π (MulticospanIndex.multicospan I) j) y

Next tactic:
rintro (a | b)
theorem multiequalizer_ext {I : MulticospanIndex.{w} C} [HasMultiequalizer I]
    [PreservesLimit I.multicospan (forget C)] (x y : ↑(multiequalizer I))
    (h : ∀ t : I.L, Multiequalizer.ι I t x = Multiequalizer.ι I t y) : x = y := by
  apply Concrete.limit_ext
  rintro (a | b)
  · 

Proof state:
case a.left
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : ConcreteCategory C
I : MulticospanIndex C
inst✝¹ : HasMultiequalizer I
inst✝ : PreservesLimit (MulticospanIndex.multicospan I) (forget C)
x y : (forget C).obj (multiequalizer I)
h : ∀ (t : I.L), (Multiequalizer.ι I t) x = (Multiequalizer.ι I t) y
a : I.L
⊢ (limit.π (MulticospanIndex.multicospan I) (WalkingMulticospan.left a)) x =
    (limit.π (MulticospanIndex.multicospan I) (WalkingMulticospan.left a)) y

Next tactic:
apply h
theorem multiequalizer_ext {I : MulticospanIndex.{w} C} [HasMultiequalizer I]
    [PreservesLimit I.multicospan (forget C)] (x y : ↑(multiequalizer I))
    (h : ∀ t : I.L, Multiequalizer.ι I t x = Multiequalizer.ι I t y) : x = y := by
  apply Concrete.limit_ext
  rintro (a | b)
  · apply h
  · 

Proof state:
case a.right
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : ConcreteCategory C
I : MulticospanIndex C
inst✝¹ : HasMultiequalizer I
inst✝ : PreservesLimit (MulticospanIndex.multicospan I) (forget C)
x y : (forget C).obj (multiequalizer I)
h : ∀ (t : I.L), (Multiequalizer.ι I t) x = (Multiequalizer.ι I t) y
b : I.R
⊢ (limit.π (MulticospanIndex.multicospan I) (WalkingMulticospan.right b)) x =
    (limit.π (MulticospanIndex.multicospan I) (WalkingMulticospan.right b)) y

Next tactic:
rw [← limit.w I.multicospan (WalkingMulticospan.Hom.fst b), comp_apply, comp_apply]
theorem multiequalizer_ext {I : MulticospanIndex.{w} C} [HasMultiequalizer I]
    [PreservesLimit I.multicospan (forget C)] (x y : ↑(multiequalizer I))
    (h : ∀ t : I.L, Multiequalizer.ι I t x = Multiequalizer.ι I t y) : x = y := by
  apply Concrete.limit_ext
  rintro (a | b)
  · apply h
  · rw [← limit.w I.multicospan (WalkingMulticospan.Hom.fst b), comp_apply, comp_apply]
    

Proof state:
case a.right
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : ConcreteCategory C
I : MulticospanIndex C
inst✝¹ : HasMultiequalizer I
inst✝ : PreservesLimit (MulticospanIndex.multicospan I) (forget C)
x y : (forget C).obj (multiequalizer I)
h : ∀ (t : I.L), (Multiequalizer.ι I t) x = (Multiequalizer.ι I t) y
b : I.R
⊢ ((MulticospanIndex.multicospan I).map (WalkingMulticospan.Hom.fst b))
      ((limit.π (MulticospanIndex.multicospan I) (WalkingMulticospan.left (MulticospanIndex.fstTo I b))) x) =
    ((MulticospanIndex.multicospan I).map (WalkingMulticospan.Hom.fst b))
      ((limit.π (MulticospanIndex.multicospan I) (WalkingMulticospan.left (MulticospanIndex.fstTo I b))) y)

Next tactic:
simp [h]
/-- An auxiliary equivalence to be used in `multiequalizerEquiv` below.-/
def multiequalizerEquivAux (I : MulticospanIndex C) :
    (I.multicospan ⋙ forget C).sections ≃
    { x : ∀ i : I.L, I.left i // ∀ i : I.R, I.fst i (x _) = I.snd i (x _) } where
  toFun x :=
    ⟨fun i => x.1 (WalkingMulticospan.left _), fun i => by
      

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : ConcreteCategory C
I : MulticospanIndex C
x : ↑(Functor.sections (MulticospanIndex.multicospan I ⋙ forget C))
i : I.R
⊢ (MulticospanIndex.fst I i) ((fun i => ↑x (WalkingMulticospan.left i)) (MulticospanIndex.fstTo I i)) =
    (MulticospanIndex.snd I i) ((fun i => ↑x (WalkingMulticospan.left i)) (MulticospanIndex.sndTo I i))

Next tactic:
have a := x.2 (WalkingMulticospan.Hom.fst i)