| module SAT.CNF (Literal(..), Clause, CNF(..), tseitin) where | |
| import IR.Boolean | |
| import qualified Data.Map.Strict as Map | |
| data Literal = Pos Int | Neg Int | |
| deriving (Eq, Ord, Show) | |
| type Clause = [Literal] | |
| data CNF = CNF | |
| { cnfClauses :: [Clause] | |
| , cnfNumVars :: Int | |
| } deriving (Show) | |
| litVar :: Literal -> Int | |
| litVar (Pos v) = v | |
| litVar (Neg v) = v | |
| negate :: Literal -> Literal | |
| negate (Pos v) = Neg v | |
| negate (Neg v) = Pos v | |
| type FreshVar = Int | |
| tseitin :: BExpr -> CNF | |
| tseitin expr = CNF clauses nextVar | |
| where | |
| (rootVar, nextVar, clauses) = runTseitin expr 1 | |
| runTseitin :: BExpr -> FreshVar -> (Int, FreshVar, [Clause]) | |
| runTseitin BTrue fresh = (fresh, fresh + 1, [[Pos fresh]]) | |
| runTseitin BFalse fresh = (fresh, fresh + 1, [[Neg fresh]]) | |
| runTseitin (BVar v) _ = (v, v + 1, []) | |
| runTseitin (BNand a b) fresh = | |
| let (aVar, fresh1, aClauses) = runTseitin a fresh | |
| (bVar, fresh2, bClauses) = runTseitin b fresh1 | |
| outVar = fresh2 | |
| fresh3 = fresh2 + 1 | |
| nandClauses = | |
| [ [Pos outVar, Pos aVar] | |
| , [Pos outVar, Pos bVar] | |
| , [Neg outVar, Neg aVar, Neg bVar] | |
| ] | |
| in (outVar, fresh3, aClauses ++ bClauses ++ nandClauses) | |