copilot-2.0.6: Examples/Sat.hs
-- | Example of a simple SAT solver (simply constructs the truth table) in
-- Copilot.
-- {-# LANGUAGE RebindableSyntax #-}
module Sat where
import Language.Copilot
import qualified Prelude as P
import Control.Monad (foldM_)
---------------------------------------------------------------------------------
-- | Number of sat variables and a Boolean function over those variables.
type SatFunc = (Int, [Stream Bool] -> Stream Bool)
-- Takes a Sat function and returns the stream of variables and a SAT function.
sat :: SatFunc -> ([Stream Bool], Stream Bool)
sat (i,f) = (xs, res)
where
-- If it becomes true, it stays true.
res = [False] ++ (f xs || res)
xs = xs' i
xs' 0 = []
xs' n = clk (period $ 2 P.^ n) (phase (0 :: Int)) : xs' (n P.- 1)
satSpec :: SatFunc -> Spec
satSpec f = do
observer "sat" (snd $ sat f)
observer "done" done
foldM_ mkObs (0 :: Int) xs
where
xs = fst $ sat f
cnt :: Stream Word64 -- Would need to be extended depending on number of
-- variables.
cnt = [1] ++ cnt + 1
done = cnt == (2 P.^ length xs)
mkObs idx strm = do observer ("obs" P.++ show idx) strm
return (idx P.+ 1)
f0 :: SatFunc
--f0 = (3, \[a,b,c] -> a && (b || (not c)))
f0 = (3, f)
where
f [a,b,c] = a && (b || (not c))
f _ = error "Bad SAT function."
f1 :: SatFunc
f1 = (9, f')
where
f' [a,b,c,d,e,f,g,h,i] =
a && b && c && d && e &&
f && g && h && i && i && not i
f' _ = error "Bad SAT function."
-- | Run the interpreter long enough to get an answer.
runFunc :: SatFunc -> IO ()
runFunc f = interpret (2 P.^ fst f) (satSpec f)
satExamples :: IO ()
satExamples = runFunc f0 >> runFunc f1
---------------------------------------------------------------------------------