1

I am trying to find total no of nodes in a Shared-BDD using CUDD. I have already written C Code using BuDDy-2.4 and it is running fine But when i am using CUDD instead of BuDDy, My program is showing error.

My BuDDY C File is:

//BuDDY_C Code for Node Count:    

#define X1 (a&b&c&d)|(!c&d&f)|(g&!g)    //Define Function-1 here
#define X2 (a&b&d&!c)|(!c&!c&d)^(g) //Define Function-2 here


#include<bdd.h>
#include<stdio.h>
#include<stdlib.h>

int main(void)
{
bdd z[2],a,b,c,d,e,f,g,h;
int i,INPUT=8,node_count,order[8]={2,5,1,6,0,4,3,7};

printf("\nGiven Variable Order:\t ");
    for(i=0;i<INPUT;i++)
        printf("%d \t",order[i]); 

   bdd_init(1000,100);
   bdd_setvarnum(INPUT);

        a = bdd_ithvar(order[0]);  //Assign Variable order stored in order[0] to a
        b = bdd_ithvar(order[1]);  //Assign Variable order stored in order[1] to b
        c = bdd_ithvar(order[2]);  //Assign Variable order stored in order[2] to c
        d = bdd_ithvar(order[3]);  //Assign Variable order stored in order[3] to d
        e = bdd_ithvar(order[4]);  //Assign Variable order stored in order[4] to e
        f = bdd_ithvar(order[5]);  //Assign Variable order stored in order[5] to f
        g = bdd_ithvar(order[6]);  //Assign Variable order stored in order[6] to g
        h = bdd_ithvar(order[7]);  //Assign Variable order stored in order[7] to h


    z[0]=X1; 
    z[1]=X2;
   node_count=bdd_anodecount(z,2);
   bdd_done();
   printf("\n Total no of nodes are %d\n",node_count);
   return 0;

}

My CUDD C Program is:

//CUDD_C Code for Node Count
#define X1 (a&b&c&d)|(!c&d&f)|(g&!g)    //Define Function-1 here
#define X2 (a&b&d&!c)|(!c&!c&d)^(g) //Define Function-2 here

#include <stdio.h>
#include <stdlib.h>
#include "cudd.h"

int main(void) {
DdNode *z[2],*a,*b,*c,*d,*e,*f,*g,*h;
int i,INPUT=8,node_count,order[8]={2,5,1,6,0,4,3,7};

printf("\nGiven Variable Order:\t ");
    for(i=0;i<INPUT;i++)
        printf("%d \t",order[i]); 

DdManager * mgr = Cudd_Init(INPUT,0,CUDD_UNIQUE_SLOTS,CUDD_CACHE_SLOTS,0);


 a = Cudd_bddIthVar(mgr, order[0]);  //Assign Variable order stored in order[0] to a
 b = Cudd_bddIthVar(mgr, order[1]);  //Assign Variable order stored in order[0] to b
 c = Cudd_bddIthVar(mgr, order[2]);  //Assign Variable order stored in order[0] to c
 d = Cudd_bddIthVar(mgr, order[3]);  //Assign Variable order stored in order[0] to d
 e = Cudd_bddIthVar(mgr, order[4]);  //Assign Variable order stored in order[0] to e
 f = Cudd_bddIthVar(mgr, order[5]);  //Assign Variable order stored in order[0] to f
 g = Cudd_bddIthVar(mgr, order[6]);  //Assign Variable order stored in order[0] to g
 h = Cudd_bddIthVar(mgr, order[7]);  //Assign Variable order stored in order[0] to h


    z[0]=X1; 
    z[1]=X2;


  Cudd_Ref(z[0]);
  Cudd_Ref(z[1]);
/*-----Calculate no of nodes and number of shared nodes*/

        node_count= Cudd_SharingSize( z, 2);   
    printf("\n Total no of nodes are %d\n",node_count);

  int err = Cudd_CheckZeroRef(mgr);
  Cudd_Quit(mgr);
  return err;
}

But this CUDD C program is showing Error

balal@balal-HP-H710:~/Desktop/cudd-3.0.0$ g++ -o test test2_cudd.c -lbdd
test2_cudd.c: In function ‘int main()’:
test2_cudd.c:2:14: error: invalid operands of types ‘DdNode*’ and ‘DdNode*’ to binary ‘operator&’
 #define X1 (a&b&c&d)|(!c&d&f)|(g&!g) //Define Function-1 here
             ~^~
test2_cudd.c:30:7: note: in expansion of macro ‘X1’
  z[0]=X1;
       ^~
test2_cudd.c:2:25: error: invalid operands of types ‘bool’ and ‘DdNode*’ to binary ‘operator&’
 #define X1 (a&b&c&d)|(!c&d&f)|(g&!g) //Define Function-1 here
                       ~~^~
test2_cudd.c:30:7: note: in expansion of macro ‘X1’
  z[0]=X1;
       ^~
