module Data.Fin.NP where
open import Type hiding (★)
open import Function
open import Data.Zero
open import Data.One
open import Data.Fin public renaming (toℕ to Fin▹ℕ)
open import Data.Nat.NP using (ℕ; zero; suc; _<=_; module ℕ°) renaming (_+_ to _+ℕ_)
open import Data.Two hiding (_==_)
import Data.Vec.NP as Vec
open Vec using (Vec; []; _∷_; _∷ʳ_; allFin; lookup; rot₁) renaming (map to vmap)
import Data.Vec.Properties as Vec
open import Data.Maybe.NP
open import Data.Sum as Sum
open import Relation.Binary.PropositionalEquality as ≡
suc-injective : ∀ {m}{i j : Fin m} → Fin.suc i ≡ suc j → i ≡ j
suc-injective refl = refl
Fin▹𝟘 : Fin 0 → 𝟘
Fin▹𝟘 ()
𝟘▹Fin : 𝟘 → Fin 0
𝟘▹Fin ()
Fin▹𝟙 : Fin 1 → 𝟙
Fin▹𝟙 _ = _
𝟙▹Fin : 𝟙 → Fin 1
𝟙▹Fin _ = zero
Fin▹𝟚 : Fin 2 → 𝟚
Fin▹𝟚 zero = 0₂
Fin▹𝟚 (suc _) = 1₂
𝟚▹Fin : 𝟚 → Fin 2
𝟚▹Fin = [0: # 0 1: # 1 ]
_+′_ : ∀ {m n} (x : Fin m) (y : Fin n) → Fin (m +ℕ n)
_+′_ {suc m} {n} zero y rewrite ℕ°.+-comm (suc m) n = inject+ _ y
suc x +′ y = suc (x +′ y)
_==_ : ∀ {n} (x y : Fin n) → 𝟚
x == y = helper (compare x y) where
helper : ∀ {n} {i j : Fin n} → Ordering i j → 𝟚
helper (equal _) = 1₂
helper _ = 0₂
swap : ∀ {i} (x y : Fin i) → Fin i → Fin i
swap x y z = case x == z 0: (case y == z 0: z 1: x) 1: y
data FinSum m n : Fin (m +ℕ n) → ★₀ where
bound : (x : Fin m) → FinSum m n (inject+ n x)
free : (x : Fin n) → FinSum m n (raise m x)
open import Relation.Binary.PropositionalEquality
cmp : ∀ m n (x : Fin (m +ℕ n)) → FinSum m n x
cmp zero n x = free x
cmp (suc m) n zero = bound zero
cmp (suc m) n (suc x) with cmp m n x
cmp (suc m) n (suc .(inject+ n x)) | bound x = bound (suc x)
cmp (suc m) n (suc .(raise m x)) | free x = free x
max : ∀ n → Fin (suc n)
max = fromℕ
reverse : ∀ {n} → Fin n → Fin n
reverse {suc n} zero = fromℕ n
reverse {suc n} (suc x) = inject₁ (reverse {n} x)
open import Data.Nat
open import Data.Nat.Properties
open import Data.Fin.Props renaming (reverse to reverse-old)
reverse-fromℕ : ∀ n → reverse (fromℕ n) ≡ zero
reverse-fromℕ zero = refl
reverse-fromℕ (suc n) rewrite reverse-fromℕ n = refl
reverse-inject₁ : ∀ {n} (x : Fin n) → reverse (inject₁ x) ≡ suc (reverse x)
reverse-inject₁ zero = refl
reverse-inject₁ (suc x) rewrite reverse-inject₁ x = refl
reverse-lem : ∀ {n} (x : Fin n) → Fin▹ℕ (reverse x) ≡ n ∸ suc (Fin▹ℕ x)
reverse-lem zero = to-from _
reverse-lem (suc x) rewrite inject₁-lemma (reverse x) = reverse-lem x
Fin▹ℕ-ℕ-lem : ∀ {n} (x : Fin (suc n)) → Fin▹ℕ (n ℕ- x) ≡ n ∸ Fin▹ℕ x
Fin▹ℕ-ℕ-lem zero = to-from _
Fin▹ℕ-ℕ-lem {zero} (suc ())
Fin▹ℕ-ℕ-lem {suc n} (suc x) = Fin▹ℕ-ℕ-lem x
reverse-old-lem : ∀ {n} (x : Fin n) → Fin▹ℕ (reverse-old x) ≡ n ∸ suc (Fin▹ℕ x)
reverse-old-lem {zero} ()
reverse-old-lem {suc n} x rewrite inject≤-lemma (n ℕ- x) (n∸m≤n (Fin▹ℕ x) (suc n)) = Fin▹ℕ-ℕ-lem x
data FinView {n} : Fin (suc n) → ★₀ where
`fromℕ : FinView (fromℕ n)
`inject₁ : ∀ x → FinView (inject₁ x)
sucFinView : ∀ {n} {i : Fin (suc n)} → FinView i → FinView (suc i)
sucFinView `fromℕ = `fromℕ
sucFinView (`inject₁ x) = `inject₁ (suc x)
finView : ∀ {n} → (i : Fin (suc n)) → FinView i
finView {zero} zero = `fromℕ
finView {suc n} zero = `inject₁ zero
finView {suc n} (suc i) = sucFinView (finView i)
finView {zero} (suc ())
module Modulo where
modq : ∀ {q} → Fin (suc q) → Maybe (Fin q)
modq {zero} _ = nothing
modq {suc q} zero = just zero
modq {suc q} (suc x) = map? suc (modq x)
modq-inj : ∀ {q} (i j : Fin (suc q)) → modq i ≡ modq j → i ≡ j
modq-inj {zero} zero zero eq = refl
modq-inj {zero} zero (suc ()) eq
modq-inj {zero} (suc ()) zero eq
modq-inj {zero} (suc ()) (suc ()) eq
modq-inj {suc q} zero zero eq = refl
modq-inj {suc q} zero (suc j) eq with modq j
modq-inj {suc q} zero (suc j) () | nothing
modq-inj {suc q} zero (suc j) () | just j'
modq-inj {suc q} (suc i) zero eq with modq i
modq-inj {suc q} (suc i) zero () | just x
modq-inj {suc q} (suc i) zero () | nothing
modq-inj {suc q} (suc i) (suc j) eq with modq i | modq j | modq-inj i j
modq-inj {suc q} (suc i) (suc j) eq | just x | just x₁ | p = cong suc (p (cong just (suc-injective (just-injective eq))))
modq-inj {suc q} (suc i) (suc j) () | just x | nothing | p
modq-inj {suc q} (suc i) (suc j) () | nothing | just x | p
modq-inj {suc q} (suc i) (suc j) eq | nothing | nothing | p = cong suc (p refl)
modq′ : ∀ {q} → Fin (suc q) → Fin (suc q)
modq′ {zero} _ = zero
modq′ {suc q} zero = suc zero
modq′ {suc q} (suc x) = lift 1 suc (modq′ x)
modqq : ∀ {q} → Fin q → Fin q
modqq {zero} x = x
modqq {suc q} x = modq′ x
modq′′ : ∀ {q} → Fin (suc q) → Maybe (Fin q)
modq′′ x with modq′ x
... | zero = nothing
... | suc y = just y
zero∃ : ∀ {q} → Fin q → Fin q
zero∃ {zero} ()
zero∃ {suc q} _ = zero
sucmod : ∀ {q} → Fin q → Fin q
sucmod x with modq (suc x)
... | nothing = zero∃ x
... | just y = y
modq-suc : ∀ {q} (i j : Fin q) → modq (suc i) ≢ just (zero∃ j)
modq-suc {zero} () () eq
modq-suc {suc q} i j eq with modq i
modq-suc {suc q} i j () | just x
modq-suc {suc q} i j () | nothing
sucmod-inj : ∀ {q}{i j : Fin q} → sucmod i ≡ sucmod j → i ≡ j
sucmod-inj {i = i} {j} eq with modq (suc i) | modq (suc j) | modq-inj (suc i) (suc j) | modq-suc i j | modq-suc j i
sucmod-inj eq | just _ | just _ | p | _ | _ = suc-injective (p (cong just eq))
sucmod-inj eq | nothing | nothing | p | _ | _ = suc-injective (p refl)
sucmod-inj eq | just _ | nothing | _ | p | _ = 𝟘-elim (p (cong Maybe.just eq))
sucmod-inj eq | nothing | just _ | _ | _ | p = 𝟘-elim (p (cong Maybe.just (sym eq)))
modq-fromℕ : ∀ q → modq (fromℕ q) ≡ nothing
modq-fromℕ zero = refl
modq-fromℕ (suc q) rewrite modq-fromℕ q = refl
modq-inject₁ : ∀ {q} (i : Fin q) → modq (inject₁ i) ≡ just i
modq-inject₁ zero = refl
modq-inject₁ (suc i) rewrite modq-inject₁ i = refl
sucmod-fromℕ : ∀ q → sucmod (fromℕ q) ≡ zero
sucmod-fromℕ q rewrite modq-fromℕ q = refl
sucmod-inject₁ : ∀ {n} (i : Fin n) → sucmod (inject₁ i) ≡ suc i
sucmod-inject₁ i rewrite modq-inject₁ i = refl
lem-inject₁ : ∀ {n a} {A : ★ a} (i : Fin n) (xs : Vec A n) x → lookup (inject₁ i) (xs ∷ʳ x) ≡ lookup i xs
lem-inject₁ zero (x₀ ∷ xs) x₁ = refl
lem-inject₁ (suc i) (x₀ ∷ xs) x₁ = lem-inject₁ i xs x₁
lem-fromℕ : ∀ {n a} {A : ★ a} (xs : Vec A n) x → lookup (fromℕ n) (xs ∷ʳ x) ≡ x
lem-fromℕ {zero} [] x = refl
lem-fromℕ {suc n} (_ ∷ xs) x = lem-fromℕ xs x
lookup-sucmod : ∀ {n a} {A : ★ a} (i : Fin (suc n)) (x : A) xs
→ lookup i (xs ∷ʳ x) ≡ lookup (sucmod i) (x ∷ xs)
lookup-sucmod i x xs with finView i
lookup-sucmod {n} .(fromℕ n) x xs | `fromℕ rewrite sucmod-fromℕ n = lem-fromℕ xs x
lookup-sucmod .(inject₁ x) x₁ xs | `inject₁ x rewrite sucmod-inject₁ x = lem-inject₁ x xs x₁
lookup-map : ∀ {n a b} {A : ★ a} {B : ★ b} (f : A → B) i (xs : Vec A n)
→ lookup i (vmap f xs) ≡ f (lookup i xs)
lookup-map f zero (x ∷ xs) = refl
lookup-map f (suc i) (x ∷ xs) = lookup-map f i xs
vec≗⇒≡ : ∀ {n a} {A : ★ a} (xs ys : Vec A n) → flip lookup xs ≗ flip lookup ys → xs ≡ ys
vec≗⇒≡ [] [] _ = refl
vec≗⇒≡ (x ∷ xs) (y ∷ ys) p rewrite vec≗⇒≡ xs ys (p ∘ suc) | p zero = refl
private
module Unused where
lookup-sucmod-rot₁ : ∀ {n a} {A : ★ a} (i : Fin n) (xs : Vec A n)
→ lookup i (rot₁ xs) ≡ lookup (sucmod i) xs
lookup-sucmod-rot₁ {zero} () xs
lookup-sucmod-rot₁ {suc n} i (x ∷ xs) = lookup-sucmod i x xs
lookup-rot₁-allFin : ∀ {n} i → lookup i (rot₁ (allFin n)) ≡ lookup i (vmap sucmod (allFin n))
lookup-rot₁-allFin {n} i rewrite lookup-sucmod-rot₁ i (allFin _)
| Vec.lookup-allFin (sucmod i)
| lookup-map sucmod i (allFin n)
| Vec.lookup∘tabulate id i
= refl
rot₁-map-sucmod : ∀ n → rot₁ (allFin n) ≡ vmap sucmod (allFin n)
rot₁-map-sucmod _ = vec≗⇒≡ _ _ lookup-rot₁-allFin