{-# LANGUAGE TypeApplications #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DeriveAnyClass #-} module Main where import Data.Function ((&)) import Data.Maybe (isJust) import qualified Data.List as List import Data.Aeson (FromJSON(..), ToJSON(..), (.=), (.:)) import qualified Data.Aeson as Aeson import Data.Hashable (Hashable(..)) import Control.Monad.IO.Class (liftIO) import Control.Monad (when) import Hedgehog import qualified Hedgehog.Gen as Gen import qualified Hedgehog.Range as Range import Test.Hspec (describe, it, hspec) import Test.Hspec.Hedgehog (hedgehog) import GHC.Generics (Generic) import Data.Aeson (FromJSON, ToJSON) import Process.Minizinc import Process.Minizinc.TH genModelData "Test002" "models/test002_04.mzn" data Input001 = Input001 { input001X :: Int } deriving (Show,Eq,Ord) instance Hashable Input001 where hashWithSalt s (Input001 x) = hashWithSalt s x instance ToJSON Input001 where toJSON (Input001 x) = Aeson.object [ "x" .= x ] data Output001 = Output001 { output001Y :: Int } deriving (Show,Eq,Ord) instance FromJSON Output001 where parseJSON = Aeson.withObject "output001" $ \v -> Output001 <$> v .: "y" solver :: MonadGen m => m Solver solver = Gen.element [ Gecode, Chuffed, COIN_BC ] mipSolver :: MonadGen m => m Solver mipSolver = Gen.element [ COIN_BC ] cpSolver :: MonadGen m => m Solver cpSolver = Gen.element [ Gecode, Chuffed ] mzncall_t001_01 = do x <- forAll $ Gen.integral (Range.linear (-100) 100) s <- forAll solver let mzn = simpleMiniZinc @Input001 @Output001 "models/test001_01.mzn" 1000 s let input = Input001 x outy <- liftIO $ runLastMinizincJSON mzn input liftIO $ cleanTmpFile mzn input Just x === fmap output001Y outy mzncall_t001_02 = do x <- forAll $ Gen.integral (Range.linear (-100) 100) s <- forAll solver let mzn = simpleMiniZinc @Input001 @Output001 "models/test001_02.mzn" 1000 s let input = Input001 x outy <- liftIO $ runLastMinizincJSON mzn input liftIO $ cleanTmpFile mzn input Nothing === outy mzncall_t001_03 = do x <- forAll $ Gen.integral (Range.linear (-100) 100) s <- forAll cpSolver let mzn = simpleMiniZinc @Input001 @Output001 "models/test001_03.mzn" 3000 s & withArgs ["-a"] let input = Input001 x outputs <- liftIO $ runMinizincJSON mzn input [] collectResults let (exhaustives,nonExhaustives) = List.partition isExhaustive outputs when (length outputs == 7) $ do liftIO $ cleanTmpFile mzn input length outputs === 7 length nonExhaustives === 6 length exhaustives === 1 where isExhaustive (Exhausted a) = True isExhaustive _ = False mzncall_t002_04 = do let mzn = simpleMiniZinc @Test002Input @Test002Output "models/test002_04.mzn" 1000 Gecode let input = Test002Input 10 True 1.2 [1,2] [True,True] [0.2,0.3] [[1,2], [3,4]] outy <- liftIO $ runLastMinizincJSON mzn input liftIO $ cleanTmpFile mzn input assert $ isJust outy prop_mzncall_t001_01 :: Property prop_mzncall_t001_01 = property mzncall_t001_01 prop_mzncall_t001_02 :: Property prop_mzncall_t001_02 = property mzncall_t001_02 prop_mzncall_t001_03 :: Property prop_mzncall_t001_03 = property mzncall_t001_03 prop_mzncall_t002_04 :: Property prop_mzncall_t002_04 = property mzncall_t002_04 tests :: IO Bool tests = checkParallel $$(discover) main :: IO () main = hspec $ do describe "output-input json reading" $ do it "should solve trivial problems" $ hedgehog $ do mzncall_t001_01 it "should not solve unsatisfiable problems" $ hedgehog $ do mzncall_t001_02 it "should find seven satisfiable answers to y in [x-3 .. x+3]" $ hedgehog $ do mzncall_t001_03 describe "autogenerated interface" $ do it "should map stuff" $ hedgehog $ do mzncall_t002_04