{-# OPTIONS --cubical --safe #-}

module CantorSpace where

open import Basis                     hiding (A; B)
open import Cubical.Data.Empty.Base   using (; rec)
open import Cubical.Data.Bool.Base    using (true; false; _≟_) renaming (Bool to 𝔹)
open import Cubical.Data.List         using (List; _∷_; [])    renaming (_++_ to _^_)
open import Frame
open import Nucleus
open import CoverFormsNucleus
open import Cover
open import Poset
open import FormalTopology
open import Compactness

We open the SnocList module with the type 𝔹 of booleans.

open import SnocList 𝔹  _≟_  renaming (SnocList to ; SnocList-set to ℂ-set)

The empty list and the snoc operator are called [] and respectively. Concatenation operation on snoc lists is called _++_. Note that concatenation on lists is therefore renamed to _^_ to prevent conflict.

The Cantor poset

xs is less than ys if there is some zs such that xs = ys ++ zs.

_≤_ :     hProp ℓ-zero
xs  ys = (Σ[ zs   ] xs  ys ++ zs) , prop
  where
    prop : isProp (Σ[ zs   ] xs  ys ++ zs)
    prop (_ , p) (_ , q) = Σ≡Prop  ws  ℂ-set xs (ys ++ ws)) (++-lemma p q)

As _≤_ is a partial order, we package it up as a poset.

ℂ-pos : Poset ℓ-zero ℓ-zero
ℂ-pos =  , _≤_ , ℂ-set , ≤-refl , ≤-trans , ≤-antisym
  where
    ≤-refl : (xs : )  [ xs  xs ]
    ≤-refl xs = [] , refl

    ≤-trans : (xs ys zs : )  [ xs  ys ]  [ ys  zs ]  [ xs  zs ]
    ≤-trans xs ys zs (as , p) (bs , q) =
      (bs ++ as) , NTS
      where
        NTS : xs  zs ++ (bs ++ as)
        NTS = xs               ≡⟨ p                      
              ys ++ as         ≡⟨ cong  -  - ++ as) q 
              (zs ++ bs) ++ as ≡⟨ sym (assoc zs bs as)   
              zs ++ (bs ++ as) 

    ≤-antisym : (xs ys : )  [ xs  ys ]  [ ys  xs ]  xs  ys
    ≤-antisym xs ys ([]     , p) ([]      , q) = p
    ≤-antisym xs ys ([]     , p) (bs  x  , q) = p
    ≤-antisym xs ys (as  x , p) ([]      , q) = sym q
    ≤-antisym xs ys (as  a , p) (bs  b  , q) =
      rec (lemma3 NTS)
      where
        NTS : xs  xs ++ ((bs  b) ++ (as  a))
        NTS = xs                           ≡⟨ p                                
              ys ++ (as  a)               ≡⟨ cong  -  - ++ as  a) q       
              (xs ++ (bs  b)) ++ (as  a) ≡⟨ sym (assoc xs (bs  b) (as  a)) 
              xs ++ ((bs  b) ++ (as  a)) 

The Cantor formal topology

We give the formal topology of the Cantor space as an interaction system.

  1. Each inhabitant of is like a stage of information.

  2. At each stage of information we can perform a trivial experiment: querying the next bit.
    ℂ-exp = λ (_ : )  Unit ℓ-zero
    
  3. Outcome of the trivial experiment is the delivery of the new bit.
    ℂ-out = λ (_ : Unit ℓ-zero)  𝔹
    
  4. This takes us to a new stage information, obtained by snoc'ing in the new bit to the current stage of information.
    ℂ-rev : {_ : }  𝔹  
    ℂ-rev {xs} b = xs  b
    

    These four components together form an interaction system that satiesfies the monotonicity and simulation properties (given in ℂ-mono and ℂ-sim).

ℂ-IS : InteractionStr 
ℂ-IS = ℂ-exp , ℂ-out , λ {xs}  ℂ-rev {xs}

ℂ-mono : hasMono ℂ-pos ℂ-IS
ℂ-mono _ _ c = []  c , refl

ℂ-sim : hasSimulation ℂ-pos ℂ-IS
ℂ-sim xs ys xs≤ys@([] , p) tt = tt , NTS
  where
    NTS : (b₁ : 𝔹)  Σ[ b₀  𝔹 ] [ (xs  b₁)  (ys  b₀) ]
    NTS b₁ = b₁ , subst  -  [ (xs  b₁)  (-  b₁) ]) p (⊑[ ℂ-pos ]-refl _)
ℂ-sim xs ys xs≤ys@(zs  z , p) tt = tt , NTS
  where
    NTS : (c₀ : 𝔹)  Σ[ c  𝔹 ] [ (xs  c₀)  (ys  c) ]
    NTS c₀ =
      head (zs  z) tt , subst  -  [ (-  c₀)  _ ]) (sym p) NTS′
      where
        φ    = cong  -  ys ++ (-  c₀)) (sym (hd-tl-lemma (zs  z) tt))
        ψ    = cong  -  -  c₀) (sym (snoc-lemma ys _ _))
        rem  = (ys ++ zs)  z  c₀                                          ≡⟨ φ 
                (ys ++ (([]  head (zs  z) tt) ++ (tail (zs  z) tt)))  c₀ ≡⟨ ψ 
                ((ys  head (zs  z) tt) ++ tail (zs  z) tt)  c₀ 
        NTS′ : [ ((ys ++ zs)  z  c₀)  (ys  head (zs  z) tt) ]
        NTS′ = ((tail (zs  z) tt)  c₀) , rem

