{-# OPTIONS --without-K #-}
module Data.Nat.PredExp2 where
open import Data.Nat
open import Data.Nat.Properties
open import Relation.Nullary
open import Relation.Nullary.Negation
open import Relation.Binary
open import Relation.Binary.PropositionalEquality as Eq using (_≡_; refl; _≢_; module ≡-Reasoning)
open import Data.Nat.Log2 using (⌈log₂_⌉)
pred[2^_] : ℕ → ℕ
pred[2^ n ] = pred (2 ^ n)
lemma/2^suc : ∀ n → 2 ^ n + 2 ^ n ≡ 2 ^ suc n
lemma/2^suc n =
begin
2 ^ n + 2 ^ n
≡˘⟨ Eq.cong ((2 ^ n) +_) (*-identityˡ (2 ^ n)) ⟩
2 ^ n + (2 ^ n + 0)
≡⟨⟩
2 ^ n + (2 ^ n + 0 * (2 ^ n))
≡⟨⟩
2 * (2 ^ n)
≡⟨⟩
2 ^ suc n
∎
where open ≡-Reasoning
private
lemma/1≤2^n : ∀ n → 1 ≤ 2 ^ n
lemma/1≤2^n zero = ≤-refl {1}
lemma/1≤2^n (suc n) =
begin
1
≤⟨ s≤s z≤n ⟩
1 + 1
≤⟨ +-mono-≤ (lemma/1≤2^n n) (lemma/1≤2^n n) ⟩
2 ^ n + 2 ^ n
≡⟨ lemma/2^suc n ⟩
2 ^ suc n
∎
where open ≤-Reasoning
lemma/2^n≢0 : ∀ n → 2 ^ n ≢ zero
lemma/2^n≢0 n 2^n≡0 with 2 ^ n | lemma/1≤2^n n
... | zero | ()
pred[2^]-mono : pred[2^_] Preserves _≤_ ⟶ _≤_
pred[2^]-mono m≤n = pred-mono-≤ (2^-mono m≤n)
where
2^-mono : (2 ^_) Preserves _≤_ ⟶ _≤_
2^-mono {y = y} z≤n = lemma/1≤2^n y
2^-mono (s≤s m≤n) = *-monoʳ-≤ 2 (2^-mono m≤n)
pred[2^suc[n]] : (n : ℕ) → suc (pred[2^ n ] + pred[2^ n ]) ≡ pred[2^ suc n ]
pred[2^suc[n]] n =
begin
suc (pred[2^ n ] + pred[2^ n ])
≡⟨⟩
suc (pred (2 ^ n) + pred (2 ^ n))
≡˘⟨ +-suc (pred (2 ^ n)) (pred (2 ^ n)) ⟩
pred (2 ^ n) + suc (pred (2 ^ n))
≡⟨ Eq.cong (pred (2 ^ n) +_) (suc-pred (2 ^ n) {{m^n≢0 2 n}}) ⟩
pred (2 ^ n) + 2 ^ n
≡˘⟨ +-∸-comm (2 ^ n) (m^n>0 2 n) ⟩
pred (2 ^ n + 2 ^ n)
≡⟨ Eq.cong pred (lemma/2^suc n) ⟩
pred (2 ^ suc n)
≡⟨⟩
pred[2^ suc n ]
∎
where
open ≡-Reasoning
pred[2^log₂] : (n : ℕ) → pred[2^ ⌈log₂ suc ⌈ n /2⌉ ⌉ ] ≤ n
pred[2^log₂] n = lemma
where
open import Data.Nat.Logarithm.Core
open import Induction.WellFounded using (Acc; acc)
lemma : ∀ {n acc} → pred[2^ ⌈log2⌉ (suc ⌈ n /2⌉) acc ] ≤ n
lemma {zero} = z≤n
lemma {suc zero} {acc _} = s≤s z≤n
lemma {suc (suc n)} {acc rs} =
begin
pred[2^ ⌈log2⌉ (suc ⌈ suc (suc n) /2⌉) (acc rs) ]
≡⟨⟩
pred[2^ suc (⌈log2⌉ ⌈ suc ⌈ suc (suc n) /2⌉ /2⌉ _) ]
≡˘⟨ pred[2^suc[n]] (⌈log2⌉ ⌈ suc ⌈ suc (suc n) /2⌉ /2⌉ _) ⟩
suc (pred[2^ (⌈log2⌉ ⌈ suc ⌈ suc (suc n) /2⌉ /2⌉ _) ] + pred[2^ (⌈log2⌉ ⌈ suc ⌈ suc (suc n) /2⌉ /2⌉ _) ])
≡⟨⟩
suc (pred[2^ ⌈log2⌉ ⌈ suc (suc ⌈ n /2⌉) /2⌉ _ ] + pred[2^ ⌈log2⌉ ⌈ suc (suc ⌈ n /2⌉) /2⌉ _ ])
≡⟨⟩
suc (pred[2^ ⌈log2⌉ (suc ⌈ ⌈ n /2⌉ /2⌉) _ ] + pred[2^ ⌈log2⌉ (suc ⌈ ⌈ n /2⌉ /2⌉) _ ])
≤⟨ s≤s (+-mono-≤ (lemma {⌈ n /2⌉}) (lemma {⌈ n /2⌉})) ⟩
suc (⌈ n /2⌉ + ⌈ n /2⌉)
≡⟨⟩
suc (⌊ suc n /2⌋ + ⌈ n /2⌉)
≤⟨ s≤s (+-monoʳ-≤ ⌊ suc n /2⌋ (⌈n/2⌉-mono (n≤1+n n))) ⟩
suc (⌊ suc n /2⌋ + ⌈ suc n /2⌉)
≡⟨ Eq.cong suc (⌊n/2⌋+⌈n/2⌉≡n (suc n)) ⟩
suc (suc n)
∎
where open ≤-Reasoning