MCPcopy Index your code
hub / github.com/OxiDD/oxidd

github.com/OxiDD/oxidd @v0.11.2

Chat with this repo
repository ↗ · DeepWiki ↗ · release v0.11.2 ↗ · + Follow
2,723 symbols 7,450 edges 154 files 718 documented · 26%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

OxiDD

Matrix

OxiDD is a highly modular decision diagram framework written in Rust. The most prominent instance of decision diagrams is provided by (reduced ordered) binary decision diagrams (BDDs), which are succinct representations of Boolean functions 𝔹n → 𝔹. Such BDD representations are canonical and thus, deciding equality of Boolean functions—in general a co-NP-complete problem—can be done in constant time. Further, many Boolean operations on two BDDs f,g are possible in 𝒪(|f| · |g|) (where |f| denotes the node count in f). There are various other kinds of decision diagrams for which OxiDD aims to be a framework enabling high-performance implementations with low effort.

Features

  • Several kinds of (reduced ordered) decision diagrams are already implemented:
    • Binary decision diagrams (BDDs)
    • BDDs with complement edges (BCDDs)
    • Zero-suppressed BDDs (ZBDDs, aka ZDDs/ZSDDs)
    • Multi-terminal BDDs (MTBDDs, aka ADDs)
    • Ternary decision diagrams (TDDs)
  • Extensibility: Due to OxiDD’s modular design, one can implement new kinds of decision diagrams without having to reimplement core data structures.
  • Concurrency: Functions represented by DDs can safely be used in multi-threaded contexts. Furthermore, apply algorithms can be executed on multiple CPU cores in parallel.
  • Performance: Compared to other popular BDD libraries (e.g., BuDDy, CUDD, and Sylvan), OxiDD is already competitive or even outperforms them.
  • Visualization: Display your DDs with ease through OxiDD-vis.
  • Support for Reordering: OxiDD can reorder a decision diagram to a given variable order. Support for dynamic reordering, e.g., via sifting, is about to come.

Getting Started

Constructing a BDD for the formula (x₀ ∧ x₁) ∨ x₂ works as follows:

// Create a manager for up to 2048 nodes, up to 1024 apply cache entries, and
// use 8 threads for the apply algorithms. In practice, you would choose higher
// capacities depending on the system resources.
let manager_ref = oxidd::bdd::new_manager(2048, 1024, 8);
// First, we create variables. This is done in two steps: `manager.add_vars()`
// adds levels to the decision diagram, `BDDFunction::var()` creates the DD
// nodes.
// The APIs are designed such that out-of-memory situations can be handled
// gracefully. In principle, every operation creating nodes can fail, including
// `BDDFunction::var()`. Hence, we call `AllocResult::from_iter()` instead of
// `Vec::from_iter()` and have the `?` operator at the end of this statement.
let x: Vec<BDDFunction> = manager_ref.with_manager_exclusive(|manager| {
    AllocResult::from_iter(manager.add_vars(3).map(|i| BDDFunction::var(manager, i)))
})?;
// Now, we actually compute the conjunction (again with `?` for allocation error
// handling):
let res = x[0].and(&x[1])?.or(&x[2])?;
println!("{}", res.satisfiable());

(We will add a more elaborate guide in the future.)

Project Structure

The main code is located in the crates directory. The framework is centered around a bunch of core traits, found in the oxidd-core crate. These traits are the abstractions enabling to easily swap one component by another, as indicated by the dependency graph below. The data structure in which DD nodes are stored is mostly defined by the oxidd-manager-index crate. There is also the oxidd-manager-pointer crate, which contains an alternative implementation (here, the edges are represented by pointers instead of 32 bit indices). Implementations of the apply cache can be found in the oxidd-cache crate. Reduction rules and main algorithms of the various DD kinds are implemented in the oxidd-rules-* crates. There are different ways how all the components can be “plugged” together. The oxidd crate provides sensible default instantiations for the end user. There are a few more crates, but the aforementioned are the most important ones.

Crate Dependency Graph

Besides the Rust code, there are also bindings for C/C++ and Python (located in the bindings directory with the corresponding Rust part in crates/oxidd-ffi-*). The bindings do not expose the entire API that can be used from Rust, but it is sufficient to, e.g., create BDDs and apply various logical operators on them. In principle, you can use the C FFI from any language that can call C functions. However, there are also more ergonomic C++ bindings built on top of the C FFI. To use them, you can just use include this repository using CMake. For Python, the easiest way is to use the package on PyPI.

FAQ

Q: What about bindings for language X?

As mentioned above, OxiDD already supports C/C++ and Python. C# and Java bindings might follow later this year. If you want to use OxiDD from a different language, please contact us. We would really like to support you and your use-case.

Q: What about dynamic/automatic reordering?

