module Data.Algorithm.SatSolver.Solver (
Assignment
, solve
) where
import qualified Data.Foldable as F
import qualified Data.List as L
import qualified Data.Map as M
import qualified Data.Tuple as T
import qualified Data.Algorithm.SatSolver.Fml as Fml
import qualified Data.Algorithm.SatSolver.Clause as Clause
import qualified Data.Algorithm.SatSolver.Lit as Lit
import qualified Data.Algorithm.SatSolver.Var as Var
type Assignment a = M.Map (Var.Var a) Bool
reduceClause :: (Eq a, Ord a) => Lit.Lit a -> Clause.Clause a -> Clause.Clause a
reduceClause l = Clause.mk . L.filter (/= Lit.neg l) . Clause.getLits
reduceFml :: (Eq a, Ord a) => Lit.Lit a -> Fml.Fml a -> Fml.Fml a
reduceFml l = Fml.mk . L.map (reduceClause l) . L.filter f . Fml.getClauses
where
f c = l `notElem` Clause.getLits c
selectLit :: (Ord a) => Fml.Fml a -> Maybe (Lit.Lit a)
selectLit fml = case Fml.getUnitClauses fml of
[] -> case Fml.selectMonotoneLit fml of
Nothing -> Fml.selectMostFrequentLit fml
Just l -> Just l
cs -> Just . L.head . Clause.getLits $ L.head cs
solve :: (Ord a) => Fml.Fml a -> Maybe (Assignment a)
solve = aux M.empty
where
aux m Fml.Fml { Fml.getClauses = [] } = Just m
aux m f = case auxLit l m f of
Nothing -> auxLit (Lit.neg l) m f
Just m' -> Just m'
where
Just l = selectLit f
auxLit l m f
| Fml.hasUnsatisfiedClause f' = Nothing
| otherwise = aux m' f'
where
f' = reduceFml l f
m' = M.insert (Lit.getVar l) (Lit.toBool l) m