toysolver-0.5.0: test/Test/MIP.hs
{-# OPTIONS_GHC -Wall -fno-warn-orphans #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Test.MIP (mipTestGroup) where
import Algebra.PartialOrd
import Algebra.Lattice
import Data.Maybe
import qualified Data.Map as Map
import Test.Tasty
import Test.Tasty.HUnit
import Test.Tasty.QuickCheck
import Test.Tasty.TH
import qualified ToySolver.Data.MIP as MIP
import qualified ToySolver.Data.MIP.Solution.CBC as CBCSol
import qualified ToySolver.Data.MIP.Solution.CPLEX as CPLEXSol
import qualified ToySolver.Data.MIP.Solution.GLPK as GLPKSol
import qualified ToySolver.Data.MIP.Solution.Gurobi as GurobiSol
import qualified ToySolver.Data.MIP.Solution.SCIP as SCIPSol
prop_status_refl :: Property
prop_status_refl = forAll arbitrary $ \(x :: MIP.Status) -> do
x `leq` x
prop_status_trans :: Property
prop_status_trans =
forAll arbitrary $ \(x :: MIP.Status) ->
forAll (upper x) $ \y ->
forAll (upper y) $ \z ->
x `leq` z
where
-- upper :: (PartialOrd a, Enum a, Bounded a) => a -> Gen a
upper a = elements [b | b <- [minBound .. maxBound], a `leq` b]
prop_status_meet_idempotency :: Property
prop_status_meet_idempotency =
forAll arbitrary $ \(x :: MIP.Status) ->
x `meet` x == x
prop_status_meet_comm :: Property
prop_status_meet_comm =
forAll arbitrary $ \(x :: MIP.Status) y ->
x `meet` y == y `meet` x
prop_status_meet_assoc :: Property
prop_status_meet_assoc =
forAll arbitrary $ \(x :: MIP.Status) y z ->
(x `meet` y) `meet` z == x `meet` (y `meet` z)
prop_status_meet_leq :: Property
prop_status_meet_leq =
forAll arbitrary $ \(x :: MIP.Status) y ->
x `meetLeq` y == x `leq` y
instance Arbitrary MIP.Status where
arbitrary = arbitraryBoundedEnum
case_CBCSol :: Assertion
case_CBCSol = do
sol <- CBCSol.readFile "samples/lp/test-solution-cbc.txt"
sol @?=
MIP.Solution
{ MIP.solStatus = MIP.StatusOptimal
, MIP.solObjectiveValue = Just (-122.5)
, MIP.solVariables = Map.fromList [("x1", 40), ("x2", 10.5), ("x3", 19.5), ("x4", 3)]
}
case_CBCSol_infeasible :: Assertion
case_CBCSol_infeasible = do
sol <- CBCSol.readFile "samples/lp/test-solution-cbc-infeasible.txt"
sol @?=
MIP.Solution
{ MIP.solStatus = MIP.StatusInfeasible
, MIP.solObjectiveValue = Just 0.00000000
, MIP.solVariables = Map.fromList [("x", 0.11111111), ("y", 0), ("z", 0.33333333)]
}
case_CBCSol_unbounded :: Assertion
case_CBCSol_unbounded = do
sol <- CBCSol.readFile "samples/lp/test-solution-cbc-unbounded.txt"
sol @?=
MIP.Solution
{ MIP.solStatus = MIP.StatusInfeasibleOrUnbounded
, MIP.solObjectiveValue = Just 0.00000000
, MIP.solVariables = Map.fromList [("x", 0), ("y", 0)]
}
case_CPLEXSol :: Assertion
case_CPLEXSol = do
sol <- CPLEXSol.readFile "samples/lp/test-solution-cplex.sol"
sol @?=
MIP.Solution
{ MIP.solStatus = MIP.StatusOptimal
, MIP.solObjectiveValue = Just 122.5
, MIP.solVariables = Map.fromList [("x1", 40), ("x2", 10.5), ("x3", 19.5), ("x4", 3)]
}
case_CPLEXSol_unbounded :: Assertion
case_CPLEXSol_unbounded = do
sol <- CPLEXSol.readFile "samples/lp/test-solution-cplex-unbounded.sol"
sol @?=
MIP.Solution
{ MIP.solStatus = MIP.StatusUnbounded
, MIP.solObjectiveValue = Just 3.0
, MIP.solVariables = Map.fromList [("x", 1.0), ("y", 2.0)]
}
case_GLPKSol :: Assertion
case_GLPKSol = do
sol <- GLPKSol.readFile "samples/lp/test-solution-glpk.sol"
sol @?=
MIP.Solution
{ MIP.solStatus = MIP.StatusOptimal
, MIP.solObjectiveValue = Just 122.5
, MIP.solVariables = Map.fromList [("x1", 40), ("x2", 10.5), ("x3", 19.5), ("x4", 3)]
}
case_GLPKSol_long_var :: Assertion
case_GLPKSol_long_var = do
sol <- GLPKSol.readFile "samples/lp/test-solution-glpk-long.sol"
sol @?=
MIP.Solution
{ MIP.solStatus = MIP.StatusOptimal
, MIP.solObjectiveValue = Just 122.5
, MIP.solVariables = Map.fromList [("x1AAAAAAAAAAAAAAAAAAAAAAAAAAAA", 40), ("x2", 10.5), ("x3", 19.5), ("x4", 3)]
}
case_GurobiSol :: Assertion
case_GurobiSol = do
sol <- GurobiSol.readFile "samples/lp/test-solution-gurobi.sol"
isJust (GurobiSol.solObjectiveValue sol) @?= True
GurobiSol.parse (GurobiSol.render sol) @?= sol
case_SCIPSol :: Assertion
case_SCIPSol = do
sol <- SCIPSol.readFile "samples/lp/test-solution-scip.sol"
sol @?=
MIP.Solution
{ MIP.solStatus = MIP.StatusOptimal
, MIP.solObjectiveValue = Just 122.5
, MIP.solVariables = Map.fromList [("x1", 40), ("x2", 10.5), ("x3", 19.5), ("x4", 3)]
}
mipTestGroup :: TestTree
mipTestGroup = $(testGroupGenerator)