Samuel Pastva
A gentle reminder that we should not forget this is still happening...
n Boolean variables—genes, proteins, other biochemical entities
Update functions—one per variable
m Boolean inputs/constants/parameters—arbitrary but fixed values
and others...
Bottom/Terminal strongly connected components
(attractors)
Single states, cycles, more complex sets...
Long-lived transients—other non-trivial SCCs
Different input valuations lead to different outcomes
Typically at least 2^50, often 2^100 or more in total
*Bryant, Randal E. "Graph-based algorithms for Boolean function manipulation." Computers, IEEE Transactions on 100.8 (1986): 677-691.
| x_1 | x_2 | x_3 |
|---|---|---|
| 1 | 0 | 1 |
| 1 | 0 | 0 |
| 0 | 1 | 1 |
Formula is satisfied exactly for valuations from the set
x_1
x_2
x_2
x_3
x_3
x_3
x_3
0
0
0
1
1
1
0
0
x_1
x_2
x_2
x_3
x_3
x_3
x_3
0
0
1
1
0
x_1
x_2
x_2
x_3
0
1
1
0
x_1
x_2
x_2
x_3
0
1
Canonical for each Boolean function (assuming fixed variable order)
Often exponentially smaller than the original tree or a DNF formula (not always)
(or relation)
O(n^2) in the number of BDD nodes (mostly)
Not the size of the set! (or formula/tree/etc.)
The first case is "practically" much better!
Nobody can usually give you these bounds...
def FWD(initial):
result = initial
next = PostAll(initial)
while next != result:
result = next
next = result.union(PostAll(result))
return result
def FWD(initial):
result = initial
done = False
while not done:
done = True
for i in [1,n]:
next = Post(i, result)
if not next.is_subset(result):
result = result.union(next)
done = False
return result
*Ciardo, Gianfranco, Gerald Lüttgen, and Radu Siminiceanu. "Saturation: an efficient iteration strategy for symbolic state—space generation." International Conference on Tools and Algorithms for the Construction and Analysis of Systems. Springer, Berlin, Heidelberg, 2001.
A simplified case for Boolean variables... more complex domains need extra loop here
SCC closed = If x is in the set, the whole SCC of x is in the set as well.
F = FWD(set) is SCC closed.
B = BWD(set) is SCC closed.
Intersection of F and B is SCC closed.
set
FWD(set)
BWD(set)
If set = {x}, then this intersection is exactly the SCC of x.
If FWD(set) minus set is empty, then the SCC is a BSCC
def SCC(universe):
if universe.is_empty():
return
pivot = Pick(universe)
F = FWD(pivot)
B = BWD(pivot)
W = F.intersect(B)
report(W)
SCC(F.minus(W))
SCC(B.minus(W))
SCC(universe.minus(F).minus(B))*Xie, Aiguo, and Peter A. Beerel. "Implicit enumeration of strongly connected components." 1999 IEEE/ACM International Conference on Computer-Aided Design. Digest of Technical Papers (Cat. No. 99CH37051). IEEE, 1999.
def BSCC(universe):
if universe.is_empty():
return
pivot = Pick(universe)
B = BWD(pivot)
F = pivot
while F.is_subset(B):
update = PostAll(F)
if update.is_subset(F):
break
F = F.union(update)
if F.is_subset(B):
report(F)
BSCC(universe.minus(B))B is computed fully, but for F, we only check if it is contained in B.
Ideally, this is using saturation instead
Pick one state per colour
Partition colours to two sets: one escapes B, the other trapped in B
def BSCC(universe):
if universe.is_empty():
return
pivot = Pick(universe)
B = BWD(pivot)
F = pivot
while F.is_subset(B):
update = PostAll(F)
if update.is_subset(F):
break
F = F.union(update)
if F.is_subset(B):
report(F)
BSCC(universe.minus(B))Even if BSCC is small, BWD is still limited by graph diameter.
Pivot selection problem: If the chance of hitting a bottom SCC is so small, what if we just selected more pivots at once?
def Reduce(universe):
pivots = ???
B = BWD(pivots)
F = FWD(pivots)
universe = universe.minus(B.minus(F))
S = F.minus(B)
B_S = BWD(S)
universe = universe.minus(B_S.minus(S))
return universe
All states that can update variable x:
(Transition Guided Reduction*)
*Beneš, Nikola, et al. "Computing bottom SCCs symbolically using transition guided reduction." International Conference on Computer Aided Verification. Springer, Cham, 2021.
Now we can continue reducing based on some other update function...
This also helps with the diameter problem:
This also helps with the diameter problem:
This also helps with the diameter problem:
BWD — one step
This also helps with the diameter problem:
FWD — two steps
This also helps with the diameter problem:
FWD — two steps
(Usually) not limited by graph diameter ⇒ distance between updates to the same variable instead.
Each reduction makes the next reductions easier ⇒ no need to reconsider eliminated states.
Any sate that can reach a single-state BSCC will be eventually eliminated.
Any state that can update a variable that is constant in some reachable BSCC will be eventually eliminated.
...but not all functions are created equal. Some reductions are still (symbolically) harder than others.
Can we somehow guess which reductions will be faster/better?
No? At least not really...
But we can just, well, run them all at once.
1. Run all reductions for each variable, one step at a time.
2. Always advance the reduction with the smallest intermediate BDD.
4. Profit
3. If one reduction eliminates some states, remove them from all reductions.
Extrapolating from 1024 single-coloured samples over a smaller subset of models...
Anywhere from 100x to 5000x speed-up compared to a parameter scan.