{-# OPTIONS --cubical --no-import-sorts --safe #-} module Cubical.Data.Nat.Lower where open import Cubical.Foundations.Equiv open import Cubical.Foundations.Function open import Cubical.Foundations.HLevels open import Cubical.Foundations.Isomorphism open import Cubical.Foundations.Prelude open import Cubical.Foundations.Path open import Cubical.Foundations.Transport open import Cubical.Data.Bool open import Cubical.Data.Empty as Empty open import Cubical.Data.Nat.Base open import Cubical.Data.Nat.Properties open import Cubical.Data.Sigma open import Cubical.Data.Sum open import Cubical.Data.Unit open import Cubical.Relation.Nullary isMonotone : (ℕ → Bool) → Type isMonotone f = ∀ n → f n ≥ f (suc n) isPropIsMonotone : ∀ f → isProp (isMonotone f) isPropIsMonotone f = isPropΠ λ n → isProp≥ (f n) (f (suc n)) isPropDepIsMonotone : isPropDep isMonotone isPropDepIsMonotone = isOfHLevel→isOfHLevelDep 1 isPropIsMonotone {_} Monotone : Type Monotone = Σ _ isMonotone isSetMonotone : isSet Monotone isSetMonotone = isSetΣ (isSet→ isSetBool) (isProp→isSet ∘ isPropIsMonotone) private variable ℓ : Level m n : Monotone private mz : ℕ → Bool mz _ = false ms : (ℕ → Bool) → (ℕ → Bool) ms _ zero = true ms f (suc m) = f m msm : ∀{f} → isMonotone f → isMonotone (ms f) msm _ zero = _ msm mf (suc m) = mf m mp : (ℕ → Bool) → (ℕ → Bool) mp f k = f (suc k) ms-mp : ∀ f → f 0 ≡ true → ms (mp f) ≡ f ms-mp f p i 0 = p (~ i) ms-mp f p i (suc k) = f (suc k) mz-lemma : ∀ f → isMonotone f → f 0 ≡ false → ∀ k → false ≡ f k mz-lemma f _ p zero = sym p mz-lemma f mf p (suc k) with f 1 | inspect f 1 | subst (_≥ f 1) p (mf 0) ... | false | [ q ]ᵢ | _ = mz-lemma (mp f) (mf ∘ suc) q k msuc : Monotone → Monotone msuc m .fst = ms (fst m) msuc m .snd = msm (snd m) mpred : Monotone → Monotone mpred f .fst k = f .fst (suc k) mpred f .snd k = f .snd (suc k) data MView : (ℕ → Bool) → Type where mzv : MView mz msv : ∀ n → MView (ms n) mview : ∀ f → isMonotone f → MView f mview f mf with f 0 | inspect f 0 ... | true | [ p ]ᵢ = subst MView (ms-mp f p) (msv (mp f)) ... | false | [ p ]ᵢ = subst MView (funExt (mz-lemma f mf p)) mzv ∞ : Monotone ∞ .fst _ = true ∞ .snd _ = _ Detached : (ℕ → Bool) → Type Detached p = Σ[ n ∈ ℕ ] Bool→Type (p n) Lower : Monotone → Type Lower m = Detached (fst m) Detached-ext : ∀{p : ℕ → Bool} (k l : Detached p) → k .fst ≡ l .fst → k ≡ l Detached-ext {p} (k , q) (l , r) s = ΣPathP (s , isPropDep∘ p isPropDep-Bool→Type q r s) Lower∞≃ℕ : Lower ∞ ≃ ℕ Lower∞≃ℕ = isoToEquiv λ where .fun → fst .inv n → n , _ .rightInv _ → refl .leftInv _ → refl where open Iso private apart : ℕ → ℕ → Type apart zero zero = ⊥ apart (suc m) (suc n) = apart m n apart _ _ = Unit ≢→apart : (i j : ℕ) → ¬ i ≡ j → apart i j ≢→apart zero zero ¬p = ¬p refl ≢→apart (suc i) (suc j) ¬p = ≢→apart i j (¬p ∘ cong suc) ≢→apart zero (suc _) _ = _ ≢→apart (suc _) zero _ = _ apart→≢ : (i j : ℕ) → apart i j → ¬ i ≡ j apart→≢ (suc _) zero _ = snotz apart→≢ zero (suc _) _ = znots apart→≢ (suc i) (suc j) i#j = apart→≢ i j i#j ∘ cong predℕ isPropApart : ∀ i j → isProp (apart i j) isPropApart 0 0 = isProp⊥ isPropApart (suc i) (suc j) = isPropApart i j isPropApart 0 (suc _) = isPropUnit isPropApart (suc _) 0 = isPropUnit _#_ : ∀{P : ℕ → Type ℓ} → Σ ℕ P → Σ ℕ P → Type u # v = apart (fst u) (fst v) _#?_ : ∀{P : ℕ → Type ℓ} → (u v : Σ ℕ P) → (u # v) ⊎ (fst u ≡ fst v) u #? v = decide (fst u) (fst v) where decide : (m n : ℕ) → apart m n ⊎ (m ≡ n) decide zero zero = inr refl decide zero (suc _) = inl _ decide (suc _) zero = inl _ decide (suc m) (suc n) = map (idfun _) (cong suc) (decide m n) #→≢ : ∀{P : ℕ → Type ℓ} (u v : Σ ℕ P) → u # v → ¬ u ≡ v #→≢ u v d = apart→≢ (fst u) (fst v) d ∘ cong fst isProp# : ∀{P : ℕ → Type ℓ} (u v : Σ ℕ P) → isProp (u # v) isProp# u v = isPropApart (fst u) (fst v) isProp#Depᵣ : ∀{P : ℕ → Type ℓ} (v : Σ ℕ P) → isPropDep (λ u → u # v) isProp#Depᵣ v = isOfHLevel→isOfHLevelDep 1 (λ u → isProp# u v) {_} {_} ≢→# : ∀{p} (u v : Detached p) → ¬ u ≡ v → u # v ≢→# u v ¬p = ≢→apart (fst u) (fst v) (¬p ∘ Detached-ext u v) dzero : ∀{f} → Detached (ms f) dzero = zero , _ dsuc : ∀{f} → Detached f → Detached (ms f) dsuc (l , p) = suc l , p module Untangle {α β} (f : Detached (ms α) → Detached (ms β)) (g : Detached (ms β) → Detached (ms α)) (rinv : section f g) (linv : retract f g) where default : ∀{γ} → (v d : Detached (ms γ)) → v # d → Detached γ default (suc l , p) _ _ = l , p default (0 , _) (suc l , p) _ = l , p #-f : ∀ u v → u # v → f u # f v #-f u v u#v with f u #? f v ... | inl fu#fv = fu#fv ... | inr fu≡fv = Empty.rec (#→≢ u v u#v u≡v) where u≡v : u ≡ v u≡v = sym (linv u) ∙∙ cong g (Detached-ext (f u) (f v) fu≡fv) ∙∙ linv v #-g : ∀ u v → u # v → g u # g v #-g u v u#v with g u #? g v ... | inl gu#gv = gu#gv ... | inr gu≡gv = Empty.rec (#→≢ u v u#v u≡v) where u≡v : u ≡ v u≡v = sym (rinv u) ∙∙ cong f (Detached-ext (g u) (g v) gu≡gv) ∙∙ rinv v f- : Detached α → Detached β f- v = default (f (dsuc v)) (f dzero) (#-f (dsuc v) dzero _) g- : Detached β → Detached α g- v = default (g (dsuc v)) (g dzero) (#-g (dsuc v) dzero _) g-f-z : ∀ v u → g dzero ≡ dsuc v → g (dsuc u) ≡ dzero → g- u ≡ v g-f-z v u r s with g (dsuc u) | g dzero | #-g (dsuc u) dzero _ ... | zero , _ | suc k , q | #gf = Detached-ext (k , q) v (cong (predℕ ∘ fst) r) ... | w@(suc k , _) | _ | #gf = Empty.rec (snotz (cong fst s)) g-f-s : ∀ v u → g (dsuc u) ≡ dsuc v → g- u ≡ v g-f-s v u r with g (dsuc u) | #-g (dsuc u) dzero _ ... | suc k , q | #gf = Detached-ext (k , q) v (cong (predℕ ∘ fst) r) ... | zero , _ | #gf = Empty.rec (znots (cong fst r)) g-f- : ∀(v : Detached α) → g- (f- v) ≡ v g-f- v with f (dsuc v) | linv (dsuc v) | #-f (dsuc v) dzero _ g-f- v | suc j , p | r | #f = g-f-s v (j , p) r ... | zero , _ | r | #f with f dzero | linv dzero ... | suc j , p | s = g-f-z v (j , p) r s f-g-z : ∀ v u → f dzero ≡ dsuc v → f (dsuc u) ≡ dzero → f- u ≡ v f-g-z v u r s with f (dsuc u) | f dzero | #-f (dsuc u) dzero _ ... | zero , _ | suc k , q | #fg = Detached-ext (k , q) v (cong (predℕ ∘ fst) r) ... | (suc _ , _) | _ | _ = Empty.rec (snotz (cong fst s)) f-g-s : ∀ v u → f (dsuc u) ≡ dsuc v → f- u ≡ v f-g-s v u r with f (dsuc u) | #-f (dsuc u) dzero _ ... | suc k , q | _ = Detached-ext (k , q) v (cong (predℕ ∘ fst) r) ... | zero , _ | _ = Empty.rec (znots (cong fst r)) f-g- : ∀ v → f- (g- v) ≡ v f-g- v with g (dsuc v) | rinv (dsuc v) | #-g (dsuc v) dzero _ ... | suc j , q | r | _ = f-g-s v (j , q) r ... | zero , _ | r | _ with g dzero | rinv dzero ... | suc k , q | s = f-g-z v (k , q) r s open Iso iso- : Iso (Detached α) (Detached β) iso- .fun = f- iso- .inv = g- iso- .rightInv = f-g- iso- .leftInv = g-f- iso-pred : ∀{α β} → Iso (Detached (ms α)) (Detached (ms β)) → Iso (Detached α) (Detached β) iso-pred i = Untangle.iso- fun inv rightInv leftInv where open Iso i isInjectiveLower : Lower m ≡ Lower n → m ≡ n isInjectiveLower {m} {n} P = curry ΣPathP (lemma (m .fst) (n .fst) (m .snd) (n .snd) (pathToIso P)) (isPropDepIsMonotone (m .snd) (n .snd) _) where lemma : ∀ α β → isMonotone α → isMonotone β → Iso (Detached α) (Detached β) → α ≡ β lemma α β mα mβ I i k with mview α mα | mview β mβ ... | mzv | mzv = mz k lemma α β mα mβ I i 0 | msv _ | msv _ = true lemma α β mα mβ I i (suc k) | msv α' | msv β' = lemma α' β' (mα ∘ suc) (mβ ∘ suc) (iso-pred I) i k lemma α β mα mβ I i k | mzv | msv β' = Empty.rec {A = α k ≡ β k} (Iso.inv I dzero .snd) i lemma α β mα mβ I i k | msv _ | mzv = Empty.rec {A = α k ≡ β k} (Iso.fun I dzero .snd) i