Zulip Chat Archive

Stream: Is there code for X?

Topic: Inf of a pair of topologies


Christopher Hoskin (Feb 06 2024 at 07:28):

Hello,

I'm looking for a result something like:

universe u

open TopologicalSpace

lemma test1 {α : Type u} [t₁ : TopologicalSpace α] {T₁ : Set (Set α)} {cond₁ : TopologicalSpace.IsTopologicalBasis T₁}
    [t₂ : TopologicalSpace α] {T₂ : Set (Set α)} {cond₂ : TopologicalSpace.IsTopologicalBasis T₂} :
    @IsTopologicalBasis α (t₁  t₂) {S |  U₁  T₁,  U₂  T₂, S = U₁  U₂} := sorry

I'm aware of:

theorem isTopologicalBasis_pi {ι : Type*} {X : ι  Type*} [ i, TopologicalSpace (X i)]
    {T :  i, Set (Set (X i))} (cond :  i, IsTopologicalBasis (T i)) :
    IsTopologicalBasis { S |  (U :  i, Set (X i)) (F : Finset ι),
      ( i, i  F  U i  T i)  S = (F : Set ι).pi U } := sorry

In Topology.Bases and though I should be able to deduce it from that.

I set off naively like this:

lemma test1 {α : Type u} [t₁ : TopologicalSpace α] {T₁ : Set (Set α)} {cond₁ : TopologicalSpace.IsTopologicalBasis T₁}
    [t₂ : TopologicalSpace α] {T₂ : Set (Set α)} {cond₂ : TopologicalSpace.IsTopologicalBasis T₂} :
    @IsTopologicalBasis α (t₁  t₂) {S |  U₁  T₁,  U₂  T₂, S = U₁  U₂} := by
  let t : ((i : Fin 2)   TopologicalSpace α)
  | 1 => t₁
  | 2 => t₂
  let T : (i : Fin 2)  Set (Set α)
  | 1 => T₁
  | 2 => T₂
  let conds : ((i : Fin 2)   @IsTopologicalBasis _ (t i) (T i))
    | 1 => cond₁
    | 2 => cond₂
  let f : Fin 2  α  α := fun _ => id
  letI := t₁  t₂
  sorry

However after many hours of trying I haven't been able to put it all together correctly.

Is there an easier way of doing this? Is there some kind of "deduce the pairwise result from the pi result" magic that I've missed?

Thanks,

Christopher

Eric Wieser (Feb 06 2024 at 07:34):

Do we have docs#isTopologicalBasis_prod ?

Eric Wieser (Feb 06 2024 at 07:35):

docs#TopologicalSpace.IsTopologicalBasis.prod should save you the trouble with Fin 2

Anatole Dedecker (Feb 06 2024 at 11:04):

In any case it’s the wrong way around to deduce the inf statement from the prod statement, it should be the converse

Anatole Dedecker (Feb 06 2024 at 11:09):

Your best option would probably be to mimic the proof of the prod statement

Junyan Xu (Feb 06 2024 at 15:10):

(deleted)

Christopher Hoskin (Feb 06 2024 at 22:51):

Well, this is true:

-- surely this must exist somewhere???
lemma subset_and_subset {s t u : Set α} (h₁ : s  u) (h₂ : t  u) : s  t  u := by
  convert (Set.inter_subset_inter h₁ h₂)
  exact (inter_self u).symm

protected theorem IsTopologicalBasis.inter {B₁ : Set (Set α)}
    {B₂ : Set (Set α)} (h₁ : IsTopologicalBasis B₁) (h₂ : IsTopologicalBasis B₂) :
    IsTopologicalBasis (image2 (·  ·) B₁ B₂) := by
  refine' isTopologicalBasis_of_isOpen_of_nhds _ _
  · rintro _ u₁, u₂, hu₁, hu₂, rfl
    exact (h₁.isOpen hu₁).inter (h₂.isOpen hu₂)
  · rintro a u hu uo
    simp only [mem_image2, exists_and_left, exists_exists_and_exists_and_eq_and, mem_inter_iff]
    rcases (h₁.nhds_hasBasis).mem_iff.1 (IsOpen.mem_nhds uo hu) with
      s, hs, hbs⟩, hsu
    rcases (h₂.nhds_hasBasis).mem_iff.1 (IsOpen.mem_nhds uo hu) with
      t, ht, hbt⟩, htu
    use s
    constructor
    · exact hs
    · use t; exact  ht, ⟨⟨hbs, hbt⟩, subset_and_subset hsu htu⟩⟩

