Hi there all,
Since I started using BDDs in automata, I have faced the following computational problem a few times. If you have any insight on how to solve it more efficiently, I'd be very interested. In particular, is there a spot in spot where this is implemented? Let me spell the problem out in general terms, then tie it to BDDs.
Definitions.
- A collection C of sets over a finite universe U is *unambiguous* if all sets in C are pairwise disjoint. In other words, C is a partition of the union of its sets.
- A collection C' refines a collection C if each set in C can be obtained as the union of sets in C'.
Problem.
Given a collection C, compute a (minimal) unambiguous refinement of C.
[[For complexity purposes, the computational task can also be written as:
Given C and k, does there exist an unambiguous refinement of C of size < k?
This is certainly NP-complete ([SP7] in Garey and Johnson is that problem without "unambiguous").]]
Motivation.
In BDDs, my use case is to have C be a collection of BDDs and a BDD represent the set of its satisfying assignments.
Building an unambiguous refinement of BDDs seems an essential step in determinization: If I have a state with two outgoing transitions labeled with BDDs {F, G} such that F&G is not False, then this state is nondeterministic. To determinize it, we will have to consider the transition labels {F&G, F&!G, !F&G}. Note that this set refines {F, G}, since F = (F&G)|(F&!G) and similarly for G.
Question.
What is known about that problem? Is there a good heuristic for it that would give an unambiguous refinement not far from the optimal?
Implementations.
I implemented it in a few different ways and would be interested in alternative implementations. Two options I have are:
- The straightforward way:
1. C' = {U} (recall that U is our universe, with BDDs this would be True)
2. for each S in C:
3. for each S' in C':
4. if (S cap S' is not empty)
5. Remove S' from C'
6. Add (S cap S') and (S^c cap S') to C' (^c denotes complement).
- A slightly more complex implementation.
I encode C' as a BDD itself, introducing lots of fresh variables; namely, if C' = {F, G} for two BDDs F and G, I introduce two fresh variables X_F and X_G, and encode C' as (F & X_F) | (G & X_G). This allows lines 3 and 4 to become:
3. Compute C' & S and project it on the X_? variables.
4. Iterate through each of the variables that appear: if X_S' appears, this means that S cap S' is nonempty.
Thanks for reading!
Cheers,
Michaël