l3lab/ntp-mathlib huggingface dataset:
/-- Cardinality of a non-empty `Icc` of finsets. -/
theorem card_Icc_finset (h : s ⊆ t) : (Icc s t).card = 2 ^ (t.card - s.card) := by
  

Proof state:
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s t : Finset α
h : s ⊆ t
⊢ card (Icc s t) = 2 ^ (card t - card s)

Next tactic:
rw [← card_sdiff h, ← card_powerset, Icc_eq_image_powerset h, Finset.card_image_iff]
/-- Cardinality of a non-empty `Icc` of finsets. -/
theorem card_Icc_finset (h : s ⊆ t) : (Icc s t).card = 2 ^ (t.card - s.card) := by
  rw [← card_sdiff h, ← card_powerset, Icc_eq_image_powerset h, Finset.card_image_iff]
  

Proof state:
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s t : Finset α
h : s ⊆ t
⊢ Set.InjOn (fun x => s ∪ x) ↑(powerset (t \ s))

Next tactic:
rintro u hu v hv (huv : s ⊔ u = s ⊔ v)
/-- Cardinality of a non-empty `Icc` of finsets. -/
theorem card_Icc_finset (h : s ⊆ t) : (Icc s t).card = 2 ^ (t.card - s.card) := by
  rw [← card_sdiff h, ← card_powerset, Icc_eq_image_powerset h, Finset.card_image_iff]
  rintro u hu v hv (huv : s ⊔ u = s ⊔ v)
  

Proof state:
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s t : Finset α
h : s ⊆ t
u : Finset α
hu : u ∈ ↑(powerset (t \ s))
v : Finset α
hv : v ∈ ↑(powerset (t \ s))
huv : s ⊔ u = s ⊔ v
⊢ u = v

Next tactic:
rw [mem_coe, mem_powerset] at hu hv
/-- Cardinality of a non-empty `Icc` of finsets. -/
theorem card_Icc_finset (h : s ⊆ t) : (Icc s t).card = 2 ^ (t.card - s.card) := by
  rw [← card_sdiff h, ← card_powerset, Icc_eq_image_powerset h, Finset.card_image_iff]
  rintro u hu v hv (huv : s ⊔ u = s ⊔ v)
  rw [mem_coe, mem_powerset] at hu hv
  

Proof state:
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s t : Finset α
h : s ⊆ t
u : Finset α
hu : u ⊆ t \ s
v : Finset α
hv : v ⊆ t \ s
huv : s ⊔ u = s ⊔ v
⊢ u = v

Next tactic:
rw [← (disjoint_sdiff.mono_right hu : Disjoint s u).sup_sdiff_cancel_left, ←
    (disjoint_sdiff.mono_right hv : Disjoint s v).sup_sdiff_cancel_left, huv]
/-- Cardinality of an `Ico` of finsets. -/
theorem card_Ico_finset (h : s ⊆ t) : (Ico s t).card = 2 ^ (t.card - s.card) - 1 := by
  

Proof state:
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s t : Finset α
h : s ⊆ t
⊢ card (Ico s t) = 2 ^ (card t - card s) - 1

Next tactic:
rw [card_Ico_eq_card_Icc_sub_one, card_Icc_finset h]
/-- Cardinality of an `Ioc` of finsets. -/
theorem card_Ioc_finset (h : s ⊆ t) : (Ioc s t).card = 2 ^ (t.card - s.card) - 1 := by
  

Proof state:
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s t : Finset α
h : s ⊆ t
⊢ card (Ioc s t) = 2 ^ (card t - card s) - 1

Next tactic:
rw [card_Ioc_eq_card_Icc_sub_one, card_Icc_finset h]
/-- Cardinality of an `Ioo` of finsets. -/
theorem card_Ioo_finset (h : s ⊆ t) : (Ioo s t).card = 2 ^ (t.card - s.card) - 2 := by
  

