src/bdd/cudd/cuddSat.c File Reference

#include "util_hack.h"
#include "cuddInt.h"
Include dependency graph for cuddSat.c:

Go to the source code of this file.

Data Structures

struct  cuddPathPair

Defines

#define DD_BIGGY   1000000
#define WEIGHT(weight, col)   ((weight) == NULL ? 1 : weight[col])

Functions

static enum st_retval freePathPair ARGS ((char *key, char *value, char *arg))
static cuddPathPair getShortest ARGS ((DdNode *root, int *cost, int *support, st_table *visited))
static DdNode *getPath ARGS ((DdManager *manager, st_table *visited, DdNode *f, int *weight, int cost))
static cuddPathPair getLargest ARGS ((DdNode *root, st_table *visited))
static DdNode *getCube ARGS ((DdManager *manager, st_table *visited, DdNode *f, int cost))
DdNodeCudd_Eval (DdManager *dd, DdNode *f, int *inputs)
DdNodeCudd_ShortestPath (DdManager *manager, DdNode *f, int *weight, int *support, int *length)
DdNodeCudd_LargestCube (DdManager *manager, DdNode *f, int *length)
int Cudd_ShortestLength (DdManager *manager, DdNode *f, int *weight)
DdNodeCudd_Decreasing (DdManager *dd, DdNode *f, int i)
DdNodeCudd_Increasing (DdManager *dd, DdNode *f, int i)
int Cudd_EquivDC (DdManager *dd, DdNode *F, DdNode *G, DdNode *D)
int Cudd_bddLeqUnless (DdManager *dd, DdNode *f, DdNode *g, DdNode *D)
int Cudd_EqualSupNorm (DdManager *dd, DdNode *f, DdNode *g, CUDD_VALUE_TYPE tolerance, int pr)
DdNodeCudd_bddMakePrime (DdManager *dd, DdNode *cube, DdNode *f)
DdNodecuddBddMakePrime (DdManager *dd, DdNode *cube, DdNode *f)
static enum st_retval freePathPair (char *key, char *value, char *arg)
static cuddPathPair getShortest (DdNode *root, int *cost, int *support, st_table *visited)
static DdNodegetPath (DdManager *manager, st_table *visited, DdNode *f, int *weight, int cost)
static cuddPathPair getLargest (DdNode *root, st_table *visited)
static DdNodegetCube (DdManager *manager, st_table *visited, DdNode *f, int cost)

Variables

static char rcsid[] DD_UNUSED = "$Id: cuddSat.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"
static DdNodeone
static DdNodezero

Define Documentation

#define DD_BIGGY   1000000

CFile***********************************************************************

FileName [cuddSat.c]

PackageName [cudd]

Synopsis [Functions for the solution of satisfiability related problems.]

Description [External procedures included in this file:

Internal procedures included in this module:

Static procedures included in this module:

]

Author [Seh-Woong Jeong, Fabio Somenzi]

Copyright [This file was created at the University of Colorado at Boulder. The University of Colorado at Boulder makes no warranty about the suitability of this software for any purpose. It is presented on an AS IS basis.]

Definition at line 52 of file cuddSat.c.

#define WEIGHT ( weight,
col   )     ((weight) == NULL ? 1 : weight[col])

Definition at line 81 of file cuddSat.c.


Function Documentation

static DdNode* getCube ARGS ( (DdManager *manager, st_table *visited, DdNode *f, int cost)   )  [static]
static cuddPathPair getLargest ARGS ( (DdNode *root, st_table *visited)   )  [static]
static DdNode* getPath ARGS ( (DdManager *manager, st_table *visited, DdNode *f, int *weight, int cost)   )  [static]
static cuddPathPair getShortest ARGS ( (DdNode *root, int *cost, int *support, st_table *visited)   )  [static]
static enum st_retval freePathPair ARGS ( (char *key, char *value, char *arg)   )  [static]

AutomaticStart

int Cudd_bddLeqUnless ( DdManager dd,
DdNode f,
DdNode g,
DdNode D 
)

Function********************************************************************

Synopsis [Tells whether f is less than of equal to G unless D is 1.]

Description [Tells whether f is less than of equal to G unless D is 1. f, g, and D are BDDs. The function returns 1 if f is less than of equal to G, and 0 otherwise. No new nodes are created.]

SideEffects [None]

SeeAlso [Cudd_EquivDC Cudd_bddLeq Cudd_bddIteConstant]

Definition at line 577 of file cuddSat.c.

