packages feed

toysolver-0.7.0: test/Test/SAT/ExistentialQuantification.hs

{-# OPTIONS_GHC -Wall #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
module Test.SAT.ExistentialQuantification (satExistentialQuantificationTestGroup) where

import Control.Monad
import qualified Data.IntSet as IntSet

import Test.Tasty
import Test.Tasty.QuickCheck
import Test.Tasty.HUnit
import Test.Tasty.TH
import qualified Test.QuickCheck.Monadic as QM

import qualified ToySolver.SAT as SAT
import qualified ToySolver.SAT.ExistentialQuantification as ExistentialQuantification
import qualified ToySolver.FileFormat.CNF as CNF

import Test.SAT.Utils

prop_ExistentialQuantification :: Property
prop_ExistentialQuantification = QM.monadicIO $ do
  phi <- QM.pick arbitraryCNF
  xs <- QM.pick $ liftM IntSet.fromList $ sublistOf [1 .. CNF.cnfNumVars phi]
  let ys = IntSet.fromList [1 .. CNF.cnfNumVars phi] IntSet.\\ xs
  psi <- QM.run $ ExistentialQuantification.project xs phi
  forM_ (allAssignments (if IntSet.null ys then 0 else IntSet.findMax ys)) $ \m -> do
    b1 <- QM.run $ do
      solver <- SAT.newSolver
      SAT.newVars_ solver (CNF.cnfNumVars phi)
      forM_ (CNF.cnfClauses phi) $ \c -> SAT.addClause solver (SAT.unpackClause c)
      SAT.solveWith solver [if SAT.evalLit m y then y else -y | y <- IntSet.toList ys]
    let b2 = evalCNF m psi
    QM.assert $ b1 == b2

brauer11_phi :: CNF.CNF
brauer11_phi =
  CNF.CNF
  { CNF.cnfNumVars = 13
  , CNF.cnfNumClauses = 23
  , CNF.cnfClauses = fmap SAT.packClause
      [
      -- μ
        [-x2, -y2]
      , [-y2, -y1]
      , [-x4, -x6, y1]
      , [-x3, y4], [x3, -y4]
      , [-x4, y3], [x4, -y3]
      , [-x5, y6], [x5, -y6]
      , [-x6, y5], [x6, -y5]

      -- ξ
      , [-x13, x1]
      , [-x13, -x2]
      , [-x13, x3]
      , [-x13, -x4]
      , [-x13, x5]
      , [-x13, -x6]
      , [x13, x1]
      , [x13, -x2]
      , [x13, -x3]
      , [x13, x4]
      , [x13, -x5]
      , [x13, x6]
      ]
  }
  where
    [y1,y2,y3,y4,y5,y6] = [1..6]
    [x1,x2,x3,x4,x5,x6,x13] = [7..13]

{-
ξ(m'1) = (¬y1 ∧ ¬y3 ∧ y4 ∧ ¬y5 ∧ y6)
ξ(m'2) = (y1 ∧ ¬y2 ∧ ¬y3 ∧ y4 ∧ ¬y5 ∧ y6)
ξ(m'3) = (y1 ∧ ¬y2 ∧ y3 ∧ ¬y4 ∧ y5 ∧ ¬y6)
ω = ¬(ξ(m'1) ∨ ξ(m'2) ∨ ξ(m'3))
-}
brauer11_omega :: CNF.CNF
brauer11_omega =
  CNF.CNF
  { CNF.cnfNumVars = 6
  , CNF.cnfNumClauses = 3
  , CNF.cnfClauses = map SAT.packClause
      [ [y1, y3, -y4, y5, -y6]
      , [-y1, y2, y3, -y4, y5, -y6]
      , [-y1, y2, -y3, y4, -y5, y6]
      ]
  }
  where
    [y1,y2,y3,y4,y5,y6] = [1..6]

case_ExistentialQuantification_project_phi :: Assertion
case_ExistentialQuantification_project_phi = do
  psi <- ExistentialQuantification.project (IntSet.fromList [7..13]) brauer11_phi
  forM_ (allAssignments 6) $ \m -> do
    b1 <- do
      solver <- SAT.newSolver
      SAT.newVars_ solver (CNF.cnfNumVars brauer11_phi)
      forM_ (CNF.cnfClauses brauer11_phi) $ \c -> SAT.addClause solver (SAT.unpackClause c)
      SAT.solveWith solver [if SAT.evalLit m y then y else -y | y <- [1..6]]
    let b2 = all (SAT.evalClause m . SAT.unpackClause) (CNF.cnfClauses psi)
    (b1 == b2) @?= True

case_ExistentialQuantification_project_phi' :: Assertion
case_ExistentialQuantification_project_phi' = do
  let [y1,y2,y3,y4,y5,y6] = [1..6]
      psi = CNF.CNF
            { CNF.cnfNumVars = 6
            , CNF.cnfNumClauses = 8
            , CNF.cnfClauses = map SAT.packClause
                [ [-y2, y6]
                , [-y3, -y6]
                , [y5, y6]
                , [y3, -y5]
                , [y4, -y6]
                , [y1, y6]
                , [-y1, -y2]
                , [-y4, y6]
                ]
            }
  forM_ (allAssignments 6) $ \m -> do
    b1 <- do
      solver <- SAT.newSolver
      SAT.newVars_ solver (CNF.cnfNumVars brauer11_phi)
      forM_ (CNF.cnfClauses brauer11_phi) $ \c -> SAT.addClause solver (SAT.unpackClause c)
      SAT.solveWith solver [if SAT.evalLit m y then y else -y | y <- [1..6]]
    let b2 = all (SAT.evalClause m . SAT.unpackClause) (CNF.cnfClauses psi)
    (b1 == b2) @?= True

case_shortestImplicantsE_phi :: Assertion
case_shortestImplicantsE_phi = do
  xss <- ExistentialQuantification.shortestImplicantsE (IntSet.fromList [7..13]) brauer11_phi
  forM_ (allAssignments 6) $ \m -> do
    b1 <- do
      solver <- SAT.newSolver
      SAT.newVars_ solver (CNF.cnfNumVars brauer11_phi)
      forM_ (CNF.cnfClauses brauer11_phi) $ \c -> SAT.addClause solver (SAT.unpackClause c)
      SAT.solveWith solver [if SAT.evalLit m y then y else -y | y <- [1..6]]
    let b2 = any (all (SAT.evalLit m) . IntSet.toList) xss
    (b1 == b2) @?= True

case_shortestImplicantsE_phi' :: Assertion
case_shortestImplicantsE_phi' = do
  let [y1,y2,y3,y4,y5,y6] = [1..6]
      xss = map IntSet.fromList
            [ [-y1, -y3, y4, -y5, y6]
            , [y1, -y2, -y3, y4, -y5, y6]
            , [y1, -y2, y3, -y4, y5, -y6]
            ]
  forM_ (allAssignments 6) $ \m -> do
    b1 <- do
      solver <- SAT.newSolver
      SAT.newVars_ solver (CNF.cnfNumVars brauer11_phi)
      forM_ (CNF.cnfClauses brauer11_phi) $ \c -> SAT.addClause solver (SAT.unpackClause c)
      SAT.solveWith solver [if SAT.evalLit m y then y else -y | y <- [1..6]]
    let b2 = any (all (SAT.evalLit m) . IntSet.toList) xss
    (b1 == b2) @?= True

case_shortestImplicantsE_omega :: Assertion
case_shortestImplicantsE_omega = do
  xss <- ExistentialQuantification.shortestImplicantsE IntSet.empty brauer11_omega
  forM_ (allAssignments 6) $ \m -> do
    b1 <- do
      solver <- SAT.newSolver
      SAT.newVars_ solver (CNF.cnfNumVars brauer11_omega)
      forM_ (CNF.cnfClauses brauer11_omega) $ \c -> SAT.addClause solver (SAT.unpackClause c)
      SAT.solveWith solver [if SAT.evalLit m y then y else -y | y <- [1..6]]
    let b2 = any (all (SAT.evalLit m) . IntSet.toList) xss
    unless (b1 == b2) $ print m

case_shortestImplicantsE_omega' :: Assertion
case_shortestImplicantsE_omega' = do
  let [y1,y2,y3,y4,y5,y6] = [1..6]
      xss = map IntSet.fromList
              [ [y2, -y6]
              , [y3, y6]
              , [-y5, -y6]
              , [-y3, y5]
              , [-y4, y6]
              , [-y1, -y6]
              , [y1, y2]
              , [y4, -y6]
              ]
  forM_ (allAssignments 6) $ \m -> do
    b1 <- do
      solver <- SAT.newSolver
      SAT.newVars_ solver (CNF.cnfNumVars brauer11_omega)
      forM_ (CNF.cnfClauses brauer11_omega) $ \c -> SAT.addClause solver (SAT.unpackClause c)
      SAT.solveWith solver [if SAT.evalLit m y then y else -y | y <- [1..6]]
    let b2 = any (all (SAT.evalLit m) . IntSet.toList) xss
    (b1 == b2) @?= True

prop_negateCNF :: Property
prop_negateCNF = QM.monadicIO $ do
  phi <- QM.pick arbitraryCNF
  psi <- QM.run $ ExistentialQuantification.negateCNF phi
  QM.monitor (counterexample $ show psi)
  forM_ (allAssignments (CNF.cnfNumVars phi)) $ \m -> do
    let b1 = evalCNF m phi
        b2 = evalCNF m psi
    unless (b1 /= b2) $ QM.monitor (counterexample $ show m)
    QM.assert $ b1 /= b2

satExistentialQuantificationTestGroup :: TestTree
satExistentialQuantificationTestGroup = $(testGroupGenerator)