Copyright | (c) Masahiro Sakai 2021 |
---|---|
License | BSD-style |
Maintainer | masahiro.sakai@gmail.com |
Stability | unstable |
Portability | non-portable |
Safe Haskell | None |
Language | Haskell2010 |
Zero-Suppressed binary decision diagram.
References:
- S. Minato, "Zero-Suppressed BDDs for Set Manipulation in Combinatorial Problems," 30th ACM/IEEE Design Automation Conference, 1993, pp. 272-277, doi: 10.1145/157485.164890. https://www.researchgate.net/publication/221062015_Zero-Suppressed_BDDs_for_Set_Manipulation_in_Combinatorial_Problems
Synopsis
- data ZDD a where
- pattern Empty :: ZDD a
- pattern Base :: ZDD a
- class ItemOrder a where
- compareItem :: proxy a -> Int -> Int -> Ordering
- data AscOrder
- data DescOrder
- withDefaultOrder :: forall r. (forall a. ItemOrder a => Proxy a -> r) -> r
- withAscOrder :: forall r. (Proxy AscOrder -> r) -> r
- withDescOrder :: forall r. (Proxy DescOrder -> r) -> r
- withCustomOrder :: forall r. (Int -> Int -> Ordering) -> (forall a. ItemOrder a => Proxy a -> r) -> r
- empty :: ZDD a
- base :: ZDD a
- singleton :: forall a. ItemOrder a => IntSet -> ZDD a
- subsets :: forall a. ItemOrder a => IntSet -> ZDD a
- combinations :: forall a. (ItemOrder a, HasCallStack) => IntSet -> Int -> ZDD a
- fromListOfIntSets :: forall a. ItemOrder a => [IntSet] -> ZDD a
- fromSetOfIntSets :: forall a. ItemOrder a => Set IntSet -> ZDD a
- subsetsAtLeast :: forall a w. (ItemOrder a, Real w) => IntMap w -> w -> ZDD a
- subsetsAtMost :: forall a w. (ItemOrder a, Real w) => IntMap w -> w -> ZDD a
- subsetsExactly :: forall a w. (ItemOrder a, Real w) => IntMap w -> w -> ZDD a
- subsetsExactlyIntegral :: forall a w. (ItemOrder a, Real w, Integral w) => IntMap w -> w -> ZDD a
- insert :: forall a. ItemOrder a => IntSet -> ZDD a -> ZDD a
- delete :: forall a. ItemOrder a => IntSet -> ZDD a -> ZDD a
- member :: forall a. ItemOrder a => IntSet -> ZDD a -> Bool
- notMember :: forall a. ItemOrder a => IntSet -> ZDD a -> Bool
- null :: ZDD a -> Bool
- size :: Integral b => ZDD a -> b
- isSubsetOf :: ItemOrder a => ZDD a -> ZDD a -> Bool
- isProperSubsetOf :: ItemOrder a => ZDD a -> ZDD a -> Bool
- disjoint :: ItemOrder a => ZDD a -> ZDD a -> Bool
- numNodes :: ZDD a -> Int
- union :: forall a. ItemOrder a => ZDD a -> ZDD a -> ZDD a
- unions :: forall f a. (Foldable f, ItemOrder a) => f (ZDD a) -> ZDD a
- intersection :: forall a. ItemOrder a => ZDD a -> ZDD a -> ZDD a
- difference :: forall a. ItemOrder a => ZDD a -> ZDD a -> ZDD a
- (\\) :: forall a. ItemOrder a => ZDD a -> ZDD a -> ZDD a
- nonSuperset :: forall a. ItemOrder a => ZDD a -> ZDD a -> ZDD a
- subset1 :: forall a. ItemOrder a => Int -> ZDD a -> ZDD a
- subset0 :: forall a. ItemOrder a => Int -> ZDD a -> ZDD a
- mapInsert :: forall a. ItemOrder a => Int -> ZDD a -> ZDD a
- mapDelete :: forall a. ItemOrder a => Int -> ZDD a -> ZDD a
- change :: forall a. ItemOrder a => Int -> ZDD a -> ZDD a
- data Sig a
- pattern SEmpty :: Sig a
- pattern SBase :: Sig a
- inSig :: Sig (ZDD a) -> ZDD a
- outSig :: ZDD a -> Sig (ZDD a)
- fold :: (Int -> b -> b -> b) -> (Bool -> b) -> ZDD a -> b
- fold' :: (Int -> b -> b -> b) -> (Bool -> b) -> ZDD a -> b
- unfoldHashable :: forall a b. (ItemOrder a, Eq b, Hashable b) => (b -> Sig b) -> b -> ZDD a
- unfoldOrd :: forall a b. (ItemOrder a, Ord b) => (b -> Sig b) -> b -> ZDD a
- minimalHittingSets :: forall a. ItemOrder a => ZDD a -> ZDD a
- minimalHittingSetsToda :: forall a. ItemOrder a => ZDD a -> ZDD a
- minimalHittingSetsKnuth :: forall a. ItemOrder a => ZDD a -> ZDD a
- minimalHittingSetsImai :: forall a. ItemOrder a => ZDD a -> ZDD a
- uniformM :: forall a g m. (ItemOrder a, StatefulGen g m, HasCallStack) => ZDD a -> g -> m IntSet
- findMinSum :: forall a w. (ItemOrder a, Num w, Ord w, HasCallStack) => (Int -> w) -> ZDD a -> (w, IntSet)
- findMaxSum :: forall a w. (ItemOrder a, Num w, Ord w, HasCallStack) => (Int -> w) -> ZDD a -> (w, IntSet)
- flatten :: ItemOrder a => ZDD a -> IntSet
- toListOfIntSets :: ZDD a -> [IntSet]
- toSetOfIntSets :: ZDD a -> Set IntSet
- type Graph f = IntMap (f Int)
- toGraph :: ZDD a -> (Graph Sig, Int)
- toGraph' :: Traversable t => t (ZDD a) -> (Graph Sig, t Int)
- fromGraph :: HasCallStack => (Graph Sig, Int) -> ZDD a
- fromGraph' :: HasCallStack => Graph Sig -> IntMap (ZDD a)
ZDD type
Zero-suppressed binary decision diagram representing family of sets
pattern Leaf :: Bool -> ZDD a | |
pattern Branch :: Int -> ZDD a -> ZDD a -> ZDD a | Smart constructor that takes the ZDD reduction rules into account |
Item ordering
withDefaultOrder :: forall r. (forall a. ItemOrder a => Proxy a -> r) -> r Source #
Currently the default order is AscOrder
withAscOrder :: forall r. (Proxy AscOrder -> r) -> r Source #
withDescOrder :: forall r. (Proxy DescOrder -> r) -> r Source #
withCustomOrder :: forall r. (Int -> Int -> Ordering) -> (forall a. ItemOrder a => Proxy a -> r) -> r Source #
Construction
The family containing only the empty set ({∅}).
>>>
toSetOfIntSets (base :: ZDD AscOrder)
fromList [fromList []]
singleton :: forall a. ItemOrder a => IntSet -> ZDD a Source #
Create a ZDD that contains only a given set.
>>>
toSetOfIntSets (singleton (IntSet.fromList [1,2,3]) :: ZDD AscOrder)
fromList [fromList [1,2,3]]
combinations :: forall a. (ItemOrder a, HasCallStack) => IntSet -> Int -> ZDD a Source #
Set of all k-combination of a set
fromListOfIntSets :: forall a. ItemOrder a => [IntSet] -> ZDD a Source #
Create a ZDD from a list of IntSet
fromSetOfIntSets :: forall a. ItemOrder a => Set IntSet -> ZDD a Source #
Create a ZDD from a set of IntSet
Pseudo-boolean constraints
subsetsAtLeast :: forall a w. (ItemOrder a, Real w) => IntMap w -> w -> ZDD a Source #
Set of all subsets whose sum of weights is at least k.
subsetsAtMost :: forall a w. (ItemOrder a, Real w) => IntMap w -> w -> ZDD a Source #
Set of all subsets whose sum of weights is at most k.
subsetsExactly :: forall a w. (ItemOrder a, Real w) => IntMap w -> w -> ZDD a Source #
Set of all subsets whose sum of weights is exactly k.
Note that combinations
is a special case where all weights are 1.
If weight type is Integral
, subsetsExactlyIntegral
is more efficient.
subsetsExactlyIntegral :: forall a w. (ItemOrder a, Real w, Integral w) => IntMap w -> w -> ZDD a Source #
Similar to subsetsExactly
but more efficient.
Insertion
insert :: forall a. ItemOrder a => IntSet -> ZDD a -> ZDD a Source #
Insert a set into the ZDD.
>>>
toSetOfIntSets (insert (IntSet.fromList [1,2,3]) (fromListOfIntSets (map IntSet.fromList [[1,3], [2,4]])) :: ZDD AscOrder)
fromList [fromList [1,2,3],fromList [1,3],fromList [2,4]]
Deletion
delete :: forall a. ItemOrder a => IntSet -> ZDD a -> ZDD a Source #
Delete a set from the ZDD.
>>>
toSetOfIntSets (delete (IntSet.fromList [1,3]) (fromListOfIntSets (map IntSet.fromList [[1,2,3], [1,3], [2,4]])) :: ZDD AscOrder)
fromList [fromList [1,2,3],fromList [2,4]]
Query
member :: forall a. ItemOrder a => IntSet -> ZDD a -> Bool Source #
Is the set a member of the family?
size :: Integral b => ZDD a -> b Source #
The number of sets in the family.
Any Integral
type can be used as a result type, but it is recommended to use
Integer
or Natural
because the size can be larger than Int64
for example:
>>>
size (subsets (IntSet.fromList [1..128]) :: ZDD AscOrder) :: Integer
340282366920938463463374607431768211456>>>
import Data.Int
>>>
maxBound :: Int64
9223372036854775807
isSubsetOf :: ItemOrder a => ZDD a -> ZDD a -> Bool Source #
(s1 `isSubsetOf` s2)
indicates whether s1
is a subset of s2
.
isProperSubsetOf :: ItemOrder a => ZDD a -> ZDD a -> Bool Source #
(s1 `isProperSubsetOf` s2)
indicates whether s1
is a proper subset of s2
.
disjoint :: ItemOrder a => ZDD a -> ZDD a -> Bool Source #
Check whether two families are disjoint (i.e., their intersection is empty).
Combine
unions :: forall f a. (Foldable f, ItemOrder a) => f (ZDD a) -> ZDD a Source #
Unions of a list of ZDDs.
intersection :: forall a. ItemOrder a => ZDD a -> ZDD a -> ZDD a Source #
Intersection of two family of sets.
difference :: forall a. ItemOrder a => ZDD a -> ZDD a -> ZDD a Source #
Difference of two family of sets.
nonSuperset :: forall a. ItemOrder a => ZDD a -> ZDD a -> ZDD a Source #
Given a family P and Q, it computes {S∈P | ∀X∈Q. X⊈S}
Sometimes it is denoted as P ↘ Q.
>>>
toSetOfIntSets (fromListOfIntSets (map IntSet.fromList [[1,2,3], [1,3], [3,4]]) `nonSuperset` singleton (IntSet.fromList [1,3]) :: ZDD AscOrder)
fromList [fromList [3,4]]
Filter
subset1 :: forall a. ItemOrder a => Int -> ZDD a -> ZDD a Source #
Select subsets that contain a particular element and then remove the element from them
>>>
toSetOfIntSets $ subset1 2 (fromListOfIntSets (map IntSet.fromList [[1,2,3], [1,3], [2,4]]) :: ZDD AscOrder)
fromList [fromList [1,3],fromList [4]]
subset0 :: forall a. ItemOrder a => Int -> ZDD a -> ZDD a Source #
Subsets that does not contain a particular element
>>>
toSetOfIntSets $ subset0 2 (fromListOfIntSets (map IntSet.fromList [[1,2,3], [1,3], [2,4], [3,4]]) :: ZDD AscOrder)
fromList [fromList [1,3],fromList [3,4]]
Map
mapInsert :: forall a. ItemOrder a => Int -> ZDD a -> ZDD a Source #
Insert an item into each element set of ZDD.
>>>
toSetOfIntSets (mapInsert 2 (fromListOfIntSets (map IntSet.fromList [[1,2,3], [1,3], [1,4]])) :: ZDD AscOrder)
fromList [fromList [1,2,3],fromList [1,2,4]]
mapDelete :: forall a. ItemOrder a => Int -> ZDD a -> ZDD a Source #
Delete an item from each element set of ZDD.
>>>
toSetOfIntSets (mapDelete 2 (fromListOfIntSets (map IntSet.fromList [[1,2,3], [1,3], [1,2,4]])) :: ZDD AscOrder)
fromList [fromList [1,3],fromList [1,4]]
change :: forall a. ItemOrder a => Int -> ZDD a -> ZDD a Source #
change x p
returns {if x∈s then s∖{x} else s∪{x} | s∈P}
>>>
toSetOfIntSets (change 2 (fromListOfIntSets (map IntSet.fromList [[1,2,3], [1,3], [1,2,4]])) :: ZDD AscOrder)
fromList [fromList [1,2,3],fromList [1,3],fromList [1,4]]
(Co)algebraic structure
Signature functor of binary decision trees, BDD, and ZDD.
Instances
Fold
Unfold
unfoldHashable :: forall a b. (ItemOrder a, Eq b, Hashable b) => (b -> Sig b) -> b -> ZDD a Source #
Top-down construction of ZDD, memoising internal states using Hashable
instance.
unfoldOrd :: forall a b. (ItemOrder a, Ord b) => (b -> Sig b) -> b -> ZDD a Source #
Top-down construction of ZDD, memoising internal states using Ord
instance.
Minimal hitting sets
minimalHittingSets :: forall a. ItemOrder a => ZDD a -> ZDD a Source #
>>>
toSetOfIntSets (minimalHittingSets (fromListOfIntSets (map IntSet.fromList [[1], [2,3,5], [2,3,6], [2,4,5], [2,4,6]]) :: ZDD AscOrder))
fromList [fromList [1,2],fromList [1,3,4],fromList [1,5,6]]
minimalHittingSetsToda :: forall a. ItemOrder a => ZDD a -> ZDD a Source #
Minimal hitting sets.
- T. Toda, “Hypergraph Transversal Computation with Binary Decision Diagrams,” SEA 2013: Experimental Algorithms. Available: http://dx.doi.org/10.1007/978-3-642-38527-8_10.
- HTC-BDD: Hypergraph Transversal Computation with Binary Decision Diagrams https://www.disc.lab.uec.ac.jp/toda/htcbdd.html
minimalHittingSetsKnuth :: forall a. ItemOrder a => ZDD a -> ZDD a Source #
Minimal hitting sets.
D. E. Knuth, "The Art of Computer Programming, Volume 4A: Combinatorial Algorithms, Part 1," Addison-Wesley Professional, 2011.
minimalHittingSetsImai :: forall a. ItemOrder a => ZDD a -> ZDD a Source #
Minimal hitting sets.
T. Imai, "One-line hack of knuth's algorithm for minimal hitting set computation with ZDDs," vol. 2015-AL-155, no. 15, Nov. 2015, pp. 1-3. [Online]. Available: http://id.nii.ac.jp/1001/00145799/.
Random sampling
uniformM :: forall a g m. (ItemOrder a, StatefulGen g m, HasCallStack) => ZDD a -> g -> m IntSet Source #
Sample a set from uniform distribution over elements of the ZDD.
The function constructs a table internally and the table is shared across
multiple use of the resulting action (m IntSet
).
Therefore, the code
let g = uniformM zdd gen s1 <- g s2 <- g
is more efficient than
s1 <- uniformM zdd gen s2 <- uniformM zdd gen
.
Min/Max
findMinSum :: forall a w. (ItemOrder a, Num w, Ord w, HasCallStack) => (Int -> w) -> ZDD a -> (w, IntSet) Source #
Find a minimum element set with respect to given weight function
\[ \min_{X\in S} \sum_{x\in X} w(x) \]
findMaxSum :: forall a w. (ItemOrder a, Num w, Ord w, HasCallStack) => (Int -> w) -> ZDD a -> (w, IntSet) Source #
Find a maximum element set with respect to given weight function
\[ \max_{X\in S} \sum_{x\in X} w(x) \]
>>>
findMaxSum (IntMap.fromList [(1,2),(2,4),(3,-3)] IntMap.!) (fromListOfIntSets (map IntSet.fromList [[1], [2], [3], [1,2,3]]) :: ZDD AscOrder)
(4,fromList [2])
Misc
flatten :: ItemOrder a => ZDD a -> IntSet Source #
Unions of all member sets
>>>
flatten (fromListOfIntSets (map IntSet.fromList [[1,2,3], [1,3], [3,4]]) :: ZDD AscOrder)
fromList [1,2,3,4]
Conversion
Conversion from/to graphs
type Graph f = IntMap (f Int) Source #
Graph where nodes are decorated using a functor f
.
The occurrences of the parameter of f
represent out-going edges.
toGraph :: ZDD a -> (Graph Sig, Int) Source #
Convert a ZDD into a pointed graph
Nodes 0
and 1
are reserved for SLeaf False
and SLeaf True
even if
they are not actually used. Therefore the result may be larger than
numNodes
if the leaf nodes are not used.
toGraph' :: Traversable t => t (ZDD a) -> (Graph Sig, t Int) Source #
Convert multiple ZDDs into a graph
fromGraph' :: HasCallStack => Graph Sig -> IntMap (ZDD a) Source #
Convert nodes of a graph into ZDDs