I have a program called LPSolve
that solves mixed integer optimization problems. The problem is that I can't dynamically add constraints during iterations, so I though about writing a Haskell program that uses LPSolve
to solve relaxations and then infer some additional constraints based on the solutions. Constraints that make use of the problem structure.
Is it possible to run an executable in Haskell and retrieve the output sent to the terminal?
Does there exist a Haskell package that solves linear programming problems?
With runInteractiveProcess you can 'talk' to a extern process via stdin/stdout
The Shelly package has some nice library methods for running external processes. It's aimed at writing shell scripts in Haskell but there's no reason you couldn't use it in an application. I find it far more convenient for shell scripting tasks than the standard library methods.
You can use GLPK and create and run problems into Haskell code
-- Usando GLPK, http://www.gnu.org/software/glpk/
import Data.List
import Data.Maybe
import Control.Monad
import Data.LinearProgram
import Data.LinearProgram.GLPK
import qualified Data.Map as M
-- Sólo por dar nombre a las varibles
x e = "X" ++ show e
-- Resuelve el problema de elegir el menor número de empleados
solveEmployees :: [(Int, Int)] -> LP String Int
solveEmployees es = execLPM $ do setDirection Min
setObjective $ linCombination $ map (\e -> (1, x e)) emps
mapM_ (\(a, b) -> geqTo (varSum [x a, x b]) 1) es
mapM_ (\n -> setVarKind (x n) BinVar) emps
where emps = nub $ map fst es ++ map snd es
-- Wrapper suponiendo que siempre hay solución (aquí siempre)
getEmployees :: [(Int, Int)] -> IO [Int]
getEmployees es = do
(_, Just (_, m)) <- glpSolveVars mipDefaults $ solveEmployees es
return $ map (read.tail.fst). M.toList. M.filter (==1) $ m
-- Tráfico de influencias, intentaremos que el empleado 'e' vaya a la playa
-- (da igual que sea de Estocolmo o de Londres)
getEmployees' :: Int -> [(Int, Int)] -> IO [Int]
getEmployees' e es = do
r <- getEmployees es
r' <- getEmployees $ filter (\(a, b ) -> a /= e && b /= e) es
return $ if length r == 1 + length r' then e: r' else r
-- Test
main = do
putStrLn $ "Input: " ++ show test2
putStrLn "Testing: solveEmployees"
r1 <- getEmployees test2
putStrLn $ show r1
putStrLn "Testing: solveEmployees' 2001"
r2 <- getEmployees' 2001 test2
putStrLn $ show r2
test1 :: [(Int, Int)]
test1 = [(1009, 2011), (1017, 2011)]
test2 :: [(Int, Int)]
test2 = [(1009, 2000), (1009, 2001), (1008, 2000), (1008, 2001)]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With