smcdel-1.2.0: src/SMCDEL/Internal/MyHaskCUDD.hs
module SMCDEL.Internal.MyHaskCUDD (
-- * Types
Bdd,
-- * Creation of new BDDs
top, bot, var,
-- * Combination and Manipulation of BDDs
neg, con, dis, imp, equ, xor, conSet, disSet, xorSet,
exists, forall, forallSet, existsSet,
restrict, restrictSet,
ifthenelse,
gfp,
-- * Get satsifying assignments
allSats, anySat, allSatsWith
) where
import qualified Cudd.Cudd
import Data.List ((\\), sort)
type Bdd = Cudd.Cudd.DdNode
-- | An assignment of boolean values to variables/integers.
type Assignment = [(Int,Bool)]
bitsToAss :: [Cudd.Cudd.SatBit] -> [Assignment]
bitsToAss = loop 0 where
loop _ [] = [ [] ]
loop n (Cudd.Cudd.DontCare:rest) = loop (n+1) rest
loop n (Cudd.Cudd.Zero :rest) = [ (n,False) : restA | restA <- loop (n+1) rest ]
loop n (Cudd.Cudd.One :rest) = [ (n,True ) : restA | restA <- loop (n+1) rest ]
manager :: Cudd.Cudd.DdManager
manager = Cudd.Cudd.cuddInit
top :: Bdd
top = Cudd.Cudd.cuddReadOne manager
bot :: Bdd
bot = Cudd.Cudd.cuddReadLogicZero manager
var :: Int -> Bdd
var = Cudd.Cudd.cuddBddIthVar manager
neg :: Bdd -> Bdd
neg = Cudd.Cudd.cuddNot manager
xor :: Bdd -> Bdd -> Bdd
xor = Cudd.Cudd.cuddBddXor manager
exists :: Int -> Bdd -> Bdd
exists n b = Cudd.Cudd.cuddBddExistAbstract manager b (Cudd.Cudd.cuddIndicesToCube manager [n])
forall :: Int -> Bdd -> Bdd
forall n b = Cudd.Cudd.cuddBddUnivAbstract manager b (Cudd.Cudd.cuddIndicesToCube manager [n])
existsSet :: [Int] -> Bdd -> Bdd
existsSet [] b = b
existsSet ns b = Cudd.Cudd.cuddBddExistAbstract manager b (Cudd.Cudd.cuddIndicesToCube manager ns)
forallSet :: [Int] -> Bdd -> Bdd
forallSet [] b = b
forallSet ns b = Cudd.Cudd.cuddBddUnivAbstract manager b (Cudd.Cudd.cuddIndicesToCube manager ns)
equ :: Bdd -> Bdd -> Bdd
equ a b = con (imp a b) (imp b a)
imp :: Bdd -> Bdd -> Bdd
imp b1 b2 = Cudd.Cudd.cuddBddIte manager b1 b2 top
ifthenelse :: Bdd -> Bdd -> Bdd -> Bdd
ifthenelse = Cudd.Cudd.cuddBddIte manager
con :: Bdd -> Bdd -> Bdd
con = Cudd.Cudd.cuddBddAnd manager
dis :: Bdd -> Bdd -> Bdd
dis = Cudd.Cudd.cuddBddOr manager
conSet :: [Bdd] -> Bdd
conSet [] = top
conSet (b:bs) = foldl con b bs
disSet :: [Bdd] -> Bdd
disSet [] = bot
disSet (b:bs) = foldl dis b bs
xorSet :: [Bdd] -> Bdd
xorSet [] = bot
xorSet (b:bs) = foldl xor b bs
gfp :: (Bdd -> Bdd) -> Bdd
gfp operator = gfpLoop top where
gfpLoop :: Bdd -> Bdd
gfpLoop current =
if current == operator current
then current
else gfpLoop (operator current)
restrict :: Bdd -> (Int,Bool) -> Bdd
restrict b (n,bit) = Cudd.Cudd.cuddBddLICompaction manager b res where
res = if bit then var n else neg (var n)
restrictSet :: Bdd -> [(Int,Bool)] -> Bdd
restrictSet b bits = Cudd.Cudd.cuddBddLICompaction manager b res where
res = conSet $ map (\(n,bit) -> if bit then var n else neg (var n)) bits
-- | Get all satisfying assignments. These will be partial, i.e. only
-- contain (a subset of) the variables that actually occur in the BDD.
allSats :: Bdd -> [Assignment]
allSats = concatMap bitsToAss . Cudd.Cudd.cuddAllSat manager
-- | Get the lexicographically smallest satisfying assignment, if there is any.
anySat :: Bdd -> Maybe Assignment
anySat = fmap (head . bitsToAss) . Cudd.Cudd.cuddOneSat manager
-- | Given a set of all variables, complete an assignment.
completeAss :: [Int] -> Assignment -> [Assignment]
completeAss allvars ass =
if null (addvars ass)
then [ass]
else concatMap (completeAss allvars) (extend ass (head (addvars ass)))
where
addvars s = allvars \\ sort (map fst s)
extend s v = [ (v,False):s, (v,True):s ]
-- | Get all complete assignments, given a set of all variables.
-- In particular this will include variables not in the BDD.
allSatsWith :: [Int] -> Bdd -> [Assignment]
allSatsWith allvars b = concatMap (completeAss allvars) (allSats b)