Skip to content

DomainTheory.Basics.LeastFixedPoint

Tom de Jong, May 2019.
Refactored Dec 2021.

Least fixed points of Scott continuous maps.

The flag --lossy-unification significantly speeds up the
typechecking.
(https://agda.readthedocs.io/en/latest/language/lossy-unification.html)


{-# OPTIONS --safe --without-K --lossy-unification #-}

open import MLTT.Spartan
open import UF.FunExt
open import UF.PropTrunc

module DomainTheory.Basics.LeastFixedPoint
        (pt : propositional-truncations-exist)
        (fe : Fun-Ext)
        (𝓥 : Universe)
       where

open PropositionalTruncation pt

open import UF.UniverseEmbedding

open import Naturals.Order
open import Notation.Order

open import DomainTheory.Basics.Dcpo pt fe 𝓥
open import DomainTheory.Basics.Exponential pt fe 𝓥
open import DomainTheory.Basics.Miscelanea pt fe 𝓥
open import DomainTheory.Basics.Pointed pt fe 𝓥

module _ (𝓓 : DCPO⊥ {𝓤} {𝓣}) where

 iter : (n : )   𝓓 ⟹ᵈᶜᵖᵒ⊥ 𝓓    𝓓 
 iter zero     f =  𝓓
 iter (succ n) f = [ 𝓓  , 𝓓  ]⟨ f  (iter n f)

 iter-is-monotone : (n : )  is-monotone ((𝓓 ⟹ᵈᶜᵖᵒ⊥ 𝓓) ) (𝓓 ) (iter n)
 iter-is-monotone zero     f g l = ⊥-is-least 𝓓 (iter zero g)
 iter-is-monotone (succ n) f g l = iter (succ n) f               ⊑⟪ 𝓓 ⟫[ ⦅1⦆ ]
                                   [ 𝓓  , 𝓓  ]⟨ g  (iter n f) ⊑⟪ 𝓓 ⟫[ ⦅2⦆ ]
                                   iter (succ n) g               ∎⟪ 𝓓 
  where
   ⦅1⦆ = l (iter n f)
   ⦅2⦆ = monotone-if-continuous (𝓓 ) (𝓓 ) g (iter n f) (iter n g)
         (iter-is-monotone n f g l)

 n-family : {I : 𝓥 ̇ } (α : I   𝓓 ⟹ᵈᶜᵖᵒ⊥ 𝓓 ) (n : )  I   𝓓 
 n-family α n i = iter n (α i)

 n-family-is-directed : {I : 𝓥 ̇ } (α : I   𝓓 ⟹ᵈᶜᵖᵒ⊥ 𝓓 )
                        (δ : is-Directed ((𝓓 ⟹ᵈᶜᵖᵒ⊥ 𝓓) ) α)
                        (n : )  is-Directed (𝓓 ) (n-family α n)
 n-family-is-directed {I} α δ n =
   inhabited-if-Directed ((𝓓 ⟹ᵈᶜᵖᵒ⊥ 𝓓 ) ) α δ , ε
  where
   ε : is-Semidirected (𝓓 ) (n-family α n)
   ε i j = ∥∥-functor h (semidirected-if-Directed ((𝓓 ⟹ᵈᶜᵖᵒ⊥ 𝓓) ) α δ i j)
    where
     h : (Σ k  I , (α i) ⊑⟪ 𝓓 ⟹ᵈᶜᵖᵒ⊥ 𝓓  (α k) ×
                    (α j) ⊑⟪ 𝓓 ⟹ᵈᶜᵖᵒ⊥ 𝓓  (α k))
        Σ k  I , (n-family α n i) ⊑⟪ 𝓓  (n-family α n k) ×
                   (n-family α n j) ⊑⟪ 𝓓  (n-family α n k)
     h (k , l , m) = k , (iter-is-monotone n (α i) (α k) l) ,
                         (iter-is-monotone n (α j) (α k) m)

 double-∐-lemma : {I : 𝓥 ̇ } (α : I   𝓓 ⟹ᵈᶜᵖᵒ⊥ 𝓓 )
                  (δ : is-Directed ((𝓓 ⟹ᵈᶜᵖᵒ⊥ 𝓓) ) α)
                  (n : )
                  (𝓓 ) (pointwise-family-is-directed (𝓓 ) (𝓓 ) α δ
                          ( (𝓓 ) (n-family-is-directed α δ n)))
                    (𝓓 ) (n-family-is-directed α δ (succ n))
 double-∐-lemma {I} α δ n = antisymmetry (𝓓 ) x y a b
  where
   ε : is-Directed (𝓓 ) (pointwise-family (𝓓 ) (𝓓 ) α
        ( (𝓓 ) (n-family-is-directed α δ n)))
   ε = (pointwise-family-is-directed (𝓓 ) (𝓓 ) α δ
        ( (𝓓 ) (n-family-is-directed α δ n)))
   φ : (n : )  is-Directed (𝓓 ) (n-family α n)
   φ n = n-family-is-directed α δ n

   x :  𝓓 
   x =  (𝓓 ) ε
   y :  𝓓 
   y =  (𝓓 ) (n-family-is-directed α δ (succ n))

   a : x ⊑⟪ 𝓓  y
   a = ∐-is-lowerbound-of-upperbounds (𝓓 ) ε y g
    where
     g : (i : I)
        (pointwise-family (𝓓 ) (𝓓 ) α ( (𝓓 ) (φ n)) i) ⊑⟪ 𝓓  y
     g i = sup-is-lowerbound-of-upperbounds
            (underlying-order (𝓓 )) s y u
      where
       β : I   𝓓 
       β = [ 𝓓  , 𝓓  ]⟨ α i   (n-family α n)
       s : is-sup (underlying-order (𝓓 ))
            (pointwise-family (𝓓 ) (𝓓 ) α ( (𝓓 ) (φ n)) i) β
       s = continuity-of-function (𝓓 ) (𝓓 ) (α i) I (n-family α n) (φ n)
       u : (j : I)  β j ⊑⟨ 𝓓   y
       u j = ∥∥-rec (prop-valuedness (𝓓 ) (β j) y) v
              (semidirected-if-Directed ((𝓓 ⟹ᵈᶜᵖᵒ⊥ 𝓓) ) α δ i j)
               where
         v : (Σ  k  I , α i ⊑⟪ 𝓓 ⟹ᵈᶜᵖᵒ⊥ 𝓓  α k × α j ⊑⟪ 𝓓 ⟹ᵈᶜᵖᵒ⊥ 𝓓  α k)
            β j ⊑⟪ 𝓓  y
         v (k , l , m) = β j                                 ⊑⟪ 𝓓 ⟫[ ⦅1⦆ ]
                         [ 𝓓  , 𝓓  ]⟨ α k  (iter n (α j)) ⊑⟪ 𝓓 ⟫[ ⦅2⦆ ]
                         iter (succ n) (α k)                 ⊑⟪ 𝓓 ⟫[ ⦅3⦆ ]
                         y                                   ∎⟪ 𝓓 
          where
           ⦅1⦆ = l (iter n (α j))
           ⦅2⦆ = monotone-if-continuous (𝓓 ) (𝓓 ) (α k)
                  (iter n (α j))
                  (iter n (α k))
                  (iter-is-monotone n (α j) (α k) m)
           ⦅3⦆ = ∐-is-upperbound (𝓓 ) (φ (succ n)) k

   b : y ⊑⟪ 𝓓  x
   b = ∐-is-lowerbound-of-upperbounds (𝓓 ) (φ (succ n)) x h
    where
     h : (i : I)  (n-family α (succ n) i) ⊑⟪ 𝓓  x
     h i = n-family α (succ n) i                ⊑⟪ 𝓓 ⟫[ ⦅1⦆ ]
           [ 𝓓  , 𝓓  ]⟨ α i  ( (𝓓 ) (φ n)) ⊑⟪ 𝓓 ⟫[ ⦅2⦆ ]
           x                                    ∎⟪ 𝓓 
      where
       ⦅1⦆ = monotone-if-continuous (𝓓 ) (𝓓 ) (α i)
              (iter n (α i))
              ( (𝓓 ) (n-family-is-directed α δ n))
              (∐-is-upperbound (𝓓 ) (φ n) i)
       ⦅2⦆ = ∐-is-upperbound (𝓓 ) ε i

 iter-is-continuous : (n : )  is-continuous ((𝓓 ⟹ᵈᶜᵖᵒ⊥ 𝓓) ) (𝓓 ) (iter n)
 iter-is-continuous zero     I α δ = a , b
  where
   a : (i : I)  iter zero (α i) ⊑⟪ 𝓓 
                 iter zero ( ((𝓓 ⟹ᵈᶜᵖᵒ⊥ 𝓓) ) {I} {α} δ)
   a i = ⊥-is-least 𝓓 (iter zero ( ((𝓓 ⟹ᵈᶜᵖᵒ⊥ 𝓓) ) {I} {α} δ))
   b : (u :  𝓓 )
      ((i : I)  iter zero (α i) ⊑⟪ 𝓓  u)
      iter zero ( ((𝓓 ⟹ᵈᶜᵖᵒ⊥ 𝓓) ) {I} {α} δ) ⊑⟪ 𝓓  u
   b u l = ⊥-is-least 𝓓 u
 iter-is-continuous (succ n) I α δ = γ
  where
   γ : is-sup (underlying-order (𝓓 ))
       (iter (succ n) ( ((𝓓 ⟹ᵈᶜᵖᵒ⊥ 𝓓) ) δ)) (iter (succ n)  α)
   γ = transport
        -  is-sup (underlying-order (𝓓 )) - (iter (succ n)  α)) (h ⁻¹) k
    where
     k : is-sup (underlying-order (𝓓 ))
         ( (𝓓 ) (n-family-is-directed α δ (succ n)))
         (iter (succ n)  α)
     k = ∐-is-sup (𝓓 ) (n-family-is-directed α δ (succ n))
     h = iter (succ n) s                                           =⟨refl⟩
         [ 𝓓  , 𝓓  ]⟨ s  (iter n s)                             =⟨ ⦅1⦆  
         [ 𝓓  , 𝓓  ]⟨ s  ( (𝓓 ) (n-family-is-directed α δ n)) =⟨refl⟩
          (𝓓 ) (pointwise-family-is-directed (𝓓 ) (𝓓 ) α δ
           ( (𝓓 ) (n-family-is-directed α δ n)))                 =⟨ ⦅2⦆  
          (𝓓 ) (n-family-is-directed α δ (succ n))               
      where
       s = ( ((𝓓 ⟹ᵈᶜᵖᵒ⊥ 𝓓) ) {I} {α} δ)
       ⦅2⦆ = double-∐-lemma α δ n
       ⦅1⦆ = ap ([ 𝓓  , 𝓓  ]⟨ s ) e
        where
         e : iter n s   (𝓓 ) (n-family-is-directed α δ n)
         e = antisymmetry (𝓓 ) (iter n s) ( (𝓓 )
              (n-family-is-directed α δ n)) l m
          where
           IH : is-sup (underlying-order (𝓓 )) (iter n ( ((𝓓 ⟹ᵈᶜᵖᵒ⊥ 𝓓) ) δ))
                (iter n  α)
           IH = iter-is-continuous n I α δ
           l : iter n s ⊑⟪ 𝓓   (𝓓 ) (n-family-is-directed α δ n)
           l = sup-is-lowerbound-of-upperbounds
                (underlying-order (𝓓 )) IH
                ( (𝓓 ) (n-family-is-directed α δ n))
                (∐-is-upperbound (𝓓 ) (n-family-is-directed α δ n))
           m :  (𝓓 ) (n-family-is-directed α δ n) ⊑⟪ 𝓓  iter n s
           m = ∐-is-lowerbound-of-upperbounds (𝓓 ) (n-family-is-directed α δ n)
                (iter n s)
                (sup-is-upperbound (underlying-order (𝓓 )) IH)

 iter-c :   DCPO[ (𝓓 ⟹ᵈᶜᵖᵒ⊥ 𝓓)  , 𝓓  ]
 iter-c n = iter n , iter-is-continuous n

 iter-is-ω-chain : (n : )  (iter-c n) ⊑⟨ ((𝓓 ⟹ᵈᶜᵖᵒ⊥ 𝓓) ) ⟹ᵈᶜᵖᵒ (𝓓 ) 
                             (iter-c (succ n))
 iter-is-ω-chain zero     f = ⊥-is-least 𝓓 (iter (succ zero) f)
 iter-is-ω-chain (succ n) f = monotone-if-continuous (𝓓 ) (𝓓 ) f
                               (iter n f)
                               (iter (succ n) f)
                               (iter-is-ω-chain n f)

 iter-increases : (n m : )  (n  m)
                 (iter-c n) ⊑⟨ ((𝓓 ⟹ᵈᶜᵖᵒ⊥ 𝓓) ) ⟹ᵈᶜᵖᵒ (𝓓 )  (iter-c m)
 iter-increases = ω-chains-increase
                   (underlying-order 𝓔) (reflexivity 𝓔) (transitivity 𝓔)
                   iter-c iter-is-ω-chain
  where
   𝓔 = ((𝓓 ⟹ᵈᶜᵖᵒ⊥ 𝓓) ) ⟹ᵈᶜᵖᵒ (𝓓 )

 iter-is-directed : is-Directed (((𝓓 ⟹ᵈᶜᵖᵒ⊥ 𝓓) ) ⟹ᵈᶜᵖᵒ (𝓓 )) iter-c
 iter-is-directed =
  ω-chains-are-Directed (((𝓓 ⟹ᵈᶜᵖᵒ⊥ 𝓓) ) ⟹ᵈᶜᵖᵒ (𝓓 ))
                        iter-c iter-is-ω-chain


Since we are working with 𝓥-dcpos, we work with a copy of the type of natural
numbers in 𝓥.


 private
  ℕ' : 𝓥 ̇
  ℕ' = Lift 𝓥 

 iter-c' : ℕ'  DCPO[ (𝓓 ⟹ᵈᶜᵖᵒ⊥ 𝓓)  , 𝓓  ]
 iter-c' = iter-c  lower

 iter-is-directed' : is-Directed (((𝓓 ⟹ᵈᶜᵖᵒ⊥ 𝓓) ) ⟹ᵈᶜᵖᵒ (𝓓 )) iter-c'
 iter-is-directed' =
  reindexed-family-is-directed (((𝓓 ⟹ᵈᶜᵖᵒ⊥ 𝓓) ) ⟹ᵈᶜᵖᵒ (𝓓 ))
                               (≃-Lift 𝓥 )
                               iter-c
                               iter-is-directed

 μ : DCPO[ ((𝓓 ⟹ᵈᶜᵖᵒ⊥ 𝓓) ) , (𝓓 ) ]
 μ = continuous-functions-sup ((𝓓 ⟹ᵈᶜᵖᵒ⊥ 𝓓) ) (𝓓 ) iter-c' iter-is-directed'

 μ-gives-a-fixed-point : (f : DCPO[ (𝓓 ) , (𝓓 ) ])
                        [ (𝓓 ⟹ᵈᶜᵖᵒ⊥ 𝓓)  , 𝓓  ]⟨ μ  f
                          [ 𝓓  , 𝓓  ]⟨ f 
                            ([ (𝓓 ⟹ᵈᶜᵖᵒ⊥ 𝓓)  , 𝓓  ]⟨ μ  f)
 μ-gives-a-fixed-point fc = antisymmetry (𝓓 ) (ν fc) (f (ν fc)) l m
  where
   ν : DCPO[ (𝓓 ) , (𝓓 ) ]   𝓓 
   ν = [ (𝓓 ⟹ᵈᶜᵖᵒ⊥ 𝓓)  , 𝓓  ]⟨ μ 
   f :  𝓓    𝓓 
   f = [ 𝓓  , 𝓓  ]⟨ fc 
   δ : is-directed (underlying-order (𝓓 ))
        (pointwise-family ((𝓓 ⟹ᵈᶜᵖᵒ⊥ 𝓓) ) (𝓓 ) (iter-c') fc)
   δ = pointwise-family-is-directed ((𝓓 ⟹ᵈᶜᵖᵒ⊥ 𝓓) ) (𝓓 ) (iter-c')
       iter-is-directed' fc

   l : ν fc ⊑⟪ 𝓓  f (ν fc)
   l = ∐-is-lowerbound-of-upperbounds (𝓓 ) δ (f (ν fc)) h
    where
     h : (n : ℕ')  iter (lower n) fc ⊑⟪ 𝓓  f (ν fc)
     h (zero , )   = ⊥-is-least 𝓓 (f (ν fc))
     h (succ n , ) = monotone-if-continuous (𝓓 ) (𝓓 ) fc
                       (iter n fc)
                       (ν fc)
                       (∐-is-upperbound (𝓓 ) δ (n , ))
   m : f (ν fc) ⊑⟪ 𝓓  ν fc
   m = sup-is-lowerbound-of-upperbounds (underlying-order (𝓓 ))
        (continuity-of-function (𝓓 ) (𝓓 ) fc ℕ' α δ) (ν fc) k
    where
     α : ℕ'   𝓓 
     α = pointwise-family ((𝓓 ⟹ᵈᶜᵖᵒ⊥ 𝓓) ) (𝓓 ) iter-c' fc
     k : (n : ℕ')  [ 𝓓  , 𝓓  ]⟨ fc  (α n) ⊑⟪ 𝓓  ν fc
     k (n , ) = f (α (n , ))  ⊑⟪ 𝓓 ⟫[ reflexivity (𝓓 ) (f (α (n , )))    ]
                 α (succ n , ) ⊑⟪ 𝓓 ⟫[ ∐-is-upperbound (𝓓 ) δ (succ n , ) ]
                 ν fc           ∎⟪ 𝓓 

 μ-gives-lowerbound-of-fixed-points :
     (f : DCPO[ (𝓓 ) , (𝓓 ) ])
     (d :  𝓓 )
    [ 𝓓  , 𝓓  ]⟨ f  d  ⊑⟪ 𝓓  d
    [ (𝓓 ⟹ᵈᶜᵖᵒ⊥ 𝓓)  , 𝓓  ]⟨ μ  f ⊑⟪ 𝓓  d
 μ-gives-lowerbound-of-fixed-points f d l =
  ∐-is-lowerbound-of-upperbounds (𝓓 )
   (pointwise-family-is-directed ((𝓓 ⟹ᵈᶜᵖᵒ⊥ 𝓓) ) (𝓓 ) iter-c'
     iter-is-directed' f)
   d g
   where
    g : (n : ℕ')  iter (lower n) f ⊑⟪ 𝓓  d
    g (zero , )   = ⊥-is-least 𝓓 d
    g (succ n , ) = iter (succ n) f    ⊑⟪ 𝓓 ⟫[ k ]
                     [ 𝓓  , 𝓓  ]⟨ f  d ⊑⟪ 𝓓 ⟫[ l ]
                     d                    ∎⟪ 𝓓 
     where
      k = monotone-if-continuous (𝓓 ) (𝓓 ) f (iter n f) d (g (n , ))