#include "util.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 (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) |
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) |
Variables | |
static char rcsid[] | DD_UNUSED = "$Id: cuddSat.c,v 1.36 2009/03/08 02:49:02 fabio 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 [Copyright (c) 1995-2004, Regents of the University of Colorado
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.]
#define WEIGHT | ( | weight, | |||
col | ) | ((weight) == NULL ? 1 : weight[col]) |
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 618 of file cuddSat.c.
00623 { 00624 DdNode *tmp, *One, *F, *G; 00625 DdNode *Ft, *Fe, *Gt, *Ge, *Dt, *De; 00626 int res; 00627 unsigned int flevel, glevel, dlevel, top; 00628 00629 statLine(dd); 00630 00631 One = DD_ONE(dd); 00632 00633 /* Check terminal cases. */ 00634 if (f == g || g == One || f == Cudd_Not(One) || D == One || 00635 D == f || D == Cudd_Not(g)) return(1); 00636 /* Check for two-operand cases. */ 00637 if (D == Cudd_Not(One) || D == g || D == Cudd_Not(f)) 00638 return(Cudd_bddLeq(dd,f,g)); 00639 if (g == Cudd_Not(One) || g == Cudd_Not(f)) return(Cudd_bddLeq(dd,f,D)); 00640 if (f == One) return(Cudd_bddLeq(dd,Cudd_Not(g),D)); 00641 00642 /* From now on, f, g, and D are non-constant, distinct, and 00643 ** non-complementary. */ 00644 00645 /* Normalize call to increase cache efficiency. We rely on the 00646 ** fact that f <= g unless D is equivalent to not(g) <= not(f) 00647 ** unless D and to f <= D unless g. We make sure that D is 00648 ** regular, and that at most one of f and g is complemented. We also 00649 ** ensure that when two operands can be swapped, the one with the 00650 ** lowest address comes first. */ 00651 00652 if (Cudd_IsComplement(D)) { 00653 if (Cudd_IsComplement(g)) { 00654 /* Special case: if f is regular and g is complemented, 00655 ** f(1,...,1) = 1 > 0 = g(1,...,1). If D(1,...,1) = 0, return 0. 00656 */ 00657 if (!Cudd_IsComplement(f)) return(0); 00658 /* !g <= D unless !f or !D <= g unless !f */ 00659 tmp = D; 00660 D = Cudd_Not(f); 00661 if (g < tmp) { 00662 f = Cudd_Not(g); 00663 g = tmp; 00664 } else { 00665 f = Cudd_Not(tmp); 00666 } 00667 } else { 00668 if (Cudd_IsComplement(f)) { 00669 /* !D <= !f unless g or !D <= g unless !f */ 00670 tmp = f; 00671 f = Cudd_Not(D); 00672 if (tmp < g) { 00673 D = g; 00674 g = Cudd_Not(tmp); 00675 } else { 00676 D = Cudd_Not(tmp); 00677 } 00678 } else { 00679 /* f <= D unless g or !D <= !f unless g */ 00680 tmp = D; 00681 D = g; 00682 if (tmp < f) { 00683 g = Cudd_Not(f); 00684 f = Cudd_Not(tmp); 00685 } else { 00686 g = tmp; 00687 } 00688 } 00689 } 00690 } else { 00691 if (Cudd_IsComplement(g)) { 00692 if (Cudd_IsComplement(f)) { 00693 /* !g <= !f unless D or !g <= D unless !f */ 00694 tmp = f; 00695 f = Cudd_Not(g); 00696 if (D < tmp) { 00697 g = D; 00698 D = Cudd_Not(tmp); 00699 } else { 00700 g = Cudd_Not(tmp); 00701 } 00702 } else { 00703 /* f <= g unless D or !g <= !f unless D */ 00704 if (g < f) { 00705 tmp = g; 00706 g = Cudd_Not(f); 00707 f = Cudd_Not(tmp); 00708 } 00709 } 00710 } else { 00711 /* f <= g unless D or f <= D unless g */ 00712 if (D < g) { 00713 tmp = D; 00714 D = g; 00715 g = tmp; 00716 } 00717 } 00718 } 00719 00720 /* From now on, D is regular. */ 00721 00722 /* Check cache. */ 00723 tmp = cuddCacheLookup(dd,DD_BDD_LEQ_UNLESS_TAG,f,g,D); 00724 if (tmp != NULL) return(tmp == One); 00725 00726 /* Find splitting variable. */ 00727 F = Cudd_Regular(f); 00728 flevel = dd->perm[F->index]; 00729 G = Cudd_Regular(g); 00730 glevel = dd->perm[G->index]; 00731 top = ddMin(flevel,glevel); 00732 dlevel = dd->perm[D->index]; 00733 top = ddMin(top,dlevel); 00734 00735 /* Compute cofactors. */ 00736 if (top == flevel) { 00737 Ft = cuddT(F); 00738 Fe = cuddE(F); 00739 if (F != f) { 00740 Ft = Cudd_Not(Ft); 00741 Fe = Cudd_Not(Fe); 00742 } 00743 } else { 00744 Ft = Fe = f; 00745 } 00746 if (top == glevel) { 00747 Gt = cuddT(G); 00748 Ge = cuddE(G); 00749 if (G != g) { 00750 Gt = Cudd_Not(Gt); 00751 Ge = Cudd_Not(Ge); 00752 } 00753 } else { 00754 Gt = Ge = g; 00755 } 00756 if (top == dlevel) { 00757 Dt = cuddT(D); 00758 De = cuddE(D); 00759 } else { 00760 Dt = De = D; 00761 } 00762 00763 /* Solve recursively. */ 00764 res = Cudd_bddLeqUnless(dd,Ft,Gt,Dt); 00765 if (res != 0) { 00766 res = Cudd_bddLeqUnless(dd,Fe,Ge,De); 00767 } 00768 cuddCacheInsert(dd,DD_BDD_LEQ_UNLESS_TAG,f,g,D,Cudd_NotCond(One,!res)); 00769 00770 return(res); 00771 00772 } /* 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 860 of file cuddSat.c.
00864 { 00865 DdNode *res; 00866 00867 if (!Cudd_bddLeq(dd,cube,f)) return(NULL); 00868 00869 do { 00870 dd->reordered = 0; 00871 res = cuddBddMakePrime(dd,cube,f); 00872 } while (dd->reordered == 1); 00873 return(res); 00874 00875 } /* 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 413 of file cuddSat.c.
00417 { 00418 unsigned int topf, level; 00419 DdNode *F, *fv, *fvn, *res; 00420 DD_CTFP cacheOp; 00421 00422 statLine(dd); 00423 #ifdef DD_DEBUG 00424 assert(0 <= i && i < dd->size); 00425 #endif 00426 00427 F = Cudd_Regular(f); 00428 topf = cuddI(dd,F->index); 00429 00430 /* Check terminal case. If topf > i, f does not depend on var. 00431 ** Therefore, f is unate in i. 00432 */ 00433 level = (unsigned) dd->perm[i]; 00434 if (topf > level) { 00435 return(DD_ONE(dd)); 00436 } 00437 00438 /* From now on, f is not constant. */ 00439 00440 /* Check cache. */ 00441 cacheOp = (DD_CTFP) Cudd_Decreasing; 00442 res = cuddCacheLookup2(dd,cacheOp,f,dd->vars[i]); 00443 if (res != NULL) { 00444 return(res); 00445 } 00446 00447 /* Compute cofactors. */ 00448 fv = cuddT(F); fvn = cuddE(F); 00449 if (F != f) { 00450 fv = Cudd_Not(fv); 00451 fvn = Cudd_Not(fvn); 00452 } 00453 00454 if (topf == (unsigned) level) { 00455 /* Special case: if fv is regular, fv(1,...,1) = 1; 00456 ** If in addition fvn is complemented, fvn(1,...,1) = 0. 00457 ** But then f(1,1,...,1) > f(0,1,...,1). Hence f is not 00458 ** monotonic decreasing in i. 00459 */ 00460 if (!Cudd_IsComplement(fv) && Cudd_IsComplement(fvn)) { 00461 return(Cudd_Not(DD_ONE(dd))); 00462 } 00463 res = Cudd_bddLeq(dd,fv,fvn) ? DD_ONE(dd) : Cudd_Not(DD_ONE(dd)); 00464 } else { 00465 res = Cudd_Decreasing(dd,fv,i); 00466 if (res == DD_ONE(dd)) { 00467 res = Cudd_Decreasing(dd,fvn,i); 00468 } 00469 } 00470 00471 cuddCacheInsert2(dd,cacheOp,f,dd->vars[i],res); 00472 return(res); 00473 00474 } /* 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 792 of file cuddSat.c.
00798 { 00799 DdNode *fv, *fvn, *gv, *gvn, *r; 00800 unsigned int topf, topg; 00801 00802 statLine(dd); 00803 /* Check terminal cases. */ 00804 if (f == g) return(1); 00805 if (Cudd_IsConstant(f) && Cudd_IsConstant(g)) { 00806 if (ddEqualVal(cuddV(f),cuddV(g),tolerance)) { 00807 return(1); 00808 } else { 00809 if (pr>0) { 00810 (void) fprintf(dd->out,"Offending nodes:\n"); 00811 (void) fprintf(dd->out, 00812 "f: address = %p\t value = %40.30f\n", 00813 (void *) f, cuddV(f)); 00814 (void) fprintf(dd->out, 00815 "g: address = %p\t value = %40.30f\n", 00816 (void *) g, cuddV(g)); 00817 } 00818 return(0); 00819 } 00820 } 00821 00822 /* We only insert the result in the cache if the comparison is 00823 ** successful. Therefore, if we hit we return 1. */ 00824 r = cuddCacheLookup2(dd,(DD_CTFP)Cudd_EqualSupNorm,f,g); 00825 if (r != NULL) { 00826 return(1); 00827 } 00828 00829 /* Compute the cofactors and solve the recursive subproblems. */ 00830 topf = cuddI(dd,f->index); 00831 topg = cuddI(dd,g->index); 00832 00833 if (topf <= topg) {fv = cuddT(f); fvn = cuddE(f);} else {fv = fvn = f;} 00834 if (topg <= topf) {gv = cuddT(g); gvn = cuddE(g);} else {gv = gvn = g;} 00835 00836 if (!Cudd_EqualSupNorm(dd,fv,gv,tolerance,pr)) return(0); 00837 if (!Cudd_EqualSupNorm(dd,fvn,gvn,tolerance,pr)) return(0); 00838 00839 cuddCacheInsert2(dd,(DD_CTFP)Cudd_EqualSupNorm,f,g,DD_ONE(dd)); 00840 00841 return(1); 00842 00843 } /* 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 518 of file cuddSat.c.
00523 { 00524 DdNode *tmp, *One, *Gr, *Dr; 00525 DdNode *Fv, *Fvn, *Gv, *Gvn, *Dv, *Dvn; 00526 int res; 00527 unsigned int flevel, glevel, dlevel, top; 00528 00529 One = DD_ONE(dd); 00530 00531 statLine(dd); 00532 /* Check terminal cases. */ 00533 if (D == One || F == G) return(1); 00534 if (D == Cudd_Not(One) || D == DD_ZERO(dd) || F == Cudd_Not(G)) return(0); 00535 00536 /* From now on, D is non-constant. */ 00537 00538 /* Normalize call to increase cache efficiency. */ 00539 if (F > G) { 00540 tmp = F; 00541 F = G; 00542 G = tmp; 00543 } 00544 if (Cudd_IsComplement(F)) { 00545 F = Cudd_Not(F); 00546 G = Cudd_Not(G); 00547 } 00548 00549 /* From now on, F is regular. */ 00550 00551 /* Check cache. */ 00552 tmp = cuddCacheLookup(dd,DD_EQUIV_DC_TAG,F,G,D); 00553 if (tmp != NULL) return(tmp == One); 00554 00555 /* Find splitting variable. */ 00556 flevel = cuddI(dd,F->index); 00557 Gr = Cudd_Regular(G); 00558 glevel = cuddI(dd,Gr->index); 00559 top = ddMin(flevel,glevel); 00560 Dr = Cudd_Regular(D); 00561 dlevel = dd->perm[Dr->index]; 00562 top = ddMin(top,dlevel); 00563 00564 /* Compute cofactors. */ 00565 if (top == flevel) { 00566 Fv = cuddT(F); 00567 Fvn = cuddE(F); 00568 } else { 00569 Fv = Fvn = F; 00570 } 00571 if (top == glevel) { 00572 Gv = cuddT(Gr); 00573 Gvn = cuddE(Gr); 00574 if (G != Gr) { 00575 Gv = Cudd_Not(Gv); 00576 Gvn = Cudd_Not(Gvn); 00577 } 00578 } else { 00579 Gv = Gvn = G; 00580 } 00581 if (top == dlevel) { 00582 Dv = cuddT(Dr); 00583 Dvn = cuddE(Dr); 00584 if (D != Dr) { 00585 Dv = Cudd_Not(Dv); 00586 Dvn = Cudd_Not(Dvn); 00587 } 00588 } else { 00589 Dv = Dvn = D; 00590 } 00591 00592 /* Solve recursively. */ 00593 res = Cudd_EquivDC(dd,Fv,Gv,Dv); 00594 if (res != 0) { 00595 res = Cudd_EquivDC(dd,Fvn,Gvn,Dvn); 00596 } 00597 cuddCacheInsert(dd,DD_EQUIV_DC_TAG,F,G,D,(res) ? One : Cudd_Not(One)); 00598 00599 return(res); 00600 00601 } /* 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 153 of file cuddSat.c.
00157 { 00158 int comple; 00159 DdNode *ptr; 00160 00161 comple = Cudd_IsComplement(f); 00162 ptr = Cudd_Regular(f); 00163 00164 while (!cuddIsConstant(ptr)) { 00165 if (inputs[ptr->index] == 1) { 00166 ptr = cuddT(ptr); 00167 } else { 00168 comple ^= Cudd_IsComplement(cuddE(ptr)); 00169 ptr = Cudd_Regular(cuddE(ptr)); 00170 } 00171 } 00172 return(Cudd_NotCond(ptr,comple)); 00173 00174 } /* 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 increasing) 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 493 of file cuddSat.c.
00497 { 00498 return(Cudd_Decreasing(dd,Cudd_Not(f),i)); 00499 00500 } /* 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 281 of file cuddSat.c.
00285 { 00286 register DdNode *F; 00287 st_table *visited; 00288 DdNode *sol; 00289 cuddPathPair *rootPair; 00290 int complement, cost; 00291 00292 one = DD_ONE(manager); 00293 zero = DD_ZERO(manager); 00294 00295 if (f == Cudd_Not(one) || f == zero) { 00296 *length = DD_BIGGY; 00297 return(Cudd_Not(one)); 00298 } 00299 /* From this point on, a path exists. */ 00300 00301 do { 00302 manager->reordered = 0; 00303 00304 /* Initialize visited table. */ 00305 visited = st_init_table(st_ptrcmp, st_ptrhash); 00306 00307 /* Now get the length of the shortest path(s) from f to 1. */ 00308 (void) getLargest(f, visited); 00309 00310 complement = Cudd_IsComplement(f); 00311 00312 F = Cudd_Regular(f); 00313 00314 if (!st_lookup(visited, F, &rootPair)) return(NULL); 00315 00316 if (complement) { 00317 cost = rootPair->neg; 00318 } else { 00319 cost = rootPair->pos; 00320 } 00321 00322 /* Recover an actual shortest path. */ 00323 sol = getCube(manager,visited,f,cost); 00324 00325 st_foreach(visited, freePathPair, NULL); 00326 st_free_table(visited); 00327 00328 } while (manager->reordered == 1); 00329 00330 *length = cost; 00331 return(sol); 00332 00333 } /* 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 such a path is found; a large number if the function is identically 0, and CUDD_OUT_OF_MEM in case of failure.]
SideEffects [None]
SeeAlso [Cudd_ShortestPath]
Definition at line 353 of file cuddSat.c.
00357 { 00358 register DdNode *F; 00359 st_table *visited; 00360 cuddPathPair *my_pair; 00361 int complement, cost; 00362 00363 one = DD_ONE(manager); 00364 zero = DD_ZERO(manager); 00365 00366 if (f == Cudd_Not(one) || f == zero) { 00367 return(DD_BIGGY); 00368 } 00369 00370 /* From this point on, a path exists. */ 00371 /* Initialize visited table and support. */ 00372 visited = st_init_table(st_ptrcmp, st_ptrhash); 00373 00374 /* Now get the length of the shortest path(s) from f to 1. */ 00375 (void) getShortest(f, weight, NULL, visited); 00376 00377 complement = Cudd_IsComplement(f); 00378 00379 F = Cudd_Regular(f); 00380 00381 if (!st_lookup(visited, F, &my_pair)) return(CUDD_OUT_OF_MEM); 00382 00383 if (complement) { 00384 cost = my_pair->neg; 00385 } else { 00386 cost = my_pair->pos; 00387 } 00388 00389 st_foreach(visited, freePathPair, NULL); 00390 st_free_table(visited); 00391 00392 return(cost); 00393 00394 } /* 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 197 of file cuddSat.c.
00203 { 00204 DdNode *F; 00205 st_table *visited; 00206 DdNode *sol; 00207 cuddPathPair *rootPair; 00208 int complement, cost; 00209 int i; 00210 00211 one = DD_ONE(manager); 00212 zero = DD_ZERO(manager); 00213 00214 /* Initialize support. Support does not depend on variable order. 00215 ** Hence, it does not need to be reinitialized if reordering occurs. 00216 */ 00217 if (support) { 00218 for (i = 0; i < manager->size; i++) { 00219 support[i] = 0; 00220 } 00221 } 00222 00223 if (f == Cudd_Not(one) || f == zero) { 00224 *length = DD_BIGGY; 00225 return(Cudd_Not(one)); 00226 } 00227 /* From this point on, a path exists. */ 00228 00229 do { 00230 manager->reordered = 0; 00231 00232 /* Initialize visited table. */ 00233 visited = st_init_table(st_ptrcmp, st_ptrhash); 00234 00235 /* Now get the length of the shortest path(s) from f to 1. */ 00236 (void) getShortest(f, weight, support, visited); 00237 00238 complement = Cudd_IsComplement(f); 00239 00240 F = Cudd_Regular(f); 00241 00242 if (!st_lookup(visited, F, &rootPair)) return(NULL); 00243 00244 if (complement) { 00245 cost = rootPair->neg; 00246 } else { 00247 cost = rootPair->pos; 00248 } 00249 00250 /* Recover an actual shortest path. */ 00251 sol = getPath(manager,visited,f,weight,cost); 00252 00253 st_foreach(visited, freePathPair, NULL); 00254 st_free_table(visited); 00255 00256 } while (manager->reordered == 1); 00257 00258 *length = cost; 00259 return(sol); 00260 00261 } /* 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 896 of file cuddSat.c.
00900 { 00901 DdNode *scan; 00902 DdNode *t, *e; 00903 DdNode *res = cube; 00904 DdNode *zero = Cudd_Not(DD_ONE(dd)); 00905 00906 Cudd_Ref(res); 00907 scan = cube; 00908 while (!Cudd_IsConstant(scan)) { 00909 DdNode *reg = Cudd_Regular(scan); 00910 DdNode *var = dd->vars[reg->index]; 00911 DdNode *expanded = Cudd_bddExistAbstract(dd,res,var); 00912 if (expanded == NULL) { 00913 return(NULL); 00914 } 00915 Cudd_Ref(expanded); 00916 if (Cudd_bddLeq(dd,expanded,f)) { 00917 Cudd_RecursiveDeref(dd,res); 00918 res = expanded; 00919 } else { 00920 Cudd_RecursiveDeref(dd,expanded); 00921 } 00922 cuddGetBranches(scan,&t,&e); 00923 if (t == zero) { 00924 scan = e; 00925 } else if (e == zero) { 00926 scan = t; 00927 } else { 00928 Cudd_RecursiveDeref(dd,res); 00929 return(NULL); /* cube is not a cube */ 00930 } 00931 } 00932 00933 if (scan == DD_ONE(dd)) { 00934 Cudd_Deref(res); 00935 return(res); 00936 } else { 00937 Cudd_RecursiveDeref(dd,res); 00938 return(NULL); 00939 } 00940 00941 } /* end of cuddBddMakePrime */
static enum st_retval freePathPair | ( | char * | key, | |
char * | value, | |||
char * | arg | |||
) | [static] |
AutomaticStart
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 960 of file cuddSat.c.
00964 { 00965 cuddPathPair *pair; 00966 00967 pair = (cuddPathPair *) value; 00968 FREE(pair); 00969 return(ST_CONTINUE); 00970 00971 } /* 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 1270 of file cuddSat.c.
01275 { 01276 DdNode *sol, *tmp; 01277 DdNode *my_dd, *T, *E; 01278 cuddPathPair *T_pair, *E_pair; 01279 int Tcost, Ecost; 01280 int complement; 01281 01282 my_dd = Cudd_Regular(f); 01283 complement = Cudd_IsComplement(f); 01284 01285 sol = one; 01286 cuddRef(sol); 01287 01288 while (!cuddIsConstant(my_dd)) { 01289 Tcost = cost - 1; 01290 Ecost = cost - 1; 01291 01292 T = cuddT(my_dd); 01293 E = cuddE(my_dd); 01294 01295 if (complement) {T = Cudd_Not(T); E = Cudd_Not(E);} 01296 01297 if (!st_lookup(visited, Cudd_Regular(T), &T_pair)) return(NULL); 01298 if ((Cudd_IsComplement(T) && T_pair->neg == Tcost) || 01299 (!Cudd_IsComplement(T) && T_pair->pos == Tcost)) { 01300 tmp = cuddBddAndRecur(manager,manager->vars[my_dd->index],sol); 01301 if (tmp == NULL) { 01302 Cudd_RecursiveDeref(manager,sol); 01303 return(NULL); 01304 } 01305 cuddRef(tmp); 01306 Cudd_RecursiveDeref(manager,sol); 01307 sol = tmp; 01308 01309 complement = Cudd_IsComplement(T); 01310 my_dd = Cudd_Regular(T); 01311 cost = Tcost; 01312 continue; 01313 } 01314 if (!st_lookup(visited, Cudd_Regular(E), &E_pair)) return(NULL); 01315 if ((Cudd_IsComplement(E) && E_pair->neg == Ecost) || 01316 (!Cudd_IsComplement(E) && E_pair->pos == Ecost)) { 01317 tmp = cuddBddAndRecur(manager,Cudd_Not(manager->vars[my_dd->index]),sol); 01318 if (tmp == NULL) { 01319 Cudd_RecursiveDeref(manager,sol); 01320 return(NULL); 01321 } 01322 cuddRef(tmp); 01323 Cudd_RecursiveDeref(manager,sol); 01324 sol = tmp; 01325 complement = Cudd_IsComplement(E); 01326 my_dd = Cudd_Regular(E); 01327 cost = Ecost; 01328 continue; 01329 } 01330 (void) fprintf(manager->err,"We shouldn't be here!\n"); 01331 manager->errorCode = CUDD_INTERNAL_ERROR; 01332 return(NULL); 01333 } 01334 01335 cuddDeref(sol); 01336 return(sol); 01337 01338 } /* 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 1182 of file cuddSat.c.
01185 { 01186 cuddPathPair *my_pair, res_pair, pair_T, pair_E; 01187 DdNode *my_root, *T, *E; 01188 01189 my_root = Cudd_Regular(root); 01190 01191 if (st_lookup(visited, my_root, &my_pair)) { 01192 if (Cudd_IsComplement(root)) { 01193 res_pair.pos = my_pair->neg; 01194 res_pair.neg = my_pair->pos; 01195 } else { 01196 res_pair.pos = my_pair->pos; 01197 res_pair.neg = my_pair->neg; 01198 } 01199 return(res_pair); 01200 } 01201 01202 /* In the case of a BDD the following test is equivalent to 01203 ** testing whether the BDD is the constant 1. This formulation, 01204 ** however, works for ADDs as well, by assuming the usual 01205 ** dichotomy of 0 and != 0. 01206 */ 01207 if (cuddIsConstant(my_root)) { 01208 if (my_root != zero) { 01209 res_pair.pos = 0; 01210 res_pair.neg = DD_BIGGY; 01211 } else { 01212 res_pair.pos = DD_BIGGY; 01213 res_pair.neg = 0; 01214 } 01215 } else { 01216 T = cuddT(my_root); 01217 E = cuddE(my_root); 01218 01219 pair_T = getLargest(T, visited); 01220 pair_E = getLargest(E, visited); 01221 res_pair.pos = ddMin(pair_T.pos, pair_E.pos) + 1; 01222 res_pair.neg = ddMin(pair_T.neg, pair_E.neg) + 1; 01223 } 01224 01225 my_pair = ALLOC(cuddPathPair, 1); 01226 if (my_pair == NULL) { /* simply do not cache this result */ 01227 if (Cudd_IsComplement(root)) { 01228 int tmp = res_pair.pos; 01229 res_pair.pos = res_pair.neg; 01230 res_pair.neg = tmp; 01231 } 01232 return(res_pair); 01233 } 01234 my_pair->pos = res_pair.pos; 01235 my_pair->neg = res_pair.neg; 01236 01237 /* Caching may fail without affecting correctness. */ 01238 st_insert(visited, (char *)my_root, (char *)my_pair); 01239 if (Cudd_IsComplement(root)) { 01240 res_pair.pos = my_pair->neg; 01241 res_pair.neg = my_pair->pos; 01242 } else { 01243 res_pair.pos = my_pair->pos; 01244 res_pair.neg = my_pair->neg; 01245 } 01246 return(res_pair); 01247 01248 } /* 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 1089 of file cuddSat.c.
01095 { 01096 DdNode *sol, *tmp; 01097 DdNode *my_dd, *T, *E; 01098 cuddPathPair *T_pair, *E_pair; 01099 int Tcost, Ecost; 01100 int complement; 01101 01102 my_dd = Cudd_Regular(f); 01103 complement = Cudd_IsComplement(f); 01104 01105 sol = one; 01106 cuddRef(sol); 01107 01108 while (!cuddIsConstant(my_dd)) { 01109 Tcost = cost - WEIGHT(weight, my_dd->index); 01110 Ecost = cost; 01111 01112 T = cuddT(my_dd); 01113 E = cuddE(my_dd); 01114 01115 if (complement) {T = Cudd_Not(T); E = Cudd_Not(E);} 01116 01117 st_lookup(visited, Cudd_Regular(T), &T_pair); 01118 if ((Cudd_IsComplement(T) && T_pair->neg == Tcost) || 01119 (!Cudd_IsComplement(T) && T_pair->pos == Tcost)) { 01120 tmp = cuddBddAndRecur(manager,manager->vars[my_dd->index],sol); 01121 if (tmp == NULL) { 01122 Cudd_RecursiveDeref(manager,sol); 01123 return(NULL); 01124 } 01125 cuddRef(tmp); 01126 Cudd_RecursiveDeref(manager,sol); 01127 sol = tmp; 01128 01129 complement = Cudd_IsComplement(T); 01130 my_dd = Cudd_Regular(T); 01131 cost = Tcost; 01132 continue; 01133 } 01134 st_lookup(visited, Cudd_Regular(E), &E_pair); 01135 if ((Cudd_IsComplement(E) && E_pair->neg == Ecost) || 01136 (!Cudd_IsComplement(E) && E_pair->pos == Ecost)) { 01137 tmp = cuddBddAndRecur(manager,Cudd_Not(manager->vars[my_dd->index]),sol); 01138 if (tmp == NULL) { 01139 Cudd_RecursiveDeref(manager,sol); 01140 return(NULL); 01141 } 01142 cuddRef(tmp); 01143 Cudd_RecursiveDeref(manager,sol); 01144 sol = tmp; 01145 complement = Cudd_IsComplement(E); 01146 my_dd = Cudd_Regular(E); 01147 cost = Ecost; 01148 continue; 01149 } 01150 (void) fprintf(manager->err,"We shouldn't be here!!\n"); 01151 manager->errorCode = CUDD_INTERNAL_ERROR; 01152 return(NULL); 01153 } 01154 01155 cuddDeref(sol); 01156 return(sol); 01157 01158 } /* 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 993 of file cuddSat.c.
00998 { 00999 cuddPathPair *my_pair, res_pair, pair_T, pair_E; 01000 DdNode *my_root, *T, *E; 01001 int weight; 01002 01003 my_root = Cudd_Regular(root); 01004 01005 if (st_lookup(visited, my_root, &my_pair)) { 01006 if (Cudd_IsComplement(root)) { 01007 res_pair.pos = my_pair->neg; 01008 res_pair.neg = my_pair->pos; 01009 } else { 01010 res_pair.pos = my_pair->pos; 01011 res_pair.neg = my_pair->neg; 01012 } 01013 return(res_pair); 01014 } 01015 01016 /* In the case of a BDD the following test is equivalent to 01017 ** testing whether the BDD is the constant 1. This formulation, 01018 ** however, works for ADDs as well, by assuming the usual 01019 ** dichotomy of 0 and != 0. 01020 */ 01021 if (cuddIsConstant(my_root)) { 01022 if (my_root != zero) { 01023 res_pair.pos = 0; 01024 res_pair.neg = DD_BIGGY; 01025 } else { 01026 res_pair.pos = DD_BIGGY; 01027 res_pair.neg = 0; 01028 } 01029 } else { 01030 T = cuddT(my_root); 01031 E = cuddE(my_root); 01032 01033 pair_T = getShortest(T, cost, support, visited); 01034 pair_E = getShortest(E, cost, support, visited); 01035 weight = WEIGHT(cost, my_root->index); 01036 res_pair.pos = ddMin(pair_T.pos+weight, pair_E.pos); 01037 res_pair.neg = ddMin(pair_T.neg+weight, pair_E.neg); 01038 01039 /* Update support. */ 01040 if (support != NULL) { 01041 support[my_root->index] = 1; 01042 } 01043 } 01044 01045 my_pair = ALLOC(cuddPathPair, 1); 01046 if (my_pair == NULL) { 01047 if (Cudd_IsComplement(root)) { 01048 int tmp = res_pair.pos; 01049 res_pair.pos = res_pair.neg; 01050 res_pair.neg = tmp; 01051 } 01052 return(res_pair); 01053 } 01054 my_pair->pos = res_pair.pos; 01055 my_pair->neg = res_pair.neg; 01056 01057 st_insert(visited, (char *)my_root, (char *)my_pair); 01058 if (Cudd_IsComplement(root)) { 01059 res_pair.pos = my_pair->neg; 01060 res_pair.neg = my_pair->pos; 01061 } else { 01062 res_pair.pos = my_pair->pos; 01063 res_pair.neg = my_pair->neg; 01064 } 01065 return(res_pair); 01066 01067 } /* end of getShortest */
char rcsid [] DD_UNUSED = "$Id: cuddSat.c,v 1.36 2009/03/08 02:49:02 fabio Exp $" [static] |