module ToySolver.SAT.PBNLC
(
PBTerm
, PBSum
, addPBAtLeast
, addPBAtMost
, addPBExactly
, addPBAtLeastSoft
, addPBAtMostSoft
, addPBExactlySoft
, linearizePBSum
, linearizePBSumWithPolarity
, evalPBSum
) where
import qualified ToySolver.SAT as SAT
import ToySolver.SAT.Types
import ToySolver.SAT.TseitinEncoder
import ToySolver.Internal.Util (revForM)
type PBTerm = (Integer, [Lit])
type PBSum = [PBTerm]
addPBAtLeast
:: Encoder
-> PBSum
-> Integer
-> IO ()
addPBAtLeast enc lhs rhs = do
let c = sum [c | (c,[]) <- lhs]
lhs' <- linearizePBSumWithPolarity enc polarityPos [(c,ls) | (c,ls) <- lhs, not (null ls)]
SAT.addPBAtLeast (encSolver enc) lhs' (rhs c)
addPBAtMost
:: Encoder
-> PBSum
-> Integer
-> IO ()
addPBAtMost enc lhs rhs =
addPBAtLeast enc [(c,ls) | (c,ls) <- lhs] (negate rhs)
addPBExactly
:: Encoder
-> PBSum
-> Integer
-> IO ()
addPBExactly enc lhs rhs = do
let c = sum [c | (c,[]) <- lhs]
lhs' <- linearizePBSum enc [(c,ls) | (c,ls) <- lhs, not (null ls)]
SAT.addPBExactly (encSolver enc) lhs' (rhs c)
addPBAtLeastSoft
:: Encoder
-> Lit
-> PBSum
-> Integer
-> IO ()
addPBAtLeastSoft enc sel lhs rhs = do
let c = sum [c | (c,[]) <- lhs]
lhs' <- linearizePBSumWithPolarity enc polarityPos [(c,ls) | (c,ls) <- lhs, not (null ls)]
SAT.addPBAtLeastSoft (encSolver enc) sel lhs' (rhs c)
addPBAtMostSoft
:: Encoder
-> Lit
-> PBSum
-> Integer
-> IO ()
addPBAtMostSoft enc sel lhs rhs =
addPBAtLeastSoft enc sel [(negate c, lit) | (c,lit) <- lhs] (negate rhs)
addPBExactlySoft
:: Encoder
-> Lit
-> PBSum
-> Integer
-> IO ()
addPBExactlySoft enc sel lhs rhs = do
let c = sum [c | (c,[]) <- lhs]
lhs' <- linearizePBSum enc [(c,ls) | (c,ls) <- lhs, not (null ls)]
SAT.addPBExactlySoft (encSolver enc) sel lhs' (rhs c)
linearizePBSum
:: Encoder
-> PBSum
-> IO PBLinSum
linearizePBSum enc = linearizePBSumWithPolarity enc polarityBoth
linearizePBSumWithPolarity
:: Encoder
-> Polarity
-> PBSum
-> IO PBLinSum
linearizePBSumWithPolarity enc p xs =
revForM xs $ \(c,ls) -> do
l <- if c > 0 then
encodeConjWithPolarity enc p ls
else
encodeConjWithPolarity enc (negatePolarity p) ls
return (c,l)
evalPBSum :: IModel m => m -> PBSum -> Integer
evalPBSum m xs = sum [c | (c,lits) <- xs, all (evalLit m) lits]