1

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

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

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

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

            
66
8226
    Ok(bdd)
67
8226
}
68

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