module Vector.Properties where open import Level using (Level) open import Function open import Data.Unit using (⊤) open import Data.Product open import Data.Sum open import Data.Bool using (Bool; T; false; true) open import Data.Maybe open import Data.Nat using (ℕ) open import Data.Fin open import Data.Fin.Properties open import Data.Vec.Functional open import Data.Vec.Functional.Properties open import Relation.Binary.PropositionalEquality open import Relation.Nullary open import Vector.Base open ≡-Reasoning private variable ℓ : Level A : Set ℓ m n : ℕ tail++same : (xs : Vector A (ℕ.suc m)) (ys : Vector A n) → tail (xs ++ ys) ≗ (tail xs ++ ys) tail++same {m = m} _ _ i with splitAt m i ... | inj₁ _ = refl ... | inj₂ _ = refl head++tail≡id : (xs : Vector A (ℕ.suc n)) → (head xs ∷ tail xs) ≗ xs head++tail≡id xs zero = refl head++tail≡id xs (suc i) = refl ++-split : ∀ x (xs : Vector A m) (ys : Vector A n) → ((x ∷ xs) ++ ys) ≗ (x ∷ xs ++ ys) ++-split x xs ys zero = refl ++-split {m = m} x xs ys (suc i) with splitAt m i ... | inj₁ _ = refl ... | inj₂ _ = refl swapCons : ∀ x (xs : Vector A n) (i j : Fin n) → swapV (x ∷ xs) (suc i) (suc j) ≗ (x ∷ swapV xs i j) swapCons _ _ _ _ zero = refl swapCons _ _ _ _ (suc _) = refl []≔-++ : ∀ (xs : Vector A m) (ys : Vector A n) p v → (xs ++ ys) [ p ↑ˡ n ]≔ v ≗ xs [ p ]≔ v ++ ys []≔-++ {m = m} {n} xs ys p v i with i ≟ p ↑ˡ n ... | yes refl rewrite updateAt-updates i {const v} (xs ++ ys) | splitAt-↑ˡ m p n = sym (updateAt-updates p _) ... | no i≢p rewrite updateAt-minimal _ _ {const v} (xs ++ ys) i≢p with splitAt m i in splitEq ... | inj₁ j = sym (updateAt-minimal j p xs (λ where refl → i≢p (sym (splitAt⁻¹-↑ˡ splitEq)))) ... | inj₂ _ = refl cong-updateAt : ∀ {xs ys : Vector A n} p f → xs ≗ ys → updateAt xs p f ≗ updateAt ys p f cong-updateAt zero f xs≡ys zero = cong f (xs≡ys zero) cong-updateAt (suc p) f xs≡ys zero = xs≡ys zero cong-updateAt zero f xs≡ys (suc i) = xs≡ys (suc i) cong-updateAt (suc p) f xs≡ys (suc i) = cong-updateAt p f (xs≡ys ∘ suc) i swapV-++ : ∀ (xs : Vector A m) (ys : Vector A n) p q → swapV (xs ++ ys) (p ↑ˡ n) (q ↑ˡ n) ≗ swapV xs p q ++ ys swapV-++ {m = m} {n} xs ys p q i = begin (xs++ysP [ q↑n ]≔ xs++ys p↑n) i ≡⟨ cong-updateAt q↑n _ xs++ysP-split i ⟩ ((xs [ p ]≔ xs q ++ ys) [ q↑n ]≔ xs++ys p↑n) i ≡⟨ xs++ysQ-split i ⟩ ((xs [ p ]≔ xs q ++ ys) [ q ↑ˡ n ]≔ xs p) i ≡⟨ []≔-++ (xs [ p ]≔ xs q) _ _ _ i ⟩ (xs [ p ]≔ xs q [ q ]≔ xs p ++ ys) i ∎ where xs++ys = xs ++ ys p↑n = p ↑ˡ n q↑n = q ↑ˡ n xs++ysP = xs++ys [ p↑n ]≔ xs++ys q↑n xs++≡q : xs++ys q↑n ≡ xs q xs++≡q = lookup-++ˡ xs ys _ xs++≡p : xs++ys p↑n ≡ xs p xs++≡p = lookup-++ˡ xs ys _ xs++ysP-split : xs++ysP ≗ xs [ p ]≔ xs q ++ ys xs++ysP-split i = trans ([]≔-++ xs ys _ _ i) (cong (λ x → (xs [ p ]≔ x ++ ys) i) xs++≡q) xs++ysQ-split : (xs [ p ]≔ xs q ++ ys) [ q↑n ]≔ xs++ys p↑n ≗ (xs [ p ]≔ xs q ++ ys) [ q↑n ]≔ xs p xs++ysQ-split i = cong (λ x → ((xs [ p ]≔ xs q ++ ys) [ q↑n ]≔ x) i) xs++≡p swap-exchange : ∀ (xs : Vector A n) i j → swapV xs i j ≗ swapV xs j i swap-exchange xs i j k with i ≟ j | k ≟ i | k ≟ j ... | yes refl | _ | _ = refl ... | no i≢j | yes refl | _ = begin _ ≡⟨ updateAt-minimal _ _ _ i≢j ⟩ _ ≡⟨ updateAt-updates i _ ⟩ _ ≡˘⟨ updateAt-updates i _ ⟩ _ ∎ ... | no i≢j | no k≢i | yes refl = begin _ ≡⟨ updateAt-updates j _ ⟩ _ ≡˘⟨ updateAt-updates j _ ⟩ _ ≡˘⟨ updateAt-minimal _ _ _ (i≢j ∘ sym) ⟩ _ ∎ ... | no i≢j | no k≢i | no k≢j = begin _ ≡⟨ updateAt-minimal _ _ _ k≢j ⟩ _ ≡⟨ updateAt-minimal _ _ _ k≢i ⟩ _ ≡˘⟨ updateAt-minimal _ _ _ k≢j ⟩ _ ≡˘⟨ updateAt-minimal _ _ _ k≢i ⟩ _ ∎ swap-injective : ∀ {xs ys : Vector A n} {i j} → swapV xs i j ≗ swapV ys i j → xs ≗ ys swap-injective {n = n} {xs} {ys} {i} {j} same k with k ≟ i | k ≟ j | i ≟ j ... | yes refl | yes refl | _ = begin _ ≡˘⟨ updateAt-updates i _ ⟩ _ ≡⟨ same k ⟩ _ ≡⟨ updateAt-updates i _ ⟩ _ ∎ ... | yes refl | no k≢j | yes refl = begin _ ≡˘⟨ updateAt-updates i _ ⟩ _ ≡˘⟨ updateAt-minimal _ _ _ k≢j ⟩ _ ≡⟨ same k ⟩ _ ≡⟨ updateAt-minimal _ _ _ k≢j ⟩ _ ≡⟨ updateAt-updates i _ ⟩ _ ∎ ... | yes refl | no k≢j | no i≢j = begin _ ≡˘⟨ updateAt-updates j _ ⟩ _ ≡⟨ same j ⟩ _ ≡⟨ updateAt-updates j _ ⟩ _ ∎ ... | no k≢i | yes refl | _ = begin _ ≡˘⟨ updateAt-updates i _ ⟩ _ ≡˘⟨ updateAt-minimal _ _ _ (k≢i ∘ sym) ⟩ _ ≡⟨ same i ⟩ _ ≡⟨ updateAt-minimal _ _ _ (k≢i ∘ sym) ⟩ _ ≡⟨ updateAt-updates i _ ⟩ _ ∎ ... | no k≢i | no k≢j | _ = begin _ ≡˘⟨ updateAt-minimal _ _ _ k≢i ⟩ _ ≡˘⟨ updateAt-minimal _ _ _ k≢j ⟩ _ ≡⟨ same k ⟩ _ ≡⟨ updateAt-minimal _ _ _ k≢j ⟩ _ ≡⟨ updateAt-minimal _ _ _ k≢i ⟩ _ ∎ swap-involute : ∀ (xs : Vector A n) i j → swapV (swapV xs i j) i j ≗ xs swap-involute xs i j k with k ≟ i | k ≟ j | i ≟ j ... | yes refl | yes refl | _ = begin _ ≡⟨ updateAt-updates i _ ⟩ _ ≡⟨ updateAt-updates i _ ⟩ _ ∎ ... | yes refl | no k≢j | _ = begin _ ≡⟨ updateAt-minimal _ _ _ k≢j ⟩ _ ≡⟨ updateAt-updates i _ ⟩ _ ≡⟨ updateAt-updates j _ ⟩ _ ∎ ... | no k≢i | yes refl | no i≢j = begin _ ≡⟨ updateAt-updates j _ ⟩ _ ≡⟨ updateAt-minimal _ _ _ i≢j ⟩ _ ≡⟨ updateAt-updates i _ ⟩ _ ∎ ... | no k≢i | yes refl | yes refl = begin _ ≡⟨ updateAt-updates j _ ⟩ _ ≡⟨ updateAt-updates i _ ⟩ _ ∎ ... | no k≢i | no k≢j | _ = begin _ ≡⟨ updateAt-minimal _ _ _ k≢j ⟩ _ ≡⟨ updateAt-minimal _ _ _ k≢i ⟩ _ ≡⟨ updateAt-minimal _ _ _ k≢j ⟩ _ ≡⟨ updateAt-minimal _ _ _ k≢i ⟩ _ ∎ swap-same-left : ∀ {xs ys : Vector A n} {i j} → swapV xs i j ≗ ys → xs ≗ swapV ys i j swap-same-left {n = n} {xs} {ys} {i} {j} same = swap-injective λ j → trans (same _) (sym (swap-involute ys _ _ _)) swap-diff : ∀ (xs : Vector A n) k {i j} → k ≢ i → k ≢ j → swapV xs i j k ≡ xs k swap-diff xs k {i} {j} k≢i k≢j = begin _ ≡⟨ updateAt-minimal _ _ _ k≢j ⟩ _ ≡⟨ updateAt-minimal _ _ _ k≢i ⟩ _ ∎ firstHasProperty : {A : Set ℓ} (xs : Vector A n) (f : A → Bool) → maybe (λ (_ , a) → T (f a)) ⊤ (findFirst xs f) firstHasProperty {n = ℕ.zero} xs f = _ firstHasProperty {n = ℕ.suc n} xs f with f (xs zero) in eqF0 ... | true rewrite eqF0 = _ ... | false rewrite eqF0 with findFirst (tail xs) f in eqF | firstHasProperty (tail xs) f ... | just _ | prop = prop ... | nothing | _ rewrite eqF = _ appendLastFromℕ : ∀ (xs : Vector A n) a → appendLast xs a (fromℕ _) ≡ a appendLastFromℕ {n = ℕ.zero} xs a = refl appendLastFromℕ {n = ℕ.suc n} xs a = appendLastFromℕ (tail xs) a appendLastInj : ∀ (xs : Vector A n) a i → appendLast xs a (inject₁ i) ≡ xs i appendLastInj xs a zero = refl appendLastInj xs a (suc i) = appendLastInj (tail xs) a i appendLastLower : ∀ (xs : Vector A n) a i (n≢i : n ≢ toℕ i) → appendLast xs a i ≡ xs (lower₁ i n≢i) appendLastLower {n = ℕ.zero} xs a zero n≢i = contradiction refl n≢i appendLastLower {n = ℕ.suc n} xs a zero n≢i = refl appendLastLower {n = ℕ.suc n} xs a (suc i) n≢i = appendLastLower (tail xs) a i (λ n≡i → n≢i (cong ℕ.suc n≡i))