src/cuBdd/cuddSat.c File Reference

#include "util.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 (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)
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)

Variables

static char rcsid[] DD_UNUSED = "$Id: cuddSat.c,v 1.36 2009/03/08 02:49:02 fabio 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 [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.]

Definition at line 79 of file cuddSat.c.

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

Definition at line 108 of file cuddSat.c.


Function Documentation

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 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 */

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 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 */

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 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 */

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 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 */

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 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 */

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 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 */

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 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 */

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 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 */

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 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 */

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 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 */

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 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 */


Variable Documentation

char rcsid [] DD_UNUSED = "$Id: cuddSat.c,v 1.36 2009/03/08 02:49:02 fabio Exp $" [static]

Definition at line 99 of file cuddSat.c.

DdNode* one [static]

Definition at line 102 of file cuddSat.c.

DdNode * zero [static]

Definition at line 102 of file cuddSat.c.


Generated on Tue Jan 12 13:57:21 2010 for glu-2.2 by  doxygen 1.6.1