module Satchmo.Boolean.Op ( constant , and, or, xor , fun2, fun3 , monadic ) where import Prelude hiding ( and, or, not ) import qualified Prelude import Satchmo.Internal import Satchmo.Code import Satchmo.Boolean.Data import Control.Monad ( foldM ) and :: [ Boolean ] -> SAT Boolean and xs = do y <- boolean sequence $ do x <- xs return $ assert [ not y, x ] assert $ y : map not xs return y or :: [ Boolean ] -> SAT Boolean or xs = do y <- and $ map not xs return $ not y xor :: [ Boolean ] -> SAT Boolean xor [] = constant False xor (x:xs) = foldM xor2 x xs -- | implement the function by giving a full CNF -- that determines the outcome fun2 :: ( Bool -> Bool -> Bool ) -> Boolean -> Boolean -> SAT Boolean fun2 f x y = do r <- boolean sequence_ $ do a <- [ False, True ] b <- [ False, True ] let pack flag var = if flag then not var else var return $ assert [ pack a x, pack b y, pack (Prelude.not $ f a b) r ] return r -- | implement the function by giving a full CNF -- that determines the outcome fun3 :: ( Bool -> Bool -> Bool -> Bool ) -> Boolean -> Boolean -> Boolean -> SAT Boolean fun3 f x y z = do r <- boolean sequence_ $ do a <- [ False, True ] b <- [ False, True ] c <- [ False, True ] let pack flag var = if flag then not var else var return $ assert [ pack a x, pack b y, pack c z , pack (Prelude.not $ f a b c) r ] return r xor2 :: Boolean -> Boolean -> SAT Boolean xor2 = fun2 (/=) -- for historic reasons: xor2_orig :: Boolean -> Boolean -> SAT Boolean xor2_orig x y = do a <- and [ x, not y ] b <- and [ not x, y ] or [ a, b ]