1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
//! # Creating a `BddVariableSet` and `BddVariable`s
//!
//! In order to create and manipulate `Bdd`s, you have to first create a `BddVariableSet`.
//! The set maintains knowledge about individual Boolean variables and their ordering.
//! Once the set is created, it is immutable.
//!
//! ## Using `BddVariableSetBuilder`
//!
//! There are multiple ways to create a `BddVariableSet`. First is to initialize the set with
//! explicitly named variables using a safe builder:
//! ```rust
//! use biodivine_lib_bdd::BddVariableSetBuilder;
//!
//! let mut var = BddVariableSetBuilder::new();
//! let v1 = var.make_variable("v1");                   // a new individual variable
//! let [v2, v3] = var.make(&["v2", "v3"]);             // a new batch of variables
//! let var_set = var.build();
//!
//! assert_eq!(Some(v1), var_set.var_by_name("v1"));
//! assert_eq!(None, var_set.var_by_name("unknown"));
//! ```
//!
//! Here, each `BddVariable` (`v1` and elements of `vars`) can be later used to create
//! `Bdd`s conditioning on these variables. The purpose of the set builder is to check for
//! duplicate or invalid variable names (some special characters are also not allowed because
//! it would break export to `.dot`). Once the set is created, you can use `var_by_name` to
//! obtain a specific variable based on the names you used.
//!
//! ## Creating the set directly
//!
//! If you don't need the `BddVariable` objects right away and all variables are known beforehand
//! (this may sound trivial, but sometimes different parts of your application can have different
//! requirements regarding the variables and it is just simpler to let them manipulate the builder
//! directly instead of collecting all the variable names in one place),
//! you can also skip the builder and just provide the names explicitly:
//!
//! ```rust
//! use biodivine_lib_bdd::BddVariableSet;
//!
//! let variables = BddVariableSet::new(&["v1", "v2", "v3"]);
//! assert_eq!(3, variables.num_vars());
//! ```
//!
//! ## Anonymous sets
//!
//! Finally, another option is to create an anonymous variable set, where the
//! variables have default names:
//!
//! ```rust
//! use biodivine_lib_bdd::BddVariableSet;
//!
//! let variables = BddVariableSet::new_anonymous(4);   // new set with 4 variables
//!
//! let vars = variables.variables();
//! assert_eq!(4, vars.len());
//! assert_eq!("x_3", variables.name_of(vars[3]));   // default name is always x_{var index}
//! ```
//!
//! By default, anonymous variables are named `x_{index}`, but you can use `name_of` to
//! obtain the name of any variable at runtime. You can also use the `variables` function to get
//! a vector of all available variables.
//!
//! ## Working with variable sets
//!
//! Once we have a variable set, we can use it to create basic `Bdd` objects:
//!
//! ```rust
//! use biodivine_lib_bdd::BddVariableSet;
//!
//! let set = BddVariableSet::new_anonymous(4);
//! let v = set.variables();
//!
//! let tt = set.mk_true();     // constant true formula
//! let v0 = set.mk_var(v[0]);  // bdd for formula (v0)
//! let not_v1 = set.mk_not_var_by_name("x_1"); // bdd for formula (!v1)
//! ```
//!
//! In order to create complex boolean combinations of these basic `Bdd`s, we can use different
//! techniques which are described in the next section of this tutorial.
//!
//! **Notice that `BddVariableSet` can be cloned.** This creates a new set with the exact same
//! variables. The `BddVariable` and `Bdd` objects can be then used with both the original
//! and cloned set interchangeably. `Bdd` objects are also cloneable (since they are just
//! vectors of BDD nodes) and can be used with any compatible `BddVariableSet`. This way, you can
//! quickly and easily share BDDs between different threads (each thread has its own clone of
//! the `BddVariableSet`).
//!