Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Creation of Boolean Variables as ZBDDs #22

Open
sirandreww opened this issue Oct 14, 2024 · 2 comments
Open

Creation of Boolean Variables as ZBDDs #22

sirandreww opened this issue Oct 14, 2024 · 2 comments

Comments

@sirandreww
Copy link

I'm working with ZDDs using this library and I'm noticing the following issue:

    let inner_node_capacity = 1 << 20;
    let apply_cache_capacity = 1 << 20;
    let threads = 1;

    let manager_ref: oxidd::zbdd::ZBDDManagerRef =
        oxidd::zbdd::new_manager(inner_node_capacity, apply_cache_capacity, threads);

    let a =
        manager_ref.with_manager_exclusive(|manager| ZBDDFunction::new_singleton(manager).unwrap());
    let b =
        manager_ref.with_manager_exclusive(|manager| ZBDDFunction::new_singleton(manager).unwrap());
    let x =
        manager_ref.with_manager_exclusive(|manager| ZBDDFunction::new_singleton(manager).unwrap());

    let def = a.and(&b).unwrap().equiv(&x).unwrap();

    let r = def.and(&x).unwrap().and(&a).unwrap();

    debug_assert!(r.satisfiable());

I'm defining 3 variables a, b, x and I'm defining x to be the result of a ^ b (x = a && b).
Then I'm checking the result of the SAT query x && a and it is not SAT? (The assert fails).
Am I somehow using the library incorrectly?

Version

oxidd = "0.7.0"

@nhusung
Copy link
Member

nhusung commented Oct 14, 2024

You seem to be confusing singleton sets and Boolean variable functions. The variable a in your code snippet corresponds to the singleton set {a}, i.e., the Boolean function a ∧ ¬b ∧ ¬x. r is def ∧ (¬a ∧ ¬b ∧ x) ∧ (a ∧ ¬b ∧ ¬x) = ⊥.

For your use case, you first need to create the singleton sets (to make the decision diagram have three levels), and then construct the Boolean functions representing the variables. I just noticed that I did not really expose the functionality on ZBDDFunction, I’ll leave this issue open until that is fixed. Until then, you may want to use the following helper function

/// Returns a pair `(singletons, boolean_vars)`. Each of the returned `Vec`s contains `n` elements.
fn zbdd_singletons_vars(mref: &ZBDDManagerRef, n: usize) -> (Vec<ZBDDFunction>, Vec<ZBDDFunction>) {
    let singletons: Vec<ZBDDFunction> = mref.with_manager_exclusive(|manager| {
        (0..n)
            .map(|_| ZBDDFunction::new_singleton(manager).unwrap())
            .collect()
    });
    let vars = mref.with_manager_shared(|manager| {
        singletons
            .iter()
            .map(|s| {
                ZBDDFunction::from_edge(
                    manager,
                    oxidd::zbdd::var_boolean_function(manager, s.as_edge(manager)).unwrap(),
                )
            })
            .collect()
    });
    (singletons, vars)
}

You can use this as follows:

let (_, vars) = zbdd_singletons_vars(manager_ref);
let a = &vars[0];
let b = &vars[1];
let x = &vars[2];

Directly calling ZBDDFunction::new_var() three times after another would mean that all the functions have different domains, which is not what you want. This is currently somewhat inconvenient and will probably be improved in one of the next releases.

@nhusung nhusung changed the title ZBDD Bug? Creation of Boolean Variables for ZBDDs Oct 14, 2024
@nhusung nhusung changed the title Creation of Boolean Variables for ZBDDs Creation of Boolean Variables as ZBDDs Oct 14, 2024
@sirandreww
Copy link
Author

sirandreww commented Oct 15, 2024

Can you provide me with a resource that explains this set representation with ZDDs?
What does the function var_boolean_function

I'm working in an environment where I am building a circuit incrementally depending on some unknown heuristic, so the number of variables that I will be using is not known to me at all.
I need to be able to add variables to the ZDDs according to my needs "on the fly".
Do you think this function would work? Is there a reason that I need to keep the singleton sets?

   fn get_new_variable(mref: &ZBDDManagerRef) -> ZBDDFunction {
        mref.with_manager_exclusive(|manager| {
            let s = ZBDDFunction::new_singleton(manager).unwrap();
            ZBDDFunction::from_edge(
                manager,
                oxidd::zbdd::var_boolean_function(manager, s.as_edge(manager)).unwrap(),
            )
        })
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants