{-# OPTIONS --cubical --erasure --guardedness  #-}

module BrouwerTree.OrdinalDecidability.LPOMinMax where

open import Cubical.Data.Nat
  using (; zero; suc)
  renaming (_+_ to _N+_)
import Cubical.Data.Nat.Order as N
import Cubical.Data.Nat.Properties as N
open import Cubical.Data.Sigma hiding (; ∃-syntax)
open import Cubical.Data.Sum renaming (rec to sumrec ; map to summap)
open import Cubical.Data.Empty as 
open import Cubical.Relation.Nullary using (Dec; yes; no)
open import Cubical.Relation.Nullary.Base
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.HLevels
open import Cubical.Foundations.Function

open import General-Properties

open import Bool as B
open import BooleanSequence

open import PropTrunc
open import Iff

open import BrouwerTree.Everything
open import BrouwerTree.OrdinalDecidability.Basic

---------------------------LPO Results: --------------------------


-------1-LPO Result on Min Function for Brw:

BoolSeq→BrwSeq : (  Bool)  Σ[ f  (  Brw) ] increasing f
BoolSeq→BrwSeq s  = f , f↑
   where
     f :   Brw
     f zero = zero
     f (suc n) with s n  true
     ... | yes sn=true = f n + ω
     ... | no sn=false = f n + ι 1
     f↑ : increasing f
     f↑ k  with s k  true
     ... | yes _ = ≤-cocone  n  f k + ι n) {_} {1} ≤-refl
     ... | no _ = ≤-refl

¬∃xPx→∀x¬Px : (s :   Bool)  ¬ (∃[ n   ] s n  true)  (k : )  s k  false
¬∃xPx→∀x¬Px s p k with  s k  true
... | yes v = ⊥.rec (p  k , v )
... | no u = sumrec  u'  ⊥.rec (u u'))  x  x) (dichotomyBool (s k))

Brw-Min : (x y : Brw)  Type
Brw-Min x y = Σ[ m  Brw ] ((α : Brw)  ((α  x) × (α  y))  α  m)

LPO-isProp : (s :   Bool)
            isProp (((k : )  s k  false)  (∃[ n   ] s n  true))
LPO-isProp s = isProp⊎ (isPropΠ  k  isSetBool (s k) false))
                       isPropPropTrunc
                        H  ∥-∥rec  ()) (F H))
 where
  F : ((x : )  s x  false)  ¬ (Σ[ n   ] s n  true)
  F h (k , hk) = true≢false (sym hk  h k)

