module Data.LinearProgram.GLPK.Solver (
GLPOpts(..),
simplexDefaults,
mipDefaults,
glpSolveVars,
RowValue(..),
glpSolveAll,
ReturnCode(..),
MsgLev(..),
BranchingTechnique(..),
BacktrackTechnique(..),
Preprocessing(..),
Cuts(..)) where
import Control.Monad
import Data.Map
import Data.LinearProgram.Spec
import Data.LinearProgram.GLPK.Common
data GLPOpts = SimplexOpts {msgLev :: MsgLev, tmLim :: !Int, presolve :: Bool} |
MipOpts {msgLev :: MsgLev, tmLim :: !Int, presolve :: Bool,
brTech :: BranchingTechnique, btTech :: BacktrackTechnique,
ppTech :: Preprocessing,
fpHeur :: Bool,
cuts :: [Cuts],
mipGap :: !Double}
data RowValue v c = RowVal {row :: !(Constraint v c), rowVal :: !Double}
simplexDefaults, mipDefaults :: GLPOpts
simplexDefaults = SimplexOpts MsgOn 10000 True
mipDefaults = MipOpts MsgOn 10000 True DrTom LocBound AllPre False [] 0.0
glpSolveVars :: (Ord v, Real c) => GLPOpts -> LP v c -> IO (ReturnCode, Maybe (Double, Map v Double))
glpSolveVars opts@SimplexOpts{} lp = runGLPK $ do
(code, vars) <- doGLP opts lp
liftM (code, ) $ maybe (return Nothing) ( \ vars -> do
obj <- getObjVal
vals <- sequence [do
val <- getColPrim i
return (v, val)
| (v, i) <- assocs vars]
return (Just (obj, fromDistinctAscList vals))) vars
glpSolveVars opts@MipOpts{} lp = runGLPK $ do
(code, vars) <- doGLP opts lp
liftM (code, ) $ maybe (return Nothing) (\ vars -> do
obj <- mipObjVal
vals <- sequence [do
val <- mipColVal i
return (v, val)
| (v, i) <- assocs vars]
return (Just (obj, fromDistinctAscList vals))) vars
glpSolveAll :: (Ord v, Real c) => GLPOpts -> LP v c -> IO (ReturnCode, Maybe (Double, Map v Double, [RowValue v c]))
glpSolveAll opts@SimplexOpts{} lp@LP{..} = runGLPK $ do
(code, vars) <- doGLP opts lp
liftM (code, ) $ maybe (return Nothing) (\ vars -> do
obj <- getObjVal
vals <- sequence [do
val <- getColPrim i
return (v, val)
| (v, i) <- assocs vars]
rows <- sequence [liftM (RowVal c) (getRowPrim i)
| (i, c) <- zip [1..] constraints]
return (Just (obj, fromDistinctAscList vals, rows))) vars
glpSolveAll opts@MipOpts{} lp@LP{..} = runGLPK $ do
(code, vars) <- doGLP opts lp
liftM (code, ) $ maybe (return Nothing) (\ vars -> do
obj <- mipObjVal
vals <- sequence [do
val <- mipColVal i
return (v, val)
| (v, i) <- assocs vars]
rows <- sequence [liftM (RowVal c) (mipRowVal i)
| (i, c) <- zip [1..] constraints]
return (Just (obj, fromDistinctAscList vals, rows))) vars
doGLP :: (Ord v, Real c) => GLPOpts -> LP v c -> GLPK (ReturnCode, Maybe (Map v Int))
doGLP SimplexOpts{..} lp = do
vars <- writeProblem lp
success <- solveSimplex msgLev tmLim presolve
bad <- getBadRay
maybe (return (success, guard (gaveAnswer success) >> Just vars)) (fail . show) bad
doGLP MipOpts{..} lp = do
vars <- writeProblem lp
success <- mipSolve msgLev brTech btTech ppTech fpHeur cuts mipGap tmLim presolve
bad <- getBadRay
return (success, guard (gaveAnswer success) >> Just vars)