Skip to main content
This is a pre-production deployment of Warehouse. Changes made here affect the production instance of PyPI (
Help us improve Python packaging - Donate today!

Library of decision diagrams and algorithms on them, in pure Python, as well as Cython bindings to CUDD, Sylvan, and BuDDy.

Project Description
[![Build Status][build_img]][travis]
[![Coverage Status][coverage]][coveralls]


A pure-Python (3 and 2) package for manipulating:

- [Binary decision diagrams]( (BDDs).
- [Multi-valued decision diagrams]( (MDDs).

as well as [Cython]( bindings to the C libraries:

- [CUDD](
- [Sylvan]( (multi-core parallelization)
- [BuDDy](

These bindings expose almost identical interfaces as the Python implementation.
The intended workflow is:

- develop your algorithm in pure Python (easy to debug and introspect),
- use the bindings to benchmark and deploy

Your code remains the same.


- All the standard functions defined, e.g.,
by [Bryant](
- Dynamic variable reordering using [Rudell's sifting algorithm](
- Reordering to obtain a given order.
- Parser of quantified Boolean expressions in either
[TLA+]( or
[Promela]( syntax.
- Pre/Image computation (relational product).
- Renaming variables.
- Conversion from BDDs to MDDs.
- Conversion functions to [`networkx`]( and
[`pydot`]( graphs.
- BDDs have methods to `dump` and `load` them using `pickle`.
- BDDs dumped by CUDD's DDDMP can be loaded using fast iterative parser.
- Garbage collection using reference counting

If you prefer to work with integer variables instead of Booleans, and have
BDD computations occur underneath, then use the module
from the [`omega` package](


In the [Markdown]( file


Two interfaces are available:

- convenience: the module
[`dd.autoref`]( wraps
`dd.bdd` and takes care of reference counting
using [`__del__`](

- "low level": the module
[`dd.bdd`]( requires that
the user in/decrement the reference counters associated with nodes that
are used outside of a `BDD`.

## Automated reference counting

The module `dd.autoref` wraps the pure-Python BDD implementation in `dd.bdd`.
A `Function` object wraps a node and decrements its reference count when
disposed by Python's garbage collector:

from dd.autoref import BDD, Function

bdd = BDD()
[bdd.add_var(var) for var in ['x', 'y']]
u = bdd.add_expr('x => y') # TLA+ syntax
u = bdd.add_expr('x -> y') # Promela syntax

# alternative
x = bdd.var('x')
not_x = ~ x
y = bdd.var('y')
v = not_x | y
assert u == v


The interface to CUDD in `dd.cudd` looks similar to `dd.autoref`,
including automated reference counting:

from dd import cudd

bdd = cudd.BDD()
[bdd.add_var(var) for var in ['x', y'']]
u = bdd.add_expr('\E x, y: x /\ y')
assert u == bdd.true, u

# longer alternative
xy = bdd.add_expr('x /\ y')
u = bdd.exist(['x', 'y'], xy)
assert u == bdd.true, u

## Reference counting by the user

The pure-Python module `dd.bdd` can be used directly,
which allows access more extensive than `dd.autoref`.
The `n` variables in a `dd.bdd.BDD` are ordered
from `0` (top level) to `n-1` (bottom level).
The terminal node `1` is at level `n`.

from dd.bdd import BDD

ordering = dict(x=0, y=1)
bdd = BDD(ordering)

Boolean expressions can be added with the method `BDD.add_expr`:

# using TLA+ syntax
u = bdd.add_expr('x \/ y')
v = bdd.add_expr('~ x \/ z')
w = bdd.apply('/\\', u, v)
r = bdd.apply('=>', u, w)

# using Promela syntax
u = bdd.add_expr('x | y')
v = bdd.add_expr('!x | z')
w = bdd.apply('&', u, v)
r = bdd.apply('->', u, w)

# w = bdd.apply('and', u, v) # also available

Garbage collection is triggered either explicitly by the user, or
when invoking the reordering algorithm.
If we invoked garbage collection next,
then the nodes `u`, `v`, `w` would be deleted.
To prevent this from happening, their reference counts should be incremented.
For example, if we want to prevent `w` from being collected as garbage, then


To decrement the reference count:


The more useful functions in `dd.bdd` are:
`image`, `preimage`, `reorder`, `to_nx`, `to_pydot`.

Use the method `BDD.dump` to write a `BDD` to a `pickle` file, and
`BDD.load` to load it back. A CUDD dddmp file can be loaded using
the function `dd.dddmp.load`.


## pure-Python

Recommended to use `pip`, because the latest version will install
dependencies before `dd`:

pip install dd


python install

If you use the latter, remember to install `ply` before `dd`.
If `ply` is absent, then the parser tables will not be cached, affecting performance.
For graph layout with `pydot`,
[graphviz]( needs to be installed.

## Cython bindings

### `dd` fetching CUDD

By default, the package installs only the Python modules.
You can select to install any Cython extensions using
the `` options:

- `--cudd`
- `--sylvan`
- `--buddy`

Pass `--fetch` to `` to tell it to download, unpack, and `make` CUDD v3.0.0. For example:

pip download dd --no-deps
tar xzf dd-*.tar.gz
cd dd-*
python install --fetch --cudd

The path to an existing CUDD build directory can be passed as an argument:

python install --cudd="/home/user/cudd"

If you prefer defining installation directories, then follow [Cython's instructions]( to define `CFLAGS` and `LDFLAGS` before running ``. You need to have copied `CuddInt.h` to the installation's include location (CUDD omits it).

If building from the repository, then first install `cython`.
For example:

git clone
cd dd
pip install cython # not needed if building from PyPI distro
python install --fetch --cudd

The above options can be passed to `pip` too, using the
in a requirements file, for example:

dd >= 0.1.1 --install-option="--fetch" --install-option="--cudd"

The command line behavior of `pip` [is currently different](, so

pip install --install-option="--fetch" dd

will propagate option `--fetch` to dependencies, and so raise an error.

### User installing build dependencies

If you build and install CUDD, Sylvan, or BuDDy yourself, then ensure that:

- the header files and libraries are present, and
- suitable compiler, include, linking, and library flags are passed,
either by setting [environment variables](
prior to calling `pip`, or by editing the file [``](

Currently, `` expects to find Sylvan under `dd/sylvan` and built with [Autotools]( (for an example, see `.travis.yml`).
If the path differs in your environment, remember to update it.


Require [`nose`]( and the extras. Run with:

cd tests/

If the extension module `dd.cudd` has not been compiled and installed,
then the CUDD tests will fail.

[BSD-3](, see file `LICENSE`.

Release History

Release History

This version
History Node


History Node


History Node


History Node


History Node


History Node


History Node


History Node


History Node


History Node


History Node


History Node


History Node


History Node


History Node


History Node


History Node


History Node


Download Files

Download Files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

File Name & Checksum SHA256 Checksum Help Version File Type Upload Date
dd-0.5.1.tar.gz (354.1 kB) Copy SHA256 Checksum SHA256 Source Mar 23, 2017

Supported By

WebFaction WebFaction Technical Writing Elastic Elastic Search Pingdom Pingdom Monitoring Dyn Dyn DNS Sentry Sentry Error Logging CloudAMQP CloudAMQP RabbitMQ Heroku Heroku PaaS Kabu Creative Kabu Creative UX & Design Fastly Fastly CDN DigiCert DigiCert EV Certificate Rackspace Rackspace Cloud Servers DreamHost DreamHost Log Hosting