在Haskell / Linear编程包中运行其他程序

时间:2013-02-12 11:40:36

标签: haskell linear-programming

我有一个名为LPSolve的程序可以解决混合整数优化问题。问题是我无法在迭代期间动态添加约束,所以我想编写一个使用LPSolve来解决松弛的Haskell程序,然后根据解决方案推断出一些额外的约束。利用问题结构的约束。

是否可以在Haskell中运行可执行文件并检索发送到终端的输出?

是否存在解决线性编程问题的Haskell包?

4 个答案:

答案 0 :(得分:5)

使用runInteractiveProcess,您可以'谈话'通过stdin / stdout进行外部进程

答案 1 :(得分:4)

Shelly package有一些很好的库方法来运行外部进程。它的目的是在Haskell中编写shell脚本,但没有理由不能在应用程序中使用它。我发现shell脚本编写任务比标准库方法更方便。

答案 2 :(得分:3)

您可以使用GLPK并在Haskell代码中创建并运行问题

-- 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)] 

答案 3 :(得分:0)

toysolver

import           Data.Default.Class (def)
import           ToySolver.Arith.Simplex
import qualified ToySolver.Data.LA            as LA

case_test1 = do
  solver <- newSolver
  x <- newVar solver
  y <- newVar solver
  z <- newVar solver
  assertAtom solver (LA.fromTerms [(7,x), (12,y), (31,z)] .==. LA.constant 17)
  assertAtom solver (LA.fromTerms [(3,x), (5,y), (14,z)]  .==. LA.constant 7)
  assertAtom solver (LA.var x .>=. LA.constant 1)
  assertAtom solver (LA.var x .<=. LA.constant 40)
  assertAtom solver (LA.var y .>=. LA.constant (-50))
  assertAtom solver (LA.var y .<=. LA.constant 50)

  setObj solver (LA.fromTerms [(-1,x), (-2,x), (-3,x)])

  o <- optimize solver def
  print o
  getValue solver x


> case_test1
Optimum
40 % 1

它解决了有理系数。

您可以添加约束以重新运行求解器:

  assertAtom solver (LA.var x .<=. LA.constant 30)
  o <- optimize solver def
  print o
  getValue solver x


> case_test1
Optimum
30 % 1