open import Algebra.DecidableField module SystemEquations.UniqueSolution {c ℓ₁ ℓ₂} (dField : DecidableField c ℓ₁ ℓ₂) where open import Algebra open import Algebra.Apartness open import Algebra.Module open import Function open import Data.Bool using (Bool; true; false; if_then_else_) open import Data.Product open import Data.Maybe using (Is-just; Maybe; just; nothing) open import Data.Sum renaming ([_,_] to [_∙_]) open import Data.Empty open import Data.Nat as ℕ using (ℕ; _∸_) open import Data.Nat.Properties as ℕ using (module ≤-Reasoning) open import Data.Fin as F using (Fin; suc; splitAt; fromℕ; toℕ; inject₁) open import Data.Fin.Properties as F open import Data.Fin.Patterns open import Data.Vec.Functional open import Relation.Nullary open import Fin.Base open import Fin.Properties open import Vector.Structures open import Vector.Properties open import Algebra.Matrix.Structures open import SystemEquations.Definitions dField open import MatrixFuncNormalization.Definitions dField import Algebra.Module.Definition as MDefinition import Algebra.Module.Props as MProps′ open import Algebra.BigOps open DecidableField dField renaming (Carrier to F) open import Algebra.Apartness.Properties.HeytingCommutativeRing heytingCommutativeRing open import Algebra.Properties.Ring ring open VRing rawRing open import Algebra.Module.Instances.AllVecLeftModule ring using (leftModule) open MRing rawRing using (Matrix; _++v_) open import Algebra.Module.Instances.CommutativeRing commutativeRing open import Data.Vec.Functional.Relation.Binary.Equality.Setoid setoid open import Relation.Binary.PropositionalEquality as ≡ using (_≡_; _≢_; subst; subst₂; cong) open import Relation.Binary.Reasoning.Setoid setoid open import Algebra.Solver.CommutativeMonoid +-commutativeMonoid hiding (id) open import Algebra.Module.PropsVec commutativeRing open import SystemEquations.VecPiv dField open import MatrixFuncNormalization.MainTheo dField open import SystemEquations.Solving dField open import lbry open SumRing ring using (∑Ext; ∑0r; δ; ∑Mul1r; ∑Split) open MDef′ open MProps private variable m n p q : ℕ private lemma-a : ∀ {a b} → a * (- b) + b * a ≈ 0# lemma-a = trans (+-congʳ (trans (*-comm _ _) (sym (-‿distribˡ-* _ _)))) (-‿inverseˡ _) module _ where open SystemEquations open _≋ⱽ_ sameSolutions≈ : {sx : SystemEquations n m} {sy : SystemEquations p m} → A++b sy ≋ⱽ A++b sx → Solution sx → Solution sy sameSolutions≈ sy≋ⱽsx (noSol f) = noSol (f ∘ sameSolutionsS (sy≋ⱽsx .bwd) _) sameSolutions≈ {sx = sx} {sy} sy≋ⱽsx (sol _ _ (f , g)) = sol _ _ (sameSolutionsS (sy≋ⱽsx .fwd) _ ∘ f , g ∘ sameSolutionsS (sy≋ⱽsx .bwd) _) solveNormedEquationUnique : ∀ (sx : SystemEquations n m) (open SystemEquations sx) → MatrixIsNormed≁0≈1 A → ∃ IsSolutionAndUnique solveNormedEquationUnique {n} {m} sx ANormed = vAffine , vAffFamily , sameSolution where open SolvingNormedEquation sx ANormed sameSolution : SameSolution vAffine sameSolution {vSol} isSol = vecSol , vecSol≈vSol where vecSol : ∀ i → F vecSol = vSol ∘ pivRes vPivSame : ∀ i → Affine.eval (vAffine (pivs i)) vecSol ≈ vSol (pivs i) vPivSame i rewrite vSplit′-same pivs i pivsCrescent = begin ∑ {m ∸ n} (λ j → vSol _ * - A i (pivRes j)) + b i ≈˘⟨ +-congˡ (isSol i) ⟩ _ + ∑ {m} (λ j → A i j * vSol j) ≈˘⟨ +-congˡ (∑-pivs′-same pivs _ pivsCrescent) ⟩ _ + (∑ (λ j → A i (pivs j) * vSol (pivs j)) + ∑ {m ∸ n} (λ j → A i (pivRes j) * vSol (pivRes j))) ≈⟨ +-congˡ (+-comm _ _) ⟩ _ + (_ + _) ≈˘⟨ +-assoc _ _ _ ⟩ _ + _ + _ ≈˘⟨ +-congʳ (∑Split {m ∸ n} _ _) ⟩ ∑ {m ∸ n} (λ j → vSol (pivRes j) * - A i (pivRes j) + A i (pivRes j) * vSol (pivRes j)) + _ ≈⟨ +-congʳ (∑Ext {m ∸ n} λ _ → lemma-a ) ⟩ _ + _ ≈⟨ +-congʳ (∑0r (m ∸ n)) ⟩ 0# + _ ≈⟨ +-identityˡ _ ⟩ ∑ (λ j → A i (pivs j) * vSol (pivs j)) ≈⟨ ∑Ext (λ j → *-congʳ (AiPj≈δij i j)) ⟩ ∑ (λ j → δ i j * vSol (pivs j)) ≈⟨ ∑Mul1r _ i ⟩ vSol _ ∎ vRPivSame : ∀ i → Affine.eval (vAffine (pivRes i)) vecSol ≈ vSol (pivRes i) vRPivSame i rewrite vSplit′-rPivs pivs i pivsCrescent = begin ∑ {m ∸ n} (λ j → _ * _) + 0# ≈⟨ +-identityʳ _ ⟩ ∑ {m ∸ n} (λ j → _ * δ i j) ≈⟨ ∑Ext (λ j → *-comm _ (δ i j)) ⟩ ∑ {m ∸ n} (λ j → δ i j * _) ≈⟨ ∑Mul1r _ i ⟩ vSol _ ∎ vecSol≈vSol : (i : Fin m) → Affine.eval (vAffine i) vecSol ≈ vSol i vecSol≈vSol i with ∃-piv⊎pivRes′ pivs pivsCrescent i ... | inj₁ (x , x≡piv) rewrite ≡.sym x≡piv = vPivSame _ ... | inj₂ (x , x≡rPiv) rewrite ≡.sym x≡rPiv = vRPivSame _ solveNormedEquationNormUnique : ∀ (sx : SystemEquations n m) (open SystemEquations sx) → MatrixIsNormed≁0≈1 A++b → Solution solveNormedEquationNormUnique sx norm with systemNormedSplit sx norm | systemUnsolvable {sx = sx} | solveNormedEquationUnique sx ... | inj₁ x | b | _ = SystemEquations.noSol $ b x ... | inj₂ y | _ | c = SystemEquations.sol _ _ $ proj₂ $ c y solveUniqueSystemEquations : (sx : SystemEquations n m) (open SystemEquations sx) → Solution solveUniqueSystemEquations sx = sameSolutions≈ A++b≋ⱽs sol-prob where open SystemEquations sx open FromNormalization≁0≈1 (normalize≈1≁0 A++b) sYs = A++b⇒systemEquations ys open SystemEquations sYs using () renaming (Solution to SYs; A++b to A++b-ys) ys≋A++b-ys : ∀ i j → ys i j ≈ A++b-ys i j ys≋A++b-ys i j = reflexive (≡.sym (same-take ys i j)) A++b≋ⱽs : A++b ≋ⱽ A++b-ys A++b≋ⱽs = ≋ⱽ-trans xs≋ⱽys $ ≋ⱽ-reflexive ys≋A++b-ys sol-prob = solveNormedEquationNormUnique sYs $ ≈-norm ys≋A++b-ys ysNormed