{-# LANGUAGE FlexibleContexts #-}
module Math.LinearEquationSolver (
Solver(..)
, solveIntegerLinearEqs
, solveIntegerLinearEqsAll
, solveRationalLinearEqs
, solveRationalLinearEqsAll
) where
import Data.SBV
solveIntegerLinearEqs :: Solver
-> [[Integer]]
-> [Integer]
-> IO (Maybe [Integer])
solveIntegerLinearEqs :: Solver -> [[Integer]] -> [Integer] -> IO (Maybe [Integer])
solveIntegerLinearEqs Solver
cfg [[Integer]]
coeffs [Integer]
res = SatResult -> Maybe [Integer]
forall a b. (Modelable a, SatModel b) => a -> Maybe b
forall b. SatModel b => SatResult -> Maybe b
extractModel (SatResult -> Maybe [Integer])
-> IO SatResult -> IO (Maybe [Integer])
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap` SMTConfig -> Symbolic SBool -> IO SatResult
forall a. Satisfiable a => SMTConfig -> a -> IO SatResult
satWith (Solver -> SMTConfig
defaultSolverConfig Solver
cfg) Symbolic SBool
cs
where cs :: Symbolic SBool
cs = String -> [[Integer]] -> [Integer] -> Symbolic SBool
forall a.
(Ord a, Num a, Num (SBV a), SymVal a) =>
String -> [[a]] -> [a] -> Symbolic SBool
buildConstraints String
"solveIntegerLinearEqs" [[Integer]]
coeffs [Integer]
res
solveIntegerLinearEqsAll :: Solver
-> Int
-> [[Integer]]
-> [Integer]
-> IO [[Integer]]
solveIntegerLinearEqsAll :: Solver -> Int -> [[Integer]] -> [Integer] -> IO [[Integer]]
solveIntegerLinearEqsAll Solver
s Int
maxNo [[Integer]]
coeffs [Integer]
res = AllSatResult -> [[Integer]]
forall a. SatModel a => AllSatResult -> [a]
extractModels (AllSatResult -> [[Integer]]) -> IO AllSatResult -> IO [[Integer]]
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap` SMTConfig -> Symbolic SBool -> IO AllSatResult
forall a. Satisfiable a => SMTConfig -> a -> IO AllSatResult
allSatWith SMTConfig
cfg Symbolic SBool
cs
where cs :: Symbolic SBool
cs = String -> [[Integer]] -> [Integer] -> Symbolic SBool
forall a.
(Ord a, Num a, Num (SBV a), SymVal a) =>
String -> [[a]] -> [a] -> Symbolic SBool
buildConstraints String
"solveIntegerLinearEqsAll" [[Integer]]
coeffs [Integer]
res
cfg :: SMTConfig
cfg = (Solver -> SMTConfig
defaultSolverConfig Solver
s) {allSatMaxModelCount = Just maxNo}
solveRationalLinearEqs :: Solver
-> [[Rational]]
-> [Rational]
-> IO (Maybe [Rational])
solveRationalLinearEqs :: Solver -> [[Rational]] -> [Rational] -> IO (Maybe [Rational])
solveRationalLinearEqs Solver
cfg [[Rational]]
coeffs [Rational]
res = (([AlgReal] -> [Rational]) -> Maybe [AlgReal] -> Maybe [Rational]
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [AlgReal] -> [Rational]
from (Maybe [AlgReal] -> Maybe [Rational])
-> (SatResult -> Maybe [AlgReal]) -> SatResult -> Maybe [Rational]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SatResult -> Maybe [AlgReal]
forall a b. (Modelable a, SatModel b) => a -> Maybe b
forall b. SatModel b => SatResult -> Maybe b
extractModel) (SatResult -> Maybe [Rational])
-> IO SatResult -> IO (Maybe [Rational])
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap` SMTConfig -> Symbolic SBool -> IO SatResult
forall a. Satisfiable a => SMTConfig -> a -> IO SatResult
satWith (Solver -> SMTConfig
defaultSolverConfig Solver
cfg) Symbolic SBool
cs
where to :: [Rational] -> [AlgReal]
to = (Rational -> AlgReal) -> [Rational] -> [AlgReal]
forall a b. (a -> b) -> [a] -> [b]
map (Rational -> AlgReal
forall a. Fractional a => Rational -> a
fromRational :: Rational -> AlgReal)
from :: [AlgReal] -> [Rational]
from = (AlgReal -> Rational) -> [AlgReal] -> [Rational]
forall a b. (a -> b) -> [a] -> [b]
map (AlgReal -> Rational
forall a. Real a => a -> Rational
toRational :: AlgReal -> Rational)
cs :: Symbolic SBool
cs = String -> [[AlgReal]] -> [AlgReal] -> Symbolic SBool
forall a.
(Ord a, Num a, Num (SBV a), SymVal a) =>
String -> [[a]] -> [a] -> Symbolic SBool
buildConstraints String
"solveRationalLinearEqs" (([Rational] -> [AlgReal]) -> [[Rational]] -> [[AlgReal]]
forall a b. (a -> b) -> [a] -> [b]
map [Rational] -> [AlgReal]
to [[Rational]]
coeffs) ([Rational] -> [AlgReal]
to [Rational]
res)
solveRationalLinearEqsAll :: Solver
-> Int
-> [[Rational]]
-> [Rational]
-> IO [[Rational]]
solveRationalLinearEqsAll :: Solver -> Int -> [[Rational]] -> [Rational] -> IO [[Rational]]
solveRationalLinearEqsAll Solver
s Int
maxNo [[Rational]]
coeffs [Rational]
res = (([AlgReal] -> [Rational]) -> [[AlgReal]] -> [[Rational]]
forall a b. (a -> b) -> [a] -> [b]
map [AlgReal] -> [Rational]
from ([[AlgReal]] -> [[Rational]])
-> (AllSatResult -> [[AlgReal]]) -> AllSatResult -> [[Rational]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AllSatResult -> [[AlgReal]]
forall a. SatModel a => AllSatResult -> [a]
extractModels) (AllSatResult -> [[Rational]])
-> IO AllSatResult -> IO [[Rational]]
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap` SMTConfig -> Symbolic SBool -> IO AllSatResult
forall a. Satisfiable a => SMTConfig -> a -> IO AllSatResult
allSatWith SMTConfig
cfg Symbolic SBool
cs
where to :: [Rational] -> [AlgReal]
to = (Rational -> AlgReal) -> [Rational] -> [AlgReal]
forall a b. (a -> b) -> [a] -> [b]
map (Rational -> AlgReal
forall a. Fractional a => Rational -> a
fromRational :: Rational -> AlgReal)
from :: [AlgReal] -> [Rational]
from = (AlgReal -> Rational) -> [AlgReal] -> [Rational]
forall a b. (a -> b) -> [a] -> [b]
map (AlgReal -> Rational
forall a. Real a => a -> Rational
toRational :: AlgReal -> Rational)
cs :: Symbolic SBool
cs = String -> [[AlgReal]] -> [AlgReal] -> Symbolic SBool
forall a.
(Ord a, Num a, Num (SBV a), SymVal a) =>
String -> [[a]] -> [a] -> Symbolic SBool
buildConstraints String
"solveRationalLinearEqsAll" (([Rational] -> [AlgReal]) -> [[Rational]] -> [[AlgReal]]
forall a b. (a -> b) -> [a] -> [b]
map [Rational] -> [AlgReal]
to [[Rational]]
coeffs) ([Rational] -> [AlgReal]
to [Rational]
res)
cfg :: SMTConfig
cfg = (Solver -> SMTConfig
defaultSolverConfig Solver
s) {allSatMaxModelCount = Just maxNo}
buildConstraints :: (Ord a, Num a, Num (SBV a), SymVal a) => String -> [[a]] -> [a] -> Symbolic SBool
buildConstraints :: forall a.
(Ord a, Num a, Num (SBV a), SymVal a) =>
String -> [[a]] -> [a] -> Symbolic SBool
buildConstraints String
f [[a]]
coeffs [a]
res
| Int
m Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 Bool -> Bool -> Bool
|| (Int -> Bool) -> [Int] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
n) [Int]
ns Bool -> Bool -> Bool
|| Int
m Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
res
= String -> Symbolic SBool
forall a. HasCallStack => String -> a
error (String -> Symbolic SBool) -> String -> Symbolic SBool
forall a b. (a -> b) -> a -> b
$ String
f String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
": received ill-formed input."
| Bool
True
= do xs <- Int -> Symbolic [SBV a]
forall a. SymVal a => Int -> Symbolic [SBV a]
mkFreeVars Int
n
let rowEq [SBV a]
row SBV a
r = [SBV a] -> SBV a
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ((SBV a -> SBV a -> SBV a) -> [SBV a] -> [SBV a] -> [SBV a]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith SBV a -> SBV a -> SBV a
forall a. Num a => a -> a -> a
(*) [SBV a]
xs [SBV a]
row) SBV a -> SBV a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV a
r
solve $ zipWith rowEq (map (map literal) coeffs) (map literal res)
where m :: Int
m = [[a]] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [[a]]
coeffs
Int
n:[Int]
ns = ([a] -> Int) -> [[a]] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [[a]]
coeffs