Although I can't believe that {s t u : Set α} (h₁ : s ⊆ u) (h₂ : t ⊆ u) : s ∩ t ⊆ u is unknown to Lean.

I then try:

lemma test1 {α : Type u} [t₁ : TopologicalSpace α] {T₁ : Set (Set α)} {cond₁ : TopologicalSpace.IsTopologicalBasis T₁}
    [t₂ : TopologicalSpace α] {T₂ : Set (Set α)} {cond₂ : TopologicalSpace.IsTopologicalBasis T₂} :
    @IsTopologicalBasis α (t₁  t₂) (image2 (·  ·) T₁ T₂) := by
  letI := t₁  t₂
  apply IsTopologicalBasis.inter
  sorry
  sorry

Getting rid of the sorrys is defeating me.

Patrick Massot (Feb 06 2024 at 22:57):

Anatole didn't write that your statement is wrong, he wrote that the optimal proof strategy goes in the other direction.

Jireh Loreaux (Feb 07 2024 at 00:05):

(deleted)

Junyan Xu (Feb 07 2024 at 00:31):

One of h1 and h2 is unnecessary:

lemma subset_and_subset {s t u : Set α} (h₁ : s  u) : s  t  u :=
  fun _ h  h₁ h.1
  -- or (s.inter_subset_left t).trans h₁

Junyan Xu (Feb 07 2024 at 00:33):

I think it's pretty easy to specialize docs#isTopologicalBasis_iInf to isTopologicalBasis_inf and that kind of statement is arguably what we should have in mathlib (rather than putting three different topologies on the same space; usually you'd use type synonyms for that).
It's usually easier to use Bool for this purpose than Fin 2, since Bool.rec is convenient and has good defeq properties. Some examples are here.

Richard Copley (Feb 07 2024 at 00:36):

Christopher Hoskin said:

Although I can't believe that {s t u : Set α} (h₁ : s ⊆ u) (h₂ : t ⊆ u) : s ∩ t ⊆ u is unknown to Lean.

The aim is not to make a library containing every obvious fact in mathematics, as entertaining as that might be (cf. The Poetry Cloud by Cixin Liu). It's a success if what is there makes your lemma easy to prove in a couple of steps!

Junyan Xu (Feb 07 2024 at 00:53):

Scratch that, I now think using docs#TopologicalSpace.IsTopologicalBasis.prod and mimicking the proof that deduces isTopologicalBasis_iInf from isTopologicalBasis_pi would be the easiest. No need to deal with universe ULift issues ...

Junyan Xu (Feb 07 2024 at 01:33):

Here's a complete proof:

import Mathlib.Topology.Bases

open TopologicalSpace

variable {X Y Z} [tY : TopologicalSpace Y] [tZ : TopologicalSpace Z] (fY : X  Y) (fZ : X  Z)

theorem induced_to_prod (f : X  Y × Z) :
    induced f inferInstance = induced (fun x  (f x).1) tY  induced (fun x  (f x).2) tZ := by
  erw [induced_inf]
  simp_rw [induced_compose]
  rfl

theorem inducing_inf_to_prod :
    @Inducing X (Y × Z) (induced fY tY  induced fZ tZ) _ fun x  (fY x, fZ x) :=
  letI := induced fY tY  induced fZ tZ; ⟨(induced_to_prod fun x  (fY x, fZ x)).symm

theorem TopologicalSpace.IsTopologicalBasis.inf
    {BY : Set (Set Y)} {BZ : Set (Set Z)} (bY : IsTopologicalBasis BY) (bZ : IsTopologicalBasis BZ) :
    @IsTopologicalBasis X (induced fY tY  induced fZ tZ) (BY.image2 (fY ⁻¹' ·  fZ ⁻¹' ·) BZ) := by
  letI := induced fY tY  induced fZ tZ
  convert (bY.prod bZ).inducing (inducing_inf_to_prod fY fZ)
  rw [Set.image_image2]; rfl