00582 {
00583     DdNode *tmp, *One, *F, *G;
00584     DdNode *Ft, *Fe, *Gt, *Ge, *Dt, *De;
00585     int res;
00586     unsigned int flevel, glevel, dlevel, top;
00587 
00588     statLine(dd);
00589 
00590     One = DD_ONE(dd);
00591 
00592     /* Check terminal cases. */
00593     if (f == g || g == One || f == Cudd_Not(One) || D == One ||
00594         D == f || D == Cudd_Not(g)) return(1);
00595     /* Check for two-operand cases. */
00596     if (D == Cudd_Not(One) || D == g || D == Cudd_Not(f))
00597         return(Cudd_bddLeq(dd,f,g));
00598     if (g == Cudd_Not(One) || g == Cudd_Not(f)) return(Cudd_bddLeq(dd,f,D));
00599     if (f == One) return(Cudd_bddLeq(dd,Cudd_Not(g),D));
00600 
00601     /* From now on, f, g, and D are non-constant, distinct, and
00602     ** non-complementary. */
00603 
00604     /* Normalize call to increase cache efficiency.  We rely on the
00605     ** fact that f <= g unless D is equivalent to not(g) <= not(f)
00606     ** unless D and to f <= D unless g.  We make sure that D is
00607     ** regular, and that at most one of f and g is complemented.  We also
00608     ** ensure that when two operands can be swapped, the one with the
00609     ** lowest address comes first. */
00610 
00611     if (Cudd_IsComplement(D)) {
00612         if (Cudd_IsComplement(g)) {
00613             /* Special case: if f is regular and g is complemented,
00614             ** f(1,...,1) = 1 > 0 = g(1,...,1).  If D(1,...,1) = 0, return 0.
00615             */
00616             if (!Cudd_IsComplement(f)) return(0);
00617             /* !g <= D unless !f  or  !D <= g unless !f */
00618             tmp = D;
00619             D = Cudd_Not(f);
00620             if (g < tmp) {
00621                 f = Cudd_Not(g);
00622                 g = tmp;
00623             } else {
00624                 f = Cudd_Not(tmp);
00625             }
00626         } else {
00627             if (Cudd_IsComplement(f)) {
00628                 /* !D <= !f unless g  or  !D <= g unless !f */
00629                 tmp = f;
00630                 f = Cudd_Not(D);
00631                 if (tmp < g) {
00632                     D = g;
00633                     g = Cudd_Not(tmp);
00634                 } else {
00635                     D = Cudd_Not(tmp);
00636                 }
00637             } else {
00638                 /* f <= D unless g  or  !D <= !f unless g */
00639                 tmp = D;
00640                 D = g;
00641                 if (tmp < f) {
00642                     g = Cudd_Not(f);
00643                     f = Cudd_Not(tmp);
00644                 } else {
00645                     g = tmp;
00646                 }
00647             }
00648         }
00649     } else {
00650         if (Cudd_IsComplement(g)) {
00651             if (Cudd_IsComplement(f)) {
00652                 /* !g <= !f unless D  or  !g <= D unless !f */
00653                 tmp = f;
00654                 f = Cudd_Not(g);
00655                 if (D < tmp) {
00656                     g = D;
00657                     D = Cudd_Not(tmp);
00658                 } else {
00659                     g = Cudd_Not(tmp);
00660                 }
00661             } else {
00662                 /* f <= g unless D  or  !g <= !f unless D */
00663                 if (g < f) {
00664                     tmp = g;
00665                     g = Cudd_Not(f);
00666                     f = Cudd_Not(tmp);
00667                 }
00668             }
00669         } else {
00670             /* f <= g unless D  or  f <= D unless g */
00671             if (D < g) {
00672                 tmp = D;
00673                 D = g;
00674                 g = tmp;
00675             }
00676         }
00677     }
00678 
00679     /* From now on, D is regular. */
00680 
00681     /* Check cache. */
00682     tmp = cuddCacheLookup(dd,DD_BDD_LEQ_UNLESS_TAG,f,g,D);
00683     if (tmp != NULL) return(tmp == One);
00684 
00685     /* Find splitting variable. */
00686     F = Cudd_Regular(f);
00687     flevel = dd->perm[F->index];
00688     G = Cudd_Regular(g);
00689     glevel = dd->perm[G->index];
00690     top = ddMin(flevel,glevel);
00691     dlevel = dd->perm[D->index];
00692     top = ddMin(top,dlevel);
00693 
00694     /* Compute cofactors. */
00695     if (top == flevel) {
00696         Ft = cuddT(F);
00697         Fe = cuddE(F);
00698         if (F != f) {
00699             Ft = Cudd_Not(Ft);
00700             Fe = Cudd_Not(Fe);
00701         }
00702     } else {
00703         Ft = Fe = f;
00704     }
00705     if (top == glevel) {
00706         Gt = cuddT(G);
00707         Ge = cuddE(G);
00708         if (G != g) {
00709             Gt = Cudd_Not(Gt);
00710             Ge = Cudd_Not(Ge);
00711         }
00712     } else {
00713         Gt = Ge = g;
00714     }
00715     if (top == dlevel) {
00716         Dt = cuddT(D);
00717         De = cuddE(D);
00718     } else {
00719         Dt = De = D;
00720     }
00721 
00722     /* Solve recursively. */
00723     res = Cudd_bddLeqUnless(dd,Ft,Gt,Dt);
00724     if (res != 0) {
00725         res = Cudd_bddLeqUnless(dd,Fe,Ge,De);
00726     }
00727     cuddCacheInsert(dd,DD_BDD_LEQ_UNLESS_TAG,f,g,D,Cudd_NotCond(One,!res));
00728 
00729     return(res);
00730 
00731 } /* end of Cudd_bddLeqUnless */

DdNode* Cudd_bddMakePrime ( DdManager dd,
DdNode cube,
DdNode f 
)

Function********************************************************************

Synopsis [Expands cube to a prime implicant of f.]

Description [Expands cube to a prime implicant of f. Returns the prime if successful; NULL otherwise. In particular, NULL is returned if cube is not a real cube or is not an implicant of f.]

SideEffects [None]

SeeAlso []

Definition at line 828 of file cuddSat.c.

00832 {
00833     DdNode *res;
00834 
00835     if (!Cudd_bddLeq(dd,cube,f)) return(NULL);
00836 
00837     do {
00838         dd->reordered = 0;
00839         res = cuddBddMakePrime(dd,cube,f);
00840     } while (dd->reordered == 1);
00841     return(res);
00842 
00843 } /* end of Cudd_bddMakePrime */

DdNode* Cudd_Decreasing ( DdManager dd,
DdNode f,
int  i 
)

Function********************************************************************

Synopsis [Determines whether a BDD is negative unate in a variable.]

