dcreager.net

Simplifying a BDD relative to an implication

[Andersen2011] is the canonical BDD introduction that I read during grad school.

https://www.cmi.ac.in/~madhavan/courses/verification-2011/andersen-bdd.pdf

It describes an algorithm called Simplify, which simplifies one BDD relation to another. That is, given two BDDs representing functions d and u, Simplify(d, u) returns another BDD u' where d ∧ u == d ∧ u'.

For constraint sets, d will be an implication describing that two individual constraints simplify relative to each other, c₁ → c₂. (If c₁ is true, then we know that c₂ is true as well.) The simplification will remove parts of the BDD where we make a redundant check on c₂ (that is, where we've already established that c₁ is true, and therefore don't need to check c₂).

Here we specialize the Simplify algorithm where d is fixed to the implication c₁ → c₂.

The text of the algorithm from [Andersen2011] is:

fn Simplify(d, u) {
  if d = 0 then return 0
  else if u ≤ 1 then return u
  else if d = 1 then
    return Mk(var(u), Simplify(d, low(u)), Simplify(d, high(u)))
  else if var(d) = var(u) then
    if low(d) = 0 then return Simplify(high(d), high(u))
    else if high(d) = 0 then return Simplify(low(d), low(u))
    else return Mk(var(u),
                   Simplify(low(d), low(u)),
                   Simplify(high(d), high(u)))
  else if var(d) < var(u) then
    return Mk(var(d), Simplify(low(d), u), Simplify(high(d), u))
  else
    return Mk(var(u), Simplify(d, low(u)), Simplify(d, high(u)))
}

There are two cases to consider: c₁ < c₂ and c₂ < c₁. (That is c₁ appears before or after c₂ in the BDD variable ordering; we're not talking about subtyping between the two constraints or the types they contain.)

Case 1: c₁ < c₂

d₁ = c₁ → c₂ = ¬c₁ ∨ c₂
var(d₁)  = c₁
low(d₁)  = 1
high(d₁) = d₂
var(d₂)  = c₂
low(d₂)  = 0
high(d₂) = 1
fn Simplify(d₁, u) {
  if u ≤ 1 then return u
  else if var(u) = c₁ then
    return Mk(c₁,
              Simplify(1, low(u)),
              Simplify(d₂, high(u)))
  else if c₁ < var(u) then
    return Mk(c₁, Simplify(1, u), Simplify(d₂, u))
  else
    return Mk(var(u), Simplify(d₁, low(u)), Simplify(d₁, high(u)))
}