module LOAG.Solver.MiniSat ( newSolvable,-- IO SatContainer newLit, -- Sat -> IO MyVar satValues, -- Sat -> IO (Int, Int) addClause, -- Sat -> [MyVar] -> IO () satsolve, -- Sat -> IO Bool value, -- Sat -> IO (Maybe Bool) fixed, -- Sat -> IO Bool MyVar(..), Sat, varnot, VarMap, Mini.conflict ) where import LOAG.Graphs import Control.Monad import Data.Maybe import qualified Data.Map as M import qualified MiniSat as Mini type Sat = Mini.Solver type VarMap = M.Map Edge MyVar data MyVar = Var Mini.Lit | VarTrue | VarFalse | VarNot MyVar deriving (Show, Eq) varnot :: MyVar -> MyVar varnot v@(Var i) = Var (Mini.neg i) varnot (VarNot v)= v varnot VarFalse = VarTrue varnot VarTrue = VarFalse newSolvable :: IO Mini.Solver newSolvable = do sat <- Mini.newSolver Mini.eliminate sat True return sat newLit :: Sat -> IO MyVar newLit sat = do p <- Mini.newLit sat return (Var (Mini.neg p)) satValues :: Sat -> IO (Int,Int) satValues sat = do v <- Mini.minisat_num_vars sat p <- Mini.minisat_num_clauses sat return (v,p) addClause :: Sat -> [MyVar] -> IO Bool addClause sat [] = return True addClause sat es = do if satisfied then return True else case fes of [] -> error "unsatisfiable" fes -> Mini.addClause sat $ map toMini fes where satisfied = any (True ==?) es fes = filter (not . (False ==?)) es b ==? v = case v of VarTrue -> b VarFalse -> not b _ -> False toMini :: MyVar -> Mini.Lit toMini (Var v) = v toMini (VarNot v) = Mini.neg (toMini v) _ = error "incorrect clause filtering" satsolve :: Sat -> [MyVar] -> IO Bool satsolve sat = Mini.solve sat . map extract extract :: MyVar -> Mini.Lit extract VarTrue = error "cannot extract True" extract VarFalse = error "cannot extract False" extract (VarNot v) = Mini.neg (extract v) extract (Var l) = l value :: Sat -> MyVar -> IO (Maybe Bool) value _ VarTrue = return $ Just True value _ VarFalse = return $ Just False value sat (VarNot v) = value sat v >>= return . fmap not value sat (Var v) = Mini.modelValue sat v fixed :: Sat -> MyVar -> IO Bool fixed _ VarTrue = return $ True fixed _ VarFalse = return $ True fixed sat (VarNot v)= fixed sat v fixed sat (Var l) = Mini.value sat l >>= return . isJust