Description [Determines whether the function represented by BDD f is negative unate (monotonic decreasing) in variable i. Returns the constant one is f is unate and the (logical) constant zero if it is not. This function does not generate any new nodes.]

SideEffects [None]

SeeAlso [Cudd_Increasing]

Definition at line 372 of file cuddSat.c.

00376 {
00377     unsigned int topf, level;
00378     DdNode *F, *fv, *fvn, *res;
00379     DdNode *(*cacheOp)(DdManager *, DdNode *, DdNode *);
00380 
00381     statLine(dd);
00382 #ifdef DD_DEBUG
00383     assert(0 <= i && i < dd->size);
00384 #endif
00385 
00386     F = Cudd_Regular(f);
00387     topf = cuddI(dd,F->index);
00388 
00389     /* Check terminal case. If topf > i, f does not depend on var.
00390     ** Therefore, f is unate in i.
00391     */
00392     level = (unsigned) dd->perm[i];
00393     if (topf > level) {
00394         return(DD_ONE(dd));
00395     }
00396 
00397     /* From now on, f is not constant. */
00398 
00399     /* Check cache. */
00400     cacheOp = (DdNode *(*)(DdManager *, DdNode *, DdNode *)) Cudd_Decreasing;
00401     res = cuddCacheLookup2(dd,cacheOp,f,dd->vars[i]);
00402     if (res != NULL) {
00403         return(res);
00404     }
00405 
00406     /* Compute cofactors. */
00407     fv = cuddT(F); fvn = cuddE(F);
00408     if (F != f) {
00409         fv = Cudd_Not(fv);
00410         fvn = Cudd_Not(fvn);
00411     }
00412 
00413     if (topf == (unsigned) level) {
00414         /* Special case: if fv is regular, fv(1,...,1) = 1;
00415         ** If in addition fvn is complemented, fvn(1,...,1) = 0.
00416         ** But then f(1,1,...,1) > f(0,1,...,1). Hence f is not
00417         ** monotonic decreasing in i.
00418         */
00419         if (!Cudd_IsComplement(fv) && Cudd_IsComplement(fvn)) {
00420             return(Cudd_Not(DD_ONE(dd)));
00421         }
00422         res = Cudd_bddLeq(dd,fv,fvn) ? DD_ONE(dd) : Cudd_Not(DD_ONE(dd));
00423     } else {
00424         res = Cudd_Decreasing(dd,fv,i);
00425         if (res == DD_ONE(dd)) {
00426             res = Cudd_Decreasing(dd,fvn,i);
00427         }
00428     }
00429 
00430     cuddCacheInsert2(dd,cacheOp,f,dd->vars[i],res);
00431     return(res);
00432 
00433 } /* end of Cudd_Decreasing */

int Cudd_EqualSupNorm ( DdManager dd,
DdNode f,
DdNode g,
CUDD_VALUE_TYPE  tolerance,
int  pr 
)

Function********************************************************************

Synopsis [Compares two ADDs for equality within tolerance.]

Description [Compares two ADDs for equality within tolerance. Two ADDs are reported to be equal if the maximum difference between them (the sup norm of their difference) is less than or equal to the tolerance parameter. Returns 1 if the two ADDs are equal (within tolerance); 0 otherwise. If parameter pr is positive the first failure is reported to the standard output.]

SideEffects [None]

SeeAlso []

Definition at line 751 of file cuddSat.c.

00757 {
00758     DdNode *fv, *fvn, *gv, *gvn, *r;
00759     unsigned int topf, topg;
00760 
00761     statLine(dd);
00762     /* Check terminal cases. */
00763     if (f == g) return(1);
00764     if (Cudd_IsConstant(f) && Cudd_IsConstant(g)) {
00765         if (ddEqualVal(cuddV(f),cuddV(g),tolerance)) {
00766             return(1);
00767         } else {
00768             if (pr>0) {
00769                 (void) fprintf(dd->out,"Offending nodes:\n");
00770 #if SIZEOF_VOID_P == 8
00771                 (void) fprintf(dd->out,
00772                                "f: address = %lx\t value = %40.30f\n",
00773                                (unsigned long) f, cuddV(f));
00774                 (void) fprintf(dd->out,
00775                                "g: address = %lx\t value = %40.30f\n",
00776                                (unsigned long) g, cuddV(g));
00777 #else
00778                 (void) fprintf(dd->out,
00779                                "f: address = %x\t value = %40.30f\n",
00780                                (unsigned) f, cuddV(f));
00781                 (void) fprintf(dd->out,
00782                                "g: address = %x\t value = %40.30f\n",
00783                                (unsigned) g, cuddV(g));
00784 #endif
00785             }
00786             return(0);
00787         }
00788     }
00789 
00790     /* We only insert the result in the cache if the comparison is
00791     ** successful. Therefore, if we hit we return 1. */
00792     r = cuddCacheLookup2(dd,(DdNode * (*)(DdManager *, DdNode *, DdNode *))Cudd_EqualSupNorm,f,g);
00793     if (r != NULL) {
00794         return(1);
00795     }
00796 
00797     /* Compute the cofactors and solve the recursive subproblems. */
00798     topf = cuddI(dd,f->index);
00799     topg = cuddI(dd,g->index);
00800 
00801     if (topf <= topg) {fv = cuddT(f); fvn = cuddE(f);} else {fv = fvn = f;}
00802     if (topg <= topf) {gv = cuddT(g); gvn = cuddE(g);} else {gv = gvn = g;}
00803 
00804     if (!Cudd_EqualSupNorm(dd,fv,gv,tolerance,pr)) return(0);
00805     if (!Cudd_EqualSupNorm(dd,fvn,gvn,tolerance,pr)) return(0);
00806 
00807     cuddCacheInsert2(dd,(DdNode * (*)(DdManager *, DdNode *, DdNode *))Cudd_EqualSupNorm,f,g,DD_ONE(dd));
00808 
00809     return(1);
00810 
00811 } /* end of Cudd_EqualSupNorm */

