Primitive Logic Directed Acyclic Graph (PL-DAG)
A Primitive Logic Directed Acyclic Graph (PL-DAG) is a DAG in which every node encodes a logical operation and every leaf represents a literal. Interior nodes freely express arbitrary Boolean combinations of their predecessors—for example, an AND-node evaluates to true only if all of its incoming nodes (or leaves) evaluate to true. This “freedom” to assemble logical relationships with minimal ceremony makes the PL-DAG both powerful and easy to work with.
Install
Core Routines
The PL-DAG provides these core APIs for working with combinations and evaluations:
1. check_combination
;
- Purpose: Takes a map of leaf-IDs →
Bound
values, propagates Boolean truth-assignments up the graph, and returns for each node whether it ends uptrue
orfalse
. Typically, you’ll inspect the root to see if a given combination is valid.
2. score_combination
;
- Purpose: After assigning
Bound
values to leaves, apply a single map of node-IDs →f64
weights. Each node’s score is computed by combining its own weight with the scores of its children. Ideal for “pricing” or weighting a single configuration.
3. check_and_score
;
- Purpose: A one-stop helper that first runs
check_combination
and then feeds the resulting Booleans intoscore_combination
. Returns both the Boolean map and the per-node scores in one call.
4. to_sparse_polyhedron
;
- Purpose: Exports the PL-DAG as a sparse polyhedral system—perfect for dropping straight into an ILP solver when you need to optimize or solve over the same logical constraints.
5. batch_score_combinations
;
- Purpose: Score a single combination against multiple weight maps at once. Returns, for each named weight set, a per-node score map.
Example Usage
use IndexMap;
use HashMap;
use ;
// Build your PL-DAG (omitting details)...
// For example, we create a model of three boolean variables x, y and z.
// We bind them to an xor constraint.
let mut pldag: Pldag = new;
// First setup the primitive variables
pldag.set_primitive;
pldag.set_primitive;
pldag.set_primitive;
// A reference ID is returned
let root = pldag.set_or;
// 1. Validate a combination:
let mut inputs: = new;
let validited = pldag.check_combination;
// Since nothing is given, and all other variable inplicitly is (0, 1) from the pldag model,
// the root will be (0,1) since there's not enough information to evalute the root `or` node.
println!; // This will be False
// If we however for instance fix x to be zero, then the root is false
inputs.insert;
let revalidited = pldag.check_combination;
println!; // This will be false
// 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).
inputs.insert;
inputs.insert;
let revalidited = pldag.check_combination;
println!; // This will be true
// 2. Score a configuration:
// We can score a configuration by using the score_combination function.
let mut weights: = new;
weights.insert;
weights.insert;
weights.insert;
// Add a discount value if the root is true
weights.insert;
let scores = pldag.check_and_score;
println!;
// And notice what will happen if we remove the x value (i.e. x being (0,1))
inputs.insert;
let scores = pldag.check_and_score;
// The root will return (5,6) meaning its value is between 5 and 6 with not enough information to
// determine the exact value.
println!;
// .. and if we set x to be 0, then the root will be definitely 5.
inputs.insert;
let scores = pldag.check_and_score;
println!;
// .. and if we set y and z to be 0, then the root will be 0.
inputs.insert;
inputs.insert;
let scores = pldag.check_and_score;
println!;
Enjoy building and evaluating logical models with the PL-DAG!