Brw-Min→LPO : (∀ (x y : Brw)  Brw-Min x y)  LPO
Brw-Min→LPO min s = fun (fst (min x y)) (snd (min x y))
  where
   y = succ ω
   f = fst (BoolSeq→BrwSeq s)
   f↑ = snd (BoolSeq→BrwSeq s)
   x = limit f {f↑}
   M : Brw
   M = fst (min x y)
   fun : (m : Brw)
          (∀ (α : Brw)  ((α  x) × (α  y))  α  m)
          ((k : )  s k  false)  (∃[ n   ]  s n  true)
   fun = Brw-ind P P-prop P₀ Pₛ Pₗ
    where
     P : Brw  Type
     P m = (∀ (α : Brw)  ((α  x) × (α  y))  α  m)
          ((k : )  s k  false)  (∃[ n   ] s n  true)
     P-prop : (m : Brw)  isProp (P m)
     P-prop m = isProp→ (LPO-isProp s)
     P₀ : P zero
     P₀ hm = ⊥.rec (lim≰zero falsity)
      where
       falsity : ω  zero
       falsity = fst (hm ω) ((ω-smallest f) , <-in-≤ ≤-refl)
     Pₛ : {m : Brw}  P m  P (succ m)
     Pₛ {m} e hsm = summap fun1 fun2 (<ω-or-≥ω  m)
      where
       fun2 : ω  m  ∃[ n   ] s n  true
       fun2 ω≤m = ∥-∥rec isPropPropTrunc F2 (below-limit-lemma ω f v1)
         where
          v1 : ω < limit f {f↑}
          v1 = <∘≤-in-< (≤-succ-mono ω≤m) (fst (snd (hsm (succ m)) ≤-refl))
          F1 : Σ[ n   ] ω < f n  Σ[ n   ] ω  f n
          F1 (n , hn) = n , <-in-≤ hn
          F : Σ[ n   ] ω  f n  ∃[ n   ] s n  true
          F2 : Σ[ n   ] ω < f n  ∃[ n   ] s n  true
          F2 = F  F1
          F (n , b) = H w
           where
            H : ∃[ k   ] (k N.≤ n) × (s k  true)  ∃[ n   ] s n  true
            H = ∥-∥map  (k , _ , e)  k , e)
            w : ∃[ k   ] (k N.≤ n) × (s k  true)
            w = lemma n b
             where
              lemma : (n : )  ω  f n  ∃[ k   ] (k N.≤ n) × (s k  true)
              lemma zero ω≤fn = ⊥.elim (lim≰zero ω≤fn)
              lemma (suc n) ω≤fn with dec-true-below n s
              ... | yes (k , l , e) =  k , N.≤-suc l , e 
              ... | no v' = ∥-∥map  (k , l , e)  k , N.≤-suc l , e)
                            (lemma n [3])
               where
                [1] : s n  false
                [1] = ¬true→false (s n)(λ (e : s n  true)  v'(n , N.≤-refl , e))
                [2] : ω  succ (f n)
                [2] = subst (ω ≤_) (f-eq₂ n [1]) ω≤fn
                  where
                    f-eq₂ : (n : )  s n  false  f (suc n)  succ (f n)
                    f-eq₂ n e with s n  true
                    ... | yes e' = ⊥.elim {_}  _  f n + ω  succ (f n)}
                                   (true≢false (sym e'  e))
                    ... | no _ = refl
                [3] : ω  f n
                [3] = lim≤sx→lim≤x ι (f n) [2]

       fun1 : m < ω  (k : )  s k  false
       fun1 m<ω = ⊥.rec ((<-irreflexive ω) fls)
        where
         t1 : ω  succ m
         t1 = fst (hsm ω) ((ω-smallest f) ,  <-in-≤ ≤-refl)
         t2 : ω  m
         t2 = lim≤sx→lim≤x ι m t1
         fls : succ ω  ω
         fls = ≤-trans (≤-succ-mono t2) m<ω
     Pₗ : {g :   Brw} {g↑ : increasing g}
         ((k : )  P (g k))  P (limit g {g↑})
     Pₗ {g} {g↑} q hg = inl (¬∃xPx→∀x¬Px s  H  ∥-∥rec  ()) fun5 H))
      where
       fun3 :  Σ[ n   ] (s n  true)  succ ω  limit f {f↑}
       fun4 :  Σ[ n   ] (s n  true)  succ ω   limit g {g↑}
       fun4 pn = ≤-antisym
                (fst (hg y) (fun3 pn , ≤-refl))
                (snd (snd (hg (limit g)) ≤-refl))
       fun5 :  Σ[ n   ] (s n  true)  
       fun5 p = succ≠lim (fun4 p)
       fun3 h = W h
        where
          W :  Σ[ n   ] s n  true  succ ω  limit f {f↑}
          W (n₀ , sn0=t ) = ≤-cocone f {k = suc(n₀ N+ 1)}
            (≤-trans (≤-succ-mono v) (add-finite-part-lemma' f {f↑} (suc n₀) 1))
           where
             v : ω  f (suc n₀)
             v with s n₀  true
             ... | yes z = ω-smallest  n  f (n₀) + ι n)
             ... | no  z' = ⊥.rec (z' sn0=t)
             V : Σ[ n   ] ω  f n
             V = (suc n₀) , v

------------------------------------------------------
----------2-LPO Result on Max function for Brwᶻˡ:

BoolSeq→BrwSeq2 : (  Bool)  Σ[ f  (  Brw) ] (increasing f)
BoolSeq→BrwSeq2 s  = f , f↑
   where
     f :   Brw
     f zero = zero
     f (suc n) with s n  true
     ... | yes sn=true = f n + (ω + ω)
     ... | no sn=false = f n + ι 1

     f↑ : increasing f
     f↑ k  with s k  true
     ... | yes _ = ≤-cocone  n  f k + (ω + ι n)) {_} {1}
                  (≤-succ-mono (≤-cocone {x = f k}  n  f k + ι n)
                  {k = zero} (x+-increasing {x = f k} zero)))
     ... | no _ = ≤-refl

