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

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

            
27
/// Create a BDD from the given bitvector.
28
6863
pub fn from_iter<'a>(
29
6863
    manager_ref: &BDDManagerRef,
30
6863
    variables: &[BDDFunction],
31
6863
    vectors: impl Iterator<Item = &'a Vec<OptBool>>,
32
6863
) -> Result<BDDFunction, MercError> {
33
6863
    let mut bdd = manager_ref.with_manager_shared(|manager| BDDFunction::f(manager));
34
330363
    for bits in vectors {
35
330363
        let mut cube = manager_ref.with_manager_shared(|manager| BDDFunction::t(manager));
36
        // Create a cube for this bitvector
37
994991
        for (i, bit) in bits.iter().enumerate() {
38
994991
            let var = variables[i].clone();
39
994991
            let literal = match *bit {
40
497824
                OptBool::True => var,
41
497167
                OptBool::False => var.not()?,
42
                OptBool::None => continue,
43
            };
44
994991
            cube = cube.and(&literal)?;
45
        }
46

            
47
330363
        bdd = bdd.or(&cube)?;
48
    }
49

            
50
6863
    Ok(bdd)
51
6863
}
52

            
53
/// Create a random BDD over the given variables with the given number of cubes.
54
6663
pub fn random_bdd(
55
6663
    manager_ref: &BDDManagerRef,
56
6663
    rng: &mut impl Rng,
57
6663
    variables: &[BDDFunction],
58
6663
) -> Result<BDDFunction, MercError> {
59
6663
    let bitvectors = random_bitvectors(rng, variables.len(), 100);
60
6663
    from_iter(manager_ref, variables, bitvectors.iter())
61
6663
}
62

            
63
/// Create the given number of variables in the BDD manager.
64
600
pub fn create_variables(manager_ref: &BDDManagerRef, num_vars: u32) -> Result<Vec<BDDFunction>, MercError> {
65
600
    Ok(manager_ref.with_manager_exclusive(|manager| {
66
600
        manager
67
600
            .add_vars(num_vars)
68
2658
            .map(|i| BDDFunction::var(manager, i))
69
600
            .collect::<Result<Vec<_>, _>>()
70
600
    })?)
71
600
}