module Order.Diagram.Lub.Reasoning {o } (P : Poset o ) where

Reasoning about least upper bounds🔗

This module provides syntax and reasoning combinators for working with partial orders that have all least upper bounds.

module Lubs
  {      :  {I : Type o} (f : I  Ob)  Ob}
  (⋃-lubs :  {I : Type o} (f : I  Ob)  is-lub P f ( f))
  where

  lubs :  {I : Type o} (f : I  Ob)  Lub P f
  lubs f = record { lub =  f ; has-lub = ⋃-lubs f }

  module ⋃-lubs {I} {f : I  Ob} = is-lub (⋃-lubs f)
  open ⋃-lubs using () renaming (fam≤lub to ⋃-inj; least to ⋃-universal) public

Performing two nested joins over and is the same as taking a single join over

  ⋃-twice
    :  {I : Type o} {J : I  Type o} (F : (i : I)  J i  Ob)
       i   λ j  F i j)
      {I = Σ I J}  p  F (p .fst) (p .snd))
  ⋃-twice F = ≤-antisym
    (⋃-universal _  i  ⋃-universal _  j  ⋃-inj _)))
    (⋃-universal _ λ (i , j)  ≤-trans (⋃-inj j) (⋃-inj i))

Let and be a pair of families. If there is a map such that then the meet of is smaller than the meet of

  ⋃≤⋃-over
    :  {I J : Type o} {f : I  Ob} {g : J  Ob}
     (to : I  J)
     (∀ i  f i  g (to i))
      f   g
  ⋃≤⋃-over to p = ⋃-universal _ λ i  ≤-trans (p i) (⋃-inj (to i))

As a corollary, if is smaller than for each then the join of is smaller than the join of

  ⋃≤⋃
    :  {I : Type o} {f g : I  Ob}
     (∀ i  f i  g i)
      f   g
  ⋃≤⋃ = ⋃≤⋃-over  i  i)

Taking the join over a contractible family is equal the unique value of the family.

  ⋃-singleton
    :  {I : Type o} {f : I  Ob}
     (p : is-contr I)
      f  f (p .centre)
  ⋃-singleton {f = f} p = ≤-antisym
    (⋃-universal _ λ i  ≤-refl' $ sym $ ap f (p .paths i))
    (⋃-inj _)

We also provide syntax for binary joins and bottom elements.

  module _ (x y : Ob) where opaque
    private
      it : Join P x y
      it = Lub→Join (lower-lub (lubs _))

    infixr 24 _∪_
    _∪_ : Ob
    _∪_ = it .Join.lub

    ∪-joins : is-join P x y _∪_
    ∪-joins = it .Join.has-join

  opaque
    has-bottom : Bottom
    has-bottom = Lub→Bottom (lower-lub (lubs  ())))

  open Joins ∪-joins public
  open Bottom has-bottom using (bot; ¡) public

There is a distributive law relating binary and infinitary joins.

  ∪-distrib-⋃-≤l
    :  {I : Type o} {x : Ob} {f : I  Ob}
       i  x  f i)  x   f
  ∪-distrib-⋃-≤l =
    ⋃-universal _ λ i  ∪-universal _ l≤∪ (≤-trans (⋃-inj i) r≤∪)

If the infinitary join is taken over a non-empty family, then the previous distributive law can be extended to an equality.

  ∪-distrib-nonempty-⋃-l
    :  {I : Type o} {x : Ob} {f : I  Ob}
      I 
       i  x  f i)  x   f
  ∪-distrib-nonempty-⋃-l i =
    ≤-antisym
      ∪-distrib-⋃-≤l
      (rec!  i  ∪-universal _ (≤-trans l≤∪ (⋃-inj i)) (⋃≤⋃ λ _  r≤∪)) i)

Large joins🔗

Let be a poset. If has all joins of size then it has all joins, regardless of size.

is-cocomplete→is-large-cocomplete
  : (lubs :  {I : Type o} (f : I  Ob)  Lub P f)
    {} {I : Type } (F : I  Ob)  Lub P F
is-cocomplete→is-large-cocomplete lubs {I = I} F =
  cover-preserves-lub
    (Ω-corestriction-is-surjective F)
    (lubs fst)

We also provide some notation for large joins.

module
  Large
    { : {I : Type o} (F : I  Ob)  Ob}
    (⋃-lubs :  {I} f  is-lub P f ( {I} f))
  where

  open Lubs ⋃-lubs using (lubs)

  opaque
    ⋃ᴸ :  {} {I : Type } (F : I  Ob)  Ob
    ⋃ᴸ F = is-cocomplete→is-large-cocomplete lubs F .Lub.lub

    ⋃ᴸ-inj :  {} {I : Type } {F : I  Ob} (i : I)  F i  ⋃ᴸ F
    ⋃ᴸ-inj = Lub.fam≤lub (is-cocomplete→is-large-cocomplete lubs _)

    ⋃ᴸ-universal :  {} {I : Type } {F : I  Ob} (x : Ob)  (∀ i  F i  x)  ⋃ᴸ F  x
    ⋃ᴸ-universal = Lub.least (is-cocomplete→is-large-cocomplete lubs _)