example {t₁ t₂ B₁ B₂} (h₁ : @IsTopologicalBasis X t₁ B₁) (h₂ : @IsTopologicalBasis X t₂ B₂) :
    @IsTopologicalBasis X (t₁  t₂) (Set.image2 (·  ·) B₁ B₂) := by
  convert @IsTopologicalBasis.inf X X X t₁ t₂ id id B₁ B₂ h₁ h₂ <;> rw [@induced_id _ (_)]
-- need to specify all implicit arguments because multiple instances on the same type
-- would be easier if `TopologicalSpace` arguments in `TopologicalSpace.IsTopologicalBasis.inf`
-- are regular implicit rather than instance implicit

Christopher Hoskin (Feb 07 2024 at 21:05):

@Junyan Xu Thanks very much for your proof. I'm afraid the way Mathlib handles topologies is just a bit beyond the grasp of my intellect. I'm trying to apply your result to the Lawson Topology:

import Mathlib.Topology.Order.LowerUpperTopology
import Mathlib.Topology.Order.ScottTopology

open Set Topology TopologicalSpace

variable {X Y Z} [tY : TopologicalSpace Y] [tZ : TopologicalSpace Z] (fY : X  Y) (fZ : X  Z)

theorem induced_to_prod (f : X  Y × Z) :
    induced f inferInstance = induced (fun x  (f x).1) tY  induced (fun x  (f x).2) tZ := by
  erw [induced_inf]
  simp_rw [induced_compose]
  rfl

theorem inducing_inf_to_prod :
    @Inducing X (Y × Z) (induced fY tY  induced fZ tZ) _ fun x  (fY x, fZ x) :=
  letI := induced fY tY  induced fZ tZ; ⟨(induced_to_prod fun x  (fY x, fZ x)).symm

theorem TopologicalSpace.IsTopologicalBasis.inf
    {BY : Set (Set Y)} {BZ : Set (Set Z)} (bY : IsTopologicalBasis BY) (bZ : IsTopologicalBasis BZ) :
    @IsTopologicalBasis X (induced fY tY  induced fZ tZ) (BY.image2 (fY ⁻¹' ·  fZ ⁻¹' ·) BZ) := by
  letI := induced fY tY  induced fZ tZ
  convert (bY.prod bZ).inducing (inducing_inf_to_prod fY fZ)
  rw [Set.image_image2]; rfl

example {t₁ t₂ B₁ B₂} (h₁ : @IsTopologicalBasis X t₁ B₁) (h₂ : @IsTopologicalBasis X t₂ B₂) :
    @IsTopologicalBasis X (t₁  t₂) (Set.image2 (·  ·) B₁ B₂) := by
  convert @IsTopologicalBasis.inf X X X t₁ t₂ id id B₁ B₂ h₁ h₂ <;> rw [@induced_id _ (_)]
-- need to specify all implicit arguments because multiple instances on the same type
-- would be easier if `TopologicalSpace` arguments in `TopologicalSpace.IsTopologicalBasis.inf`
-- are regular implicit rather than instance implicit

namespace Topology

variable {α : Type*}

variable [Preorder α]

/--
The Lawson topology is defined as the meet of the `LowerTopology` and the `ScottTopology`.
-/
def lawson : TopologicalSpace α := lower α  scott

variable (α) [TopologicalSpace α]

/-
The Lawson topology is defined as the meet of the `LowerTopology` and the `ScottTopology`.
-/
class IsLawson : Prop where
  topology_eq_lawson : TopologicalSpace α = lawson

/--
The sets of the form U\↑F where U is Scott open and F is finite form a basis for the Lawson
topology
-/
def lawsonBasis := (image2 (fun x x_1  WithLower.toLower ⁻¹' x  WithScott.toScott ⁻¹' x_1)
    (IsLower.lowerBasis (WithLower α)) {U | @IsOpen (WithScott α) _ U})

namespace IsLawson

variable [TopologicalSpace α] [IsLawson α]

