MIP 0.1.0.0 → 0.1.1.0
raw patch · 10 files changed
+78/−23 lines, 10 filesdep ~basePVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependency ranges changed: base
API changes (from Hackage documentation)
+ Numeric.Optimization.MIP.Base: class Default a
+ Numeric.Optimization.MIP.Base: def :: Default a => a
- Numeric.Optimization.MIP: parseLPString :: FileOptions -> String -> String -> Either (ParseError String) (Problem Scientific)
+ Numeric.Optimization.MIP: parseLPString :: (Stream s, Token s ~ Char, IsString (Tokens s)) => FileOptions -> String -> s -> Either (ParseError s) (Problem Scientific)
- Numeric.Optimization.MIP: parseMPSString :: FileOptions -> String -> String -> Either (ParseError String) (Problem Scientific)
+ Numeric.Optimization.MIP: parseMPSString :: (Stream s, Token s ~ Char, IsString (Tokens s)) => FileOptions -> String -> s -> Either (ParseError s) (Problem Scientific)
Files
- ChangeLog.md +6/−0
- MIP.cabal +9/−9
- README.md +4/−0
- src/Numeric/Optimization/MIP.hs +35/−5
- src/Numeric/Optimization/MIP/Base.hs +8/−1
- src/Numeric/Optimization/MIP/FileUtils.hs +3/−0
- src/Numeric/Optimization/MIP/LPFile.hs +3/−3
- src/Numeric/Optimization/MIP/MPSFile.hs +3/−2
- src/Numeric/Optimization/MIP/Solver/CBC.hs +6/−2
- test/TestSuite.hs +1/−1
ChangeLog.md view
@@ -2,6 +2,12 @@ ## Unreleased changes +## 0.1.1.0++* re-export `Default` class from `Numeric.Optimization.MIP`.+* fix to work with recent version of CBC+* generalize type of `parseLPString` and `parseMPSString`+ ## 0.1.0.0 * Separated from toysolver package
MIP.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: ac803e98baaa0544b947d71e759475b741c54bd5c39105056cfd3d1fbc25b4e0+-- hash: f6b1b8d7874f11e9e522f0bba9ad5789dbfe74e4a863836348e4a8f03c658484 name: MIP-version: 0.1.0.0+version: 0.1.1.0 synopsis: Library for using Mixed Integer Programming (MIP) description: Please see the README on GitHub at <https://github.com/msakai/haskell-MIP/tree/master/MIP#readme> category: Math, Algorithms, Optimisation, Optimization@@ -31,32 +31,32 @@ location: https://github.com/msakai/haskell-MIP flag TestCBC- description: run test cases that depends on cbc command+ description: run test cases that depend on cbc command manual: True default: False flag TestCPLEX- description: run test cases that depends on cplex command+ description: run test cases that depend on cplex command manual: True default: False flag TestGlpsol- description: run test cases that depends on glpsol command+ description: run test cases that depend on glpsol command manual: True default: False flag TestGurobiCl- description: run test cases that depends on gurobi_cl command+ description: run test cases that depend on gurobi_cl command manual: True default: False flag TestLPSolve- description: run test cases that depends on lp_solve command+ description: run test cases that depend on lp_solve command manual: True default: False flag TestSCIP- description: run test cases that depends on scip command+ description: run test cases that depend on scip command manual: True default: False @@ -101,7 +101,7 @@ , filepath , intern >=0.9.1.2 && <1.0.0.0 , lattices- , megaparsec >=5 && <9+ , megaparsec >=5 && <10 , mtl >=2.1.2 , process >=1.1.0.2 , scientific
README.md view
@@ -1,5 +1,9 @@ # MIP +[](https://hackage.haskell.org/package/MIP)+[](https://packdeps.haskellers.com/feed?needle=MIP)+[](https://opensource.org/licenses/BSD-3-Clause)+ Library for using Mixed Integer Programming (MIP) in Haskell. This library contains functions like:
src/Numeric/Optimization/MIP.hs view
@@ -1,7 +1,9 @@ {-# OPTIONS_GHC -Wall #-} {-# OPTIONS_HADDOCK show-extensions #-} {-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeFamilies #-} ----------------------------------------------------------------------------- -- | -- Module : Numeric.Optimization.MIP@@ -16,28 +18,39 @@ -- ----------------------------------------------------------------------------- module Numeric.Optimization.MIP- ( module Numeric.Optimization.MIP.Base+ (+ -- * The MIP Problem/Solution types+ module Numeric.Optimization.MIP.Base++ -- * File I/O+ -- $IO++ -- ** Reading problem files , readFile , readLPFile , readMPSFile , parseLPString , parseMPSString+ , ParseError++ -- ** Generating problem files , writeFile , writeLPFile , writeMPSFile , toLPString , toMPSString- , ParseError ) where import Prelude hiding (readFile, writeFile) import Control.Exception import Data.Char import Data.Scientific (Scientific)+import Data.String import qualified Data.Text.Lazy as TL import qualified Data.Text.Lazy.IO as TLIO import System.FilePath (takeExtension, splitExtension) import System.IO hiding (readFile, writeFile)+import Text.Megaparsec (Stream (..)) import Numeric.Optimization.MIP.Base import Numeric.Optimization.MIP.FileUtils (ParseError)@@ -52,7 +65,7 @@ import GHC.IO.Encoding (getLocaleEncoding) #endif --- | Parse .lp or .mps file based on file extension+-- | Parse LP or MPS file based on file extension. readFile :: FileOptions -> FilePath -> IO (Problem Scientific) readFile opt fname = case getExt fname of@@ -105,13 +118,22 @@ #endif -- | Parse a string containing LP file data.-parseLPString :: FileOptions -> String -> String -> Either (ParseError String) (Problem Scientific)+#if MIN_VERSION_megaparsec(6,0,0)+parseLPString :: (Stream s, Token s ~ Char, IsString (Tokens s)) => FileOptions -> String -> s -> Either (ParseError s) (Problem Scientific)+#else+parseLPString :: (Stream s, Token s ~ Char) => FileOptions -> String -> s -> Either (ParseError s) (Problem Scientific)+#endif parseLPString = LPFile.parseString -- | Parse a string containing MPS file data.-parseMPSString :: FileOptions -> String -> String -> Either (ParseError String) (Problem Scientific)+#if MIN_VERSION_megaparsec(6,0,0)+parseMPSString :: (Stream s, Token s ~ Char, IsString (Tokens s)) => FileOptions -> String -> s -> Either (ParseError s) (Problem Scientific)+#else+parseMPSString :: (Stream s, Token s ~ Char) => FileOptions -> String -> s -> Either (ParseError s) (Problem Scientific)+#endif parseMPSString = MPSFile.parseString +-- | Generate LP file or MPS file based on file extension. writeFile :: FileOptions -> FilePath -> Problem Scientific -> IO () writeFile opt fname prob = case getExt fname of@@ -127,12 +149,14 @@ #endif s -> s +-- | Generate LP file. writeLPFile :: FileOptions -> FilePath -> Problem Scientific -> IO () writeLPFile opt fname prob = case LPFile.render opt prob of Left err -> ioError $ userError err Right s -> writeTextFile opt fname s +-- | Generate MPS file. writeMPSFile :: FileOptions -> FilePath -> Problem Scientific -> IO () writeMPSFile opt fname prob = case MPSFile.render opt prob of@@ -159,8 +183,14 @@ writeSimple #endif +-- | Generate a 'TL.Text' containing LP file data. toLPString :: FileOptions -> Problem Scientific -> Either String TL.Text toLPString = LPFile.render +-- | Generate a 'TL.Text' containing MPS file data. toMPSString :: FileOptions -> Problem Scientific -> Either String TL.Text toMPSString = MPSFile.render++-- $IO+-- If this library is built with @WithZlib@ flag (enabled by default), +-- reading/writing gzipped file (@.gz@) are also supported.
src/Numeric/Optimization/MIP/Base.hs view
@@ -77,6 +77,7 @@ , FileOptions (..) -- * Utilities+ , Default (..) , Variables (..) , intersectBounds ) where@@ -269,16 +270,19 @@ } deriving (Eq, Ord, Show) +-- | Equality constraint. (.==.) :: Num c => Expr c -> Expr c -> Constraint c lhs .==. rhs = case splitConst (lhs - rhs) of (e, c) -> def{ constrExpr = e, constrLB = Finite (- c), constrUB = Finite (- c) } +-- | Inequality constraint (≤). (.<=.) :: Num c => Expr c -> Expr c -> Constraint c lhs .<=. rhs = case splitConst (lhs - rhs) of (e, c) -> def{ constrExpr = e, constrUB = Finite (- c) } +-- | Inequality constraint (≥). (.>=.) :: Num c => Expr c -> Expr c -> Constraint c lhs .>=. rhs = case splitConst (lhs - rhs) of@@ -356,7 +360,9 @@ , (StatusInfeasibleOrUnbounded, StatusInfeasible) ] -+-- | /meet/ (greatest lower bound) operator of the partial order of 'Status' type.+--+-- If the version of @lattices@ is \<2, then @MeetSemiLattice@ instance can also be used. meetStatus :: Status -> Status -> Status StatusUnknown `meetStatus` _b = StatusUnknown StatusFeasible `meetStatus` b@@ -387,6 +393,7 @@ #endif +-- | Type for representing a solution of MIP problem. data Solution r = Solution { solStatus :: Status
src/Numeric/Optimization/MIP/FileUtils.hs view
@@ -21,6 +21,9 @@ #endif import qualified Text.Megaparsec as MP +-- | Error type for parsing.+--+-- The definition is slightly different based on the @megaparsec@ version. #if MIN_VERSION_megaparsec(7,0,0) type ParseError s = MP.ParseErrorBundle s Void #elif MIN_VERSION_megaparsec(6,0,0)
src/Numeric/Optimization/MIP/LPFile.hs view
@@ -17,7 +17,7 @@ -- Stability : provisional -- Portability : non-portable ----- A CPLEX .lp format parser library.+-- A CPLEX @.lp@ format parser library. -- -- References: --@@ -87,7 +87,7 @@ #endif -- | Parse a string containing LP file data.--- The source name is only | used in error messages and may be the empty string.+-- The source name is only used in error messages and may be the empty string. #if MIN_VERSION_megaparsec(6,0,0) parseString :: (Stream s, Token s ~ Char, IsString (Tokens s)) => MIP.FileOptions -> String -> s -> Either (ParseError s) (MIP.Problem Scientific) #else@@ -484,7 +484,7 @@ -- --------------------------------------------------------------------------- --- | Render a problem into a string.+-- | Render a problem into a 'TL.Text' containing LP file data. render :: MIP.FileOptions -> MIP.Problem Scientific -> Either String TL.Text render _ mip = Right $ execM $ render' $ normalize mip
src/Numeric/Optimization/MIP/MPSFile.hs view
@@ -16,7 +16,7 @@ -- Stability : provisional -- Portability : non-portable ----- A .mps format parser library.+-- A @.mps@ format parser library. -- -- References: --@@ -104,7 +104,7 @@ #endif -- | Parse a string containing MPS file data.--- The source name is only | used in error messages and may be the empty string.+-- The source name is only used in error messages and may be the empty string. #if MIN_VERSION_megaparsec(6,0,0) parseString :: (Stream s, Token s ~ Char, IsString (Tokens s)) => MIP.FileOptions -> String -> s -> Either (ParseError s) (MIP.Problem Scientific) #else@@ -617,6 +617,7 @@ -- --------------------------------------------------------------------------- +-- | Render a problem into a 'TL.Text' containing MPS file data. render :: MIP.FileOptions -> MIP.Problem Scientific -> Either String TL.Text render _ mip | not (checkAtMostQuadratic mip) = Left "Expression must be atmost quadratic" render _ mip = Right $ execM $ render' $ nameRows mip
src/Numeric/Optimization/MIP/Solver/CBC.hs view
@@ -41,7 +41,7 @@ instance IsSolver CBC IO where solve solver opt prob = do- case LPFile.render def prob of+ case LPFile.render def prob{ MIP.objectiveFunction = obj' } of Left err -> ioError $ userError err Right lp -> do withSystemTempFile "cbc.lp" $ \fname1 h1 -> do@@ -61,7 +61,11 @@ ExitFailure n -> ioError $ userError $ "exit with " ++ show n ExitSuccess -> do sol <- CBCSol.readFile fname2- if MIP.objDir (MIP.objectiveFunction prob) == MIP.OptMax then+ if isMax then return $ sol{ MIP.solObjectiveValue = fmap negate (MIP.solObjectiveValue sol) } else return sol+ where+ obj = MIP.objectiveFunction prob+ isMax = MIP.objDir obj == MIP.OptMax+ obj' = if isMax then obj{ MIP.objDir = MIP.OptMin, MIP.objExpr = - MIP.objExpr obj } else obj
test/TestSuite.hs view
@@ -8,7 +8,7 @@ import Test.MPSFile main :: IO ()-main = defaultMain $ testGroup "ToySolver test suite"+main = defaultMain $ testGroup "MIP test suite" [ lpTestGroup , mipTestGroup , mipSolverTestGroup