open import Level using (Level; _⊔_) open import Function open import Algebra open import Algebra.Module open import Data.Empty open import Data.Bool hiding (_≟_) open import Data.Maybe using (Maybe; map) open import Data.Product open import Data.Sum renaming ([_,_] to [_⊕_]) open import Data.Nat as ℕ using (ℕ; _∸_) open import Data.Nat.Properties as ℕ hiding (_≟_) open import Data.Vec as V renaming (_∷_ to _::_) using (Vec; []) open import Data.Fin hiding (_+_; _-_) open import Data.Fin.Properties open import Data.Fin.Patterns open import Data.Fin.Permutation as ↭ hiding (remove; _≈_) open import Data.Fin.Permutation.Components renaming (transpose to transposeC) open import Data.List as L using (List) open import Data.Vec.Functional hiding (transpose) open import Data.Vec.Functional.Properties hiding (++-cong) import Data.Vec.Functional.Relation.Binary.Equality.Setoid as ≋-props open import Relation.Binary import Relation.Binary.Reasoning.Setoid as ≈-Reasoning open import Relation.Binary.PropositionalEquality as ≡ hiding (sym) open import Relation.Nullary open import Relation.Nullary.Decidable import Algebra.Solver.CommutativeMonoid as CMonoidSolver open import Vector.Base import Vector.Setoid.Properties as VecProps open import Vector.Properties open import Vector.Permutation import Algebra.Module.Base as MBase import Algebra.Module.Definition as MDefinitions import Algebra.Module.DefsField as DField open import Algebra.BigOps open import Vec.Updates.Base renaming (_∷_ to _::_) open import Vec.Relation.FirstOrNot module Algebra.Module.VecSpace {rr ℓr mr ℓm} {ring : Ring rr ℓr} (leftModule : LeftModule ring mr ℓm) where infixl 4 _≈ⱽ_ open MBase ring open module R = Ring ring renaming (Carrier to R) open LeftModule leftModule renaming (Carrierᴹ to M) open ≋-props ≈ᴹ-setoid open SetoidProps ≈ᴹ-setoid open VecProps ≈ᴹ-setoid module ≈ᴹ-Reasoning = ≈-Reasoning ≈ᴹ-setoid module ≈ᴹ = Setoid ≈ᴹ-setoid module ≋-Reasoning {n} = ≈-Reasoning (≋-setoid n) open MDefinitions leftModule open SumCommMonoid +ᴹ-commutativeMonoid private variable m n : ℕ x y : M i j p q : Fin n xs xs‵ ys ys‵ zs : Vector M n r : R _[_]←_*[_] : Vector M n → Fin n → R → Fin n → Vector M n (M [ q ]← r *[ p ]) i with does (q ≟ i) ... | true = M i +ᴹ r *ₗ M p ... | false = M i matOps→func : VecOp n → Vector M n → Vector M n matOps→func (swapOp p q p≢q) xs = swapV xs p q matOps→func (addCons p q p≢q r) xs = xs [ q ]← r *[ p ] matOps→func-cong : (xs ys : Vector M n) (mOps : VecOp n) → xs ≋ ys → matOps→func mOps xs ≋ matOps→func mOps ys matOps→func-cong xs ys (swapOp p q p≢q) xs≈ys i = []≔-cong (xs≈ys _) ([]≔-cong (xs≈ys _) xs≈ys _) q i matOps→func-cong xs ys (addCons p q p≢q r) xs≈ys i with does $ q ≟ i ... | false = xs≈ys i ... | true = +ᴹ-cong (xs≈ys i) (*ₗ-cong R.refl (xs≈ys p)) private opposite-injective : Injective _≡_ _≡_ (opposite {n}) opposite-injective {ℕ.suc n} {i} {j} eq = toℕ-injective $ ∸-cancelˡ-≡ {m = n} (toℕ≤pred[n] i) (toℕ≤pred[n] j) (begin n ∸ toℕ i ≡˘⟨ opposite-prop i ⟩ toℕ (opposite i) ≡⟨ cong toℕ eq ⟩ toℕ (opposite j) ≡⟨ opposite-prop j ⟩ n ∸ toℕ j ∎) where open ≡-Reasoning opVecOps : Op₁ $ VecOp n opVecOps (swapOp p q p≢q) = swapOp (opposite p) (opposite q) $ p≢q ∘ opposite-injective opVecOps (addCons p q p≢q r) = addCons (opposite p) (opposite q) (p≢q ∘ opposite-injective) r invVecOp : Op₁ $ VecOp n invVecOp (swapOp p q p≢q) = swapOp q p (p≢q ∘ ≡.sym) invVecOp (addCons p q p≢q r) = addCons q p (p≢q ∘ ≡.sym) r data _≈ⱽ_ : Rel (Vector M n) (rr ⊔ mr ⊔ ℓm) where idR : xs ≋ ys → xs ≈ⱽ ys rec : (mOps : VecOp n) → xs ≈ⱽ ys → matOps→func mOps ys ≋ zs → xs ≈ⱽ zs ≈ⱽ⇒listVops : {xs : Vector M n} → xs ≈ⱽ ys → List (VecOp n) ≈ⱽ⇒listVops (idR _) = L.[] ≈ⱽ⇒listVops (rec mOps xs≈ⱽys _) = mOps L.∷ ≈ⱽ⇒listVops xs≈ⱽys ∷≈≋→≈ⱽ : x ≈ᴹ y → xs ≋ ys → (x ∷ xs) ≈ⱽ (y ∷ ys) ∷≈≋→≈ⱽ = idR ∘₂ ≋-cons []←suc : ∀ x xs r (p q : Fin n) → ((x ∷ xs) [ suc q ]← r *[ suc p ]) ≋ (x ∷ xs [ q ]← r *[ p ]) []←suc x xs r p q zero = ≈ᴹ-refl []←suc x xs r p q (suc i) with q ≟ i ... | yes _ = ≈ᴹ-refl ... | no _ = ≈ᴹ-refl ≡r*[] : ∀ (xs : Vector M n) r p q → (xs [ q ]← r *[ p ]) q ≡ xs q +ᴹ r *ₗ xs p ≡r*[] xs r p q with q ≟ q ... | yes _ = ≡.refl ... | no ¬q = ⊥-elim (¬q ≡.refl) ≢r*[] : ∀ (xs : Vector M n) r p q {i} → q ≢ i → (xs [ q ]← r *[ p ]) i ≡ xs i ≢r*[] xs r p q {i} q≢i with q ≟ i ... | yes q≡i = ⊥-elim (q≢i q≡i) ... | no _ = ≡.refl []←++ : ∀ (xs : Vector M m) (ys : Vector M n) r p q → ((xs ++ ys) [ q ↑ˡ n ]← r *[ p ↑ˡ n ]) ≋ (xs [ q ]← r *[ p ] ++ ys) []←++ {m = m} {n = n} xs ys r p q i with q ↑ˡ n ≟ i | toℕ i ℕ.<? m ... | no q↑n≢i | yes i<m = α where α : _ α with q ≟ fromℕ< i<m ... | yes refl = ⊥-elim (q↑n≢i (toℕ-injective (begin toℕ (fromℕ< i<m ↑ˡ n) ≡⟨ toℕ-↑ˡ _ _ ⟩ toℕ (fromℕ< i<m) ≡⟨ toℕ-fromℕ< _ ⟩ toℕ i ∎))) where open ≡-Reasoning ... | no q≢i = begin [ xs ⊕ ys ] (splitAt m i) ≡⟨ lookup-++-< xs ys i i<m ⟩ xs (fromℕ< i<m) ≡˘⟨ ≢r*[] xs r p q q≢i ⟩ (xs [ q ]← r *[ p ]) (fromℕ< i<m) ≡˘⟨ lookup-++-< (xs [ q ]← r *[ p ]) ys i i<m ⟩ (xs [ q ]← r *[ p ] ++ ys) i ∎ where open ≈ᴹ-Reasoning ... | yes q↑n≡i | no ¬i<m = ⊥-elim (¬i<m (begin-strict toℕ i ≡˘⟨ cong toℕ q↑n≡i ⟩ toℕ (q ↑ˡ n) ≡⟨ toℕ-↑ˡ _ _ ⟩ toℕ q <⟨ toℕ<n _ ⟩ m ∎)) where open ≤-Reasoning ... | no _ | no ¬i<m rewrite splitAt-≥ m i (≮⇒≥ ¬i<m) = ≈ᴹ-refl ... | yes refl | yes i<m rewrite splitAt-< m i i<m with q ≟ fromℕ< i<m ... | yes _ rewrite splitAt-< m (p ↑ˡ n) (≤-<-trans (ℕ.≤-reflexive (toℕ-↑ˡ _ _)) (toℕ<n _)) = +ᴹ-congˡ (*ₗ-congˡ (≈ᴹ-reflexive (cong xs (toℕ-injective α)))) where open ≡-Reasoning α = begin toℕ (fromℕ< (≤-<-trans (ℕ.≤-reflexive (toℕ-↑ˡ p n)) (toℕ<n p))) ≡⟨ toℕ-fromℕ< _ ⟩ toℕ (p ↑ˡ n) ≡⟨ toℕ-↑ˡ _ _ ⟩ toℕ p ∎ ... | no q≠i = ⊥-elim (q≠i (≡.sym (toℕ-injective (≡.trans (toℕ-fromℕ< _) (toℕ-↑ˡ _ _))))) ∷≈ⱽ→≈ⱽ : x ≈ᴹ y → xs ≈ⱽ ys → (x ∷ xs) ≈ⱽ (y ∷ ys) ∷≈ⱽ→≈ⱽ x≈y (idR xs≋ys) = ∷≈≋→≈ⱽ x≈y xs≋ys ∷≈ⱽ→≈ⱽ x≈y (rec (swapOp p q p≢q) xs≈ys mopsM) = rec (swapOp (suc p) (suc q) (p≢q ∘ λ where refl → ≡.refl)) (∷≈ⱽ→≈ⱽ x≈y xs≈ys) (≋-trans (≈ᴹ-reflexive ∘ swapCons _ _ _ _) (≋-consˡ mopsM)) ∷≈ⱽ→≈ⱽ x≈y (rec (addCons p q p≢q r) xs≈ys mopsM) = rec (addCons (suc p) (suc q) (p≢q ∘ λ where refl → ≡.refl) r) (∷≈ⱽ→≈ⱽ x≈y xs≈ys) (≋-trans ([]←suc _ _ _ _ _) (≋-consˡ mopsM)) ≈ⱽ++ : xs ≈ⱽ xs‵ → ys ≋ ys‵ → (xs ++ ys) ≈ⱽ (xs‵ ++ ys‵) ≈ⱽ++ (idR xs≋xs‵) = idR ∘ ++⁺ _≈ᴹ_ xs≋xs‵ ≈ⱽ++ {xs‵ = xs‵} {ys‵ = ys‵} (rec {ys = ys} (swapOp p q p≢q) xs≈xs‵ mOpsZ) ys≋ys‵ = rec (swapOp (p ↑ˡ _) (q ↑ˡ _) (p≢q ∘ ↑ˡ-injective _ _ _)) (≈ⱽ++ xs≈xs‵ ys≋ys‵) (begin swapV (ys ++ ys‵) (p ↑ˡ _) (q ↑ˡ _) ≈⟨ (λ i → ≈ᴹ-reflexive (swapV-++ ys ys‵ p q i)) ⟩ swapV ys p q ++ ys‵ ≈⟨ ++-congʳ _ xs‵ mOpsZ ⟩ xs‵ ++ ys‵ ∎) where open ≋-Reasoning ≈ⱽ++ {xs‵ = xs‵} {ys‵ = ys‵} (rec {ys = ys} (addCons p q p≢q r) xs≈xs‵ mOpsZ) ys≋ys‵ = rec (addCons (p ↑ˡ _) (q ↑ˡ _) (p≢q ∘ ↑ˡ-injective _ _ _) r) (≈ⱽ++ xs≈xs‵ ys≋ys‵) (begin (ys ++ ys‵) [ q ↑ˡ _ ]← r *[ p ↑ˡ _ ] ≈⟨ []←++ _ _ _ p q ⟩ ys [ q ]← r *[ p ] ++ ys‵ ≈⟨ ++-congʳ (ys [ q ]← r *[ p ]) xs‵ mOpsZ ⟩ xs‵ ++ ys‵ ∎) where open ≋-Reasoning ≈ⱽ-refl : Reflexive (_≈ⱽ_ {n = n}) ≈ⱽ-refl = idR ≋-refl ≈ⱽ-trans : Transitive (_≈ⱽ_ {n = n}) ≈ⱽ-trans (idR xs≋ys) (idR ys≋zs) = idR (≋-trans xs≋ys ys≋zs) ≈ⱽ-trans (rec mOps xs≈ⱽys mOpsXs) (idR ys≋zs) = rec mOps xs≈ⱽys (≋-trans mOpsXs ys≋zs) ≈ⱽ-trans xs≈ⱽys (rec {ys = ws} mOpsYsZs ys≈ⱽzs mOpsYs) = rec mOpsYsZs (≈ⱽ-trans xs≈ⱽys ys≈ⱽzs) mOpsYs [_,,_] : M → M → Vector M 2 [ x ,, y ] zero = x [ x ,, y ] (suc i) = y private v→ij : (v : Fin 2) (i j : Fin n) → Fin n v→ij 0F i j = i v→ij 1F i j = j stepVecSpace : ∀ {n} → (let n′ = ℕ.suc (ℕ.suc n)) → (xs : Vector M n′) (ys : Vector M 2) (i j : Fin n′) (let x = xs i) (let y = xs j) → i ≢ j → [ x ,, y ] ≈ⱽ ys → (let x′ = ys 0F) (let y′ = ys 1F) → xs ≈ⱽ xs [ i ]≔ x′ [ j ]≔ y′ stepVecSpace xs ys i j i≢j (idR xsIJ≈ys) = idR xs≈zs where xs≈zs : xs ≋ (xs [ i ]≔ ys 0F [ j ]≔ ys 1F) xs≈zs k with k ≟ j ... | yes refl = ≈ᴹ.sym $ begin (xs [ i ]≔ ys 0F [ j ]≔ ys 1F) k ≡⟨ updateAt-updates j _ ⟩ ys 1F ≈˘⟨ xsIJ≈ys 1F ⟩ xs k ∎ where open ≈ᴹ-Reasoning ... | no k≢j with k ≟ i ... | yes ≡.refl = ≈ᴹ.sym $ begin (xs [ i ]≔ ys 0F [ j ]≔ ys 1F) k ≡⟨ updateAt-minimal _ _ _ k≢j ⟩ (xs [ i ]≔ ys 0F) k ≡⟨ updateAt-updates i _ ⟩ ys 0F ≈˘⟨ xsIJ≈ys 0F ⟩ xs k ∎ where open ≈ᴹ-Reasoning ... | no k≢i = ≈ᴹ.sym $ begin (xs [ i ]≔ ys 0F [ j ]≔ ys 1F) k ≡⟨ updateAt-minimal _ _ _ k≢j ⟩ (xs [ i ]≔ ys 0F) k ≡⟨ updateAt-minimal _ _ _ k≢i ⟩ xs k ∎ where open ≈ᴹ-Reasoning stepVecSpace xs ys i j i≢j (rec {ys = zs} (swapOp p q p≢q) xy≈ⱽys swapZsYs) = rec (swapOp i′ j′ (proj₁ (helper p q p≢q swapZsYs))) (stepVecSpace _ _ _ _ i≢j xy≈ⱽys) (proj₂ (helper p q p≢q swapZsYs)) where open ≈ᴹ-Reasoning i′ = v→ij p i j j′ = v→ij q i j helper : (p q : Fin 2) (p≢q : p ≢ q) (let i′ = v→ij p i j) (let j′ = v→ij q i j) (let ws = xs [ i ]≔ zs 0F [ j ]≔ zs 1F) → swapV zs p q ≋ ys → i′ ≢ j′ × swapV ws i′ j′ ≋ xs [ i ]≔ ys 0F [ j ]≔ ys 1F helper 0F 0F p≢q _ = contradiction ≡.refl p≢q helper 1F 1F p≢q _ = contradiction ≡.refl p≢q proj₁ (helper 0F 1F p≢q _) = i≢j proj₁ (helper 1F 0F p≢q _) = i≢j ∘ ≡.sym proj₂ (helper 0F 1F p≢q sZs≋ys) k with k ≟ i | k ≟ j ... | yes refl | yes refl = contradiction ≡.refl i≢j ... | yes refl | no k≢j = begin (_ [ j ]≔ _) k ≡⟨ updateAt-minimal _ j _ k≢j ⟩ (_ [ k ]≔ _) k ≡⟨ updateAt-updates k _ ⟩ (_ [ j ]≔ _) j ≡⟨ updateAt-updates j _ ⟩ zs 1F ≈⟨ sZs≋ys 0F ⟩ ys 0F ≡˘⟨ updateAt-updates i _ ⟩ (xs [ i ]≔ ys 0F) k ≡˘⟨ updateAt-minimal _ j _ k≢j ⟩ (xs [ i ]≔ ys 0F [ j ]≔ ys 1F) k ∎ ... | no k≢i | yes refl = begin (_ [ k ]≔ _) k ≡⟨ updateAt-updates k _ ⟩ (_ [ k ]≔ _) i ≡⟨ updateAt-minimal _ k _ (k≢i ∘ ≡.sym) ⟩ (_ [ i ]≔ _) i ≡⟨ updateAt-updates i _ ⟩ zs 0F ≈⟨ sZs≋ys _ ⟩ ys 1F ≡˘⟨ updateAt-updates k _ ⟩ (_ [ k ]≔ _) k ∎ ... | no k≢i | no k≢j = begin (_ [ j ]≔ _) k ≡⟨ updateAt-minimal _ j _ k≢j ⟩ (_ [ i ]≔ _) k ≡⟨ updateAt-minimal _ i _ k≢i ⟩ (_ [ j ]≔ _) k ≡⟨ updateAt-minimal _ j _ k≢j ⟩ (_ [ i ]≔ _) k ≡⟨ updateAt-minimal _ i _ k≢i ⟩ xs k ≡˘⟨ updateAt-minimal _ i _ k≢i ⟩ (_ [ i ]≔ _) k ≡˘⟨ updateAt-minimal _ j _ k≢j ⟩ (_ [ j ]≔ _) k ∎ proj₂ (helper 1F 0F p≢q sZs≋ys) k with k ≟ i | k ≟ j ... | yes refl | yes refl = contradiction ≡.refl i≢j ... | yes refl | no k≢j = begin (_ [ k ]≔ _) k ≡⟨ updateAt-updates k _ ⟩ (_ [ j ]≔ _) j ≡⟨ updateAt-updates j _ ⟩ zs 1F ≈⟨ sZs≋ys _ ⟩ ys 0F ≡˘⟨ updateAt-updates k _ ⟩ (_ [ k ]≔ _) k ≡˘⟨ updateAt-minimal _ j _ k≢j ⟩ (_ [ j ]≔ _) k ∎ ... | no k≢i | yes refl = begin (_ [ i ]≔ _) k ≡⟨ updateAt-minimal _ i _ k≢i ⟩ (_ [ k ]≔ _) k ≡⟨ updateAt-updates k _ ⟩ (_ [ k ]≔ _) i ≡⟨ updateAt-minimal _ k _ (k≢i ∘ ≡.sym) ⟩ (_ [ i ]≔ _) i ≡⟨ updateAt-updates i _ ⟩ zs 0F ≈⟨ sZs≋ys _ ⟩ ys 1F ≡˘⟨ updateAt-updates k _ ⟩ (_ [ k ]≔ _) k ∎ ... | no k≢i | no k≢j = begin (_ [ i ]≔ _) k ≡⟨ updateAt-minimal _ i _ k≢i ⟩ (_ [ j ]≔ _) k ≡⟨ updateAt-minimal _ j _ k≢j ⟩ (_ [ j ]≔ _) k ≡⟨ updateAt-minimal _ j _ k≢j ⟩ (_ [ i ]≔ _) k ≡⟨ updateAt-minimal _ i _ k≢i ⟩ xs k ≡˘⟨ updateAt-minimal _ i _ k≢i ⟩ (_ [ i ]≔ _) k ≡˘⟨ updateAt-minimal _ j _ k≢j ⟩ (_ [ j ]≔ _) k ∎ stepVecSpace {n} xs ys i j i≢j (rec {ys = zs} (addCons p q p≢q r) xy≈ⱽys addZsYs) = rec (addCons i′ j′ (helper p q p≢q addZsYs .proj₁) r) (stepVecSpace _ _ _ _ i≢j xy≈ⱽys) (helper p q p≢q addZsYs .proj₂) where open ≈ᴹ-Reasoning i′ = v→ij p i j j′ = v→ij q i j helper : (p q : Fin 2) (p≢q : p ≢ q) (let i′ = v→ij p i j) (let j′ = v→ij q i j) (let ws = xs [ i ]≔ zs 0F [ j ]≔ zs 1F) → zs [ q ]← r *[ p ] ≋ ys → i′ ≢ j′ × ws [ j′ ]← r *[ i′ ] ≋ xs [ i ]≔ ys 0F [ j ]≔ ys 1F helper 0F 0F p≢q = contradiction ≡.refl p≢q helper 1F 1F p≢q = contradiction ≡.refl p≢q proj₁ (helper 0F 1F p≢q _) = i≢j proj₁ (helper 1F 0F p≢q _) = i≢j ∘ ≡.sym proj₂ (helper 0F 1F _ zs≋ys) k with j ≟ k | k ≟ i ... | yes refl | yes refl = contradiction ≡.refl i≢j ... | yes refl | no k≢i = begin (xs [ i ]≔ zs 0F [ k ]≔ zs 1F) k +ᴹ r *ₗ (xs [ i ]≔ zs 0F [ k ]≔ zs 1F) i ≈⟨ +ᴹ-cong (≈ᴹ-reflexive (updateAt-updates k _)) (*ₗ-congˡ (≈ᴹ-reflexive (≡.trans (updateAt-minimal _ k _ (k≢i ∘ ≡.sym)) (updateAt-updates i xs)))) ⟩ zs 1F +ᴹ r *ₗ zs 0F ≈⟨ zs≋ys 1F ⟩ ys 1F ≡˘⟨ updateAt-updates k _ ⟩ (xs [ i ]≔ ys 0F [ j ]≔ ys 1F) k ∎ ... | no j≢k | yes refl = begin (xs [ i ]≔ zs 0F [ j ]≔ zs 1F) k ≡⟨ updateAt-minimal _ j _ (j≢k ∘ ≡.sym) ⟩ (xs [ i ]≔ zs 0F) k ≡⟨ updateAt-updates k xs ⟩ zs 0F ≈⟨ zs≋ys 0F ⟩ ys 0F ≡˘⟨ updateAt-updates k xs ⟩ (xs [ i ]≔ ys 0F) k ≡˘⟨ updateAt-minimal _ j _ (j≢k ∘ ≡.sym) ⟩ (xs [ i ]≔ ys 0F [ j ]≔ ys 1F) k ∎ ... | no j≢k | no k≢i = begin (xs [ i ]≔ zs 0F [ j ]≔ zs 1F) k ≡⟨ updateAt-minimal _ j _ (j≢k ∘ ≡.sym) ⟩ (xs [ i ]≔ zs 0F) k ≡⟨ updateAt-minimal _ i _ k≢i ⟩ xs k ≡˘⟨ updateAt-minimal _ i _ k≢i ⟩ (xs [ i ]≔ ys 0F) k ≡˘⟨ updateAt-minimal _ j _ (j≢k ∘ ≡.sym) ⟩ (xs [ i ]≔ ys 0F [ j ]≔ ys 1F) k ∎ proj₂ (helper 1F 0F p≢q zs≋ys) k with i ≟ k | k ≟ j ... | yes refl | yes refl = contradiction ≡.refl i≢j ... | yes refl | no k≢j = begin (xs [ i ]≔ zs 0F [ j ]≔ zs 1F) i +ᴹ r *ₗ (xs [ i ]≔ zs 0F [ j ]≔ zs 1F) j ≈⟨ +ᴹ-cong (≈ᴹ-reflexive (≡.trans (updateAt-minimal _ j _ k≢j) (updateAt-updates i _))) (*ₗ-congˡ (≈ᴹ-reflexive (updateAt-updates j _))) ⟩ zs 0F +ᴹ r *ₗ zs 1F ≈⟨ zs≋ys 0F ⟩ ys 0F ≡˘⟨ updateAt-updates i _ ⟩ (xs [ i ]≔ ys 0F) i ≡˘⟨ updateAt-minimal _ j _ k≢j ⟩ (xs [ i ]≔ ys 0F [ j ]≔ ys 1F) i ∎ ... | no i≢k | yes refl = begin (xs [ i ]≔ zs 0F [ j ]≔ zs 1F) k ≡⟨ updateAt-updates k _ ⟩ zs 1F ≈⟨ zs≋ys 1F ⟩ ys 1F ≡˘⟨ updateAt-updates k _ ⟩ (xs [ i ]≔ ys 0F [ j ]≔ ys 1F) k ∎ ... | no i≢k | no k≢j = begin (xs [ i ]≔ zs 0F [ j ]≔ zs 1F) k ≡⟨ updateAt-minimal _ j _ k≢j ⟩ (xs [ i ]≔ zs 0F) k ≡⟨ updateAt-minimal _ i _ (i≢k ∘ ≡.sym) ⟩ xs k ≡˘⟨ updateAt-minimal _ i _ (i≢k ∘ ≡.sym) ⟩ (xs [ i ]≔ ys 0F) k ≡˘⟨ updateAt-minimal _ j _ k≢j ⟩ (xs [ i ]≔ ys 0F [ j ]≔ ys 1F) k ∎ open _reaches_ renaming (ys to ws; xs*ys≈x to xs*ws≈x) open _≋ⱽ_ open CMonoidSolver +ᴹ-commutativeMonoid hiding (_≟_) ≈ⱽ⇒⊆ⱽ : xs ≈ⱽ ys → xs ⊆ⱽ ys ws (≈ⱽ⇒⊆ⱽ (idR x) record { ys = ys ; xs*ys≈x = xs*ys≈x }) = ys xs*ws≈x (≈ⱽ⇒⊆ⱽ (idR {xs = xs} {ys = zs} xs≈zs) {x} record { ys = ys ; xs*ys≈x = xs*zs≈x }) = begin ∑ (ys *ᵣ zs) ≈˘⟨ ∑Ext (*ₗ-congˡ ∘ xs≈zs) ⟩ ∑ (ys *ᵣ xs) ≈⟨ xs*zs≈x ⟩ x ∎ where open ≈ᴹ-Reasoning ws (≈ⱽ⇒⊆ⱽ (rec (swapOp p q p≢q) xs≈ⱽys swap≈ys) {x} reach@record { ys = ys ; xs*ys≈x = xs*ys≈x }) = swapV (≈ⱽ⇒⊆ⱽ xs≈ⱽys reach .ws) p q xs*ws≈x (≈ⱽ⇒⊆ⱽ {n} {ys = yss} (rec {xs = xs} {zs} (swapOp p q p≢q) xs≈ⱽys swap≈ys) {x} reach@record { ys = ys ; xs*ys≈x = xs*ys≈x }) = begin ∑ (sws *ᵣ yss) ≈˘⟨ ∑Ext (*ₗ-congˡ ∘ swap≈ys) ⟩ ∑ (sws *ᵣ swapV zs p q) ≈⟨ ∑Ext {n} sameness ⟩ ∑ (swapV (wss *ᵣ zs) p q) ≈⟨ ∑Swap (wss *ᵣ zs) p q ⟩ ∑ (wss *ᵣ zs) ≈⟨ help .xs*ws≈x ⟩ x ∎ where open ≈ᴹ-Reasoning eqn = ≈ⱽ⇒⊆ⱽ xs≈ⱽys help = eqn reach wss = ws help sws = swapV wss p q wssZs = wss *ᵣ zs sameness : sws *ᵣ swapV zs p q ≋ swapV (wss *ᵣ zs) p q sameness k = begin swapV wss p q k *ₗ swapV zs p q k ≈⟨ *ₗ-congʳ (reflexive (vecUpdates≡reflectBool-theo2 wss indices valuesWss k)) ⟩ evalFromPosition valuesWss (wss k) evaluatedWss *ₗ swapV zs p q k ≈⟨ *ₗ-congˡ (≈ᴹ-reflexive (vecUpdates≡reflectBool-theo2 zs indices val2 k)) ⟩ _ *ₗ _ ≈⟨ helper _ (vBoolFromIndices indices k .proj₂) ⟩ _ ≈˘⟨ ≈ᴹ-reflexive (vecUpdates≡reflectBool-theo2 wssZs indices val3 k) ⟩ swapV wssZs p q k ∎ where indices = q :: p :: V.[] valuesWss = wss p :: wss q :: V.[] evaluatedWss = firstTrue $ proj₁ $ vBoolFromIndices indices k val2 = zs p :: zs q :: V.[] val3 = wssZs p :: wssZs q :: V.[] helper : ∀ vBool (vType : VecWithType (λ (ind , b) → Reflects (k ≡ ind) b) $ V.zip indices vBool) → evalFromPosition valuesWss (wss k) (firstTrue vBool) *ₗ evalFromPosition val2 (zs k) (firstTrue vBool) ≈ᴹ evalFromPosition val3 (wssZs k) (firstTrue vBool) helper (true :: _) (ofʸ ≡.refl :: _) = ≈ᴹ-refl helper (false :: true :: V.[]) (ofⁿ _ :: ofʸ ≡.refl :: []) = ≈ᴹ-refl helper (false :: false :: V.[]) (ofⁿ _ :: ofⁿ _ :: []) = ≈ᴹ-refl ws (≈ⱽ⇒⊆ⱽ {ys = yss} (rec {xs = xs} {zs} (addCons p q p≢q r) xs≈ⱽys zs≋ys) x∈xs) = let wss = ws (≈ⱽ⇒⊆ⱽ xs≈ⱽys x∈xs) in wss [ p ]≔ (wss p - wss q * r) xs*ws≈x (≈ⱽ⇒⊆ⱽ {n} {ys = yss} (rec {xs = xs} {zs} (addCons p q p≢q r) xs≈ⱽys zs≋ys) {x} x∈xs) = begin ∑ (sws *ᵣ yss) ≈˘⟨ ∑Ext (*ₗ-congˡ ∘ zs≋ys) ⟩ ∑ (sws *ᵣ (zs [ q ]← r *[ p ])) ≈⟨ sameness ⟩ ∑ (wss *ᵣ zs) ≈⟨ help .xs*ws≈x ⟩ x ∎ where open ≈ᴹ-Reasoning module ∼ = ≈-Reasoning R.setoid help = ≈ⱽ⇒⊆ⱽ xs≈ⱽys x∈xs wss = ws help sws : Vector R n sws = wss [ p ]≔ (wss p - wss q * r) q≢p = p≢q ∘ ≡.sym wss*zs = wss *ᵣ zs sws*zs = sws *ᵣ (zs [ q ]← r *[ p ]) zsPq≡ : (zs [ q ]← r *[ p ]) q ≡ zs q +ᴹ r *ₗ zs p zsPq≡ rewrite dec-yes (q ≟ q) ≡.refl .proj₂ = ≡.refl sws*zsP≡ : sws*zs p ≡ sws p *ₗ zs p sws*zsP≡ rewrite dec-no (q ≟ p) (p≢q ∘ ≡.sym) = ≡.refl sws*zsK≡ : ∀ {k} → k ≢ q → sws*zs k ≡ sws k *ₗ zs k sws*zsK≡ {k} k≢q rewrite dec-no (q ≟ k) (k≢q ∘ ≡.sym) = ≡.refl sws*zsQ : sws*zs q ≈ᴹ sws q *ₗ zs q +ᴹ (sws q * r) *ₗ zs p sws*zsQ = begin _ ≈⟨ *ₗ-congˡ (≈ᴹ-reflexive zsPq≡) ⟩ sws q *ₗ (zs q +ᴹ r *ₗ zs p) ≈⟨ *ₗ-distribˡ _ _ _ ⟩ sws q *ₗ zs q +ᴹ sws q *ₗ r *ₗ zs p ≈˘⟨ +ᴹ-congˡ (*ₗ-assoc _ _ _) ⟩ _ ∎ swsP : sws p + sws q * r ≈ wss p swsP = ∼.begin sws p + sws q * r ∼.≈⟨ +-cong (reflexive (updateAt-updates p wss)) (*-congʳ (reflexive (updateAt-minimal q p _ q≢p))) ⟩ wss p - wss q * r + wss q * r ∼.≈⟨ R.+-assoc (wss p) _ _ ⟩ wss p + (- (wss q * r) + wss q * r) ∼.≈⟨ +-congˡ (-‿inverseˡ _) ⟩ wss p + 0# ∼.≈⟨ R.+-identityʳ _ ⟩ wss p ∼.∎ swsQ : sws q ≈ wss q swsQ = reflexive (updateAt-minimal q p wss q≢p) lemma₁ : (sws p + sws q * r) *ₗ zs p +ᴹ sws q *ₗ zs q ≈ᴹ wss p *ₗ zs p +ᴹ wss q *ₗ zs q lemma₁ = +ᴹ-cong (*ₗ-congʳ swsP) (*ₗ-congʳ swsQ) theo₀ : sws*zs p +ᴹ sws*zs q ≈ᴹ wss*zs p +ᴹ wss*zs q theo₀ = begin _ ≈⟨ +ᴹ-cong (≈ᴹ-reflexive sws*zsP≡) sws*zsQ ⟩ sws p *ₗ zs p +ᴹ (sws q *ₗ zs q +ᴹ (sws q * r) *ₗ zs p) ≈⟨ solve 3 (λ a b c → a ⊕ b ⊕ c ⊜ (a ⊕ c) ⊕ b) ≈ᴹ-refl (sws p *ₗ zs p) (sws q *ₗ zs q) ((sws q * r) *ₗ zs p) ⟩ sws p *ₗ zs p +ᴹ (sws q * r) *ₗ zs p +ᴹ sws q *ₗ zs q ≈˘⟨ +ᴹ-congʳ (*ₗ-distribʳ (zs p) _ _) ⟩ (sws p + sws q * r) *ₗ zs p +ᴹ sws q *ₗ zs q ≈⟨ lemma₁ ⟩ _ ∎ theo₁ : sws*zs p +ᴹ (sws*zs [ p ]≔ 0ᴹ) q ≈ᴹ wss*zs p +ᴹ (wss*zs [ p ]≔ 0ᴹ) q theo₁ = begin _ +ᴹ _ ≈⟨ +ᴹ-congˡ (≈ᴹ-reflexive (updateAt-minimal q p sws*zs q≢p)) ⟩ _ +ᴹ sws*zs q ≈⟨ theo₀ ⟩ _ +ᴹ wss*zs q ≈˘⟨ +ᴹ-congˡ (≈ᴹ-reflexive (updateAt-minimal q p wss*zs q≢p)) ⟩ _ +ᴹ _ ∎ theo₂ : sws*zs [ p ]≔ 0ᴹ [ q ]≔ 0ᴹ ≋ wss*zs [ p ]≔ 0ᴹ [ q ]≔ 0ᴹ theo₂ k = helper _ $ vBoolFromIndices indices k .proj₂ where indices = q :: p :: V.[] v0 = 0ᴹ :: 0ᴹ :: V.[] helper : ∀ vBool (vType : VecIndBool indices vBool k) → (sws*zs [ p ]≔ 0ᴹ [ q ]≔ 0ᴹ) k ≈ᴹ (wss*zs [ p ]≔ 0ᴹ [ q ]≔ 0ᴹ) k helper (true :: _) vt@(ofʸ ≡.refl :: _) = begin _ ≡⟨ vecUpdates≡reflectBool-theo sws*zs v0 k vt ⟩ 0ᴹ ≡˘⟨ vecUpdates≡reflectBool-theo wss*zs v0 k vt ⟩ _ ∎ helper (false :: true :: _) vt@(_ :: _ :: _) = ≈ᴹ-reflexive (≡.trans (vecUpdates≡reflectBool-theo sws*zs v0 k vt) (≡.sym $ vecUpdates≡reflectBool-theo wss*zs v0 k vt)) helper (false :: false :: V.[]) vt@(ofⁿ k≢q :: ofⁿ k≢p :: []) = begin _ ≡⟨ vecUpdates≡reflectBool-theo sws*zs v0 k vt ⟩ sws*zs k ≡⟨ sws*zsK≡ k≢q ⟩ _ *ₗ zs k ≈⟨ *ₗ-congʳ (reflexive (updateAt-minimal k p _ k≢p)) ⟩ wss k *ₗ zs k ≡˘⟨ vecUpdates≡reflectBool-theo wss*zs v0 k vt ⟩ _ ∎ sameness : ∑ (sws *ᵣ (zs [ q ]← r *[ p ])) ≈ᴹ ∑ (wss *ᵣ zs) sameness = begin ∑ sws*zs ≈⟨ ∑Remove₂ sws*zs p ⟩ sws*zs p +ᴹ _ ≈⟨ +ᴹ-congˡ (∑Remove₂ {n} _ q) ⟩ sws*zs p +ᴹ (_ +ᴹ _) ≈˘⟨ +ᴹ-assoc (sws*zs p) _ _ ⟩ sws*zs p +ᴹ (sws*zs [ p ]≔ 0ᴹ) q +ᴹ _ ≈⟨ +ᴹ-cong theo₁ (∑Ext theo₂) ⟩ wss*zs p +ᴹ (wss*zs [ p ]≔ 0ᴹ) q +ᴹ _ ≈⟨ +ᴹ-assoc _ _ _ ⟩ wss*zs p +ᴹ (_ +ᴹ _) ≈˘⟨ +ᴹ-congˡ (∑Remove₂ {n} _ q) ⟩ wss*zs p +ᴹ _ ≈˘⟨ ∑Remove₂ wss*zs p ⟩ ∑ wss*zs ∎ ≈ⱽ-sym : Symmetric (_≈ⱽ_ {n = n}) ≈ⱽ-sym (idR xs≈ys) = idR (≋-sym xs≈ys) ≈ⱽ-sym {x = xs} {zs} (rec {ys = ys} (MBase.swapOp p q p≢q) xs≈ⱽys fMops) = ≈ⱽ-trans (rec (swapOp p q p≢q) (idR (≋-sym fMops)) λ i → ≈ᴹ-reflexive (swap-involute ys p q i)) ys≈ⱽxs where ys≈ⱽxs = ≈ⱽ-sym xs≈ⱽys ≈ⱽ-sym {x = xs} {zs} (rec {ys = ys} (MBase.addCons p q p≢q r) xs≈ⱽys fMops) = ≈ⱽ-trans (rec (addCons p q p≢q (- r)) (idR (≋-sym fMops)) sameVec) ys≈ⱽxs where ys≈ⱽxs = ≈ⱽ-sym xs≈ⱽys sameVec : ((ys [ q ]← r *[ p ]) [ q ]← - r *[ p ]) ≋ ys sameVec i with q ≟ i ... | no q≢i rewrite dec-no (q ≟ i) q≢i | dec-no (q ≟ i) q≢i = ≈ᴹ-refl ... | yes ≡.refl rewrite dec-yes (i ≟ i) ≡.refl .proj₂ | dec-no (i ≟ p) (p≢q ∘ ≡.sym) = begin ys i +ᴹ r *ₗ ys p +ᴹ - r *ₗ ys p ≈⟨ +ᴹ-assoc _ _ _ ⟩ ys i +ᴹ (r *ₗ ys p +ᴹ - r *ₗ ys p) ≈⟨ +ᴹ-congˡ (begin _ ≈˘⟨ *ₗ-distribʳ (ys p) r (- r) ⟩ (r - r) *ₗ ys p ≈⟨ *ₗ-congʳ (-‿inverseʳ _) ⟩ 0# *ₗ ys p ≈⟨ *ₗ-zeroˡ _ ⟩ _ ∎ ) ⟩ ys i +ᴹ 0ᴹ ≈⟨ +ᴹ-identityʳ _ ⟩ ys i ∎ where open ≈ᴹ-Reasoning ≈ⱽ⇒⊇ⱽ : xs ≈ⱽ ys → xs ⊇ⱽ ys ≈ⱽ⇒⊇ⱽ = ≈ⱽ⇒⊆ⱽ ∘ ≈ⱽ-sym ≈ⱽ⇒≋ⱽ : xs ≈ⱽ ys → xs ≋ⱽ ys ≈ⱽ⇒≋ⱽ xs≈ⱽys = record { fwd = ≈ⱽ⇒⊆ⱽ xs≈ⱽys ; bwd = ≈ⱽ⇒⊇ⱽ xs≈ⱽys }