Zulip Chat Archive

Stream: new members

Topic: Defining the Particular Point Topology


Luigi Massacci (Jan 30 2024 at 18:39):

So a per the title, I defined the Particular point topology on a type (I recall someone was looking for it and also there was a discussion about adding the Sierpinksi space to Counterexamples), so here it is. I have a couple questions though:

a) I'm very confused by the whole typeclass (eg: DiscreTeopology, OrderTopology) vs type alias (CofiniteTopology) approach to "generic" topologies. When is one favoured over the other? I went with the latter since this seems closer in spirit to CofiniteTopology, but I don't really get why there's this distinction.
b) Is there any way to improve the definition? That p : X hanging there is a bit ugly but I couldn't find a better way.

import Mathlib.Tactic
import Mathlib.Topology.Filter
import Mathlib.Topology.Order

open Topology TopologicalSpace Set Function Classical Filter

/-- A type synonym equipped with the topology whose open sets are the empty set
and the sets containing a specified point -/
def ParticularPointTopology (X : Type*) (p : X) := X

namespace ParticularPointTopology

instance {X : Type*} (p : X) : Inhabited (ParticularPointTopology X p) where
  default := p

def of : X  ParticularPointTopology X p:=
  Equiv.refl X

variable {X : Type*} (p : X)

instance : TopologicalSpace (ParticularPointTopology X p) where
  IsOpen s := s.Nonempty  p  s
  isOpen_univ := by simp only [univ_nonempty, mem_univ, forall_true_left]
  isOpen_inter s t := by
    rintro hs ht x, hxs, hxt
    exact hs x, hxs⟩, ht x, hxt⟩⟩
  isOpen_sUnion := by
    rintro s h x, t, hts, hxt
    exact mem_sUnion_of_mem (h t hts x, hxt⟩) hts

theorem isOpen_iff {s : Set (ParticularPointTopology X p)} : IsOpen s  s.Nonempty  p  s :=
  Iff.rfl

theorem isOpen_iff' {s : Set (ParticularPointTopology X p)} : IsOpen s  s =   p  s := by
  simp only [isOpen_iff, nonempty_iff_ne_empty, or_iff_not_imp_left]

