module Order.DCPO where
Directed-complete partial orders🔗
Let be a partial order. A family of elements is a semi-directed family if for every there merely exists some such and A semidirected family is a directed family when is merely inhabited.
module _ {o ℓ} (P : Poset o ℓ) where
open Order.Reasoning P
: ∀ {Ix : Type o} → (Ix → Ob) → Type _
is-semidirected-family {Ix = Ix} f = ∀ i j → ∃[ k ∈ Ix ] (f i ≤ f k × f j ≤ f k)
is-semidirected-family
record is-directed-family {Ix : Type o} (f : Ix → Ob) : Type (o ⊔ ℓ) where
no-eta-equality
field
: ∥ Ix ∥
elt : is-semidirected-family f semidirected
Note that any family whose indexing type is a proposition is automatically semi-directed:
prop-indexed→semidirected: ∀ {Ix : Type o} → (s : Ix → Ob) → is-prop Ix
→ is-semidirected-family s
=
prop-indexed→semidirected s prop i j (i , ≤-refl , ≤-refl' (ap s (prop j i))) inc
The poset is a directed-complete partial order, or DCPO, if it has least upper bounds of all directed families.
record is-dcpo : Type (lsuc o ⊔ ℓ) where
no-eta-equality
field
directed-lubs: ∀ {Ix : Type o} (f : Ix → Ob) → is-directed-family f → Lub P f
module ⋃ {Ix : Type o} (f : Ix → Ob) (dir : is-directed-family f) =
(directed-lubs f dir)
Lub
open ⋃ using () renaming (lub to ⋃; fam≤lub to fam≤⋃; least to ⋃-least) public
Since least upper bounds are unique when they exist, being a DCPO is a property of a poset, and not structure on that poset.
Scott-continuous functions🔗
Let and be a pair of posets. A monotone map is called Scott-continuous when it preserves all directed lubs.
: (f : Posets.Hom P Q) → Type _
is-scott-continuous =
is-scott-continuous f ∀ {Ix} (s : Ix → P.Ob) (fam : is-directed-family P s)
→ ∀ x → is-lub P s x → is-lub Q (f .hom ⊙ s) (f .hom x)
is-scott-continuous-is-prop: ∀ (f : Posets.Hom P Q) → is-prop (is-scott-continuous f)
_ = hlevel 1 is-scott-continuous-is-prop
If is a DCPO, then any function which preserves directed lubs is automatically a monotone map, and, consequently, Scott-continuous.
To see this, suppose we’re given with The family that sends to and to is directed: is inhabited, and is a least upper bound for arbitrary values of the family. Since preserves lubs, we have
opaque
dcpo+scott→monotone: is-dcpo P
→ (f : P.Ob → Q.Ob)
→ (∀ {Ix} (s : Ix → Poset.Ob P) (fam : is-directed-family P s)
→ ∀ x → is-lub P s x → is-lub Q (f ⊙ s) (f x))
→ ∀ {x y} → x P.≤ y → f x Q.≤ f y
{x} {y} p =
dcpo+scott→monotone is-dcpo f scott .is-lub.fam≤lub (lift true) where
fs-lub : Lift o Bool → P.Ob
s (lift b) = if b then x else y
s
: ∀ b → s b P.≤ s (lift false)
sx≤sfalse (lift true) = p
sx≤sfalse (lift false) = P.≤-refl
sx≤sfalse
: is-directed-family P s
s-directed .elt =
s-directed (lift true)
inc .semidirected i j =
s-directed (lift false , sx≤sfalse _ , sx≤sfalse _)
inc
: is-lub P s y
s-lub .is-lub.fam≤lub = sx≤sfalse
s-lub .is-lub.least z lt = lt (lift false)
s-lub
: is-lub Q (f ⊙ s) (f y)
fs-lub = scott s s-directed y s-lub fs-lub
Moreover, if is an arbitrary monotone map, and is a directed family, then is still a directed family.
monotone∘directed: ∀ {Ix : Type o}
→ {s : Ix → P.Ob}
→ (f : Posets.Hom P Q)
→ is-directed-family P s
→ is-directed-family Q (f .hom ⊙ s)
.elt = dir .elt
monotone∘directed f dir .is-directed-family.semidirected i j =
monotone∘directed f dir (Σ-map₂ (×-map (f .pres-≤) (f .pres-≤)))
∥-∥-map (dir .semidirected i j)
The identity function is Scott-continuous.
scott-id: ∀ {P : Poset o ℓ}
→ is-scott-continuous (Posets.id {x = P})
= lub scott-id s fam x lub
Scott-continuous functions are closed under composition.
scott-∘: ∀ {P Q R : Poset o ℓ}
→ (f : Posets.Hom Q R) (g : Posets.Hom P Q)
→ is-scott-continuous f → is-scott-continuous g
→ is-scott-continuous (f Posets.∘ g)
=
scott-∘ f g f-scott g-scott s dir x lub (g .hom ⊙ s)
f-scott (monotone∘directed g dir)
(g .hom x)
(g-scott s dir x lub)
The category of DCPOs🔗
DCPOs form a subcategory of the category of posets. Furthermore, since being a DCPO is a property, identity of DCPOs is determined by identity of their underlying posets: thus, the category of DCPOs is univalent.
: ∀ (o ℓ : Level) → Subcat (Posets o ℓ) (lsuc o ⊔ ℓ) (lsuc o ⊔ ℓ)
DCPOs-subcat .Subcat.is-ob = is-dcpo
DCPOs-subcat o ℓ .Subcat.is-hom f _ _ = is-scott-continuous f
DCPOs-subcat o ℓ .Subcat.is-hom-prop f _ _ = is-scott-continuous-is-prop f
DCPOs-subcat o ℓ .Subcat.is-hom-id _ = scott-id
DCPOs-subcat o ℓ .Subcat.is-hom-∘ {f = f} {g = g} = scott-∘ f g
DCPOs-subcat o ℓ
: ∀ (o ℓ : Level) → Precategory (lsuc (o ⊔ ℓ)) (lsuc o ⊔ ℓ)
DCPOs = Subcategory (DCPOs-subcat o ℓ)
DCPOs o ℓ
: ∀ {o ℓ} → is-category (DCPOs o ℓ)
DCPOs-is-category = subcat-is-category Posets-is-category (λ _ → hlevel 1) DCPOs-is-category
Reasoning with DCPOs🔗
The following pair of modules re-exports facts about the underlying posets (resp. monotone maps) of DCPOs (resp. Scott-continuous functions). They also prove a plethora of small lemmas that are useful in formalisation but not for informal reading.
These proofs are all quite straightforward, so we omit them.
module DCPO {o ℓ} (D : DCPO o ℓ) where
: Poset o ℓ
poset = D .fst
poset
open Order.Reasoning poset public
: Set o
set = el ⌞ D ⌟ Ob-is-set
set
: is-dcpo poset
has-dcpo = D .snd
has-dcpo
open is-dcpo has-dcpo public
⋃-pointwise: ∀ {Ix} {s s' : Ix → Ob}
→ {fam : is-directed-family poset s} {fam' : is-directed-family poset s'}
→ (∀ ix → s ix ≤ s' ix)
→ ⋃ s fam ≤ ⋃ s' fam'
= ⋃.least _ _ (⋃ _ _) λ ix →
⋃-pointwise p (p ix) (⋃.fam≤lub _ _ ix)
≤-trans
module Scott {o ℓ} {D E : DCPO o ℓ} (f : DCPOs.Hom D E) where
private
module D = DCPO D
module E = DCPO E
: Posets.Hom D.poset E.poset
mono = Subcat-hom.hom f
mono
: ∀ {x y} → x D.≤ y → f # x E.≤ f # y
monotone = mono .pres-≤
monotone
opaque
pres-directed-lub: ∀ {Ix} (s : Ix → D.Ob) → is-directed-family D.poset s
→ ∀ x → is-lub (D .fst) s x → is-lub (E .fst) (apply f ⊙ s) (f # x)
= Subcat-hom.witness f
pres-directed-lub
directed: ∀ {Ix} {s : Ix → D.Ob} → is-directed-family D.poset s
→ is-directed-family E.poset (apply f ⊙ s)
= monotone∘directed (Subcat-hom.hom f) dir
directed dir
pres-⋃: ∀ {Ix} (s : Ix → D.Ob) → (dir : is-directed-family D.poset s)
→ f # (D.⋃ s dir) ≡ E.⋃ (apply f ⊙ s) (directed dir)
=
pres-⋃ s dir .≤-antisym
E(is-lub.least (pres-directed-lub s dir (D.⋃ s dir) (D.⋃.has-lub s dir))
(E.⋃ (apply f ⊙ s) (directed dir))
(E.⋃.fam≤lub (apply f ⊙ s) (directed dir)))
(E.⋃.least (apply f ⊙ s) (directed dir) (apply f (D.⋃ s dir)) λ i →
(D.⋃.fam≤lub s dir i)) monotone
We also provide a couple methods for constructing Scott-continuous maps. First, we note that if a function is monotonic and commutes with some chosen assignment of least upper bounds, then it is Scott-continuous.
to-scott: (f : D.Ob → E.Ob)
→ (∀ {x y} → x D.≤ y → f x E.≤ f y)
→ (∀ {Ix} (s : Ix → D.Ob) → (dir : is-directed-family D.poset s)
→ is-lub E.poset (f ⊙ s) (f (D.⋃ s dir)))
→ DCPOs.Hom D E
= sub-hom fᵐ pres-lub where
to-scott f monotone pres-⋃ : Monotone D.poset E.poset
fᵐ .hom = f
fᵐ .pres-≤ = monotone
fᵐ
pres-lub: ∀ {Ix} (s : Ix → D.Ob) → (dir : is-directed-family D.poset s)
→ ∀ x → is-lub D.poset s x → is-lub E.poset (f ⊙ s) (f x)
.is-lub.fam≤lub i =
pres-lub s dir x x-lub (is-lub.fam≤lub x-lub i)
monotone .is-lub.least y le =
pres-lub s dir x x-lub .≤⟨ monotone (is-lub.least x-lub _ (D.⋃.fam≤lub s dir)) ⟩
f x E(D.⋃ s dir) E.=⟨ lub-unique (pres-⋃ s dir) (E.⋃.has-lub (f ⊙ s) (monotone∘directed fᵐ dir)) ⟩
f .⋃ (f ⊙ s) _ E.≤⟨ E.⋃.least _ _ y le ⟩
E.≤∎ y E
Furthermore, if preserves arbitrary least upper bounds, then it is monotone, and thus Scott-continuous.
to-scott-directed: (f : D.Ob → E.Ob)
→ (∀ {Ix} (s : Ix → D.Ob) → (dir : is-directed-family D.poset s)
→ ∀ x → is-lub D.poset s x → is-lub E.poset (f ⊙ s) (f x))
→ DCPOs.Hom D E
.Subcat-hom.hom .hom = f
to-scott-directed f pres .Subcat-hom.hom .pres-≤ =
to-scott-directed f pres .has-dcpo f pres
dcpo+scott→monotone D.Subcat-hom.witness = pres to-scott-directed f pres