improve cudd with bdd printing -> nodes, and true=1 false=0

This commit is contained in:
Vítor Santos Costa 2015-03-04 09:50:15 +00:00
parent 3d9006db32
commit 4386c42d02
2 changed files with 109 additions and 26 deletions

View File

@ -28,8 +28,9 @@ The following predicates construct a BDD:
mtbdd_eval/2, mtbdd_eval/2,
bdd_tree/2, bdd_tree/2,
bdd_size/2, bdd_size/2,
bdd_print/2, bdd_print/2,
bdd_to_probability_sum_product/2, bdd_print/3,
bdd_to_probability_sum_product/2,
bdd_to_probability_sum_product/3, bdd_to_probability_sum_product/3,
bdd_close/1, bdd_close/1,
mtbdd_close/1]). mtbdd_close/1]).
@ -55,7 +56,7 @@ may include:
+ Logical Variables: + Logical Variables:
a leaf-node can be a logical variable. a leaf-node can be a logical variable.
+ `0` and `1` + `0` and `1`
@ -359,6 +360,22 @@ bdd_print(cudd(M,Top,_Vars, _), File) :-
bdd_print(add(M,Top,_Vars, _), File) :- bdd_print(add(M,Top,_Vars, _), File) :-
cudd_print(M, Top, File). cudd_print(M, Top, File).
bdd_print(cudd(M,Top, Vars, _), File, Names) :-
Vars =.. [_|LVars],
%trace,
maplist( fetch_name(Names), LVars, Ss),
cudd_print(M, Top, File, Ss).
bdd_print(add(M,Top, Vars, _), File, Names) :-
Vars =.. [_|LVars],
maplist( fetch_name(Names), LVars, Ss),
cudd_print(M, Top, File, Ss).
fetch_name([S=V1|_], V2, SN) :- V1 == V2, !,
( atom(S) -> SN = S ; format(atom(SN), '~w', [S]) ).
fetch_name([_|Y], V, S) :- !,
fetch_name(Y, V, S).
fetch_name([], V, V).
mtbdd_close(add(M,_,_Vars,_)) :- mtbdd_close(add(M,_,_Vars,_)) :-
cudd_die(M). cudd_die(M).

View File