We finally package up all this as a formal topology

cantor : FormalTopology ℓ-zero ℓ-zero
cantor = ℂ-pos , ℂ-IS , ℂ-mono , ℂ-sim

open NucleusFrom cantor using () renaming (L to cantor-frame)

_ : Frame (ℓ-suc ℓ-zero) ℓ-zero ℓ-zero
_ = cantor-frame

from which we get a covering relation

open CoverFromFormalTopology cantor renaming (_◁_ to _<ℂ|_)

_ :   (  hProp ℓ-zero)  Type ℓ-zero
_ = _<ℂ|_

The Cantor formal topology is compact

We now want to view a list of s as a finite cover. We associate with some xss : List ℂ a subset, being covered by which corresponds to being covered by this list.

ℂ-down : List   𝒫 
ℂ-down = down cantor

syntax ℂ-down xss xs = xs  xss

This subset is downwards-closed.

↓-dc : (xss : List )  [ isDownwardsClosed ℂ-pos  -  -  xss) ]
↓-dc (xs  xss) ys zs ys◁xs∷xss zs≤ys =
  ∥∥-rec (is-true-prop (zs  (xs  xss))) NTS ys◁xs∷xss
  where
    open PosetReasoning ℂ-pos using (_⊑⟨_⟩_; _■)

    NTS : [ ys  xs ]  [ ys  xss ]  [ zs  (xs  xss) ]
    NTS (inl ys≤xs)  =  inl (zs ⊑⟨ zs≤ys  ys ⊑⟨ ys≤xs  xs ) 
    NTS (inr ys◁xss) =  inr (↓-dc xss ys zs ys◁xss zs≤ys)    

We claim that the Cantor space is compact.

compact : isCompact cantor

Two little lemmas

U⊆V⇒◁U⊆◁V : (xs : ) (U : 𝒫 ) (V : 𝒫 )  [ U  V ]  xs <ℂ| U  xs <ℂ| V
U⊆V⇒◁U⊆◁V xs U V U⊆V = ◁-lem₄ U V NTS xs
  where
    NTS : (u : )  [ u  U ]  u <ℂ| V
    NTS u u∈U = dir (U⊆V u u∈U)

↓-++-left : (xss yss : List )  [  -  -  xss)   -  -  (xss ^ yss)) ]
↓-++-left []         yss _ ()
↓-++-left (xs  xss) yss ys ys∈down-xs-xss =
  ∥∥-rec (is-true-prop (ys  ((xs  xss) ^ yss))) NTS ys∈down-xs-xss
  where
    NTS : [ ys  xs ]  [ ys  xss ]  [ ys  (xs  xss ^ yss) ]
    NTS (inl ys≤xs)       =  inl ys≤xs 
    NTS (inr ys∈down-xss) =  inr (↓-++-left xss yss ys ys∈down-xss) 

↓-++-right : (xss yss : List )  [  -  -  yss)   -  -  (xss ^ yss)) ]
↓-++-right xss        []         _  ()
↓-++-right []         (ys  yss) zs zs∈◁ys∷yss = zs∈◁ys∷yss
↓-++-right (xs  xss) (ys  yss) zs zs∈◁ys∷yss =
  ∥∥-rec (is-true-prop (zs  (xs  xss ^ ys  yss))) NTS zs∈◁ys∷yss
  where
    NTS : [ zs  ys ]  [ zs  yss ]  [ zs  (xs  xss ^ ys  yss) ]
    NTS (inl zs≤ys)  = let IH = ↓-++-right xss _ _  inl (⊑[ ℂ-pos ]-refl ys) 
                        in  inr (↓-dc (xss ^ ys  yss) ys zs IH zs≤ys) 
    NTS (inr zs◁yss) =  inr (↓-++-right xss _ zs  inr zs◁yss ) 

◁^-decide : (xs : ) (yss zss : List )
           [ xs  (yss ^ zss) ]
            [ xs  yss ]  [ xs  zss ] 
◁^-decide xs []         zss k =  inr k 
◁^-decide xs (ys  yss) zss k = ∥∥-rec (∥∥-prop _) NTS₀ k
  where
    NTS₀ : [ xs  ys ]  [ xs  (yss ^ zss) ]   [ xs  (ys  yss) ]  [ xs  zss ] 
    NTS₀ (inl xs≤ys) =  inl  inl xs≤ys  
    NTS₀ (inr xs◁yss^zss) = ∥∥-rec (∥∥-prop _) NTS₁ (◁^-decide xs yss zss xs◁yss^zss)
      where
        NTS₁ : [ xs  yss ]  [ xs  zss ]   [ xs  (ys  yss) ]  [ xs  zss ] 
        NTS₁ (inl xs◁yss) =  inl  inr xs◁yss  
        NTS₁ (inr xs◁zss) =  inr xs◁zss          