int Cudd_EquivDC ( DdManager dd,
DdNode F,
DdNode G,
DdNode D 
)

Function********************************************************************

Synopsis [Tells whether F and G are identical wherever D is 0.]

Description [Tells whether F and G are identical wherever D is 0. F and G are either two ADDs or two BDDs. D is either a 0-1 ADD or a BDD. The function returns 1 if F and G are equivalent, and 0 otherwise. No new nodes are created.]

SideEffects [None]

SeeAlso [Cudd_bddLeqUnless]

Definition at line 477 of file cuddSat.c.

00482 {
00483     DdNode *tmp, *One, *Gr, *Dr;
00484     DdNode *Fv, *Fvn, *Gv, *Gvn, *Dv, *Dvn;
00485     int res;
00486     unsigned int flevel, glevel, dlevel, top;
00487 
00488     One = DD_ONE(dd);
00489 
00490     statLine(dd);
00491     /* Check terminal cases. */
00492     if (D == One || F == G) return(1);
00493     if (D == Cudd_Not(One) || D == DD_ZERO(dd) || F == Cudd_Not(G)) return(0);
00494 
00495     /* From now on, D is non-constant. */
00496 
00497     /* Normalize call to increase cache efficiency. */
00498     if (F > G) {
00499         tmp = F;
00500         F = G;
00501         G = tmp;
00502     }
00503     if (Cudd_IsComplement(F)) {
00504         F = Cudd_Not(F);
00505         G = Cudd_Not(G);
00506     }
00507 
00508     /* From now on, F is regular. */
00509 
00510     /* Check cache. */
00511     tmp = cuddCacheLookup(dd,DD_EQUIV_DC_TAG,F,G,D);
00512     if (tmp != NULL) return(tmp == One);
00513 
00514     /* Find splitting variable. */
00515     flevel = cuddI(dd,F->index);
00516     Gr = Cudd_Regular(G);
00517     glevel = cuddI(dd,Gr->index);
00518     top = ddMin(flevel,glevel);
00519     Dr = Cudd_Regular(D);
00520     dlevel = dd->perm[Dr->index];
00521     top = ddMin(top,dlevel);
00522 
00523     /* Compute cofactors. */
00524     if (top == flevel) {
00525         Fv = cuddT(F);
00526         Fvn = cuddE(F);
00527     } else {
00528         Fv = Fvn = F;
00529     }
00530     if (top == glevel) {
00531         Gv = cuddT(Gr);
00532         Gvn = cuddE(Gr);
00533         if (G != Gr) {
00534             Gv = Cudd_Not(Gv);
00535             Gvn = Cudd_Not(Gvn);
00536         }
00537     } else {
00538         Gv = Gvn = G;
00539     }
00540     if (top == dlevel) {
00541         Dv = cuddT(Dr);
00542         Dvn = cuddE(Dr);
00543         if (D != Dr) {
00544             Dv = Cudd_Not(Dv);
00545             Dvn = Cudd_Not(Dvn);
00546         }
00547     } else {
00548         Dv = Dvn = D;
00549     }
00550 
00551     /* Solve recursively. */
00552     res = Cudd_EquivDC(dd,Fv,Gv,Dv);
00553     if (res != 0) {
00554         res = Cudd_EquivDC(dd,Fvn,Gvn,Dvn);
00555     }
00556     cuddCacheInsert(dd,DD_EQUIV_DC_TAG,F,G,D,(res) ? One : Cudd_Not(One));
00557 
00558     return(res);
00559 
00560 } /* end of Cudd_EquivDC */

DdNode* Cudd_Eval ( DdManager dd,
DdNode f,
int *  inputs 
)

AutomaticEnd Function********************************************************************

Synopsis [Returns the value of a DD for a given variable assignment.]

