Skip to content

Commit

Permalink
Add serde-wasm-bindgen, allow VTree type as input parameter (#75)
Browse files Browse the repository at this point in the history
This PR primarily adds choice on how a user can generate a VTree. For now, we support right/left-linear and even splits (with the number as an extra parameter).

Right now, `wasm_bindgen` only supports C-like enums, instead of Rust's variant-like approach - so, I need to do some serialization to make this work.

For the future:

1. more VTree generation methods
2. better error message when `even_split` fails

I use these changes in mattxwang/indecision@cacac51
  • Loading branch information
mattxwang committed Apr 9, 2023
1 parent 70b6360 commit 0db9ace
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 20 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Expand Up @@ -32,6 +32,7 @@ rsgm = { git = "https://github.com/pmall-neu/rsgm" }
rand_chacha = "0.3.1"
getrandom = { version = "0.2", features = ["js"] } # req for wasm
wasm-bindgen = "0.2.84"
serde-wasm-bindgen = "0.4"


[lib]
Expand Down
54 changes: 34 additions & 20 deletions src/wasm/mod.rs
Expand Up @@ -6,27 +6,30 @@ use crate::repr::{cnf::Cnf, var_label::VarLabel, vtree::VTree};
use crate::serialize::{ser_bdd, ser_sdd, ser_vtree};
use wasm_bindgen::prelude::*;

#[derive(Serialize, Deserialize)]
pub enum VTreeType {
LeftLinear,
RightLinear,
EvenSplit(usize),
}

// used in: https://github.com/mattxwang/indecision
#[wasm_bindgen]
pub fn get_vtree(cnf_input: String) -> String {
pub fn vtree(cnf_input: String, vtree_type_input: JsValue) -> Result<JsValue, JsValue> {
let cnf = Cnf::from_file(cnf_input);

let range: Vec<usize> = (0..cnf.num_vars() + 1).collect();
let binding = range
.iter()
.map(|i| VarLabel::new(*i as u64))
.collect::<Vec<VarLabel>>();
let vars = binding.as_slice();
let vtree_type: VTreeType = serde_wasm_bindgen::from_value(vtree_type_input)?;

let vtree = VTree::right_linear(vars);
let vtree = build_vtree(&cnf, vtree_type);

let json = ser_vtree::VTreeSerializer::from_vtree(&vtree);
serde_json::to_string(&json).unwrap()
let serialized = ser_vtree::VTreeSerializer::from_vtree(&vtree);

Ok(serde_wasm_bindgen::to_value(&serialized)?)
}

// used in: https://github.com/mattxwang/indecision
#[wasm_bindgen]
pub fn get_bdd(cnf_input: String) -> String {
pub fn bdd(cnf_input: String) -> String {
let cnf = Cnf::from_file(cnf_input);

let mut man = BddManager::<BddApplyTable<BddPtr>>::new_default_order_lru(cnf.num_vars());
Expand All @@ -39,22 +42,33 @@ pub fn get_bdd(cnf_input: String) -> String {

// used in: https://github.com/mattxwang/indecision
#[wasm_bindgen]
pub fn get_sdd(cnf_input: String) -> String {
pub fn sdd(cnf_input: String, vtree_type_input: JsValue) -> Result<JsValue, JsValue> {
let cnf = Cnf::from_file(cnf_input);

let vtree_type: VTreeType = serde_wasm_bindgen::from_value(vtree_type_input)?;

let vtree = build_vtree(&cnf, vtree_type);

let mut compr_mgr = SddManager::<CompressionCanonicalizer>::new(vtree);
let sdd = compr_mgr.from_cnf(&cnf);

let serialized = ser_sdd::SDDSerializer::from_sdd(sdd);

Ok(serde_wasm_bindgen::to_value(&serialized)?)
}

// internal function -- no intermediate types needed
fn build_vtree(cnf: &Cnf, vtree_type: VTreeType) -> VTree {
let range: Vec<usize> = (0..cnf.num_vars() + 1).collect();
let binding = range
.iter()
.map(|i| VarLabel::new(*i as u64))
.collect::<Vec<VarLabel>>();
let vars = binding.as_slice();

let vtree = VTree::right_linear(vars);

let mut compr_mgr = SddManager::<CompressionCanonicalizer>::new(vtree);
let sdd = compr_mgr.from_cnf(&cnf);

let json = ser_sdd::SDDSerializer::from_sdd(sdd);

serde_json::to_string(&json).unwrap()
match vtree_type {
VTreeType::LeftLinear => VTree::left_linear(vars),
VTreeType::RightLinear => VTree::right_linear(vars),
VTreeType::EvenSplit(num) => VTree::even_split(vars, num),
}
}

0 comments on commit 0db9ace

Please sign in to comment.