module Numeric.Limp.Solvers.Cbc.MatrixRepr where
import Numeric.Limp.Canon
import Numeric.Limp.Rep
import Data.Either (isLeft)
import qualified Data.Map as M
import qualified Data.Set as S
import qualified Data.Vector.Storable as V
import Data.Vector.Storable (Vector)
import Numeric.Limp.Solvers.Cbc.Internal.Wrapper
data MatrixRepr
= MatrixRepr
{ _starts :: Vector Int
, _inds :: Vector Int
, _vals :: Vector Double
, _colLs :: Vector Double
, _colUs :: Vector Double
, _obj :: Vector Double
, _rowLs :: Vector Double
, _rowUs :: Vector Double
, _ints :: Vector Int
}
deriving Show
matrixReprOfProgram :: (Ord z, Ord r) => Program z r IntDouble -> MatrixRepr
matrixReprOfProgram p
= MatrixRepr starts inds vals colLs colUs obj rowLs rowUs ints
where
starts
= V.fromList
$ scanl (+) 0
$ map length nestedindvals
inds = V.fromList $ map fst $ concat nestedindvals
vals = V.fromList $ map snd $ concat nestedindvals
nestedindvals = map getIndVals $ S.toList vs
colLs = V.fromList $ map (fst . boundsOfVar) $ S.toList vs
colUs = V.fromList $ map (snd . boundsOfVar) $ S.toList vs
obj
= case _objective p of
Linear m
-> V.fromList
$ map (maybe 0 unwrapR . flip M.lookup m) $ S.toList vs
rowLs = V.fromList $ map (fst . boundsOfCon) cons
rowUs = V.fromList $ map (snd . boundsOfCon) cons
ints = V.fromList $ map snd $ filter (isLeft . fst) $ S.toList vs `zip` [0..]
vs = varsOfProgram p
cons = case _constraints p of
Constraint cs -> cs
getIndVals v
= concatMap (\(C1 _ (Linear m) _, ix) ->
case M.lookup v m of
Nothing -> []
Just mul -> [(ix, unwrapR mul)]) (cons `zip` [0..])
boundsOfVar v
= case M.lookup v $ _bounds p of
Nothing -> (lower Nothing, upper Nothing)
Just (l,u) -> (lower l, upper u)
boundsOfCon (C1 l _ u) = (lower l, upper u)
upper = maybe getCoinDblMax unwrapR
lower = maybe (-getCoinDblMax) unwrapR
makeAssignment :: (Ord z, Ord r) => Program z r IntDouble -> Vector Double -> Assignment z r IntDouble
makeAssignment p values
= go M.empty M.empty
$ S.toList (varsOfProgram p) `zip` V.toList values
where
go mz mr []
= Assignment mz mr
go mz mr ((Left z, val) : rest)
= go (M.insert z (Z $ truncate val) mz) mr rest
go mz mr ((Right r, val) : rest)
= go mz (M.insert r (R $ val) mr) rest