module Satchmo.Counting
( atleast
, atmost
, exactly
)
where
import Prelude hiding ( and, or, not )
import Satchmo.Boolean
import Satchmo.SAT ( SAT)
atleast :: MonadSAT m => Int -> [ Boolean ] -> m Boolean
atleast k xs = fmap not $ atmost (k1) xs
atmost_block :: MonadSAT m => Int -> [ Boolean ] -> m [ Boolean ]
atmost_block k [] = do
t <- constant $ True
return $ replicate (k+1) t
atmost_block k (x:xs) = do
cs <- atmost_block k xs
f <- constant False
sequence $ do
(p,q) <- zip cs ( f : cs )
return $ do
fun3 ( \ x p q -> if x then q else p ) x p q
atmost :: MonadSAT m => Int -> [ Boolean ] -> m Boolean
atmost k xs = do
cs <- atmost_block k xs
return $ cs !! k
exactly_block :: MonadSAT m => Int -> [ Boolean ] -> m [ Boolean ]
exactly_block k [] = do
t <- constant True
f <- constant False
return $ t : replicate k f
exactly_block k (x:xs) = do
f <- constant False
cs <- exactly_block k xs
sequence $ do
(p,q) <- zip cs ( f : cs )
return $ do
fun3 ( \ x p q -> if x then q else p ) x p q
exactly :: MonadSAT m => Int -> [ Boolean ] -> m Boolean
exactly k xs = do
cs <- exactly_block k xs
return $ cs !! k