# Ruddy
Ruddy is a minimalistic, high-performance Rust library
for [(reduced and ordered) binary decision diagrams](https://en.wikipedia.org/wiki/Binary_decision_diagram) (BDDs),
which are a compact representation of Boolean functions.
> The name `Ruddy` is a blend of `BuDDy` (one of the first widely used BDD libraries) and `Rust`. However,
> `Ruddy` is not affiliated with the developers of `BuDDy` in any formal way. The name is meant merely as a tribute.
## Features
Most popular BDD implementations use a *shared* representation, where all BDD nodes are stored in a single pool managed
by a manager. This allows graphs shared between BDDs to be stored only once in memory. An alternative is the *split*
representation, where each BDD owns its nodes (e.g., as an array).
When BDDs do not meaningfully share nodes, split representations can be faster and more memory-efficient. Ruddy
implements both representations, letting users choose what works best for their use case.
Currently, Ruddy supports the following features:
- Binary logical operators (conjunction, xor, ...) and negation.
- Existential and universal quantification, also combined with a binary operator (also called *relational product*).
- Satisfying valuations and paths iterators along with methods to count them.
- Export to DOT.
- Conversion between split and shared BDDs.
- Binary and text (de)serialization of split BDDs.
## Usage
An example of using the Ruddy split implementation:
```rust
use ruddy::split::Bdd;
use ruddy::VariableId;
fn example_split() {
// Create two variables v0 and v1.
let v0 = VariableId::new(0);
let v1 = VariableId::new(1);
// Make the BDDs representing `v0=true` and `v1=true`.
let a = Bdd::new_literal(v0, true);
let b = Bdd::new_literal(v1, true);
// Calculate BDD `a => b`.
let imp = a.implies(&b);
// Calculate BDD `!a ∨ b`.
let equiv_imp = a.not().or(&b);
// Check that they are equivalent.
assert!(imp.iff(&equiv_imp).is_true());
}
```
The same example, using the shared implementation:
```rust
use ruddy::shared::BddManager;
use ruddy::VariableId;
fn example_shared() {
// Create the manager.
let mut manager = BddManager::new();
// Create two variables v0 and v1.
let v0 = VariableId::new(0);
let v1 = VariableId::new(1);
// Make the BDDs representing `v0=true` and `v1=true`.
let a = manager.new_bdd_literal(v0, true);
let b = manager.new_bdd_literal(v1, true);
// Calculate BDD `a => b`.
let imp = manager.implies(&a, &b);
// Calculate BDD `!a ∨ b`.
let not_a = manager.not(&a);
let equiv_imp = manager.or(¬_a, &b);
// Check that they are equivalent.
assert!(imp == equiv_imp);
}
```
More complex examples can be found in the `examples` folder.