test2_cudd.c:2:33: error: invalid operands of types ‘DdNode*’ and ‘bool’ to binary ‘operator&’
 #define X1 (a&b&c&d)|(!c&d&f)|(g&!g) //Define Function-1 here
                                ~^~~
test2_cudd.c:30:7: note: in expansion of macro ‘X1’
  z[0]=X1;
       ^~
test2_cudd.c:3:14: error: invalid operands of types ‘DdNode*’ and ‘DdNode*’ to binary ‘operator&’
 #define X2 (a&b&d&!c)|(!c&!c&d)^(g) //Define Function-2 here
             ~^~
test2_cudd.c:31:7: note: in expansion of macro ‘X2’
  z[1]=X2;
       ^~
test2_cudd.c:3:29: error: invalid operands of types ‘int’ and ‘DdNode*’ to binary ‘operator&’
 #define X2 (a&b&d&!c)|(!c&!c&d)^(g) //Define Function-2 here
                        ~~~~~^~
test2_cudd.c:31:7: note: in expansion of macro ‘X2’
  z[1]=X2;
       ^~
balal@balal-HP-H710:~/Desktop/cudd-3.0.0$ 

2 Answers2

0

You are trying to use the "&" operator on BDD nodes while writing your program in C. Since C does not support operator overloading, this won't work because the "&" operator could at most mean to take the bitwise AND of the addresses, which is not what you want.

In order to compute the AND of two BDDs, you have to use the Cudd_bddAnd function. See, for instance, here for an example. Note that your macros will become a lot longer in this way and need to include local variables apart from scopes.

The alternative is to use the C++ interface to CUDD, where BDDs can be encapsulated into objects that support operator overloading.

Note that

z[0]=X1; 
z[1]=X2;
Cudd_Ref(z[0]);
Cudd_Ref(z[1]);

can also potentially cause trouble. In CUDD, nodes have to be referenced with Cudd_Ref(...) before any other CUDD function is called that can create new nodes. Since your X2 macro includes operations over BDDs, this can happen. So it's best practice to Cudd_Ref(...) BDDs immediately. The following looks better:

z[0]=X1; 
Cudd_Ref(z[0]);
z[1]=X2;
Cudd_Ref(z[1]);

Note that your Buddy code is also wrong for the same reason. However, since the BDD type there is defined as "typedef int BDD;" the compiler used bitwise AND and OR on the BDD node numbers instead, which is why it compiled to code that produces wrong results.

DCTLib
  • 1,016
  • 8
  • 22
0

Another possibility is to use the Cython interface to CUDD that is included in the Python package dd. Installation of dd with the module dd.cudd is described here and could be summarized as

pip download dd --no-deps
tar -xzf dd-*.tar.gz
cd dd-*/
python setup.py install --fetch --cudd

This will download and build CUDD, and build and install the Cython bindings of dd to CUDD. dd has Cython bindings also to BuDDy, and those could be built similarly, with the user downloading and building BuDDy, and passing --buddy to the script setup.py.

The example code could be translated to the following Python code.

from dd import cudd as _bdd

bdd = _bdd.BDD()
bdd.declare('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h')
# /\ is conjunction in TLA+, \/ disjunction, ~ negation
X1 = bdd.add_expr('(a /\ b /\ c /\ d) \/ (~ c /\ d /\ f) \/ (g /\ ~ g)')
    # note that g /\ ~ g is FALSE
X2 = bdd.add_expr('(a /\ b /\ d /\ ~ c) \/ ((~ c /\ ~ c /\ d) ^ g)')
    # note that ~ c /\ ~ c is ~ c


# using the operators &, |, ! for conjunction, disjunction, and negation
X1_ = bdd.add_expr('(a & b & c & d) \/ (!c & d & f) \/ (g & !g)')
X2_ = bdd.add_expr('(a & b & d & !c) \/ ((!c & !c & d) ^ g)')
assert X1 == X1_, (X1, X1_)
assert X2 == X2_, (X2, X2_)


def descendants(roots):
    """Return nodes reachable from `roots`.

    Nodes in `roots` are included.
    """
    if not roots:
        return set()
    visited = set()
    for u in roots:
        _descendants(u, visited)
    assert set(roots).issubset(visited), (roots, visited)
    return visited

def _descendants(u, visited):
    v, w = u.low, u.high
    # terminal node or visited ?
    if u.low is None or u in visited:
        return
    _descendants(v, visited)
    _descendants(w, visited)
    visited.add(u)


r = descendants([X1, X2])
print(len(r))

# plot diagrams of the results using GraphViz
bdd.dump('X1.pdf', [X1])
bdd.dump('X2.pdf', [X2])

The function descendants computes the set of nodes reachable from the given nodes (the nodes referenced by X1 and X2), including the given nodes. The answer for the variable order in my run is 16 nodes. The diagrams for the BDDs of the Boolean functions X1 and X2 are the following.

BDD of Boolean function X1

Boolean function <code>X1</code>

BDD of Boolean function X2

Boolean function <code>X2</code>

0 _
  • 10,524
  • 11
  • 77
  • 109