-
Eric Giovannini authoredEric Giovannini authored
Lemmas.agda 13.35 KiB
{-# OPTIONS --cubical --rewriting --guarded #-}
-- to allow opening this module in other files while there are still holes
{-# OPTIONS --allow-unsolved-metas #-}
open import Common.Later
module Semantics.Monotone.Lemmas (k : Clock) where
open import Cubical.Foundations.Prelude
open import Cubical.Data.Nat renaming (ℕ to Nat) hiding (_^_)
open import Cubical.Relation.Binary
open import Cubical.Relation.Binary.Poset
open import Cubical.Foundations.Structure
open import Cubical.Foundations.Transport
open import Cubical.Data.Unit
open import Cubical.Data.Sigma
open import Cubical.Data.Empty
open import Cubical.Foundations.Function
open import Semantics.Predomains
open import Semantics.Lift k
open import Semantics.Monotone.Base
open import Semantics.StrongBisimulation k
open import Semantics.PredomainInternalHom
-- open import Syntax.GradualSTLC
-- open import Syntax.SyntacticTermPrecision k
private
variable
l : Level
A B : Set l
private
▹_ : Set l → Set l
▹_ A = ▹_,_ k A
open LiftPredomain
{-
test : (A B : Type) -> (eq : A ≡ B) -> (x : A) -> (T : (A : Type) -> A -> Type) ->
(T A x) -> (T B (transport eq x))
test A B eq x T Tx = transport (λ i -> T (eq i) (transport-filler eq x i)) Tx
-- transport (λ i -> T (eq i) ?) Tx
-- Goal : eq i
-- Constraints:
-- x = ?8 (i = i0) : A
-- ?8 (i = i1) = transp (λ i₁ → eq i₁) i0 x : B
-- transport-filler : ∀ {ℓ} {A B : Type ℓ} (p : A ≡ B) (x : A)
-- → PathP (λ i → p i) x (transport p x)
test' : (A B : Predomain) -> (S : Type) ->
(eq : A ≡ B) ->
(x : ⟨ A ⟩) ->
(T : (A : Predomain) -> ⟨ A ⟩ -> Type) ->
(T A x) -> T B (transport (λ i -> ⟨ eq i ⟩) x)
test' A B S eq x T Tx = transport
(λ i -> T (eq i) (transport-filler (λ j → ⟨ eq j ⟩) x i))
Tx
-}
-- If A ≡ B, then we can translate knowledge about a relation on A
-- to its image in B obtained by transporting the related elements of A
-- along the equality of the underlying sets of A and B
rel-transport :
{A B : Predomain} ->
(eq : A ≡ B) ->
{a1 a2 : ⟨ A ⟩} ->
rel A a1 a2 ->
rel B
(transport (λ i -> ⟨ eq i ⟩) a1)
(transport (λ i -> ⟨ eq i ⟩) a2)
rel-transport {A} {B} eq {a1} {a2} a1≤a2 =
transport (λ i -> rel (eq i)
(transport-filler (λ j -> ⟨ eq j ⟩) a1 i)
(transport-filler (λ j -> ⟨ eq j ⟩) a2 i))
a1≤a2
rel-transport-sym : {A B : Predomain} ->
(eq : A ≡ B) ->
{b1 b2 : ⟨ B ⟩} ->
rel B b1 b2 ->
rel A
(transport (λ i → ⟨ sym eq i ⟩) b1)
(transport (λ i → ⟨ sym eq i ⟩) b2)
rel-transport-sym eq {b1} {b2} b1≤b2 = rel-transport (sym eq) b1≤b2
mTransport : {A B : Predomain} -> (eq : A ≡ B) -> ⟨ A ==> B ⟩
mTransport {A} {B} eq = record {
f = λ b → transport (λ i -> ⟨ eq i ⟩) b ;
isMon = λ {b1} {b2} b1≤b2 → rel-transport eq b1≤b2 }
mTransportSym : {A B : Predomain} -> (eq : A ≡ B) -> ⟨ B ==> A ⟩
mTransportSym {A} {B} eq = record {
f = λ b → transport (λ i -> ⟨ sym eq i ⟩) b ;
isMon = λ {b1} {b2} b1≤b2 → rel-transport (sym eq) b1≤b2 }
-- Transporting the domain of a monotone function preserves monotonicity
mon-transport-domain : {A B C : Predomain} ->
(eq : A ≡ B) ->
(f : MonFun A C) ->
{b1 b2 : ⟨ B ⟩} ->
(rel B b1 b2) ->
rel C
(MonFun.f f (transport (λ i → ⟨ sym eq i ⟩ ) b1))
(MonFun.f f (transport (λ i → ⟨ sym eq i ⟩ ) b2))
mon-transport-domain eq f {b1} {b2} b1≤b2 =
MonFun.isMon f (rel-transport (sym eq) b1≤b2)
mTransportDomain : {A B C : Predomain} ->
(eq : A ≡ B) ->
MonFun A C ->
MonFun B C
mTransportDomain {A} {B} {C} eq f = record {
f = g eq f;
isMon = mon-transport-domain eq f }
where
g : {A B C : Predomain} ->
(eq : A ≡ B) ->
MonFun A C ->
⟨ B ⟩ -> ⟨ C ⟩
g eq f b = MonFun.f f (transport (λ i → ⟨ sym eq i ⟩ ) b)
-- rel (𝕃 B) (ext f la) (ext f' la') ≡ _A_1119
-- ord (ext f la) (ext f' la') ≡
-- ord' (next ord) (ext' f (next (ext f)) la) (ext' f (next (ext f)) la')
-- ext respects monotonicity, in a general, heterogeneous sense
ext-monotone-het : {A A' B B' : Predomain} ->
(rAA' : ⟨ A ⟩ -> ⟨ A' ⟩ -> Type) -> (rBB' : ⟨ B ⟩ -> ⟨ B' ⟩ -> Type) ->
(f : ⟨ A ⟩ -> ⟨ (𝕃 B) ⟩) -> (f' : ⟨ A' ⟩ -> ⟨ (𝕃 B') ⟩) ->
fun-order-het A A' (𝕃 B) (𝕃 B') rAA' (LiftRelation._≾_ B B' rBB') f f' ->
(la : ⟨ 𝕃 A ⟩) -> (la' : ⟨ 𝕃 A' ⟩) ->
(LiftRelation._≾_ A A' rAA' la la') ->
LiftRelation._≾_ B B' rBB' (ext f la) (ext f' la')
ext-monotone-het {A} {A'} {B} {B'} rAA' rBB' f f' f≤f' la la' la≤la' =
let fixed = fix (monotone-ext') in
transport
(sym (λ i -> LiftBB'.unfold-≾ i (unfold-ext f i la) (unfold-ext f' i la')))
(fixed la la' (transport (λ i → LiftAA'.unfold-≾ i la la') la≤la'))
where
-- Note that these four have already been
-- passed (next _≾_) as a parameter (this happened in
-- the defintion of the module 𝕃, where we said
-- open Inductive (next _≾_) public)
_≾'LA_ = LiftPredomain._≾'_ A
_≾'LA'_ = LiftPredomain._≾'_ A'
_≾'LB_ = LiftPredomain._≾'_ B
_≾'LB'_ = LiftPredomain._≾'_ B'
module LiftAA' = LiftRelation A A' rAA'
module LiftBB' = LiftRelation B B' rBB'
-- The heterogeneous lifted relations
_≾'LALA'_ = LiftAA'.Inductive._≾'_ (next LiftAA'._≾_)
_≾'LBLB'_ = LiftBB'.Inductive._≾'_ (next LiftBB'._≾_)
monotone-ext' :
▹ (
(la : ⟨ 𝕃 A ⟩) -> (la' : ⟨ 𝕃 A' ⟩) ->
(la ≾'LALA' la') ->
(ext' f (next (ext f)) la) ≾'LBLB'
(ext' f' (next (ext f')) la')) ->
(la : ⟨ 𝕃 A ⟩) -> (la' : ⟨ 𝕃 A' ⟩) ->
(la ≾'LALA' la') ->
(ext' f (next (ext f)) la) ≾'LBLB'
(ext' f' (next (ext f')) la')
monotone-ext' IH (η x) (η y) x≤y =
transport
(λ i → LiftBB'.unfold-≾ i (f x) (f' y))
(f≤f' x y x≤y)
monotone-ext' IH ℧ la' la≤la' = tt
monotone-ext' IH (θ lx~) (θ ly~) la≤la' = λ t ->
transport
(λ i → (sym (LiftBB'.unfold-≾)) i
(sym (unfold-ext f) i (lx~ t))
(sym (unfold-ext f') i (ly~ t)))
(IH t (lx~ t) (ly~ t)
(transport (λ i -> LiftAA'.unfold-≾ i (lx~ t) (ly~ t)) (la≤la' t)))
-- ext respects monotonicity (in the usual homogeneous sense)
-- This can be rewritten to reuse the above result!
ext-monotone : {A B : Predomain} ->
(f f' : ⟨ A ⟩ -> ⟨ (𝕃 B) ⟩) ->
fun-order A (𝕃 B) f f' ->
(la la' : ⟨ 𝕃 A ⟩) ->
rel (𝕃 A) la la' ->
rel (𝕃 B) (ext f la) (ext f' la')
ext-monotone {A} {B} f f' f≤f' la la' la≤la' =
let fixed = fix (monotone-ext' f f' f≤f') in
transport
(sym (λ i -> unfold-≾ B i (unfold-ext f i la) (unfold-ext f' i la')))
(fixed la la' (transport (λ i → unfold-≾ A i la la') la≤la'))
where
-- bring the homogeneous lifted relations into scope
_≾LA_ = LiftPredomain._≾_ A
_≾LB_ = LiftPredomain._≾_ B
-- Note that these next two have already been
-- passed (next _≾_) as a parameter (this happened in
-- the defintion of the module 𝕃, where we said
-- open Inductive (next _≾_) public)
_≾'LA_ = LiftPredomain._≾'_ A
_≾'LB_ = LiftPredomain._≾'_ B
monotone-ext' :
(f f' : ⟨ A ⟩ -> ⟨ (𝕃 B) ⟩) ->
(fun-order A (𝕃 B) f f') ->
▹ (
(la la' : ⟨ 𝕃 A ⟩) ->
la ≾'LA la' ->
(ext' f (next (ext f)) la) ≾'LB
(ext' f' (next (ext f')) la')) ->
(la la' : ⟨ 𝕃 A ⟩) ->
la ≾'LA la' ->
(ext' f (next (ext f)) la) ≾'LB
(ext' f' (next (ext f')) la')
monotone-ext' f f' f≤f' IH (η x) (η y) x≤y =
transport
(λ i → unfold-≾ B i (f x) (f' y))
(f≤f' x y x≤y)
monotone-ext' f f' f≤f' IH ℧ la' la≤la' = tt
monotone-ext' f f' f≤f' IH (θ lx~) (θ ly~) la≤la' = λ t ->
transport
(λ i → (sym (unfold-≾ B)) i
(sym (unfold-ext f) i (lx~ t))
(sym (unfold-ext f') i (ly~ t)))
(IH t (lx~ t) (ly~ t)
(transport (λ i -> unfold-≾ A i (lx~ t) (ly~ t)) (la≤la' t)))
{-
ext-monotone' : {A B : Predomain} ->
{la la' : ⟨ 𝕃 A ⟩} ->
(f f' : ⟨ A ⟩ -> ⟨ (𝕃 B) ⟩) ->
rel (𝕃 A) la la' ->
fun-order A (𝕃 B) f f' ->
rel (𝕃 B) (ext f la) (ext f' la')
ext-monotone' {A} {B} {la} {la'} f f' la≤la' f≤f' =
let fixed = fix (monotone-ext' f f' f≤f') in
--transport
--(sym (λ i -> ord B (unfold-ext f i la) (unfold-ext f' i la')))
(fixed la la' (transport (λ i → unfold-ord A i la la') la≤la'))
where
monotone-ext' :
(f f' : ⟨ A ⟩ -> ⟨ (𝕃 B) ⟩) ->
(fun-order A (𝕃 B) f f') ->
▹ (
(la la' : ⟨ 𝕃 A ⟩) ->
ord' A (next (ord A)) la la' ->
ord B
(ext f la)
(ext f' la')) ->
(la la' : ⟨ 𝕃 A ⟩) ->
ord' A (next (ord A)) la la' ->
ord B
(ext f la)
(ext f' la')
monotone-ext' f f' f≤f' IH (η x) (η y) x≤y = {!!} -- (f≤f' x y x≤y)
monotone-ext' f f' f≤f' IH ℧ la' la≤la' = transport (sym (λ i -> unfold-ord B i (ext f ℧) (ext f' la'))) {!!}
-- transport (sym (λ i → unfold-ord B i (ext' f (next (ext f)) ℧) (ext' f' (next (ext f')) la'))) tt
monotone-ext' f f' f≤f' IH (θ lx~) (θ ly~) la≤la' = {!!} -- λ t -> ?
-}
bind-monotone : {A B : Predomain} ->
{la la' : ⟨ 𝕃 A ⟩} ->
(f f' : ⟨ A ⟩ -> ⟨ (𝕃 B) ⟩) ->
rel (𝕃 A) la la' ->
fun-order A (𝕃 B) f f' ->
rel (𝕃 B) (bind la f) (bind la' f')
bind-monotone {A} {B} {la} {la'} f f' la≤la' f≤f' =
ext-monotone f f' f≤f' la la' la≤la'
mapL-monotone-het : {A A' B B' : Predomain} ->
(rAA' : ⟨ A ⟩ -> ⟨ A' ⟩ -> Type) -> (rBB' : ⟨ B ⟩ -> ⟨ B' ⟩ -> Type) ->
(f : ⟨ A ⟩ -> ⟨ B ⟩) -> (f' : ⟨ A' ⟩ -> ⟨ B' ⟩) ->
fun-order-het A A' B B' rAA' rBB' f f' ->
(la : ⟨ 𝕃 A ⟩) -> (la' : ⟨ 𝕃 A' ⟩) ->
(LiftRelation._≾_ A A' rAA' la la') ->
LiftRelation._≾_ B B' rBB' (mapL f la) (mapL f' la')
mapL-monotone-het {A} {A'} {B} {B'} rAA' rBB' f f' f≤f' la la' la≤la' =
ext-monotone-het rAA' rBB' (ret ∘ f) (ret ∘ f')
(λ a a' a≤a' → LiftRelation.Properties.ord-η-monotone B B' rBB' (f≤f' a a' a≤a'))
la la' la≤la'
-- This is a special case of the above
mapL-monotone : {A B : Predomain} ->
{la la' : ⟨ 𝕃 A ⟩} ->
(f f' : ⟨ A ⟩ -> ⟨ B ⟩) ->
rel (𝕃 A) la la' ->
fun-order A B f f' ->
rel (𝕃 B) (mapL f la) (mapL f' la')
mapL-monotone {A} {B} {la} {la'} f f' la≤la' f≤f' =
bind-monotone (ret ∘ f) (ret ∘ f') la≤la'
(λ a1 a2 a1≤a2 → ord-η-monotone B (f≤f' a1 a2 a1≤a2))
-- As a corollary/special case, we can consider the case of a single
-- monotone function.
monotone-bind-mon : {A B : Predomain} ->
{la la' : ⟨ 𝕃 A ⟩} ->
(f : MonFun A (𝕃 B)) ->
(rel (𝕃 A) la la') ->
rel (𝕃 B) (bind la (MonFun.f f)) (bind la' (MonFun.f f))
monotone-bind-mon f la≤la' =
bind-monotone (MonFun.f f) (MonFun.f f) la≤la' (mon-fun-order-refl f)
{-
-- bind respects monotonicity
monotone-bind : {A B : Predomain} ->
{la la' : ⟨ 𝕃 A ⟩} ->
(f f' : MonFun A (𝕃 B)) ->
rel (𝕃 A) la la' ->
rel (arr' A (𝕃 B)) f f' ->
rel (𝕃 B) (bind la (MonFun.f f)) (bind la' (MonFun.f f'))
monotone-bind {A} {B} {la} {la'} f f' la≤la' f≤f' =
{!!}
where
monotone-ext' :
(f f' : MonFun A (𝕃 B)) ->
(rel (arr' A (𝕃 B)) f f') ->
▹ (
(la la' : ⟨ 𝕃 A ⟩) ->
ord' A (next (ord A)) la la' ->
ord' B (next (ord B))
(ext' (MonFun.f f) (next (ext (MonFun.f f))) la)
(ext' (MonFun.f f') (next (ext (MonFun.f f'))) la')) ->
(la la' : ⟨ 𝕃 A ⟩) ->
ord' A (next (ord A)) la la' ->
ord' B (next (ord B))
(ext' (MonFun.f f) (next (ext (MonFun.f f))) la)
(ext' (MonFun.f f') (next (ext (MonFun.f f'))) la')
monotone-ext' f f' f≤f' IH (η x) (η y) x≤y =
transport
(λ i → unfold-ord B i (MonFun.f f x) (MonFun.f f' y))
(f≤f' x y x≤y)
monotone-ext' f f' f≤f' IH ℧ la' la≤la' = tt
monotone-ext' f f' f≤f' IH (θ lx~) (θ ly~) la≤la' = λ t ->
transport
(λ i → (sym (unfold-ord B)) i
(sym (unfold-ext (MonFun.f f)) i (lx~ t))
(sym (unfold-ext (MonFun.f f')) i (ly~ t)))
--(ext (MonFun.f f) (lx~ t))
--(ext (MonFun.f f') (ly~ t)))
(IH t (lx~ t) (ly~ t)
(transport (λ i -> unfold-ord A i (lx~ t) (ly~ t)) (la≤la' t)))
-- (IH t (θ lx~) {!θ ly~!} la≤la')
-}
-- unfold-ord : ord ≡ ord' (next ord)
-- For the η case:
-- Goal:
-- ord' B (λ _ → fix (ord' B)) (MonFun.f f x) (MonFun.f f' y)
-- Know: (x₁ y₁ : fst A) →
-- rel A x₁ y₁ →
-- fix (ord' B) (MonFun.f f x₁) (MonFun.f f' y₁)
-- For the θ case:
-- Goal:
-- ord B
-- ext (MonFun.f f)) (lx~ t)
-- ext (MonFun.f f')) (ly~ t)
-- Know: IH : ...
-- la≤la' : (t₁ : Tick k) → fix (ord' A) (lx~ t₁) (ly~ t₁)
-- The IH is in terms of ord' (i.e., ord' A (next (ord A)) la la')
-- but the assumption la ≤ la' in the θ case is equivalent to
-- (t₁ : Tick k) → fix (ord' A) (lx~ t₁) (ly~ t₁)