lemma topology_eq : _ = lawson := topology_eq_lawson

protected theorem isTopologicalBasis : TopologicalSpace.IsTopologicalBasis (lawsonBasis α) := by
  rw [lawsonBasis]
  convert IsTopologicalBasis.inf WithLower.toLower WithScott.toScott IsLower.isTopologicalBasis (TopologicalSpace.isTopologicalBasis_opens (α := WithScott α))
  erw [topology_eq α]
  rw [lawson]
  apply (congrArg₂ Inf.inf _) _
  sorry
  sorry

end IsLawson

end Topology

Is this the right idea? I reduce it to the goals

scott = induced (WithScott.toScott) WithScott.instTopologicalSpaceWithScott

and

lower α = induced (WithLower.toLower) WithLower.instTopologicalSpaceWithLower

but then I'm not sure what to do next (or if this is just nonsense)?

Thanks,

Christopher

Ruben Van de Velde (Feb 07 2024 at 21:24):

I think you rather want to create Lawson as a type alias for \a and define an instance : TopologicalSpace (Lawson \a)

Jireh Loreaux (Feb 07 2024 at 21:34):

@Christopher Hoskin Ruben may be right, but your goals are easily provable.

example {α : Type*} [Preorder α] :
    lower α = induced WithLower.toLower WithLower.instTopologicalSpaceWithLower := by
  letI _ := lower α; exact @IsLower.WithLowerHomeomorph α _ (lower α) rfl |>.inducing.induced

Yaël Dillies (Feb 07 2024 at 22:00):

Ruben Van de Velde said:

I think you rather want to create Lawson as a type alias for α and define an instance : TopologicalSpace (Lawson α)

This is not really the pattern in this part of the library (or rather the pattern is to have both the type synonym and the topology on the original space)

Christopher Hoskin (Feb 07 2024 at 22:09):

I left out the type synonym and some of the other boilerplate for a MWE, but I have it in the file I'm working on.

Christopher Hoskin (Feb 07 2024 at 22:20):

@Yaël Dillies we have:

def lower (α : Type*) [Preorder α] : TopologicalSpace α

but

variable {α β : Type*}
variable [Preorder α]
...
def scottHausdorff : TopologicalSpace α where
...
def scott : TopologicalSpace α := upperSet α  scottHausdorff

Presumably it should be:

def scottHausdorff (α : Type*) [Preorder α]  : TopologicalSpace α where
...
def scott (α : Type*) [Preorder α]  : TopologicalSpace α := upperSet α  scottHausdorff α

to be consistent?

Yaël Dillies (Feb 07 2024 at 22:21):

Hmm yeah, α should be explicit in scottHausdorff

Yaël Dillies (Feb 07 2024 at 22:21):

Sorry I didn't catch that in review

Christopher Hoskin (Feb 07 2024 at 22:21):

Similarly we have:

#check IsLower.WithLowerHomeomorph

but

#check WithScott.withScottHomeomorph

which is right?

Yaël Dillies (Feb 07 2024 at 22:22):

The latter

Christopher Hoskin (Feb 07 2024 at 22:22):

I'll do a PR to make it consistent then.

Christopher Hoskin (Feb 07 2024 at 22:47):

https://github.com/leanprover-community/mathlib4/pull/10346

Christopher Hoskin (Feb 09 2024 at 06:42):

This works:

example {α : Type*} [Preorder α] :
    lower α = induced WithLower.toLower WithLower.instTopologicalSpaceWithLower := by
  letI _ := lower α; exact @WithLower.withLowerHomeomorph α _ (lower α) rfl |>.inducing.induced

But this fails with (deterministic) timeout at 'isDefEq', maximum number of heartbeats (1000000) has been reached (use 'set_option maxHeartbeats <num>' to set the limit)

set_option maxHeartbeats 1000000 in
example {α : Type*} [Preorder α] :
    scott α = induced WithScott.toScott WithScott.instTopologicalSpaceWithScott := by
  letI _ := scott α; exact @WithScott.withScottHomeomorph α _ (scott α) rfl |>.inducing.induced

Jireh Loreaux (Feb 09 2024 at 09:19):