Proof state:
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s t : Finset α
h : s ⊆ t
⊢ card (Ioo s t) = 2 ^ (card t - card s) - 2

Next tactic:
rw [card_Ioo_eq_card_Icc_sub_two, card_Icc_finset h]
/-- Cardinality of an `Iic` of finsets. -/
theorem card_Iic_finset : (Iic s).card = 2 ^ s.card := by 

Proof state:
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s t : Finset α
⊢ card (Iic s) = 2 ^ card s

Next tactic:
rw [Iic_eq_powerset, card_powerset]
/-- Cardinality of an `Iio` of finsets. -/
theorem card_Iio_finset : (Iio s).card = 2 ^ s.card - 1 := by
  

Proof state:
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s t : Finset α
⊢ card (Iio s) = 2 ^ card s - 1

Next tactic:
rw [Iio_eq_ssubsets, ssubsets, card_erase_of_mem (mem_powerset_self _), card_powerset]
/-- A function `f` from `Finset α` is monotone if and only if `f s ≤ f (cons a s ha)` for all `s`
and `a ∉ s`. -/
lemma monotone_iff_forall_le_cons : Monotone f ↔ ∀ s, ∀ ⦃a⦄ (ha), f s ≤ f (cons a s ha) := by
  

Proof state:
α : Type u_1
β : Type u_2
inst✝ : Preorder β
s t : Finset α
f : Finset α → β
⊢ Monotone f ↔ ∀ (s : Finset α) ⦃a : α⦄ (ha : a ∉ s), f s ≤ f (cons a s ha)

Next tactic:
classical simp [monotone_iff_forall_covby, covby_iff_exists_cons]
/-- A function `f` from `Finset α` is monotone if and only if `f s ≤ f (cons a s ha)` for all `s`
and `a ∉ s`. -/
lemma monotone_iff_forall_le_cons : Monotone f ↔ ∀ s, ∀ ⦃a⦄ (ha), f s ≤ f (cons a s ha) := by
  classical 

Proof state:
α : Type u_1
β : Type u_2
inst✝ : Preorder β
s t : Finset α
f : Finset α → β
⊢ Monotone f ↔ ∀ (s : Finset α) ⦃a : α⦄ (ha : a ∉ s), f s ≤ f (cons a s ha)

Next tactic:
simp [monotone_iff_forall_covby, covby_iff_exists_cons]
/-- A function `f` from `Finset α` is strictly monotone if and only if `f s < f (cons a s ha)` for
all `s` and `a ∉ s`. -/
lemma strictMono_iff_forall_lt_cons : StrictMono f ↔ ∀ s ⦃a⦄ ha, f s < f (cons a s ha) := by
  

Proof state:
α : Type u_1
β : Type u_2
inst✝ : Preorder β
s t : Finset α
f : Finset α → β
⊢ StrictMono f ↔ ∀ (s : Finset α) ⦃a : α⦄ (ha : a ∉ s), f s < f (cons a s ha)

Next tactic:
classical simp [strictMono_iff_forall_covby, covby_iff_exists_cons]
/-- A function `f` from `Finset α` is strictly monotone if and only if `f s < f (cons a s ha)` for
all `s` and `a ∉ s`. -/
lemma strictMono_iff_forall_lt_cons : StrictMono f ↔ ∀ s ⦃a⦄ ha, f s < f (cons a s ha) := by
  classical 

Proof state:
α : Type u_1
β : Type u_2
inst✝ : Preorder β
s t : Finset α
f : Finset α → β
⊢ StrictMono f ↔ ∀ (s : Finset α) ⦃a : α⦄ (ha : a ∉ s), f s < f (cons a s ha)

Next tactic:
simp [strictMono_iff_forall_covby, covby_iff_exists_cons]
/-- A function `f` from `Finset α` is monotone if and only if `f s ≤ f (insert a s)` for all `s` and
`a ∉ s`. -/
lemma monotone_iff_forall_le_insert : Monotone f ↔ ∀ s ⦃a⦄, a ∉ s → f s ≤ f (insert a s) := by
  

