Module TheoSource

Theory-Augmented Binary Decision Diagrams (BDDs)

This module provides an efficient implementation of Binary Decision Diagrams with support for theory reasoning over linear orders and equality (including booleans, strings, integers, semantic versions).

BDDs are canonical representations of boolean functions that enable efficient logical operations and satisfiability checking through hash-consing and memoization.

Features:

Example usage:

  module Theo = Theo.Make(Theo.Void)
  let open Theo.Syntax in
  let b1 = Theo.var Boolean in
  let b2 = Theo.var Boolean in
  let expr = Theo.atom b1 && not (Theo.atom b2) in
  if Theo.is_tautology expr then Printf.printf "Always true\n"
  else Printf.printf "Depends on variables\n"

Architecture: The library is built around a few core concepts:

Example: Combining Theories To use multiple theories (e.g., String equality and Version comparisons) in the same BDD:

  (* 1. Define your atomic types *)
  module StringAtom = struct ... end (* implements Comparable *)
  module VersionAtom = struct ... end (* implements Comparable *)

  (* 2. Instantiate primitive theories *)
  module StringEq = Theo.Eq(StringAtom)
  module VersionLeq = Theo.Leq(VersionAtom)

  (* 3. Combine them into a single theory *)
  module MyTheory = Theo.Combine(VersionLeq)(StringEq)

  (* 4. Create the BDD module *)
  module MyBDD = Theo.Make(MyTheory)

  (* 5. Instantiate syntax helpers for convenient construction *)
  (* Notice we pass parts of the sum theory to the helpers *)
  module V = VersionLeq.Syntax(MyTheory.Left(MyBDD))
  module S = StringEq.Syntax(MyTheory.Right(MyBDD))

  (* 6. Now you can mix them! *)
  let v_var = MyBDD.var ()
  let s_var = MyBDD.var ()
  let expr = MyBDD.and_ V.(v_var < v) S.(s_var = s)

Example: Working with Constraints You can also use the syntax modules to build restrict constraints, and pattern match on constraints using view_constraint.

  (* 1. Build constraint syntax helpers *)
  (* Instead of MyBDD, we pass MyBDD.Constraint to the syntax functors *)
  module V_cstr = VersionLeq.Syntax (MyTheory.Left (MyBDD.Constraint))
  module S_cstr = StringEq.Syntax (MyTheory.Right (MyBDD.Constraint))

  (* 2. Create constraints *)
  (* Note: These return atomic_constraint list, NOT a BDD *)
  let c1 = V_cstr.(v_var < v)
  let c2 = S_cstr.(s_var = s)

  (* 3. Combine constraints *)
  let constraints = MyBDD.Constraint.and_ c1 c2

  (* 4. Restrict a BDD *)
  let restricted_expr = MyBDD.restrict expr constraints

  (* 5. Introspection (Pattern Matching) *)
  let match_constraint (c : MyBDD.atomic_constraint) =
    match MyBDD.view_constraint c with
    | MyBDD.Constraint { var; payload = Bool; value } ->
        Printf.printf "Bool var %d = %b" var value
    | MyBDD.Constraint { var; payload = Theory desc; value } -> (
        (* 'desc' is a 'desc MyTheory.t' (the sum type) *)
        match desc with
        | MyTheory.Left (VersionLeq.Bound { limit; inclusive }) ->
            Printf.printf "Version <= %s is %b"
              (VersionAtom.to_string limit)
              value
        | MyTheory.Right (StringEq.Const s) ->
            Printf.printf "String = %s is %b" (StringAtom.to_string s) value
        )
Sourcemodule type Theory = sig ... end

The interface for theory atoms.

Variables

Sourcemodule Var : sig ... end

Global unique variables.

The Core BDD Engine

Sourcemodule Make (T : Theory) : sig ... end

Functor to create a BDD implementation for a specific theory.

Sourcemodule type Formula = sig ... end

The abstract interface for "formulas". This abstraction allows syntax helpers (like Leq.Syntax) to be reused with any BDD implementation that contains the appropriate theory.

Theory Composition

Sourcemodule Combine (A : Theory) (B : Theory) : sig ... end

Combine(A)(B) creates a new theory that is the sum of A and B. This allows a single BDD to reason about multiple types of atoms simultaneously.

An empty theory.

Primitive theories

Sourcemodule type Comparable = sig ... end

Input signature for primitive theories.

Sourcemodule type Primitive_theory = sig ... end

Augmented theory interface for primitive theories.

Sourcemodule Leq (C : Comparable) : sig ... end

The theory of linear order (<=, <, =, <>).

Sourcemodule Eq (C : Comparable) : sig ... end

The theory of equality (=, <>).