The proof

The proof is by induction on the proof of xs ◁ U.

compact xs U U-dc (dir xs∈U) =  xs  [] , NTS₀ , NTS₁ 
  where
    NTS₀ : xs <ℂ|  -  -  (xs  []))
    NTS₀ = dir  inl (⊑[ ℂ-pos ]-refl xs) 

    NTS₁ : [  -  -  (xs  []))  U ]
    NTS₁ ys ∣ys◁[xs]∣ = ∥∥-rec (is-true-prop (ys  U)) NTS₁′ ∣ys◁[xs]∣
      where
        NTS₁′ : [ ys  xs ]  [ ys  [] ]  [ U ys ]
        NTS₁′ (inl ys≤xs) = U-dc xs ys xs∈U ys≤xs

compact xs U U-dc (branch tt f) =
  let
    IH₀ :  Σ[ yss₀  List  ]
              ((xs  true) <ℂ|  -  -  yss₀)) × [ ℂ-down yss₀  U ] 
    IH₀ = compact (xs  true) U U-dc (f true)
    IH₁ :  Σ[ yss  List  ]
              ((xs  false) <ℂ|  -  -  yss) × [ ℂ-down yss  U ]) 
    IH₁ = compact (xs  false) U U-dc (f false)
  in
    ∥∥-rec (∥∥-prop _)  φ  ∥∥-rec (∥∥-prop _)  ψ   NTS φ ψ ) IH₁) IH₀
  where
    NTS : Σ[ yss₀  _ ] ((xs   true) <ℂ| λ -  -  yss₀) × [ ℂ-down yss₀  U ]
         Σ[ yss₁  _ ] ((xs  false) <ℂ| λ -  -  yss₁) × [ ℂ-down yss₁  U ]
         Σ[ yss   _ ] (xs <ℂ| λ -  -  yss) × [ ℂ-down yss  U ]
    NTS (yss , φ , p) (zss , ψ , q) = yss ^ zss , branch tt g , NTS′
      where
        g : (c : 𝔹)  (xs  c) <ℂ|  -  ℂ-down (yss ^ zss) -)
        g false = U⊆V⇒◁U⊆◁V _ (ℂ-down zss) (ℂ-down (yss ^ zss)) (↓-++-right yss zss) ψ
        g true  = U⊆V⇒◁U⊆◁V _ (ℂ-down yss) (ℂ-down (yss ^ zss)) (↓-++-left  yss zss) φ

        NTS′ : [  -  -  (yss ^ zss))  U ]
        NTS′ ys ys◁yss₀^yss₁ =
          ∥∥-rec (is-true-prop (ys  U)) NTS₂ (◁^-decide _ yss _ ys◁yss₀^yss₁)
          where
            NTS₂ : [ ys  yss ]  [ ys  zss ]  [ ys  U ]
            NTS₂ (inl ys◁yss₀) = p ys ys◁yss₀
            NTS₂ (inr ys◁yss₁) = q ys ys◁yss₁

compact xs U U-dc (squash xs◁U₀ xs◁U₁ i) =
  squash (compact xs U U-dc xs◁U₀) (compact xs U U-dc xs◁U₁) i

Some examples

An example of an element of the Cantor frame is the set of opens that contain true. This is clearly downwards-closed and a fixed point for the covering relation.

containing-true :  cantor-frame ∣F
containing-true = (W , W-dc) , fixing
  where
    W : 𝒫 
    W xs = true elem xs

    W-dc : [ isDownwardsClosed ℂ-pos W ]
    W-dc xs ys xs∈W ys≤xs@(zs , ys=xs++zs) =
      subst  -  [ -  W ]) (sym ys=xs++zs) (elem-lemma xs zs true xs∈W)

    lemma : (xs : )  ((x : 𝔹)  [ true elem (xs  x) ])  [ true elem xs ]
    lemma []       f with f false
    lemma []       f | ()
    lemma (xs  x) f with x
    lemma (xs  x) f | false = lemma xs λ { false  f false ; true  tt }
    lemma (xs  x) f | true  = tt

    fixing : NucleusFrom.𝕛 cantor (W , W-dc)  (W , W-dc)
    fixing =
      Σ≡Prop
        (isProp[]  isDownwardsClosed ℂ-pos)
        (funExt λ xs  ⇔toPath (fixing₀ xs) (fixing₁ xs))
      where
        fixing₀ : (xs : )  [ xs  (NucleusFrom.𝕛 cantor (W , W-dc) .π₀) ]  [ xs  W ]
        fixing₀ xs (dir p)        = p
        fixing₀ xs (branch b f)   = lemma xs  x  fixing₀ (xs  x) (f x))
        fixing₀ xs (squash p q i) = isProp[] (W xs) (fixing₀ xs p) (fixing₀ xs q) i

        fixing₁ : (xs : )  [ xs  W ]  [ xs  (NucleusFrom.𝕛 cantor (W , W-dc) .π₀) ]
        fixing₁ xs xs∈W = dir xs∈W