Proof state:
α : Type u_1
β : Type u_2
inst✝¹ : Preorder β
s t : Finset α
f : Finset α → β
inst✝ : DecidableEq α
⊢ Monotone f ↔ ∀ (s : Finset α) ⦃a : α⦄, a ∉ s → f s ≤ f (insert a s)

Next tactic:
simp [monotone_iff_forall_le_cons]
/-- A function `f` from `Finset α` is strictly monotone if and only if `f s < f (insert a s)` for
all `s` and `a ∉ s`. -/
lemma strictMono_iff_forall_lt_insert : StrictMono f ↔ ∀ s ⦃a⦄, a ∉ s → f s < f (insert a s) := by
  

Proof state:
α : Type u_1
β : Type u_2
inst✝¹ : Preorder β
s t : Finset α
f : Finset α → β
inst✝ : DecidableEq α
⊢ StrictMono f ↔ ∀ (s : Finset α) ⦃a : α⦄, a ∉ s → f s < f (insert a s)

Next tactic:
simp [strictMono_iff_forall_lt_cons]
instance {X : Profinite} : TopologicalSpace ((forget Profinite).obj X) := by
  

Proof state:
X : Profinite
⊢ TopologicalSpace ((forget Profinite).obj X)

Next tactic:
change TopologicalSpace X
instance {X : Profinite} : TopologicalSpace ((forget Profinite).obj X) := by
  change TopologicalSpace X
  

Proof state:
X : Profinite
⊢ TopologicalSpace ↑X.toCompHaus.toTop

Next tactic:
exact inferInstance
instance {X : Profinite} : TotallyDisconnectedSpace ((forget Profinite).obj X) := by
  

Proof state:
X : Profinite
⊢ TotallyDisconnectedSpace ((forget Profinite).obj X)

Next tactic:
change TotallyDisconnectedSpace X
instance {X : Profinite} : TotallyDisconnectedSpace ((forget Profinite).obj X) := by
  change TotallyDisconnectedSpace X
  

Proof state:
X : Profinite
⊢ TotallyDisconnectedSpace ↑X.toCompHaus.toTop

Next tactic:
exact inferInstance
instance {X : Profinite} : CompactSpace ((forget Profinite).obj X) := by
  

Proof state:
X : Profinite
⊢ CompactSpace ((forget Profinite).obj X)

Next tactic:
change CompactSpace X
instance {X : Profinite} : CompactSpace ((forget Profinite).obj X) := by
  change CompactSpace X
  

Proof state:
X : Profinite
⊢ CompactSpace ↑X.toCompHaus.toTop

Next tactic:
exact inferInstance
instance {X : Profinite} : T2Space ((forget Profinite).obj X) := by
  

Proof state:
X : Profinite
⊢ T2Space ((forget Profinite).obj X)

Next tactic:
change T2Space X
instance {X : Profinite} : T2Space ((forget Profinite).obj X) := by
  change T2Space X
  

Proof state:
X : Profinite
⊢ T2Space ↑X.toCompHaus.toTop

Next tactic:
exact inferInstance
/-- The natural functor from `Fintype` to `Profinite`, endowing a finite type with the
discrete topology. -/
@[simps!]
def FintypeCat.toProfinite : FintypeCat ⥤ Profinite where
  obj A := Profinite.of A
  map f := ⟨f, by 

Proof state:
X✝ Y✝ : FintypeCat
f : X✝ ⟶ Y✝
⊢ Continuous f

