1
use oxidd::BooleanFunction;
2
use oxidd::ManagerRef;
3
use oxidd::bdd::BDDFunction;
4
use oxidd::bdd::BDDManagerRef;
5
use oxidd::util::OptBool;
6
use oxidd::util::OutOfMemory;
7
use rand::Rng;
8
use rand::RngExt;
9

            
10
/// Generate `num_vectors` random bitvectors of length `num_vars`.
11
8399
pub fn random_bitvectors<R: Rng>(rng: &mut R, num_vars: usize, num_vectors: usize) -> Vec<Vec<OptBool>> {
12
8399
    let mut vectors = Vec::new();
13
8399
    for _ in 0..rng.random_range(0..num_vectors) {
14
38330
        let mut vec = Vec::new();
15
38330
        for _ in 0..num_vars {
16
118968
            vec.push(if rng.random_bool(0.5) {
17
59233
                OptBool::True
18
            } else {
19
59735
                OptBool::False
20
            });
21
        }
22
38330
        vectors.push(vec);
23
    }
24
8399
    vectors
25
8399
}
26

            
27
/// Constructs a BDD representing the given cube (bitvector) over the given variables.
28
74556
pub fn bdd_from_cube(
29
74556
    manager_ref: &BDDManagerRef,
30
74556
    variables: &[BDDFunction],
31
74556
    cube: &[OptBool],
32
74556
) -> Result<BDDFunction, OutOfMemory> {
33
74556
    assert_eq!(
34
74556
        variables.len(),
35
74556
        cube.len(),
36
        "variables and cube must have the same length"
37
    );
38
74556
    let mut bdd = manager_ref.with_manager_shared(|manager| BDDFunction::t(manager));
39
227646
    for (i, bit) in cube.iter().enumerate() {
40
227646
        let var = variables[i].clone();
41
227646
        let literal = match *bit {
42
113346
            OptBool::True => var,
43
114300
            OptBool::False => var.not()?,
44
            OptBool::None => continue,
45
        };
46
227646
        bdd = bdd.and(&literal)?;
47
    }
48
74556
    Ok(bdd)
49
74556
}
50

            
51
/// Create a BDD from the given iterator over bitvector.
52
8399
pub fn bdd_from_iter<'a, I>(
53
8399
    manager_ref: &BDDManagerRef,
54
8399
    variables: &[BDDFunction],
55
8399
    vectors: I,
56
8399
) -> Result<BDDFunction, OutOfMemory>
57
8399
where
58
8399
    I: Iterator<Item = &'a Vec<OptBool>>,
59
{
60
8399
    let mut bdd = manager_ref.with_manager_shared(|manager| BDDFunction::f(manager));
61
38330
    for bits in vectors {
62
38330
        bdd = bdd.or(&bdd_from_cube(manager_ref, variables, bits)?)?;
63
    }
64

            
65
8399
    Ok(bdd)
66
8399
}
67

            
68
/// Create a random BDD over the given variables with the given number of cubes.
69
8199
pub fn random_bdd<R: Rng>(
70
8199
    manager_ref: &BDDManagerRef,
71
8199
    rng: &mut R,
72
8199
    variables: &[BDDFunction],
73
8199
    num_of_cubes: usize,
74
8199
) -> Result<BDDFunction, OutOfMemory> {
75
8199
    let bitvectors = random_bitvectors(rng, variables.len(), num_of_cubes);
76
8199
    bdd_from_iter(manager_ref, variables, bitvectors.iter())
77
8199
}