picologic-0.2.0: tests/tests.hs
import Picologic.AST
import Picologic.Tseitin
import Picologic.Solver
import Picologic.Pretty
import Test.QuickCheck
import Data.List
import qualified Data.Map as M
import System.Exit (exitFailure)
import System.IO.Unsafe (unsafePerformIO)
instance Arbitrary Expr where
arbitrary = sized $ \n ->
tree (round $ sqrt $ fromIntegral n :: Int)
where tree 0 = elements $ map (Var . Ident) (concat $ replicate 3 ["a", "b", "c", "d"]) ++ [Top, Bottom]
tree n =
oneof
[do a <- tree (pred n)
return $ Neg a,
do l <- arbitrary
let n2 = l `mod` n
a <- tree n2
b <- tree (n-n2)
con <- elements [Conj, Disj, Implies, Iff]
return $ con a b]
shrink (Var _) = []
shrink (Neg (Neg x)) = [x, Neg x] ++ map Neg (shrink x)
shrink (Neg x) = [x] ++ map Neg (shrink x)
shrink (Conj a b) = [a, b]
++ map (Conj a) (shrink b)
++ map (\aa-> Conj aa b) (shrink a)
shrink (Disj a b) = [a, b]
++ map (Disj a) (shrink b)
++ map (\aa-> Disj aa b) (shrink a)
shrink (Implies a b) = [a, b]
++ map (Implies a) (shrink b)
++ map (\aa-> Implies aa b) (shrink a)
shrink (Iff a b) = [a, b]
++ map (Iff a) (shrink b)
++ map (\aa-> Iff aa b) (shrink a)
shrink Top = []
shrink Bottom = []
envl = [(Ident "a", True),
(Ident "b", True),
(Ident "c", False),
(Ident "d", False)]
env = M.fromList envl
test_nnf :: Expr -> Bool
test_nnf e = eval env e == eval env (nnf e)
test_cnf :: Expr -> Bool
test_cnf e = eval env e == eval env (cnf e)
test_tseitin :: Expr -> Bool
test_tseitin e = unsafePerformIO test
where test = do
let vars = variables e
let ts = tseitinCNF e
-- putStrLn "\nexpr"
-- print $ ppExprLisp e
-- putStrLn "tseitin"
-- print $ ppExprLisp ts
-- putStrLn "tseitin clauses"
-- mapM_ print $ clausesExpr ts
let ce = cnf e
as <- solveCNF ce
bs0 <- solveCNF ts
let bs = dropTseitinVarsInSolutions bs0
let as1 = addVarsToSolutions vars as
let bs1 = addVarsToSolutions vars bs
--print ("as", as)
--print ("bs", bs)
return $ normalize as1 == normalize bs1
normalize (Solutions ssv) = sort $ map sort ssv
test_partEval :: Expr -> Bool
test_partEval e = if eval env e
then elast == Top
else elast == Bottom
where
envs = map (\(i,v) -> M.singleton i v) envl
elast = last $ scanl (flip partEval) e envs
qc = verboseCheckWith (stdArgs { maxSuccess = 2000 })
-- how to make an error fail a 'cabal test'?
qcwf p = verboseCheckWith (stdArgs { maxSuccess = 1000 })
(whenFail exitFailure p)
main = do
putStrLn "nnf"
qc test_nnf
putStrLn "cnf"
qc test_cnf
putStrLn "tseitin"
qc test_tseitin
putStrLn "partEval"
qc test_partEval