Next tactic:
continuity
/-- An explicit limit cone for a functor `F : J ⥤ Profinite`, defined in terms of
`CompHaus.limitCone`, which is defined in terms of `TopCat.limitCone`. -/
def limitCone {J : Type v} [SmallCategory J] (F : J ⥤ ProfiniteMax.{v, u}) : Limits.Cone F where
  pt :=
    { toCompHaus := (CompHaus.limitCone.{v, u} (F ⋙ profiniteToCompHaus)).pt
      isTotallyDisconnected := by
        

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ ProfiniteMax
⊢ TotallyDisconnectedSpace ↑(CompHaus.limitCone (F ⋙ profiniteToCompHaus)).pt.toTop

Next tactic:
change TotallyDisconnectedSpace ({ u : ∀ j : J, F.obj j | _ } : Type _)
/-- An explicit limit cone for a functor `F : J ⥤ Profinite`, defined in terms of
`CompHaus.limitCone`, which is defined in terms of `TopCat.limitCone`. -/
def limitCone {J : Type v} [SmallCategory J] (F : J ⥤ ProfiniteMax.{v, u}) : Limits.Cone F where
  pt :=
    { toCompHaus := (CompHaus.limitCone.{v, u} (F ⋙ profiniteToCompHaus)).pt
      isTotallyDisconnected := by
        change TotallyDisconnectedSpace ({ u : ∀ j : J, F.obj j | _ } : Type _)
        

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ ProfiniteMax
⊢ TotallyDisconnectedSpace
    ↑{u | ∀ {i j : J} (f : i ⟶ j), (((F ⋙ profiniteToCompHaus) ⋙ compHausToTop).map f) (u i) = u j}

Next tactic:
exact Subtype.totallyDisconnectedSpace
/-- An explicit limit cone for a functor `F : J ⥤ Profinite`, defined in terms of
`CompHaus.limitCone`, which is defined in terms of `TopCat.limitCone`. -/
def limitCone {J : Type v} [SmallCategory J] (F : J ⥤ ProfiniteMax.{v, u}) : Limits.Cone F where
  pt :=
    { toCompHaus := (CompHaus.limitCone.{v, u} (F ⋙ profiniteToCompHaus)).pt
      isTotallyDisconnected := by
        change TotallyDisconnectedSpace ({ u : ∀ j : J, F.obj j | _ } : Type _)
        exact Subtype.totallyDisconnectedSpace }
  π :=
  { app := (CompHaus.limitCone.{v, u} (F ⋙ profiniteToCompHaus)).π.app
    -- Porting note: was `by tidy`:
    naturality := by
      

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ ProfiniteMax
⊢ ∀ ⦃X Y : J⦄ (f : X ⟶ Y),
    ((Functor.const J).obj (mk (CompHaus.limitCone (F ⋙ profiniteToCompHaus)).pt)).map f ≫
        (CompHaus.limitCone (F ⋙ profiniteToCompHaus)).π.app Y =
      (CompHaus.limitCone (F ⋙ profiniteToCompHaus)).π.app X ≫ F.map f

Next tactic:
intro j k f
/-- An explicit limit cone for a functor `F : J ⥤ Profinite`, defined in terms of
`CompHaus.limitCone`, which is defined in terms of `TopCat.limitCone`. -/
def limitCone {J : Type v} [SmallCategory J] (F : J ⥤ ProfiniteMax.{v, u}) : Limits.Cone F where
  pt :=
    { toCompHaus := (CompHaus.limitCone.{v, u} (F ⋙ profiniteToCompHaus)).pt
      isTotallyDisconnected := by
        change TotallyDisconnectedSpace ({ u : ∀ j : J, F.obj j | _ } : Type _)
        exact Subtype.totallyDisconnectedSpace }
  π :=
  { app := (CompHaus.limitCone.{v, u} (F ⋙ profiniteToCompHaus)).π.app
    -- Porting note: was `by tidy`:
    naturality := by
      intro j k f
      

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ ProfiniteMax
j k : J
f : j ⟶ k
⊢ ((Functor.const J).obj (mk (CompHaus.limitCone (F ⋙ profiniteToCompHaus)).pt)).map f ≫
      (CompHaus.limitCone (F ⋙ profiniteToCompHaus)).π.app k =
    (CompHaus.limitCone (F ⋙ profiniteToCompHaus)).π.app j ≫ F.map f

Next tactic:
ext ⟨g, p⟩
/-- An explicit limit cone for a functor `F : J ⥤ Profinite`, defined in terms of
`CompHaus.limitCone`, which is defined in terms of `TopCat.limitCone`. -/
def limitCone {J : Type v} [SmallCategory J] (F : J ⥤ ProfiniteMax.{v, u}) : Limits.Cone F where
  pt :=
    { toCompHaus := (CompHaus.limitCone.{v, u} (F ⋙ profiniteToCompHaus)).pt
      isTotallyDisconnected := by
        change TotallyDisconnectedSpace ({ u : ∀ j : J, F.obj j | _ } : Type _)
        exact Subtype.totallyDisconnectedSpace }
  π :=
  { app := (CompHaus.limitCone.{v, u} (F ⋙ profiniteToCompHaus)).π.app
    -- Porting note: was `by tidy`:
    naturality := by
      intro j k f
      ext ⟨g, p⟩
      

Proof state:
case w.mk
J : Type v
inst✝ : SmallCategory J
F : J ⥤ ProfiniteMax
j k : J
f : j ⟶ k
g : (j : J) → ↑(((F ⋙ profiniteToCompHaus) ⋙ compHausToTop).obj j)
p : g ∈ {u | ∀ {i j : J} (f : i ⟶ j), (((F ⋙ profiniteToCompHaus) ⋙ compHausToTop).map f) (u i) = u j}
⊢ (((Functor.const J).obj (mk (CompHaus.limitCone (F ⋙ profiniteToCompHaus)).pt)).map f ≫
        (CompHaus.limitCone (F ⋙ profiniteToCompHaus)).π.app k)
      { val := g, property := p } =
    ((CompHaus.limitCone (F ⋙ profiniteToCompHaus)).π.app j ≫ F.map f) { val := g, property := p }

Next tactic:
exact (p f).symm
noncomputable instance forgetPreservesLimits : Limits.PreservesLimits (forget Profinite) := by
  

Proof state:
⊢ Limits.PreservesLimits (forget Profinite)

Next tactic:
apply Limits.compPreservesLimits Profinite.toTopCat (forget TopCat)
instance forget_reflectsIsomorphisms : ReflectsIsomorphisms (forget Profinite) := by
  

Proof state:
X Y : Profinite
f : X ⟶ Y
⊢ ReflectsIsomorphisms (forget Profinite)

Next tactic:
constructor
instance forget_reflectsIsomorphisms : ReflectsIsomorphisms (forget Profinite) := by
  constructor
  

Proof state:
case reflects
X Y : Profinite
f : X ⟶ Y
⊢ ∀ {A B : Profinite} (f : A ⟶ B) [inst : IsIso ((forget Profinite).map f)], IsIso f

Next tactic:
intro A B f hf
instance forget_reflectsIsomorphisms : ReflectsIsomorphisms (forget Profinite) := by
  constructor
  intro A B f hf
  

Proof state:
case reflects
X Y : Profinite
f✝ : X ⟶ Y
A B : Profinite
f : A ⟶ B
hf : IsIso ((forget Profinite).map f)
⊢ IsIso f

Next tactic:
exact Profinite.isIso_of_bijective _ ((isIso_iff_bijective f).mp hf)
/-- The equivalence between isomorphisms in `Profinite` and homeomorphisms
of topological spaces. -/
@[simps!]
noncomputable
def isoEquivHomeo : (X ≅ Y) ≃ (X ≃ₜ Y) where
  toFun := homeoOfIso
  invFun := isoOfHomeo
  left_inv f := by 

Proof state:
X Y : Profinite
f✝ : X ⟶ Y
f : X ≅ Y
⊢ isoOfHomeo (homeoOfIso f) = f

Next tactic:
ext
/-- The equivalence between isomorphisms in `Profinite` and homeomorphisms
of topological spaces. -/
@[simps!]
noncomputable
def isoEquivHomeo : (X ≅ Y) ≃ (X ≃ₜ Y) where
  toFun := homeoOfIso
  invFun := isoOfHomeo
  left_inv f := by ext; 

Proof state:
case w.w
X Y : Profinite
f✝ : X ⟶ Y
f : X ≅ Y
x✝ : (forget Profinite).obj X
⊢ (isoOfHomeo (homeoOfIso f)).hom x✝ = f.hom x✝

Next tactic:
rfl
/-- The equivalence between isomorphisms in `Profinite` and homeomorphisms
of topological spaces. -/
@[simps!]
noncomputable
def isoEquivHomeo : (X ≅ Y) ≃ (X ≃ₜ Y) where
  toFun := homeoOfIso
  invFun := isoOfHomeo
  left_inv f := by ext; rfl
  right_inv f := by 

Proof state:
X Y : Profinite
f✝ : X ⟶ Y
f : ↑X.toCompHaus.toTop ≃ₜ ↑Y.toCompHaus.toTop
⊢ homeoOfIso (isoOfHomeo f) = f

Next tactic:
ext
/-- The equivalence between isomorphisms in `Profinite` and homeomorphisms
of topological spaces. -/
@[simps!]
noncomputable
def isoEquivHomeo : (X ≅ Y) ≃ (X ≃ₜ Y) where
  toFun := homeoOfIso
  invFun := isoOfHomeo
  left_inv f := by ext; rfl
  right_inv f := by ext; 

Proof state:
case H
X Y : Profinite
f✝ : X ⟶ Y
f : ↑X.toCompHaus.toTop ≃ₜ ↑Y.toCompHaus.toTop
x✝ : ↑X.toCompHaus.toTop
⊢ (homeoOfIso (isoOfHomeo f)) x✝ = f x✝

Next tactic:
rfl
theorem epi_iff_surjective {X Y : Profinite.{u}} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by
  

Proof state:
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
⊢ Epi f ↔ Function.Surjective ⇑f

Next tactic:
constructor
theorem epi_iff_surjective {X Y : Profinite.{u}} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by
  constructor
  · -- Porting note: in mathlib3 `contrapose` saw through `Function.Surjective`.
    

Proof state:
case mp
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
⊢ Epi f → Function.Surjective ⇑f

Next tactic:
dsimp [Function.Surjective]
theorem epi_iff_surjective {X Y : Profinite.{u}} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by
  constructor
  · -- Porting note: in mathlib3 `contrapose` saw through `Function.Surjective`.
    dsimp [Function.Surjective]
    

Proof state:
case mp
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
⊢ Epi f → ∀ (b : (forget Profinite).obj Y), ∃ a, f a = b

Next tactic:
contrapose!
theorem epi_iff_surjective {X Y : Profinite.{u}} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by
  constructor
  · -- Porting note: in mathlib3 `contrapose` saw through `Function.Surjective`.
    dsimp [Function.Surjective]
    contrapose!
    

Proof state:
case mp
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
⊢ (∃ b, ∀ (a : (forget Profinite).obj X), f a ≠ b) → ¬Epi f

Next tactic:
rintro ⟨y, hy⟩ hf
theorem epi_iff_surjective {X Y : Profinite.{u}} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by
  constructor
  · -- Porting note: in mathlib3 `contrapose` saw through `Function.Surjective`.
    dsimp [Function.Surjective]
    contrapose!
    rintro ⟨y, hy⟩ hf
    

Proof state:
case mp.intro
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
y : (forget Profinite).obj Y
hy : ∀ (a : (forget Profinite).obj X), f a ≠ y
hf : Epi f
⊢ False

Next tactic:
skip
theorem epi_iff_surjective {X Y : Profinite.{u}} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by
  constructor
  · -- Porting note: in mathlib3 `contrapose` saw through `Function.Surjective`.
    dsimp [Function.Surjective]
    contrapose!
    rintro ⟨y, hy⟩ hf
    skip
    

Proof state:
case mp.intro
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
y : (forget Profinite).obj Y
hy : ∀ (a : (forget Profinite).obj X), f a ≠ y
hf : Epi f
⊢ False

Next tactic:
let C := Set.range f
theorem epi_iff_surjective {X Y : Profinite.{u}} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by
  constructor
  · -- Porting note: in mathlib3 `contrapose` saw through `Function.Surjective`.
    dsimp [Function.Surjective]
    contrapose!
    rintro ⟨y, hy⟩ hf
    skip
    let C := Set.range f
    

Proof state:
case mp.intro
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
y : (forget Profinite).obj Y
hy : ∀ (a : (forget Profinite).obj X), f a ≠ y
hf : Epi f
C : Set ((forget Profinite).obj Y) := Set.range ⇑f
⊢ False

Next tactic:
have hC : IsClosed C := (isCompact_range f.continuous).isClosed
theorem epi_iff_surjective {X Y : Profinite.{u}} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by
  constructor
  · -- Porting note: in mathlib3 `contrapose` saw through `Function.Surjective`.
    dsimp [Function.Surjective]
    contrapose!
    rintro ⟨y, hy⟩ hf
    skip
    let C := Set.range f
    have hC : IsClosed C := (isCompact_range f.continuous).isClosed
    

Proof state:
case mp.intro
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
y : (forget Profinite).obj Y
hy : ∀ (a : (forget Profinite).obj X), f a ≠ y
hf : Epi f
C : Set ((forget Profinite).obj Y) := Set.range ⇑f
hC : IsClosed C
⊢ False

Next tactic:
let U := Cᶜ
theorem epi_iff_surjective {X Y : Profinite.{u}} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by
  constructor
  · -- Porting note: in mathlib3 `contrapose` saw through `Function.Surjective`.
    dsimp [Function.Surjective]
    contrapose!
    rintro ⟨y, hy⟩ hf
    skip
    let C := Set.range f
    have hC : IsClosed C := (isCompact_range f.continuous).isClosed
    let U := Cᶜ
    

Proof state:
case mp.intro
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
y : (forget Profinite).obj Y
hy : ∀ (a : (forget Profinite).obj X), f a ≠ y
hf : Epi f
C : Set ((forget Profinite).obj Y) := Set.range ⇑f
hC : IsClosed C
U : Set ((forget Profinite).obj Y) := Cᶜ
⊢ False

Next tactic:
have hyU : y ∈ U := by
      refine' Set.mem_compl _
      rintro ⟨y', hy'⟩
      exact hy y' hy'
theorem epi_iff_surjective {X Y : Profinite.{u}} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by
  constructor
  · -- Porting note: in mathlib3 `contrapose` saw through `Function.Surjective`.
    dsimp [Function.Surjective]
    contrapose!
    rintro ⟨y, hy⟩ hf
    skip
    let C := Set.range f
    have hC : IsClosed C := (isCompact_range f.continuous).isClosed
    let U := Cᶜ
    have hyU : y ∈ U := by
      

Proof state:
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
y : (forget Profinite).obj Y
hy : ∀ (a : (forget Profinite).obj X), f a ≠ y
hf : Epi f
C : Set ((forget Profinite).obj Y) := Set.range ⇑f
hC : IsClosed C
U : Set ((forget Profinite).obj Y) := Cᶜ
⊢ y ∈ U

Next tactic:
refine' Set.mem_compl _
theorem epi_iff_surjective {X Y : Profinite.{u}} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by
  constructor
  · -- Porting note: in mathlib3 `contrapose` saw through `Function.Surjective`.
    dsimp [Function.Surjective]
    contrapose!
    rintro ⟨y, hy⟩ hf
    skip
    let C := Set.range f
    have hC : IsClosed C := (isCompact_range f.continuous).isClosed
    let U := Cᶜ
    have hyU : y ∈ U := by
      refine' Set.mem_compl _
      

Proof state:
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
y : (forget Profinite).obj Y
hy : ∀ (a : (forget Profinite).obj X), f a ≠ y
hf : Epi f
C : Set ((forget Profinite).obj Y) := Set.range ⇑f
hC : IsClosed C
U : Set ((forget Profinite).obj Y) := Cᶜ
⊢ y ∉ C

Next tactic:
rintro ⟨y', hy'⟩
theorem epi_iff_surjective {X Y : Profinite.{u}} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by
  constructor
  · -- Porting note: in mathlib3 `contrapose` saw through `Function.Surjective`.
    dsimp [Function.Surjective]
    contrapose!
    rintro ⟨y, hy⟩ hf
    skip
    let C := Set.range f
    have hC : IsClosed C := (isCompact_range f.continuous).isClosed
    let U := Cᶜ
    have hyU : y ∈ U := by
      refine' Set.mem_compl _
      rintro ⟨y', hy'⟩
      

Proof state:
case intro
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
y : (forget Profinite).obj Y
hy : ∀ (a : (forget Profinite).obj X), f a ≠ y
hf : Epi f
C : Set ((forget Profinite).obj Y) := Set.range ⇑f
hC : IsClosed C
U : Set ((forget Profinite).obj Y) := Cᶜ
y' : (forget Profinite).obj X
hy' : f y' = y
⊢ False

Next tactic:
exact hy y' hy'
theorem epi_iff_surjective {X Y : Profinite.{u}} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by
  constructor
  · -- Porting note: in mathlib3 `contrapose` saw through `Function.Surjective`.
    dsimp [Function.Surjective]
    contrapose!
    rintro ⟨y, hy⟩ hf
    skip
    let C := Set.range f
    have hC : IsClosed C := (isCompact_range f.continuous).isClosed
    let U := Cᶜ
    have hyU : y ∈ U := by
      refine' Set.mem_compl _
      rintro ⟨y', hy'⟩
      exact hy y' hy'
    

Proof state:
case mp.intro
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
y : (forget Profinite).obj Y
hy : ∀ (a : (forget Profinite).obj X), f a ≠ y
hf : Epi f
C : Set ((forget Profinite).obj Y) := Set.range ⇑f
hC : IsClosed C
U : Set ((forget Profinite).obj Y) := Cᶜ
hyU : y ∈ U
⊢ False

Next tactic:
have hUy : U ∈ 𝓝 y := hC.compl_mem_nhds hyU
theorem epi_iff_surjective {X Y : Profinite.{u}} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by
  constructor
  · -- Porting note: in mathlib3 `contrapose` saw through `Function.Surjective`.
    dsimp [Function.Surjective]
    contrapose!
    rintro ⟨y, hy⟩ hf
    skip
    let C := Set.range f
    have hC : IsClosed C := (isCompact_range f.continuous).isClosed
    let U := Cᶜ
    have hyU : y ∈ U := by
      refine' Set.mem_compl _
      rintro ⟨y', hy'⟩
      exact hy y' hy'
    have hUy : U ∈ 𝓝 y := hC.compl_mem_nhds hyU
    

Proof state:
case mp.intro
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
y : (forget Profinite).obj Y
hy : ∀ (a : (forget Profinite).obj X), f a ≠ y
hf : Epi f
C : Set ((forget Profinite).obj Y) := Set.range ⇑f
hC : IsClosed C
U : Set ((forget Profinite).obj Y) := Cᶜ
hyU : y ∈ U
hUy : U ∈ 𝓝 y
⊢ False

Next tactic:
obtain ⟨V, hV, hyV, hVU⟩ := isTopologicalBasis_isClopen.mem_nhds_iff.mp hUy