Description [Finds the value of a DD for a given variable assignment. The variable assignment is passed in an array of int's, that should specify a zero or a one for each variable in the support of the function. Returns a pointer to a constant node. No new nodes are produced.]

SideEffects [None]

SeeAlso [Cudd_bddLeq Cudd_addEvalConst]

Definition at line 119 of file cuddSat.c.

00123 {
00124     int comple;
00125     DdNode *ptr;
00126 
00127     comple = Cudd_IsComplement(f);
00128     ptr = Cudd_Regular(f);
00129 
00130     while (!cuddIsConstant(ptr)) {
00131         if (inputs[ptr->index] == 1) {
00132             ptr = cuddT(ptr);
00133         } else {
00134             comple ^= Cudd_IsComplement(cuddE(ptr));
00135             ptr = Cudd_Regular(cuddE(ptr));
00136         }
00137     }
00138     return(Cudd_NotCond(ptr,comple));
00139 
00140 } /* end of Cudd_Eval */

DdNode* Cudd_Increasing ( DdManager dd,
DdNode f,
int  i 
)

Function********************************************************************

Synopsis [Determines whether a BDD is positive unate in a variable.]

Description [Determines whether the function represented by BDD f is positive unate (monotonic decreasing) in variable i. It is based on Cudd_Decreasing and the fact that f is monotonic increasing in i if and only if its complement is monotonic decreasing in i.]

SideEffects [None]

SeeAlso [Cudd_Decreasing]

Definition at line 452 of file cuddSat.c.

00456 {
00457     return(Cudd_Decreasing(dd,Cudd_Not(f),i));
00458 
00459 } /* end of Cudd_Increasing */

DdNode* Cudd_LargestCube ( DdManager manager,
DdNode f,
int *  length 
)

Function********************************************************************

Synopsis [Finds a largest cube in a DD.]

Description [Finds a largest cube in a DD. f is the DD we want to get the largest cube for. The problem is translated into the one of finding a shortest path in f, when both THEN and ELSE arcs are assumed to have unit length. This yields a largest cube in the disjoint cover corresponding to the DD. Therefore, it is not necessarily the largest implicant of f. Returns the largest cube as a BDD.]

SideEffects [The number of literals of the cube is returned in length.]

SeeAlso [Cudd_ShortestPath]

Definition at line 243 of file cuddSat.c.

00247 {
00248     register    DdNode  *F;
00249     st_table    *visited;
00250     DdNode      *sol;
00251     cuddPathPair *rootPair;
00252     int         complement, cost;
00253 
00254     one = DD_ONE(manager);
00255     zero = DD_ZERO(manager);
00256 
00257     if (f == Cudd_Not(one) || f == zero) {
00258         *length = DD_BIGGY;
00259         return(Cudd_Not(one));
00260     }
00261     /* From this point on, a path exists. */
00262 
00263     /* Initialize visited table. */
00264     visited = st_init_table(st_ptrcmp, st_ptrhash);
00265 
00266     /* Now get the length of the shortest path(s) from f to 1. */
00267     (void) getLargest(f, visited);
00268 
00269     complement = Cudd_IsComplement(f);
00270 
00271     F = Cudd_Regular(f);
00272 
00273     st_lookup(visited, (char *)F, (char **)&rootPair);
00274     
00275     if (complement) {
00276         cost = rootPair->neg;
00277     } else {
00278         cost = rootPair->pos;
00279     }
00280 
00281     /* Recover an actual shortest path. */
00282     do {
00283         manager->reordered = 0;
00284         sol = getCube(manager,visited,f,cost);
00285     } while (manager->reordered == 1);
00286 
00287     st_foreach(visited, freePathPair, NULL);
00288     st_free_table(visited);
00289 
00290     *length = cost;
00291     return(sol);
00292 
00293 } /* end of Cudd_LargestCube */

int Cudd_ShortestLength ( DdManager manager,
DdNode f,
int *  weight 
)

Function********************************************************************

Synopsis [Find the length of the shortest path(s) in a DD.]

Description [Find the length of the shortest path(s) in a DD. f is the DD we want to get the shortest path for; weight\[i\] is the weight of the THEN edge coming from the node whose index is i. All ELSE edges have 0 weight. Returns the length of the shortest path(s) if successful; CUDD_OUT_OF_MEM otherwise.]

SideEffects [None]

SeeAlso [Cudd_ShortestPath]

Definition at line 312 of file cuddSat.c.

00316 {
00317     register    DdNode  *F;
00318     st_table    *visited;
00319     cuddPathPair *my_pair;
00320     int         complement, cost;
00321 
00322     one = DD_ONE(manager);
00323     zero = DD_ZERO(manager);
00324 
00325     if (f == Cudd_Not(one) || f == zero) {
00326         return(DD_BIGGY);
00327     }
00328 
00329     /* From this point on, a path exists. */
00330     /* Initialize visited table and support. */
00331     visited = st_init_table(st_ptrcmp, st_ptrhash);
00332 
00333     /* Now get the length of the shortest path(s) from f to 1. */
00334     (void) getShortest(f, weight, NULL, visited);
00335 
00336     complement = Cudd_IsComplement(f);
00337 
00338     F = Cudd_Regular(f);
00339 
00340     st_lookup(visited, (char *)F, (char **)&my_pair);
00341     
00342     if (complement) {
00343         cost = my_pair->neg;
00344     } else {
00345         cost = my_pair->pos;
00346     }
00347 
00348     st_foreach(visited, freePathPair, NULL);
00349     st_free_table(visited);
00350 
00351     return(cost);
00352 
00353 } /* end of Cudd_ShortestLength */

DdNode* Cudd_ShortestPath ( DdManager manager,
DdNode f,
int *  weight,
int *  support,
int *  length 
)

Function********************************************************************

Synopsis [Finds a shortest path in a DD.]

Description [Finds a shortest path in a DD. f is the DD we want to get the shortest path for; weight\[i\] is the weight of the THEN arc coming from the node whose index is i. If weight is NULL, then unit weights are assumed for all THEN arcs. All ELSE arcs have 0 weight. If non-NULL, both weight and support should point to arrays with at least as many entries as there are variables in the manager. Returns the shortest path as the BDD of a cube.]

SideEffects [support contains on return the true support of f. If support is NULL on entry, then Cudd_ShortestPath does not compute the true support info. length contains the length of the path.]

SeeAlso [Cudd_ShortestLength Cudd_LargestCube]

Definition at line 163 of file cuddSat.c.

00169 {
00170     register    DdNode  *F;
00171     st_table    *visited;
00172     DdNode      *sol;
00173     cuddPathPair *rootPair;
00174     int         complement, cost;
00175     int         i;
00176 
00177     one = DD_ONE(manager);
00178     zero = DD_ZERO(manager);
00179 
00180     /* Initialize support. */
00181     if (support) {
00182         for (i = 0; i < manager->size; i++) {
00183             support[i] = 0;
00184         }
00185     }
00186 
00187     if (f == Cudd_Not(one) || f == zero) {
00188         *length = DD_BIGGY;
00189         return(Cudd_Not(one));
00190     }
00191     /* From this point on, a path exists. */
00192 
00193     /* Initialize visited table. */
00194     visited = st_init_table(st_ptrcmp, st_ptrhash);
00195 
00196     /* Now get the length of the shortest path(s) from f to 1. */
00197     (void) getShortest(f, weight, support, visited);
00198 
00199     complement = Cudd_IsComplement(f);
00200 
00201     F = Cudd_Regular(f);
00202 
00203     st_lookup(visited, (char *)F, (char **)&rootPair);
00204     
00205     if (complement) {
00206         cost = rootPair->neg;
00207     } else {
00208         cost = rootPair->pos;
00209     }
00210 
00211     /* Recover an actual shortest path. */
00212     do {
00213         manager->reordered = 0;
00214         sol = getPath(manager,visited,f,weight,cost);
00215     } while (manager->reordered == 1);
00216 
00217     st_foreach(visited, freePathPair, NULL);
00218     st_free_table(visited);
00219 
00220     *length = cost;
00221     return(sol);
00222 
00223 } /* end of Cudd_ShortestPath */

DdNode* cuddBddMakePrime ( DdManager dd,
DdNode cube,
DdNode f 
)

Function********************************************************************

Synopsis [Performs the recursive step of Cudd_bddMakePrime.]

Description [Performs the recursive step of Cudd_bddMakePrime. Returns the prime if successful; NULL otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 864 of file cuddSat.c.

00868 {
00869     DdNode *scan;
00870     DdNode *t, *e;
00871     DdNode *res = cube;
00872     DdNode *zero = Cudd_Not(DD_ONE(dd));
00873 
00874     Cudd_Ref(res);
00875     scan = cube;
00876     while (!Cudd_IsConstant(scan)) {
00877         DdNode *reg = Cudd_Regular(scan);
00878         DdNode *var = dd->vars[reg->index];
00879         DdNode *expanded = Cudd_bddExistAbstract(dd,res,var);
00880         if (expanded == NULL) {
00881             return(NULL);
00882         }
00883         Cudd_Ref(expanded);
00884         if (Cudd_bddLeq(dd,expanded,f)) {
00885             Cudd_RecursiveDeref(dd,res);
00886             res = expanded;
00887         } else {
00888             Cudd_RecursiveDeref(dd,expanded);
00889         }
00890         cuddGetBranches(scan,&t,&e);
00891         if (t == zero) {
00892             scan = e;
00893         } else if (e == zero) {
00894             scan = t;
00895         } else {
00896             Cudd_RecursiveDeref(dd,res);
00897             return(NULL);       /* cube is not a cube */
00898         }
00899     }
00900 
00901     if (scan == DD_ONE(dd)) {
00902         Cudd_Deref(res);
00903         return(res);
00904     } else {
00905         Cudd_RecursiveDeref(dd,res);
00906         return(NULL);
00907     }
00908 
00909 } /* end of cuddBddMakePrime */

static enum st_retval freePathPair ( char *  key,
char *  value,
char *  arg 
) [static]

Function********************************************************************

Synopsis [Frees the entries of the visited symbol table.]

Description [Frees the entries of the visited symbol table. Returns ST_CONTINUE.]

SideEffects [None]

Definition at line 928 of file cuddSat.c.

00932 {
00933     cuddPathPair *pair;
00934 
00935     pair = (cuddPathPair *) value;
00936         FREE(pair);
00937     return(ST_CONTINUE);
00938 
00939 } /* end of freePathPair */

static DdNode* getCube ( DdManager manager,
st_table visited,
DdNode f,
int  cost 
) [static]

Function********************************************************************

Synopsis [Build a BDD for a largest cube of f.]

Description [Build a BDD for a largest cube of f. Given the minimum length from the root, and the minimum lengths for each node (in visited), apply triangulation at each node. Of the two children of each node on a shortest path, at least one is on a shortest path. In case of ties the procedure chooses the THEN children. Returns a pointer to the cube BDD representing the path if successful; NULL otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 1237 of file cuddSat.c.

01242 {
01243     DdNode      *sol, *tmp;
01244     DdNode      *my_dd, *T, *E;
01245     cuddPathPair *T_pair, *E_pair;
01246     int         Tcost, Ecost;
01247     int         complement;
01248 
01249     my_dd = Cudd_Regular(f);
01250     complement = Cudd_IsComplement(f);
01251 
01252     sol = one;
01253     cuddRef(sol);
01254 
01255     while (!cuddIsConstant(my_dd)) {
01256         Tcost = cost - 1;
01257         Ecost = cost - 1;
01258 
01259         T = cuddT(my_dd);
01260         E = cuddE(my_dd);
01261 
01262         if (complement) {T = Cudd_Not(T); E = Cudd_Not(E);}
01263 
01264         st_lookup(visited, (char *)Cudd_Regular(T), (char **)&T_pair);
01265         if ((Cudd_IsComplement(T) && T_pair->neg == Tcost) ||
01266         (!Cudd_IsComplement(T) && T_pair->pos == Tcost)) {
01267             tmp = cuddBddAndRecur(manager,manager->vars[my_dd->index],sol);
01268             if (tmp == NULL) {
01269                 Cudd_RecursiveDeref(manager,sol);
01270                 return(NULL);
01271             }
01272             cuddRef(tmp);
01273             Cudd_RecursiveDeref(manager,sol);
01274             sol = tmp;
01275 
01276             complement =  Cudd_IsComplement(T);
01277             my_dd = Cudd_Regular(T);
01278             cost = Tcost;
01279             continue;
01280         }
01281         st_lookup(visited, (char *)Cudd_Regular(E), (char **)&E_pair);
01282         if ((Cudd_IsComplement(E) && E_pair->neg == Ecost) ||
01283         (!Cudd_IsComplement(E) && E_pair->pos == Ecost)) {
01284             tmp = cuddBddAndRecur(manager,Cudd_Not(manager->vars[my_dd->index]),sol);
01285             if (tmp == NULL) {
01286                 Cudd_RecursiveDeref(manager,sol);
01287                 return(NULL);
01288             }
01289             cuddRef(tmp);
01290             Cudd_RecursiveDeref(manager,sol);
01291             sol = tmp;
01292             complement = Cudd_IsComplement(E);
01293             my_dd = Cudd_Regular(E);
01294             cost = Ecost;
01295             continue;
01296         }
01297         (void) fprintf(manager->err,"We shouldn't be here!\n");
01298         manager->errorCode = CUDD_INTERNAL_ERROR;
01299         return(NULL);
01300     }
01301 
01302     cuddDeref(sol);
01303     return(sol);
01304 
01305 } /* end of getCube */

static cuddPathPair getLargest ( DdNode root,
st_table visited 
) [static]

Function********************************************************************

Synopsis [Finds the size of the largest cube(s) in a DD.]

Description [Finds the size of the largest cube(s) in a DD. This problem is translated into finding the shortest paths from a node when both THEN and ELSE arcs have unit lengths. Uses a local symbol table to store the lengths for each node. Only the lengths for the regular nodes are entered in the table, because those for the complement nodes are simply obtained by swapping the two lenghts. Returns a pair of lengths: the length of the shortest path to 1; and the length of the shortest path to 0. This is done so as to take complement arcs into account.]

SideEffects [none]

SeeAlso []

Definition at line 1150 of file cuddSat.c.

01153 {
01154     cuddPathPair *my_pair, res_pair, pair_T, pair_E;
01155     DdNode      *my_root, *T, *E;
01156 
01157     my_root = Cudd_Regular(root);
01158 
01159     if (st_lookup(visited, (char *)my_root, (char **)&my_pair)) {
01160         if (Cudd_IsComplement(root)) {
01161             res_pair.pos = my_pair->neg;
01162             res_pair.neg = my_pair->pos;
01163         } else {
01164             res_pair.pos = my_pair->pos;
01165             res_pair.neg = my_pair->neg;
01166         }
01167         return(res_pair);
01168     }
01169 
01170     /* In the case of a BDD the following test is equivalent to
01171     ** testing whether the BDD is the constant 1. This formulation,
01172     ** however, works for ADDs as well, by assuming the usual
01173     ** dichotomy of 0 and != 0.
01174     */
01175     if (cuddIsConstant(my_root)) {
01176         if (my_root != zero) {
01177             res_pair.pos = 0;
01178             res_pair.neg = DD_BIGGY;
01179         } else {
01180             res_pair.pos = DD_BIGGY;
01181             res_pair.neg = 0;
01182         }
01183     } else {
01184         T = cuddT(my_root);
01185         E = cuddE(my_root);
01186 
01187         pair_T = getLargest(T, visited);
01188         pair_E = getLargest(E, visited);
01189         res_pair.pos = ddMin(pair_T.pos, pair_E.pos) + 1;
01190         res_pair.neg = ddMin(pair_T.neg, pair_E.neg) + 1;
01191     }
01192 
01193     my_pair = ALLOC(cuddPathPair, 1);
01194     if (my_pair == NULL) {      /* simlpy do not cache this result */
01195         if (Cudd_IsComplement(root)) {
01196             int tmp = res_pair.pos;
01197             res_pair.pos = res_pair.neg;
01198             res_pair.neg = tmp;
01199         }
01200         return(res_pair);
01201     }
01202     my_pair->pos = res_pair.pos;
01203     my_pair->neg = res_pair.neg;
01204 
01205     st_insert(visited, (char *)my_root, (char *)my_pair);
01206     if (Cudd_IsComplement(root)) {
01207         res_pair.pos = my_pair->neg;
01208         res_pair.neg = my_pair->pos;
01209     } else {
01210         res_pair.pos = my_pair->pos;
01211         res_pair.neg = my_pair->neg;
01212     }
01213     return(res_pair);
01214 
01215 } /* end of getLargest */

static DdNode* getPath ( DdManager manager,
st_table visited,
DdNode f,
int *  weight,
int  cost 
) [static]

Function********************************************************************

Synopsis [Build a BDD for a shortest path of f.]

Description [Build a BDD for a shortest path of f. Given the minimum length from the root, and the minimum lengths for each node (in visited), apply triangulation at each node. Of the two children of each node on a shortest path, at least one is on a shortest path. In case of ties the procedure chooses the THEN children. Returns a pointer to the cube BDD representing the path if successful; NULL otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 1057 of file cuddSat.c.

01063 {
01064     DdNode      *sol, *tmp;
01065     DdNode      *my_dd, *T, *E;
01066     cuddPathPair *T_pair, *E_pair;
01067     int         Tcost, Ecost;
01068     int         complement;
01069 
01070     my_dd = Cudd_Regular(f);
01071     complement = Cudd_IsComplement(f);
01072 
01073     sol = one;
01074     cuddRef(sol);
01075 
01076     while (!cuddIsConstant(my_dd)) {
01077         Tcost = cost - WEIGHT(weight, my_dd->index);
01078         Ecost = cost;
01079 
01080         T = cuddT(my_dd);
01081         E = cuddE(my_dd);
01082 
01083         if (complement) {T = Cudd_Not(T); E = Cudd_Not(E);}
01084 
01085         st_lookup(visited, (char *)Cudd_Regular(T), (char **)&T_pair);
01086         if ((Cudd_IsComplement(T) && T_pair->neg == Tcost) ||
01087         (!Cudd_IsComplement(T) && T_pair->pos == Tcost)) {
01088             tmp = cuddBddAndRecur(manager,manager->vars[my_dd->index],sol);
01089             if (tmp == NULL) {
01090                 Cudd_RecursiveDeref(manager,sol);
01091                 return(NULL);
01092             }
01093             cuddRef(tmp);
01094             Cudd_RecursiveDeref(manager,sol);
01095             sol = tmp;
01096 
01097             complement =  Cudd_IsComplement(T);
01098             my_dd = Cudd_Regular(T);
01099             cost = Tcost;
01100             continue;
01101         }
01102         st_lookup(visited, (char *)Cudd_Regular(E), (char **)&E_pair);
01103         if ((Cudd_IsComplement(E) && E_pair->neg == Ecost) ||
01104         (!Cudd_IsComplement(E) && E_pair->pos == Ecost)) {
01105             tmp = cuddBddAndRecur(manager,Cudd_Not(manager->vars[my_dd->index]),sol);
01106             if (tmp == NULL) {
01107                 Cudd_RecursiveDeref(manager,sol);
01108                 return(NULL);
01109             }
01110             cuddRef(tmp);
01111             Cudd_RecursiveDeref(manager,sol);
01112             sol = tmp;
01113             complement = Cudd_IsComplement(E);
01114             my_dd = Cudd_Regular(E);
01115             cost = Ecost;
01116             continue;
01117         }
01118         (void) fprintf(manager->err,"We shouldn't be here!!\n");
01119         manager->errorCode = CUDD_INTERNAL_ERROR;
01120         return(NULL);
01121     }
01122 
01123     cuddDeref(sol);
01124     return(sol);
01125 
01126 } /* end of getPath */

static cuddPathPair getShortest ( DdNode root,
int *  cost,
int *  support,
st_table visited 
) [static]

Function********************************************************************

Synopsis [Finds the length of the shortest path(s) in a DD.]

Description [Finds the length of the shortest path(s) in a DD. Uses a local symbol table to store the lengths for each node. Only the lengths for the regular nodes are entered in the table, because those for the complement nodes are simply obtained by swapping the two lenghts. Returns a pair of lengths: the length of the shortest path to 1; and the length of the shortest path to 0. This is done so as to take complement arcs into account.]

SideEffects [Accumulates the support of the DD in support.]

SeeAlso []

Definition at line 961 of file cuddSat.c.

00966 {
00967     cuddPathPair *my_pair, res_pair, pair_T, pair_E;
00968     DdNode      *my_root, *T, *E;
00969     int         weight;
00970 
00971     my_root = Cudd_Regular(root);
00972 
00973     if (st_lookup(visited, (char *)my_root, (char **)&my_pair)) {
00974         if (Cudd_IsComplement(root)) {
00975             res_pair.pos = my_pair->neg;
00976             res_pair.neg = my_pair->pos;
00977         } else {
00978             res_pair.pos = my_pair->pos;
00979             res_pair.neg = my_pair->neg;
00980         }
00981         return(res_pair);
00982     }
00983 
00984     /* In the case of a BDD the following test is equivalent to
00985     ** testing whether the BDD is the constant 1. This formulation,
00986     ** however, works for ADDs as well, by assuming the usual
00987     ** dichotomy of 0 and != 0.
00988     */
00989     if (cuddIsConstant(my_root)) {
00990         if (my_root != zero) {
00991             res_pair.pos = 0;
00992             res_pair.neg = DD_BIGGY;
00993         } else {
00994             res_pair.pos = DD_BIGGY;
00995             res_pair.neg = 0;
00996         }
00997     } else {
00998         T = cuddT(my_root);
00999         E = cuddE(my_root);
01000 
01001         pair_T = getShortest(T, cost, support, visited);
01002         pair_E = getShortest(E, cost, support, visited);
01003         weight = WEIGHT(cost, my_root->index);
01004         res_pair.pos = ddMin(pair_T.pos+weight, pair_E.pos);
01005         res_pair.neg = ddMin(pair_T.neg+weight, pair_E.neg);
01006 
01007         /* Update support. */
01008         if (support != NULL) {
01009             support[my_root->index] = 1;
01010         }
01011     }
01012 
01013     my_pair = ALLOC(cuddPathPair, 1);
01014     if (my_pair == NULL) {
01015         if (Cudd_IsComplement(root)) {
01016             int tmp = res_pair.pos;
01017             res_pair.pos = res_pair.neg;
01018             res_pair.neg = tmp;
01019         }
01020         return(res_pair);
01021     }
01022     my_pair->pos = res_pair.pos;
01023     my_pair->neg = res_pair.neg;
01024 
01025     st_insert(visited, (char *)my_root, (char *)my_pair);
01026     if (Cudd_IsComplement(root)) {
01027         res_pair.pos = my_pair->neg;
01028         res_pair.neg = my_pair->pos;
01029     } else {
01030         res_pair.pos = my_pair->pos;
01031         res_pair.neg = my_pair->neg;
01032     }
01033     return(res_pair);
01034 
01035 } /* end of getShortest */


Variable Documentation

char rcsid [] DD_UNUSED = "$Id: cuddSat.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $" [static]

Definition at line 72 of file cuddSat.c.

DdNode* one [static]

Definition at line 75 of file cuddSat.c.

DdNode * zero [static]

Definition at line 75 of file cuddSat.c.


Generated on Tue Jan 5 12:18:56 2010 for abc70930 by  doxygen 1.6.1