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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use super::*;
use std::collections::HashMap;
use std::convert::TryInto;
impl BddVariableSetBuilder {
pub fn new() -> BddVariableSetBuilder {
BddVariableSetBuilder {
var_names: Vec::new(),
var_names_set: HashSet::new(),
}
}
pub fn make_variable(&mut self, name: &str) -> BddVariable {
let new_variable_id = self.var_names.len();
if new_variable_id >= (u16::MAX - 1) as usize {
panic!(
"Too many BDD variables. There can be at most {} variables.",
u16::MAX - 1
)
}
if self.var_names_set.contains(name) {
panic!("BDD variable {} already exists.", name);
}
if name.chars().any(|c| NOT_IN_VAR_NAME.contains(&c)) {
panic!(
"Variable name {} is invalid. Cannot use {:?}",
name, NOT_IN_VAR_NAME
);
}
self.var_names_set.insert(name.to_string());
self.var_names.push(name.to_string());
BddVariable(new_variable_id as u16)
}
pub fn make<const X: usize>(&mut self, names: &[&str; X]) -> [BddVariable; X] {
self.make_variables(names).try_into().unwrap()
}
pub fn make_variables(&mut self, names: &[&str]) -> Vec<BddVariable> {
names.iter().map(|name| self.make_variable(name)).collect()
}
pub fn build(self) -> BddVariableSet {
let mut mapping: HashMap<String, u16> = HashMap::new();
for name_index in 0..self.var_names.len() {
let name = self.var_names[name_index].clone();
mapping.insert(name, name_index as u16);
}
BddVariableSet {
num_vars: self.var_names.len() as u16,
var_names: self.var_names,
var_index_mapping: mapping,
}
}
}
impl Default for BddVariableSetBuilder {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[should_panic]
fn bdd_variables_builder_too_large() {
let mut builder = BddVariableSetBuilder::new();
for i in 0..u16::MAX {
builder.make_variable(&format!("v{}", i));
}
}
#[test]
#[should_panic]
fn bdd_variables_builder_duplicate_variable() {
let mut builder = BddVariableSetBuilder::new();
builder.make_variable("var1");
builder.make_variable("var1");
}
#[test]
fn bdd_variables_builder() {
let mut builder = BddVariableSetBuilder::new();
let v1 = builder.make_variable("v1");
let v2 = builder.make_variable("v2");
let v3 = builder.make_variable("v3");
let variables = builder.build();
assert_eq!(3, variables.num_vars());
assert_eq!(Some(v1), variables.var_by_name("v1"));
assert_eq!(Some(v2), variables.var_by_name("v2"));
assert_eq!(Some(v3), variables.var_by_name("v3"));
assert_eq!(None, variables.var_by_name("v4"));
}
#[test]
fn bdd_variables_builder_batch() {
let mut builder = BddVariableSetBuilder::new();
let [v1, v2, v3] = builder.make(&["v1", "v2", "v3"]);
let variables = builder.build();
assert_eq!(3, variables.num_vars());
assert_eq!(Some(v1), variables.var_by_name("v1"));
assert_eq!(Some(v2), variables.var_by_name("v2"));
assert_eq!(Some(v3), variables.var_by_name("v3"));
assert_eq!(None, variables.var_by_name("v4"));
}
#[test]
#[should_panic]
fn bdd_variables_builder_invalid_name() {
let mut builder = BddVariableSetBuilder::new();
builder.make_variable("a^b");
}
}