Brwᶻˡ-Max : (x y : Brwᶻˡ)  Type
Brwᶻˡ-Max (x , _) (y , _)  =
 Σ[ m  Brw ]  (α : Brw)  ((α  x)  (α  y) )  (α  m )

Brwᶻˡ-Connex : (x y : Brwᶻˡ)  Type
Brwᶻˡ-Connex x y  = (fst x  fst y)  (fst y  fst x)

Brwᶻˡ-Max→Brwᶻˡ-Connex : (x y : Brwᶻˡ)
                        Brwᶻˡ-Max x y
                        Brwᶻˡ-Connex x y
Brwᶻˡ-Max→Brwᶻˡ-Connex x y max = sumrec
                        p  inr (≤-trans t2 p))
                        q  inl (≤-trans t1 q))
                       t3
  where
   xx = fst x
   yy = fst y
   mxy = fst max
   t1 : xx  mxy
   t1 = lr (snd max xx) (inl ≤-refl)
   t2 : yy  mxy
   t2 = lr (snd max yy) (inr ≤-refl)
   t3 : (mxy  xx)  (mxy  yy)
   t3 = rl (snd max mxy) ≤-refl

Brwᶻˡ-Connex→LPO : (∀ (x y : Brwᶻˡ)  Brwᶻˡ-Connex x y)  LPO
Brwᶻˡ-Connex→LPO cnvx s = sumrec  p  inl (Hl p))
                                  q  inr (Hr q)) H
  where
   f = fst (BoolSeq→BrwSeq2 s)
   f↑ = snd (BoolSeq→BrwSeq2 s)
   ω2 : Brwᶻˡ
   ω2 = (ω + ω) , inl ω+ω-islim
   ff : Brwᶻˡ
   ff = limit f {f↑} , inl   (f , f↑) , limit-is-sup f f↑  
   H : (limit f {f↑}  ω + ω)  (ω + ω  limit f {f↑})
   H = cnvx ff ω2
   Hl : limit f {f↑}  ω + ω   k  s k  false
   Hl p = ¬∃xPx→∀x¬Px s (∥-∥rec  ()) [1])
    where
     [1] : ¬ (Σ[ n   ] s n  true)
     [1] (m , hm) = <-irreflexive (limit f {f↑}) (≤∘<-in-< p [3])
      where
       f-eq₁ : (n : )  s n  true  f (suc n)  f n + (ω + ω)
       f-eq₁ n e with s n  true
       ... | yes _ = refl
       ... | no  ν = ⊥.elim {_}  _  succ (f n)  f n + (ω + ω)} (ν e)
       [2] : ω + ω  f (suc m)
       [2] = ≤-trans (+x-increasing (ω + ω)) (≤-refl-≡ (sym (f-eq₁ m hm)))
       [3] : ω + ω < limit f {f↑}
       [3] = ≤-cocone f {k = suc (m N+ 1)} (≤-trans (≤-succ-mono [2])
            (add-finite-part-lemma' f {f↑} (suc m) 1))
   Hr : ω + ω  limit f {f↑}  ∃[ n   ] s n  true
   Hr p = [5] [2]
    where
     [1] :  n  ω + ι n)  f
     [1] = lim≤lim→weakly-bisimilar  n  ω + ι n) f p
     [2] : ∃[ n   ] ω  f n
     [2] = [1] zero
     [3] : (n : )   ω  f n  Σ[ m   ] s m  true
     [3] zero p = ⊥.rec (lim≰zero p)
     [3] (suc n) p with s n  true
     ... | yes v = n , v
     ... | no u = [3] n [4]
      where
        [4] : ω  f n
        [4] = lim≤sx→lim≤x ι (f n) p
     [5] : ∃[ n   ] ω  f n  ∃[ m   ] s m  true
     [5] = ∥-∥rec isPropPropTrunc  (m , hm)   [3] m hm )

Brwᶻˡ-Max→LPO : (∀ (x y : Brwᶻˡ)  Brwᶻˡ-Max x y)  LPO
Brwᶻˡ-Max→LPO max = Brwᶻˡ-Connex→LPO  x y  Brwᶻˡ-Max→Brwᶻˡ-Connex x y (max x y))

------