module Order.Diagram.Lub where
module _ {o ℓ} (P : Poset o ℓ) where
open Poset P
Least upper bounds🔗
A lub (short for least upper bound) for a family of elements is, as the name implies, a least elemnet among the upper boudns of the Being an upper bound means that we have for all Being the least upper bound means that if we’re given some other satisfying (for each then we have
The same observation about the naming of glbs vs meets applies to lubs, with the binary name being join.
record is-lub
{ℓᵢ} {I : Type ℓᵢ} (F : I → Ob) (lub : Ob)
: Type (o ⊔ ℓ ⊔ ℓᵢ)
where
no-eta-equality
field
: ∀ i → F i ≤ lub
fam≤lub : (ub' : Ob) → (∀ i → F i ≤ ub') → lub ≤ ub'
least
record Lub {ℓᵢ} {I : Type ℓᵢ} (F : I → Ob) : Type (o ⊔ ℓ ⊔ ℓᵢ) where
no-eta-equality
field
: Ob
lub : is-lub F lub
has-lub open is-lub has-lub public
unquoteDecl H-Level-is-lub = declare-record-hlevel 1 H-Level-is-lub (quote is-lub)
module _ {o ℓ} {P : Poset o ℓ} where
open Order.Reasoning P
open is-lub
lub-unique: ∀ {ℓᵢ} {I : Type ℓᵢ} {F : I → Ob} {x y}
→ is-lub P F x → is-lub P F y
→ x ≡ y
{x = x} {y = y} lub lub' = ≤-antisym
lub-unique (lub .least y (lub' .fam≤lub))
(lub' .least x (lub .fam≤lub))
Lub-is-prop: ∀ {ℓᵢ} {I : Type ℓᵢ} {F : I → Ob}
→ is-prop (Lub P F)
.Lub.lub =
Lub-is-prop p q i (Lub.has-lub p) (Lub.has-lub q) i
lub-unique {F = F} p q i .Lub.has-lub =
Lub-is-prop
is-prop→pathp(λ i → hlevel {T = is-lub _ _ (lub-unique (Lub.has-lub p) (Lub.has-lub q) i)} 1)
(Lub.has-lub p) (Lub.has-lub q) i
instance
H-Level-Lub: ∀ {ℓᵢ} {I : Type ℓᵢ} {F : I → Ob} {n}
→ H-Level (Lub P F) (suc n)
= prop-instance Lub-is-prop
H-Level-Lub
lift-is-lub: ∀ {ℓᵢ ℓᵢ'} {I : Type ℓᵢ} {F : I → Ob} {lub}
→ is-lub P F lub → is-lub P (F ⊙ lower {ℓ = ℓᵢ'}) lub
.fam≤lub (lift ix) = is .fam≤lub ix
lift-is-lub is .least ub' le = is .least ub' (le ⊙ lift)
lift-is-lub is
lift-lub: ∀ {ℓᵢ ℓᵢ'} {I : Type ℓᵢ} {F : I → Ob}
→ Lub P F → Lub P (F ⊙ lower {ℓ = ℓᵢ'})
.Lub.lub = Lub.lub lub
lift-lub lub .Lub.has-lub = lift-is-lub (Lub.has-lub lub)
lift-lub lub
lower-is-lub: ∀ {ℓᵢ ℓᵢ'} {I : Type ℓᵢ} {F : I → Ob} {lub}
→ is-lub P (F ⊙ lower {ℓ = ℓᵢ'}) lub → is-lub P F lub
.fam≤lub ix = is .fam≤lub (lift ix)
lower-is-lub is .least ub' le = is .least ub' (le ⊙ lower)
lower-is-lub is
lower-lub: ∀ {ℓᵢ ℓᵢ'} {I : Type ℓᵢ} {F : I → Ob}
→ Lub P (F ⊙ lower {ℓ = ℓᵢ'}) → Lub P F
.Lub.lub = Lub.lub lub
lower-lub lub .Lub.has-lub = lower-is-lub (Lub.has-lub lub) lower-lub lub
module _
{ℓᵢ ℓᵢ'} {Ix : Type ℓᵢ} {Im : Type ℓᵢ'}
{f : Ix → Im}
{F : Im → Ob}
(surj : is-surjective f)
where
: ∀ {lub} → is-lub P F lub → is-lub P (F ⊙ f) lub
cover-preserves-is-lub .fam≤lub x = l .fam≤lub (f x)
cover-preserves-is-lub l .least ub' le = l .least ub' λ i → ∥-∥-out! do
cover-preserves-is-lub l (i' , p) ← surj i
(≤-trans (≤-refl' (ap F (sym p))) (le i'))
pure
: Lub P F → Lub P (F ⊙ f)
cover-preserves-lub .Lub.lub = _
cover-preserves-lub l .Lub.has-lub = cover-preserves-is-lub (l .Lub.has-lub)
cover-preserves-lub l
: ∀ {lub} → is-lub P (F ⊙ f) lub → is-lub P F lub
cover-reflects-is-lub .fam≤lub x = ∥-∥-out! do
cover-reflects-is-lub l (y , p) ← surj x
(≤-trans (≤-refl' (ap F (sym p))) (l .fam≤lub y))
pure .least ub' le = l .least ub' λ i → le (f i)
cover-reflects-is-lub l
: Lub P (F ⊙ f) → Lub P F
cover-reflects-lub .Lub.lub = _
cover-reflects-lub l .Lub.has-lub = cover-reflects-is-lub (l .Lub.has-lub)
cover-reflects-lub l
cast-is-lub: ∀ {ℓᵢ ℓᵢ'} {I : Type ℓᵢ} {I' : Type ℓᵢ'} {F : I → Ob} {G : I' → Ob} {lub}
→ (e : I ≃ I')
→ (∀ i → F i ≡ G (Equiv.to e i))
→ is-lub P F lub
→ is-lub P G lub
{G = G} e p has-lub .fam≤lub i' =
cast-is-lub
≤-trans(≤-refl' (sym (p (Equiv.from e i') ∙ ap G (Equiv.ε e i'))))
(has-lub .fam≤lub (Equiv.from e i'))
.least ub G≤ub =
cast-is-lub e p has-lub .least ub (λ i → ≤-trans (≤-refl' (p i)) (G≤ub (Equiv.to e i)))
has-lub
cast-is-lubᶠ: ∀ {ℓᵢ} {I : Type ℓᵢ} {F G : I → Ob} {lub}
→ (∀ i → F i ≡ G i)
→ is-lub P F lub
→ is-lub P G lub
{lub = lub} p has-lub = cast-is-lub (_ , id-equiv) p has-lub cast-is-lubᶠ
Let be a family. If there is some such that for all then is the least upper bound of
fam-bound→is-lub: ∀ {ℓᵢ} {I : Type ℓᵢ} {F : I → Ob}
→ (i : I) → (∀ j → F j ≤ F i)
→ is-lub P F (F i)
.fam≤lub = ge
fam-bound→is-lub i ge .least y le = le i fam-bound→is-lub i ge
If is the least upper bound of a constant family, then must be equal to every member of the family.
lub-of-const-fam: ∀ {ℓᵢ} {I : Type ℓᵢ} {F : I → Ob} {x}
→ (∀ i j → F i ≡ F j)
→ is-lub P F x
→ ∀ i → F i ≡ x
{F = F} is-const x-lub i =
lub-of-const-fam
≤-antisym(fam≤lub x-lub i)
(least x-lub (F i) λ j → ≤-refl' (sym (is-const i j)))
Furthermore, if is a constant family and is merely inhabited, then has a least upper bound.
const-inhabited-fam→is-lub: ∀ {ℓᵢ} {I : Type ℓᵢ} {F : I → Ob} {x}
→ (∀ i → F i ≡ x)
→ ∥ I ∥
→ is-lub P F x
{I = I} {F = F} {x = x} is-const =
const-inhabited-fam→is-lub where
rec! mk-is-lub : I → is-lub P F x
mk-is-lub .is-lub.fam≤lub j = ≤-refl' (is-const j)
mk-is-lub i .is-lub.least y le =
mk-is-lub i
x =˘⟨ is-const i ⟩
F i ≤⟨ le i ⟩
y ≤∎
const-inhabited-fam→lub: ∀ {ℓᵢ} {I : Type ℓᵢ} {F : I → Ob}
→ (∀ i j → F i ≡ F j)
→ ∥ I ∥
→ Lub P F
{I = I} {F = F} is-const =
const-inhabited-fam→lub where
rec! mk-lub : I → Lub P F
mk-lub .Lub.lub = F i
mk-lub i .Lub.has-lub =
mk-lub i (λ j → is-const j i) (inc i) const-inhabited-fam→is-lub