readme_example/
readme_example.rs

1use indexmap::IndexMap;
2use pldag::{Pldag, Bound};
3
4fn main() {
5    // Build your PL-DAG
6    // For example, we create a model of three boolean variables x, y and z.
7    // We bind them to an OR constraint.
8    let mut pldag: Pldag = Pldag::new();
9
10    // First setup the primitive variables
11    pldag.set_primitive("x".to_string(), (0, 1));
12    pldag.set_primitive("y".to_string(), (0, 1));
13    pldag.set_primitive("z".to_string(), (0, 1));
14
15    // A reference ID is returned
16    let root = pldag.set_or(vec![
17        "x".to_string(),
18        "y".to_string(),
19        "z".to_string(),
20    ]);
21
22    // 1. Validate a combination:
23    let mut inputs: IndexMap<String, Bound> = IndexMap::new();
24    let validated = pldag.propagate(&inputs);
25    // Since nothing is given, and all other variables implicitly have bounds (0, 1) from the pldag model,
26    // the root will be (0,1) since there's not enough information to evaluate the root `or` node.
27    println!("Root valid? {}", *validated.get(&root).unwrap() == (1, 1)); // This will be false
28
29    // If we however fix x to be zero, then we can check the result
30    inputs.insert("x".to_string(), (0,0));
31    let revalidated = pldag.propagate(&inputs);
32    println!("Root valid? {}", *revalidated.get(&root).unwrap() == (1, 1)); // This will be false
33
34    // However, fixing y and z to 1 will yield the root node to be true (since the root will be true if any of x, y or z is true).
35    inputs.insert("y".to_string(), (1,1));
36    inputs.insert("z".to_string(), (1,1));
37    let revalidated = pldag.propagate(&inputs);
38    println!("Root valid? {}", *revalidated.get(&root).unwrap() == (1, 1)); // This will be true
39
40    // 2. Score a configuration:
41    // We can score a configuration by setting coefficients on nodes.
42    pldag.set_coef("x".to_string(), 1.0);
43    pldag.set_coef("y".to_string(), 2.0);
44    pldag.set_coef("z".to_string(), 3.0);
45    // Add a discount value if the root is true
46    pldag.set_coef(root.clone(), -1.0);
47
48    // Use propagate_coefs to get both bounds and accumulated coefficients
49    let scores = pldag.propagate_coefs(&inputs);
50    // The result contains (bounds, coefficients) for each node
51    let root_result = scores.get(&root).unwrap();
52    println!("Root bounds: {:?}, Total score: {:?}", root_result.0, root_result.1);
53
54    // And notice what will happen if we remove the x value (i.e. x being (0,1))
55    inputs.insert("x".to_string(), (0,1));
56    let scores = pldag.propagate_coefs(&inputs);
57    // The coefficients will reflect the range of possible values
58    let root_result = scores.get(&root).unwrap();
59    println!("Root bounds: {:?}, Score range: {:?}", root_result.0, root_result.1);
60
61    // .. and if we set x to be 0, then the score will be more constrained.
62    inputs.insert("x".to_string(), (0,0));
63    let scores = pldag.propagate_coefs(&inputs);
64    let root_result = scores.get(&root).unwrap();
65    println!("Root bounds: {:?}, Score: {:?}", root_result.0, root_result.1);
66
67    // .. and if we set y and z to be 0, then the root will be 0.
68    inputs.insert("y".to_string(), (0,0));
69    inputs.insert("z".to_string(), (0,0));
70    let scores = pldag.propagate_coefs(&inputs);
71    let root_result = scores.get(&root).unwrap();
72    println!("Root bounds: {:?}, Score: {:?}", root_result.0, root_result.1);
73}