satchmo-2.9.9.4: src/Satchmo/Boolean/Data.hs
{-# language MultiParamTypeClasses #-}
{-# language TypeSynonymInstances #-}
{-# language FlexibleInstances #-}
{-# language NoMonomorphismRestriction #-}
{-# language TemplateHaskell #-}
{-# language DeriveGeneric #-}
module Satchmo.Boolean.Data
( Boolean(..), Booleans, encode
, boolean, exists, forall
, constant
, not, monadic
, assertOr -- , assertOrW
, assertAnd -- , assertAndW
, assert -- for legacy code
)
where
import Prelude hiding ( not )
import qualified Prelude
import qualified Satchmo.Code as C
import Satchmo.Data
import Satchmo.MonadSAT
-- import Data.Function.Memoize
import Data.Array
import Data.Maybe ( fromJust )
import Data.List ( partition )
import Control.Monad.Reader
import GHC.Generics (Generic)
import Data.Hashable
data Boolean = Boolean { encode :: !Literal }
| Constant { value :: !Bool }
deriving (Eq, Ord, Show, Generic)
instance Hashable Boolean
-- $(deriveMemoizable ''Boolean)
{-
-- FIXME: @Pepe: what is the reason for these instances?
instance Eq Boolean where
b1@Boolean{} == b2@Boolean{} = encode b1 == encode b2
b1@Constant{} == b2@Constant{} = value b1 == value b2
_ == _ = False
instance Ord Boolean where
b1@Boolean{} `compare` b2@Boolean{} = encode b1 `compare` encode b2
b1@Constant{} `compare` b2@Constant{} = value b1 `compare` value b2
Boolean{} `compare` Constant{} = GT
Constant{} `compare` Boolean{} = LT
instance Enum Boolean where
fromEnum (Constant True) = -1
fromEnum (Constant False) = 0
fromEnum (Boolean (Literal lit) dec) = lit
toEnum 0 = Constant False
toEnum (-1) = Constant True
toEnum l = let x = literal l in Boolean x (asks $ \fm -> fromJust (M.lookup x fm))
-}
type Booleans = [ Boolean ]
isConstant :: Boolean -> Bool
isConstant ( Constant {} ) = True
isConstant _ = False
boolean :: MonadSAT m => m ( Boolean )
boolean = exists
exists :: MonadSAT m => m ( Boolean )
exists = do
x <- fresh
return $ Boolean
{ encode = x
{-
, decode = asks $ \ fm ->
( positive x == )
$ fromJust
$ M.lookup ( variable x ) fm
-}
}
forall :: MonadSAT m => m ( Boolean )
forall = do
x <- fresh_forall
return $ Boolean
{ encode = x
-- , decode = error "Boolean.forall cannot be decoded"
}
constant :: MonadSAT m => Bool -> m (Boolean)
constant v = do
return $ Constant { value = v }
{-# INLINABLE constant #-}
-- not :: Boolean -> Boolean
not b = case b of
Boolean {} -> Boolean
{ encode = nicht $ encode b
-- , decode = do x <- decode b ; return $ Prelude.not x
}
Constant {} -> Constant { value = Prelude.not $ value b }
{-# INLINABLE not #-}
-- assertOr, assertAnd :: MonadSAT m => [ Boolean (Literal m ) ] -> m ()
assertOr = assert
assert :: MonadSAT m => [ Boolean ] -> m ()
assert bs = do
let ( con, uncon ) = partition isConstant bs
let cval = Prelude.or $ map value con
when ( Prelude.not cval ) $ emit $ clause $ map encode uncon
{-# INLINABLE assert #-}
-- assertAnd :: MonadSAT m => [ Boolean ] -> m ()
assertAnd bs = forM_ bs $ assertOr . return
{-
assertOrW, assertAndW :: MonadSAT m => Weight -> [ Boolean ] -> m ()
assertOrW w bs = do
let ( con, uncon ) = partition isConstant bs
let cval = Prelude.or $ map value con
when ( Prelude.not cval ) $ emitW w $ clause $ map encode uncon
assertAndW w bs = forM_ bs $ assertOrW w . return
-}
monadic :: Monad m
=> ( [ a ] -> m b )
-> ( [ m a ] -> m b )
monadic f ms = do
xs <- sequence ms
f xs