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", (0, 1));
12    pldag.set_primitive("y", (0, 1));
13    pldag.set_primitive("z", (0, 1));
14
15    // A reference ID is returned
16    let root = pldag.set_or(vec![
17        "x",
18        "y",
19        "z",
20    ]).unwrap();
21
22    // 1. Validate a combination:
23    let mut inputs: IndexMap<&str, 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", (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", (1,1));
36    inputs.insert("z", (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", 1.0);
43    pldag.set_coef("y", 2.0);
44    pldag.set_coef("z", 3.0);
45    // Add a discount value if the root is true
46    pldag.set_coef(&root, -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", (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", (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", (0,0));
69    inputs.insert("z", (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
74    // Build a simple OR‑of‑three model
75    let mut pldag = Pldag::new();
76    pldag.set_primitive("x", (0, 1));
77    pldag.set_primitive("y", (0, 1));
78    pldag.set_primitive("z", (0, 1));
79    let root = pldag.set_or(vec!["x", "y", "z"]).unwrap();
80
81    // 1. Validate a combination
82    let validated = pldag.propagate_default();
83    println!("root bound = {:?}", validated[&root]);
84
85    // 2. Optimise with coefficients
86    pldag.set_coef("x", 1.0);
87    pldag.set_coef("y", 2.0);
88    pldag.set_coef("z", 3.0);
89    pldag.set_coef(&root, -1.0);
90    let scored = pldag.propagate_coefs_default();
91    println!("root value = {:?}", scored[&root].1);
92}