Open Ravenslofty opened 3 years ago
From the part of the DAG shown above, this looks like the classical variable-ordering problem with ROBDDs: the size of the BDD can depend heavily on whether one variable or the other comes first. In the worst case one can have exponential blowup if one chooses the wrong order.
The efficient operations on BDDs depend on variables always existing in a certain order in any path from a root to a terminal; so unfortunately we can't arbitrarily reorder nodes in certain subsets of the DAG. However, we could choose a different variable order overall.
Like most good things, the fun is spoiled here by the fact that doing so optimally is NP-hard, unfortunately...
However, there's plenty of prior work on how to do this optimization; I'm happy to review code if someone wants to try to build a variable-order optimization framework!
Well, I took a look at the paper on sifting and dynamic variable-order optimisation, but I think it runs into a design problem with boolean_expression
- the user has indexes into the BDD (BDDFunc
) which would be invalidated if the BDD order was changed, if I'm understanding correctly.
Yes, that's a fundamental problem if you want to do things on the fly -- the data structure is immutable (which is what allows us to dedup); a BDDFunc
always refers to the same node contents. But it would be reasonable to provide a batch optimization API, I think -- basically, take one BDD, decide on a new variable order, build a new BDD, and return a map from old BDDFunc
to new BDDFunc
indices.
Here's my example program:
If you look at the output dot, there's a lot of duplication of things like the
a_select
andb_select
muxes, much of which I would argue is unnecessary.From this snippet of the output, it seems to me that all the "b_inv is true" nodes can be merged and all the "b_inv is false" nodes can be merged. If you then recursively follow this upwards, this would remove a lot of redundancy.