z3-408.2: examples/Example/Monad/ToSMTLib.hs
-- | Generate SMTLib.
module Example.Monad.ToSMTLib
( run )
where
import Control.Applicative
import Control.Monad ( join )
import Data.Maybe
import qualified Data.Traversable as T
import Z3.Monad
run :: IO ()
run = evalZ3 script >>= putStrLn
script :: Z3 String
script = do
intSort <- mkIntSort
q1 <- flip mkConst intSort =<< mkStringSymbol "q1"
q2 <- flip mkConst intSort =<< mkStringSymbol "q2"
q3 <- flip mkConst intSort =<< mkStringSymbol "q3"
q4 <- flip mkConst intSort =<< mkStringSymbol "q4"
_1 <- mkIntNum (1::Integer)
_4 <- mkIntNum (4::Integer)
-- the ith-queen is in the ith-row.
-- qi is the column of the ith-queen
as1 <- mkAnd =<< T.sequence [mkLe _1 q1, mkLe q1 _4]
as2 <- mkAnd =<< T.sequence [mkLe _1 q2, mkLe q2 _4]
as3 <- mkAnd =<< T.sequence [mkLe _1 q3, mkLe q3 _4]
as4 <- mkAnd =<< T.sequence [mkLe _1 q4, mkLe q4 _4]
-- different columns
as5 <- mkDistinct [q1,q2,q3,q4]
-- avoid diagonal attacks
as6 <- mkNot =<< diagonal 1 q1 q2
as7 <- mkNot =<< diagonal 2 q1 q3
as8 <- mkNot =<< diagonal 3 q1 q4
as9 <- mkNot =<< diagonal 1 q2 q3
as10 <- mkNot =<< diagonal 2 q2 q4
as11 <- mkNot =<< diagonal 1 q3 q4
-- SMTLib script
_true <- mkTrue
benchmarkToSMTLibString "queens" "QF_LIA" "unknown" ""
[as1,as2,as3,as4,as5,as6,as7,as8,as9,as10,as11]
_true
where mkAbs :: AST -> Z3 AST
mkAbs x = do
_0 <- mkIntNum (0::Integer)
join $ mkIte <$> mkLe _0 x <*> pure x <*> mkUnaryMinus x
diagonal d c c' =
join $ mkEq <$> (mkAbs =<< mkSub [c',c]) <*> (mkIntNum d)