๐ŸŒณ Binary Decision Diagrams (BDDs)

Canonical representations of Boolean functions with memoized operations

Overview

BDDs are a compressed, canonical data structure for representing Boolean functions. A Reduced Ordered BDD (ROBDD) guarantees that two functions are equal if and only if their BDD nodes are identical, enabling O(1) equivalence checking. They are the workhorse of hardware verification, model checking, and symbolic computation.

This implementation provides hash-consing (unique table), the Apply algorithm for arbitrary Boolean operations, quantification, and an interactive REPL for exploring BDD construction.

Concepts Demonstrated

Core Types

type bdd =
  | Zero                        (* terminal false *)
  | One                         (* terminal true *)
  | Node of int * bdd * bdd     (* variable, low (0), high (1) *)

(* Unique table for hash-consing โ€” same structure โ†’ same node *)
let unique_table : (int * int * int, bdd) Hashtbl.t

Key Operations

OperationDescriptionComplexity
mk var low highCreate/lookup a BDD node (hash-consed)O(1) amortized
apply op a bCombine two BDDs with any Boolean opO(|a|ยท|b|)
restrict bdd var valueSet a variable to true/falseO(|bdd|)
exists var bddExistential quantificationO(|bdd|ยฒ)
sat_count bddCount satisfying assignmentsO(|bdd|)
all_sat bddEnumerate all solutionsO(solutions)
to_dot bddExport for Graphviz visualizationO(|bdd|)

How It Works

(* Build a BDD for (x1 AND x2) OR x3 *)
let x1 = var 1
let x2 = var 2
let x3 = var 3
let f = bdd_or (bdd_and x1 x2) x3

(* Equivalence check is O(1) โ€” compare node identity *)
let g = bdd_or x3 (bdd_and x1 x2)
(* f and g point to the SAME node thanks to canonicity *)

(* Count satisfying assignments *)
let n = sat_count f 3  (* 3 variables โ†’ 5 of 8 assignments satisfy f *)

Why BDDs?

Related Modules