1use itertools::Itertools;
8use std::cmp;
9use std::collections::hash_map::Entry as HashEntry;
10use std::collections::{BTreeSet, HashMap, HashSet};
11use std::fmt;
12use std::fmt::Debug;
13use std::hash::Hash;
14use std::usize;
15
16use cubes::{Cube, CubeList, CubeVar};
17use idd::*;
18use Expr;
19
20pub type BDDFunc = usize;
23
24pub const BDD_ZERO: BDDFunc = usize::MAX;
26pub const BDD_ONE: BDDFunc = usize::MAX - 1;
28
29pub(crate) type BDDLabel = usize;
30
31#[derive(Clone, PartialEq, Eq, Hash)]
32pub(crate) struct BDDNode {
33 pub label: BDDLabel,
34 pub lo: BDDFunc,
35 pub hi: BDDFunc,
36 pub varcount: usize,
37}
38
39fn bdd_func_str(b: BDDFunc) -> String {
40 if b == BDD_ZERO {
41 "ZERO".to_owned()
42 } else if b == BDD_ONE {
43 "ONE".to_owned()
44 } else {
45 format!("{}", b)
46 }
47}
48
49impl fmt::Debug for BDDNode {
50 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
51 write!(
52 f,
53 "BDDNode(label = {}, lo = {}, hi = {})",
54 self.label,
55 bdd_func_str(self.lo),
56 bdd_func_str(self.hi)
57 )
58 }
59}
60
61#[derive(Clone, Debug)]
62pub(crate) struct LabelBDD {
63 pub nodes: Vec<BDDNode>,
64 dedup_hash: HashMap<BDDNode, BDDFunc>,
65}
66
67impl LabelBDD {
68 pub fn new() -> LabelBDD {
69 LabelBDD {
70 nodes: Vec::new(),
71 dedup_hash: HashMap::new(),
72 }
73 }
74
75 fn get_node(&mut self, label: BDDLabel, lo: BDDFunc, hi: BDDFunc) -> BDDFunc {
76 if lo == hi {
77 return lo;
78 }
79 let n = BDDNode {
80 label: label,
81 lo: lo,
82 hi: hi,
83 varcount: cmp::min(self.sat_varcount(lo), self.sat_varcount(hi) + 1),
84 };
85 match self.dedup_hash.entry(n.clone()) {
86 HashEntry::Occupied(o) => *o.get(),
87 HashEntry::Vacant(v) => {
88 let idx = self.nodes.len() as BDDFunc;
89 self.nodes.push(n);
90 v.insert(idx);
91 idx
92 }
93 }
94 }
95
96 fn sat_varcount(&self, f: BDDFunc) -> usize {
97 if f == BDD_ZERO || f == BDD_ONE {
98 0
99 } else {
100 self.nodes[f].varcount
101 }
102 }
103
104 pub fn terminal(&mut self, label: BDDLabel) -> BDDFunc {
105 self.get_node(label, BDD_ZERO, BDD_ONE)
106 }
107
108 pub fn constant(&mut self, value: bool) -> BDDFunc {
109 if value {
110 BDD_ONE
111 } else {
112 BDD_ZERO
113 }
114 }
115
116 pub fn restrict(&mut self, f: BDDFunc, label: BDDLabel, val: bool) -> BDDFunc {
120 if f == BDD_ZERO {
121 return BDD_ZERO;
122 }
123 if f == BDD_ONE {
124 return BDD_ONE;
125 }
126
127 let node = self.nodes[f].clone();
128 if label < node.label {
129 f
130 } else if label == node.label {
131 if val {
132 node.hi
133 } else {
134 node.lo
135 }
136 } else {
137 let lo = self.restrict(node.lo, label, val);
138 let hi = self.restrict(node.hi, label, val);
139 self.get_node(node.label, lo, hi)
140 }
141 }
142
143 fn min_label(&self, f: BDDFunc) -> Option<BDDLabel> {
144 if f == BDD_ZERO || f == BDD_ONE {
145 None
146 } else {
147 Some(self.nodes[f].label)
148 }
149 }
150
151 pub fn ite(&mut self, i: BDDFunc, t: BDDFunc, e: BDDFunc) -> BDDFunc {
155 if i == BDD_ONE {
156 t
157 } else if i == BDD_ZERO {
158 e
159 } else if t == e {
160 t
161 } else if t == BDD_ONE && e == BDD_ZERO {
162 i
163 } else {
164 let i_var = self.min_label(i).unwrap_or(usize::MAX);
165 let t_var = self.min_label(t).unwrap_or(usize::MAX);
166 let e_var = self.min_label(e).unwrap_or(usize::MAX);
167 let split = cmp::min(i_var, cmp::min(t_var, e_var));
168 assert!(split != usize::MAX);
169 let i_lo = self.restrict(i, split, false);
170 let t_lo = self.restrict(t, split, false);
171 let e_lo = self.restrict(e, split, false);
172 let i_hi = self.restrict(i, split, true);
173 let t_hi = self.restrict(t, split, true);
174 let e_hi = self.restrict(e, split, true);
175 let lo = self.ite(i_lo, t_lo, e_lo);
176 let hi = self.ite(i_hi, t_hi, e_hi);
177 self.get_node(split, lo, hi)
178 }
179 }
180
181 pub fn not(&mut self, n: BDDFunc) -> BDDFunc {
182 self.ite(n, BDD_ZERO, BDD_ONE)
183 }
184
185 pub fn and(&mut self, a: BDDFunc, b: BDDFunc) -> BDDFunc {
186 self.ite(a, b, BDD_ZERO)
187 }
188
189 pub fn or(&mut self, a: BDDFunc, b: BDDFunc) -> BDDFunc {
190 self.ite(a, BDD_ONE, b)
191 }
192
193 pub fn xor(&mut self, a: BDDFunc, b: BDDFunc) -> BDDFunc {
194 let not_b = self.not(b);
195 self.ite(a, not_b, b)
196 }
197
198 pub fn implies(&mut self, a: BDDFunc, b: BDDFunc) -> BDDFunc {
199 let not_a = self.not(a);
200 self.or(not_a, b)
201 }
202
203 pub fn evaluate(&self, func: BDDFunc, inputs: &[bool]) -> Option<bool> {
204 let mut f = func;
205 for (i, val) in inputs.iter().enumerate() {
206 if f == BDD_ZERO || f == BDD_ONE {
207 break;
208 }
209 let node = &self.nodes[f];
210 if node.label > i {
211 continue;
212 } else if node.label == i {
213 f = if *val { node.hi } else { node.lo };
214 }
215 }
216 match f {
217 BDD_ZERO => Some(false),
218 BDD_ONE => Some(true),
219 _ => None,
220 }
221 }
222
223 fn compute_cubelist(&self, memoize_vec: &mut Vec<Option<CubeList>>, n: BDDFunc, nvars: usize) {
224 if memoize_vec[n].is_some() {
225 return;
226 }
227 let label = self.nodes[n].label;
228 let lo = self.nodes[n].lo;
229 let hi = self.nodes[n].hi;
230 let lo_list = match lo {
231 BDD_ZERO => CubeList::new(),
232 BDD_ONE => CubeList::from_list(&[Cube::true_cube(nvars)])
233 .with_var(label as usize, CubeVar::False),
234 _ => {
235 self.compute_cubelist(memoize_vec, lo, nvars);
236 memoize_vec[lo]
237 .as_ref()
238 .unwrap()
239 .with_var(label as usize, CubeVar::False)
240 }
241 };
242 let hi_list = match hi {
243 BDD_ZERO => CubeList::new(),
244 BDD_ONE => CubeList::from_list(&[Cube::true_cube(nvars)])
245 .with_var(label as usize, CubeVar::True),
246 _ => {
247 self.compute_cubelist(memoize_vec, hi, nvars);
248 memoize_vec[hi]
249 .as_ref()
250 .unwrap()
251 .with_var(label as usize, CubeVar::True)
252 }
253 };
254 let new_list = lo_list.merge(&hi_list);
255 memoize_vec[n] = Some(new_list);
256 }
257
258 fn cube_to_expr(&self, c: &Cube) -> Expr<BDDLabel> {
259 c.vars()
260 .enumerate()
261 .flat_map(|(i, v)| match v {
262 &CubeVar::False => Some(Expr::not(Expr::Terminal(i))),
263 &CubeVar::True => Some(Expr::Terminal(i)),
264 &CubeVar::DontCare => None,
265 })
266 .fold1(|a, b| Expr::and(a, b))
267 .unwrap_or(Expr::Const(true))
268 }
269
270 fn cubelist_to_expr(&self, c: &CubeList) -> Expr<BDDLabel> {
271 c.cubes()
272 .map(|c| self.cube_to_expr(c))
273 .fold1(|a, b| Expr::or(a, b))
274 .unwrap_or(Expr::Const(false))
275 }
276
277 pub fn to_expr(&self, func: BDDFunc, nvars: usize) -> Expr<BDDLabel> {
278 if func == BDD_ZERO {
279 Expr::Const(false)
280 } else if func == BDD_ONE {
281 Expr::Const(true)
282 } else {
283 let mut cubelists: Vec<Option<CubeList>> = Vec::with_capacity(self.nodes.len());
285 cubelists.resize(self.nodes.len(), None);
286 self.compute_cubelist(&mut cubelists, func, nvars);
287 self.cubelist_to_expr(cubelists[func].as_ref().unwrap())
288 }
289 }
290
291 pub fn max_sat(&mut self, funcs: &[BDDFunc]) -> BDDFunc {
294 let mut idd = LabelIDD::from_bdd(self);
299 let idd_funcs: Vec<_> = funcs.iter().map(|f| idd.from_bdd_func(*f)).collect();
300 let satisfied_count = idd_funcs
301 .iter()
302 .cloned()
303 .fold1(|a, b| idd.add(a.clone(), b.clone()))
304 .unwrap();
305
306 let max_count = idd.max_value(satisfied_count.clone());
308
309 let c = idd.constant(max_count);
312 idd.eq(satisfied_count, c, self)
313 }
314}
315
316#[derive(Clone, Debug)]
335pub struct BDD<T>
336where
337 T: Clone + Debug + Eq + Hash,
338{
339 bdd: LabelBDD,
340 labels: HashMap<T, BDDLabel>,
341 rev_labels: Vec<T>,
342}
343
344impl<T> BDD<T>
345where
346 T: Clone + Debug + Eq + Hash,
347{
348 pub fn new() -> BDD<T> {
350 BDD {
351 bdd: LabelBDD::new(),
352 labels: HashMap::new(),
353 rev_labels: Vec::new(),
354 }
355 }
356
357 fn label(&mut self, t: T) -> BDDLabel {
358 match self.labels.entry(t.clone()) {
359 HashEntry::Occupied(o) => *o.get(),
360 HashEntry::Vacant(v) => {
361 let next_id = self.rev_labels.len() as BDDLabel;
362 v.insert(next_id);
363 self.rev_labels.push(t);
364 next_id
365 }
366 }
367 }
368
369 pub fn terminal(&mut self, t: T) -> BDDFunc {
373 let l = self.label(t);
374 self.bdd.terminal(l)
375 }
376
377 pub fn constant(&mut self, val: bool) -> BDDFunc {
379 self.bdd.constant(val)
380 }
381
382 pub fn ite(&mut self, i: BDDFunc, t: BDDFunc, e: BDDFunc) -> BDDFunc {
385 self.bdd.ite(i, t, e)
386 }
387
388 pub fn not(&mut self, n: BDDFunc) -> BDDFunc {
391 self.bdd.not(n)
392 }
393
394 pub fn and(&mut self, a: BDDFunc, b: BDDFunc) -> BDDFunc {
397 self.bdd.and(a, b)
398 }
399
400 pub fn or(&mut self, a: BDDFunc, b: BDDFunc) -> BDDFunc {
403 self.bdd.or(a, b)
404 }
405
406 pub fn xor(&mut self, a: BDDFunc, b: BDDFunc) -> BDDFunc {
409 self.bdd.xor(a, b)
410 }
411
412 pub fn implies(&mut self, a: BDDFunc, b: BDDFunc) -> BDDFunc {
414 self.bdd.implies(a, b)
415 }
416
417 pub fn sat(&self, f: BDDFunc) -> bool {
419 match f {
420 BDD_ZERO => false,
421 _ => true,
422 }
423 }
424
425 pub fn restrict(&mut self, f: BDDFunc, t: T, val: bool) -> BDDFunc {
427 self.bdd.restrict(f, self.labels[&t], val)
428 }
429
430 pub fn from_expr(&mut self, e: &Expr<T>) -> BDDFunc {
433 match e {
434 &Expr::Terminal(ref t) => self.terminal(t.clone()),
435 &Expr::Const(val) => self.constant(val),
436 &Expr::Not(ref x) => {
437 let xval = self.from_expr(&**x);
438 self.not(xval)
439 }
440 &Expr::And(ref a, ref b) => {
441 let aval = self.from_expr(&**a);
442 let bval = self.from_expr(&**b);
443 self.and(aval, bval)
444 }
445 &Expr::Or(ref a, ref b) => {
446 let aval = self.from_expr(&**a);
447 let bval = self.from_expr(&**b);
448 self.or(aval, bval)
449 }
450 }
451 }
452
453 pub fn evaluate(&self, f: BDDFunc, values: &HashMap<T, bool>) -> bool {
456 let size = self.rev_labels.len();
457 let mut valarray = Vec::with_capacity(size);
458 valarray.resize(size, false);
459 for (t, l) in &self.labels {
460 valarray[*l as usize] = *values.get(t).unwrap_or(&false);
461 }
462 self.bdd.evaluate(f, &valarray).unwrap()
463 }
464
465 pub fn sat_one(&self, f: BDDFunc) -> Option<HashMap<T, bool>> {
475 let mut h = HashMap::new();
476 if self.sat_one_internal(f, &mut h) {
477 Some(h)
478 } else {
479 None
480 }
481 }
482
483 fn sat_one_internal(&self, f: BDDFunc, assignments: &mut HashMap<T, bool>) -> bool {
484 match f {
485 BDD_ZERO => false,
486 BDD_ONE => true,
487 _ => {
488 let hi = self.bdd.nodes[f].hi;
489 let lo = self.bdd.nodes[f].lo;
490 if hi != BDD_ZERO
491 && (lo == BDD_ZERO || self.bdd.sat_varcount(hi) < self.bdd.sat_varcount(lo))
492 {
493 assignments.insert(self.rev_labels[self.bdd.nodes[f].label].clone(), true);
494 self.sat_one_internal(hi, assignments);
495 } else {
496 assignments.insert(self.rev_labels[self.bdd.nodes[f].label].clone(), false);
497 self.sat_one_internal(lo, assignments);
498 }
499 true
500 }
501 }
502 }
503
504 pub fn to_expr(&self, f: BDDFunc) -> Expr<T> {
506 self.bdd
507 .to_expr(f, self.rev_labels.len())
508 .map(|t: &BDDLabel| self.rev_labels[*t as usize].clone())
509 }
510
511 pub fn to_dot(&self, f: BDDFunc) -> String {
513 let mut out = String::from("digraph bdd {\n");
517
518 let mut nodes = BTreeSet::new();
519 self.reachable_nodes(f, &mut nodes);
520 for func in nodes {
521 if func <= f {
522 out.push_str(&format!(
523 "n{} [label = {:?}];\n",
524 func, self.rev_labels[self.bdd.nodes[func].label]
525 ));
526 out.push_str(&format!(
527 "n{} -> n{} [style=dotted];\n",
528 func, self.bdd.nodes[func].lo
529 ));
530 out.push_str(&format!("n{} -> n{};\n", func, self.bdd.nodes[func].hi));
531 }
532 }
533
534 out.push_str(&format!("n{} [label=\"0\"];\n", BDD_ZERO));
535 out.push_str(&format!("n{} [label=\"1\"];\n", BDD_ONE));
536
537 out.push_str("}");
538
539 out.to_string()
540 }
541
542 fn reachable_nodes(&self, f: BDDFunc, s: &mut BTreeSet<BDDFunc>) {
545 if f != BDD_ZERO && f != BDD_ONE {
546 if s.insert(f) {
548 self.reachable_nodes(self.bdd.nodes[f].hi, s);
549 self.reachable_nodes(self.bdd.nodes[f].lo, s);
550 }
551 }
552 }
553
554 pub fn max_sat(&mut self, funcs: &[BDDFunc]) -> BDDFunc {
557 self.bdd.max_sat(funcs)
558 }
559
560 pub fn labels(&self) -> Vec<T> {
562 self.labels.keys().cloned().collect()
563 }
564}
565
566pub trait BDDOutput<T, E> {
571 fn write_label(&self, label: T, label_id: u64) -> Result<(), E>;
572 fn write_node(
573 &self,
574 node_id: BDDFunc,
575 label_id: u64,
576 lo: BDDFunc,
577 hi: BDDFunc,
578 ) -> Result<(), E>;
579}
580
581pub struct PersistedBDD<T>
586where
587 T: Clone + Debug + Eq + Hash,
588{
589 bdd: BDD<T>,
590 next_output_func: BDDFunc,
591 next_output_label: BDDLabel,
592}
593
594impl<T> PersistedBDD<T>
595where
596 T: Clone + Debug + Eq + Hash,
597{
598 pub fn new() -> PersistedBDD<T> {
600 PersistedBDD {
601 bdd: BDD::new(),
602 next_output_func: 0,
603 next_output_label: 0,
604 }
605 }
606
607 pub fn bdd(&self) -> &BDD<T> {
609 &self.bdd
610 }
611
612 pub fn bdd_mut(&mut self) -> &mut BDD<T> {
614 &mut self.bdd
615 }
616
617 pub fn persist<E>(&mut self, f: BDDFunc, out: &dyn BDDOutput<T, E>) -> Result<(), E> {
621 if f == BDD_ZERO || f == BDD_ONE {
622 return Ok(());
624 }
625 while self.next_output_label < self.bdd.rev_labels.len() {
626 let id = self.next_output_label;
627 let t = self.bdd.rev_labels[id].clone();
628 out.write_label(t, id as u64)?;
629 self.next_output_label += 1;
630 }
631 while self.next_output_func <= f {
632 let id = self.next_output_func;
633 let node = &self.bdd.bdd.nodes[id];
634 out.write_node(id, node.label as u64, node.lo, node.hi)?;
635 self.next_output_func += 1;
636 }
637 Ok(())
638 }
639
640 pub fn persist_all<E>(&mut self, out: &dyn BDDOutput<T, E>) -> Result<(), E> {
642 if self.bdd.bdd.nodes.len() > 0 {
643 let last_f = self.bdd.bdd.nodes.len() - 1;
644 self.persist(last_f, out)
645 } else {
646 Ok(())
647 }
648 }
649}
650
651pub struct BDDLoader<'a, T>
656where
657 T: Clone + Debug + Eq + Hash + 'a,
658{
659 bdd: &'a mut BDD<T>,
660}
661
662impl<'a, T> BDDLoader<'a, T>
663where
664 T: Clone + Debug + Eq + Hash + 'a,
665{
666 pub fn new(bdd: &'a mut BDD<T>) -> BDDLoader<'a, T> {
670 assert!(bdd.labels.len() == 0);
671 assert!(bdd.rev_labels.len() == 0);
672 assert!(bdd.bdd.nodes.len() == 0);
673 BDDLoader { bdd: bdd }
674 }
675
676 pub fn inject_label(&mut self, t: T, id: u64) {
680 assert!(id == self.bdd.rev_labels.len() as u64);
681 self.bdd.rev_labels.push(t.clone());
682 self.bdd.labels.insert(t, id as BDDLabel);
683 }
684
685 pub fn inject_node(&mut self, id: BDDFunc, label_id: u64, lo: BDDFunc, hi: BDDFunc) {
689 assert!(id == self.bdd.bdd.nodes.len() as BDDFunc);
690 let n = BDDNode {
691 label: label_id as BDDLabel,
692 lo: lo,
693 hi: hi,
694 varcount: cmp::min(
695 self.bdd.bdd.sat_varcount(lo),
696 self.bdd.bdd.sat_varcount(hi) + 1,
697 ),
698 };
699 self.bdd.bdd.nodes.push(n.clone());
700 self.bdd.bdd.dedup_hash.insert(n, id);
701 }
702}
703
704#[cfg(test)]
705mod test {
706 use super::*;
707 use std::cell::RefCell;
708 use std::collections::HashMap;
709 use Expr;
710 extern crate rand;
711 extern crate rand_xorshift;
712 use self::rand::{Rng, SeedableRng};
713 use self::rand_xorshift::XorShiftRng;
714
715 fn term_hashmap(vals: &[bool], h: &mut HashMap<u32, bool>) {
716 h.clear();
717 for (i, v) in vals.iter().enumerate() {
718 h.insert(i as u32, *v);
719 }
720 }
721
722 fn test_bdd(
723 b: &BDD<u32>,
724 f: BDDFunc,
725 h: &mut HashMap<u32, bool>,
726 inputs: &[bool],
727 expected: bool,
728 ) {
729 term_hashmap(inputs, h);
730 assert!(b.evaluate(f, h) == expected);
731 }
732
733 #[test]
734 fn bdd_eval() {
735 let mut h = HashMap::new();
736 let mut b = BDD::new();
737 let expr = Expr::or(
738 Expr::and(Expr::Terminal(0), Expr::Terminal(1)),
739 Expr::and(Expr::not(Expr::Terminal(2)), Expr::not(Expr::Terminal(3))),
740 );
741 let f = b.from_expr(&expr);
742 test_bdd(&b, f, &mut h, &[false, false, true, true], false);
743 test_bdd(&b, f, &mut h, &[true, false, true, true], false);
744 test_bdd(&b, f, &mut h, &[true, true, true, true], true);
745 test_bdd(&b, f, &mut h, &[false, false, false, true], false);
746 test_bdd(&b, f, &mut h, &[false, false, false, false], true);
747 }
748
749 fn bits_to_hashmap(bits: usize, n: usize, h: &mut HashMap<u32, bool>) {
750 for b in 0..bits {
751 h.insert(b as u32, (n & (1 << b)) != 0);
752 }
753 }
754
755 fn test_bdd_expr(e: Expr<u32>, nterminals: usize) {
756 let mut b = BDD::new();
757 let f = b.from_expr(&e);
758 let mut terminal_values = HashMap::new();
759 let mut expected_satisfiable = false;
760 for v in 0..(1 << nterminals) {
761 bits_to_hashmap(nterminals, v, &mut terminal_values);
762 let expr_val = e.evaluate(&terminal_values);
763 let bdd_val = b.evaluate(f, &terminal_values);
764 assert!(expr_val == bdd_val);
765 if expr_val {
766 expected_satisfiable = true;
767 }
768 }
769 let sat_result = b.sat_one(f);
771 assert!(sat_result.is_some() == expected_satisfiable);
772 if expected_satisfiable {
773 assert!(b.evaluate(f, &sat_result.unwrap()));
774 }
775 }
776
777 fn random_expr<R: Rng>(r: &mut R, nterminals: usize) -> Expr<u32> {
778 match r.gen_range(0, 5) {
779 0 => Expr::Terminal(r.gen_range(0, nterminals) as u32),
780 1 => Expr::Const(r.gen::<bool>()),
781 2 => Expr::Not(Box::new(random_expr(r, nterminals))),
782 3 => Expr::And(
783 Box::new(random_expr(r, nterminals)),
784 Box::new(random_expr(r, nterminals)),
785 ),
786 4 => Expr::Or(
787 Box::new(random_expr(r, nterminals)),
788 Box::new(random_expr(r, nterminals)),
789 ),
790 _ => unreachable!(),
791 }
792 }
793
794 #[test]
795 fn bdd_exhaustive_exprs() {
796 let mut rng = XorShiftRng::from_seed(rand::thread_rng().gen());
797 for _ in 0..100 {
798 let expr = random_expr(&mut rng, 6);
799 test_bdd_expr(expr, 6);
800 }
801 }
802
803 #[test]
804 fn bdd_to_expr() {
805 let mut b = BDD::new();
806 let f_true = b.constant(true);
807 assert!(b.to_expr(f_true) == Expr::Const(true));
808 let f_false = b.constant(false);
809 assert!(b.to_expr(f_false) == Expr::Const(false));
810 let f_0 = b.terminal(0);
811 let f_1 = b.terminal(1);
812 let f_and = b.and(f_0, f_1);
813 assert!(b.to_expr(f_and) == Expr::and(Expr::Terminal(0), Expr::Terminal(1)));
814 let f_or = b.or(f_0, f_1);
815 assert!(b.to_expr(f_or) == Expr::or(Expr::Terminal(1), Expr::Terminal(0)));
816 let f_not = b.not(f_0);
817 assert!(b.to_expr(f_not) == Expr::not(Expr::Terminal(0)));
818 let f_2 = b.terminal(2);
819 let f_1_or_2 = b.or(f_1, f_2);
820 let f_0_and_1_or_2 = b.and(f_0, f_1_or_2);
821 assert!(
822 b.to_expr(f_0_and_1_or_2)
823 == Expr::or(
824 Expr::and(Expr::Terminal(0), Expr::Terminal(2)),
825 Expr::and(Expr::Terminal(0), Expr::Terminal(1))
826 )
827 );
828 }
829
830 #[derive(Clone, Debug)]
831 struct InMemoryBDDLog {
832 labels: RefCell<Vec<(u64, String)>>,
833 nodes: RefCell<Vec<(BDDFunc, u64, BDDFunc, BDDFunc)>>,
834 }
835
836 impl InMemoryBDDLog {
837 pub fn new() -> InMemoryBDDLog {
838 InMemoryBDDLog {
839 labels: RefCell::new(Vec::new()),
840 nodes: RefCell::new(Vec::new()),
841 }
842 }
843 }
844
845 impl BDDOutput<String, ()> for InMemoryBDDLog {
846 fn write_label(&self, l: String, label_id: u64) -> Result<(), ()> {
847 let mut labels = self.labels.borrow_mut();
848 labels.push((label_id, l));
849 Ok(())
850 }
851
852 fn write_node(
853 &self,
854 node_id: BDDFunc,
855 label_id: u64,
856 lo: BDDFunc,
857 hi: BDDFunc,
858 ) -> Result<(), ()> {
859 let mut nodes = self.nodes.borrow_mut();
860 nodes.push((node_id, label_id, lo, hi));
861 Ok(())
862 }
863 }
864
865 #[test]
866 fn dot_output() {
868 let mut bdd = BDD::new();
869 let a = bdd.terminal("a");
870 let b = bdd.terminal("b");
871 let b_and_a = bdd.and(a, b);
872 {
873 let dot = bdd.to_dot(b_and_a);
874 assert_eq!(
875 dot,
876 indoc!(
877 "
878 digraph bdd {
879 n1 [label = \"b\"];
880 n1 -> n18446744073709551615 [style=dotted];
881 n1 -> n18446744073709551614;
882 n2 [label = \"a\"];
883 n2 -> n18446744073709551615 [style=dotted];
884 n2 -> n1;
885 n18446744073709551615 [label=\"0\"];
886 n18446744073709551614 [label=\"1\"];
887 }"
888 )
889 );
890 }
891 let c = bdd.terminal("c");
892 let c_or_a = bdd.or(c, a);
893 {
894 let dot = bdd.to_dot(c_or_a);
895 assert_eq!(
896 dot,
897 indoc!(
898 "
899 digraph bdd {
900 n3 [label = \"c\"];
901 n3 -> n18446744073709551615 [style=dotted];
902 n3 -> n18446744073709551614;
903 n4 [label = \"a\"];
904 n4 -> n3 [style=dotted];
905 n4 -> n18446744073709551614;
906 n18446744073709551615 [label=\"0\"];
907 n18446744073709551614 [label=\"1\"];
908 }"
909 )
910 );
911 }
912 let not_c_and_b = bdd.not(b_and_a);
913 let c_or_a_and_not_b_and_a = bdd.and(c_or_a, not_c_and_b);
914 {
915 let dot = bdd.to_dot(c_or_a_and_not_b_and_a);
916 assert_eq!(
917 dot,
918 indoc!(
919 "
920 digraph bdd {
921 n3 [label = \"c\"];
922 n3 -> n18446744073709551615 [style=dotted];
923 n3 -> n18446744073709551614;
924 n5 [label = \"b\"];
925 n5 -> n18446744073709551614 [style=dotted];
926 n5 -> n18446744073709551615;
927 n7 [label = \"a\"];
928 n7 -> n3 [style=dotted];
929 n7 -> n5;
930 n18446744073709551615 [label=\"0\"];
931 n18446744073709551614 [label=\"1\"];
932 }"
933 )
934 );
935 }
936 {
937 let new_a = bdd.terminal("a");
938 let d = bdd.terminal("d");
939 let new_a_or_d = bdd.or(new_a, d);
940 let dot = bdd.to_dot(new_a_or_d);
941 assert_eq!(
942 dot,
943 indoc!(
944 "
945 digraph bdd {
946 n8 [label = \"d\"];
947 n8 -> n18446744073709551615 [style=dotted];
948 n8 -> n18446744073709551614;
949 n9 [label = \"a\"];
950 n9 -> n8 [style=dotted];
951 n9 -> n18446744073709551614;
952 n18446744073709551615 [label=\"0\"];
953 n18446744073709551614 [label=\"1\"];
954 }"
955 )
956 );
957 }
958 }
959
960 #[test]
961 fn sat_one() {
962 let mut bdd = BDD::new();
963
964 assert!(bdd.sat_one(BDD_ONE).is_some());
966 assert!(bdd.sat_one(BDD_ZERO).is_none());
967
968 let a = bdd.terminal("a");
969 let b = bdd.terminal("b");
970 let b_and_a = bdd.and(a, b);
971 let result = bdd.sat_one(b_and_a);
972 assert!(result.is_some());
973 assert!(bdd.evaluate(b_and_a, &result.unwrap()));
974
975 let c = bdd.terminal("c");
976 let not_c = bdd.not(c);
977 let b_and_a_or_not_c = bdd.or(b_and_a, not_c);
978 let result = bdd.sat_one(b_and_a_or_not_c);
979 assert!(result.is_some());
980 assert!(bdd.evaluate(b_and_a_or_not_c, &result.unwrap()));
981
982 let c_and_not_c = bdd.and(c, not_c);
984 assert!(bdd.sat_one(c_and_not_c).is_none());
985 }
986
987 #[test]
988 fn max_sat() {
989 let mut bdd = BDD::new();
990 let a = bdd.terminal(0);
992 let b = bdd.terminal(1);
993 let c = bdd.terminal(2);
994 let d = bdd.terminal(3);
995 let cnot = bdd.not(c);
996 let dnot = bdd.not(d);
997 let ab = bdd.and(a, b);
998 let ac = bdd.and(a, c);
999 let bd = bdd.and(b, d);
1000 let ad = bdd.and(a, d);
1001 let max_sat = bdd.max_sat(&[a, ab, ac, cnot, c, bd, ad, dnot]);
1002 let abc = bdd.and(ab, c);
1003 let abcd = bdd.and(abc, d);
1004 assert!(max_sat == abcd);
1005 }
1006
1007 #[test]
1008 fn max_sat_min_var() {
1009 let mut bdd = BDD::new();
1010 let a = bdd.terminal(0);
1012 let b = bdd.terminal(1);
1013 let c = bdd.terminal(2);
1014 let d = bdd.terminal(3);
1015 let cnot = bdd.not(c);
1016 let dnot = bdd.not(d);
1017 let ab = bdd.and(a, b);
1018 let ac = bdd.and(a, c);
1019 let bd = bdd.and(b, d);
1020 let max_sat = bdd.max_sat(&[a, ab, ac, cnot, c, bd, dnot]);
1021 let abc = bdd.and(ab, c);
1022 assert!(max_sat == abc);
1023 let assn = bdd.sat_one(max_sat).unwrap();
1024 assert!(assn.get(&0) == Some(&true));
1025 assert!(assn.get(&1) == Some(&true));
1026 assert!(assn.get(&2) == Some(&true));
1027 assert!(assn.get(&3) == None);
1028 }
1029
1030 #[test]
1031 fn persist_bdd() {
1032 let out = InMemoryBDDLog::new();
1033 let mut p = PersistedBDD::new();
1034 let term_a = p.bdd_mut().terminal("A".to_owned());
1035 let term_b = p.bdd_mut().terminal("B".to_owned());
1036 let term_c = p.bdd_mut().terminal("C".to_owned());
1037 let ab = p.bdd_mut().and(term_a, term_b);
1038 let ab_or_c = p.bdd_mut().or(ab, term_c);
1039 p.persist(ab_or_c, &out).unwrap();
1040 assert!(
1041 *out.labels.borrow()
1042 == vec![
1043 (0, "A".to_owned()),
1044 (1, "B".to_owned()),
1045 (2, "C".to_owned()),
1046 ]
1047 );
1048 assert!(
1049 *out.nodes.borrow()
1050 == vec![
1051 (0, 0, BDD_ZERO, BDD_ONE),
1052 (1, 1, BDD_ZERO, BDD_ONE),
1053 (2, 2, BDD_ZERO, BDD_ONE),
1054 (3, 0, BDD_ZERO, 1),
1055 (4, 1, 2, BDD_ONE),
1056 (5, 0, 2, 4),
1057 ]
1058 );
1059 }
1060
1061 #[test]
1062 fn load_bdd() {
1063 let mut bdd = BDD::new();
1064 {
1065 let mut loader = BDDLoader::new(&mut bdd);
1066 loader.inject_label("A".to_owned(), 0);
1067 loader.inject_label("B".to_owned(), 1);
1068 loader.inject_node(0, 1, BDD_ZERO, BDD_ONE);
1069 loader.inject_node(1, 0, BDD_ZERO, 0);
1070 }
1071 let mut h = HashMap::new();
1072 h.insert("A".to_owned(), true);
1073 h.insert("B".to_owned(), true);
1074 assert!(bdd.evaluate(1, &h) == true);
1075 }
1076
1077 #[test]
1078 fn persist_empty_bdd() {
1079 let out = InMemoryBDDLog::new();
1080 let mut p = PersistedBDD::new();
1081 p.persist(BDD_ZERO, &out).unwrap();
1082 }
1083}