theorem isClosed_iff {s : Set (ParticularPointTopology X p)} : IsClosed s  s = univ  p  s := by
  simp only [ isOpen_compl_iff, isOpen_iff', compl_empty_iff, mem_compl_iff]

theorem nhds_eq (a : (ParticularPointTopology X p)) : 𝓝 a = 𝓟 {a, p} := by
  ext x
  simp [_root_.mem_nhds_iff, isOpen_iff]
  constructor
  intro t, htx, htp, hta
  refine insert_subset (htx hta) (singleton_subset_iff.mpr (htx (htp (nonempty_of_mem hta))))
  refine fun h  ⟨{a, p}, h, fun _  mem_insert_of_mem a rfl, mem_insert a {p}⟩

theorem mem_nhds_iff {a : (ParticularPointTopology X p)} {s : Set (ParticularPointTopology X p)} :
    s  𝓝 a  a  s  p  s := by
    simp [nhds_eq]
    constructor
    refine fun h  h <| mem_insert a {p}, h <| mem_insert_of_mem a rfl
    rintro as, ps x (hx | hx) <;> (rw [hx]; assumption)

theorem empty_interior_of_closed {s : Set (ParticularPointTopology X p)} (hs : IsClosed s) (huniv : s  univ)
  : interior s =  := by
  simp only [isClosed_iff] at hs
  rcases hs with h | h
  · contradiction
  · have : p  interior s := not_mem_subset interior_subset h
    rcases (@isOpen_iff' _ _ (interior s)).mp <| isOpen_interior
    · assumption
    · contradiction

instance : T0Space (ParticularPointTopology X p) where
  t0 x y h:= by
    have : y  {x, p}  p  {x, p} := by
      rw [ (@mem_nhds_iff _ _ _ {x, p}),  h]; simp [nhds_eq, subset_refl]
    have : x  {y, p}  p  {y, p} := by
      rw [ (@mem_nhds_iff _ _ _ {y, p}), h]; simp [nhds_eq, subset_refl]
    aesop

instance : SeparableSpace (ParticularPointTopology X p) where
  exists_countable_dense := by
    refine ⟨{p}, countable_singleton p, dense_iff_inter_open.mpr ?_
    refine fun U h₁ h₂  inter_singleton_nonempty.mpr <| ((isOpen_iff _).mp h₁ h₂)

instance : FirstCountableTopology (ParticularPointTopology X p) where
  nhds_generated_countable := by
    refine fun a  ⟨{{a, p}}, ?_
    simp only [countable_singleton, nhds_eq, generate_singleton, and_self]

end ParticularPointTopology

Ruben Van de Velde (Jan 30 2024 at 18:49):

Certainly that Inhabited instance will never be used, because the p argument cannot be found. Maybe you want to provide it under the assumption that X itself is inhabited?

Yaël Dillies (Jan 30 2024 at 18:51):

a. The best is to have both. Eg check docs#Topology.IsScott and docs#Topology.WithScott

Luigi Massacci (Jan 30 2024 at 19:08):

@Yaël Dillies thank you. @Ruben Van de Velde, that seems very reasonable but are you suggesting adding [Inhabited X] to the variable {X : Type*} … declaration, adding it as an hypothesis to def ParticularPointTopology or providing just the instance Inhabited (ParticularPointTopology X p) under the assumption [Inhabited X]? I guess eliminating it altogether might also be a viable option

Junyan Xu (Jan 30 2024 at 21:18):

Certainly that Inhabited instance will never be used, because the p argument cannot be found. Maybe you want to provide it under the assumption that X itself is inhabited?

ParticularPointTopology X p depends on p so Lean should be able to unify and find p. If it can't it will warn you once you write the instance ...

Luigi Massacci (Feb 26 2024 at 17:27):

I'm resurrecting this thread since I got around to finishing things. At the the I had the type synonym working, and as an mwe this was the state of things.

import Mathlib.Tactic
import Mathlib.Topology.Filter
import Mathlib.Topology.Order

open Topology TopologicalSpace Set Function Classical Filter

/-- A type synonym equipped with the topology whose open sets are the empty set
and the sets containing a specified point -/

def ParticularPoint (X : Type*) (p : X) := X

namespace ParticularPoint

def of : X  ParticularPoint X p:=
  Equiv.refl X

variable {X : Type*} (p : X) {s : Set (ParticularPoint X p)} (a : (ParticularPoint X p))

instance : TopologicalSpace (ParticularPoint X p) where
  IsOpen s := s.Nonempty  p  s
  isOpen_univ := by simp only [mem_univ, implies_true]
  isOpen_inter s t := by
    rintro hs ht x, hxs, hxt
    exact hs x, hxs⟩, ht x, hxt⟩⟩
  isOpen_sUnion := by
    rintro s h x, t, hts, hxt
    exact mem_sUnion_of_mem (h t hts x, hxt⟩) hts

theorem isOpen_iff  : IsOpen s  s.Nonempty  p  s :=
  Iff.rfl

theorem nhds_eq : 𝓝 a = 𝓟 {a, p} := by
  ext u
  simp [_root_.mem_nhds_iff, isOpen_iff]
  constructor
  intro t, htu, htp, hta
  refine insert_subset (htu hta) (singleton_subset_iff.mpr (htu (htp (nonempty_of_mem hta))))
  refine fun h  ⟨{a, p}, h, fun _  mem_insert_of_mem a rfl, mem_insert a {p}⟩

theorem mem_nhds_iff :
    s  𝓝 a  a  s  p  s := by
    simp [nhds_eq]
    constructor
    refine fun h  h <| mem_insert a {p}, h <| mem_insert_of_mem a rfl
    rintro as, ps x (hx | hx) <;> (rw [hx]; assumption)

instance : T0Space (ParticularPoint X p) where
  t0 x y h:= by
    have : y  {x, p}  p  {x, p} := by
      rw [ (@mem_nhds_iff _ _ {x, p}),  h]; simp [nhds_eq, subset_refl]
    have : x  {y, p}  p  {y, p} := by
      rw [ (@mem_nhds_iff _ _ {y, p}), h]; simp [nhds_eq, subset_refl]
    aesop

I tried to make it into a typeclass instead, but now I run into problems. First, I need to specify p when using the theorems, but I guess that might be unavoidable. (I tried making it implicit and ran into other troubles). But more importantly I run into this error:

cannot find synthesization order for instance @instT0Space with type
   {X : Type u_2} (p : X) [inst : TopologicalSpace X] [inst_1 : IsParticularPoint X p], T0Space X
all remaining arguments have metavariables:
  @IsParticularPoint X ?p inst✝¹Lean 4

The code mwe is the following:

import Mathlib.Tactic
import Mathlib.Topology.Filter
import Mathlib.Topology.Order

open Topology TopologicalSpace Set Function Classical Filter

section ParticularPoint

/- A nonempty set `s` is open in the Particular Point topology iff
it contains some particular point p -/
def ParticularPoint (X : Type*) (p : X) : TopologicalSpace X where
  IsOpen s := s.Nonempty  p  s
  isOpen_univ := by simp only [mem_univ, implies_true]
  isOpen_inter s t := by
    rintro hs ht x, hxs, hxt
    exact hs x, hxs⟩, ht x, hxt⟩⟩
  isOpen_sUnion := by
    rintro s h x, t, hts, hxt
    exact mem_sUnion_of_mem (h t hts x, hxt⟩) hts

variable (X : Type*) (p : X) [TopologicalSpace X]

/-- Predicate for a topological space to be equipped with the Particular Point Topology for some point. -/
class IsParticularPoint : Prop where
  topology_eq_particularPoint : TopologicalSpace X = ParticularPoint X p

instance : @IsParticularPoint X p (ParticularPoint X p) :=
  @IsParticularPoint.mk _ _ (ParticularPoint X p) rfl

namespace IsParticularPoint
variable {X: Type*} (p : X) [TopologicalSpace X] [IsParticularPoint X p] {s : Set X}

lemma topology_eq : _ = ParticularPoint X p := topology_eq_particularPoint

lemma isOpen_iff :
    IsOpen s  s.Nonempty  p  s := by erw [@topology_eq X p _]; rfl

theorem nhds_eq (a : X) : 𝓝 a = 𝓟 {a, p} := by
  ext u
  simp [_root_.mem_nhds_iff, isOpen_iff]
  constructor
  intro t, htu, htp, hta
  refine insert_subset (htu hta) (singleton_subset_iff.mpr (htu ?_))
  exact (isOpen_iff p).mp htp (Set.nonempty_of_mem hta)
  refine fun h  ⟨{a, p}, h, ?_, mem_insert a {p}⟩
  refine (isOpen_iff p).mpr (fun _  mem_insert_of_mem a rfl)

theorem mem_nhds_iff {a : X} :
    s  𝓝 a  a  s  p  s := by
    simp [nhds_eq p]
    constructor
    refine fun h  h <| mem_insert a {p}, h <| mem_insert_of_mem a rfl
    rintro as, ps x (hx | hx) <;> (rw [hx]; assumption)

instance : T0Space X where
  t0 x y h:= by
    have : y  {x, p}  p  {x, p} := by
      rw [ (@mem_nhds_iff _ _ _ _ {x, p}),  h]; simp [nhds_eq p, subset_refl]
    have : x  {y, p}  p  {y, p} := by
      rw [ (@mem_nhds_iff X p _ _ {y, p}), h]; simp [nhds_eq p, subset_refl]
    aesop

end IsParticularPoint
end ParticularPoint

I tried to do it like docs#Topology.IsScott as you suggested @Yaël Dillies but I'm at a bit of a loss as to what exactly the problem is

Yaël Dillies (Feb 26 2024 at 17:36):

Surely it should be T0Space (ParticularPoint X p) instead of T0Space X?

Luigi Massacci (Feb 26 2024 at 18:04):

How could that work? In the second example ParticularPoint X p is a of type TopologicalSpace X. I should probably have renamed it in the first one to WithParticularPoint. Anyway I decided to solve the problem by adding the type synonym and then proving the instance on that. However in docs#Topology.IsScott they managed to do that with just the typeclass. Dunno.

I just added the following:

def WithParticularPoint (X : Type*) (p : X) := X

namespace WithParticularPoint

instance : TopologicalSpace (WithParticularPoint X p) := ParticularPoint X p
instance : IsParticularPoint (WithParticularPoint X p) p := rfl

end WithParticularPoint

open IsParticularPoint

instance : T0Space (WithParticularPoint X p) where
  t0 x y h:= by
    have : y  {x, p}  p  {x, p} := by
      rw [ (@mem_nhds_iff (WithParticularPoint X p) _ _ _ {x, p}),  h];
      simp [@nhds_eq (WithParticularPoint X p) p, subset_refl]
    have : x  {y, p}  p  {y, p} := by
      rw [ (@mem_nhds_iff (WithParticularPoint X p) _ _ _ {y, p}), h];
      simp [@nhds_eq (WithParticularPoint X p) p, subset_refl]
    aesop


end ParticularPoint

Luigi Massacci (Feb 26 2024 at 18:04):

Which is guess is kosher enough?

Yaël Dillies (Feb 26 2024 at 18:48):

Luigi Massacci said:

I decided to solve the problem by adding the type synonym and then proving the instance on that. However in docs#Topology.IsScott they managed to do that with just the typeclass. Dunno.

That's because the Scott topology doesn't require more data than typeclasses can provide. Your "particular topology" does, since p can't be found by typeclass search.

Luigi Massacci (Feb 26 2024 at 18:54):

That makes sense


Last updated: May 02 2025 at 03:31 UTC