{-# OPTIONS --safe #-}
module Cubical.Data.Nat.Order.Recursive where
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Function
open import Cubical.Foundations.HLevels
open import Cubical.Foundations.Transport
open import Cubical.Data.Empty as Empty
open import Cubical.Data.Sigma
open import Cubical.Data.Sum as Sum
open import Cubical.Data.Unit
open import Cubical.Data.Nat.Base
open import Cubical.Data.Nat.Properties
open import Cubical.Induction.WellFounded
open import Cubical.Relation.Nullary
infix 4 _≤_ _<_
_≤_ : ℕ → ℕ → Type₀
zero ≤ _ = Unit
suc m ≤ zero = ⊥
suc m ≤ suc n = m ≤ n
_<_ : ℕ → ℕ → Type₀
m < n = suc m ≤ n
_≤?_ : (m n : ℕ) → Dec (m ≤ n)
zero ≤? _ = yes tt
suc m ≤? zero = no λ ()
suc m ≤? suc n = m ≤? n
data Trichotomy (m n : ℕ) : Type₀ where
lt : m < n → Trichotomy m n
eq : m ≡ n → Trichotomy m n
gt : n < m → Trichotomy m n
private
variable
ℓ : Level
R : Type ℓ
P : ℕ → Type ℓ
k l m n : ℕ
isProp≤ : isProp (m ≤ n)
isProp≤ {zero} = isPropUnit
isProp≤ {suc m} {zero} = isProp⊥
isProp≤ {suc m} {suc n} = isProp≤ {m} {n}
≤-k+ : m ≤ n → k + m ≤ k + n
≤-k+ {k = zero} m≤n = m≤n
≤-k+ {k = suc k} m≤n = ≤-k+ {k = k} m≤n
≤-+k : m ≤ n → m + k ≤ n + k
≤-+k {m} {n} {k} m≤n
= transport (λ i → +-comm k m i ≤ +-comm k n i) (≤-k+ {m} {n} {k} m≤n)
≤-refl : ∀ m → m ≤ m
≤-refl zero = _
≤-refl (suc m) = ≤-refl m
≤-trans : k ≤ m → m ≤ n → k ≤ n
≤-trans {zero} _ _ = _
≤-trans {suc k} {suc m} {suc n} = ≤-trans {k} {m} {n}
≤-antisym : m ≤ n → n ≤ m → m ≡ n
≤-antisym {zero} {zero} _ _ = refl
≤-antisym {suc m} {suc n} m≤n n≤m = cong suc (≤-antisym m≤n n≤m)
≤-k+-cancel : k + m ≤ k + n → m ≤ n
≤-k+-cancel {k = zero} m≤n = m≤n
≤-k+-cancel {k = suc k} m≤n = ≤-k+-cancel {k} m≤n
≤-+k-cancel : m + k ≤ n + k → m ≤ n
≤-+k-cancel {m} {k} {n}
= ≤-k+-cancel {k} {m} {n} ∘ transport λ i → +-comm m k i ≤ +-comm n k i
¬m<m : ¬ m < m
¬m<m {suc m} = ¬m<m {m}
≤0→≡0 : n ≤ 0 → n ≡ 0
≤0→≡0 {zero} _ = refl
¬m+n<m : ¬ m + n < m
¬m+n<m {suc m} = ¬m+n<m {m}
<-weaken : m < n → m ≤ n
<-weaken {zero} _ = _
<-weaken {suc m} {suc n} = <-weaken {m}
<-trans : k < m → m < n → k < n
<-trans {k} {m} {n} k<m m<n
= ≤-trans {suc k} {m} {n} k<m (<-weaken {m} m<n)
<-asym : m < n → ¬ n < m
<-asym {m} m<n n<m = ¬m<m {m} (<-trans {m} {_} {m} m<n n<m)
<→≢ : n < m → ¬ n ≡ m
<→≢ {n} {m} p q = ¬m<m {m = m} (subst {x = n} (_< m) q p)
Trichotomy-suc : Trichotomy m n → Trichotomy (suc m) (suc n)
Trichotomy-suc (lt m<n) = lt m<n
Trichotomy-suc (eq m≡n) = eq (cong suc m≡n)
Trichotomy-suc (gt n<m) = gt n<m
_≟_ : ∀ m n → Trichotomy m n
zero ≟ zero = eq refl
zero ≟ suc n = lt _
suc m ≟ zero = gt _
suc m ≟ suc n = Trichotomy-suc (m ≟ n)
k≤k+n : ∀ k → k ≤ k + n
k≤k+n zero = _
k≤k+n (suc k) = k≤k+n k
n≤k+n : ∀ n → n ≤ k + n
n≤k+n {k} n = transport (λ i → n ≤ +-comm n k i) (k≤k+n n)
≤-split : m ≤ n → (m < n) ⊎ (m ≡ n)
≤-split {zero} {zero} m≤n = inr refl
≤-split {zero} {suc n} m≤n = inl _
≤-split {suc m} {suc n} m≤n
= Sum.map (idfun _) (cong suc) (≤-split {m} {n} m≤n)
module WellFounded where
wf-< : WellFounded _<_
wf-rec-< : ∀ n → WFRec _<_ (Acc _<_) n
wf-< n = acc (wf-rec-< n)
wf-rec-< (suc n) m m≤n with ≤-split {m} {n} m≤n
... | inl m<n = wf-rec-< n m m<n
... | inr m≡n = subst⁻ (Acc _<_) m≡n (wf-< n)
wf-elim : (∀ n → (∀ m → m < n → P m) → P n) → ∀ n → P n
wf-elim = WFI.induction WellFounded.wf-<
wf-rec : (∀ n → (∀ m → m < n → R) → R) → ℕ → R
wf-rec {R = R} = wf-elim {P = λ _ → R}
module Minimal where
Least : ∀{ℓ} → (ℕ → Type ℓ) → (ℕ → Type ℓ)
Least P m = P m × (∀ n → n < m → ¬ P n)
isPropLeast : (∀ m → isProp (P m)) → ∀ m → isProp (Least P m)
isPropLeast pP m
= isPropΣ (pP m) (λ _ → isPropΠ3 λ _ _ _ → isProp⊥)
Least→ : Σ _ (Least P) → Σ _ P
Least→ = map-snd fst
search
: (∀ m → Dec (P m))
→ ∀ n → (Σ[ m ∈ ℕ ] Least P m) ⊎ (∀ m → m < n → ¬ P m)
search dec zero = inr (λ _ b _ → b)
search {P = P} dec (suc n) with search dec n
... | inl tup = inl tup
... | inr ¬P<n with dec n
... | yes Pn = inl (n , Pn , ¬P<n)
... | no ¬Pn = inr λ m m≤n
→ case ≤-split m≤n of λ where
(inl m<n) → ¬P<n m m<n
(inr m≡n) → subst⁻ (¬_ ∘ P) m≡n ¬Pn
→Least : (∀ m → Dec (P m)) → Σ _ P → Σ _ (Least P)
→Least dec (n , Pn) with search dec n
... | inl least = least
... | inr ¬P<n = n , Pn , ¬P<n
Least-unique : ∀ m n → Least P m → Least P n → m ≡ n
Least-unique m n (Pm , ¬P<m) (Pn , ¬P<n) with m ≟ n
... | lt m<n = Empty.rec (¬P<n m m<n Pm)
... | eq m≡n = m≡n
... | gt n<m = Empty.rec (¬P<m n n<m Pn)
isPropΣLeast : (∀ m → isProp (P m)) → isProp (Σ _ (Least P))
isPropΣLeast pP (m , LPm) (n , LPn)
= ΣPathP λ where
.fst → Least-unique m n LPm LPn
.snd → isOfHLevel→isOfHLevelDep 1 (isPropLeast pP)
LPm LPn (Least-unique m n LPm LPn)
Decidable→Collapsible
: (∀ m → isProp (P m)) → (∀ m → Dec (P m)) → Collapsible (Σ ℕ P)
Decidable→Collapsible pP dP = λ where
.fst → Least→ ∘ →Least dP
.snd x y → cong Least→ (isPropΣLeast pP (→Least dP x) (→Least dP y))
open Minimal using (Decidable→Collapsible) public