I think you want the symm of that homeomorphism, but I'm not at Lean to check. You might also try providing the arguments to IsScott.mk explicitly instead of hiding them behind the anonymous constructor with rfl.

Anatole Dedecker (Feb 13 2024 at 10:35):

Coming back to the original question, I still think it's cleaner to do (all code below is with the environment of docs#IsTopologicalBasis.prod)

protected theorem IsTopologicalBasis.inf {t₁ t₂ : TopologicalSpace β} {B₁ B₂ : Set (Set β)}
    (h₁ : IsTopologicalBasis (t := t₁) B₁) (h₂ : IsTopologicalBasis (t := t₂) B₂) :
    IsTopologicalBasis (t := t₁  t₂) (image2 (·  ·) B₁ B₂) := by
  let  _: TopologicalSpace β := t₁  t₂
  refine isTopologicalBasis_of_isOpen_of_nhds (t := _) ?_ ?_
  · rintro _ u₁, hu₁, u₂, hu₂, rfl
    exact ((h₁.isOpen (t := t₁) hu₁).mono inf_le_left).inter
      ((h₂.isOpen (t := t₂) hu₂).mono inf_le_right)
  · rintro x u hu uo
    rcases (nhds_inf (a := x)).symm  (h₁.nhds_hasBasis (t := t₁)).inf (h₂.nhds_hasBasis (t := t₂))
      |>.mem_iff.1 (uo.mem_nhds hu) with ⟨⟨s, t⟩, ⟨⟨hs, ha⟩, ht, hb⟩, hu
    exact s  t, mem_image2_of_mem hs ht, ha, hb⟩, hu

and then change the prod theorem to

protected theorem IsTopologicalBasis.induced [s : TopologicalSpace β] (f : α  β)
    {T : Set (Set β)} (h : IsTopologicalBasis T) :
    IsTopologicalBasis (t := induced f s) ((preimage f) '' T) :=
  h.inducing (t := induced f s) (inducing_induced f)

protected theorem IsTopologicalBasis.prod {β} [TopologicalSpace β] {B₁ : Set (Set α)}
    {B₂ : Set (Set β)} (h₁ : IsTopologicalBasis B₁) (h₂ : IsTopologicalBasis B₂) :
    IsTopologicalBasis (image2 (· ×ˢ ·) B₁ B₂) := by
  have := (h₁.induced Prod.fst).inf (h₂.induced Prod.snd)
  rwa [image2_image_left, image2_image_right] at this

Anatole Dedecker (Feb 13 2024 at 10:35):

Did anyone make a PR out of Junyan's version already? If not I'll open a PR with this and other cleanups in this file.

Christopher Hoskin (Feb 13 2024 at 18:17):

Anatole Dedecker said:

Did anyone make a PR out of Junyan's version already? If not I'll open a PR with this and other cleanups in this file.

@Anatole Dedecker I've been experimenting with it locally, but have done nothing towards preparing a PR, so I'd be very happy for you to go ahead.

Anatole Dedecker (Feb 19 2024 at 21:23):

#10732

Christopher Hoskin (Feb 25 2024 at 22:14):

This seems to work:

def lawson_basis := (image2 (fun x x_1  WithLower.toLower ⁻¹' x  WithScott.toScott ⁻¹' x_1)
  (IsLower.lowerBasis (WithLower α)) {U | @IsOpen (WithScott α) _ U})

protected theorem isTopologicalBasis : TopologicalSpace.IsTopologicalBasis (lawson_basis α) := by
  rw [lawson_basis]
  convert IsTopologicalBasis.inf_induced (γ := α) IsLower.isTopologicalBasis
    (TopologicalSpace.isTopologicalBasis_opens (α := WithScott α)) WithLower.toLower WithScott.toScott
  erw [topology_eq α]
  rw [lawson]
  apply (congrArg₂ Inf.inf _) _
  letI _ := lower α; exact @IsLower.withLowerHomeomorph α _ (lower α) rfl |>.inducing.induced
  letI _ := scott α; exact @IsScott.withScottHomeomorph α _ (scott α) rfl |>.inducing.induced

Last updated: May 02 2025 at 03:31 UTC