{-# LANGUAGE FlexibleContexts #-} module Math.Programming.Tests.IP where import Control.Monad.IO.Class import Math.Programming import Test.Hspec makeIPTests :: (MonadIO m, MonadIP v c o m) => -- | The runner for the API being tested. (m () -> IO ()) -> -- | The resulting test suite. Spec makeIPTests runner = describe "IP problems" $ do it "solves a simple MIP" (runner simpleMIPTest) -- | We solve a simple MIP of the form -- -- @ -- min x + y -- s.t. x >= 1.1 -- y >= 1.1 -- 0 <= x <= 5 -- 0 <= y <= 5 -- x integer -- @ -- -- The optimal solution to this MIP is x = 2, y = 1.1. simpleMIPTest :: (MonadIO m, MonadIP v c o m) => m () simpleMIPTest = do x <- bounded 0 5 `asKind` Integer y <- bounded 0 5 `asKind` Continuous _ <- var x .>= 1.1 _ <- var y .>= 1.1 objective <- minimize $ var x .+. var y status <- optimizeIP -- Check that we reached optimality liftIO $ status `shouldBe` Optimal let expectedX = 2 expectedY = 1.1 expectedObj = expectedX + expectedY vx <- getVariableValue x liftIO $ abs (vx - expectedX) `shouldSatisfy` (<= 1e-3) vy <- getVariableValue y liftIO $ abs (vy - expectedY) `shouldSatisfy` (<= 1e-3) vobj <- getObjectiveValue objective liftIO $ abs (vobj - expectedObj) `shouldSatisfy` (<= 1e-3)