@ -1,5 +1,5 @@
/** /**
@defgroup CUDD CUDD Interface @defgroup CUDD CUDD Interface
@ingroup BDDs @ingroup BDDs
@brief Interface to the CUDD Library @brief Interface to the CUDD Library
@ -24,7 +24,7 @@ we can pass a BDD to another BDD, ie:
~~~~~.pl ~~~~~.pl
bdd(BDD) :- bdd(BDD) :-
Vs = vs(X,Y,Z), Vs = vs(X,Y,Z),
bdd_new(X+(Y*Z),Vs,BDD0), bdd_new(X+(Y*Z),Vs,BDD0),
bdd_new(xor(BDD0,-(nand(X,BDD0) + nor(Y,BDD0)) ), Vs, BDD). bdd_new(xor(BDD0,-(nand(X,BDD0) + nor(Y,BDD0)) ), Vs, BDD).
~~~~~ ~~~~~
@ -32,7 +32,7 @@ This is useful to construct complex BDDs quickly, but does not mean
CUDD will generate better/faster code. CUDD will generate better/faster code.
2. 2.
*/ */
#include <stdio.h> #include <stdio.h>
@ -57,16 +57,17 @@ static YAP_Functor FunctorDollarVar,
FunctorCudd, FunctorCudd,
FunctorAnd, FunctorAnd,
FunctorAnd4, FunctorAnd4,
FunctorOr, FunctorOr,
FunctorOr4, FunctorOr4,
FunctorLAnd, FunctorLAnd,
FunctorLOr, FunctorLOr,
FunctorNot, FunctorNot,
FunctorMinus1, FunctorMinus1,
FunctorXor, FunctorXor,
FunctorNand, FunctorNand,
FunctorNor, FunctorNor,
FunctorTimes, FunctorTimes,
FunctorImplies,
FunctorPlus, FunctorPlus,
FunctorMinus, FunctorMinus,
FunctorTimes4, FunctorTimes4,
@ -75,7 +76,7 @@ static YAP_Functor FunctorDollarVar,
FunctorOutPos, FunctorOutPos,
FunctorOutNeg; FunctorOutNeg;
static YAP_Term TermMinusOne, TermPlusOne; static YAP_Term TermMinusOne, TermZero, TermPlusOne, TermTrue, TermFalse;
void init_cudd(void); void init_cudd(void);
@ -243,7 +244,7 @@ term_to_cudd(DdManager *manager, YAP_Term t)
else { else {
YAP_Error(DOMAIN_ERROR_OUT_OF_RANGE, t, "unsupported number in CUDD"); YAP_Error(DOMAIN_ERROR_OUT_OF_RANGE, t, "unsupported number in CUDD");
return NULL; return NULL;
} }
} else if (YAP_IsFloatTerm(t)) { } else if (YAP_IsFloatTerm(t)) {
YAP_Int i = YAP_FloatOfTerm(t); YAP_Int i = YAP_FloatOfTerm(t);
if (i == 0.0) if (i == 0.0)
@ -253,7 +254,16 @@ term_to_cudd(DdManager *manager, YAP_Term t)
else { else {
YAP_Error(DOMAIN_ERROR_OUT_OF_RANGE, t, "unsupported number in CUDD"); YAP_Error(DOMAIN_ERROR_OUT_OF_RANGE, t, "unsupported number in CUDD");
return NULL; return NULL;
} }
} else if (YAP_IsAtomTerm(t)) {
if (t == TermFalse)
return Cudd_ReadLogicZero(manager);
else if (t == TermTrue)
return Cudd_ReadOne(manager);
else {
YAP_Error(DOMAIN_ERROR_OUT_OF_RANGE, t, "unsupported atom %s in CUDD", YAP_AtomName(YAP_AtomOfTerm(t)));
return NULL;
}
} else if (YAP_IsVarTerm(t)) { } else if (YAP_IsVarTerm(t)) {
YAP_Error(INSTANTIATION_ERROR, t, "unsupported unbound term in CUDD"); YAP_Error(INSTANTIATION_ERROR, t, "unsupported unbound term in CUDD");
return NULL; return NULL;
@ -279,8 +289,8 @@ p_term_to_cudd(void)
t = term_to_cudd(manager, YAP_ARG1); t = term_to_cudd(manager, YAP_ARG1);
if (!t) if (!t)
return FALSE; return FALSE;
return return
YAP_Unify(YAP_ARG3, YAP_MkIntTerm((YAP_Int)t)); YAP_Unify(YAP_ARG3, YAP_MkIntTerm((YAP_Int)t));
} }
static DdNode * static DdNode *
@ -293,6 +303,16 @@ add_times(DdManager *manager, DdNode *x1, DdNode *x2)
return tmp; return tmp;
} }
static DdNode *
add_implies(DdManager *manager, DdNode *x1, DdNode *x2)
{
DdNode *tmp;
tmp = Cudd_addApply(manager,Cudd_addLeq,x1,x2);
Cudd_Ref(tmp);
return tmp;
}
static DdNode * static DdNode *
add_plus(DdManager *manager, DdNode *x1, DdNode *x2) add_plus(DdManager *manager, DdNode *x1, DdNode *x2)
{ {
@ -379,6 +399,14 @@ term_to_add(DdManager *manager, YAP_Term t)
DdNode *x2 = term_to_add(manager, YAP_ArgOfTerm(2, t)); DdNode *x2 = term_to_add(manager, YAP_ArgOfTerm(2, t));
DdNode *tmp = add_minus(manager, x1, x2); DdNode *tmp = add_minus(manager, x1, x2);
Cudd_RecursiveDeref(manager,x1);
Cudd_RecursiveDeref(manager,x2);
return tmp;
} else if (f == FunctorImplies) {
DdNode *x1 = term_to_add(manager, YAP_ArgOfTerm(1, t));
DdNode *x2 = term_to_add(manager, YAP_ArgOfTerm(2, t));
DdNode *tmp = add_implies(manager, x1, x2);
Cudd_RecursiveDeref(manager,x1); Cudd_RecursiveDeref(manager,x1);
Cudd_RecursiveDeref(manager,x2); Cudd_RecursiveDeref(manager,x2);
return tmp; return tmp;
@ -428,7 +456,7 @@ p_term_to_add(void)
} }
t = term_to_add(manager, YAP_ARG1); t = term_to_add(manager, YAP_ARG1);
return YAP_Unify(YAP_ARG3, YAP_MkIntTerm((YAP_Int)manager)) && return YAP_Unify(YAP_ARG3, YAP_MkIntTerm((YAP_Int)manager)) &&
YAP_Unify(YAP_ARG4, YAP_MkIntTerm((YAP_Int)t)); YAP_Unify(YAP_ARG4, YAP_MkIntTerm((YAP_Int)t));
} }
static YAP_Bool complement(int i) static YAP_Bool complement(int i)
@ -494,7 +522,7 @@ p_eval_cudd(void)
} }
val = cudd_eval_top(manager, n, ar); val = cudd_eval_top(manager, n, ar);
free(ar); free(ar);
return YAP_Unify(YAP_ARG4, YAP_MkIntTerm(val)); return YAP_Unify(YAP_ARG4, YAP_MkIntTerm(val));
} }
static double static double
@ -534,7 +562,7 @@ p_eval_add(void)
} }
val = add_eval(manager, n, ar); val = add_eval(manager, n, ar);
free(ar); free(ar);
return YAP_Unify(YAP_ARG4, YAP_MkFloatTerm(val)); return YAP_Unify(YAP_ARG4, YAP_MkFloatTerm(val));
} }
typedef struct { typedef struct {
@ -686,7 +714,7 @@ p_add_to_term(void)
DdGen *dgen = Cudd_FirstNode(manager, n0, &node); DdGen *dgen = Cudd_FirstNode(manager, n0, &node);
hash_table_entry *hash = (hash_table_entry *)calloc(sz,sizeof(hash_table_entry)); hash_table_entry *hash = (hash_table_entry *)calloc(sz,sizeof(hash_table_entry));
YAP_Term *ar; YAP_Term *ar;
if (!dgen) if (!dgen)
return FALSE; return FALSE;
ar = (YAP_Term *)malloc(vars*sizeof(YAP_Term)); ar = (YAP_Term *)malloc(vars*sizeof(YAP_Term));
@ -797,7 +825,7 @@ p_cudd_to_p(void)
DdGen *dgen = Cudd_FirstNode(manager, n0, &node); DdGen *dgen = Cudd_FirstNode(manager, n0, &node);
hash_table_entry_dbl *hash = (hash_table_entry_dbl *)calloc(sz,sizeof(hash_table_entry_dbl)); hash_table_entry_dbl *hash = (hash_table_entry_dbl *)calloc(sz,sizeof(hash_table_entry_dbl));
double *ar; double *ar;
if (!dgen) if (!dgen)
return FALSE; return FALSE;
ar = (double *)malloc(vars*sizeof(double)); ar = (double *)malloc(vars*sizeof(double));
@ -836,6 +864,40 @@ p_cudd_print(void)
return TRUE; return TRUE;
} }
static YAP_Bool
p_cudd_print_with_names(void)
{
DdManager *manager = (DdManager *)YAP_IntOfTerm(YAP_ARG1);
DdNode *n0 = (DdNode *)YAP_IntOfTerm(YAP_ARG2);
const char *s = YAP_AtomName(YAP_AtomOfTerm(YAP_ARG3));
const char **namesp;
YAP_Term names = YAP_ARG4;
FILE *f;
YAP_Int len;
if (!strcmp(s, "user_output")) f = stdout;
else if (!strcmp(s, "user_error")) f = stderr;
else if (!strcmp(s, "user")) f = stdout;
else f = fopen(s, "w");
if ((len = YAP_ListLength(names)) < 0)
return FALSE;
if ((namesp = malloc(sizeof(const char *)*len)) == NULL)
return FALSE;
while (YAP_IsPairTerm(names)) {
YAP_Int i = 0;
YAP_Term hd = YAP_HeadOfTerm( names);
char * s = YAP_AtomName(YAP_AtomOfTerm(hd));
const char *ns = malloc(strlen(s)+1);
strncpy(ns, s, strlen(s)+1);
namesp[i++] = ns;
names = YAP_TailOfTerm( names);
}
Cudd_DumpDot(manager, 1, &n0, (char **)namesp, NULL, f);
free( namesp );
if (f != stdout && f != stderr)
fclose(f);
return TRUE;
}
static YAP_Bool static YAP_Bool
p_cudd_die(void) p_cudd_die(void)
{ {
@ -856,7 +918,7 @@ p_cudd_release_node(void)
void void
init_cudd(void) init_cudd(void)
{ {
FunctorDollarVar = YAP_MkFunctor(YAP_LookupAtom("$VAR"), 1); FunctorDollarVar = YAP_MkFunctor(YAP_LookupAtom("$VAR"), 1);
FunctorAnd = YAP_MkFunctor(YAP_LookupAtom("/\\"), 2); FunctorAnd = YAP_MkFunctor(YAP_LookupAtom("/\\"), 2);
FunctorOr = YAP_MkFunctor(YAP_LookupAtom("\\/"), 2); FunctorOr = YAP_MkFunctor(YAP_LookupAtom("\\/"), 2);
@ -872,6 +934,7 @@ init_cudd(void)
FunctorMinus = YAP_MkFunctor(YAP_LookupAtom("-"), 2); FunctorMinus = YAP_MkFunctor(YAP_LookupAtom("-"), 2);
FunctorTimes4 = YAP_MkFunctor(YAP_LookupAtom("*"), 4); FunctorTimes4 = YAP_MkFunctor(YAP_LookupAtom("*"), 4);
FunctorPlus4 = YAP_MkFunctor(YAP_LookupAtom("+"), 4); FunctorPlus4 = YAP_MkFunctor(YAP_LookupAtom("+"), 4);
FunctorImplies = YAP_MkFunctor(YAP_LookupAtom("->"), 2);
FunctorNot = YAP_MkFunctor(YAP_LookupAtom("not"), 1); FunctorNot = YAP_MkFunctor(YAP_LookupAtom("not"), 1);
FunctorMinus1 = YAP_MkFunctor(YAP_LookupAtom("-"), 1); FunctorMinus1 = YAP_MkFunctor(YAP_LookupAtom("-"), 1);
FunctorOutPos = YAP_MkFunctor(YAP_LookupAtom("pp"), 4); FunctorOutPos = YAP_MkFunctor(YAP_LookupAtom("pp"), 4);
@ -879,7 +942,9 @@ init_cudd(void)
FunctorOutAdd = YAP_MkFunctor(YAP_LookupAtom("add"), 4); FunctorOutAdd = YAP_MkFunctor(YAP_LookupAtom("add"), 4);
FunctorCudd = YAP_MkFunctor(YAP_LookupAtom("cudd"), 1); FunctorCudd = YAP_MkFunctor(YAP_LookupAtom("cudd"), 1);
TermMinusOne = YAP_MkIntTerm(-1); TermMinusOne = YAP_MkIntTerm(-1);
TermPlusOne = YAP_MkIntTerm(-1); TermPlusOne = YAP_MkIntTerm(+1);
TermFalse = YAP_MkAtomTerm(YAP_LookupAtom("false"));
TermTrue = YAP_MkAtomTerm(YAP_LookupAtom("true"));
YAP_UserCPredicate("term_to_cudd", p_term_to_cudd, 3); YAP_UserCPredicate("term_to_cudd", p_term_to_cudd, 3);
YAP_UserCPredicate("term_to_add", p_term_to_add, 4); YAP_UserCPredicate("term_to_add", p_term_to_add, 4);
YAP_UserCPredicate("cudd_eval", p_eval_cudd, 4); YAP_UserCPredicate("cudd_eval", p_eval_cudd, 4);
@ -891,6 +956,7 @@ init_cudd(void)
YAP_UserCPredicate("cudd_die", p_cudd_die, 1); YAP_UserCPredicate("cudd_die", p_cudd_die, 1);
YAP_UserCPredicate("cudd_release_node", p_cudd_release_node, 2); YAP_UserCPredicate("cudd_release_node", p_cudd_release_node, 2);
YAP_UserCPredicate("cudd_print", p_cudd_print, 3); YAP_UserCPredicate("cudd_print", p_cudd_print, 3);
YAP_UserCPredicate("cudd_print", p_cudd_print_with_names, 4);
} }
/** /**