open import Algebra.DecidableField module SystemEquations.Data {c ℓ₁ ℓ₂} (dField : DecidableField c ℓ₁ ℓ₂) where open import Level open import Function open import Data.Empty open import Data.Bool open import Data.Unit.Polymorphic open import Data.Nat hiding (_⊔_) open import Data.Maybe as Maybe open import Data.Product open import Data.Vec open import Data.Vec.Functional using (fromVec; toVec) open import Vec.Base open import Algebra.MatrixData.Base open DecidableField dField renaming (Carrier to F) open import SystemEquations.Definitions dField as SE using () open import SystemEquations.UniqueSolution dField private variable m n : ℕ infix 6 _+span_ record Affine (p : ℕ) : Set c where constructor vAff field coeff : Vec F p constant : F VecAffine : (nVars freeVars : ℕ) → Set c VecAffine nVars freeVars = Vec (Affine freeVars) nVars unfoldConstants : VecAffine n m → Vec F n unfoldConstants [] = [] unfoldConstants (vAff coeff constant ∷ xs) = constant ∷ unfoldConstants xs unfoldVecs : VecAffine n m → Matrix F n m unfoldVecs [] = [] unfoldVecs (vAff coeff constant ∷ xs) = coeff ∷ unfoldVecs xs record AffineTranspose (nVars freeVars : ℕ) : Set c where constructor _+span_ field constants : Vec F nVars coeffs : Matrix F freeVars nVars open AffineTranspose vAff→vAffT : VecAffine n m → AffineTranspose n m vAff→vAffT xs = unfoldConstants xs +span transpose (unfoldVecs xs) record SystemEquations (rows cols : ℕ) : Set c where constructor system field A : Matrix F rows cols b : Vec F rows data Solution (n : ℕ) : Set (c ⊔ ℓ₁) where sol : ∀ p (affine : VecAffine n p) → Solution n noSol : Solution n HasSolution? : Solution n → Bool HasSolution? (sol _ _) = true HasSolution? noSol = false HasNoSolution? : Solution n → Bool HasNoSolution? = not ∘ HasSolution? HasNoSolution : Solution n → Set HasNoSolution = T ∘ HasNoSolution? HasUniqueSolution? : Solution n → Bool HasUniqueSolution? (sol ℕ.zero affine) = true HasUniqueSolution? (sol (ℕ.suc p) affine) = false HasUniqueSolution? noSol = false HasUniqueSolution : Solution n → Set HasUniqueSolution = T ∘ HasUniqueSolution? solve : SystemEquations n m → Solution m solve se = help solF where open SystemEquations se seF = SE.system (matrixData→Fun A) (fromVec b) module SeF = SE.SystemEquations seF solF = solveUniqueSystemEquations seF help : SeF.Solution → Solution _ help (SE.SystemEquations.sol p affine x) = sol p $ tabulate $ help2 ∘ affine where help2 : _ → _ help2 (SE.vAff coeff constant) = vAff (toVec coeff) constant help (SE.SystemEquations.noSol _) = noSol sizeSolutionT : Solution n → Set _ sizeSolutionT (sol _ _) = ℕ sizeSolutionT noSol = ⊤ sizeSolution : (solution : Solution n) → sizeSolutionT solution sizeSolution (sol p _) = p sizeSolution noSol = _ solMComplexT : Solution m → Set _ solMComplexT {m} (sol p affine) = Matrix F p m solMComplexT noSol = ⊤ solMComplex : (solution : Solution n) → solMComplexT solution solMComplex (sol p affine) = coeffs $ vAff→vAffT affine solMComplex noSol = _ solveComplex0 : (A : Matrix F n m) → solMComplexT $ solve $ system A $ repeat 0# solveComplex0 A = solMComplex $ solve $ system A $ repeat 0# solAllT : Solution m → Set c solAllT {m} (sol ℕ.zero affine) = Vec F m solAllT {m} (sol p@(ℕ.suc _) affine) = AffineTranspose m p solAllT noSol = ⊤ solAll : (solt : Solution m) → solAllT solt solAll (sol ℕ.zero affine) = unfoldConstants affine solAll (sol (ℕ.suc p) affine) = vAff→vAffT affine solAll noSol = _ solveAll : (A : Matrix F n m) (b : Vec F n) → solAllT $ solve $ system A b solveAll A b = solAll $ solve $ system A b