\import Function.Meta
\import Logic
\import Logic.Meta
\import Order.Lattice
\import Order.PartialOrder
\import Paths.Meta
\import Set.Subset
\open Bounded(top,bottom)
\class RatherBelow {A : Bounded.MeetSemilattice} (R : A -> A -> \Prop) {
| <=<-left {U V W : A} : R U V -> V <= W -> R U W
| <=<-right {U V W : A} : U <= V -> R V W -> R U W
| <=<_top {V : A} : R V top
| <=<_meet {U V U' V' : A} : R U V -> R U' V' -> R (U ∧ U') (V ∧ V')
\lemma <=<_meet-same {U V V' : A} (p : R U V) (q : R U V') : R U (V ∧ V')
=> <=<-right (meet-univ <=-refl <=-refl) (<=<_meet p q)
\type \infix 4 <=<o (V U : A) : \Prop
=> ∃ (R' : A -> A -> \Prop) (\Pi {V U : A} -> R' V U -> R V U) (\Pi {V U : A} -> R' V U -> ∃ (W : A) (R' V W) (R W U)) (R' V U)
\lemma <=<o_<=< {V U : A} (p : V <=<o U) : R V U \elim p
| inP (R,p,q,r) => p r
\lemma <=<o-inter {V U : A} (p : V <=<o U) : ∃ (W : A) (V <=<o W) (R W U) \elim p
| inP (R,p,q,RVU) => \case q RVU \with {
| inP (W,RVW,W<=<U) => inP (W, inP (R, p, q, RVW), W<=<U)
}
\func Omega : RatherBelow {A} \cowith
| R => <=<o
| <=<_top => inP (\lam V U => U = top, \lam p => rewrite p <=<_top, \lam p => inP (top, idp, rewrite p <=<_top), idp)
| <=<-left {W} {V} {U} p V<=U => \case \elim p \with {
| inP (R,p,q,RWV) => inP (\lam V U => ∃ (U' : A) (R V U') (U' <= U), \lam (inP (U',RVU',U'<=U)) => <=<-left (p RVU') U'<=U, \lam (inP (U',RVU',U'<=U)) => \case q RVU' \with {
| inP (W,RVW,W<=<U') => inP (W, inP (W, RVW, <=-refl), <=<-left W<=<U' U'<=U)
}, inP (V, RWV, V<=U))
}
| <=<-right {W} {V} {U} W<=V => \case __ \with {
| inP (R,p,q,RVU) => inP (\lam V U => ∃ (V' : A) (R V' U) (V <= V'), \lam (inP (V',RV'U,V<=V')) => <=<-right V<=V' (p RV'U), \lam (inP (V',RV'U,V<=V')) => \case q RV'U \with {
| inP (W,RV'W,W<=<U) => inP (W, inP (V', RV'W, V<=V'), W<=<U)
}, inP (V, RVU, W<=V))
}
| <=<_meet {V1} {U1} {V2} {U2} => \case __, __ \with {
| inP (R,p,q,RV1U1), inP (R',p',q',R'V2U2) => inP
(\lam V U => ∃ (V1 V2 U1 U2 : A) (R V1 U1) (R' V2 U2) (V = V1 ∧ V2) (U = U1 ∧ U2),
\lam (inP (V1,V2,U1,U2,RV1U1,R'V2U2,Vp,Up)) => rewrite (Vp,Up) $ <=<_meet (p RV1U1) (p' R'V2U2),
\lam (inP (V1,V2,U1,U2,RV1U1,R'V2U2,Vp,Up)) => \case q RV1U1, q' R'V2U2 \with {
| inP (W1,RV1W1,W1<=<U1), inP (W2,R'V2W2,W2<=<U2) => inP (W1 ∧ W2, inP (V1, V2, W1, W2, RV1W1, R'V2W2, Vp, idp), rewrite Up $ <=<_meet W1<=<U1 W2<=<U2)
},
inP (V1, V2, U1, U2, RV1U1, R'V2U2, idp, idp))
}
\type \infix 4 <=<c (V U : A) : \Prop
=> ∃ (R' : A -> A -> \Prop) (\Pi {V U : A} -> R' V U -> R V U) (\Pi {V U : A} -> R' V U -> ∃ (W : A) (R' V W) (R' W U)) (R' V U)
\lemma <=<c_<=<o {V U : A} (p : V <=<c U) : V <=<o U \elim p
| inP (R,p,q,r) => inP (R, p, \lam r => TruncP.map (q r) \lam (W,RVW,RWU) => (W, RVW, p RWU), r)
\lemma <=<c_<=< {V U : A} (p : V <=<c U) : R V U
=> <=<o_<=< (<=<c_<=<o p)
\lemma <=<c-inter {V U : A} (p : V <=<c U) : ∃ (W : A) (V <=<c W) (W <=<c U) \elim p
| inP (R,p,q,RVU) => \case q RVU \with {
| inP (W,RVW,RWU) => inP (W, inP (R, p, q, RVW), inP (R, p, q, RWU))
}
\lemma <=<c-func {R2 : RatherBelow {A}} (p : \Pi {V U : A} -> R V U -> R2 V U) {V U : A} (q : V <=<c U) : V R2.<=<c U \elim q
| inP (R',f,g,r) => inP (R', \lam r => p (f r), g, r)
\func Interpolative : RatherBelow {A} \cowith
| R => <=<c
| <=<_top => inP (\lam V U => U = {A} top, \lam p => rewrite p <=<_top, \lam p => inP (top, idp, p), idp)
| <=<-left {W} {V} {U} p V<=U => \case \elim p \with {
| inP (R,p,q,RWV) => inP (\lam V U => ∃ (U' : A) (R V U') (U' <= U), \lam (inP (U',RVU',U'<=U)) => <=<-left (p RVU') U'<=U, \lam (inP (U',RVU',U'<=U)) => \case q RVU' \with {
| inP (W,RVW,RWU') => inP (W, inP (W, RVW, <=-refl), inP (U', RWU', U'<=U))
}, inP (V, RWV, V<=U))
}
| <=<-right {W} {V} {U} W<=V => \case __ \with {
| inP (R,p,q,RVU) => inP (\lam V U => ∃ (V' : A) (R V' U) (V <= V'), \lam (inP (V',RV'U,V<=V')) => <=<-right V<=V' (p RV'U), \lam (inP (V',RV'U,V<=V')) => \case q RV'U \with {
| inP (W,RV'W,RWU) => inP (W, inP (V', RV'W, V<=V'), inP (W, RWU, <=-refl))
}, inP (V, RVU, W<=V))
}
| <=<_meet {V1} {U1} {V2} {U2} => \case __, __ \with {
| inP (R,p,q,RV1U1), inP (R',p',q',R'V2U2) => inP
(\lam V U => ∃ (V1 V2 U1 U2 : A) (R V1 U1) (R' V2 U2) (V = V1 ∧ V2) (U = U1 ∧ U2),
\lam (inP (V1,V2,U1,U2,RV1U1,R'V2U2,Vp,Up)) => rewrite (Vp,Up) $ <=<_meet (p RV1U1) (p' R'V2U2),
\lam (inP (V1,V2,U1,U2,RV1U1,R'V2U2,Vp,Up)) => \case q RV1U1, q' R'V2U2 \with {
| inP (W1,RV1W1,RW1U1), inP (W2,R'V2W2,R'W2U2) => inP (W1 ∧ W2, inP (V1, V2, W1, W2, RV1W1, R'V2W2, Vp, idp), inP (W1, W2, U1, U2, RW1U1, R'W2U2, idp, Up))
},
inP (V1, V2, U1, U2, RV1U1, R'V2U2, idp, idp))
}
} \where {
\lemma <=<c_bottom {A : CompleteLattice} {R : RatherBelow {A}} (p : \Pi {U : A} -> R bottom U) {U : A} : bottom R.<=<c U
=> inP (\lam V _ => V = bottom, \lam q => rewrite q p, \lam q => inP (bottom, q, idp), idp)
}
\lemma <=<c_^-1 {X Y : \Set} {RX : RatherBelow {SetLattice X}} {RY : RatherBelow {SetLattice Y}} {f : X -> Y} (<=<_^-1 : \Pi {U V : Set Y} -> RY U V -> RX (f ^-1 U) (f ^-1 V)) {U V : Set Y} (p : U RY.<=<c V) : f ^-1 U RX.<=<c f ^-1 V \elim p
| inP (R',g,h,r) => inP (\lam U V => ∃ (U' V' : R') (U = f ^-1 U') (V = f ^-1 V'), \lam (inP (U',V',R'U'V',p,q)) => rewrite (p,q) $ <=<_^-1 $ g R'U'V', \lam (inP (U',V',R'U'V',p,q)) => \case h R'U'V' \with {
| inP (W,R'U'W,R'WV') => inP (f ^-1 W, inP (U', W, R'U'W, p, idp), inP (W, V', R'WV', idp, q))
}, inP (U, V, r, idp, idp))