neuppl / rsdd Goto Github PK
View Code? Open in Web Editor NEWPerformant and safe knowledge compilation in rust
Home Page: https://neuppl.github.io/rsdd-docs/
License: MIT License
Performant and safe knowledge compilation in rust
Home Page: https://neuppl.github.io/rsdd-docs/
License: MIT License
Add a swap
method to the BddBuilder
trait:
pub trait BddBuilder<'a>: BottomUpBuilder<'a, BddPtr<'a>> {
/// swaps variables `a` and `b` in the variable order.
/// all pointers into the manager are invalidated.
/// returns a new manager and root list, where the order of roots in the returned list
/// matches the order provided by `roots.`
fn swap(manager: BddManger<'a>, roots: Vec<BddPtr<'a>, a: VarLabel, b: VarLabel) -> (Manager<'b>, Vec<BddPtr<'b>>;
/// reorders all BDDs to have the order `order`.
/// all pointers into the manager are invalidated.
/// returns a new manager and root list, where the order of roots in the returned list
/// matches the order provided by `roots.`
fn reorder(manager: BddManger<'a>, roots: Vec<BddPtr<'a>, order: VarOrder) -> (Manager<'b>, Vec<BddPtr<'b>>;
}
reorder
should be implemented in terms of swap
.Add a /bin/
directory that organizes the following main binaries for interacting with the library.
bottomup_cnf_to_bdd
: takes as input a CNF and outputs a BDD.
order
, specifies a variable order:
auto_minfill
: use a min-fill heuristic to find the variable orderingauto_force
: use the FORCE heuristic to find a variable orderingmanual
: provide a manual variable order as a JSON filestrategy
, specifies a compilation order (i.e., a tree describing the sequence in which clauses are conjoined together)
dtree
, uses the dtree decomposition of the CNF according to the variable orderverbose
, show verbose output (timing information, hash table information, etc.)progress
, show a progress bar that gives an estimate of compilation progress (fraction of compiled clauses)bottomup_formula_to_bdd
: takes as input an arbitrary logical formula and outputs a BDD.
ordering
manual
, must provide a manual variable order.interaction_minfill
: user provides an interaction graph between variables and minfill is run to extract a good variable orderbottomup_cnf_to_sdd
: same as for BDDbottomup_formula_to_sdd
: same as for BDDcnf_to_ddnnf
: compiles a d-DNNF from a CNF
order
, specifies a variable ordering strategy
static_minfill
, follows a static variable ordering based on the minfill heuristic on the graphstatic_manual
, user provides a manual static variable orderingweighted_model_count
: takes as input a compiled circuit and weight file and outputs the resulting weighted model count
circuit
, either a dDNNF, SDD, or BDDsemiring
, choice of semiring under which to perform the computation
f64
or rational
for now; more to come laterweights
A JSON file describing the weights (a dictionary mapping literals to weights)When doing a ternary And
with the RSDD CLI, RSDD only considers the first two arguments in the conjunction, and ignores the third. This is the case for all n-ary operations with n>2.
Command:
cargo run --release --bin weighted_model_count --features="cli" -- -f minimal_example.sexp -w minimal_example_weights.json
minimal_example.sexp
:
(And (Not (Var T0)) (Not (Var T1)) (Not (Var T2)))
minimal_example_weights.json
:
{"T0": { "low": 0.9, "high": 0.1}, "T1": { "low": 0.9, "high": 0.1}, "T2": { "low": 0.9, "high": 0.1}}
Expected Output:
unweighted model count: 1
weighted model count: 0.729
Actual Output:
unweighted model count: 2
weighted model count: 0.81
There is a workaround to this issue that you can just do nesting of binary conjunctions. For example using the following formula file.
minimal_example_workaround.sexp
:
(And (Not (Var T0)) (And (Not (Var T1)) (Not (Var T2))))
This is fine, but RSDD should at least error on invalid input instead of giving an incorrect output.
Jotting this down so I don't forget - we should try to cache our cargo dependencies so that our CI build times are shorter.
Coupe thoughts:
Cargo.lock
Updating this to be a tracking issue for the standardized import/export of all the main datastructures within the library.
All these import/export tools can be found in src/serialize/
In addition to serializing/deserializing these data structures, it's necessary to be able to load them into the relevant builder/manager. Here we track these workflows:
RSDD CLI is generating a non-reduced BDD with duplicate leaves/redundant nodes. We suspect this is leading to a noticeable performance loss in runtime of programs using larger BDDs. It is unclear if this issue is in the CLI only, or if it is in the core RSDD code.
weighted_model_count.rs
code to get printed BDD outputHere is the change as a git diff to main branch at commit sha `39aadfb`:
diff --git a/bin/weighted_model_count.rs b/bin/weighted_model_count.rs
index e2359d4..a482696 100644
--- a/bin/weighted_model_count.rs
+++ b/bin/weighted_model_count.rs
@@ -155,6 +155,7 @@ fn single_wmc(
let bdd = builder.smooth(bdd, num_vars);
let res = bdd.unsmoothed_wmc(¶ms);
+ println!("{}", bdd.to_string_debug());
let elapsed = start.elapsed();
Command:
cargo run --release --bin weighted_model_count --features="cli" -- -f minimal_example.sexp -w minimal_example_weights.json
minimal_example.sexp
:
(And (Var T0) (Var T1))
minimal_example_weights.json
:
{"T0": { "low": 0.9, "high": 0.1}, "T1": { "low": 0.9, "high": 0.1}}
Expected Output:
(0, (1, T, F))
unweighted model count: 1
weighted model count: 0.01
Actual Output:
(0, (1, T, F), (1, F, F))
unweighted model count: 1
weighted model count: 0.010000000000000002
Currently all nodes that are allocated by the bottom-up managers are never deallocated. This issue establishes a garbage collection interface for collecting unused nodes. It adds the following method to the BottomUpBuilder
trait:
pub trait BottomUpBuilder<'a, Ptr> {
...
/// garbage collects all nodes in the builder.
/// only the roots provided in the `roots` argument are guaranteed to be preserved.
/// Roots may be moved during garbage collection; these new roots are returned in the
/// same order in which they were provided.
fn collect(&'a self, roots: Vec<Ptr>) -> Vec<Ptr>
}
This issue involves scoping and implementing the garbage collecting strategy. Design considerations:
Motivated from a conversation with Lisa: on top of model counting with .wmc()
, it would be moderately useful to list out all valid models that satisfy a logical formula, and (optionally) the associated weights with each model.
Since this is computationally hard, we should do this on-demand only from the user. We can probably use the existing PartialModel
struct; we could then return a tuple for each model, which contains both the assignments for each variable, and the associated weight.
I'm thinking something that looks like this:
let weights = WmcParams::new(/* ... */);
let formula: DDNNFPtr = builder.compile_cnf(); // can be whatever approach we'd prefer
let valid_models: ValidModels = formula.enumerate_models(&order, &weights);
for model in valid_models {
println!("weight: {}, assignments: {}", model.weight(), model.assignments())
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.