OxiDD already supports reordering in the sense of establishing a given variable order. Implementing this without introducing unsafe code in the algorithms applying operators, adding rather expensive synchronization mechanisms, or disabling concurrency entirely was a larger effort. More details on that can be found in our paper. But now, adding reordering heuristics such as sifting is a low-hanging fruit. Next up, we will also work on dynamic reordering (i.e., aborting operations for reordering and restarting them afterwards) and automatic reordering (i.e., heuristics that identify points in time where dynamic reordering is beneficial).

Licensing

OxiDD is licensed under either MIT or Apache 2.0 at your opinion.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this project by you, as defined in the Apache 2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Publications

The seminal paper presenting OxiDD was published at TACAS'24. If you use OxiDD, please cite us as:

Nils Husung, Clemens Dubslaff, Holger Hermanns, and Maximilian A. Köhl: OxiDD: A safe, concurrent, modular, and performant decision diagram framework in Rust. In: Proceedings of the 30th International Conference on Tools and Algorithms for the Construction and Analysis of Systems (TACAS’24)

@inproceedings{oxidd24,
  author        = {Husung, Nils and Dubslaff, Clemens and Hermanns, Holger and K{\"o}hl, Maximilian A.},
  booktitle     = {Proceedings of the 30th International Conference on Tools and Algorithms for the Construction and Analysis of Systems (TACAS'24)},
  title         = {{OxiDD}: A Safe, Concurrent, Modular, and Performant Decision Diagram Framework in {Rust}},
  year          = {2024},
  doi           = {10.1007/978-3-031-57256-2_13}
}

Acknowledgements

This work is partially supported by the German Research Foundation (DFG) under the projects TRR 248 (see https://perspicuous-computing.science, project ID 389792660) and EXC 2050/1 (CeTI, project ID 390696704, as part of Germany’s Excellence Strategy).

Extension points exported contracts — how you extend this code

DiagramRules (Interface)
Reduction rules for decision diagrams This trait is intended to be implemented on a zero-sized type. Refer to [`Diagram [6 …
crates/oxidd-core/src/lib.rs
AsciiDisplay (Interface)
Like [`std::fmt::Display`], but the format should use ASCII characters only [6 implementers]
crates/oxidd-dump/src/lib.rs
Status (Interface)
Status of a slot in the hash table A status can either be free, a tombstone, or a hash value of the associated item. Th [2 …
crates/linear-hashtbl/src/raw.rs
TerminalManagerCons (Interface)
Terminal manager type constructor [2 implementers]
crates/oxidd-manager-index/src/manager.rs
AtomicRefCounted (Interface)
Atomically reference counted value # Safety The reference counter must be initialized to 1 (or a larger value, be awar [2 …
crates/arcslab/src/lib.rs
HasZBDDOpApplyCache (Interface)
Workaround for https://github.com/rust-lang/rust/issues/49601 [1 implementers]
crates/oxidd-rules-zbdd/src/apply_rec.rs
CManagerRef (Interface)
(no doc) [3 implementers]
crates/oxidd-ffi-c/src/util/mod.rs
StatisticsGenerator (Interface)
Trait for generating and printing statistics Implementors of this trait in this crate do not print anything unless the [1 …
crates/oxidd-cache/src/lib.rs

Core symbols most depended-on inside this repo

borrowed
called by 549
crates/oxidd-test-utils/src/edge.rs
with_manager_shared
called by 200
crates/oxidd-manager-index/src/manager.rs
get_node
called by 180
crates/oxidd-test-utils/src/edge.rs
len
called by 122
crates/oxidd-parser/src/lib.rs
clone_edge
called by 117
crates/oxidd-test-utils/src/edge.rs
push
called by 108
crates/oxidd-parser/src/tv_bitvec.rs
level
called by 106
crates/oxidd-core/src/lib.rs
iter
called by 90
crates/oxidd-parser/src/vec2d/mod.rs

Shape

Method 1,660
Function 637
Class 308
Interface 60
Enum 58

Languages

Rust87%
C++10%
Python3%

Modules by API surface

bindings/cpp/include/oxidd/bridge.hpp126 symbols
crates/oxidd-manager-index/src/manager.rs111 symbols
crates/oxidd-core/src/function.rs107 symbols
crates/oxidd-manager-pointer/src/manager.rs99 symbols
crates/oxidd-ffi-c/src/bdd.rs82 symbols
crates/oxidd-ffi-c/src/bcdd.rs82 symbols
crates/oxidd-parser/src/lib.rs79 symbols
crates/oxidd-ffi-c/src/zbdd.rs79 symbols
bindings/python/oxidd/protocols.py73 symbols
crates/oxidd-ffi-python/src/bdd.rs67 symbols
crates/oxidd-ffi-python/src/bcdd.rs67 symbols
crates/oxidd-ffi-python/src/zbdd.rs65 symbols

For agents

$ claude mcp add oxidd \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page