module ToySolver.Converter.WBO2PB
( convert
, addWBO
) where
import Control.Monad
import Control.Monad.Primitive
import Control.Monad.ST
import Data.Array.IArray
import Data.Primitive.MutVar
import qualified ToySolver.SAT.Types as SAT
import ToySolver.SAT.Store.PB
import qualified Data.PseudoBoolean as PBFile
convert :: PBFile.SoftFormula -> (PBFile.Formula, SAT.Model -> SAT.Model, SAT.Model -> SAT.Model)
convert wbo = runST $ do
let nv = PBFile.wboNumVars wbo
db <- newPBStore
(obj, defs) <- addWBO db wbo
formula <- getPBFormula db
let mforth :: SAT.Model -> SAT.Model
mforth m = array (1, PBFile.pbNumVars formula) $ assocs m ++ [(v, SAT.evalPBConstraint m constr) | (v, constr) <- defs]
mback :: SAT.Model -> SAT.Model
mback = SAT.restrictModel nv
return
( formula{ PBFile.pbObjectiveFunction = Just obj }
, mforth
, mback
)
addWBO :: (PrimMonad m, SAT.AddPBNL m enc) => enc -> PBFile.SoftFormula -> m (SAT.PBSum, [(SAT.Var, PBFile.Constraint)])
addWBO db wbo = do
SAT.newVars_ db $ PBFile.wboNumVars wbo
objRef <- newMutVar []
defsRef <- newMutVar []
forM_ (PBFile.wboConstraints wbo) $ \(cost, constr@(lhs,op,rhs)) -> do
case cost of
Nothing -> do
case op of
PBFile.Ge -> SAT.addPBNLAtLeast db lhs rhs
PBFile.Eq -> SAT.addPBNLExactly db lhs rhs
Just w -> do
case op of
PBFile.Ge -> do
case lhs of
[(1,ls)] | rhs == 1 -> do
modifyMutVar objRef (\obj -> (w,[]) : (w,ls) : obj)
[(1,ls)] | rhs == 0 -> do
modifyMutVar objRef ((w,ls) :)
_ | and [c==1 && length ls == 1 | (c,ls) <- lhs] && rhs == 1 -> do
modifyMutVar objRef ((w, [l | (_,[l]) <- lhs]) :)
_ -> do
sel <- SAT.newVar db
SAT.addPBNLAtLeastSoft db sel lhs rhs
modifyMutVar objRef ((w,[sel]) :)
modifyMutVar defsRef ((sel,constr) :)
PBFile.Eq -> do
sel <- SAT.newVar db
SAT.addPBNLExactlySoft db sel lhs rhs
modifyMutVar objRef ((w,[sel]) :)
modifyMutVar defsRef ((sel,constr) :)
obj <- liftM reverse $ readMutVar objRef
defs <- liftM reverse $ readMutVar defsRef
case PBFile.wboTopCost wbo of
Nothing -> return ()
Just t -> SAT.addPBNLAtMost db obj (t 1)
return (obj, defs)