Tom de Jong, early January 2022.
In category theory, the Ind-completion freely adds filtered colimits. For a
poset, the Ind-completion can be described as the preorder of directed families
into the poset, ordered by cofinality.
We construct the Ind-completion for a 𝓥-dcpo 𝓓 and show it is a preorder. We
define and characterize what it means for the map Ind → 𝓓 that takes suprema to
have a left adjoint. We also consider the poset reflection Ind/≈ of Ind and
define what it means for the induced map Ind/≈ → 𝓓 to have a left adjoint.
This development is used in exploring possible notions of continuous dcpo in
ContinuityDiscussion.lagda. In particular, the observation that the
Ind-completion is a preorder and not a poset is seen to be important there.
\begin{code}
{-# OPTIONS --safe --without-K #-}
open import MLTT.Spartan hiding (J)
open import UF.FunExt
open import UF.PropTrunc
module DomainTheory.BasesAndContinuity.IndCompletion
(pt : propositional-truncations-exist)
(fe : Fun-Ext)
(𝓥 : Universe)
where
open PropositionalTruncation pt
open import UF.Equiv
open import UF.EquivalenceExamples
open import UF.Subsingletons
open import UF.Subsingletons-FunExt
open import UF.Sets
open import DomainTheory.Basics.Dcpo pt fe 𝓥
open import DomainTheory.Basics.Miscelanea pt fe 𝓥
open import DomainTheory.Basics.WayBelow pt fe 𝓥
module Ind-completion
(𝓓 : DCPO {𝓤} {𝓣})
where
Ind : 𝓥 ⁺ ⊔ 𝓤 ⊔ 𝓣 ̇
Ind = Σ I ꞉ 𝓥 ̇ , Σ α ꞉ (I → ⟨ 𝓓 ⟩) , is-Directed 𝓓 α
index-of-underlying-family : Ind → 𝓥 ̇
index-of-underlying-family = pr₁
underlying-family : (α : Ind) → index-of-underlying-family α → ⟨ 𝓓 ⟩
underlying-family α = pr₁ (pr₂ α)
_≲_ : Ind → Ind → 𝓥 ⊔ 𝓣 ̇
(I , α , _) ≲ (J , β , _) = (i : I) → ∃ j ꞉ J , α i ⊑⟨ 𝓓 ⟩ β j
≲-is-prop-valued : (α β : Ind) → is-prop (α ≲ β)
≲-is-prop-valued α β = Π-is-prop fe (λ i → ∥∥-is-prop)
≲-is-reflexive : (α : Ind) → α ≲ α
≲-is-reflexive (I , α , δ) i = ∣ i , reflexivity 𝓓 (α i) ∣
≲-is-transitive : (σ τ ρ : Ind) → σ ≲ τ → τ ≲ ρ → σ ≲ ρ
≲-is-transitive (I , α , δ) (J , β , ε) (K , γ , ϕ)
α-cofinal-in-β β-cofinal-in-γ i = ∥∥-rec ∥∥-is-prop r (α-cofinal-in-β i)
where
r : (Σ j ꞉ J , α i ⊑⟨ 𝓓 ⟩ β j)
→ (∃ k ꞉ K , α i ⊑⟨ 𝓓 ⟩ γ k)
r (j , u) = ∥∥-functor (λ (k , v) → k , (α i ⊑⟨ 𝓓 ⟩[ u ]
β j ⊑⟨ 𝓓 ⟩[ v ]
γ k ∎⟨ 𝓓 ⟩))
(β-cofinal-in-γ j)
\end{code}
We now construct directed suprema of 𝓥-small families in Ind.
\begin{code}
Ind-∐ : {I : 𝓥 ̇ } (𝓐 : I → Ind)
→ is-directed _≲_ 𝓐
→ Ind
Ind-∐ {I} 𝓐 (I-inhabited , 𝓐-semidirected) =
Σ J , β , K-is-inhabited , β-is-semidirected
where
J : I → 𝓥 ̇
J i = pr₁ (𝓐 i)
α : (i : I) → J i → ⟨ 𝓓 ⟩
α i = pr₁ (pr₂ (𝓐 i))
δ : (i : I) → is-Directed 𝓓 (α i)
δ i = pr₂ (pr₂ (𝓐 i))
K : 𝓥 ̇
K = Σ J
β : K → ⟨ 𝓓 ⟩
β (i , j) = α i j
K-is-inhabited : ∥ K ∥
K-is-inhabited =
∥∥-rec ∥∥-is-prop h I-inhabited
where
h : I → ∥ K ∥
h i = ∥∥-functor (λ j → (i , j)) (inhabited-if-Directed 𝓓 (α i) (δ i))
β-is-semidirected : is-semidirected (underlying-order 𝓓) β
β-is-semidirected (i₁ , j₁) (i₂ , j₂) =
∥∥-rec ∥∥-is-prop f (𝓐-semidirected i₁ i₂)
where
f : (Σ i ꞉ I , (𝓐 i₁ ≲ 𝓐 i) × (𝓐 i₂ ≲ 𝓐 i))
→ ∃ k ꞉ K , (β (i₁ , j₁) ⊑⟨ 𝓓 ⟩ β k) × (β (i₂ , j₂) ⊑⟨ 𝓓 ⟩ β k)
f (i , u₁ , u₂) = ∥∥-rec ∥∥-is-prop g (u₁ j₁)
where
g : (Σ jⁱ₁ ꞉ J i , β (i₁ , j₁) ⊑⟨ 𝓓 ⟩ β (i , jⁱ₁))
→ ∃ k ꞉ K , (β (i₁ , j₁) ⊑⟨ 𝓓 ⟩ β k) × (β (i₂ , j₂) ⊑⟨ 𝓓 ⟩ β k)
g (jⁱ₁ , v₁) = ∥∥-rec ∥∥-is-prop h (u₂ j₂)
where
h : (Σ jⁱ₂ ꞉ J i , β (i₂ , j₂) ⊑⟨ 𝓓 ⟩ β (i , jⁱ₂))
→ ∃ k ꞉ K , (β (i₁ , j₁) ⊑⟨ 𝓓 ⟩ β k) × (β (i₂ , j₂) ⊑⟨ 𝓓 ⟩ β k)
h (jⁱ₂ , v₂) = ∥∥-functor r
(semidirected-if-Directed 𝓓 (α i) (δ i) jⁱ₁ jⁱ₂)
where
r : (Σ j ꞉ J i , (α i jⁱ₁ ⊑⟨ 𝓓 ⟩ α i j) × (α i jⁱ₂ ⊑⟨ 𝓓 ⟩ α i j))
→ Σ k ꞉ K , (β (i₁ , j₁) ⊑⟨ 𝓓 ⟩ β k) × (β (i₂ , j₂) ⊑⟨ 𝓓 ⟩ β k)
r (j , w₁ , w₂) = (i , j) ,
( (β (i₁ , j₁) ⊑⟨ 𝓓 ⟩[ v₁ ]
β (i , jⁱ₁) ⊑⟨ 𝓓 ⟩[ w₁ ]
β (i , j) ∎⟨ 𝓓 ⟩)
, (β (i₂ , j₂) ⊑⟨ 𝓓 ⟩[ v₂ ]
β (i , jⁱ₂) ⊑⟨ 𝓓 ⟩[ w₂ ]
β (i , j) ∎⟨ 𝓓 ⟩))
Ind-∐-is-directed : {I : 𝓥 ̇ } (𝓐 : I → Ind) (δ : is-directed _≲_ 𝓐)
→ is-Directed 𝓓 (underlying-family (Ind-∐ 𝓐 δ))
Ind-∐-is-directed 𝓐 δ = pr₂ (pr₂ (Ind-∐ 𝓐 δ))
Ind-∐-is-upperbound : {I : 𝓥 ̇ } (𝓐 : I → Ind) (δ : is-directed _≲_ 𝓐)
→ is-upperbound _≲_ (Ind-∐ 𝓐 δ) 𝓐
Ind-∐-is-upperbound 𝓐 δ i j =
∣ (i , j) , reflexivity 𝓓 (pr₁ (pr₂ (𝓐 i)) j) ∣
Ind-∐-is-lowerbound-of-upperbounds : {I : 𝓥 ̇ } (𝓐 : I → Ind)
(δ : is-directed _≲_ 𝓐)
→ is-lowerbound-of-upperbounds _≲_
(Ind-∐ 𝓐 δ) 𝓐
Ind-∐-is-lowerbound-of-upperbounds {A} 𝓐 _ _ ub (i , j) = ub i j
\end{code}
Taking suprema in our 𝓥-dcpo 𝓓 of directed families indexed into 𝓓 defines a
monotone map from Ind to 𝓓.
\begin{code}
∐-map : Ind → ⟨ 𝓓 ⟩
∐-map (I , α , δ) = ∐ 𝓓 δ
≲-to-⊑-of-∐ : {I J : 𝓥 ̇ } {α : I → ⟨ 𝓓 ⟩} {β : J → ⟨ 𝓓 ⟩}
(δ : is-Directed 𝓓 α) (ε : is-Directed 𝓓 β)
→ (I , α , δ) ≲ (J , β , ε)
→ ∐ 𝓓 δ ⊑⟨ 𝓓 ⟩ ∐ 𝓓 ε
≲-to-⊑-of-∐ {I} {J} {α} {β} δ ε α-cofinal-in-β =
∐-⊑-if-cofinal 𝓓 α-cofinal-in-β δ ε
∐-map-is-monotone : (α β : Ind) → α ≲ β → ∐-map α ⊑⟨ 𝓓 ⟩ ∐-map β
∐-map-is-monotone (I , α , δ) (J , β , ε) = ≲-to-⊑-of-∐ δ ε
\end{code}
Since we can view every element of 𝓓 as a constant directed family into 𝓓, we
also have a map in the other direction which comes in useful at times.
\begin{code}
⌞_⌟ : ⟨ 𝓓 ⟩ → (𝟙{𝓥} → ⟨ 𝓓 ⟩)
⌞_⌟ x = λ _ → x
⌞⌟-is-directed : (x : ⟨ 𝓓 ⟩) → is-Directed 𝓓 ⌞ x ⌟
⌞⌟-is-directed x = ∣ ⋆ ∣ , σ
where
σ : is-semidirected (underlying-order 𝓓) (λ _ → x)
σ i j = ∣ ⋆ , reflexivity 𝓓 x , reflexivity 𝓓 x ∣
ι : ⟨ 𝓓 ⟩ → Ind
ι x = 𝟙 , ⌞ x ⌟ , ⌞⌟-is-directed x
\end{code}
In our discussions on the notion of continuous dcpo we will be interested in
∐-map having a left adjoint, see ContinuityDiscussion.lagda.
We define what that means here and note that it is helpful to consider an
auxilliary relation between Ind(D) and D that we call "being left adjunct to",
because a map L : D → Ind(D) is a left adjoint to ∐-map precisely when L(x) is
left adjunct to x for every x : D.
\begin{code}
_is-left-adjunct-to_ : Ind → ⟨ 𝓓 ⟩ → 𝓥 ⁺ ⊔ 𝓤 ⊔ 𝓣 ̇
α is-left-adjunct-to x = (β : Ind) → (α ≲ β) ↔ (x ⊑⟨ 𝓓 ⟩ ∐-map β)
being-left-adjunct-to-is-prop : (σ : Ind) (x : ⟨ 𝓓 ⟩)
→ is-prop (σ is-left-adjunct-to x)
being-left-adjunct-to-is-prop σ x =
Π-is-prop fe (λ τ → ↔-is-prop fe fe (≲-is-prop-valued σ τ)
(prop-valuedness 𝓓 x (∐-map τ)))
left-adjoint-to-∐-map : (⟨ 𝓓 ⟩ → Ind) → 𝓥 ⁺ ⊔ 𝓤 ⊔ 𝓣 ̇
left-adjoint-to-∐-map L = (x : ⟨ 𝓓 ⟩) → L x is-left-adjunct-to x
being-left-adjoint-to-∐-map-is-prop : (L : ⟨ 𝓓 ⟩ → Ind)
→ is-prop (left-adjoint-to-∐-map L)
being-left-adjoint-to-∐-map-is-prop L =
Π-is-prop fe (λ x → being-left-adjunct-to-is-prop (L x) x)
∐-map-has-specified-left-adjoint : 𝓥 ⁺ ⊔ 𝓤 ⊔ 𝓣 ̇
∐-map-has-specified-left-adjoint = Σ left-adjoint-to-∐-map
\end{code}
We can equivalently describe the adjoint-condition in terms of directed suprema
and the way-below relation.
\begin{code}
_approximates_ : Ind → ⟨ 𝓓 ⟩ → 𝓥 ⁺ ⊔ 𝓤 ⊔ 𝓣 ̇
(I , α , δ) approximates x = (∐ 𝓓 δ = x) × ((i : I) → α i ≪⟨ 𝓓 ⟩ x)
approximates-to-∐-= : {(I , α , δ) : Ind} {x : ⟨ 𝓓 ⟩}
→ (I , α , δ) approximates x
→ ∐ 𝓓 δ = x
approximates-to-∐-= = pr₁
approximates-to-≪ : {(I , α , δ) : Ind} {x : ⟨ 𝓓 ⟩}
→ (I , α , δ) approximates x
→ ((i : I) → α i ≪⟨ 𝓓 ⟩ x)
approximates-to-≪ = pr₂
approximates-is-prop : (σ : Ind) (x : ⟨ 𝓓 ⟩) → is-prop (σ approximates x)
approximates-is-prop σ x =
×-is-prop (sethood 𝓓) (Π-is-prop fe (λ i → ≪-is-prop-valued 𝓓))
is-approximating : (⟨ 𝓓 ⟩ → Ind) → 𝓥 ⁺ ⊔ 𝓤 ⊔ 𝓣 ̇
is-approximating L = (x : ⟨ 𝓓 ⟩) → (L x) approximates x
left-adjunct-to-if-approximates : (σ : Ind) (x : ⟨ 𝓓 ⟩)
→ σ approximates x → σ is-left-adjunct-to x
left-adjunct-to-if-approximates σ@(I , α , δ) x (x-sup-of-α , α-way-below-x)
τ@(J , β , ε) = ⦅⇒⦆ , ⦅⇐⦆
where
⦅⇒⦆ : σ ≲ τ → x ⊑⟨ 𝓓 ⟩ ∐-map τ
⦅⇒⦆ α-cofinal-in-β = transport (λ - → - ⊑⟨ 𝓓 ⟩ ∐-map τ) x-sup-of-α
(≲-to-⊑-of-∐ δ ε α-cofinal-in-β)
⦅⇐⦆ : x ⊑⟨ 𝓓 ⟩ ∐-map τ → σ ≲ τ
⦅⇐⦆ x-below-∐β i = α-way-below-x i J β ε x-below-∐β
approximates-if-left-adjunct-to : (σ : Ind) (x : ⟨ 𝓓 ⟩)
→ σ is-left-adjunct-to x
→ σ approximates x
approximates-if-left-adjunct-to σ@(I , α , δ) x ladj =
x-is-sup-of-α , α-way-below-x
where
α-way-below-x : (i : I) → α i ≪⟨ 𝓓 ⟩ x
α-way-below-x i J β ε x-below-∐β = h i
where
h : (I , α , δ) ≲ (J , β , ε)
h = rl-implication (ladj (J , β , ε)) x-below-∐β
x-is-sup-of-α : ∐ 𝓓 δ = x
x-is-sup-of-α = antisymmetry 𝓓 (∐ 𝓓 δ) x ⦅1⦆ ⦅2⦆
where
⦅1⦆ : ∐ 𝓓 δ ⊑⟨ 𝓓 ⟩ x
⦅1⦆ = ∐-is-lowerbound-of-upperbounds 𝓓 δ x
(λ i → ≪-to-⊑ 𝓓 (α-way-below-x i))
⦅2⦆ : x ⊑⟨ 𝓓 ⟩ ∐ 𝓓 δ
⦅2⦆ = lr-implication (ladj σ) (≲-is-reflexive σ)
approximate-left-adjunct-to-≃ : (σ : Ind) (x : ⟨ 𝓓 ⟩)
→ σ approximates x ≃ σ is-left-adjunct-to x
approximate-left-adjunct-to-≃ σ x = logically-equivalent-props-are-equivalent
(approximates-is-prop σ x)
(being-left-adjunct-to-is-prop σ x)
(left-adjunct-to-if-approximates σ x)
(approximates-if-left-adjunct-to σ x)
left-adjoint-to-∐-map-characterization : (L : ⟨ 𝓓 ⟩ → Ind)
→ is-approximating L
≃ left-adjoint-to-∐-map L
left-adjoint-to-∐-map-characterization L =
Π-cong fe fe (λ x → approximate-left-adjunct-to-≃ (L x) x)
\end{code}
One may observe that the type (left-to-adjoint-to-∐-map L) does not require L to
be functorial/monotone, as would normally be required for an adjoint/Galois
connection. But this actually follows from the "hom-set" condition, as we show
now.
\begin{code}
left-adjoint-to-∐-map-is-monotone : (L : ⟨ 𝓓 ⟩ → Ind)
→ left-adjoint-to-∐-map L
→ (x y : ⟨ 𝓓 ⟩)
→ x ⊑⟨ 𝓓 ⟩ y
→ L x ≲ L y
left-adjoint-to-∐-map-is-monotone L L-left-adjoint x y x-below-y = γ
where
γ : L x ≲ L y
γ = rl-implication (L-left-adjoint x (L y)) x-below-∐-Ly
where
x-below-∐-Ly = x ⊑⟨ 𝓓 ⟩[ x-below-y ]
y ⊑⟨ 𝓓 ⟩[ =-to-⊒ 𝓓 (pr₁ approx) ]
∐-map (L y) ∎⟨ 𝓓 ⟩
where
approx : L y approximates y
approx = approximates-if-left-adjunct-to (L y) y (L-left-adjoint y)
\end{code}
Because Ind is a preorder and not a poset, the type expressing that ∐-map has a
specified left adjoint is not a proposition, as the supposed left adjoint can
map elements of 𝓓 to bicofinal (but nonequal) directed families.
We could take the poset reflection Ind/≈ of Ind and ask that the map Ind/≈ → 𝓓
induced by the supremum-map Ind → 𝓓 has a left adjoint to obtain a type that is
a proposition. We describe that process here.
This is *not* the same as asking that ∐-map : Ind → 𝓓 has an unspecified left
adjoint, as we explain in ContinuityDiscussion.lagda.
\begin{code}
module Ind-completion-poset-reflection
(pe : Prop-Ext)
(𝓓 : DCPO {𝓤} {𝓣})
where
open Ind-completion 𝓓
open import OrderedTypes.PosetReflection pt fe pe
open poset-reflection Ind _≲_ ≲-is-prop-valued ≲-is-reflexive ≲-is-transitive public
Ind/≈ : 𝓥 ⁺ ⊔ 𝓣 ⁺ ⊔ 𝓤 ̇
Ind/≈ = poset-reflection-carrier
Ind/≈-is-set : is-set Ind/≈
Ind/≈-is-set = poset-reflection-is-set
∐-map/-specification :
∃! f̃ ꞉ (Ind/≈ → ⟨ 𝓓 ⟩) , ((σ' τ' : Ind/≈) → σ' ≤ τ' → f̃ σ' ⊑⟨ 𝓓 ⟩ f̃ τ')
× (f̃ ∘ η ∼ ∐-map)
∐-map/-specification =
universal-property (underlying-order 𝓓) (sethood 𝓓) (prop-valuedness 𝓓)
(reflexivity 𝓓) (transitivity 𝓓) (antisymmetry 𝓓)
∐-map ∐-map-is-monotone
∐-map/ : Ind/≈ → ⟨ 𝓓 ⟩
∐-map/ = ∃!-witness ∐-map/-specification
∐-map/-triangle : (α : Ind) → ∐-map/ (η α) = ∐-map α
∐-map/-triangle = pr₂ (∃!-is-witness ∐-map/-specification)
left-adjoint-to-∐-map/ : (⟨ 𝓓 ⟩ → Ind/≈)
→ 𝓥 ⁺ ⊔ 𝓣 ⁺ ⊔ 𝓤 ̇
left-adjoint-to-∐-map/ L' =
(x : ⟨ 𝓓 ⟩) (α' : Ind/≈) → (L' x ≤ α') ↔ (x ⊑⟨ 𝓓 ⟩ ∐-map/ α')
being-left-adjoint-to-∐-map/-is-prop : (L' : ⟨ 𝓓 ⟩ → Ind/≈)
→ is-prop (left-adjoint-to-∐-map/ L')
being-left-adjoint-to-∐-map/-is-prop L' =
Π₂-is-prop fe (λ x α' → ×-is-prop
(Π-is-prop fe (λ _ → prop-valuedness 𝓓 x (∐-map/ α')))
(Π-is-prop fe (λ _ → ≤-is-prop-valued (L' x) α')))
∐-map/-has-specified-left-adjoint : 𝓥 ⁺ ⊔ 𝓣 ⁺ ⊔ 𝓤 ̇
∐-map/-has-specified-left-adjoint = Σ left-adjoint-to-∐-map/
∐-map/-having-left-adjoint-is-prop : is-prop ∐-map/-has-specified-left-adjoint
∐-map/-having-left-adjoint-is-prop
(L , L-is-left-adjoint) (L' , L'-is-left-adjoint) =
to-subtype-= being-left-adjoint-to-∐-map/-is-prop
(dfunext fe (λ x → ≤-is-antisymmetric (L x) (L' x)
(rl-implication (L-is-left-adjoint x (L' x))
(lr-implication (L'-is-left-adjoint x (L' x))
(≤-is-reflexive (L' x))))
(rl-implication (L'-is-left-adjoint x (L x))
(lr-implication (L-is-left-adjoint x (L x))
(≤-is-reflexive (L x))))))
\end{code}