#include "util_hack.h"
#include "cuddInt.h"
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)) |
DdNode * | Cudd_Eval (DdManager *dd, DdNode *f, int *inputs) |
DdNode * | Cudd_ShortestPath (DdManager *manager, DdNode *f, int *weight, int *support, int *length) |
DdNode * | Cudd_LargestCube (DdManager *manager, DdNode *f, int *length) |
int | Cudd_ShortestLength (DdManager *manager, DdNode *f, int *weight) |
DdNode * | Cudd_Decreasing (DdManager *dd, DdNode *f, int i) |
DdNode * | Cudd_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) |
DdNode * | Cudd_bddMakePrime (DdManager *dd, DdNode *cube, DdNode *f) |
DdNode * | cuddBddMakePrime (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 DdNode * | getPath (DdManager *manager, st_table *visited, DdNode *f, int *weight, int cost) |
static cuddPathPair | getLargest (DdNode *root, st_table *visited) |
static DdNode * | getCube (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 DdNode * | one |
static DdNode * | zero |
#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.]
#define WEIGHT | ( | weight, | |||
col | ) | ((weight) == NULL ? 1 : weight[col]) |
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] |
AutomaticStart
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
char rcsid [] DD_UNUSED = "$Id: cuddSat.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $" [static] |