pub struct Pldag {
    pub nodes: IndexMap<String, Node>,
}Expand description
A Primitive Logic Directed Acyclic Graph (PL-DAG).
The PL-DAG represents a logical system where:
- Primitive nodes are leaf variables with bounds
 - Composite nodes represent logical constraints over other nodes
 - Each node has an associated coefficient for accumulation operations
 
The DAG structure ensures no cycles and enables efficient bottom-up propagation.
Fields§
§nodes: IndexMap<String, Node>Map from node IDs to their corresponding nodes
Implementations§
Source§impl Pldag
 
impl Pldag
Sourcepub fn new() -> Pldag
 
pub fn new() -> Pldag
Examples found in repository?
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}Sourcepub fn transitive_dependencies(&self) -> HashMap<ID, HashSet<ID>>
 
pub fn transitive_dependencies(&self) -> HashMap<ID, HashSet<ID>>
Computes the transitive dependency closure for all nodes.
For each node in the DAG, this method calculates all nodes that can be reached by following dependency edges (the set of all descendants).
§Returns
A map from each node ID to the set of all node IDs it transitively depends on
Sourcepub fn primitive_combinations(&self) -> impl Iterator<Item = HashMap<ID, i64>>
 
pub fn primitive_combinations(&self) -> impl Iterator<Item = HashMap<ID, i64>>
Generates all possible combinations of primitive variable assignments.
Enumerates the Cartesian product of all primitive variable bounds, yielding every possible complete assignment of values to primitive variables.
§Returns
An iterator over all possible variable assignments as HashMaps
Sourcepub fn propagate(&self, assignment: &Assignment) -> Assignment
 
pub fn propagate(&self, assignment: &Assignment) -> Assignment
Propagates bounds through the DAG bottom-up.
Starting from the given variable assignments, this method computes bounds for all composite nodes by propagating constraints upward through the DAG.
§Arguments
assignment- Initial assignment of bounds to variables
§Returns
Complete assignment including bounds for all reachable nodes
Examples found in repository?
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}Sourcepub fn propagate_default(&self) -> Assignment
 
pub fn propagate_default(&self) -> Assignment
Propagates bounds using default primitive variable bounds.
Convenience method that calls propagate with the default bounds
of all primitive variables as defined in the DAG.
§Returns
Complete assignment with bounds for all nodes
Sourcepub fn propagate_many_coefs(
    &self,
    assignments: Vec<&Assignment>,
) -> Vec<ValuedAssignment> ⓘ
 
pub fn propagate_many_coefs( &self, assignments: Vec<&Assignment>, ) -> Vec<ValuedAssignment> ⓘ
Propagates bounds and accumulates coefficients for multiple assignments.
For each input assignment, this method:
- Propagates bounds through the DAG
 - Accumulates coefficients where each parent’s coefficient is the sum of its children’s coefficients plus its own coefficient
 
§Arguments
assignments- Vector of assignments to process
§Returns
Vector of valued assignments, each containing bounds and accumulated coefficients
Sourcepub fn propagate_coefs(&self, assignment: &Assignment) -> ValuedAssignment
 
pub fn propagate_coefs(&self, assignment: &Assignment) -> ValuedAssignment
Propagates bounds and accumulates coefficients for a single assignment.
Convenience method that calls propagate_many_coefs with a single assignment.
§Arguments
assignment- The assignment to propagate
§Returns
A valued assignment containing bounds and accumulated coefficients for all nodes
§Panics
Panics if no assignments are returned (should not happen under normal circumstances)
Examples found in repository?
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}Sourcepub fn propagate_coefs_default(&self) -> ValuedAssignment
 
pub fn propagate_coefs_default(&self) -> ValuedAssignment
Propagates bounds and coefficients using default primitive bounds.
Convenience method that calls propagate_coefs with the default bounds
of all primitive variables.
§Returns
A valued assignment with bounds and coefficients for all nodes
Sourcepub fn get_objective(&self) -> IndexMap<String, f64>
 
pub fn get_objective(&self) -> IndexMap<String, f64>
Retrieves the objective function coefficients from all primitive nodes.
Collects the coefficients of all primitive (leaf) nodes in the DAG, which represent the objective function values for ILP optimization. Composite nodes are excluded from the result.
§Returns
A map from primitive variable names to their objective coefficients
Sourcepub fn to_sparse_polyhedron(
    &self,
    double_binding: bool,
    integer_constraints: bool,
    fixed_constraints: bool,
) -> SparsePolyhedron
 
pub fn to_sparse_polyhedron( &self, double_binding: bool, integer_constraints: bool, fixed_constraints: bool, ) -> SparsePolyhedron
Converts the PL-DAG to a sparse polyhedron for ILP solving.
Transforms the logical constraints in the DAG into a system of linear inequalities suitable for integer linear programming solvers.
§Arguments
double_binding- If true, creates bidirectional implications for composite nodesinteger_constraints- If true, adds bounds constraints for integer variablesfixed_constraints- If true, adds equality constraints for fixed primitive variables
§Returns
A SparsePolyhedron representing the DAG constraints
Sourcepub fn to_sparse_polyhedron_default(&self) -> SparsePolyhedron
 
pub fn to_sparse_polyhedron_default(&self) -> SparsePolyhedron
Converts the PL-DAG to a sparse polyhedron with default settings.
Convenience method that calls to_sparse_polyhedron with all options enabled:
double_binding=true, integer_constraints=true, fixed_constraints=true.
§Returns
A SparsePolyhedron with full constraint encoding
Sourcepub fn to_dense_polyhedron(
    &self,
    double_binding: bool,
    integer_constraints: bool,
    fixed_constraints: bool,
) -> DensePolyhedron
 
pub fn to_dense_polyhedron( &self, double_binding: bool, integer_constraints: bool, fixed_constraints: bool, ) -> DensePolyhedron
Sourcepub fn to_dense_polyhedron_default(&self) -> DensePolyhedron
 
pub fn to_dense_polyhedron_default(&self) -> DensePolyhedron
Converts the PL-DAG to a dense polyhedron with default settings.
§Returns
A DensePolyhedron with all constraint options enabled
Sourcepub fn set_coef(&mut self, id: ID, coefficient: f64)
 
pub fn set_coef(&mut self, id: ID, coefficient: f64)
Sets the coefficient for a specific node.
Updates the coefficient value associated with the given node ID. If the node doesn’t exist, this method has no effect.
§Arguments
id- The node ID to updatecoefficient- The new coefficient value
Examples found in repository?
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}Sourcepub fn set_primitive(&mut self, id: ID, bound: Bound)
 
pub fn set_primitive(&mut self, id: ID, bound: Bound)
Creates a primitive (leaf) variable with the specified bounds.
Primitive variables represent the base variables in the DAG and have no dependencies on other nodes.
§Arguments
id- Unique identifier for the variablebound- The allowed range (min, max) for this variable
Examples found in repository?
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}Sourcepub fn set_primitives(&mut self, ids: Vec<ID>, bound: Bound)
 
pub fn set_primitives(&mut self, ids: Vec<ID>, bound: Bound)
Creates multiple primitive variables with the same bounds.
Convenience method to create several primitive variables at once. Duplicate IDs are automatically filtered out.
§Arguments
ids- Vector of unique identifiers for the variablesbound- The common bound to apply to all variables
Sourcepub fn set_gelineq(
    &mut self,
    coefficient_variables: Vec<Coefficient>,
    bias: i64,
) -> ID
 
pub fn set_gelineq( &mut self, coefficient_variables: Vec<Coefficient>, bias: i64, ) -> ID
Creates a general linear inequality constraint.
Creates a constraint of the form: sum(coeff_i * var_i) + bias >= 0. The constraint is automatically assigned a unique ID based on its content.
§Arguments
coefficient_variables- Vector of (variable_id, coefficient) pairsbias- Constant bias term
§Returns
The unique ID assigned to this constraint
Sourcepub fn set_or(&mut self, references: Vec<ID>) -> ID
 
pub fn set_or(&mut self, references: Vec<ID>) -> ID
Creates a logical OR constraint.
Returns true if AT LEAST ONE of the referenced variables is true. Implemented as: sum(variables) >= 1.
§Arguments
references- Vector of variable IDs to OR together
§Returns
The unique ID assigned to this constraint
Examples found in repository?
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}Sourcepub fn set_imply(&mut self, condition: ID, consequence: ID) -> ID
 
pub fn set_imply(&mut self, condition: ID, consequence: ID) -> ID
Creates a logical IMPLICATION constraint: condition -> consequence.
Returns true if the condition is false OR the consequence is true. Implemented as: NOT(condition) OR consequence.
§Arguments
condition- The condition variable IDconsequence- The consequence variable ID
§Returns
The unique ID assigned to this constraint
Auto Trait Implementations§
impl Freeze for Pldag
impl RefUnwindSafe for Pldag
impl Send for Pldag
impl Sync for Pldag
impl Unpin for Pldag
impl UnwindSafe for Pldag
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
    T: ?Sized,
 
impl<T> BorrowMut<T> for Twhere
    T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
 
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> IntoEither for T
 
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
 
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
 
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more