#include <math.h>
#include "cudd.h"
#include "st.h"
Go to the source code of this file.
#define cuddAdjust | ( | x | ) | ((x) = ((x) >= DD_CRI_HI_MARK) ? DD_PLUS_INF_VAL : (((x) <= DD_CRI_LO_MARK) ? DD_MINUS_INF_VAL : (x))) |
Macro***********************************************************************
Synopsis [Enforces DD_MINUS_INF_VAL <= x <= DD_PLUS_INF_VAL.]
Description [Enforces DD_MINUS_INF_VAL <= x <= DD_PLUS_INF_VAL. Furthermore, if x <= DD_MINUS_INF_VAL/2, x is set to DD_MINUS_INF_VAL. Similarly, if DD_PLUS_INF_VAL/2 <= x, x is set to DD_PLUS_INF_VAL. Normally this macro is a NOOP. However, if HAVE_IEEE_754 is not defined, it makes sure that a value does not get larger than infinity in absolute value, and once it gets to infinity, stays there. If the value overflows before this macro is applied, no recovery is possible.]
SideEffects [none]
SeeAlso []
#define cuddDeallocMove | ( | unique, | |||
node | ) |
((DdNode *)(node))->ref = 0; \ ((DdNode *)(node))->next = (unique)->nextFree; \ (unique)->nextFree = (DdNode *)(node);
Macro***********************************************************************
Synopsis [Adds node to the head of the free list.]
Description [Adds node to the head of the free list. Does not deallocate memory chunks that become free. This function is also used by the dynamic reordering functions.]
SideEffects [None]
SeeAlso [cuddDeallocNode cuddDynamicAllocNode]
#define cuddDeallocNode | ( | unique, | |||
node | ) |
Macro***********************************************************************
Synopsis [Adds node to the head of the free list.]
Description [Adds node to the head of the free list. Does not deallocate memory chunks that become free. This function is also used by the dynamic reordering functions.]
SideEffects [None]
SeeAlso [cuddAllocNode cuddDynamicAllocNode cuddDeallocMove]
#define cuddDeref | ( | n | ) | cuddSatDec(Cudd_Regular(n)->ref) |
Macro***********************************************************************
Synopsis [Decreases the reference count of a node, if it is not saturated.]
Description [Decreases the reference count of node. It is primarily used in recursive procedures to decrease the ref count of a result node before returning it. This accomplishes the goal of removing the protection applied by a previous cuddRef. This being a macro, it is faster than Cudd_Deref, but it cannot be used in constructs like cuddDeref(a = b()).]
SideEffects [none]
SeeAlso [Cudd_Deref]
#define cuddE | ( | node | ) | ((node)->type.kids.E) |
Macro***********************************************************************
Synopsis [Returns the else child of an internal node.]
Description [Returns the else child of an internal node. If node
is a constant node, the result is unpredictable. The pointer passed to cuddE must be regular.]
SideEffects [none]
SeeAlso [Cudd_E]
#define cuddI | ( | dd, | |||
index | ) | (((index)==CUDD_CONST_INDEX)?(int)(index):(dd)->perm[(index)]) |
Macro***********************************************************************
Synopsis [Finds the current position of variable index in the order.]
Description [Finds the current position of variable index in the order. This macro duplicates the functionality of Cudd_ReadPerm, but it does not check for out-of-bounds indices and it is more efficient.]
SideEffects [none]
SeeAlso [Cudd_ReadPerm]
#define cuddIsConstant | ( | node | ) | ((node)->index == CUDD_CONST_INDEX) |
Macro***********************************************************************
Synopsis [Returns 1 if the node is a constant node.]
Description [Returns 1 if the node is a constant node (rather than an internal node). All constant nodes have the same index (CUDD_CONST_INDEX). The pointer passed to cuddIsConstant must be regular.]
SideEffects [none]
SeeAlso [Cudd_IsConstant]
#define cuddIZ | ( | dd, | |||
index | ) | (((index)==CUDD_CONST_INDEX)?(int)(index):(dd)->permZ[(index)]) |
Macro***********************************************************************
Synopsis [Finds the current position of ZDD variable index in the order.]
Description [Finds the current position of ZDD variable index in the order. This macro duplicates the functionality of Cudd_ReadPermZdd, but it does not check for out-of-bounds indices and it is more efficient.]
SideEffects [none]
SeeAlso [Cudd_ReadPermZdd]
#define cuddRef | ( | n | ) | cuddSatInc(Cudd_Regular(n)->ref) |
Macro***********************************************************************
Synopsis [Increases the reference count of a node, if it is not saturated.]
Description [Increases the reference count of a node, if it is not saturated. This being a macro, it is faster than Cudd_Ref, but it cannot be used in constructs like cuddRef(a = b()).]
SideEffects [none]
SeeAlso [Cudd_Ref]
#define cuddSatDec | ( | x | ) | ((x) -= (x) != (DdHalfWord)DD_MAXREF) |
#define cuddSatInc | ( | x | ) | ((x) += (x) != (DdHalfWord)DD_MAXREF) |
#define cuddT | ( | node | ) | ((node)->type.kids.T) |
Macro***********************************************************************
Synopsis [Returns the then child of an internal node.]
Description [Returns the then child of an internal node. If node
is a constant node, the result is unpredictable. The pointer passed to cuddT must be regular.]
SideEffects [none]
SeeAlso [Cudd_T]
#define cuddV | ( | node | ) | ((node)->type.value) |
Macro***********************************************************************
Synopsis [Returns the value of a constant node.]
Description [Returns the value of a constant node. If node
is an internal node, the result is unpredictable. The pointer passed to cuddV must be regular.]
SideEffects [none]
SeeAlso [Cudd_V]
#define DD_INLINE |
CHeaderFile*****************************************************************
FileName [cuddInt.h]
PackageName [cudd]
Synopsis [Internal data structures of the CUDD package.]
Description []
SeeAlso []
Author [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.]
Revision [
]
#define DD_LSDIGIT | ( | x | ) | ((x) & DD_APA_MASK) |
Macro***********************************************************************
Synopsis [Extract the least significant digit of a double digit.]
Description [Extract the least significant digit of a double digit. Used in the manipulation of arbitrary precision integers.]
SideEffects [None]
SeeAlso [DD_MSDIGIT]
#define DD_MAXREF ((DdHalfWord) ~0) |
#define DD_MINUS_INFINITY | ( | dd | ) | ((dd)->minusinfinity) |
#define DD_MSDIGIT | ( | x | ) | ((x) >> DD_APA_BITS) |
Macro***********************************************************************
Synopsis [Extract the most significant digit of a double digit.]
Description [Extract the most significant digit of a double digit. Used in the manipulation of arbitrary precision integers.]
SideEffects [None]
SeeAlso [DD_LSDIGIT]
#define DD_ONE | ( | dd | ) | ((dd)->one) |
#define DD_PLUS_INFINITY | ( | dd | ) | ((dd)->plusinfinity) |
#define DD_ZERO | ( | dd | ) | ((dd)->zero) |
Macro***********************************************************************
Synopsis [Returns the arithmetic 0 constant node.]
Description [Returns the arithmetic 0 constant node. This is different from the logical zero. The latter is obtained by Cudd_Not(DD_ONE(dd)).]
SideEffects [none]
SeeAlso [DD_ONE Cudd_Not DD_PLUS_INFINITY DD_MINUS_INFINITY]
#define ddAbs | ( | x | ) | (((x)<0) ? -(x) : (x)) |
#define ddCHash | ( | o, | |||
f, | |||||
g, | |||||
h, | |||||
s | ) |
#define ddCHash2 | ( | o, | |||
f, | |||||
g, | |||||
s | ) | (((((unsigned)(f) + (unsigned)(o)) * DD_P1 + (unsigned)(g)) * DD_P2) >> (s)) |
#define ddEqualVal | ( | x, | |||
y, | |||||
e | ) | (ddAbs((x)-(y))<(e)) |
#define ddHash | ( | f, | |||
g, | |||||
s | ) | ((((unsigned)(f) * DD_P1 + (unsigned)(g)) * DD_P2) >> (s)) |
#define ddMax | ( | x, | |||
y | ) | (((y) > (x)) ? (y) : (x)) |
#define ddMin | ( | x, | |||
y | ) | (((y) < (x)) ? (y) : (x)) |
#define statLine | ( | dd | ) |
Macro***********************************************************************
Synopsis [Outputs a line of stats.]
Description [Outputs a line of stats if DD_COUNT and DD_STATS are defined. Increments the number of recursive calls if DD_COUNT is defined.]
SideEffects [None]
SeeAlso []
DdNode* cuddAddApplyRecur | ( | DdManager * | dd, | |
DdNode * | *)(DdManager *, DdNode **, DdNode **, | |||
DdNode * | f, | |||
DdNode * | g | |||
) |
Function********************************************************************
Synopsis [Performs the recursive step for Cudd_addBddPattern.]
Description [Performs the recursive step for Cudd_addBddPattern. Returns a pointer to the resulting BDD if successful; NULL otherwise.]
SideEffects [None]
SeeAlso []
Definition at line 489 of file cuddBridge.c.
00492 { 00493 DdNode *res, *T, *E; 00494 DdNode *fv, *fvn; 00495 int v; 00496 00497 statLine(dd); 00498 /* Check terminal case. */ 00499 if (cuddIsConstant(f)) { 00500 return(Cudd_NotCond(DD_ONE(dd),f == DD_ZERO(dd))); 00501 } 00502 00503 /* Check cache. */ 00504 res = cuddCacheLookup1(dd,Cudd_addBddPattern,f); 00505 if (res != NULL) return(res); 00506 00507 /* Recursive step. */ 00508 v = f->index; 00509 fv = cuddT(f); fvn = cuddE(f); 00510 00511 T = cuddAddBddDoPattern(dd,fv); 00512 if (T == NULL) return(NULL); 00513 cuddRef(T); 00514 00515 E = cuddAddBddDoPattern(dd,fvn); 00516 if (E == NULL) { 00517 Cudd_RecursiveDeref(dd, T); 00518 return(NULL); 00519 } 00520 cuddRef(E); 00521 if (Cudd_IsComplement(T)) { 00522 res = (T == E) ? Cudd_Not(T) : cuddUniqueInter(dd,v,Cudd_Not(T),Cudd_Not(E)); 00523 if (res == NULL) { 00524 Cudd_RecursiveDeref(dd, T); 00525 Cudd_RecursiveDeref(dd, E); 00526 return(NULL); 00527 } 00528 res = Cudd_Not(res); 00529 } else { 00530 res = (T == E) ? T : cuddUniqueInter(dd,v,T,E); 00531 if (res == NULL) { 00532 Cudd_RecursiveDeref(dd, T); 00533 Cudd_RecursiveDeref(dd, E); 00534 return(NULL); 00535 } 00536 } 00537 cuddDeref(T); 00538 cuddDeref(E); 00539 00540 /* Store result. */ 00541 cuddCacheInsert1(dd,Cudd_addBddPattern,f,res); 00542 00543 return(res); 00544 00545 } /* end of cuddAddBddDoPattern */
Function********************************************************************
Synopsis [Performs the recursive step of Cudd_addCmpl.]
Description [Performs the recursive step of Cudd_addCmpl. Returns a pointer to the resulting ADD if successful; NULL otherwise.]
SideEffects [None]
SeeAlso [Cudd_addCmpl]
Definition at line 558 of file cuddAddIte.c.
00561 { 00562 DdNode *one,*zero; 00563 DdNode *r,*Fv,*Fnv,*t,*e; 00564 00565 statLine(dd); 00566 one = DD_ONE(dd); 00567 zero = DD_ZERO(dd); 00568 00569 if (cuddIsConstant(f)) { 00570 if (f == zero) { 00571 return(one); 00572 } else { 00573 return(zero); 00574 } 00575 } 00576 r = cuddCacheLookup1(dd,Cudd_addCmpl,f); 00577 if (r != NULL) { 00578 return(r); 00579 } 00580 Fv = cuddT(f); 00581 Fnv = cuddE(f); 00582 t = cuddAddCmplRecur(dd,Fv); 00583 if (t == NULL) return(NULL); 00584 cuddRef(t); 00585 e = cuddAddCmplRecur(dd,Fnv); 00586 if (e == NULL) { 00587 Cudd_RecursiveDeref(dd,t); 00588 return(NULL); 00589 } 00590 cuddRef(e); 00591 r = (t == e) ? t : cuddUniqueInter(dd,(int)f->index,t,e); 00592 if (r == NULL) { 00593 Cudd_RecursiveDeref(dd, t); 00594 Cudd_RecursiveDeref(dd, e); 00595 return(NULL); 00596 } 00597 cuddDeref(t); 00598 cuddDeref(e); 00599 cuddCacheInsert1(dd,Cudd_addCmpl,f,r); 00600 return(r); 00601 00602 } /* end of cuddAddCmplRecur */
Function********************************************************************
Synopsis [Performs the recursive step of Cudd_addCompose.]
Description [Performs the recursive step of Cudd_addCompose. Returns the composed BDD if successful; NULL otherwise.]
SideEffects [None]
SeeAlso [Cudd_addCompose]
Definition at line 948 of file cuddCompose.c.
00953 { 00954 DdNode *f1, *f0, *g1, *g0, *r, *t, *e; 00955 unsigned int v, topf, topg, topindex; 00956 00957 statLine(dd); 00958 v = dd->perm[proj->index]; 00959 topf = cuddI(dd,f->index); 00960 00961 /* Terminal case. Subsumes the test for constant f. */ 00962 if (topf > v) return(f); 00963 00964 /* Check cache. */ 00965 r = cuddCacheLookup(dd,DD_ADD_COMPOSE_RECUR_TAG,f,g,proj); 00966 if (r != NULL) { 00967 return(r); 00968 } 00969 00970 if (topf == v) { 00971 /* Compose. */ 00972 f1 = cuddT(f); 00973 f0 = cuddE(f); 00974 r = cuddAddIteRecur(dd, g, f1, f0); 00975 if (r == NULL) return(NULL); 00976 } else { 00977 /* Compute cofactors of f and g. Remember the index of the top 00978 ** variable. 00979 */ 00980 topg = cuddI(dd,g->index); 00981 if (topf > topg) { 00982 topindex = g->index; 00983 f1 = f0 = f; 00984 } else { 00985 topindex = f->index; 00986 f1 = cuddT(f); 00987 f0 = cuddE(f); 00988 } 00989 if (topg > topf) { 00990 g1 = g0 = g; 00991 } else { 00992 g1 = cuddT(g); 00993 g0 = cuddE(g); 00994 } 00995 /* Recursive step. */ 00996 t = cuddAddComposeRecur(dd, f1, g1, proj); 00997 if (t == NULL) return(NULL); 00998 cuddRef(t); 00999 e = cuddAddComposeRecur(dd, f0, g0, proj); 01000 if (e == NULL) { 01001 Cudd_RecursiveDeref(dd, t); 01002 return(NULL); 01003 } 01004 cuddRef(e); 01005 01006 if (t == e) { 01007 r = t; 01008 } else { 01009 r = cuddUniqueInter(dd, (int) topindex, t, e); 01010 if (r == NULL) { 01011 Cudd_RecursiveDeref(dd, t); 01012 Cudd_RecursiveDeref(dd, e); 01013 return(NULL); 01014 } 01015 } 01016 cuddDeref(t); 01017 cuddDeref(e); 01018 } 01019 01020 cuddCacheInsert(dd,DD_ADD_COMPOSE_RECUR_TAG,f,g,proj,r); 01021 01022 return(r); 01023 01024 } /* end of cuddAddComposeRecur */
Function********************************************************************
Synopsis [Performs the recursive step of Cudd_addConstrain.]
Description [Performs the recursive step of Cudd_addConstrain. Returns a pointer to the result if successful; NULL otherwise.]
SideEffects [None]
SeeAlso [Cudd_addConstrain]
Definition at line 1199 of file cuddGenCof.c.
01203 { 01204 DdNode *Fv, *Fnv, *Cv, *Cnv, *t, *e, *r; 01205 DdNode *one, *zero; 01206 unsigned int topf, topc; 01207 int index; 01208 01209 statLine(dd); 01210 one = DD_ONE(dd); 01211 zero = DD_ZERO(dd); 01212 01213 /* Trivial cases. */ 01214 if (c == one) return(f); 01215 if (c == zero) return(zero); 01216 if (Cudd_IsConstant(f)) return(f); 01217 if (f == c) return(one); 01218 01219 /* Now f and c are non-constant. */ 01220 01221 /* Check the cache. */ 01222 r = cuddCacheLookup2(dd, Cudd_addConstrain, f, c); 01223 if (r != NULL) { 01224 return(r); 01225 } 01226 01227 /* Recursive step. */ 01228 topf = dd->perm[f->index]; 01229 topc = dd->perm[c->index]; 01230 if (topf <= topc) { 01231 index = f->index; 01232 Fv = cuddT(f); Fnv = cuddE(f); 01233 } else { 01234 index = c->index; 01235 Fv = Fnv = f; 01236 } 01237 if (topc <= topf) { 01238 Cv = cuddT(c); Cnv = cuddE(c); 01239 } else { 01240 Cv = Cnv = c; 01241 } 01242 01243 if (!Cudd_IsConstant(Cv)) { 01244 t = cuddAddConstrainRecur(dd, Fv, Cv); 01245 if (t == NULL) 01246 return(NULL); 01247 } else if (Cv == one) { 01248 t = Fv; 01249 } else { /* Cv == zero: return Fnv @ Cnv */ 01250 if (Cnv == one) { 01251 r = Fnv; 01252 } else { 01253 r = cuddAddConstrainRecur(dd, Fnv, Cnv); 01254 if (r == NULL) 01255 return(NULL); 01256 } 01257 return(r); 01258 } 01259 cuddRef(t); 01260 01261 if (!Cudd_IsConstant(Cnv)) { 01262 e = cuddAddConstrainRecur(dd, Fnv, Cnv); 01263 if (e == NULL) { 01264 Cudd_RecursiveDeref(dd, t); 01265 return(NULL); 01266 } 01267 } else if (Cnv == one) { 01268 e = Fnv; 01269 } else { /* Cnv == zero: return Fv @ Cv previously computed */ 01270 cuddDeref(t); 01271 return(t); 01272 } 01273 cuddRef(e); 01274 01275 r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); 01276 if (r == NULL) { 01277 Cudd_RecursiveDeref(dd, e); 01278 Cudd_RecursiveDeref(dd, t); 01279 return(NULL); 01280 } 01281 cuddDeref(t); 01282 cuddDeref(e); 01283 01284 cuddCacheInsert2(dd, Cudd_addConstrain, f, c, r); 01285 return(r); 01286 01287 } /* end of cuddAddConstrainRecur */
AutomaticStart
Function********************************************************************
Synopsis [Performs the recursive step of Cudd_addExistAbstract.]
Description [Performs the recursive step of Cudd_addExistAbstract. Returns the ADD obtained by abstracting the variables of cube from f, if successful; NULL otherwise.]
SideEffects [None]
SeeAlso []
Definition at line 252 of file cuddAddAbs.c.
00256 { 00257 DdNode *T, *E, *res, *res1, *res2, *zero; 00258 00259 statLine(manager); 00260 zero = DD_ZERO(manager); 00261 00262 /* Cube is guaranteed to be a cube at this point. */ 00263 if (f == zero || cuddIsConstant(cube)) { 00264 return(f); 00265 } 00266 00267 /* Abstract a variable that does not appear in f => multiply by 2. */ 00268 if (cuddI(manager,f->index) > cuddI(manager,cube->index)) { 00269 res1 = cuddAddExistAbstractRecur(manager, f, cuddT(cube)); 00270 if (res1 == NULL) return(NULL); 00271 cuddRef(res1); 00272 /* Use the "internal" procedure to be alerted in case of 00273 ** dynamic reordering. If dynamic reordering occurs, we 00274 ** have to abort the entire abstraction. 00275 */ 00276 res = cuddAddApplyRecur(manager,Cudd_addTimes,res1,two); 00277 if (res == NULL) { 00278 Cudd_RecursiveDeref(manager,res1); 00279 return(NULL); 00280 } 00281 cuddRef(res); 00282 Cudd_RecursiveDeref(manager,res1); 00283 cuddDeref(res); 00284 return(res); 00285 } 00286 00287 if ((res = cuddCacheLookup2(manager, Cudd_addExistAbstract, f, cube)) != NULL) { 00288 return(res); 00289 } 00290 00291 T = cuddT(f); 00292 E = cuddE(f); 00293 00294 /* If the two indices are the same, so are their levels. */ 00295 if (f->index == cube->index) { 00296 res1 = cuddAddExistAbstractRecur(manager, T, cuddT(cube)); 00297 if (res1 == NULL) return(NULL); 00298 cuddRef(res1); 00299 res2 = cuddAddExistAbstractRecur(manager, E, cuddT(cube)); 00300 if (res2 == NULL) { 00301 Cudd_RecursiveDeref(manager,res1); 00302 return(NULL); 00303 } 00304 cuddRef(res2); 00305 res = cuddAddApplyRecur(manager, Cudd_addPlus, res1, res2); 00306 if (res == NULL) { 00307 Cudd_RecursiveDeref(manager,res1); 00308 Cudd_RecursiveDeref(manager,res2); 00309 return(NULL); 00310 } 00311 cuddRef(res); 00312 Cudd_RecursiveDeref(manager,res1); 00313 Cudd_RecursiveDeref(manager,res2); 00314 cuddCacheInsert2(manager, Cudd_addExistAbstract, f, cube, res); 00315 cuddDeref(res); 00316 return(res); 00317 } else { /* if (cuddI(manager,f->index) < cuddI(manager,cube->index)) */ 00318 res1 = cuddAddExistAbstractRecur(manager, T, cube); 00319 if (res1 == NULL) return(NULL); 00320 cuddRef(res1); 00321 res2 = cuddAddExistAbstractRecur(manager, E, cube); 00322 if (res2 == NULL) { 00323 Cudd_RecursiveDeref(manager,res1); 00324 return(NULL); 00325 } 00326 cuddRef(res2); 00327 res = (res1 == res2) ? res1 : 00328 cuddUniqueInter(manager, (int) f->index, res1, res2); 00329 if (res == NULL) { 00330 Cudd_RecursiveDeref(manager,res1); 00331 Cudd_RecursiveDeref(manager,res2); 00332 return(NULL); 00333 } 00334 cuddDeref(res1); 00335 cuddDeref(res2); 00336 cuddCacheInsert2(manager, Cudd_addExistAbstract, f, cube, res); 00337 return(res); 00338 } 00339 00340 } /* end of cuddAddExistAbstractRecur */
Function********************************************************************
Synopsis [Implements the recursive step of Cudd_addIte(f,g,h).]
Description [Implements the recursive step of Cudd_addIte(f,g,h). Returns a pointer to the resulting ADD if successful; NULL otherwise.]
SideEffects [None]
SeeAlso [Cudd_addIte]
Definition at line 441 of file cuddAddIte.c.
00446 { 00447 DdNode *one,*zero; 00448 DdNode *r,*Fv,*Fnv,*Gv,*Gnv,*Hv,*Hnv,*t,*e; 00449 unsigned int topf,topg,toph,v; 00450 int index; 00451 00452 statLine(dd); 00453 /* Trivial cases. */ 00454 00455 /* One variable cases. */ 00456 if (f == (one = DD_ONE(dd))) { /* ITE(1,G,H) = G */ 00457 return(g); 00458 } 00459 if (f == (zero = DD_ZERO(dd))) { /* ITE(0,G,H) = H */ 00460 return(h); 00461 } 00462 00463 /* From now on, f is known to not be a constant. */ 00464 addVarToConst(f,&g,&h,one,zero); 00465 00466 /* Check remaining one variable cases. */ 00467 if (g == h) { /* ITE(F,G,G) = G */ 00468 return(g); 00469 } 00470 00471 if (g == one) { /* ITE(F,1,0) = F */ 00472 if (h == zero) return(f); 00473 } 00474 00475 topf = cuddI(dd,f->index); 00476 topg = cuddI(dd,g->index); 00477 toph = cuddI(dd,h->index); 00478 v = ddMin(topg,toph); 00479 00480 /* A shortcut: ITE(F,G,H) = (x,G,H) if F=(x,1,0), x < top(G,H). */ 00481 if (topf < v && cuddT(f) == one && cuddE(f) == zero) { 00482 r = cuddUniqueInter(dd,(int)f->index,g,h); 00483 return(r); 00484 } 00485 if (topf < v && cuddT(f) == zero && cuddE(f) == one) { 00486 r = cuddUniqueInter(dd,(int)f->index,h,g); 00487 return(r); 00488 } 00489 00490 /* Check cache. */ 00491 r = cuddCacheLookup(dd,DD_ADD_ITE_TAG,f,g,h); 00492 if (r != NULL) { 00493 return(r); 00494 } 00495 00496 /* Compute cofactors. */ 00497 if (topf <= v) { 00498 v = ddMin(topf,v); /* v = top_var(F,G,H) */ 00499 index = f->index; 00500 Fv = cuddT(f); Fnv = cuddE(f); 00501 } else { 00502 Fv = Fnv = f; 00503 } 00504 if (topg == v) { 00505 index = g->index; 00506 Gv = cuddT(g); Gnv = cuddE(g); 00507 } else { 00508 Gv = Gnv = g; 00509 } 00510 if (toph == v) { 00511 index = h->index; 00512 Hv = cuddT(h); Hnv = cuddE(h); 00513 } else { 00514 Hv = Hnv = h; 00515 } 00516 00517 /* Recursive step. */ 00518 t = cuddAddIteRecur(dd,Fv,Gv,Hv); 00519 if (t == NULL) return(NULL); 00520 cuddRef(t); 00521 00522 e = cuddAddIteRecur(dd,Fnv,Gnv,Hnv); 00523 if (e == NULL) { 00524 Cudd_RecursiveDeref(dd,t); 00525 return(NULL); 00526 } 00527 cuddRef(e); 00528 00529 r = (t == e) ? t : cuddUniqueInter(dd,index,t,e); 00530 if (r == NULL) { 00531 Cudd_RecursiveDeref(dd,t); 00532 Cudd_RecursiveDeref(dd,e); 00533 return(NULL); 00534 } 00535 cuddDeref(t); 00536 cuddDeref(e); 00537 00538 cuddCacheInsert(dd,DD_ADD_ITE_TAG,f,g,h,r); 00539 00540 return(r); 00541 00542 } /* end of cuddAddIteRecur */
DdNode* cuddAddMonadicApplyRecur | ( | DdManager * | dd, | |
DdNode *(*)(DdManager *, DdNode *) | op, | |||
DdNode * | f | |||
) |
Function********************************************************************
Synopsis [Implements the recursive step of Cudd_addNegate.]
Description [Implements the recursive step of Cudd_addNegate. Returns a pointer to the result.]
SideEffects [None]
Definition at line 176 of file cuddAddNeg.c.
00179 { 00180 DdNode *res, 00181 *fv, *fvn, 00182 *T, *E; 00183 00184 statLine(dd); 00185 /* Check terminal cases. */ 00186 if (cuddIsConstant(f)) { 00187 res = cuddUniqueConst(dd,-cuddV(f)); 00188 return(res); 00189 } 00190 00191 /* Check cache */ 00192 res = cuddCacheLookup1(dd,Cudd_addNegate,f); 00193 if (res != NULL) return(res); 00194 00195 /* Recursive Step */ 00196 fv = cuddT(f); 00197 fvn = cuddE(f); 00198 T = cuddAddNegateRecur(dd,fv); 00199 if (T == NULL) return(NULL); 00200 cuddRef(T); 00201 00202 E = cuddAddNegateRecur(dd,fvn); 00203 if (E == NULL) { 00204 Cudd_RecursiveDeref(dd,T); 00205 return(NULL); 00206 } 00207 cuddRef(E); 00208 res = (T == E) ? T : cuddUniqueInter(dd,(int)f->index,T,E); 00209 if (res == NULL) { 00210 Cudd_RecursiveDeref(dd, T); 00211 Cudd_RecursiveDeref(dd, E); 00212 return(NULL); 00213 } 00214 cuddDeref(T); 00215 cuddDeref(E); 00216 00217 /* Store result. */ 00218 cuddCacheInsert1(dd,Cudd_addNegate,f,res); 00219 00220 return(res); 00221 00222 } /* end of cuddAddNegateRecur */
Function********************************************************************
Synopsis [Performs the recursive step of Cudd_addOrAbstract.]
Description [Performs the recursive step of Cudd_addOrAbstract. Returns the ADD obtained by abstracting the variables of cube from f, if successful; NULL otherwise.]
SideEffects [None]
SeeAlso []
Definition at line 465 of file cuddAddAbs.c.
00469 { 00470 DdNode *T, *E, *res, *res1, *res2, *one; 00471 00472 statLine(manager); 00473 one = DD_ONE(manager); 00474 00475 /* Cube is guaranteed to be a cube at this point. */ 00476 if (cuddIsConstant(f) || cube == one) { 00477 return(f); 00478 } 00479 00480 /* Abstract a variable that does not appear in f. */ 00481 if (cuddI(manager,f->index) > cuddI(manager,cube->index)) { 00482 res = cuddAddOrAbstractRecur(manager, f, cuddT(cube)); 00483 return(res); 00484 } 00485 00486 if ((res = cuddCacheLookup2(manager, Cudd_addOrAbstract, f, cube)) != NULL) { 00487 return(res); 00488 } 00489 00490 T = cuddT(f); 00491 E = cuddE(f); 00492 00493 /* If the two indices are the same, so are their levels. */ 00494 if (f->index == cube->index) { 00495 res1 = cuddAddOrAbstractRecur(manager, T, cuddT(cube)); 00496 if (res1 == NULL) return(NULL); 00497 cuddRef(res1); 00498 if (res1 != one) { 00499 res2 = cuddAddOrAbstractRecur(manager, E, cuddT(cube)); 00500 if (res2 == NULL) { 00501 Cudd_RecursiveDeref(manager,res1); 00502 return(NULL); 00503 } 00504 cuddRef(res2); 00505 res = cuddAddApplyRecur(manager, Cudd_addOr, res1, res2); 00506 if (res == NULL) { 00507 Cudd_RecursiveDeref(manager,res1); 00508 Cudd_RecursiveDeref(manager,res2); 00509 return(NULL); 00510 } 00511 cuddRef(res); 00512 Cudd_RecursiveDeref(manager,res1); 00513 Cudd_RecursiveDeref(manager,res2); 00514 } else { 00515 res = res1; 00516 } 00517 cuddCacheInsert2(manager, Cudd_addOrAbstract, f, cube, res); 00518 cuddDeref(res); 00519 return(res); 00520 } else { /* if (cuddI(manager,f->index) < cuddI(manager,cube->index)) */ 00521 res1 = cuddAddOrAbstractRecur(manager, T, cube); 00522 if (res1 == NULL) return(NULL); 00523 cuddRef(res1); 00524 res2 = cuddAddOrAbstractRecur(manager, E, cube); 00525 if (res2 == NULL) { 00526 Cudd_RecursiveDeref(manager,res1); 00527 return(NULL); 00528 } 00529 cuddRef(res2); 00530 res = (res1 == res2) ? res1 : 00531 cuddUniqueInter(manager, (int) f->index, res1, res2); 00532 if (res == NULL) { 00533 Cudd_RecursiveDeref(manager,res1); 00534 Cudd_RecursiveDeref(manager,res2); 00535 return(NULL); 00536 } 00537 cuddDeref(res1); 00538 cuddDeref(res2); 00539 cuddCacheInsert2(manager, Cudd_addOrAbstract, f, cube, res); 00540 return(res); 00541 } 00542 00543 } /* end of cuddAddOrAbstractRecur */
Function********************************************************************
Synopsis [Performs the recursive step of Cudd_addRestrict.]
Description [Performs the recursive step of Cudd_addRestrict. Returns the restricted ADD if successful; otherwise NULL.]
SideEffects [None]
SeeAlso [Cudd_addRestrict]
Definition at line 1303 of file cuddGenCof.c.
01307 { 01308 DdNode *Fv, *Fnv, *Cv, *Cnv, *t, *e, *r, *one, *zero; 01309 unsigned int topf, topc; 01310 int index; 01311 01312 statLine(dd); 01313 one = DD_ONE(dd); 01314 zero = DD_ZERO(dd); 01315 01316 /* Trivial cases */ 01317 if (c == one) return(f); 01318 if (c == zero) return(zero); 01319 if (Cudd_IsConstant(f)) return(f); 01320 if (f == c) return(one); 01321 01322 /* Now f and c are non-constant. */ 01323 01324 /* Check the cache. */ 01325 r = cuddCacheLookup2(dd, Cudd_addRestrict, f, c); 01326 if (r != NULL) { 01327 return(r); 01328 } 01329 01330 topf = dd->perm[f->index]; 01331 topc = dd->perm[c->index]; 01332 01333 if (topc < topf) { /* abstract top variable from c */ 01334 DdNode *d, *s1, *s2; 01335 01336 /* Find cofactors of c. */ 01337 s1 = cuddT(c); 01338 s2 = cuddE(c); 01339 /* Take the OR by applying DeMorgan. */ 01340 d = cuddAddApplyRecur(dd, Cudd_addOr, s1, s2); 01341 if (d == NULL) return(NULL); 01342 cuddRef(d); 01343 r = cuddAddRestrictRecur(dd, f, d); 01344 if (r == NULL) { 01345 Cudd_RecursiveDeref(dd, d); 01346 return(NULL); 01347 } 01348 cuddRef(r); 01349 Cudd_RecursiveDeref(dd, d); 01350 cuddCacheInsert2(dd, Cudd_addRestrict, f, c, r); 01351 cuddDeref(r); 01352 return(r); 01353 } 01354 01355 /* Recursive step. Here topf <= topc. */ 01356 index = f->index; 01357 Fv = cuddT(f); Fnv = cuddE(f); 01358 if (topc == topf) { 01359 Cv = cuddT(c); Cnv = cuddE(c); 01360 } else { 01361 Cv = Cnv = c; 01362 } 01363 01364 if (!Cudd_IsConstant(Cv)) { 01365 t = cuddAddRestrictRecur(dd, Fv, Cv); 01366 if (t == NULL) return(NULL); 01367 } else if (Cv == one) { 01368 t = Fv; 01369 } else { /* Cv == zero: return(Fnv @ Cnv) */ 01370 if (Cnv == one) { 01371 r = Fnv; 01372 } else { 01373 r = cuddAddRestrictRecur(dd, Fnv, Cnv); 01374 if (r == NULL) return(NULL); 01375 } 01376 return(r); 01377 } 01378 cuddRef(t); 01379 01380 if (!Cudd_IsConstant(Cnv)) { 01381 e = cuddAddRestrictRecur(dd, Fnv, Cnv); 01382 if (e == NULL) { 01383 Cudd_RecursiveDeref(dd, t); 01384 return(NULL); 01385 } 01386 } else if (Cnv == one) { 01387 e = Fnv; 01388 } else { /* Cnv == zero: return (Fv @ Cv) previously computed */ 01389 cuddDeref(t); 01390 return(t); 01391 } 01392 cuddRef(e); 01393 01394 r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); 01395 if (r == NULL) { 01396 Cudd_RecursiveDeref(dd, e); 01397 Cudd_RecursiveDeref(dd, t); 01398 return(NULL); 01399 } 01400 cuddDeref(t); 01401 cuddDeref(e); 01402 01403 cuddCacheInsert2(dd, Cudd_addRestrict, f, c, r); 01404 return(r); 01405 01406 } /* end of cuddAddRestrictRecur */
Function********************************************************************
Synopsis [Implements the recursive step of Cudd_addRoundOff.]
Description [Implements the recursive step of Cudd_addRoundOff. Returns a pointer to the result.]
SideEffects [None]
Definition at line 236 of file cuddAddNeg.c.
00240 { 00241 00242 DdNode *res, *fv, *fvn, *T, *E; 00243 double n; 00244 DD_CTFP1 cacheOp; 00245 00246 statLine(dd); 00247 if (cuddIsConstant(f)) { 00248 n = ceil(cuddV(f)*trunc)/trunc; 00249 res = cuddUniqueConst(dd,n); 00250 return(res); 00251 } 00252 cacheOp = (DD_CTFP1) Cudd_addRoundOff; 00253 res = cuddCacheLookup1(dd,cacheOp,f); 00254 if (res != NULL) { 00255 return(res); 00256 } 00257 /* Recursive Step */ 00258 fv = cuddT(f); 00259 fvn = cuddE(f); 00260 T = cuddAddRoundOffRecur(dd,fv,trunc); 00261 if (T == NULL) { 00262 return(NULL); 00263 } 00264 cuddRef(T); 00265 E = cuddAddRoundOffRecur(dd,fvn,trunc); 00266 if (E == NULL) { 00267 Cudd_RecursiveDeref(dd,T); 00268 return(NULL); 00269 } 00270 cuddRef(E); 00271 res = (T == E) ? T : cuddUniqueInter(dd,(int)f->index,T,E); 00272 if (res == NULL) { 00273 Cudd_RecursiveDeref(dd,T); 00274 Cudd_RecursiveDeref(dd,E); 00275 return(NULL); 00276 } 00277 cuddDeref(T); 00278 cuddDeref(E); 00279 00280 /* Store result. */ 00281 cuddCacheInsert1(dd,cacheOp,f,res); 00282 return(res); 00283 00284 } /* end of cuddAddRoundOffRecur */
Function********************************************************************
Synopsis [Performs the recursive step of addScalarInverse.]
Description [Returns a pointer to the resulting ADD in case of success. Returns NULL if any discriminants smaller than epsilon is encountered.]
SideEffects [None]
Definition at line 152 of file cuddAddInv.c.
00156 { 00157 DdNode *t, *e, *res; 00158 CUDD_VALUE_TYPE value; 00159 00160 statLine(dd); 00161 if (cuddIsConstant(f)) { 00162 if (ddAbs(cuddV(f)) < cuddV(epsilon)) return(NULL); 00163 value = 1.0 / cuddV(f); 00164 res = cuddUniqueConst(dd,value); 00165 return(res); 00166 } 00167 00168 res = cuddCacheLookup2(dd,Cudd_addScalarInverse,f,epsilon); 00169 if (res != NULL) return(res); 00170 00171 t = cuddAddScalarInverseRecur(dd,cuddT(f),epsilon); 00172 if (t == NULL) return(NULL); 00173 cuddRef(t); 00174 00175 e = cuddAddScalarInverseRecur(dd,cuddE(f),epsilon); 00176 if (e == NULL) { 00177 Cudd_RecursiveDeref(dd, t); 00178 return(NULL); 00179 } 00180 cuddRef(e); 00181 00182 res = (t == e) ? t : cuddUniqueInter(dd,(int)f->index,t,e); 00183 if (res == NULL) { 00184 Cudd_RecursiveDeref(dd, t); 00185 Cudd_RecursiveDeref(dd, e); 00186 return(NULL); 00187 } 00188 cuddDeref(t); 00189 cuddDeref(e); 00190 00191 cuddCacheInsert2(dd,Cudd_addScalarInverse,f,epsilon,res); 00192 00193 return(res); 00194 00195 } /* end of cuddAddScalarInverseRecur */
Function********************************************************************
Synopsis [Performs the recursive step of Cudd_addUnivAbstract.]
Description [Performs the recursive step of Cudd_addUnivAbstract. Returns the ADD obtained by abstracting the variables of cube from f, if successful; NULL otherwise.]
SideEffects [None]
SeeAlso []
Definition at line 357 of file cuddAddAbs.c.
00361 { 00362 DdNode *T, *E, *res, *res1, *res2, *one, *zero; 00363 00364 statLine(manager); 00365 one = DD_ONE(manager); 00366 zero = DD_ZERO(manager); 00367 00368 /* Cube is guaranteed to be a cube at this point. 00369 ** zero and one are the only constatnts c such that c*c=c. 00370 */ 00371 if (f == zero || f == one || cube == one) { 00372 return(f); 00373 } 00374 00375 /* Abstract a variable that does not appear in f. */ 00376 if (cuddI(manager,f->index) > cuddI(manager,cube->index)) { 00377 res1 = cuddAddUnivAbstractRecur(manager, f, cuddT(cube)); 00378 if (res1 == NULL) return(NULL); 00379 cuddRef(res1); 00380 /* Use the "internal" procedure to be alerted in case of 00381 ** dynamic reordering. If dynamic reordering occurs, we 00382 ** have to abort the entire abstraction. 00383 */ 00384 res = cuddAddApplyRecur(manager, Cudd_addTimes, res1, res1); 00385 if (res == NULL) { 00386 Cudd_RecursiveDeref(manager,res1); 00387 return(NULL); 00388 } 00389 cuddRef(res); 00390 Cudd_RecursiveDeref(manager,res1); 00391 cuddDeref(res); 00392 return(res); 00393 } 00394 00395 if ((res = cuddCacheLookup2(manager, Cudd_addUnivAbstract, f, cube)) != NULL) { 00396 return(res); 00397 } 00398 00399 T = cuddT(f); 00400 E = cuddE(f); 00401 00402 /* If the two indices are the same, so are their levels. */ 00403 if (f->index == cube->index) { 00404 res1 = cuddAddUnivAbstractRecur(manager, T, cuddT(cube)); 00405 if (res1 == NULL) return(NULL); 00406 cuddRef(res1); 00407 res2 = cuddAddUnivAbstractRecur(manager, E, cuddT(cube)); 00408 if (res2 == NULL) { 00409 Cudd_RecursiveDeref(manager,res1); 00410 return(NULL); 00411 } 00412 cuddRef(res2); 00413 res = cuddAddApplyRecur(manager, Cudd_addTimes, res1, res2); 00414 if (res == NULL) { 00415 Cudd_RecursiveDeref(manager,res1); 00416 Cudd_RecursiveDeref(manager,res2); 00417 return(NULL); 00418 } 00419 cuddRef(res); 00420 Cudd_RecursiveDeref(manager,res1); 00421 Cudd_RecursiveDeref(manager,res2); 00422 cuddCacheInsert2(manager, Cudd_addUnivAbstract, f, cube, res); 00423 cuddDeref(res); 00424 return(res); 00425 } else { /* if (cuddI(manager,f->index) < cuddI(manager,cube->index)) */ 00426 res1 = cuddAddUnivAbstractRecur(manager, T, cube); 00427 if (res1 == NULL) return(NULL); 00428 cuddRef(res1); 00429 res2 = cuddAddUnivAbstractRecur(manager, E, cube); 00430 if (res2 == NULL) { 00431 Cudd_RecursiveDeref(manager,res1); 00432 return(NULL); 00433 } 00434 cuddRef(res2); 00435 res = (res1 == res2) ? res1 : 00436 cuddUniqueInter(manager, (int) f->index, res1, res2); 00437 if (res == NULL) { 00438 Cudd_RecursiveDeref(manager,res1); 00439 Cudd_RecursiveDeref(manager,res2); 00440 return(NULL); 00441 } 00442 cuddDeref(res1); 00443 cuddDeref(res2); 00444 cuddCacheInsert2(manager, Cudd_addUnivAbstract, f, cube, res); 00445 return(res); 00446 } 00447 00448 } /* end of cuddAddUnivAbstractRecur */
Function********************************************************************
Synopsis [Fast storage allocation for DdNodes in the table.]
Description [Fast storage allocation for DdNodes in the table. The first 4 bytes of a chunk contain a pointer to the next block; the rest contains DD_MEM_CHUNK spaces for DdNodes. Returns a pointer to a new node if successful; NULL is memory is full.]
SideEffects [None]
SeeAlso [cuddDynamicAllocNode]
Definition at line 231 of file cuddTable.c.
00233 { 00234 int i; 00235 DdNodePtr *mem; 00236 DdNode *list, *node; 00237 extern DD_OOMFP MMoutOfMemory; 00238 DD_OOMFP saveHandler; 00239 00240 if (unique->nextFree == NULL) { /* free list is empty */ 00241 /* Check for exceeded limits. */ 00242 if ((unique->keys - unique->dead) + (unique->keysZ - unique->deadZ) > 00243 unique->maxLive) { 00244 unique->errorCode = CUDD_TOO_MANY_NODES; 00245 return(NULL); 00246 } 00247 if (unique->stash == NULL || unique->memused > unique->maxmemhard) { 00248 (void) cuddGarbageCollect(unique,1); 00249 mem = NULL; 00250 } 00251 if (unique->nextFree == NULL) { 00252 if (unique->memused > unique->maxmemhard) { 00253 unique->errorCode = CUDD_MAX_MEM_EXCEEDED; 00254 return(NULL); 00255 } 00256 /* Try to allocate a new block. */ 00257 saveHandler = MMoutOfMemory; 00258 MMoutOfMemory = Cudd_OutOfMem; 00259 mem = (DdNodePtr *) ALLOC(DdNode,DD_MEM_CHUNK + 1); 00260 MMoutOfMemory = saveHandler; 00261 if (mem == NULL) { 00262 /* No more memory: Try collecting garbage. If this succeeds, 00263 ** we end up with mem still NULL, but unique->nextFree != 00264 ** NULL. */ 00265 if (cuddGarbageCollect(unique,1) == 0) { 00266 /* Last resort: Free the memory stashed away, if there 00267 ** any. If this succeeeds, mem != NULL and 00268 ** unique->nextFree still NULL. */ 00269 if (unique->stash != NULL) { 00270 FREE(unique->stash); 00271 unique->stash = NULL; 00272 /* Inhibit resizing of tables. */ 00273 cuddSlowTableGrowth(unique); 00274 /* Now try again. */ 00275 mem = (DdNodePtr *) ALLOC(DdNode,DD_MEM_CHUNK + 1); 00276 } 00277 if (mem == NULL) { 00278 /* Out of luck. Call the default handler to do 00279 ** whatever it specifies for a failed malloc. 00280 ** If this handler returns, then set error code, 00281 ** print warning, and return. */ 00282 (*MMoutOfMemory)(sizeof(DdNode)*(DD_MEM_CHUNK + 1)); 00283 unique->errorCode = CUDD_MEMORY_OUT; 00284 #ifdef DD_VERBOSE 00285 (void) fprintf(unique->err, 00286 "cuddAllocNode: out of memory"); 00287 (void) fprintf(unique->err, "Memory in use = %lu\n", 00288 unique->memused); 00289 #endif 00290 return(NULL); 00291 } 00292 } 00293 } 00294 if (mem != NULL) { /* successful allocation; slice memory */ 00295 ptruint offset; 00296 unique->memused += (DD_MEM_CHUNK + 1) * sizeof(DdNode); 00297 mem[0] = (DdNodePtr) unique->memoryList; 00298 unique->memoryList = mem; 00299 00300 /* Here we rely on the fact that a DdNode is as large 00301 ** as 4 pointers. */ 00302 offset = (ptruint) mem & (sizeof(DdNode) - 1); 00303 mem += (sizeof(DdNode) - offset) / sizeof(DdNodePtr); 00304 assert(((ptruint) mem & (sizeof(DdNode) - 1)) == 0); 00305 list = (DdNode *) mem; 00306 00307 i = 1; 00308 do { 00309 list[i - 1].ref = 0; 00310 list[i - 1].next = &list[i]; 00311 } while (++i < DD_MEM_CHUNK); 00312 00313 list[DD_MEM_CHUNK-1].ref = 0; 00314 list[DD_MEM_CHUNK-1].next = NULL; 00315 00316 unique->nextFree = &list[0]; 00317 } 00318 } 00319 } 00320 unique->allocated++; 00321 node = unique->nextFree; 00322 unique->nextFree = node->next; 00323 return(node); 00324 00325 } /* end of cuddAllocNode */
int cuddAnnealing | ( | DdManager * | table, | |
int | lower, | |||
int | upper | |||
) |
AutomaticEnd Function********************************************************************
Synopsis [Get new variable-order by simulated annealing algorithm.]
Description [Get x, y by random selection. Choose either exchange or jump randomly. In case of jump, choose between jump_up and jump_down randomly. Do exchange or jump and get optimal case. Loop until there is no improvement or temperature reaches minimum. Returns 1 in case of success; 0 otherwise.]
SideEffects [None]
SeeAlso []
Definition at line 154 of file cuddAnneal.c.
00158 { 00159 int nvars; 00160 int size; 00161 int x,y; 00162 int result; 00163 int c1, c2, c3, c4; 00164 int BestCost; 00165 int *BestOrder; 00166 double NewTemp, temp; 00167 double rand1; 00168 int innerloop, maxGen; 00169 int ecount, ucount, dcount; 00170 00171 nvars = upper - lower + 1; 00172 00173 result = cuddSifting(table,lower,upper); 00174 #ifdef DD_STATS 00175 (void) fprintf(table->out,"\n"); 00176 #endif 00177 if (result == 0) return(0); 00178 00179 size = table->keys - table->isolated; 00180 00181 /* Keep track of the best order. */ 00182 BestCost = size; 00183 BestOrder = ALLOC(int,nvars); 00184 if (BestOrder == NULL) { 00185 table->errorCode = CUDD_MEMORY_OUT; 00186 return(0); 00187 } 00188 copyOrder(table,BestOrder,lower,upper); 00189 00190 temp = BETA * size; 00191 maxGen = (int) (MAXGEN_RATIO * nvars); 00192 00193 c1 = size + 10; 00194 c2 = c1 + 10; 00195 c3 = size; 00196 c4 = c2 + 10; 00197 ecount = ucount = dcount = 0; 00198 00199 while (!stopping_criterion(c1, c2, c3, c4, temp)) { 00200 #ifdef DD_STATS 00201 (void) fprintf(table->out,"temp=%f\tsize=%d\tgen=%d\t", 00202 temp,size,maxGen); 00203 tosses = acceptances = 0; 00204 #endif 00205 for (innerloop = 0; innerloop < maxGen; innerloop++) { 00206 /* Choose x, y randomly. */ 00207 x = (int) Cudd_Random() % nvars; 00208 do { 00209 y = (int) Cudd_Random() % nvars; 00210 } while (x == y); 00211 x += lower; 00212 y += lower; 00213 if (x > y) { 00214 int tmp = x; 00215 x = y; 00216 y = tmp; 00217 } 00218 00219 /* Choose move with roulette wheel. */ 00220 rand1 = random_generator(); 00221 if (rand1 < EXC_PROB) { 00222 result = ddExchange(table,x,y,temp); /* exchange */ 00223 ecount++; 00224 #if 0 00225 (void) fprintf(table->out, 00226 "Exchange of %d and %d: size = %d\n", 00227 x,y,table->keys - table->isolated); 00228 #endif 00229 } else if (rand1 < EXC_PROB + JUMP_UP_PROB) { 00230 result = ddJumpingAux(table,y,x,y,temp); /* jumping_up */ 00231 ucount++; 00232 #if 0 00233 (void) fprintf(table->out, 00234 "Jump up of %d to %d: size = %d\n", 00235 y,x,table->keys - table->isolated); 00236 #endif 00237 } else { 00238 result = ddJumpingAux(table,x,x,y,temp); /* jumping_down */ 00239 dcount++; 00240 #if 0 00241 (void) fprintf(table->out, 00242 "Jump down of %d to %d: size = %d\n", 00243 x,y,table->keys - table->isolated); 00244 #endif 00245 } 00246 00247 if (!result) { 00248 FREE(BestOrder); 00249 return(0); 00250 } 00251 00252 size = table->keys - table->isolated; /* keep current size */ 00253 if (size < BestCost) { /* update best order */ 00254 BestCost = size; 00255 copyOrder(table,BestOrder,lower,upper); 00256 } 00257 } 00258 c1 = c2; 00259 c2 = c3; 00260 c3 = c4; 00261 c4 = size; 00262 NewTemp = ALPHA * temp; 00263 if (NewTemp >= 1.0) { 00264 maxGen = (int)(log(NewTemp) / log(temp) * maxGen); 00265 } 00266 temp = NewTemp; /* control variable */ 00267 #ifdef DD_STATS 00268 (void) fprintf(table->out,"uphill = %d\taccepted = %d\n", 00269 tosses,acceptances); 00270 fflush(table->out); 00271 #endif 00272 } 00273 00274 result = restoreOrder(table,BestOrder,lower,upper); 00275 FREE(BestOrder); 00276 if (!result) return(0); 00277 #ifdef DD_STATS 00278 fprintf(table->out,"#:N_EXCHANGE %8d : total exchanges\n",ecount); 00279 fprintf(table->out,"#:N_JUMPUP %8d : total jumps up\n",ucount); 00280 fprintf(table->out,"#:N_JUMPDOWN %8d : total jumps down",dcount); 00281 #endif 00282 return(1); 00283 00284 } /* end of cuddAnnealing */
int cuddBddAlignToZdd | ( | DdManager * | table | ) |
Function********************************************************************
Synopsis [Reorders BDD variables according to the order of the ZDD variables.]
Description [Reorders BDD variables according to the order of the ZDD variables. This function can be called at the end of ZDD reordering to insure that the order of the BDD variables is consistent with the order of the ZDD variables. The number of ZDD variables must be a multiple of the number of BDD variables. Let M
be the ratio of the two numbers. cuddBddAlignToZdd then considers the ZDD variables from M*i
to (M+1)*i-1
as corresponding to BDD variable i
. This function should be normally called from Cudd_zddReduceHeap, which clears the cache. Returns 1 in case of success; 0 otherwise.]
SideEffects [Changes the BDD variable order for all diagrams and performs garbage collection of the BDD unique table.]
SeeAlso [Cudd_ShuffleHeap Cudd_zddReduceHeap]
Definition at line 1242 of file cuddReorder.c.
01244 { 01245 int *invperm; /* permutation array */ 01246 int M; /* ratio of ZDD variables to BDD variables */ 01247 int i; /* loop index */ 01248 int result; /* return value */ 01249 01250 /* We assume that a ratio of 0 is OK. */ 01251 if (table->size == 0) 01252 return(1); 01253 01254 M = table->sizeZ / table->size; 01255 /* Check whether the number of ZDD variables is a multiple of the 01256 ** number of BDD variables. 01257 */ 01258 if (M * table->size != table->sizeZ) 01259 return(0); 01260 /* Create and initialize the inverse permutation array. */ 01261 invperm = ALLOC(int,table->size); 01262 if (invperm == NULL) { 01263 table->errorCode = CUDD_MEMORY_OUT; 01264 return(0); 01265 } 01266 for (i = 0; i < table->sizeZ; i += M) { 01267 int indexZ = table->invpermZ[i]; 01268 int index = indexZ / M; 01269 invperm[i / M] = index; 01270 } 01271 /* Eliminate dead nodes. Do not scan the cache again, because we 01272 ** assume that Cudd_zddReduceHeap has already cleared it. 01273 */ 01274 cuddGarbageCollect(table,0); 01275 01276 /* Initialize number of isolated projection functions. */ 01277 table->isolated = 0; 01278 for (i = 0; i < table->size; i++) { 01279 if (table->vars[i]->ref == 1) table->isolated++; 01280 } 01281 01282 /* Initialize the interaction matrix. */ 01283 result = cuddInitInteract(table); 01284 if (result == 0) return(0); 01285 01286 result = ddShuffle(table, invperm); 01287 FREE(invperm); 01288 /* Free interaction matrix. */ 01289 FREE(table->interact); 01290 /* Fix the BDD variable group tree. */ 01291 bddFixTree(table,table->tree); 01292 return(result); 01293 01294 } /* end of cuddBddAlignToZdd */
Function********************************************************************
Synopsis [Takes the AND of two BDDs and simultaneously abstracts the variables in cube.]
Description [Takes the AND of two BDDs and simultaneously abstracts the variables in cube. The variables are existentially abstracted. Returns a pointer to the result is successful; NULL otherwise.]
SideEffects [None]
SeeAlso [Cudd_bddAndAbstract]
Definition at line 196 of file cuddAndAbs.c.
00201 { 00202 DdNode *F, *ft, *fe, *G, *gt, *ge; 00203 DdNode *one, *zero, *r, *t, *e; 00204 unsigned int topf, topg, topcube, top, index; 00205 00206 statLine(manager); 00207 one = DD_ONE(manager); 00208 zero = Cudd_Not(one); 00209 00210 /* Terminal cases. */ 00211 if (f == zero || g == zero || f == Cudd_Not(g)) return(zero); 00212 if (f == one && g == one) return(one); 00213 00214 if (cube == one) { 00215 return(cuddBddAndRecur(manager, f, g)); 00216 } 00217 if (f == one || f == g) { 00218 return(cuddBddExistAbstractRecur(manager, g, cube)); 00219 } 00220 if (g == one) { 00221 return(cuddBddExistAbstractRecur(manager, f, cube)); 00222 } 00223 /* At this point f, g, and cube are not constant. */ 00224 00225 if (f > g) { /* Try to increase cache efficiency. */ 00226 DdNode *tmp = f; 00227 f = g; 00228 g = tmp; 00229 } 00230 00231 /* Here we can skip the use of cuddI, because the operands are known 00232 ** to be non-constant. 00233 */ 00234 F = Cudd_Regular(f); 00235 G = Cudd_Regular(g); 00236 topf = manager->perm[F->index]; 00237 topg = manager->perm[G->index]; 00238 top = ddMin(topf, topg); 00239 topcube = manager->perm[cube->index]; 00240 00241 while (topcube < top) { 00242 cube = cuddT(cube); 00243 if (cube == one) { 00244 return(cuddBddAndRecur(manager, f, g)); 00245 } 00246 topcube = manager->perm[cube->index]; 00247 } 00248 /* Now, topcube >= top. */ 00249 00250 /* Check cache. */ 00251 if (F->ref != 1 || G->ref != 1) { 00252 r = cuddCacheLookup(manager, DD_BDD_AND_ABSTRACT_TAG, f, g, cube); 00253 if (r != NULL) { 00254 return(r); 00255 } 00256 } 00257 00258 if (topf == top) { 00259 index = F->index; 00260 ft = cuddT(F); 00261 fe = cuddE(F); 00262 if (Cudd_IsComplement(f)) { 00263 ft = Cudd_Not(ft); 00264 fe = Cudd_Not(fe); 00265 } 00266 } else { 00267 index = G->index; 00268 ft = fe = f; 00269 } 00270 00271 if (topg == top) { 00272 gt = cuddT(G); 00273 ge = cuddE(G); 00274 if (Cudd_IsComplement(g)) { 00275 gt = Cudd_Not(gt); 00276 ge = Cudd_Not(ge); 00277 } 00278 } else { 00279 gt = ge = g; 00280 } 00281 00282 if (topcube == top) { /* quantify */ 00283 DdNode *Cube = cuddT(cube); 00284 t = cuddBddAndAbstractRecur(manager, ft, gt, Cube); 00285 if (t == NULL) return(NULL); 00286 /* Special case: 1 OR anything = 1. Hence, no need to compute 00287 ** the else branch if t is 1. Likewise t + t * anything == t. 00288 ** Notice that t == fe implies that fe does not depend on the 00289 ** variables in Cube. Likewise for t == ge. 00290 */ 00291 if (t == one || t == fe || t == ge) { 00292 if (F->ref != 1 || G->ref != 1) 00293 cuddCacheInsert(manager, DD_BDD_AND_ABSTRACT_TAG, 00294 f, g, cube, t); 00295 return(t); 00296 } 00297 cuddRef(t); 00298 /* Special case: t + !t * anything == t + anything. */ 00299 if (t == Cudd_Not(fe)) { 00300 e = cuddBddExistAbstractRecur(manager, ge, Cube); 00301 } else if (t == Cudd_Not(ge)) { 00302 e = cuddBddExistAbstractRecur(manager, fe, Cube); 00303 } else { 00304 e = cuddBddAndAbstractRecur(manager, fe, ge, Cube); 00305 } 00306 if (e == NULL) { 00307 Cudd_IterDerefBdd(manager, t); 00308 return(NULL); 00309 } 00310 if (t == e) { 00311 r = t; 00312 cuddDeref(t); 00313 } else { 00314 cuddRef(e); 00315 r = cuddBddAndRecur(manager, Cudd_Not(t), Cudd_Not(e)); 00316 if (r == NULL) { 00317 Cudd_IterDerefBdd(manager, t); 00318 Cudd_IterDerefBdd(manager, e); 00319 return(NULL); 00320 } 00321 r = Cudd_Not(r); 00322 cuddRef(r); 00323 Cudd_DelayedDerefBdd(manager, t); 00324 Cudd_DelayedDerefBdd(manager, e); 00325 cuddDeref(r); 00326 } 00327 } else { 00328 t = cuddBddAndAbstractRecur(manager, ft, gt, cube); 00329 if (t == NULL) return(NULL); 00330 cuddRef(t); 00331 e = cuddBddAndAbstractRecur(manager, fe, ge, cube); 00332 if (e == NULL) { 00333 Cudd_IterDerefBdd(manager, t); 00334 return(NULL); 00335 } 00336 if (t == e) { 00337 r = t; 00338 cuddDeref(t); 00339 } else { 00340 cuddRef(e); 00341 if (Cudd_IsComplement(t)) { 00342 r = cuddUniqueInter(manager, (int) index, 00343 Cudd_Not(t), Cudd_Not(e)); 00344 if (r == NULL) { 00345 Cudd_IterDerefBdd(manager, t); 00346 Cudd_IterDerefBdd(manager, e); 00347 return(NULL); 00348 } 00349 r = Cudd_Not(r); 00350 } else { 00351 r = cuddUniqueInter(manager,(int)index,t,e); 00352 if (r == NULL) { 00353 Cudd_IterDerefBdd(manager, t); 00354 Cudd_IterDerefBdd(manager, e); 00355 return(NULL); 00356 } 00357 } 00358 cuddDeref(e); 00359 cuddDeref(t); 00360 } 00361 } 00362 00363 if (F->ref != 1 || G->ref != 1) 00364 cuddCacheInsert(manager, DD_BDD_AND_ABSTRACT_TAG, f, g, cube, r); 00365 return (r); 00366 00367 } /* end of cuddBddAndAbstractRecur */
Function********************************************************************
Synopsis [Implements the recursive step of Cudd_bddAnd.]
Description [Implements the recursive step of Cudd_bddAnd by taking the conjunction of two BDDs. Returns a pointer to the result is successful; NULL otherwise.]
SideEffects [None]
SeeAlso [Cudd_bddAnd]
Definition at line 882 of file cuddBddIte.c.
00886 { 00887 DdNode *F, *fv, *fnv, *G, *gv, *gnv; 00888 DdNode *one, *r, *t, *e; 00889 unsigned int topf, topg, index; 00890 00891 statLine(manager); 00892 one = DD_ONE(manager); 00893 00894 /* Terminal cases. */ 00895 F = Cudd_Regular(f); 00896 G = Cudd_Regular(g); 00897 if (F == G) { 00898 if (f == g) return(f); 00899 else return(Cudd_Not(one)); 00900 } 00901 if (F == one) { 00902 if (f == one) return(g); 00903 else return(f); 00904 } 00905 if (G == one) { 00906 if (g == one) return(f); 00907 else return(g); 00908 } 00909 00910 /* At this point f and g are not constant. */ 00911 if (f > g) { /* Try to increase cache efficiency. */ 00912 DdNode *tmp = f; 00913 f = g; 00914 g = tmp; 00915 F = Cudd_Regular(f); 00916 G = Cudd_Regular(g); 00917 } 00918 00919 /* Check cache. */ 00920 if (F->ref != 1 || G->ref != 1) { 00921 r = cuddCacheLookup2(manager, Cudd_bddAnd, f, g); 00922 if (r != NULL) return(r); 00923 } 00924 00925 /* Here we can skip the use of cuddI, because the operands are known 00926 ** to be non-constant. 00927 */ 00928 topf = manager->perm[F->index]; 00929 topg = manager->perm[G->index]; 00930 00931 /* Compute cofactors. */ 00932 if (topf <= topg) { 00933 index = F->index; 00934 fv = cuddT(F); 00935 fnv = cuddE(F); 00936 if (Cudd_IsComplement(f)) { 00937 fv = Cudd_Not(fv); 00938 fnv = Cudd_Not(fnv); 00939 } 00940 } else { 00941 index = G->index; 00942 fv = fnv = f; 00943 } 00944 00945 if (topg <= topf) { 00946 gv = cuddT(G); 00947 gnv = cuddE(G); 00948 if (Cudd_IsComplement(g)) { 00949 gv = Cudd_Not(gv); 00950 gnv = Cudd_Not(gnv); 00951 } 00952 } else { 00953 gv = gnv = g; 00954 } 00955 00956 t = cuddBddAndRecur(manager, fv, gv); 00957 if (t == NULL) return(NULL); 00958 cuddRef(t); 00959 00960 e = cuddBddAndRecur(manager, fnv, gnv); 00961 if (e == NULL) { 00962 Cudd_IterDerefBdd(manager, t); 00963 return(NULL); 00964 } 00965 cuddRef(e); 00966 00967 if (t == e) { 00968 r = t; 00969 } else { 00970 if (Cudd_IsComplement(t)) { 00971 r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e)); 00972 if (r == NULL) { 00973 Cudd_IterDerefBdd(manager, t); 00974 Cudd_IterDerefBdd(manager, e); 00975 return(NULL); 00976 } 00977 r = Cudd_Not(r); 00978 } else { 00979 r = cuddUniqueInter(manager,(int)index,t,e); 00980 if (r == NULL) { 00981 Cudd_IterDerefBdd(manager, t); 00982 Cudd_IterDerefBdd(manager, e); 00983 return(NULL); 00984 } 00985 } 00986 } 00987 cuddDeref(e); 00988 cuddDeref(t); 00989 if (F->ref != 1 || G->ref != 1) 00990 cuddCacheInsert2(manager, Cudd_bddAnd, f, g, r); 00991 return(r); 00992 00993 } /* end of cuddBddAndRecur */
Function********************************************************************
Synopsis [Performs the recursive steps of Cudd_bddBoleanDiff.]
Description [Performs the recursive steps of Cudd_bddBoleanDiff. Returns the BDD obtained by XORing the cofactors of f with respect to var if successful; NULL otherwise. Exploits the fact that dF/dx = dF'/dx.]
SideEffects [None]
SeeAlso []
Definition at line 630 of file cuddBddAbs.c.
00634 { 00635 DdNode *T, *E, *res, *res1, *res2; 00636 00637 statLine(manager); 00638 if (cuddI(manager,f->index) > manager->perm[var->index]) { 00639 /* f does not depend on var. */ 00640 return(Cudd_Not(DD_ONE(manager))); 00641 } 00642 00643 /* From now on, f is non-constant. */ 00644 00645 /* If the two indices are the same, so are their levels. */ 00646 if (f->index == var->index) { 00647 res = cuddBddXorRecur(manager, cuddT(f), cuddE(f)); 00648 return(res); 00649 } 00650 00651 /* From now on, cuddI(manager,f->index) < cuddI(manager,cube->index). */ 00652 00653 /* Check the cache. */ 00654 res = cuddCacheLookup2(manager, cuddBddBooleanDiffRecur, f, var); 00655 if (res != NULL) { 00656 return(res); 00657 } 00658 00659 /* Compute the cofactors of f. */ 00660 T = cuddT(f); E = cuddE(f); 00661 00662 res1 = cuddBddBooleanDiffRecur(manager, T, var); 00663 if (res1 == NULL) return(NULL); 00664 cuddRef(res1); 00665 res2 = cuddBddBooleanDiffRecur(manager, Cudd_Regular(E), var); 00666 if (res2 == NULL) { 00667 Cudd_IterDerefBdd(manager, res1); 00668 return(NULL); 00669 } 00670 cuddRef(res2); 00671 /* ITE takes care of possible complementation of res1 and of the 00672 ** case in which res1 == res2. */ 00673 res = cuddBddIteRecur(manager, manager->vars[f->index], res1, res2); 00674 if (res == NULL) { 00675 Cudd_IterDerefBdd(manager, res1); 00676 Cudd_IterDerefBdd(manager, res2); 00677 return(NULL); 00678 } 00679 cuddDeref(res1); 00680 cuddDeref(res2); 00681 cuddCacheInsert2(manager, cuddBddBooleanDiffRecur, f, var, res); 00682 return(res); 00683 00684 } /* end of cuddBddBooleanDiffRecur */
Function********************************************************************
Synopsis [Approximates the conjunction of two BDDs f and g.]
Description [Approximates the conjunction of two BDDs f and g. Returns a pointer to the resulting BDD if successful; NULL if the intermediate result blows up.]
SideEffects [None]
SeeAlso [Cudd_bddClippingAnd]
Definition at line 197 of file cuddClip.c.
00203 { 00204 DdNode *res; 00205 00206 res = cuddBddClippingAndRecur(dd,f,g,maxDepth,direction); 00207 00208 return(res); 00209 00210 } /* end of cuddBddClippingAnd */
DdNode* cuddBddClippingAndAbstract | ( | DdManager * | dd, | |
DdNode * | f, | |||
DdNode * | g, | |||
DdNode * | cube, | |||
int | maxDepth, | |||
int | direction | |||
) |
Function********************************************************************
Synopsis [Approximates the conjunction of two BDDs f and g and simultaneously abstracts the variables in cube.]
Description [Approximates the conjunction of two BDDs f and g and simultaneously abstracts the variables in cube. Returns a pointer to the resulting BDD if successful; NULL if the intermediate result blows up.]
SideEffects [None]
SeeAlso [Cudd_bddClippingAndAbstract]
Definition at line 229 of file cuddClip.c.
00236 { 00237 DdNode *res; 00238 00239 res = cuddBddClipAndAbsRecur(dd,f,g,cube,maxDepth,direction); 00240 00241 return(res); 00242 00243 } /* end of cuddBddClippingAndAbstract */
Function********************************************************************
Synopsis [Performs the recursive step of Cudd_bddClosestCube.]
Description [Performs the recursive step of Cudd_bddClosestCube. Returns the cube if succesful; NULL otherwise. The procedure uses a four-way recursion to examine all four combinations of cofactors of f
and g
according to the following formula.
H(f,g) = min(H(ft,gt), H(fe,ge), H(ft,ge)+1, H(fe,gt)+1)
Bounding is based on the following observations.
The variable bound
is set at the largest value of the distance that we are still interested in. Therefore, we desist when
(bound == -1) and (F != not(G)) or (bound == 0) and (F == not(G)).
If we were maximally aggressive in using the bound, we would always set the bound to the minimum distance seen thus far minus one. That is, we would maintain the invariant
bound < minD,
except at the very beginning, when we have no value for minD
.
However, we do not use bound < minD
when examining the two negative cofactors, because we try to find a large cube at minimum distance. To do so, we try to find a cube in the negative cofactors at the same or smaller distance from the cube found in the positive cofactors.
When we compute H(ft,ge)
and H(fe,gt)
we know that we are going to add 1 to the result of the recursive call to account for the difference in the splitting variable. Therefore, we decrease the bound correspondingly.
Another important observation concerns the need of examining all four pairs of cofators only when both f
and g
depend on the top variable.
Suppose gt == ge == g
. (That is, g
does not depend on the top variable.) Then
H(f,g) = min(H(ft,g), H(fe,g), H(ft,g)+1, H(fe,g)+1) = min(H(ft,g), H(fe,g)) .
Therefore, under these circumstances, we skip the two "cross" cases.
An interesting feature of this function is the scheme used for caching the results in the global computed table. Since we have a cube and a distance, we combine them to form an ADD. The combination replaces the zero child of the top node of the cube with the negative of the distance. (The use of the negative is to avoid ambiguity with 1.) The degenerate cases (zero and one) are treated specially because the distance is known (0 for one, and infinity for zero).]
SideEffects [None]
SeeAlso [Cudd_bddClosestCube]
Definition at line 1642 of file cuddPriority.c.
01647 { 01648 DdNode *res, *F, *G, *ft, *fe, *gt, *ge, *tt, *ee; 01649 DdNode *ctt, *cee, *cte, *cet; 01650 CUDD_VALUE_TYPE minD, dtt, dee, dte, det; 01651 DdNode *one = DD_ONE(dd); 01652 DdNode *lzero = Cudd_Not(one); 01653 DdNode *azero = DD_ZERO(dd); 01654 unsigned int topf, topg, index; 01655 01656 statLine(dd); 01657 if (bound < (f == Cudd_Not(g))) return(azero); 01658 /* Terminal cases. */ 01659 if (g == lzero || f == lzero) return(azero); 01660 if (f == one && g == one) return(one); 01661 01662 /* Check cache. */ 01663 F = Cudd_Regular(f); 01664 G = Cudd_Regular(g); 01665 if (F->ref != 1 || G->ref != 1) { 01666 res = cuddCacheLookup2(dd,(DD_CTFP) Cudd_bddClosestCube, f, g); 01667 if (res != NULL) return(res); 01668 } 01669 01670 topf = cuddI(dd,F->index); 01671 topg = cuddI(dd,G->index); 01672 01673 /* Compute cofactors. */ 01674 if (topf <= topg) { 01675 index = F->index; 01676 ft = cuddT(F); 01677 fe = cuddE(F); 01678 if (Cudd_IsComplement(f)) { 01679 ft = Cudd_Not(ft); 01680 fe = Cudd_Not(fe); 01681 } 01682 } else { 01683 index = G->index; 01684 ft = fe = f; 01685 } 01686 01687 if (topg <= topf) { 01688 gt = cuddT(G); 01689 ge = cuddE(G); 01690 if (Cudd_IsComplement(g)) { 01691 gt = Cudd_Not(gt); 01692 ge = Cudd_Not(ge); 01693 } 01694 } else { 01695 gt = ge = g; 01696 } 01697 01698 tt = cuddBddClosestCube(dd,ft,gt,bound); 01699 if (tt == NULL) return(NULL); 01700 cuddRef(tt); 01701 ctt = separateCube(dd,tt,&dtt); 01702 if (ctt == NULL) { 01703 Cudd_RecursiveDeref(dd, tt); 01704 return(NULL); 01705 } 01706 cuddRef(ctt); 01707 Cudd_RecursiveDeref(dd, tt); 01708 minD = dtt; 01709 bound = ddMin(bound,minD); 01710 01711 ee = cuddBddClosestCube(dd,fe,ge,bound); 01712 if (ee == NULL) { 01713 Cudd_RecursiveDeref(dd, ctt); 01714 return(NULL); 01715 } 01716 cuddRef(ee); 01717 cee = separateCube(dd,ee,&dee); 01718 if (cee == NULL) { 01719 Cudd_RecursiveDeref(dd, ctt); 01720 Cudd_RecursiveDeref(dd, ee); 01721 return(NULL); 01722 } 01723 cuddRef(cee); 01724 Cudd_RecursiveDeref(dd, ee); 01725 minD = ddMin(dtt, dee); 01726 if (minD <= CUDD_CONST_INDEX) bound = ddMin(bound,minD-1); 01727 01728 if (minD > 0 && topf == topg) { 01729 DdNode *te = cuddBddClosestCube(dd,ft,ge,bound-1); 01730 if (te == NULL) { 01731 Cudd_RecursiveDeref(dd, ctt); 01732 Cudd_RecursiveDeref(dd, cee); 01733 return(NULL); 01734 } 01735 cuddRef(te); 01736 cte = separateCube(dd,te,&dte); 01737 if (cte == NULL) { 01738 Cudd_RecursiveDeref(dd, ctt); 01739 Cudd_RecursiveDeref(dd, cee); 01740 Cudd_RecursiveDeref(dd, te); 01741 return(NULL); 01742 } 01743 cuddRef(cte); 01744 Cudd_RecursiveDeref(dd, te); 01745 dte += 1.0; 01746 minD = ddMin(minD, dte); 01747 } else { 01748 cte = azero; 01749 cuddRef(cte); 01750 dte = CUDD_CONST_INDEX + 1.0; 01751 } 01752 if (minD <= CUDD_CONST_INDEX) bound = ddMin(bound,minD-1); 01753 01754 if (minD > 0 && topf == topg) { 01755 DdNode *et = cuddBddClosestCube(dd,fe,gt,bound-1); 01756 if (et == NULL) { 01757 Cudd_RecursiveDeref(dd, ctt); 01758 Cudd_RecursiveDeref(dd, cee); 01759 Cudd_RecursiveDeref(dd, cte); 01760 return(NULL); 01761 } 01762 cuddRef(et); 01763 cet = separateCube(dd,et,&det); 01764 if (cet == NULL) { 01765 Cudd_RecursiveDeref(dd, ctt); 01766 Cudd_RecursiveDeref(dd, cee); 01767 Cudd_RecursiveDeref(dd, cte); 01768 Cudd_RecursiveDeref(dd, et); 01769 return(NULL); 01770 } 01771 cuddRef(cet); 01772 Cudd_RecursiveDeref(dd, et); 01773 det += 1.0; 01774 minD = ddMin(minD, det); 01775 } else { 01776 cet = azero; 01777 cuddRef(cet); 01778 det = CUDD_CONST_INDEX + 1.0; 01779 } 01780 01781 if (minD == dtt) { 01782 if (dtt == dee && ctt == cee) { 01783 res = createResult(dd,CUDD_CONST_INDEX,1,ctt,dtt); 01784 } else { 01785 res = createResult(dd,index,1,ctt,dtt); 01786 } 01787 } else if (minD == dee) { 01788 res = createResult(dd,index,0,cee,dee); 01789 } else if (minD == dte) { 01790 #ifdef DD_DEBUG 01791 assert(topf == topg); 01792 #endif 01793 res = createResult(dd,index,1,cte,dte); 01794 } else { 01795 #ifdef DD_DEBUG 01796 assert(topf == topg); 01797 #endif 01798 res = createResult(dd,index,0,cet,det); 01799 } 01800 if (res == NULL) { 01801 Cudd_RecursiveDeref(dd, ctt); 01802 Cudd_RecursiveDeref(dd, cee); 01803 Cudd_RecursiveDeref(dd, cte); 01804 Cudd_RecursiveDeref(dd, cet); 01805 return(NULL); 01806 } 01807 cuddRef(res); 01808 Cudd_RecursiveDeref(dd, ctt); 01809 Cudd_RecursiveDeref(dd, cee); 01810 Cudd_RecursiveDeref(dd, cte); 01811 Cudd_RecursiveDeref(dd, cet); 01812 01813 /* Only cache results that are different from azero to avoid 01814 ** storing results that depend on the value of the bound. */ 01815 if ((F->ref != 1 || G->ref != 1) && res != azero) 01816 cuddCacheInsert2(dd,(DD_CTFP) Cudd_bddClosestCube, f, g, res); 01817 01818 cuddDeref(res); 01819 return(res); 01820 01821 } /* end of cuddBddClosestCube */
Function********************************************************************
Synopsis [Performs the recursive step of Cudd_bddCompose.]
Description [Performs the recursive step of Cudd_bddCompose. Exploits the fact that the composition of f' with g produces the complement of the composition of f with g to better utilize the cache. Returns the composed BDD if successful; NULL otherwise.]
SideEffects [None]
SeeAlso [Cudd_bddCompose]
Definition at line 846 of file cuddCompose.c.
00851 { 00852 DdNode *F, *G, *f1, *f0, *g1, *g0, *r, *t, *e; 00853 unsigned int v, topf, topg, topindex; 00854 int comple; 00855 00856 statLine(dd); 00857 v = dd->perm[proj->index]; 00858 F = Cudd_Regular(f); 00859 topf = cuddI(dd,F->index); 00860 00861 /* Terminal case. Subsumes the test for constant f. */ 00862 if (topf > v) return(f); 00863 00864 /* We solve the problem for a regular pointer, and then complement 00865 ** the result if the pointer was originally complemented. 00866 */ 00867 comple = Cudd_IsComplement(f); 00868 00869 /* Check cache. */ 00870 r = cuddCacheLookup(dd,DD_BDD_COMPOSE_RECUR_TAG,F,g,proj); 00871 if (r != NULL) { 00872 return(Cudd_NotCond(r,comple)); 00873 } 00874 00875 if (topf == v) { 00876 /* Compose. */ 00877 f1 = cuddT(F); 00878 f0 = cuddE(F); 00879 r = cuddBddIteRecur(dd, g, f1, f0); 00880 if (r == NULL) return(NULL); 00881 } else { 00882 /* Compute cofactors of f and g. Remember the index of the top 00883 ** variable. 00884 */ 00885 G = Cudd_Regular(g); 00886 topg = cuddI(dd,G->index); 00887 if (topf > topg) { 00888 topindex = G->index; 00889 f1 = f0 = F; 00890 } else { 00891 topindex = F->index; 00892 f1 = cuddT(F); 00893 f0 = cuddE(F); 00894 } 00895 if (topg > topf) { 00896 g1 = g0 = g; 00897 } else { 00898 g1 = cuddT(G); 00899 g0 = cuddE(G); 00900 if (g != G) { 00901 g1 = Cudd_Not(g1); 00902 g0 = Cudd_Not(g0); 00903 } 00904 } 00905 /* Recursive step. */ 00906 t = cuddBddComposeRecur(dd, f1, g1, proj); 00907 if (t == NULL) return(NULL); 00908 cuddRef(t); 00909 e = cuddBddComposeRecur(dd, f0, g0, proj); 00910 if (e == NULL) { 00911 Cudd_IterDerefBdd(dd, t); 00912 return(NULL); 00913 } 00914 cuddRef(e); 00915 00916 r = cuddBddIteRecur(dd, dd->vars[topindex], t, e); 00917 if (r == NULL) { 00918 Cudd_IterDerefBdd(dd, t); 00919 Cudd_IterDerefBdd(dd, e); 00920 return(NULL); 00921 } 00922 cuddRef(r); 00923 Cudd_IterDerefBdd(dd, t); /* t & e not necessarily part of r */ 00924 Cudd_IterDerefBdd(dd, e); 00925 cuddDeref(r); 00926 } 00927 00928 cuddCacheInsert(dd,DD_BDD_COMPOSE_RECUR_TAG,F,g,proj,r); 00929 00930 return(Cudd_NotCond(r,comple)); 00931 00932 } /* end of cuddBddComposeRecur */
Function********************************************************************
Synopsis [Performs the recursive step of Cudd_bddConstrain.]
Description [Performs the recursive step of Cudd_bddConstrain. Returns a pointer to the result if successful; NULL otherwise.]
SideEffects [None]
SeeAlso [Cudd_bddConstrain]
Definition at line 779 of file cuddGenCof.c.
00783 { 00784 DdNode *Fv, *Fnv, *Cv, *Cnv, *t, *e, *r; 00785 DdNode *one, *zero; 00786 unsigned int topf, topc; 00787 int index; 00788 int comple = 0; 00789 00790 statLine(dd); 00791 one = DD_ONE(dd); 00792 zero = Cudd_Not(one); 00793 00794 /* Trivial cases. */ 00795 if (c == one) return(f); 00796 if (c == zero) return(zero); 00797 if (Cudd_IsConstant(f)) return(f); 00798 if (f == c) return(one); 00799 if (f == Cudd_Not(c)) return(zero); 00800 00801 /* Make canonical to increase the utilization of the cache. */ 00802 if (Cudd_IsComplement(f)) { 00803 f = Cudd_Not(f); 00804 comple = 1; 00805 } 00806 /* Now f is a regular pointer to a non-constant node; c is also 00807 ** non-constant, but may be complemented. 00808 */ 00809 00810 /* Check the cache. */ 00811 r = cuddCacheLookup2(dd, Cudd_bddConstrain, f, c); 00812 if (r != NULL) { 00813 return(Cudd_NotCond(r,comple)); 00814 } 00815 00816 /* Recursive step. */ 00817 topf = dd->perm[f->index]; 00818 topc = dd->perm[Cudd_Regular(c)->index]; 00819 if (topf <= topc) { 00820 index = f->index; 00821 Fv = cuddT(f); Fnv = cuddE(f); 00822 } else { 00823 index = Cudd_Regular(c)->index; 00824 Fv = Fnv = f; 00825 } 00826 if (topc <= topf) { 00827 Cv = cuddT(Cudd_Regular(c)); Cnv = cuddE(Cudd_Regular(c)); 00828 if (Cudd_IsComplement(c)) { 00829 Cv = Cudd_Not(Cv); 00830 Cnv = Cudd_Not(Cnv); 00831 } 00832 } else { 00833 Cv = Cnv = c; 00834 } 00835 00836 if (!Cudd_IsConstant(Cv)) { 00837 t = cuddBddConstrainRecur(dd, Fv, Cv); 00838 if (t == NULL) 00839 return(NULL); 00840 } else if (Cv == one) { 00841 t = Fv; 00842 } else { /* Cv == zero: return Fnv @ Cnv */ 00843 if (Cnv == one) { 00844 r = Fnv; 00845 } else { 00846 r = cuddBddConstrainRecur(dd, Fnv, Cnv); 00847 if (r == NULL) 00848 return(NULL); 00849 } 00850 return(Cudd_NotCond(r,comple)); 00851 } 00852 cuddRef(t); 00853 00854 if (!Cudd_IsConstant(Cnv)) { 00855 e = cuddBddConstrainRecur(dd, Fnv, Cnv); 00856 if (e == NULL) { 00857 Cudd_IterDerefBdd(dd, t); 00858 return(NULL); 00859 } 00860 } else if (Cnv == one) { 00861 e = Fnv; 00862 } else { /* Cnv == zero: return Fv @ Cv previously computed */ 00863 cuddDeref(t); 00864 return(Cudd_NotCond(t,comple)); 00865 } 00866 cuddRef(e); 00867 00868 if (Cudd_IsComplement(t)) { 00869 t = Cudd_Not(t); 00870 e = Cudd_Not(e); 00871 r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); 00872 if (r == NULL) { 00873 Cudd_IterDerefBdd(dd, e); 00874 Cudd_IterDerefBdd(dd, t); 00875 return(NULL); 00876 } 00877 r = Cudd_Not(r); 00878 } else { 00879 r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); 00880 if (r == NULL) { 00881 Cudd_IterDerefBdd(dd, e); 00882 Cudd_IterDerefBdd(dd, t); 00883 return(NULL); 00884 } 00885 } 00886 cuddDeref(t); 00887 cuddDeref(e); 00888 00889 cuddCacheInsert2(dd, Cudd_bddConstrain, f, c, r); 00890 return(Cudd_NotCond(r,comple)); 00891 00892 } /* end of cuddBddConstrainRecur */
Function********************************************************************
Synopsis [Performs the recursive steps of Cudd_bddExistAbstract.]
Description [Performs the recursive steps of Cudd_bddExistAbstract. Returns the BDD obtained by abstracting the variables of cube from f if successful; NULL otherwise. It is also used by Cudd_bddUnivAbstract.]
SideEffects [None]
SeeAlso [Cudd_bddExistAbstract Cudd_bddUnivAbstract]
Definition at line 348 of file cuddBddAbs.c.
00352 { 00353 DdNode *F, *T, *E, *res, *res1, *res2, *one; 00354 00355 statLine(manager); 00356 one = DD_ONE(manager); 00357 F = Cudd_Regular(f); 00358 00359 /* Cube is guaranteed to be a cube at this point. */ 00360 if (cube == one || F == one) { 00361 return(f); 00362 } 00363 /* From now on, f and cube are non-constant. */ 00364 00365 /* Abstract a variable that does not appear in f. */ 00366 while (manager->perm[F->index] > manager->perm[cube->index]) { 00367 cube = cuddT(cube); 00368 if (cube == one) return(f); 00369 } 00370 00371 /* Check the cache. */ 00372 if (F->ref != 1 && (res = cuddCacheLookup2(manager, Cudd_bddExistAbstract, f, cube)) != NULL) { 00373 return(res); 00374 } 00375 00376 /* Compute the cofactors of f. */ 00377 T = cuddT(F); E = cuddE(F); 00378 if (f != F) { 00379 T = Cudd_Not(T); E = Cudd_Not(E); 00380 } 00381 00382 /* If the two indices are the same, so are their levels. */ 00383 if (F->index == cube->index) { 00384 if (T == one || E == one || T == Cudd_Not(E)) { 00385 return(one); 00386 } 00387 res1 = cuddBddExistAbstractRecur(manager, T, cuddT(cube)); 00388 if (res1 == NULL) return(NULL); 00389 if (res1 == one) { 00390 if (F->ref != 1) 00391 cuddCacheInsert2(manager, Cudd_bddExistAbstract, f, cube, one); 00392 return(one); 00393 } 00394 cuddRef(res1); 00395 res2 = cuddBddExistAbstractRecur(manager, E, cuddT(cube)); 00396 if (res2 == NULL) { 00397 Cudd_IterDerefBdd(manager,res1); 00398 return(NULL); 00399 } 00400 cuddRef(res2); 00401 res = cuddBddAndRecur(manager, Cudd_Not(res1), Cudd_Not(res2)); 00402 if (res == NULL) { 00403 Cudd_IterDerefBdd(manager, res1); 00404 Cudd_IterDerefBdd(manager, res2); 00405 return(NULL); 00406 } 00407 res = Cudd_Not(res); 00408 cuddRef(res); 00409 Cudd_IterDerefBdd(manager, res1); 00410 Cudd_IterDerefBdd(manager, res2); 00411 if (F->ref != 1) 00412 cuddCacheInsert2(manager, Cudd_bddExistAbstract, f, cube, res); 00413 cuddDeref(res); 00414 return(res); 00415 } else { /* if (cuddI(manager,F->index) < cuddI(manager,cube->index)) */ 00416 res1 = cuddBddExistAbstractRecur(manager, T, cube); 00417 if (res1 == NULL) return(NULL); 00418 cuddRef(res1); 00419 res2 = cuddBddExistAbstractRecur(manager, E, cube); 00420 if (res2 == NULL) { 00421 Cudd_IterDerefBdd(manager, res1); 00422 return(NULL); 00423 } 00424 cuddRef(res2); 00425 /* ITE takes care of possible complementation of res1 and of the 00426 ** case in which res1 == res2. */ 00427 res = cuddBddIteRecur(manager, manager->vars[F->index], res1, res2); 00428 if (res == NULL) { 00429 Cudd_IterDerefBdd(manager, res1); 00430 Cudd_IterDerefBdd(manager, res2); 00431 return(NULL); 00432 } 00433 cuddDeref(res1); 00434 cuddDeref(res2); 00435 if (F->ref != 1) 00436 cuddCacheInsert2(manager, Cudd_bddExistAbstract, f, cube, res); 00437 return(res); 00438 } 00439 00440 } /* end of cuddBddExistAbstractRecur */
Function********************************************************************
Synopsis [Implements the recursive step of Cudd_bddIntersect.]
Description []
SideEffects [None]
SeeAlso [Cudd_bddIntersect]
Definition at line 767 of file cuddBddIte.c.
00771 { 00772 DdNode *res; 00773 DdNode *F, *G, *t, *e; 00774 DdNode *fv, *fnv, *gv, *gnv; 00775 DdNode *one, *zero; 00776 unsigned int index, topf, topg; 00777 00778 statLine(dd); 00779 one = DD_ONE(dd); 00780 zero = Cudd_Not(one); 00781 00782 /* Terminal cases. */ 00783 if (f == zero || g == zero || f == Cudd_Not(g)) return(zero); 00784 if (f == g || g == one) return(f); 00785 if (f == one) return(g); 00786 00787 /* At this point f and g are not constant. */ 00788 if (f > g) { DdNode *tmp = f; f = g; g = tmp; } 00789 res = cuddCacheLookup2(dd,Cudd_bddIntersect,f,g); 00790 if (res != NULL) return(res); 00791 00792 /* Find splitting variable. Here we can skip the use of cuddI, 00793 ** because the operands are known to be non-constant. 00794 */ 00795 F = Cudd_Regular(f); 00796 topf = dd->perm[F->index]; 00797 G = Cudd_Regular(g); 00798 topg = dd->perm[G->index]; 00799 00800 /* Compute cofactors. */ 00801 if (topf <= topg) { 00802 index = F->index; 00803 fv = cuddT(F); 00804 fnv = cuddE(F); 00805 if (Cudd_IsComplement(f)) { 00806 fv = Cudd_Not(fv); 00807 fnv = Cudd_Not(fnv); 00808 } 00809 } else { 00810 index = G->index; 00811 fv = fnv = f; 00812 } 00813 00814 if (topg <= topf) { 00815 gv = cuddT(G); 00816 gnv = cuddE(G); 00817 if (Cudd_IsComplement(g)) { 00818 gv = Cudd_Not(gv); 00819 gnv = Cudd_Not(gnv); 00820 } 00821 } else { 00822 gv = gnv = g; 00823 } 00824 00825 /* Compute partial results. */ 00826 t = cuddBddIntersectRecur(dd,fv,gv); 00827 if (t == NULL) return(NULL); 00828 cuddRef(t); 00829 if (t != zero) { 00830 e = zero; 00831 } else { 00832 e = cuddBddIntersectRecur(dd,fnv,gnv); 00833 if (e == NULL) { 00834 Cudd_IterDerefBdd(dd, t); 00835 return(NULL); 00836 } 00837 } 00838 cuddRef(e); 00839 00840 if (t == e) { /* both equal zero */ 00841 res = t; 00842 } else if (Cudd_IsComplement(t)) { 00843 res = cuddUniqueInter(dd,(int)index,Cudd_Not(t),Cudd_Not(e)); 00844 if (res == NULL) { 00845 Cudd_IterDerefBdd(dd, t); 00846 Cudd_IterDerefBdd(dd, e); 00847 return(NULL); 00848 } 00849 res = Cudd_Not(res); 00850 } else { 00851 res = cuddUniqueInter(dd,(int)index,t,e); 00852 if (res == NULL) { 00853 Cudd_IterDerefBdd(dd, t); 00854 Cudd_IterDerefBdd(dd, e); 00855 return(NULL); 00856 } 00857 } 00858 cuddDeref(e); 00859 cuddDeref(t); 00860 00861 cuddCacheInsert2(dd,Cudd_bddIntersect,f,g,res); 00862 00863 return(res); 00864 00865 } /* end of cuddBddIntersectRecur */
Function********************************************************************
Synopsis [Performs the recursive step of Cudd_bddIsop.]
Description []
SideEffects [None]
SeeAlso [Cudd_bddIsop]
Definition at line 571 of file cuddZddIsop.c.
00575 { 00576 DdNode *one = DD_ONE(dd); 00577 DdNode *zero = Cudd_Not(one); 00578 int v, top_l, top_u; 00579 DdNode *Lsub0, *Usub0, *Lsub1, *Usub1, *Ld, *Ud; 00580 DdNode *Lsuper0, *Usuper0, *Lsuper1, *Usuper1; 00581 DdNode *Isub0, *Isub1, *Id; 00582 DdNode *x; 00583 DdNode *term0, *term1, *sum; 00584 DdNode *Lv, *Uv, *Lnv, *Unv; 00585 DdNode *r; 00586 int index; 00587 00588 statLine(dd); 00589 if (L == zero) 00590 return(zero); 00591 if (U == one) 00592 return(one); 00593 00594 /* Check cache */ 00595 r = cuddCacheLookup2(dd, cuddBddIsop, L, U); 00596 if (r) 00597 return(r); 00598 00599 top_l = dd->perm[Cudd_Regular(L)->index]; 00600 top_u = dd->perm[Cudd_Regular(U)->index]; 00601 v = ddMin(top_l, top_u); 00602 00603 /* Compute cofactors */ 00604 if (top_l == v) { 00605 index = Cudd_Regular(L)->index; 00606 Lv = Cudd_T(L); 00607 Lnv = Cudd_E(L); 00608 if (Cudd_IsComplement(L)) { 00609 Lv = Cudd_Not(Lv); 00610 Lnv = Cudd_Not(Lnv); 00611 } 00612 } 00613 else { 00614 index = Cudd_Regular(U)->index; 00615 Lv = Lnv = L; 00616 } 00617 00618 if (top_u == v) { 00619 Uv = Cudd_T(U); 00620 Unv = Cudd_E(U); 00621 if (Cudd_IsComplement(U)) { 00622 Uv = Cudd_Not(Uv); 00623 Unv = Cudd_Not(Unv); 00624 } 00625 } 00626 else { 00627 Uv = Unv = U; 00628 } 00629 00630 Lsub0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Uv)); 00631 if (Lsub0 == NULL) 00632 return(NULL); 00633 Cudd_Ref(Lsub0); 00634 Usub0 = Unv; 00635 Lsub1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Unv)); 00636 if (Lsub1 == NULL) { 00637 Cudd_RecursiveDeref(dd, Lsub0); 00638 return(NULL); 00639 } 00640 Cudd_Ref(Lsub1); 00641 Usub1 = Uv; 00642 00643 Isub0 = cuddBddIsop(dd, Lsub0, Usub0); 00644 if (Isub0 == NULL) { 00645 Cudd_RecursiveDeref(dd, Lsub0); 00646 Cudd_RecursiveDeref(dd, Lsub1); 00647 return(NULL); 00648 } 00649 Cudd_Ref(Isub0); 00650 Isub1 = cuddBddIsop(dd, Lsub1, Usub1); 00651 if (Isub1 == NULL) { 00652 Cudd_RecursiveDeref(dd, Lsub0); 00653 Cudd_RecursiveDeref(dd, Lsub1); 00654 Cudd_RecursiveDeref(dd, Isub0); 00655 return(NULL); 00656 } 00657 Cudd_Ref(Isub1); 00658 Cudd_RecursiveDeref(dd, Lsub0); 00659 Cudd_RecursiveDeref(dd, Lsub1); 00660 00661 Lsuper0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Isub0)); 00662 if (Lsuper0 == NULL) { 00663 Cudd_RecursiveDeref(dd, Isub0); 00664 Cudd_RecursiveDeref(dd, Isub1); 00665 return(NULL); 00666 } 00667 Cudd_Ref(Lsuper0); 00668 Lsuper1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Isub1)); 00669 if (Lsuper1 == NULL) { 00670 Cudd_RecursiveDeref(dd, Isub0); 00671 Cudd_RecursiveDeref(dd, Isub1); 00672 Cudd_RecursiveDeref(dd, Lsuper0); 00673 return(NULL); 00674 } 00675 Cudd_Ref(Lsuper1); 00676 Usuper0 = Unv; 00677 Usuper1 = Uv; 00678 00679 /* Ld = Lsuper0 + Lsuper1 */ 00680 Ld = cuddBddAndRecur(dd, Cudd_Not(Lsuper0), Cudd_Not(Lsuper1)); 00681 Ld = Cudd_NotCond(Ld, Ld != NULL); 00682 if (Ld == NULL) { 00683 Cudd_RecursiveDeref(dd, Isub0); 00684 Cudd_RecursiveDeref(dd, Isub1); 00685 Cudd_RecursiveDeref(dd, Lsuper0); 00686 Cudd_RecursiveDeref(dd, Lsuper1); 00687 return(NULL); 00688 } 00689 Cudd_Ref(Ld); 00690 Ud = cuddBddAndRecur(dd, Usuper0, Usuper1); 00691 if (Ud == NULL) { 00692 Cudd_RecursiveDeref(dd, Isub0); 00693 Cudd_RecursiveDeref(dd, Isub1); 00694 Cudd_RecursiveDeref(dd, Lsuper0); 00695 Cudd_RecursiveDeref(dd, Lsuper1); 00696 Cudd_RecursiveDeref(dd, Ld); 00697 return(NULL); 00698 } 00699 Cudd_Ref(Ud); 00700 Cudd_RecursiveDeref(dd, Lsuper0); 00701 Cudd_RecursiveDeref(dd, Lsuper1); 00702 00703 Id = cuddBddIsop(dd, Ld, Ud); 00704 if (Id == NULL) { 00705 Cudd_RecursiveDeref(dd, Isub0); 00706 Cudd_RecursiveDeref(dd, Isub1); 00707 Cudd_RecursiveDeref(dd, Ld); 00708 Cudd_RecursiveDeref(dd, Ud); 00709 return(NULL); 00710 } 00711 Cudd_Ref(Id); 00712 Cudd_RecursiveDeref(dd, Ld); 00713 Cudd_RecursiveDeref(dd, Ud); 00714 00715 x = cuddUniqueInter(dd, index, one, zero); 00716 if (x == NULL) { 00717 Cudd_RecursiveDeref(dd, Isub0); 00718 Cudd_RecursiveDeref(dd, Isub1); 00719 Cudd_RecursiveDeref(dd, Id); 00720 return(NULL); 00721 } 00722 Cudd_Ref(x); 00723 term0 = cuddBddAndRecur(dd, Cudd_Not(x), Isub0); 00724 if (term0 == NULL) { 00725 Cudd_RecursiveDeref(dd, Isub0); 00726 Cudd_RecursiveDeref(dd, Isub1); 00727 Cudd_RecursiveDeref(dd, Id); 00728 Cudd_RecursiveDeref(dd, x); 00729 return(NULL); 00730 } 00731 Cudd_Ref(term0); 00732 Cudd_RecursiveDeref(dd, Isub0); 00733 term1 = cuddBddAndRecur(dd, x, Isub1); 00734 if (term1 == NULL) { 00735 Cudd_RecursiveDeref(dd, Isub1); 00736 Cudd_RecursiveDeref(dd, Id); 00737 Cudd_RecursiveDeref(dd, x); 00738 Cudd_RecursiveDeref(dd, term0); 00739 return(NULL); 00740 } 00741 Cudd_Ref(term1); 00742 Cudd_RecursiveDeref(dd, x); 00743 Cudd_RecursiveDeref(dd, Isub1); 00744 /* sum = term0 + term1 */ 00745 sum = cuddBddAndRecur(dd, Cudd_Not(term0), Cudd_Not(term1)); 00746 sum = Cudd_NotCond(sum, sum != NULL); 00747 if (sum == NULL) { 00748 Cudd_RecursiveDeref(dd, Id); 00749 Cudd_RecursiveDeref(dd, term0); 00750 Cudd_RecursiveDeref(dd, term1); 00751 return(NULL); 00752 } 00753 Cudd_Ref(sum); 00754 Cudd_RecursiveDeref(dd, term0); 00755 Cudd_RecursiveDeref(dd, term1); 00756 /* r = sum + Id */ 00757 r = cuddBddAndRecur(dd, Cudd_Not(sum), Cudd_Not(Id)); 00758 r = Cudd_NotCond(r, r != NULL); 00759 if (r == NULL) { 00760 Cudd_RecursiveDeref(dd, Id); 00761 Cudd_RecursiveDeref(dd, sum); 00762 return(NULL); 00763 } 00764 Cudd_Ref(r); 00765 Cudd_RecursiveDeref(dd, sum); 00766 Cudd_RecursiveDeref(dd, Id); 00767 00768 cuddCacheInsert2(dd, cuddBddIsop, L, U, r); 00769 00770 Cudd_Deref(r); 00771 return(r); 00772 00773 } /* end of cuddBddIsop */
Function********************************************************************
Synopsis [Implements the recursive step of Cudd_bddIte.]
Description [Implements the recursive step of Cudd_bddIte. Returns a pointer to the resulting BDD. NULL if the intermediate result blows up or if reordering occurs.]
SideEffects [None]
SeeAlso []
Definition at line 629 of file cuddBddIte.c.
00634 { 00635 DdNode *one, *zero, *res; 00636 DdNode *r, *Fv, *Fnv, *Gv, *Gnv, *H, *Hv, *Hnv, *t, *e; 00637 unsigned int topf, topg, toph, v; 00638 int index; 00639 int comple; 00640 00641 statLine(dd); 00642 /* Terminal cases. */ 00643 00644 /* One variable cases. */ 00645 if (f == (one = DD_ONE(dd))) /* ITE(1,G,H) = G */ 00646 return(g); 00647 00648 if (f == (zero = Cudd_Not(one))) /* ITE(0,G,H) = H */ 00649 return(h); 00650 00651 /* From now on, f is known not to be a constant. */ 00652 if (g == one || f == g) { /* ITE(F,F,H) = ITE(F,1,H) = F + H */ 00653 if (h == zero) { /* ITE(F,1,0) = F */ 00654 return(f); 00655 } else { 00656 res = cuddBddAndRecur(dd,Cudd_Not(f),Cudd_Not(h)); 00657 return(Cudd_NotCond(res,res != NULL)); 00658 } 00659 } else if (g == zero || f == Cudd_Not(g)) { /* ITE(F,!F,H) = ITE(F,0,H) = !F * H */ 00660 if (h == one) { /* ITE(F,0,1) = !F */ 00661 return(Cudd_Not(f)); 00662 } else { 00663 res = cuddBddAndRecur(dd,Cudd_Not(f),h); 00664 return(res); 00665 } 00666 } 00667 if (h == zero || f == h) { /* ITE(F,G,F) = ITE(F,G,0) = F * G */ 00668 res = cuddBddAndRecur(dd,f,g); 00669 return(res); 00670 } else if (h == one || f == Cudd_Not(h)) { /* ITE(F,G,!F) = ITE(F,G,1) = !F + G */ 00671 res = cuddBddAndRecur(dd,f,Cudd_Not(g)); 00672 return(Cudd_NotCond(res,res != NULL)); 00673 } 00674 00675 /* Check remaining one variable case. */ 00676 if (g == h) { /* ITE(F,G,G) = G */ 00677 return(g); 00678 } else if (g == Cudd_Not(h)) { /* ITE(F,G,!G) = F <-> G */ 00679 res = cuddBddXorRecur(dd,f,h); 00680 return(res); 00681 } 00682 00683 /* From here, there are no constants. */ 00684 comple = bddVarToCanonicalSimple(dd, &f, &g, &h, &topf, &topg, &toph); 00685 00686 /* f & g are now regular pointers */ 00687 00688 v = ddMin(topg, toph); 00689 00690 /* A shortcut: ITE(F,G,H) = (v,G,H) if F = (v,1,0), v < top(G,H). */ 00691 if (topf < v && cuddT(f) == one && cuddE(f) == zero) { 00692 r = cuddUniqueInter(dd, (int) f->index, g, h); 00693 return(Cudd_NotCond(r,comple && r != NULL)); 00694 } 00695 00696 /* Check cache. */ 00697 r = cuddCacheLookup(dd, DD_BDD_ITE_TAG, f, g, h); 00698 if (r != NULL) { 00699 return(Cudd_NotCond(r,comple)); 00700 } 00701 00702 /* Compute cofactors. */ 00703 if (topf <= v) { 00704 v = ddMin(topf, v); /* v = top_var(F,G,H) */ 00705 index = f->index; 00706 Fv = cuddT(f); Fnv = cuddE(f); 00707 } else { 00708 Fv = Fnv = f; 00709 } 00710 if (topg == v) { 00711 index = g->index; 00712 Gv = cuddT(g); Gnv = cuddE(g); 00713 } else { 00714 Gv = Gnv = g; 00715 } 00716 if (toph == v) { 00717 H = Cudd_Regular(h); 00718 index = H->index; 00719 Hv = cuddT(H); Hnv = cuddE(H); 00720 if (Cudd_IsComplement(h)) { 00721 Hv = Cudd_Not(Hv); 00722 Hnv = Cudd_Not(Hnv); 00723 } 00724 } else { 00725 Hv = Hnv = h; 00726 } 00727 00728 /* Recursive step. */ 00729 t = cuddBddIteRecur(dd,Fv,Gv,Hv); 00730 if (t == NULL) return(NULL); 00731 cuddRef(t); 00732 00733 e = cuddBddIteRecur(dd,Fnv,Gnv,Hnv); 00734 if (e == NULL) { 00735 Cudd_IterDerefBdd(dd,t); 00736 return(NULL); 00737 } 00738 cuddRef(e); 00739 00740 r = (t == e) ? t : cuddUniqueInter(dd,index,t,e); 00741 if (r == NULL) { 00742 Cudd_IterDerefBdd(dd,t); 00743 Cudd_IterDerefBdd(dd,e); 00744 return(NULL); 00745 } 00746 cuddDeref(t); 00747 cuddDeref(e); 00748 00749 cuddCacheInsert(dd, DD_BDD_ITE_TAG, f, g, h, r); 00750 return(Cudd_NotCond(r,comple)); 00751 00752 } /* end of cuddBddIteRecur */
Function********************************************************************
Synopsis [Performs safe minimization of a BDD.]
Description [Performs safe minimization of a BDD. Given the BDD f
of a function to be minimized and a BDD c
representing the care set, Cudd_bddLICompaction produces the BDD of a function that agrees with f
wherever c
is 1. Safe minimization means that the size of the result is guaranteed not to exceed the size of f
. This function is based on the DAC97 paper by Hong et al.. Returns a pointer to the result if successful; NULL otherwise.]
SideEffects [None]
SeeAlso [Cudd_bddLICompaction]
Definition at line 1430 of file cuddGenCof.c.
01434 { 01435 st_table *marktable, *markcache, *buildcache; 01436 DdNode *res, *zero; 01437 01438 zero = Cudd_Not(DD_ONE(dd)); 01439 if (c == zero) return(zero); 01440 01441 /* We need to use local caches for both steps of this operation. 01442 ** The results of the edge marking step are only valid as long as the 01443 ** edge markings themselves are available. However, the edge markings 01444 ** are lost at the end of one invocation of Cudd_bddLICompaction. 01445 ** Hence, the cache entries for the edge marking step must be 01446 ** invalidated at the end of this function. 01447 ** For the result of the building step we argue as follows. The result 01448 ** for a node and a given constrain depends on the BDD in which the node 01449 ** appears. Hence, the same node and constrain may give different results 01450 ** in successive invocations. 01451 */ 01452 marktable = st_init_table(st_ptrcmp,st_ptrhash); 01453 if (marktable == NULL) { 01454 return(NULL); 01455 } 01456 markcache = st_init_table(MarkCacheCompare,MarkCacheHash); 01457 if (markcache == NULL) { 01458 st_free_table(marktable); 01459 return(NULL); 01460 } 01461 if (cuddBddLICMarkEdges(dd,f,c,marktable,markcache) == CUDD_OUT_OF_MEM) { 01462 st_foreach(markcache, MarkCacheCleanUp, NULL); 01463 st_free_table(marktable); 01464 st_free_table(markcache); 01465 return(NULL); 01466 } 01467 st_foreach(markcache, MarkCacheCleanUp, NULL); 01468 st_free_table(markcache); 01469 buildcache = st_init_table(st_ptrcmp,st_ptrhash); 01470 if (buildcache == NULL) { 01471 st_free_table(marktable); 01472 return(NULL); 01473 } 01474 res = cuddBddLICBuildResult(dd,f,buildcache,marktable); 01475 st_free_table(buildcache); 01476 st_free_table(marktable); 01477 return(res); 01478 01479 } /* end of cuddBddLICompaction */
Function********************************************************************
Synopsis [Performs the recursive step of Cudd_bddLiteralSetIntersection.]
Description [Performs the recursive step of Cudd_bddLiteralSetIntersection. Scans the cubes for common variables, and checks whether they agree in phase. Returns a pointer to the resulting cube if successful; NULL otherwise.]
SideEffects [None]
Definition at line 149 of file cuddLiteral.c.
00153 { 00154 DdNode *res, *tmp; 00155 DdNode *F, *G; 00156 DdNode *fc, *gc; 00157 DdNode *one; 00158 DdNode *zero; 00159 unsigned int topf, topg, comple; 00160 int phasef, phaseg; 00161 00162 statLine(dd); 00163 if (f == g) return(f); 00164 00165 F = Cudd_Regular(f); 00166 G = Cudd_Regular(g); 00167 one = DD_ONE(dd); 00168 00169 /* Here f != g. If F == G, then f and g are complementary. 00170 ** Since they are two cubes, this case only occurs when f == v, 00171 ** g == v', and v is a variable or its complement. 00172 */ 00173 if (F == G) return(one); 00174 00175 zero = Cudd_Not(one); 00176 topf = cuddI(dd,F->index); 00177 topg = cuddI(dd,G->index); 00178 /* Look for a variable common to both cubes. If there are none, this 00179 ** loop will stop when the constant node is reached in both cubes. 00180 */ 00181 while (topf != topg) { 00182 if (topf < topg) { /* move down on f */ 00183 comple = f != F; 00184 f = cuddT(F); 00185 if (comple) f = Cudd_Not(f); 00186 if (f == zero) { 00187 f = cuddE(F); 00188 if (comple) f = Cudd_Not(f); 00189 } 00190 F = Cudd_Regular(f); 00191 topf = cuddI(dd,F->index); 00192 } else if (topg < topf) { 00193 comple = g != G; 00194 g = cuddT(G); 00195 if (comple) g = Cudd_Not(g); 00196 if (g == zero) { 00197 g = cuddE(G); 00198 if (comple) g = Cudd_Not(g); 00199 } 00200 G = Cudd_Regular(g); 00201 topg = cuddI(dd,G->index); 00202 } 00203 } 00204 00205 /* At this point, f == one <=> g == 1. It suffices to test one of them. */ 00206 if (f == one) return(one); 00207 00208 res = cuddCacheLookup2(dd,Cudd_bddLiteralSetIntersection,f,g); 00209 if (res != NULL) { 00210 return(res); 00211 } 00212 00213 /* Here f and g are both non constant and have the same top variable. */ 00214 comple = f != F; 00215 fc = cuddT(F); 00216 phasef = 1; 00217 if (comple) fc = Cudd_Not(fc); 00218 if (fc == zero) { 00219 fc = cuddE(F); 00220 phasef = 0; 00221 if (comple) fc = Cudd_Not(fc); 00222 } 00223 comple = g != G; 00224 gc = cuddT(G); 00225 phaseg = 1; 00226 if (comple) gc = Cudd_Not(gc); 00227 if (gc == zero) { 00228 gc = cuddE(G); 00229 phaseg = 0; 00230 if (comple) gc = Cudd_Not(gc); 00231 } 00232 00233 tmp = cuddBddLiteralSetIntersectionRecur(dd,fc,gc); 00234 if (tmp == NULL) { 00235 return(NULL); 00236 } 00237 00238 if (phasef != phaseg) { 00239 res = tmp; 00240 } else { 00241 cuddRef(tmp); 00242 if (phasef == 0) { 00243 res = cuddBddAndRecur(dd,Cudd_Not(dd->vars[F->index]),tmp); 00244 } else { 00245 res = cuddBddAndRecur(dd,dd->vars[F->index],tmp); 00246 } 00247 if (res == NULL) { 00248 Cudd_RecursiveDeref(dd,tmp); 00249 return(NULL); 00250 } 00251 cuddDeref(tmp); /* Just cuddDeref, because it is included in result */ 00252 } 00253 00254 cuddCacheInsert2(dd,Cudd_bddLiteralSetIntersection,f,g,res); 00255 00256 return(res); 00257 00258 } /* end of cuddBddLiteralSetIntersectionRecur */
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 */
Function********************************************************************
Synopsis [Implements the recursive step of Cudd_bddAnd.]
Description [Implements the recursive step of Cudd_bddNPAnd. Returns a pointer to the result is successful; NULL otherwise.]
SideEffects [None]
SeeAlso [Cudd_bddNPAnd]
Definition at line 1058 of file cuddGenCof.c.
01062 { 01063 DdNode *F, *ft, *fe, *G, *gt, *ge; 01064 DdNode *one, *r, *t, *e; 01065 unsigned int topf, topg, index; 01066 01067 statLine(manager); 01068 one = DD_ONE(manager); 01069 01070 /* Terminal cases. */ 01071 F = Cudd_Regular(f); 01072 G = Cudd_Regular(g); 01073 if (F == G) { 01074 if (f == g) return(one); 01075 else return(Cudd_Not(one)); 01076 } 01077 if (G == one) { 01078 if (g == one) return(f); 01079 else return(g); 01080 } 01081 if (F == one) { 01082 return(f); 01083 } 01084 01085 /* At this point f and g are not constant. */ 01086 /* Check cache. */ 01087 if (F->ref != 1 || G->ref != 1) { 01088 r = cuddCacheLookup2(manager, Cudd_bddNPAnd, f, g); 01089 if (r != NULL) return(r); 01090 } 01091 01092 /* Here we can skip the use of cuddI, because the operands are known 01093 ** to be non-constant. 01094 */ 01095 topf = manager->perm[F->index]; 01096 topg = manager->perm[G->index]; 01097 01098 if (topg < topf) { /* abstract top variable from g */ 01099 DdNode *d; 01100 01101 /* Find complements of cofactors of g. */ 01102 if (Cudd_IsComplement(g)) { 01103 gt = cuddT(G); 01104 ge = cuddE(G); 01105 } else { 01106 gt = Cudd_Not(cuddT(g)); 01107 ge = Cudd_Not(cuddE(g)); 01108 } 01109 /* Take the OR by applying DeMorgan. */ 01110 d = cuddBddAndRecur(manager, gt, ge); 01111 if (d == NULL) return(NULL); 01112 d = Cudd_Not(d); 01113 cuddRef(d); 01114 r = cuddBddNPAndRecur(manager, f, d); 01115 if (r == NULL) { 01116 Cudd_IterDerefBdd(manager, d); 01117 return(NULL); 01118 } 01119 cuddRef(r); 01120 Cudd_IterDerefBdd(manager, d); 01121 cuddCacheInsert2(manager, Cudd_bddNPAnd, f, g, r); 01122 cuddDeref(r); 01123 return(r); 01124 } 01125 01126 /* Compute cofactors. */ 01127 index = F->index; 01128 ft = cuddT(F); 01129 fe = cuddE(F); 01130 if (Cudd_IsComplement(f)) { 01131 ft = Cudd_Not(ft); 01132 fe = Cudd_Not(fe); 01133 } 01134 01135 if (topg == topf) { 01136 gt = cuddT(G); 01137 ge = cuddE(G); 01138 if (Cudd_IsComplement(g)) { 01139 gt = Cudd_Not(gt); 01140 ge = Cudd_Not(ge); 01141 } 01142 } else { 01143 gt = ge = g; 01144 } 01145 01146 t = cuddBddAndRecur(manager, ft, gt); 01147 if (t == NULL) return(NULL); 01148 cuddRef(t); 01149 01150 e = cuddBddAndRecur(manager, fe, ge); 01151 if (e == NULL) { 01152 Cudd_IterDerefBdd(manager, t); 01153 return(NULL); 01154 } 01155 cuddRef(e); 01156 01157 if (t == e) { 01158 r = t; 01159 } else { 01160 if (Cudd_IsComplement(t)) { 01161 r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e)); 01162 if (r == NULL) { 01163 Cudd_IterDerefBdd(manager, t); 01164 Cudd_IterDerefBdd(manager, e); 01165 return(NULL); 01166 } 01167 r = Cudd_Not(r); 01168 } else { 01169 r = cuddUniqueInter(manager,(int)index,t,e); 01170 if (r == NULL) { 01171 Cudd_IterDerefBdd(manager, t); 01172 Cudd_IterDerefBdd(manager, e); 01173 return(NULL); 01174 } 01175 } 01176 } 01177 cuddDeref(e); 01178 cuddDeref(t); 01179 if (F->ref != 1 || G->ref != 1) 01180 cuddCacheInsert2(manager, Cudd_bddNPAnd, f, g, r); 01181 return(r); 01182 01183 } /* end of cuddBddNPAndRecur */
Function********************************************************************
Synopsis [Performs the recursive step of Cudd_bddRestrict.]
Description [Performs the recursive step of Cudd_bddRestrict. Returns the restricted BDD if successful; otherwise NULL.]
SideEffects [None]
SeeAlso [Cudd_bddRestrict]
Definition at line 908 of file cuddGenCof.c.
00912 { 00913 DdNode *Fv, *Fnv, *Cv, *Cnv, *t, *e, *r, *one, *zero; 00914 unsigned int topf, topc; 00915 int index; 00916 int comple = 0; 00917 00918 statLine(dd); 00919 one = DD_ONE(dd); 00920 zero = Cudd_Not(one); 00921 00922 /* Trivial cases */ 00923 if (c == one) return(f); 00924 if (c == zero) return(zero); 00925 if (Cudd_IsConstant(f)) return(f); 00926 if (f == c) return(one); 00927 if (f == Cudd_Not(c)) return(zero); 00928 00929 /* Make canonical to increase the utilization of the cache. */ 00930 if (Cudd_IsComplement(f)) { 00931 f = Cudd_Not(f); 00932 comple = 1; 00933 } 00934 /* Now f is a regular pointer to a non-constant node; c is also 00935 ** non-constant, but may be complemented. 00936 */ 00937 00938 /* Check the cache. */ 00939 r = cuddCacheLookup2(dd, Cudd_bddRestrict, f, c); 00940 if (r != NULL) { 00941 return(Cudd_NotCond(r,comple)); 00942 } 00943 00944 topf = dd->perm[f->index]; 00945 topc = dd->perm[Cudd_Regular(c)->index]; 00946 00947 if (topc < topf) { /* abstract top variable from c */ 00948 DdNode *d, *s1, *s2; 00949 00950 /* Find complements of cofactors of c. */ 00951 if (Cudd_IsComplement(c)) { 00952 s1 = cuddT(Cudd_Regular(c)); 00953 s2 = cuddE(Cudd_Regular(c)); 00954 } else { 00955 s1 = Cudd_Not(cuddT(c)); 00956 s2 = Cudd_Not(cuddE(c)); 00957 } 00958 /* Take the OR by applying DeMorgan. */ 00959 d = cuddBddAndRecur(dd, s1, s2); 00960 if (d == NULL) return(NULL); 00961 d = Cudd_Not(d); 00962 cuddRef(d); 00963 r = cuddBddRestrictRecur(dd, f, d); 00964 if (r == NULL) { 00965 Cudd_IterDerefBdd(dd, d); 00966 return(NULL); 00967 } 00968 cuddRef(r); 00969 Cudd_IterDerefBdd(dd, d); 00970 cuddCacheInsert2(dd, Cudd_bddRestrict, f, c, r); 00971 cuddDeref(r); 00972 return(Cudd_NotCond(r,comple)); 00973 } 00974 00975 /* Recursive step. Here topf <= topc. */ 00976 index = f->index; 00977 Fv = cuddT(f); Fnv = cuddE(f); 00978 if (topc == topf) { 00979 Cv = cuddT(Cudd_Regular(c)); Cnv = cuddE(Cudd_Regular(c)); 00980 if (Cudd_IsComplement(c)) { 00981 Cv = Cudd_Not(Cv); 00982 Cnv = Cudd_Not(Cnv); 00983 } 00984 } else { 00985 Cv = Cnv = c; 00986 } 00987 00988 if (!Cudd_IsConstant(Cv)) { 00989 t = cuddBddRestrictRecur(dd, Fv, Cv); 00990 if (t == NULL) return(NULL); 00991 } else if (Cv == one) { 00992 t = Fv; 00993 } else { /* Cv == zero: return(Fnv @ Cnv) */ 00994 if (Cnv == one) { 00995 r = Fnv; 00996 } else { 00997 r = cuddBddRestrictRecur(dd, Fnv, Cnv); 00998 if (r == NULL) return(NULL); 00999 } 01000 return(Cudd_NotCond(r,comple)); 01001 } 01002 cuddRef(t); 01003 01004 if (!Cudd_IsConstant(Cnv)) { 01005 e = cuddBddRestrictRecur(dd, Fnv, Cnv); 01006 if (e == NULL) { 01007 Cudd_IterDerefBdd(dd, t); 01008 return(NULL); 01009 } 01010 } else if (Cnv == one) { 01011 e = Fnv; 01012 } else { /* Cnv == zero: return (Fv @ Cv) previously computed */ 01013 cuddDeref(t); 01014 return(Cudd_NotCond(t,comple)); 01015 } 01016 cuddRef(e); 01017 01018 if (Cudd_IsComplement(t)) { 01019 t = Cudd_Not(t); 01020 e = Cudd_Not(e); 01021 r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); 01022 if (r == NULL) { 01023 Cudd_IterDerefBdd(dd, e); 01024 Cudd_IterDerefBdd(dd, t); 01025 return(NULL); 01026 } 01027 r = Cudd_Not(r); 01028 } else { 01029 r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); 01030 if (r == NULL) { 01031 Cudd_IterDerefBdd(dd, e); 01032 Cudd_IterDerefBdd(dd, t); 01033 return(NULL); 01034 } 01035 } 01036 cuddDeref(t); 01037 cuddDeref(e); 01038 01039 cuddCacheInsert2(dd, Cudd_bddRestrict, f, c, r); 01040 return(Cudd_NotCond(r,comple)); 01041 01042 } /* end of cuddBddRestrictRecur */
Function********************************************************************
Synopsis [Convert a BDD from a manager to another one.]
Description [Convert a BDD from a manager to another one. Returns a pointer to the BDD in the destination manager if successful; NULL otherwise.]
SideEffects [None]
SeeAlso [Cudd_bddTransfer]
Definition at line 439 of file cuddBridge.c.
00443 { 00444 DdNode *res; 00445 st_table *table = NULL; 00446 st_generator *gen = NULL; 00447 DdNode *key, *value; 00448 00449 table = st_init_table(st_ptrcmp,st_ptrhash); 00450 if (table == NULL) goto failure; 00451 res = cuddBddTransferRecur(ddS, ddD, f, table); 00452 if (res != NULL) cuddRef(res); 00453 00454 /* Dereference all elements in the table and dispose of the table. 00455 ** This must be done also if res is NULL to avoid leaks in case of 00456 ** reordering. */ 00457 gen = st_init_gen(table); 00458 if (gen == NULL) goto failure; 00459 while (st_gen(gen, &key, &value)) { 00460 Cudd_RecursiveDeref(ddD, value); 00461 } 00462 st_free_gen(gen); gen = NULL; 00463 st_free_table(table); table = NULL; 00464 00465 if (res != NULL) cuddDeref(res); 00466 return(res); 00467 00468 failure: 00469 /* No need to free gen because it is always NULL here. */ 00470 if (table != NULL) st_free_table(table); 00471 return(NULL); 00472 00473 } /* end of cuddBddTransfer */
Function********************************************************************
Synopsis [Takes the exclusive OR of two BDDs and simultaneously abstracts the variables in cube.]
Description [Takes the exclusive OR of two BDDs and simultaneously abstracts the variables in cube. The variables are existentially abstracted. Returns a pointer to the result is successful; NULL otherwise.]
SideEffects [None]
SeeAlso [Cudd_bddAndAbstract]
Definition at line 458 of file cuddBddAbs.c.
00463 { 00464 DdNode *F, *fv, *fnv, *G, *gv, *gnv; 00465 DdNode *one, *zero, *r, *t, *e, *Cube; 00466 unsigned int topf, topg, topcube, top, index; 00467 00468 statLine(manager); 00469 one = DD_ONE(manager); 00470 zero = Cudd_Not(one); 00471 00472 /* Terminal cases. */ 00473 if (f == g) { 00474 return(zero); 00475 } 00476 if (f == Cudd_Not(g)) { 00477 return(one); 00478 } 00479 if (cube == one) { 00480 return(cuddBddXorRecur(manager, f, g)); 00481 } 00482 if (f == one) { 00483 return(cuddBddExistAbstractRecur(manager, Cudd_Not(g), cube)); 00484 } 00485 if (g == one) { 00486 return(cuddBddExistAbstractRecur(manager, Cudd_Not(f), cube)); 00487 } 00488 if (f == zero) { 00489 return(cuddBddExistAbstractRecur(manager, g, cube)); 00490 } 00491 if (g == zero) { 00492 return(cuddBddExistAbstractRecur(manager, f, cube)); 00493 } 00494 00495 /* At this point f, g, and cube are not constant. */ 00496 00497 if (f > g) { /* Try to increase cache efficiency. */ 00498 DdNode *tmp = f; 00499 f = g; 00500 g = tmp; 00501 } 00502 00503 /* Check cache. */ 00504 r = cuddCacheLookup(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube); 00505 if (r != NULL) { 00506 return(r); 00507 } 00508 00509 /* Here we can skip the use of cuddI, because the operands are known 00510 ** to be non-constant. 00511 */ 00512 F = Cudd_Regular(f); 00513 topf = manager->perm[F->index]; 00514 G = Cudd_Regular(g); 00515 topg = manager->perm[G->index]; 00516 top = ddMin(topf, topg); 00517 topcube = manager->perm[cube->index]; 00518 00519 if (topcube < top) { 00520 return(cuddBddXorExistAbstractRecur(manager, f, g, cuddT(cube))); 00521 } 00522 /* Now, topcube >= top. */ 00523 00524 if (topf == top) { 00525 index = F->index; 00526 fv = cuddT(F); 00527 fnv = cuddE(F); 00528 if (Cudd_IsComplement(f)) { 00529 fv = Cudd_Not(fv); 00530 fnv = Cudd_Not(fnv); 00531 } 00532 } else { 00533 index = G->index; 00534 fv = fnv = f; 00535 } 00536 00537 if (topg == top) { 00538 gv = cuddT(G); 00539 gnv = cuddE(G); 00540 if (Cudd_IsComplement(g)) { 00541 gv = Cudd_Not(gv); 00542 gnv = Cudd_Not(gnv); 00543 } 00544 } else { 00545 gv = gnv = g; 00546 } 00547 00548 if (topcube == top) { 00549 Cube = cuddT(cube); 00550 } else { 00551 Cube = cube; 00552 } 00553 00554 t = cuddBddXorExistAbstractRecur(manager, fv, gv, Cube); 00555 if (t == NULL) return(NULL); 00556 00557 /* Special case: 1 OR anything = 1. Hence, no need to compute 00558 ** the else branch if t is 1. 00559 */ 00560 if (t == one && topcube == top) { 00561 cuddCacheInsert(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube, one); 00562 return(one); 00563 } 00564 cuddRef(t); 00565 00566 e = cuddBddXorExistAbstractRecur(manager, fnv, gnv, Cube); 00567 if (e == NULL) { 00568 Cudd_IterDerefBdd(manager, t); 00569 return(NULL); 00570 } 00571 cuddRef(e); 00572 00573 if (topcube == top) { /* abstract */ 00574 r = cuddBddAndRecur(manager, Cudd_Not(t), Cudd_Not(e)); 00575 if (r == NULL) { 00576 Cudd_IterDerefBdd(manager, t); 00577 Cudd_IterDerefBdd(manager, e); 00578 return(NULL); 00579 } 00580 r = Cudd_Not(r); 00581 cuddRef(r); 00582 Cudd_IterDerefBdd(manager, t); 00583 Cudd_IterDerefBdd(manager, e); 00584 cuddDeref(r); 00585 } else if (t == e) { 00586 r = t; 00587 cuddDeref(t); 00588 cuddDeref(e); 00589 } else { 00590 if (Cudd_IsComplement(t)) { 00591 r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e)); 00592 if (r == NULL) { 00593 Cudd_IterDerefBdd(manager, t); 00594 Cudd_IterDerefBdd(manager, e); 00595 return(NULL); 00596 } 00597 r = Cudd_Not(r); 00598 } else { 00599 r = cuddUniqueInter(manager,(int)index,t,e); 00600 if (r == NULL) { 00601 Cudd_IterDerefBdd(manager, t); 00602 Cudd_IterDerefBdd(manager, e); 00603 return(NULL); 00604 } 00605 } 00606 cuddDeref(e); 00607 cuddDeref(t); 00608 } 00609 cuddCacheInsert(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube, r); 00610 return (r); 00611 00612 } /* end of cuddBddXorExistAbstractRecur */
Function********************************************************************
Synopsis [Implements the recursive step of Cudd_bddXor.]
Description [Implements the recursive step of Cudd_bddXor by taking the exclusive OR of two BDDs. Returns a pointer to the result is successful; NULL otherwise.]
SideEffects [None]
SeeAlso [Cudd_bddXor]
Definition at line 1010 of file cuddBddIte.c.
01014 { 01015 DdNode *fv, *fnv, *G, *gv, *gnv; 01016 DdNode *one, *zero, *r, *t, *e; 01017 unsigned int topf, topg, index; 01018 01019 statLine(manager); 01020 one = DD_ONE(manager); 01021 zero = Cudd_Not(one); 01022 01023 /* Terminal cases. */ 01024 if (f == g) return(zero); 01025 if (f == Cudd_Not(g)) return(one); 01026 if (f > g) { /* Try to increase cache efficiency and simplify tests. */ 01027 DdNode *tmp = f; 01028 f = g; 01029 g = tmp; 01030 } 01031 if (g == zero) return(f); 01032 if (g == one) return(Cudd_Not(f)); 01033 if (Cudd_IsComplement(f)) { 01034 f = Cudd_Not(f); 01035 g = Cudd_Not(g); 01036 } 01037 /* Now the first argument is regular. */ 01038 if (f == one) return(Cudd_Not(g)); 01039 01040 /* At this point f and g are not constant. */ 01041 01042 /* Check cache. */ 01043 r = cuddCacheLookup2(manager, Cudd_bddXor, f, g); 01044 if (r != NULL) return(r); 01045 01046 /* Here we can skip the use of cuddI, because the operands are known 01047 ** to be non-constant. 01048 */ 01049 topf = manager->perm[f->index]; 01050 G = Cudd_Regular(g); 01051 topg = manager->perm[G->index]; 01052 01053 /* Compute cofactors. */ 01054 if (topf <= topg) { 01055 index = f->index; 01056 fv = cuddT(f); 01057 fnv = cuddE(f); 01058 } else { 01059 index = G->index; 01060 fv = fnv = f; 01061 } 01062 01063 if (topg <= topf) { 01064 gv = cuddT(G); 01065 gnv = cuddE(G); 01066 if (Cudd_IsComplement(g)) { 01067 gv = Cudd_Not(gv); 01068 gnv = Cudd_Not(gnv); 01069 } 01070 } else { 01071 gv = gnv = g; 01072 } 01073 01074 t = cuddBddXorRecur(manager, fv, gv); 01075 if (t == NULL) return(NULL); 01076 cuddRef(t); 01077 01078 e = cuddBddXorRecur(manager, fnv, gnv); 01079 if (e == NULL) { 01080 Cudd_IterDerefBdd(manager, t); 01081 return(NULL); 01082 } 01083 cuddRef(e); 01084 01085 if (t == e) { 01086 r = t; 01087 } else { 01088 if (Cudd_IsComplement(t)) { 01089 r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e)); 01090 if (r == NULL) { 01091 Cudd_IterDerefBdd(manager, t); 01092 Cudd_IterDerefBdd(manager, e); 01093 return(NULL); 01094 } 01095 r = Cudd_Not(r); 01096 } else { 01097 r = cuddUniqueInter(manager,(int)index,t,e); 01098 if (r == NULL) { 01099 Cudd_IterDerefBdd(manager, t); 01100 Cudd_IterDerefBdd(manager, e); 01101 return(NULL); 01102 } 01103 } 01104 } 01105 cuddDeref(e); 01106 cuddDeref(t); 01107 cuddCacheInsert2(manager, Cudd_bddXor, f, g, r); 01108 return(r); 01109 01110 } /* end of cuddBddXorRecur */
DdNode* cuddBiasedUnderApprox | ( | DdManager * | dd, | |
DdNode * | f, | |||
DdNode * | b, | |||
int | numVars, | |||
int | threshold, | |||
double | quality1, | |||
double | quality0 | |||
) |
Function********************************************************************
Synopsis [Applies the biased remapping underappoximation algorithm.]
Description [Applies the biased remapping underappoximation algorithm. Proceeds in three phases:
Returns the approximated BDD if successful; NULL otherwise.]
SideEffects [None]
SeeAlso [Cudd_BiasedUnderApprox]
Definition at line 687 of file cuddApprox.c.
00695 { 00696 ApproxInfo *info; 00697 DdNode *subset; 00698 int result; 00699 DdHashTable *cache; 00700 00701 if (f == NULL) { 00702 fprintf(dd->err, "Cannot subset, nil object\n"); 00703 dd->errorCode = CUDD_INVALID_ARG; 00704 return(NULL); 00705 } 00706 00707 if (Cudd_IsConstant(f)) { 00708 return(f); 00709 } 00710 00711 /* Create table where node data are accessible via a hash table. */ 00712 info = gatherInfo(dd, f, numVars, TRUE); 00713 if (info == NULL) { 00714 (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); 00715 dd->errorCode = CUDD_MEMORY_OUT; 00716 return(NULL); 00717 } 00718 00719 cache = cuddHashTableInit(dd,2,2); 00720 result = BAapplyBias(dd, Cudd_Regular(f), b, info, cache); 00721 if (result == CARE_ERROR) { 00722 (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); 00723 cuddHashTableQuit(cache); 00724 FREE(info->page); 00725 st_free_table(info->table); 00726 FREE(info); 00727 dd->errorCode = CUDD_MEMORY_OUT; 00728 return(NULL); 00729 } 00730 cuddHashTableQuit(cache); 00731 00732 /* Mark nodes that should be replaced by zero. */ 00733 result = BAmarkNodes(dd, f, info, threshold, quality1, quality0); 00734 if (result == 0) { 00735 (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); 00736 FREE(info->page); 00737 st_free_table(info->table); 00738 FREE(info); 00739 dd->errorCode = CUDD_MEMORY_OUT; 00740 return(NULL); 00741 } 00742 00743 /* Build the result. */ 00744 subset = RAbuildSubset(dd, f, info); 00745 #if 1 00746 if (subset && info->size < Cudd_DagSize(subset)) 00747 (void) fprintf(dd->err, "Wrong prediction: %d versus actual %d\n", 00748 info->size, Cudd_DagSize(subset)); 00749 #endif 00750 FREE(info->page); 00751 st_free_table(info->table); 00752 FREE(info); 00753 00754 #ifdef DD_DEBUG 00755 if (subset != NULL) { 00756 cuddRef(subset); 00757 #if 0 00758 (void) Cudd_DebugCheck(dd); 00759 (void) Cudd_CheckKeys(dd); 00760 #endif 00761 if (!Cudd_bddLeq(dd, subset, f)) { 00762 (void) fprintf(dd->err, "Wrong subset\n"); 00763 } 00764 cuddDeref(subset); 00765 dd->errorCode = CUDD_INTERNAL_ERROR; 00766 } 00767 #endif 00768 return(subset); 00769 00770 } /* end of cuddBiasedUnderApprox */
void cuddCacheFlush | ( | DdManager * | table | ) |
Function********************************************************************
Synopsis [Flushes the cache.]
Description []
SideEffects [None]
SeeAlso []
Definition at line 1001 of file cuddCache.c.
01003 { 01004 int i, slots; 01005 DdCache *cache; 01006 01007 slots = table->cacheSlots; 01008 cache = table->cache; 01009 for (i = 0; i < slots; i++) { 01010 table->cachedeletions += cache[i].data != NULL; 01011 cache[i].data = NULL; 01012 } 01013 table->cacheLastInserts = table->cacheinserts; 01014 01015 return; 01016 01017 } /* end of cuddCacheFlush */
void cuddCacheInsert | ( | DdManager * | table, | |
ptruint | op, | |||
DdNode * | f, | |||
DdNode * | g, | |||
DdNode * | h, | |||
DdNode * | data | |||
) |
Function********************************************************************
Synopsis [Inserts a result in the cache.]
Description []
SideEffects [None]
SeeAlso [cuddCacheInsert2 cuddCacheInsert1]
Definition at line 214 of file cuddCache.c.
00221 { 00222 int posn; 00223 register DdCache *entry; 00224 ptruint uf, ug, uh; 00225 00226 uf = (ptruint) f | (op & 0xe); 00227 ug = (ptruint) g | (op >> 4); 00228 uh = (ptruint) h; 00229 00230 posn = ddCHash2(uh,uf,ug,table->cacheShift); 00231 entry = &table->cache[posn]; 00232 00233 table->cachecollisions += entry->data != NULL; 00234 table->cacheinserts++; 00235 00236 entry->f = (DdNode *) uf; 00237 entry->g = (DdNode *) ug; 00238 entry->h = uh; 00239 entry->data = data; 00240 #ifdef DD_CACHE_PROFILE 00241 entry->count++; 00242 #endif 00243 00244 } /* end of cuddCacheInsert */
void cuddCacheInsert1 | ( | DdManager * | table, | |
DdNode * | *)(DdManager *, DdNode *, | |||
DdNode * | f, | |||
DdNode * | data | |||
) |
void cuddCacheInsert2 | ( | DdManager * | table, | |
DdNode * | *)(DdManager *, DdNode *, DdNode *, | |||
DdNode * | f, | |||
DdNode * | g, | |||
DdNode * | data | |||
) |
Function********************************************************************
Synopsis [Looks up in the cache for the result of op applied to f, g, and h.]
Description [Returns the result if found; it returns NULL if no result is found.]
SideEffects [None]
SeeAlso [cuddCacheLookup2 cuddCacheLookup1]
Definition at line 344 of file cuddCache.c.
00350 { 00351 int posn; 00352 DdCache *en,*cache; 00353 DdNode *data; 00354 ptruint uf, ug, uh; 00355 00356 uf = (ptruint) f | (op & 0xe); 00357 ug = (ptruint) g | (op >> 4); 00358 uh = (ptruint) h; 00359 00360 cache = table->cache; 00361 #ifdef DD_DEBUG 00362 if (cache == NULL) { 00363 return(NULL); 00364 } 00365 #endif 00366 00367 posn = ddCHash2(uh,uf,ug,table->cacheShift); 00368 en = &cache[posn]; 00369 if (en->data != NULL && en->f==(DdNodePtr)uf && en->g==(DdNodePtr)ug && 00370 en->h==uh) { 00371 data = Cudd_Regular(en->data); 00372 table->cacheHits++; 00373 if (data->ref == 0) { 00374 cuddReclaim(table,data); 00375 } 00376 return(en->data); 00377 } 00378 00379 /* Cache miss: decide whether to resize. */ 00380 table->cacheMisses++; 00381 00382 if (table->cacheSlack >= 0 && 00383 table->cacheHits > table->cacheMisses * table->minHit) { 00384 cuddCacheResize(table); 00385 } 00386 00387 return(NULL); 00388 00389 } /* end of cuddCacheLookup */
DdNode* cuddCacheLookup2 | ( | DdManager * | table, | |
DdNode * | *)(DdManager *, DdNode *, DdNode *, | |||
DdNode * | f, | |||
DdNode * | g | |||
) |
DdNode* cuddCacheLookup2Zdd | ( | DdManager * | table, | |
DdNode * | *)(DdManager *, DdNode *, DdNode *, | |||
DdNode * | f, | |||
DdNode * | g | |||
) |
Function********************************************************************
Synopsis [Looks up in the cache for the result of op applied to f, g, and h.]
Description [Returns the result if found; it returns NULL if no result is found.]
SideEffects [None]
SeeAlso [cuddCacheLookup2Zdd cuddCacheLookup1Zdd]
Definition at line 406 of file cuddCache.c.
00412 { 00413 int posn; 00414 DdCache *en,*cache; 00415 DdNode *data; 00416 ptruint uf, ug, uh; 00417 00418 uf = (ptruint) f | (op & 0xe); 00419 ug = (ptruint) g | (op >> 4); 00420 uh = (ptruint) h; 00421 00422 cache = table->cache; 00423 #ifdef DD_DEBUG 00424 if (cache == NULL) { 00425 return(NULL); 00426 } 00427 #endif 00428 00429 posn = ddCHash2(uh,uf,ug,table->cacheShift); 00430 en = &cache[posn]; 00431 if (en->data != NULL && en->f==(DdNodePtr)uf && en->g==(DdNodePtr)ug && 00432 en->h==uh) { 00433 data = Cudd_Regular(en->data); 00434 table->cacheHits++; 00435 if (data->ref == 0) { 00436 cuddReclaimZdd(table,data); 00437 } 00438 return(en->data); 00439 } 00440 00441 /* Cache miss: decide whether to resize. */ 00442 table->cacheMisses++; 00443 00444 if (table->cacheSlack >= 0 && 00445 table->cacheHits > table->cacheMisses * table->minHit) { 00446 cuddCacheResize(table); 00447 } 00448 00449 return(NULL); 00450 00451 } /* end of cuddCacheLookupZdd */
int cuddCacheProfile | ( | DdManager * | table, | |
FILE * | fp | |||
) |
Function********************************************************************
Synopsis [Computes and prints a profile of the cache usage.]
Description [Computes and prints a profile of the cache usage. Returns 1 if successful; 0 otherwise.]
SideEffects [None]
SeeAlso []
Definition at line 746 of file cuddCache.c.
00749 { 00750 DdCache *cache = table->cache; 00751 int slots = table->cacheSlots; 00752 int nzeroes = 0; 00753 int i, retval; 00754 double exUsed; 00755 00756 #ifdef DD_CACHE_PROFILE 00757 double count, mean, meansq, stddev, expected; 00758 long max, min; 00759 int imax, imin; 00760 double *hystogramQ, *hystogramR; /* histograms by quotient and remainder */ 00761 int nbins = DD_HYSTO_BINS; 00762 int bin; 00763 long thiscount; 00764 double totalcount, exStddev; 00765 00766 meansq = mean = expected = 0.0; 00767 max = min = (long) cache[0].count; 00768 imax = imin = 0; 00769 totalcount = 0.0; 00770 00771 hystogramQ = ALLOC(double, nbins); 00772 if (hystogramQ == NULL) { 00773 table->errorCode = CUDD_MEMORY_OUT; 00774 return(0); 00775 } 00776 hystogramR = ALLOC(double, nbins); 00777 if (hystogramR == NULL) { 00778 FREE(hystogramQ); 00779 table->errorCode = CUDD_MEMORY_OUT; 00780 return(0); 00781 } 00782 for (i = 0; i < nbins; i++) { 00783 hystogramQ[i] = 0; 00784 hystogramR[i] = 0; 00785 } 00786 00787 for (i = 0; i < slots; i++) { 00788 thiscount = (long) cache[i].count; 00789 if (thiscount > max) { 00790 max = thiscount; 00791 imax = i; 00792 } 00793 if (thiscount < min) { 00794 min = thiscount; 00795 imin = i; 00796 } 00797 if (thiscount == 0) { 00798 nzeroes++; 00799 } 00800 count = (double) thiscount; 00801 mean += count; 00802 meansq += count * count; 00803 totalcount += count; 00804 expected += count * (double) i; 00805 bin = (i * nbins) / slots; 00806 hystogramQ[bin] += (double) thiscount; 00807 bin = i % nbins; 00808 hystogramR[bin] += (double) thiscount; 00809 } 00810 mean /= (double) slots; 00811 meansq /= (double) slots; 00812 00813 /* Compute the standard deviation from both the data and the 00814 ** theoretical model for a random distribution. */ 00815 stddev = sqrt(meansq - mean*mean); 00816 exStddev = sqrt((1 - 1/(double) slots) * totalcount / (double) slots); 00817 00818 retval = fprintf(fp,"Cache average accesses = %g\n", mean); 00819 if (retval == EOF) return(0); 00820 retval = fprintf(fp,"Cache access standard deviation = %g ", stddev); 00821 if (retval == EOF) return(0); 00822 retval = fprintf(fp,"(expected = %g)\n", exStddev); 00823 if (retval == EOF) return(0); 00824 retval = fprintf(fp,"Cache max accesses = %ld for slot %d\n", max, imax); 00825 if (retval == EOF) return(0); 00826 retval = fprintf(fp,"Cache min accesses = %ld for slot %d\n", min, imin); 00827 if (retval == EOF) return(0); 00828 exUsed = 100.0 * (1.0 - exp(-totalcount / (double) slots)); 00829 retval = fprintf(fp,"Cache used slots = %.2f%% (expected %.2f%%)\n", 00830 100.0 - (double) nzeroes * 100.0 / (double) slots, 00831 exUsed); 00832 if (retval == EOF) return(0); 00833 00834 if (totalcount > 0) { 00835 expected /= totalcount; 00836 retval = fprintf(fp,"Cache access hystogram for %d bins", nbins); 00837 if (retval == EOF) return(0); 00838 retval = fprintf(fp," (expected bin value = %g)\nBy quotient:", 00839 expected); 00840 if (retval == EOF) return(0); 00841 for (i = nbins - 1; i>=0; i--) { 00842 retval = fprintf(fp," %.0f", hystogramQ[i]); 00843 if (retval == EOF) return(0); 00844 } 00845 retval = fprintf(fp,"\nBy residue: "); 00846 if (retval == EOF) return(0); 00847 for (i = nbins - 1; i>=0; i--) { 00848 retval = fprintf(fp," %.0f", hystogramR[i]); 00849 if (retval == EOF) return(0); 00850 } 00851 retval = fprintf(fp,"\n"); 00852 if (retval == EOF) return(0); 00853 } 00854 00855 FREE(hystogramQ); 00856 FREE(hystogramR); 00857 #else 00858 for (i = 0; i < slots; i++) { 00859 nzeroes += cache[i].h == 0; 00860 } 00861 exUsed = 100.0 * 00862 (1.0 - exp(-(table->cacheinserts - table->cacheLastInserts) / 00863 (double) slots)); 00864 retval = fprintf(fp,"Cache used slots = %.2f%% (expected %.2f%%)\n", 00865 100.0 - (double) nzeroes * 100.0 / (double) slots, 00866 exUsed); 00867 if (retval == EOF) return(0); 00868 #endif 00869 return(1); 00870 00871 } /* end of cuddCacheProfile */
void cuddCacheResize | ( | DdManager * | table | ) |
Function********************************************************************
Synopsis [Resizes the cache.]
Description []
SideEffects [None]
SeeAlso []
Definition at line 886 of file cuddCache.c.
00888 { 00889 DdCache *cache, *oldcache, *oldacache, *entry, *old; 00890 int i; 00891 int posn, shift; 00892 unsigned int slots, oldslots; 00893 double offset; 00894 int moved = 0; 00895 extern DD_OOMFP MMoutOfMemory; 00896 DD_OOMFP saveHandler; 00897 #ifndef DD_CACHE_PROFILE 00898 ptruint misalignment; 00899 DdNodePtr *mem; 00900 #endif 00901 00902 oldcache = table->cache; 00903 oldacache = table->acache; 00904 oldslots = table->cacheSlots; 00905 slots = table->cacheSlots = oldslots << 1; 00906 00907 #ifdef DD_VERBOSE 00908 (void) fprintf(table->err,"Resizing the cache from %d to %d entries\n", 00909 oldslots, slots); 00910 (void) fprintf(table->err, 00911 "\thits = %g\tmisses = %g\thit ratio = %5.3f\n", 00912 table->cacheHits, table->cacheMisses, 00913 table->cacheHits / (table->cacheHits + table->cacheMisses)); 00914 #endif 00915 00916 saveHandler = MMoutOfMemory; 00917 MMoutOfMemory = Cudd_OutOfMem; 00918 table->acache = cache = ALLOC(DdCache,slots+1); 00919 MMoutOfMemory = saveHandler; 00920 /* If we fail to allocate the new table we just give up. */ 00921 if (cache == NULL) { 00922 #ifdef DD_VERBOSE 00923 (void) fprintf(table->err,"Resizing failed. Giving up.\n"); 00924 #endif 00925 table->cacheSlots = oldslots; 00926 table->acache = oldacache; 00927 /* Do not try to resize again. */ 00928 table->maxCacheHard = oldslots - 1; 00929 table->cacheSlack = - (int) (oldslots + 1); 00930 return; 00931 } 00932 /* If the size of the cache entry is a power of 2, we want to 00933 ** enforce alignment to that power of two. This happens when 00934 ** DD_CACHE_PROFILE is not defined. */ 00935 #ifdef DD_CACHE_PROFILE 00936 table->cache = cache; 00937 #else 00938 mem = (DdNodePtr *) cache; 00939 misalignment = (ptruint) mem & (sizeof(DdCache) - 1); 00940 mem += (sizeof(DdCache) - misalignment) / sizeof(DdNodePtr); 00941 table->cache = cache = (DdCache *) mem; 00942 assert(((ptruint) table->cache & (sizeof(DdCache) - 1)) == 0); 00943 #endif 00944 shift = --(table->cacheShift); 00945 table->memused += (slots - oldslots) * sizeof(DdCache); 00946 table->cacheSlack -= slots; /* need these many slots to double again */ 00947 00948 /* Clear new cache. */ 00949 for (i = 0; (unsigned) i < slots; i++) { 00950 cache[i].data = NULL; 00951 cache[i].h = 0; 00952 #ifdef DD_CACHE_PROFILE 00953 cache[i].count = 0; 00954 #endif 00955 } 00956 00957 /* Copy from old cache to new one. */ 00958 for (i = 0; (unsigned) i < oldslots; i++) { 00959 old = &oldcache[i]; 00960 if (old->data != NULL) { 00961 posn = ddCHash2(old->h,old->f,old->g,shift); 00962 entry = &cache[posn]; 00963 entry->f = old->f; 00964 entry->g = old->g; 00965 entry->h = old->h; 00966 entry->data = old->data; 00967 #ifdef DD_CACHE_PROFILE 00968 entry->count = 1; 00969 #endif 00970 moved++; 00971 } 00972 } 00973 00974 FREE(oldacache); 00975 00976 /* Reinitialize measurements so as to avoid division by 0 and 00977 ** immediate resizing. 00978 */ 00979 offset = (double) (int) (slots * table->minHit + 1); 00980 table->totCacheMisses += table->cacheMisses - offset; 00981 table->cacheMisses = offset; 00982 table->totCachehits += table->cacheHits; 00983 table->cacheHits = 0; 00984 table->cacheLastInserts = table->cacheinserts - (double) moved; 00985 00986 } /* end of cuddCacheResize */
Function********************************************************************
Synopsis [Checks whether g is the BDD of a cube.]
Description [Checks whether g is the BDD of a cube. Returns 1 in case of success; 0 otherwise. The constant 1 is a valid cube, but all other constant functions cause cuddCheckCube to return 0.]
SideEffects [None]
SeeAlso []
Definition at line 189 of file cuddCof.c.
00192 { 00193 DdNode *g1,*g0,*one,*zero; 00194 00195 one = DD_ONE(dd); 00196 if (g == one) return(1); 00197 if (Cudd_IsConstant(g)) return(0); 00198 00199 zero = Cudd_Not(one); 00200 cuddGetBranches(g,&g1,&g0); 00201 00202 if (g0 == zero) { 00203 return(cuddCheckCube(dd, g1)); 00204 } 00205 if (g1 == zero) { 00206 return(cuddCheckCube(dd, g0)); 00207 } 00208 return(0); 00209 00210 } /* end of cuddCheckCube */
void cuddClearDeathRow | ( | DdManager * | table | ) |
Function********************************************************************
Synopsis [Clears the death row.]
Description []
SideEffects [None]
SeeAlso [Cudd_DelayedDerefBdd Cudd_IterDerefBdd Cudd_CheckZeroRef cuddGarbageCollect]
Definition at line 722 of file cuddRef.c.
00724 { 00725 #ifndef DD_NO_DEATH_ROW 00726 int i; 00727 00728 for (i = 0; i < table->deathRowDepth; i++) { 00729 if (table->deathRow[i] == NULL) break; 00730 Cudd_IterDerefBdd(table,table->deathRow[i]); 00731 table->deathRow[i] = NULL; 00732 } 00733 #ifdef DD_DEBUG 00734 for (; i < table->deathRowDepth; i++) { 00735 assert(table->deathRow[i] == NULL); 00736 } 00737 #endif 00738 table->nextDead = 0; 00739 #endif 00740 00741 } /* end of cuddClearDeathRow */
Function********************************************************************
Synopsis [Performs the recursive step of Cudd_Cofactor.]
Description [Performs the recursive step of Cudd_Cofactor. Returns a pointer to the cofactor if successful; NULL otherwise.]
SideEffects [None]
SeeAlso [Cudd_Cofactor]
Definition at line 226 of file cuddCof.c.
00230 { 00231 DdNode *one,*zero,*F,*G,*g1,*g0,*f1,*f0,*t,*e,*r; 00232 unsigned int topf,topg; 00233 int comple; 00234 00235 statLine(dd); 00236 F = Cudd_Regular(f); 00237 if (cuddIsConstant(F)) return(f); 00238 00239 one = DD_ONE(dd); 00240 00241 /* The invariant g != 0 is true on entry to this procedure and is 00242 ** recursively maintained by it. Therefore it suffices to test g 00243 ** against one to make sure it is not constant. 00244 */ 00245 if (g == one) return(f); 00246 /* From now on, f and g are known not to be constants. */ 00247 00248 comple = f != F; 00249 r = cuddCacheLookup2(dd,Cudd_Cofactor,F,g); 00250 if (r != NULL) { 00251 return(Cudd_NotCond(r,comple)); 00252 } 00253 00254 topf = dd->perm[F->index]; 00255 G = Cudd_Regular(g); 00256 topg = dd->perm[G->index]; 00257 00258 /* We take the cofactors of F because we are going to rely on 00259 ** the fact that the cofactors of the complement are the complements 00260 ** of the cofactors to better utilize the cache. Variable comple 00261 ** remembers whether we have to complement the result or not. 00262 */ 00263 if (topf <= topg) { 00264 f1 = cuddT(F); f0 = cuddE(F); 00265 } else { 00266 f1 = f0 = F; 00267 } 00268 if (topg <= topf) { 00269 g1 = cuddT(G); g0 = cuddE(G); 00270 if (g != G) { g1 = Cudd_Not(g1); g0 = Cudd_Not(g0); } 00271 } else { 00272 g1 = g0 = g; 00273 } 00274 00275 zero = Cudd_Not(one); 00276 if (topf >= topg) { 00277 if (g0 == zero || g0 == DD_ZERO(dd)) { 00278 r = cuddCofactorRecur(dd, f1, g1); 00279 } else if (g1 == zero || g1 == DD_ZERO(dd)) { 00280 r = cuddCofactorRecur(dd, f0, g0); 00281 } else { 00282 (void) fprintf(dd->out, 00283 "Cudd_Cofactor: Invalid restriction 2\n"); 00284 dd->errorCode = CUDD_INVALID_ARG; 00285 return(NULL); 00286 } 00287 if (r == NULL) return(NULL); 00288 } else /* if (topf < topg) */ { 00289 t = cuddCofactorRecur(dd, f1, g); 00290 if (t == NULL) return(NULL); 00291 cuddRef(t); 00292 e = cuddCofactorRecur(dd, f0, g); 00293 if (e == NULL) { 00294 Cudd_RecursiveDeref(dd, t); 00295 return(NULL); 00296 } 00297 cuddRef(e); 00298 00299 if (t == e) { 00300 r = t; 00301 } else if (Cudd_IsComplement(t)) { 00302 r = cuddUniqueInter(dd,(int)F->index,Cudd_Not(t),Cudd_Not(e)); 00303 if (r != NULL) 00304 r = Cudd_Not(r); 00305 } else { 00306 r = cuddUniqueInter(dd,(int)F->index,t,e); 00307 } 00308 if (r == NULL) { 00309 Cudd_RecursiveDeref(dd ,e); 00310 Cudd_RecursiveDeref(dd ,t); 00311 return(NULL); 00312 } 00313 cuddDeref(t); 00314 cuddDeref(e); 00315 } 00316 00317 cuddCacheInsert2(dd,Cudd_Cofactor,F,g,r); 00318 00319 return(Cudd_NotCond(r,comple)); 00320 00321 } /* end of cuddCofactorRecur */
int cuddComputeFloorLog2 | ( | unsigned int | value | ) |
Function********************************************************************
Synopsis [Returns the floor of the logarithm to the base 2.]
Description [Returns the floor of the logarithm to the base 2. The input value is assumed to be greater than 0.]
SideEffects [None]
SeeAlso []
Definition at line 1033 of file cuddCache.c.
01035 { 01036 int floorLog = 0; 01037 #ifdef DD_DEBUG 01038 assert(value > 0); 01039 #endif 01040 while (value > 1) { 01041 floorLog++; 01042 value >>= 1; 01043 } 01044 return(floorLog); 01045 01046 } /* end of cuddComputeFloorLog2 */
Function********************************************************************
Synopsis [Looks up in the cache for the result of op applied to f, g, and h.]
Description [Looks up in the cache for the result of op applied to f, g, and h. Assumes that the calling procedure (e.g., Cudd_bddIteConstant) is only interested in whether the result is constant or not. Returns the result if found (possibly DD_NON_CONSTANT); otherwise it returns NULL.]
SideEffects [None]
SeeAlso [cuddCacheLookup]
Definition at line 687 of file cuddCache.c.
00693 { 00694 int posn; 00695 DdCache *en,*cache; 00696 ptruint uf, ug, uh; 00697 00698 uf = (ptruint) f | (op & 0xe); 00699 ug = (ptruint) g | (op >> 4); 00700 uh = (ptruint) h; 00701 00702 cache = table->cache; 00703 #ifdef DD_DEBUG 00704 if (cache == NULL) { 00705 return(NULL); 00706 } 00707 #endif 00708 posn = ddCHash2(uh,uf,ug,table->cacheShift); 00709 en = &cache[posn]; 00710 00711 /* We do not reclaim here because the result should not be 00712 * referenced, but only tested for being a constant. 00713 */ 00714 if (en->data != NULL && 00715 en->f == (DdNodePtr)uf && en->g == (DdNodePtr)ug && en->h == uh) { 00716 table->cacheHits++; 00717 return(en->data); 00718 } 00719 00720 /* Cache miss: decide whether to resize. */ 00721 table->cacheMisses++; 00722 00723 if (table->cacheSlack >= 0 && 00724 table->cacheHits > table->cacheMisses * table->minHit) { 00725 cuddCacheResize(table); 00726 } 00727 00728 return(NULL); 00729 00730 } /* end of cuddConstantLookup */
Function********************************************************************
Synopsis [Performs the recursive step of Cudd_CProjection.]
Description [Performs the recursive step of Cudd_CProjection. Returns the projection if successful; NULL otherwise.]
SideEffects [None]
SeeAlso [Cudd_CProjection]
Definition at line 1421 of file cuddPriority.c.
01426 { 01427 DdNode *res, *res1, *res2, *resA; 01428 DdNode *r, *y, *RT, *RE, *YT, *YE, *Yrest, *Ra, *Ran, *Gamma, *Alpha; 01429 unsigned int topR, topY, top, index; 01430 DdNode *one = DD_ONE(dd); 01431 01432 statLine(dd); 01433 if (Y == one) return(R); 01434 01435 #ifdef DD_DEBUG 01436 assert(!Cudd_IsConstant(Y)); 01437 #endif 01438 01439 if (R == Cudd_Not(one)) return(R); 01440 01441 res = cuddCacheLookup2(dd, Cudd_CProjection, R, Y); 01442 if (res != NULL) return(res); 01443 01444 r = Cudd_Regular(R); 01445 topR = cuddI(dd,r->index); 01446 y = Cudd_Regular(Y); 01447 topY = cuddI(dd,y->index); 01448 01449 top = ddMin(topR, topY); 01450 01451 /* Compute the cofactors of R */ 01452 if (topR == top) { 01453 index = r->index; 01454 RT = cuddT(r); 01455 RE = cuddE(r); 01456 if (r != R) { 01457 RT = Cudd_Not(RT); RE = Cudd_Not(RE); 01458 } 01459 } else { 01460 RT = RE = R; 01461 } 01462 01463 if (topY > top) { 01464 /* Y does not depend on the current top variable. 01465 ** We just need to compute the results on the two cofactors of R 01466 ** and make them the children of a node labeled r->index. 01467 */ 01468 res1 = cuddCProjectionRecur(dd,RT,Y,Ysupp); 01469 if (res1 == NULL) return(NULL); 01470 cuddRef(res1); 01471 res2 = cuddCProjectionRecur(dd,RE,Y,Ysupp); 01472 if (res2 == NULL) { 01473 Cudd_RecursiveDeref(dd,res1); 01474 return(NULL); 01475 } 01476 cuddRef(res2); 01477 res = cuddBddIteRecur(dd, dd->vars[index], res1, res2); 01478 if (res == NULL) { 01479 Cudd_RecursiveDeref(dd,res1); 01480 Cudd_RecursiveDeref(dd,res2); 01481 return(NULL); 01482 } 01483 /* If we have reached this point, res1 and res2 are now 01484 ** incorporated in res. cuddDeref is therefore sufficient. 01485 */ 01486 cuddDeref(res1); 01487 cuddDeref(res2); 01488 } else { 01489 /* Compute the cofactors of Y */ 01490 index = y->index; 01491 YT = cuddT(y); 01492 YE = cuddE(y); 01493 if (y != Y) { 01494 YT = Cudd_Not(YT); YE = Cudd_Not(YE); 01495 } 01496 if (YT == Cudd_Not(one)) { 01497 Alpha = Cudd_Not(dd->vars[index]); 01498 Yrest = YE; 01499 Ra = RE; 01500 Ran = RT; 01501 } else { 01502 Alpha = dd->vars[index]; 01503 Yrest = YT; 01504 Ra = RT; 01505 Ran = RE; 01506 } 01507 Gamma = cuddBddExistAbstractRecur(dd,Ra,cuddT(Ysupp)); 01508 if (Gamma == NULL) return(NULL); 01509 if (Gamma == one) { 01510 res1 = cuddCProjectionRecur(dd,Ra,Yrest,cuddT(Ysupp)); 01511 if (res1 == NULL) return(NULL); 01512 cuddRef(res1); 01513 res = cuddBddAndRecur(dd, Alpha, res1); 01514 if (res == NULL) { 01515 Cudd_RecursiveDeref(dd,res1); 01516 return(NULL); 01517 } 01518 cuddDeref(res1); 01519 } else if (Gamma == Cudd_Not(one)) { 01520 res1 = cuddCProjectionRecur(dd,Ran,Yrest,cuddT(Ysupp)); 01521 if (res1 == NULL) return(NULL); 01522 cuddRef(res1); 01523 res = cuddBddAndRecur(dd, Cudd_Not(Alpha), res1); 01524 if (res == NULL) { 01525 Cudd_RecursiveDeref(dd,res1); 01526 return(NULL); 01527 } 01528 cuddDeref(res1); 01529 } else { 01530 cuddRef(Gamma); 01531 resA = cuddCProjectionRecur(dd,Ran,Yrest,cuddT(Ysupp)); 01532 if (resA == NULL) { 01533 Cudd_RecursiveDeref(dd,Gamma); 01534 return(NULL); 01535 } 01536 cuddRef(resA); 01537 res2 = cuddBddAndRecur(dd, Cudd_Not(Gamma), resA); 01538 if (res2 == NULL) { 01539 Cudd_RecursiveDeref(dd,Gamma); 01540 Cudd_RecursiveDeref(dd,resA); 01541 return(NULL); 01542 } 01543 cuddRef(res2); 01544 Cudd_RecursiveDeref(dd,Gamma); 01545 Cudd_RecursiveDeref(dd,resA); 01546 res1 = cuddCProjectionRecur(dd,Ra,Yrest,cuddT(Ysupp)); 01547 if (res1 == NULL) { 01548 Cudd_RecursiveDeref(dd,res2); 01549 return(NULL); 01550 } 01551 cuddRef(res1); 01552 res = cuddBddIteRecur(dd, Alpha, res1, res2); 01553 if (res == NULL) { 01554 Cudd_RecursiveDeref(dd,res1); 01555 Cudd_RecursiveDeref(dd,res2); 01556 return(NULL); 01557 } 01558 cuddDeref(res1); 01559 cuddDeref(res2); 01560 } 01561 } 01562 01563 cuddCacheInsert2(dd,Cudd_CProjection,R,Y,res); 01564 01565 return(res); 01566 01567 } /* end of cuddCProjectionRecur */
int cuddDestroySubtables | ( | DdManager * | unique, | |
int | n | |||
) |
Function********************************************************************
Synopsis [Destroys the n most recently created subtables in a unique table.]
Description [Destroys the n most recently created subtables in a unique table. n should be positive. The subtables should not contain any live nodes, except the (isolated) projection function. The projection functions are freed. Returns 1 if successful; 0 otherwise.]
SideEffects [The variable map used for fast variable substitution is destroyed if it exists. In this case the cache is also cleared.]
SeeAlso [cuddInsertSubtables Cudd_SetVarMap]
Definition at line 2093 of file cuddTable.c.
02096 { 02097 DdSubtable *subtables; 02098 DdNodePtr *nodelist; 02099 DdNodePtr *vars; 02100 int firstIndex, lastIndex; 02101 int index, level, newlevel; 02102 int lowestLevel; 02103 int shift; 02104 int found; 02105 02106 /* Sanity check and set up. */ 02107 if (n <= 0) return(0); 02108 if (n > unique->size) n = unique->size; 02109 02110 subtables = unique->subtables; 02111 vars = unique->vars; 02112 firstIndex = unique->size - n; 02113 lastIndex = unique->size; 02114 02115 /* Check for nodes labeled by the variables being destroyed 02116 ** that may still be in use. It is allowed to destroy a variable 02117 ** only if there are no such nodes. Also, find the lowest level 02118 ** among the variables being destroyed. This will make further 02119 ** processing more efficient. 02120 */ 02121 lowestLevel = unique->size; 02122 for (index = firstIndex; index < lastIndex; index++) { 02123 level = unique->perm[index]; 02124 if (level < lowestLevel) lowestLevel = level; 02125 nodelist = subtables[level].nodelist; 02126 if (subtables[level].keys - subtables[level].dead != 1) return(0); 02127 /* The projection function should be isolated. If the ref count 02128 ** is 1, everything is OK. If the ref count is saturated, then 02129 ** we need to make sure that there are no nodes pointing to it. 02130 ** As for the external references, we assume the application is 02131 ** responsible for them. 02132 */ 02133 if (vars[index]->ref != 1) { 02134 if (vars[index]->ref != DD_MAXREF) return(0); 02135 found = cuddFindParent(unique,vars[index]); 02136 if (found) { 02137 return(0); 02138 } else { 02139 vars[index]->ref = 1; 02140 } 02141 } 02142 Cudd_RecursiveDeref(unique,vars[index]); 02143 } 02144 02145 /* Collect garbage, because we cannot afford having dead nodes pointing 02146 ** to the dead nodes in the subtables being destroyed. 02147 */ 02148 (void) cuddGarbageCollect(unique,1); 02149 02150 /* Here we know we can destroy our subtables. */ 02151 for (index = firstIndex; index < lastIndex; index++) { 02152 level = unique->perm[index]; 02153 nodelist = subtables[level].nodelist; 02154 #ifdef DD_DEBUG 02155 assert(subtables[level].keys == 0); 02156 #endif 02157 FREE(nodelist); 02158 unique->memused -= sizeof(DdNodePtr) * subtables[level].slots; 02159 unique->slots -= subtables[level].slots; 02160 unique->dead -= subtables[level].dead; 02161 } 02162 02163 /* Here all subtables to be destroyed have their keys field == 0 and 02164 ** their hash tables have been freed. 02165 ** We now scan the subtables from level lowestLevel + 1 to level size - 1, 02166 ** shifting the subtables as required. We keep a running count of 02167 ** how many subtables have been moved, so that we know by how many 02168 ** positions each subtable should be shifted. 02169 */ 02170 shift = 1; 02171 for (level = lowestLevel + 1; level < unique->size; level++) { 02172 if (subtables[level].keys == 0) { 02173 shift++; 02174 continue; 02175 } 02176 newlevel = level - shift; 02177 subtables[newlevel].slots = subtables[level].slots; 02178 subtables[newlevel].shift = subtables[level].shift; 02179 subtables[newlevel].keys = subtables[level].keys; 02180 subtables[newlevel].maxKeys = subtables[level].maxKeys; 02181 subtables[newlevel].dead = subtables[level].dead; 02182 subtables[newlevel].nodelist = subtables[level].nodelist; 02183 index = unique->invperm[level]; 02184 unique->perm[index] = newlevel; 02185 unique->invperm[newlevel] = index; 02186 subtables[newlevel].bindVar = subtables[level].bindVar; 02187 subtables[newlevel].varType = subtables[level].varType; 02188 subtables[newlevel].pairIndex = subtables[level].pairIndex; 02189 subtables[newlevel].varHandled = subtables[level].varHandled; 02190 subtables[newlevel].varToBeGrouped = subtables[level].varToBeGrouped; 02191 } 02192 /* Destroy the map. If a surviving variable is 02193 ** mapped to a dying variable, and the map were used again, 02194 ** an out-of-bounds access to unique->vars would result. */ 02195 if (unique->map != NULL) { 02196 cuddCacheFlush(unique); 02197 FREE(unique->map); 02198 unique->map = NULL; 02199 } 02200 02201 unique->minDead = (unsigned) (unique->gcFrac * (double) unique->slots); 02202 unique->size -= n; 02203 02204 return(1); 02205 02206 } /* end of cuddDestroySubtables */
Function********************************************************************
Synopsis [Dynamically allocates a Node.]
Description [Dynamically allocates a Node. This procedure is similar to cuddAllocNode in Cudd_Table.c, but it does not attempt garbage collection, because during reordering there are no dead nodes. Returns a pointer to a new node if successful; NULL is memory is full.]
SideEffects [None]
SeeAlso [cuddAllocNode]
Definition at line 402 of file cuddReorder.c.
00404 { 00405 int i; 00406 DdNodePtr *mem; 00407 DdNode *list, *node; 00408 extern DD_OOMFP MMoutOfMemory; 00409 DD_OOMFP saveHandler; 00410 00411 if (table->nextFree == NULL) { /* free list is empty */ 00412 /* Try to allocate a new block. */ 00413 saveHandler = MMoutOfMemory; 00414 MMoutOfMemory = Cudd_OutOfMem; 00415 mem = (DdNodePtr *) ALLOC(DdNode, DD_MEM_CHUNK + 1); 00416 MMoutOfMemory = saveHandler; 00417 if (mem == NULL && table->stash != NULL) { 00418 FREE(table->stash); 00419 table->stash = NULL; 00420 /* Inhibit resizing of tables. */ 00421 table->maxCacheHard = table->cacheSlots - 1; 00422 table->cacheSlack = - (int) (table->cacheSlots + 1); 00423 for (i = 0; i < table->size; i++) { 00424 table->subtables[i].maxKeys <<= 2; 00425 } 00426 mem = (DdNodePtr *) ALLOC(DdNode,DD_MEM_CHUNK + 1); 00427 } 00428 if (mem == NULL) { 00429 /* Out of luck. Call the default handler to do 00430 ** whatever it specifies for a failed malloc. If this 00431 ** handler returns, then set error code, print 00432 ** warning, and return. */ 00433 (*MMoutOfMemory)(sizeof(DdNode)*(DD_MEM_CHUNK + 1)); 00434 table->errorCode = CUDD_MEMORY_OUT; 00435 #ifdef DD_VERBOSE 00436 (void) fprintf(table->err, 00437 "cuddDynamicAllocNode: out of memory"); 00438 (void) fprintf(table->err,"Memory in use = %lu\n", 00439 table->memused); 00440 #endif 00441 return(NULL); 00442 } else { /* successful allocation; slice memory */ 00443 unsigned long offset; 00444 table->memused += (DD_MEM_CHUNK + 1) * sizeof(DdNode); 00445 mem[0] = (DdNode *) table->memoryList; 00446 table->memoryList = mem; 00447 00448 /* Here we rely on the fact that the size of a DdNode is a 00449 ** power of 2 and a multiple of the size of a pointer. 00450 ** If we align one node, all the others will be aligned 00451 ** as well. */ 00452 offset = (unsigned long) mem & (sizeof(DdNode) - 1); 00453 mem += (sizeof(DdNode) - offset) / sizeof(DdNodePtr); 00454 #ifdef DD_DEBUG 00455 assert(((unsigned long) mem & (sizeof(DdNode) - 1)) == 0); 00456 #endif 00457 list = (DdNode *) mem; 00458 00459 i = 1; 00460 do { 00461 list[i - 1].ref = 0; 00462 list[i - 1].next = &list[i]; 00463 } while (++i < DD_MEM_CHUNK); 00464 00465 list[DD_MEM_CHUNK-1].ref = 0; 00466 list[DD_MEM_CHUNK - 1].next = NULL; 00467 00468 table->nextFree = &list[0]; 00469 } 00470 } /* if free list empty */ 00471 00472 node = table->nextFree; 00473 table->nextFree = node->next; 00474 return (node); 00475 00476 } /* end of cuddDynamicAllocNode */
int cuddExact | ( | DdManager * | table, | |
int | lower, | |||
int | upper | |||
) |
AutomaticEnd Function********************************************************************
Synopsis [Exact variable ordering algorithm.]
Description [Exact variable ordering algorithm. Finds an optimum order for the variables between lower and upper. Returns 1 if successful; 0 otherwise.]
SideEffects [None]
SeeAlso []
Definition at line 149 of file cuddExact.c.
00153 { 00154 int k, i, j; 00155 int maxBinomial, oldSubsets, newSubsets; 00156 int subsetCost; 00157 int size; /* number of variables to be reordered */ 00158 int unused, nvars, level, result; 00159 int upperBound, lowerBound, cost; 00160 int roots; 00161 char *mask = NULL; 00162 DdHalfWord *symmInfo = NULL; 00163 DdHalfWord **newOrder = NULL; 00164 DdHalfWord **oldOrder = NULL; 00165 int *newCost = NULL; 00166 int *oldCost = NULL; 00167 DdHalfWord **tmpOrder; 00168 int *tmpCost; 00169 DdHalfWord *bestOrder = NULL; 00170 DdHalfWord *order; 00171 #ifdef DD_STATS 00172 int ddTotalSubsets; 00173 #endif 00174 00175 /* Restrict the range to be reordered by excluding unused variables 00176 ** at the two ends. */ 00177 while (table->subtables[lower].keys == 1 && 00178 table->vars[table->invperm[lower]]->ref == 1 && 00179 lower < upper) 00180 lower++; 00181 while (table->subtables[upper].keys == 1 && 00182 table->vars[table->invperm[upper]]->ref == 1 && 00183 lower < upper) 00184 upper--; 00185 if (lower == upper) return(1); /* trivial problem */ 00186 00187 /* Apply symmetric sifting to get a good upper bound and to extract 00188 ** symmetry information. */ 00189 result = cuddSymmSiftingConv(table,lower,upper); 00190 if (result == 0) goto cuddExactOutOfMem; 00191 00192 #ifdef DD_STATS 00193 (void) fprintf(table->out,"\n"); 00194 ddTotalShuffles = 0; 00195 ddTotalSubsets = 0; 00196 #endif 00197 00198 /* Initialization. */ 00199 nvars = table->size; 00200 size = upper - lower + 1; 00201 /* Count unused variable among those to be reordered. This is only 00202 ** used to compute maxBinomial. */ 00203 unused = 0; 00204 for (i = lower + 1; i < upper; i++) { 00205 if (table->subtables[i].keys == 1 && 00206 table->vars[table->invperm[i]]->ref == 1) 00207 unused++; 00208 } 00209 00210 /* Find the maximum number of subsets we may have to store. */ 00211 maxBinomial = getMaxBinomial(size - unused); 00212 if (maxBinomial == -1) goto cuddExactOutOfMem; 00213 00214 newOrder = getMatrix(maxBinomial, size); 00215 if (newOrder == NULL) goto cuddExactOutOfMem; 00216 00217 newCost = ALLOC(int, maxBinomial); 00218 if (newCost == NULL) goto cuddExactOutOfMem; 00219 00220 oldOrder = getMatrix(maxBinomial, size); 00221 if (oldOrder == NULL) goto cuddExactOutOfMem; 00222 00223 oldCost = ALLOC(int, maxBinomial); 00224 if (oldCost == NULL) goto cuddExactOutOfMem; 00225 00226 bestOrder = ALLOC(DdHalfWord, size); 00227 if (bestOrder == NULL) goto cuddExactOutOfMem; 00228 00229 mask = ALLOC(char, nvars); 00230 if (mask == NULL) goto cuddExactOutOfMem; 00231 00232 symmInfo = initSymmInfo(table, lower, upper); 00233 if (symmInfo == NULL) goto cuddExactOutOfMem; 00234 00235 roots = ddCountRoots(table, lower, upper); 00236 00237 /* Initialize the old order matrix for the empty subset and the best 00238 ** order to the current order. The cost for the empty subset includes 00239 ** the cost of the levels between upper and the constants. These levels 00240 ** are not going to change. Hence, we count them only once. 00241 */ 00242 oldSubsets = 1; 00243 for (i = 0; i < size; i++) { 00244 oldOrder[0][i] = bestOrder[i] = (DdHalfWord) table->invperm[i+lower]; 00245 } 00246 subsetCost = table->constants.keys; 00247 for (i = upper + 1; i < nvars; i++) 00248 subsetCost += getLevelKeys(table,i); 00249 oldCost[0] = subsetCost; 00250 /* The upper bound is initialized to the current size of the BDDs. */ 00251 upperBound = table->keys - table->isolated; 00252 00253 /* Now consider subsets of increasing size. */ 00254 for (k = 1; k <= size; k++) { 00255 #ifdef DD_STATS 00256 (void) fprintf(table->out,"Processing subsets of size %d\n", k); 00257 fflush(table->out); 00258 #endif 00259 newSubsets = 0; 00260 level = size - k; /* offset of first bottom variable */ 00261 00262 for (i = 0; i < oldSubsets; i++) { /* for each subset of size k-1 */ 00263 order = oldOrder[i]; 00264 cost = oldCost[i]; 00265 lowerBound = computeLB(table, order, roots, cost, lower, upper, 00266 level); 00267 if (lowerBound >= upperBound) 00268 continue; 00269 /* Impose new order. */ 00270 result = ddShuffle(table, order, lower, upper); 00271 if (result == 0) goto cuddExactOutOfMem; 00272 upperBound = updateUB(table,upperBound,bestOrder,lower,upper); 00273 /* For each top bottom variable. */ 00274 for (j = level; j >= 0; j--) { 00275 /* Skip unused variables. */ 00276 if (table->subtables[j+lower-1].keys == 1 && 00277 table->vars[table->invperm[j+lower-1]]->ref == 1) continue; 00278 /* Find cost under this order. */ 00279 subsetCost = cost + getLevelKeys(table, lower + level); 00280 newSubsets = updateEntry(table, order, level, subsetCost, 00281 newOrder, newCost, newSubsets, mask, 00282 lower, upper); 00283 if (j == 0) 00284 break; 00285 if (checkSymmInfo(table, symmInfo, order[j-1], level) == 0) 00286 continue; 00287 pushDown(order,j-1,level); 00288 /* Impose new order. */ 00289 result = ddShuffle(table, order, lower, upper); 00290 if (result == 0) goto cuddExactOutOfMem; 00291 upperBound = updateUB(table,upperBound,bestOrder,lower,upper); 00292 } /* for each bottom variable */ 00293 } /* for each subset of size k */ 00294 00295 /* New orders become old orders in preparation for next iteration. */ 00296 tmpOrder = oldOrder; tmpCost = oldCost; 00297 oldOrder = newOrder; oldCost = newCost; 00298 newOrder = tmpOrder; newCost = tmpCost; 00299 #ifdef DD_STATS 00300 ddTotalSubsets += newSubsets; 00301 #endif 00302 oldSubsets = newSubsets; 00303 } 00304 result = ddShuffle(table, bestOrder, lower, upper); 00305 if (result == 0) goto cuddExactOutOfMem; 00306 #ifdef DD_STATS 00307 #ifdef DD_VERBOSE 00308 (void) fprintf(table->out,"\n"); 00309 #endif 00310 (void) fprintf(table->out,"#:S_EXACT %8d: total subsets\n", 00311 ddTotalSubsets); 00312 (void) fprintf(table->out,"#:H_EXACT %8d: total shuffles", 00313 ddTotalShuffles); 00314 #endif 00315 00316 freeMatrix(newOrder); 00317 freeMatrix(oldOrder); 00318 FREE(bestOrder); 00319 FREE(oldCost); 00320 FREE(newCost); 00321 FREE(symmInfo); 00322 FREE(mask); 00323 return(1); 00324 00325 cuddExactOutOfMem: 00326 00327 if (newOrder != NULL) freeMatrix(newOrder); 00328 if (oldOrder != NULL) freeMatrix(oldOrder); 00329 if (bestOrder != NULL) FREE(bestOrder); 00330 if (oldCost != NULL) FREE(oldCost); 00331 if (newCost != NULL) FREE(newCost); 00332 if (symmInfo != NULL) FREE(symmInfo); 00333 if (mask != NULL) FREE(mask); 00334 table->errorCode = CUDD_MEMORY_OUT; 00335 return(0); 00336 00337 } /* end of cuddExact */
void cuddFreeTable | ( | DdManager * | unique | ) |
Function********************************************************************
Synopsis [Frees the resources associated to a unique table.]
Description []
SideEffects [None]
SeeAlso [cuddInitTable]
Definition at line 649 of file cuddTable.c.
00651 { 00652 DdNodePtr *next; 00653 DdNodePtr *memlist = unique->memoryList; 00654 int i; 00655 00656 if (unique->univ != NULL) cuddZddFreeUniv(unique); 00657 while (memlist != NULL) { 00658 next = (DdNodePtr *) memlist[0]; /* link to next block */ 00659 FREE(memlist); 00660 memlist = next; 00661 } 00662 unique->nextFree = NULL; 00663 unique->memoryList = NULL; 00664 00665 for (i = 0; i < unique->size; i++) { 00666 FREE(unique->subtables[i].nodelist); 00667 } 00668 for (i = 0; i < unique->sizeZ; i++) { 00669 FREE(unique->subtableZ[i].nodelist); 00670 } 00671 FREE(unique->constants.nodelist); 00672 FREE(unique->subtables); 00673 FREE(unique->subtableZ); 00674 FREE(unique->acache); 00675 FREE(unique->perm); 00676 FREE(unique->permZ); 00677 FREE(unique->invperm); 00678 FREE(unique->invpermZ); 00679 FREE(unique->vars); 00680 if (unique->map != NULL) FREE(unique->map); 00681 FREE(unique->stack); 00682 #ifndef DD_NO_DEATH_ROW 00683 FREE(unique->deathRow); 00684 #endif 00685 if (unique->tree != NULL) Mtr_FreeTree(unique->tree); 00686 if (unique->treeZ != NULL) Mtr_FreeTree(unique->treeZ); 00687 if (unique->linear != NULL) FREE(unique->linear); 00688 while (unique->preGCHook != NULL) 00689 Cudd_RemoveHook(unique,unique->preGCHook->f,CUDD_PRE_GC_HOOK); 00690 while (unique->postGCHook != NULL) 00691 Cudd_RemoveHook(unique,unique->postGCHook->f,CUDD_POST_GC_HOOK); 00692 while (unique->preReorderingHook != NULL) 00693 Cudd_RemoveHook(unique,unique->preReorderingHook->f, 00694 CUDD_PRE_REORDERING_HOOK); 00695 while (unique->postReorderingHook != NULL) 00696 Cudd_RemoveHook(unique,unique->postReorderingHook->f, 00697 CUDD_POST_REORDERING_HOOK); 00698 FREE(unique); 00699 00700 } /* end of cuddFreeTable */
int cuddGa | ( | DdManager * | table, | |
int | lower, | |||
int | upper | |||
) |
AutomaticEnd Function********************************************************************
Synopsis [Genetic algorithm for DD reordering.]
Description [Genetic algorithm for DD reordering. The two children of a crossover will be stored in storedd[popsize] and storedd[popsize+1] --- the last two slots in the storedd array. (This will make comparisons and replacement easy.) Returns 1 in case of success; 0 otherwise.]
SideEffects [None]
SeeAlso []
Definition at line 188 of file cuddGenetic.c.
00192 { 00193 int i,n,m; /* dummy/loop vars */ 00194 int index; 00195 #ifdef DD_STATS 00196 double average_fitness; 00197 #endif 00198 int small; /* index of smallest DD in population */ 00199 00200 /* Do an initial sifting to produce at least one reasonable individual. */ 00201 if (!cuddSifting(table,lower,upper)) return(0); 00202 00203 /* Get the initial values. */ 00204 numvars = upper - lower + 1; /* number of variables to be reordered */ 00205 if (table->populationSize == 0) { 00206 popsize = 3 * numvars; /* population size is 3 times # of vars */ 00207 if (popsize > 120) { 00208 popsize = 120; /* Maximum population size is 120 */ 00209 } 00210 } else { 00211 popsize = table->populationSize; /* user specified value */ 00212 } 00213 if (popsize < 4) popsize = 4; /* enforce minimum population size */ 00214 00215 /* Allocate population table. */ 00216 storedd = ALLOC(int,(popsize+2)*(numvars+1)); 00217 if (storedd == NULL) { 00218 table->errorCode = CUDD_MEMORY_OUT; 00219 return(0); 00220 } 00221 00222 /* Initialize the computed table. This table is made up of two data 00223 ** structures: A hash table with the key given by the order, which says 00224 ** if a given order is present in the population; and the repeat 00225 ** vector, which says how many copies of a given order are stored in 00226 ** the population table. If there are multiple copies of an order, only 00227 ** one has a repeat count greater than 1. This copy is the one pointed 00228 ** by the computed table. 00229 */ 00230 repeat = ALLOC(int,popsize); 00231 if (repeat == NULL) { 00232 table->errorCode = CUDD_MEMORY_OUT; 00233 FREE(storedd); 00234 return(0); 00235 } 00236 for (i = 0; i < popsize; i++) { 00237 repeat[i] = 0; 00238 } 00239 computed = st_init_table(array_compare,array_hash); 00240 if (computed == NULL) { 00241 table->errorCode = CUDD_MEMORY_OUT; 00242 FREE(storedd); 00243 FREE(repeat); 00244 return(0); 00245 } 00246 00247 /* Copy the current DD and its size to the population table. */ 00248 for (i = 0; i < numvars; i++) { 00249 STOREDD(0,i) = table->invperm[i+lower]; /* order of initial DD */ 00250 } 00251 STOREDD(0,numvars) = table->keys - table->isolated; /* size of initial DD */ 00252 00253 /* Store the initial order in the computed table. */ 00254 if (st_insert(computed,(char *)storedd,(char *) 0) == ST_OUT_OF_MEM) { 00255 FREE(storedd); 00256 FREE(repeat); 00257 st_free_table(computed); 00258 return(0); 00259 } 00260 repeat[0]++; 00261 00262 /* Insert the reverse order as second element of the population. */ 00263 for (i = 0; i < numvars; i++) { 00264 STOREDD(1,numvars-1-i) = table->invperm[i+lower]; /* reverse order */ 00265 } 00266 00267 /* Now create the random orders. make_random fills the population 00268 ** table with random permutations. The successive loop builds and sifts 00269 ** the DDs for the reverse order and each random permutation, and stores 00270 ** the results in the computed table. 00271 */ 00272 if (!make_random(table,lower)) { 00273 table->errorCode = CUDD_MEMORY_OUT; 00274 FREE(storedd); 00275 FREE(repeat); 00276 st_free_table(computed); 00277 return(0); 00278 } 00279 for (i = 1; i < popsize; i++) { 00280 result = build_dd(table,i,lower,upper); /* build and sift order */ 00281 if (!result) { 00282 FREE(storedd); 00283 FREE(repeat); 00284 st_free_table(computed); 00285 return(0); 00286 } 00287 if (st_lookup_int(computed,(char *)&STOREDD(i,0),&index)) { 00288 repeat[index]++; 00289 } else { 00290 if (st_insert(computed,(char *)&STOREDD(i,0),(char *)(long)i) == 00291 ST_OUT_OF_MEM) { 00292 FREE(storedd); 00293 FREE(repeat); 00294 st_free_table(computed); 00295 return(0); 00296 } 00297 repeat[i]++; 00298 } 00299 } 00300 00301 #if 0 00302 #ifdef DD_STATS 00303 /* Print the initial population. */ 00304 (void) fprintf(table->out,"Initial population after sifting\n"); 00305 for (m = 0; m < popsize; m++) { 00306 for (i = 0; i < numvars; i++) { 00307 (void) fprintf(table->out," %2d",STOREDD(m,i)); 00308 } 00309 (void) fprintf(table->out," : %3d (%d)\n", 00310 STOREDD(m,numvars),repeat[m]); 00311 } 00312 #endif 00313 #endif 00314 00315 small = find_best(); 00316 #ifdef DD_STATS 00317 average_fitness = find_average_fitness(); 00318 (void) fprintf(table->out,"\nInitial population: best fitness = %d, average fitness %8.3f",STOREDD(small,numvars),average_fitness); 00319 #endif 00320 00321 /* Decide how many crossovers should be tried. */ 00322 if (table->numberXovers == 0) { 00323 cross = 3*numvars; 00324 if (cross > 60) { /* do a maximum of 50 crossovers */ 00325 cross = 60; 00326 } 00327 } else { 00328 cross = table->numberXovers; /* use user specified value */ 00329 } 00330 00331 /* Perform the crossovers to get the best order. */ 00332 for (m = 0; m < cross; m++) { 00333 if (!PMX(table->size)) { /* perform one crossover */ 00334 table->errorCode = CUDD_MEMORY_OUT; 00335 FREE(storedd); 00336 FREE(repeat); 00337 st_free_table(computed); 00338 return(0); 00339 } 00340 /* The offsprings are left in the last two entries of the 00341 ** population table. These are now considered in turn. 00342 */ 00343 for (i = popsize; i <= popsize+1; i++) { 00344 result = build_dd(table,i,lower,upper); /* build and sift child */ 00345 if (!result) { 00346 FREE(storedd); 00347 FREE(repeat); 00348 st_free_table(computed); 00349 return(0); 00350 } 00351 large = largest(); /* find the largest DD in population */ 00352 00353 /* If the new child is smaller than the largest DD in the current 00354 ** population, enter it into the population in place of the 00355 ** largest DD. 00356 */ 00357 if (STOREDD(i,numvars) < STOREDD(large,numvars)) { 00358 /* Look up the largest DD in the computed table. 00359 ** Decrease its repetition count. If the repetition count 00360 ** goes to 0, remove the largest DD from the computed table. 00361 */ 00362 result = st_lookup_int(computed,(char *)&STOREDD(large,0), 00363 &index); 00364 if (!result) { 00365 FREE(storedd); 00366 FREE(repeat); 00367 st_free_table(computed); 00368 return(0); 00369 } 00370 repeat[index]--; 00371 if (repeat[index] == 0) { 00372 int *pointer = &STOREDD(index,0); 00373 result = st_delete(computed, &pointer, NULL); 00374 if (!result) { 00375 FREE(storedd); 00376 FREE(repeat); 00377 st_free_table(computed); 00378 return(0); 00379 } 00380 } 00381 /* Copy the new individual to the entry of the 00382 ** population table just made available and update the 00383 ** computed table. 00384 */ 00385 for (n = 0; n <= numvars; n++) { 00386 STOREDD(large,n) = STOREDD(i,n); 00387 } 00388 if (st_lookup_int(computed,(char *)&STOREDD(large,0), 00389 &index)) { 00390 repeat[index]++; 00391 } else { 00392 if (st_insert(computed,(char *)&STOREDD(large,0), 00393 (char *)(long)large) == ST_OUT_OF_MEM) { 00394 FREE(storedd); 00395 FREE(repeat); 00396 st_free_table(computed); 00397 return(0); 00398 } 00399 repeat[large]++; 00400 } 00401 } 00402 } 00403 } 00404 00405 /* Find the smallest DD in the population and build it; 00406 ** that will be the result. 00407 */ 00408 small = find_best(); 00409 00410 /* Print stats on the final population. */ 00411 #ifdef DD_STATS 00412 average_fitness = find_average_fitness(); 00413 (void) fprintf(table->out,"\nFinal population: best fitness = %d, average fitness %8.3f",STOREDD(small,numvars),average_fitness); 00414 #endif 00415 00416 /* Clean up, build the result DD, and return. */ 00417 st_free_table(computed); 00418 computed = NULL; 00419 result = build_dd(table,small,lower,upper); 00420 FREE(storedd); 00421 FREE(repeat); 00422 return(result); 00423 00424 } /* end of cuddGa */
int cuddGarbageCollect | ( | DdManager * | unique, | |
int | clearCache | |||
) |
Function********************************************************************
Synopsis [Performs garbage collection on the unique tables.]
Description [Performs garbage collection on the BDD and ZDD unique tables. If clearCache is 0, the cache is not cleared. This should only be specified if the cache has been cleared right before calling cuddGarbageCollect. (As in the case of dynamic reordering.) Returns the total number of deleted nodes.]
SideEffects [None]
SeeAlso []
Definition at line 719 of file cuddTable.c.
00722 { 00723 DdHook *hook; 00724 DdCache *cache = unique->cache; 00725 DdNode *sentinel = &(unique->sentinel); 00726 DdNodePtr *nodelist; 00727 int i, j, deleted, totalDeleted, totalDeletedZ; 00728 DdCache *c; 00729 DdNode *node,*next; 00730 DdNodePtr *lastP; 00731 int slots; 00732 long localTime; 00733 #ifndef DD_UNSORTED_FREE_LIST 00734 #ifdef DD_RED_BLACK_FREE_LIST 00735 DdNodePtr tree; 00736 #else 00737 DdNodePtr *memListTrav, *nxtNode; 00738 DdNode *downTrav, *sentry; 00739 int k; 00740 #endif 00741 #endif 00742 00743 #ifndef DD_NO_DEATH_ROW 00744 cuddClearDeathRow(unique); 00745 #endif 00746 00747 hook = unique->preGCHook; 00748 while (hook != NULL) { 00749 int res = (hook->f)(unique,"DD",NULL); 00750 if (res == 0) return(0); 00751 hook = hook->next; 00752 } 00753 00754 if (unique->dead + unique->deadZ == 0) { 00755 hook = unique->postGCHook; 00756 while (hook != NULL) { 00757 int res = (hook->f)(unique,"DD",NULL); 00758 if (res == 0) return(0); 00759 hook = hook->next; 00760 } 00761 return(0); 00762 } 00763 00764 /* If many nodes are being reclaimed, we want to resize the tables 00765 ** more aggressively, to reduce the frequency of garbage collection. 00766 */ 00767 if (clearCache && unique->gcFrac == DD_GC_FRAC_LO && 00768 unique->slots <= unique->looseUpTo && unique->stash != NULL) { 00769 unique->minDead = (unsigned) (DD_GC_FRAC_HI * (double) unique->slots); 00770 #ifdef DD_VERBOSE 00771 (void) fprintf(unique->err,"GC fraction = %.2f\t", DD_GC_FRAC_HI); 00772 (void) fprintf(unique->err,"minDead = %d\n", unique->minDead); 00773 #endif 00774 unique->gcFrac = DD_GC_FRAC_HI; 00775 return(0); 00776 } 00777 00778 localTime = util_cpu_time(); 00779 00780 unique->garbageCollections++; 00781 #ifdef DD_VERBOSE 00782 (void) fprintf(unique->err, 00783 "garbage collecting (%d dead BDD nodes out of %d, min %d)...", 00784 unique->dead, unique->keys, unique->minDead); 00785 (void) fprintf(unique->err, 00786 " (%d dead ZDD nodes out of %d)...", 00787 unique->deadZ, unique->keysZ); 00788 #endif 00789 00790 /* Remove references to garbage collected nodes from the cache. */ 00791 if (clearCache) { 00792 slots = unique->cacheSlots; 00793 for (i = 0; i < slots; i++) { 00794 c = &cache[i]; 00795 if (c->data != NULL) { 00796 if (cuddClean(c->f)->ref == 0 || 00797 cuddClean(c->g)->ref == 0 || 00798 (((ptruint)c->f & 0x2) && Cudd_Regular(c->h)->ref == 0) || 00799 (c->data != DD_NON_CONSTANT && 00800 Cudd_Regular(c->data)->ref == 0)) { 00801 c->data = NULL; 00802 unique->cachedeletions++; 00803 } 00804 } 00805 } 00806 cuddLocalCacheClearDead(unique); 00807 } 00808 00809 /* Now return dead nodes to free list. Count them for sanity check. */ 00810 totalDeleted = 0; 00811 #ifndef DD_UNSORTED_FREE_LIST 00812 #ifdef DD_RED_BLACK_FREE_LIST 00813 tree = NULL; 00814 #endif 00815 #endif 00816 00817 for (i = 0; i < unique->size; i++) { 00818 if (unique->subtables[i].dead == 0) continue; 00819 nodelist = unique->subtables[i].nodelist; 00820 00821 deleted = 0; 00822 slots = unique->subtables[i].slots; 00823 for (j = 0; j < slots; j++) { 00824 lastP = &(nodelist[j]); 00825 node = *lastP; 00826 while (node != sentinel) { 00827 next = node->next; 00828 if (node->ref == 0) { 00829 deleted++; 00830 #ifndef DD_UNSORTED_FREE_LIST 00831 #ifdef DD_RED_BLACK_FREE_LIST 00832 #ifdef __osf__ 00833 #pragma pointer_size save 00834 #pragma pointer_size short 00835 #endif 00836 cuddOrderedInsert(&tree,node); 00837 #ifdef __osf__ 00838 #pragma pointer_size restore 00839 #endif 00840 #endif 00841 #else 00842 cuddDeallocNode(unique,node); 00843 #endif 00844 } else { 00845 *lastP = node; 00846 lastP = &(node->next); 00847 } 00848 node = next; 00849 } 00850 *lastP = sentinel; 00851 } 00852 if ((unsigned) deleted != unique->subtables[i].dead) { 00853 ddReportRefMess(unique, i, "cuddGarbageCollect"); 00854 } 00855 totalDeleted += deleted; 00856 unique->subtables[i].keys -= deleted; 00857 unique->subtables[i].dead = 0; 00858 } 00859 if (unique->constants.dead != 0) { 00860 nodelist = unique->constants.nodelist; 00861 deleted = 0; 00862 slots = unique->constants.slots; 00863 for (j = 0; j < slots; j++) { 00864 lastP = &(nodelist[j]); 00865 node = *lastP; 00866 while (node != NULL) { 00867 next = node->next; 00868 if (node->ref == 0) { 00869 deleted++; 00870 #ifndef DD_UNSORTED_FREE_LIST 00871 #ifdef DD_RED_BLACK_FREE_LIST 00872 #ifdef __osf__ 00873 #pragma pointer_size save 00874 #pragma pointer_size short 00875 #endif 00876 cuddOrderedInsert(&tree,node); 00877 #ifdef __osf__ 00878 #pragma pointer_size restore 00879 #endif 00880 #endif 00881 #else 00882 cuddDeallocNode(unique,node); 00883 #endif 00884 } else { 00885 *lastP = node; 00886 lastP = &(node->next); 00887 } 00888 node = next; 00889 } 00890 *lastP = NULL; 00891 } 00892 if ((unsigned) deleted != unique->constants.dead) { 00893 ddReportRefMess(unique, CUDD_CONST_INDEX, "cuddGarbageCollect"); 00894 } 00895 totalDeleted += deleted; 00896 unique->constants.keys -= deleted; 00897 unique->constants.dead = 0; 00898 } 00899 if ((unsigned) totalDeleted != unique->dead) { 00900 ddReportRefMess(unique, -1, "cuddGarbageCollect"); 00901 } 00902 unique->keys -= totalDeleted; 00903 unique->dead = 0; 00904 #ifdef DD_STATS 00905 unique->nodesFreed += (double) totalDeleted; 00906 #endif 00907 00908 totalDeletedZ = 0; 00909 00910 for (i = 0; i < unique->sizeZ; i++) { 00911 if (unique->subtableZ[i].dead == 0) continue; 00912 nodelist = unique->subtableZ[i].nodelist; 00913 00914 deleted = 0; 00915 slots = unique->subtableZ[i].slots; 00916 for (j = 0; j < slots; j++) { 00917 lastP = &(nodelist[j]); 00918 node = *lastP; 00919 while (node != NULL) { 00920 next = node->next; 00921 if (node->ref == 0) { 00922 deleted++; 00923 #ifndef DD_UNSORTED_FREE_LIST 00924 #ifdef DD_RED_BLACK_FREE_LIST 00925 #ifdef __osf__ 00926 #pragma pointer_size save 00927 #pragma pointer_size short 00928 #endif 00929 cuddOrderedInsert(&tree,node); 00930 #ifdef __osf__ 00931 #pragma pointer_size restore 00932 #endif 00933 #endif 00934 #else 00935 cuddDeallocNode(unique,node); 00936 #endif 00937 } else { 00938 *lastP = node; 00939 lastP = &(node->next); 00940 } 00941 node = next; 00942 } 00943 *lastP = NULL; 00944 } 00945 if ((unsigned) deleted != unique->subtableZ[i].dead) { 00946 ddReportRefMess(unique, i, "cuddGarbageCollect"); 00947 } 00948 totalDeletedZ += deleted; 00949 unique->subtableZ[i].keys -= deleted; 00950 unique->subtableZ[i].dead = 0; 00951 } 00952 00953 /* No need to examine the constant table for ZDDs. 00954 ** If we did we should be careful not to count whatever dead 00955 ** nodes we found there among the dead ZDD nodes. */ 00956 if ((unsigned) totalDeletedZ != unique->deadZ) { 00957 ddReportRefMess(unique, -1, "cuddGarbageCollect"); 00958 } 00959 unique->keysZ -= totalDeletedZ; 00960 unique->deadZ = 0; 00961 #ifdef DD_STATS 00962 unique->nodesFreed += (double) totalDeletedZ; 00963 #endif 00964 00965 00966 #ifndef DD_UNSORTED_FREE_LIST 00967 #ifdef DD_RED_BLACK_FREE_LIST 00968 unique->nextFree = cuddOrderedThread(tree,unique->nextFree); 00969 #else 00970 memListTrav = unique->memoryList; 00971 sentry = NULL; 00972 while (memListTrav != NULL) { 00973 ptruint offset; 00974 nxtNode = (DdNodePtr *)memListTrav[0]; 00975 offset = (ptruint) memListTrav & (sizeof(DdNode) - 1); 00976 memListTrav += (sizeof(DdNode) - offset) / sizeof(DdNodePtr); 00977 downTrav = (DdNode *)memListTrav; 00978 k = 0; 00979 do { 00980 if (downTrav[k].ref == 0) { 00981 if (sentry == NULL) { 00982 unique->nextFree = sentry = &downTrav[k]; 00983 } else { 00984 /* First hook sentry->next to the dead node and then 00985 ** reassign sentry to the dead node. */ 00986 sentry = (sentry->next = &downTrav[k]); 00987 } 00988 } 00989 } while (++k < DD_MEM_CHUNK); 00990 memListTrav = nxtNode; 00991 } 00992 sentry->next = NULL; 00993 #endif 00994 #endif 00995 00996 unique->GCTime += util_cpu_time() - localTime; 00997 00998 hook = unique->postGCHook; 00999 while (hook != NULL) { 01000 int res = (hook->f)(unique,"DD",NULL); 01001 if (res == 0) return(0); 01002 hook = hook->next; 01003 } 01004 01005 #ifdef DD_VERBOSE 01006 (void) fprintf(unique->err," done\n"); 01007 #endif 01008 01009 return(totalDeleted+totalDeletedZ); 01010 01011 } /* end of cuddGarbageCollect */
Function********************************************************************
Synopsis [Computes the children of g.]
Description []
SideEffects [None]
SeeAlso []
Definition at line 158 of file cuddCof.c.
00162 { 00163 DdNode *G = Cudd_Regular(g); 00164 00165 *g1 = cuddT(G); 00166 *g0 = cuddE(G); 00167 if (Cudd_IsComplement(g)) { 00168 *g1 = Cudd_Not(*g1); 00169 *g0 = Cudd_Not(*g0); 00170 } 00171 00172 } /* end of cuddGetBranches */
DdHashTable* cuddHashTableInit | ( | DdManager * | manager, | |
unsigned int | keySize, | |||
unsigned int | initSize | |||
) |
Function********************************************************************
Synopsis [Initializes a hash table.]
Description [Initializes a hash table. Returns a pointer to the new table if successful; NULL otherwise.]
SideEffects [None]
SeeAlso [cuddHashTableQuit]
Definition at line 534 of file cuddLCache.c.
00538 { 00539 DdHashTable *hash; 00540 int logSize; 00541 00542 #ifdef __osf__ 00543 #pragma pointer_size save 00544 #pragma pointer_size short 00545 #endif 00546 hash = ALLOC(DdHashTable, 1); 00547 if (hash == NULL) { 00548 manager->errorCode = CUDD_MEMORY_OUT; 00549 return(NULL); 00550 } 00551 hash->keysize = keySize; 00552 hash->manager = manager; 00553 hash->memoryList = NULL; 00554 hash->nextFree = NULL; 00555 hash->itemsize = (keySize + 1) * sizeof(DdNode *) + 00556 sizeof(ptrint) + sizeof(DdHashItem *); 00557 /* We have to guarantee that the shift be < 32. */ 00558 if (initSize < 2) initSize = 2; 00559 logSize = cuddComputeFloorLog2(initSize); 00560 hash->numBuckets = 1 << logSize; 00561 hash->shift = sizeof(int) * 8 - logSize; 00562 hash->bucket = ALLOC(DdHashItem *, hash->numBuckets); 00563 if (hash->bucket == NULL) { 00564 manager->errorCode = CUDD_MEMORY_OUT; 00565 FREE(hash); 00566 return(NULL); 00567 } 00568 memset(hash->bucket, 0, hash->numBuckets * sizeof(DdHashItem *)); 00569 hash->size = 0; 00570 hash->maxsize = hash->numBuckets * DD_MAX_HASHTABLE_DENSITY; 00571 #ifdef __osf__ 00572 #pragma pointer_size restore 00573 #endif 00574 return(hash); 00575 00576 } /* end of cuddHashTableInit */
int cuddHashTableInsert | ( | DdHashTable * | hash, | |
DdNodePtr * | key, | |||
DdNode * | value, | |||
ptrint | count | |||
) |
Function********************************************************************
Synopsis [Inserts an item in a hash table.]
Description [Inserts an item in a hash table when the key has more than three pointers. Returns 1 if successful; 0 otherwise.]
SideEffects [None]
SeeAlso [[cuddHashTableInsert1 cuddHashTableInsert2 cuddHashTableInsert3 cuddHashTableLookup]
Definition at line 644 of file cuddLCache.c.
00649 { 00650 int result; 00651 unsigned int posn; 00652 DdHashItem *item; 00653 unsigned int i; 00654 00655 #ifdef DD_DEBUG 00656 assert(hash->keysize > 3); 00657 #endif 00658 00659 if (hash->size > hash->maxsize) { 00660 result = cuddHashTableResize(hash); 00661 if (result == 0) return(0); 00662 } 00663 item = cuddHashTableAlloc(hash); 00664 if (item == NULL) return(0); 00665 hash->size++; 00666 item->value = value; 00667 cuddRef(value); 00668 item->count = count; 00669 for (i = 0; i < hash->keysize; i++) { 00670 item->key[i] = key[i]; 00671 } 00672 posn = ddLCHash(key,hash->keysize,hash->shift); 00673 item->next = hash->bucket[posn]; 00674 hash->bucket[posn] = item; 00675 00676 return(1); 00677 00678 } /* end of cuddHashTableInsert */
int cuddHashTableInsert1 | ( | DdHashTable * | hash, | |
DdNode * | f, | |||
DdNode * | value, | |||
ptrint | count | |||
) |
Function********************************************************************
Synopsis [Inserts an item in a hash table.]
Description [Inserts an item in a hash table when the key is one pointer. Returns 1 if successful; 0 otherwise.]
SideEffects [None]
SeeAlso [cuddHashTableInsert cuddHashTableInsert2 cuddHashTableInsert3 cuddHashTableLookup1]
Definition at line 763 of file cuddLCache.c.
00768 { 00769 int result; 00770 unsigned int posn; 00771 DdHashItem *item; 00772 00773 #ifdef DD_DEBUG 00774 assert(hash->keysize == 1); 00775 #endif 00776 00777 if (hash->size > hash->maxsize) { 00778 result = cuddHashTableResize(hash); 00779 if (result == 0) return(0); 00780 } 00781 item = cuddHashTableAlloc(hash); 00782 if (item == NULL) return(0); 00783 hash->size++; 00784 item->value = value; 00785 cuddRef(value); 00786 item->count = count; 00787 item->key[0] = f; 00788 posn = ddLCHash2(f,f,hash->shift); 00789 item->next = hash->bucket[posn]; 00790 hash->bucket[posn] = item; 00791 00792 return(1); 00793 00794 } /* end of cuddHashTableInsert1 */
int cuddHashTableInsert2 | ( | DdHashTable * | hash, | |
DdNode * | f, | |||
DdNode * | g, | |||
DdNode * | value, | |||
ptrint | count | |||
) |
Function********************************************************************
Synopsis [Inserts an item in a hash table.]
Description [Inserts an item in a hash table when the key is composed of two pointers. Returns 1 if successful; 0 otherwise.]
SideEffects [None]
SeeAlso [cuddHashTableInsert cuddHashTableInsert1 cuddHashTableInsert3 cuddHashTableLookup2]
Definition at line 870 of file cuddLCache.c.
00876 { 00877 int result; 00878 unsigned int posn; 00879 DdHashItem *item; 00880 00881 #ifdef DD_DEBUG 00882 assert(hash->keysize == 2); 00883 #endif 00884 00885 if (hash->size > hash->maxsize) { 00886 result = cuddHashTableResize(hash); 00887 if (result == 0) return(0); 00888 } 00889 item = cuddHashTableAlloc(hash); 00890 if (item == NULL) return(0); 00891 hash->size++; 00892 item->value = value; 00893 cuddRef(value); 00894 item->count = count; 00895 item->key[0] = f; 00896 item->key[1] = g; 00897 posn = ddLCHash2(f,g,hash->shift); 00898 item->next = hash->bucket[posn]; 00899 hash->bucket[posn] = item; 00900 00901 return(1); 00902 00903 } /* end of cuddHashTableInsert2 */
int cuddHashTableInsert3 | ( | DdHashTable * | hash, | |
DdNode * | f, | |||
DdNode * | g, | |||
DdNode * | h, | |||
DdNode * | value, | |||
ptrint | count | |||
) |
Function********************************************************************
Synopsis [Inserts an item in a hash table.]
Description [Inserts an item in a hash table when the key is composed of three pointers. Returns 1 if successful; 0 otherwise.]
SideEffects [None]
SeeAlso [cuddHashTableInsert cuddHashTableInsert1 cuddHashTableInsert2 cuddHashTableLookup3]
Definition at line 980 of file cuddLCache.c.
00987 { 00988 int result; 00989 unsigned int posn; 00990 DdHashItem *item; 00991 00992 #ifdef DD_DEBUG 00993 assert(hash->keysize == 3); 00994 #endif 00995 00996 if (hash->size > hash->maxsize) { 00997 result = cuddHashTableResize(hash); 00998 if (result == 0) return(0); 00999 } 01000 item = cuddHashTableAlloc(hash); 01001 if (item == NULL) return(0); 01002 hash->size++; 01003 item->value = value; 01004 cuddRef(value); 01005 item->count = count; 01006 item->key[0] = f; 01007 item->key[1] = g; 01008 item->key[2] = h; 01009 posn = ddLCHash3(f,g,h,hash->shift); 01010 item->next = hash->bucket[posn]; 01011 hash->bucket[posn] = item; 01012 01013 return(1); 01014 01015 } /* end of cuddHashTableInsert3 */
DdNode* cuddHashTableLookup | ( | DdHashTable * | hash, | |
DdNodePtr * | key | |||
) |
Function********************************************************************
Synopsis [Looks up a key in a hash table.]
Description [Looks up a key consisting of more than three pointers in a hash table. Returns the value associated to the key if there is an entry for the given key in the table; NULL otherwise. If the entry is present, its reference counter is decremented if not saturated. If the counter reaches 0, the value of the entry is dereferenced, and the entry is returned to the free list.]
SideEffects [None]
SeeAlso [cuddHashTableLookup1 cuddHashTableLookup2 cuddHashTableLookup3 cuddHashTableInsert]
Definition at line 699 of file cuddLCache.c.
00702 { 00703 unsigned int posn; 00704 DdHashItem *item, *prev; 00705 unsigned int i, keysize; 00706 00707 #ifdef DD_DEBUG 00708 assert(hash->keysize > 3); 00709 #endif 00710 00711 posn = ddLCHash(key,hash->keysize,hash->shift); 00712 item = hash->bucket[posn]; 00713 prev = NULL; 00714 00715 keysize = hash->keysize; 00716 while (item != NULL) { 00717 DdNodePtr *key2 = item->key; 00718 int equal = 1; 00719 for (i = 0; i < keysize; i++) { 00720 if (key[i] != key2[i]) { 00721 equal = 0; 00722 break; 00723 } 00724 } 00725 if (equal) { 00726 DdNode *value = item->value; 00727 cuddSatDec(item->count); 00728 if (item->count == 0) { 00729 cuddDeref(value); 00730 if (prev == NULL) { 00731 hash->bucket[posn] = item->next; 00732 } else { 00733 prev->next = item->next; 00734 } 00735 item->next = hash->nextFree; 00736 hash->nextFree = item; 00737 hash->size--; 00738 } 00739 return(value); 00740 } 00741 prev = item; 00742 item = item->next; 00743 } 00744 return(NULL); 00745 00746 } /* end of cuddHashTableLookup */
DdNode* cuddHashTableLookup1 | ( | DdHashTable * | hash, | |
DdNode * | f | |||
) |
Function********************************************************************
Synopsis [Looks up a key consisting of one pointer in a hash table.]
Description [Looks up a key consisting of one pointer in a hash table. Returns the value associated to the key if there is an entry for the given key in the table; NULL otherwise. If the entry is present, its reference counter is decremented if not saturated. If the counter reaches 0, the value of the entry is dereferenced, and the entry is returned to the free list.]
SideEffects [None]
SeeAlso [cuddHashTableLookup cuddHashTableLookup2 cuddHashTableLookup3 cuddHashTableInsert1]
Definition at line 815 of file cuddLCache.c.
00818 { 00819 unsigned int posn; 00820 DdHashItem *item, *prev; 00821 00822 #ifdef DD_DEBUG 00823 assert(hash->keysize == 1); 00824 #endif 00825 00826 posn = ddLCHash2(f,f,hash->shift); 00827 item = hash->bucket[posn]; 00828 prev = NULL; 00829 00830 while (item != NULL) { 00831 DdNodePtr *key = item->key; 00832 if (f == key[0]) { 00833 DdNode *value = item->value; 00834 cuddSatDec(item->count); 00835 if (item->count == 0) { 00836 cuddDeref(value); 00837 if (prev == NULL) { 00838 hash->bucket[posn] = item->next; 00839 } else { 00840 prev->next = item->next; 00841 } 00842 item->next = hash->nextFree; 00843 hash->nextFree = item; 00844 hash->size--; 00845 } 00846 return(value); 00847 } 00848 prev = item; 00849 item = item->next; 00850 } 00851 return(NULL); 00852 00853 } /* end of cuddHashTableLookup1 */
DdNode* cuddHashTableLookup2 | ( | DdHashTable * | hash, | |
DdNode * | f, | |||
DdNode * | g | |||
) |
Function********************************************************************
Synopsis [Looks up a key consisting of two pointers in a hash table.]
Description [Looks up a key consisting of two pointer in a hash table. Returns the value associated to the key if there is an entry for the given key in the table; NULL otherwise. If the entry is present, its reference counter is decremented if not saturated. If the counter reaches 0, the value of the entry is dereferenced, and the entry is returned to the free list.]
SideEffects [None]
SeeAlso [cuddHashTableLookup cuddHashTableLookup1 cuddHashTableLookup3 cuddHashTableInsert2]
Definition at line 924 of file cuddLCache.c.
00928 { 00929 unsigned int posn; 00930 DdHashItem *item, *prev; 00931 00932 #ifdef DD_DEBUG 00933 assert(hash->keysize == 2); 00934 #endif 00935 00936 posn = ddLCHash2(f,g,hash->shift); 00937 item = hash->bucket[posn]; 00938 prev = NULL; 00939 00940 while (item != NULL) { 00941 DdNodePtr *key = item->key; 00942 if ((f == key[0]) && (g == key[1])) { 00943 DdNode *value = item->value; 00944 cuddSatDec(item->count); 00945 if (item->count == 0) { 00946 cuddDeref(value); 00947 if (prev == NULL) { 00948 hash->bucket[posn] = item->next; 00949 } else { 00950 prev->next = item->next; 00951 } 00952 item->next = hash->nextFree; 00953 hash->nextFree = item; 00954 hash->size--; 00955 } 00956 return(value); 00957 } 00958 prev = item; 00959 item = item->next; 00960 } 00961 return(NULL); 00962 00963 } /* end of cuddHashTableLookup2 */
DdNode* cuddHashTableLookup3 | ( | DdHashTable * | hash, | |
DdNode * | f, | |||
DdNode * | g, | |||
DdNode * | h | |||
) |
Function********************************************************************
Synopsis [Looks up a key consisting of three pointers in a hash table.]
Description [Looks up a key consisting of three pointers in a hash table. Returns the value associated to the key if there is an entry for the given key in the table; NULL otherwise. If the entry is present, its reference counter is decremented if not saturated. If the counter reaches 0, the value of the entry is dereferenced, and the entry is returned to the free list.]
SideEffects [None]
SeeAlso [cuddHashTableLookup cuddHashTableLookup1 cuddHashTableLookup2 cuddHashTableInsert3]
Definition at line 1036 of file cuddLCache.c.
01041 { 01042 unsigned int posn; 01043 DdHashItem *item, *prev; 01044 01045 #ifdef DD_DEBUG 01046 assert(hash->keysize == 3); 01047 #endif 01048 01049 posn = ddLCHash3(f,g,h,hash->shift); 01050 item = hash->bucket[posn]; 01051 prev = NULL; 01052 01053 while (item != NULL) { 01054 DdNodePtr *key = item->key; 01055 if ((f == key[0]) && (g == key[1]) && (h == key[2])) { 01056 DdNode *value = item->value; 01057 cuddSatDec(item->count); 01058 if (item->count == 0) { 01059 cuddDeref(value); 01060 if (prev == NULL) { 01061 hash->bucket[posn] = item->next; 01062 } else { 01063 prev->next = item->next; 01064 } 01065 item->next = hash->nextFree; 01066 hash->nextFree = item; 01067 hash->size--; 01068 } 01069 return(value); 01070 } 01071 prev = item; 01072 item = item->next; 01073 } 01074 return(NULL); 01075 01076 } /* end of cuddHashTableLookup3 */
void cuddHashTableQuit | ( | DdHashTable * | hash | ) |
Function********************************************************************
Synopsis [Shuts down a hash table.]
Description [Shuts down a hash table, dereferencing all the values.]
SideEffects [None]
SeeAlso [cuddHashTableInit]
Definition at line 591 of file cuddLCache.c.
00593 { 00594 #ifdef __osf__ 00595 #pragma pointer_size save 00596 #pragma pointer_size short 00597 #endif 00598 unsigned int i; 00599 DdManager *dd = hash->manager; 00600 DdHashItem *bucket; 00601 DdHashItem **memlist, **nextmem; 00602 unsigned int numBuckets = hash->numBuckets; 00603 00604 for (i = 0; i < numBuckets; i++) { 00605 bucket = hash->bucket[i]; 00606 while (bucket != NULL) { 00607 Cudd_RecursiveDeref(dd, bucket->value); 00608 bucket = bucket->next; 00609 } 00610 } 00611 00612 memlist = hash->memoryList; 00613 while (memlist != NULL) { 00614 nextmem = (DdHashItem **) memlist[0]; 00615 FREE(memlist); 00616 memlist = nextmem; 00617 } 00618 00619 FREE(hash->bucket); 00620 FREE(hash); 00621 #ifdef __osf__ 00622 #pragma pointer_size restore 00623 #endif 00624 00625 return; 00626 00627 } /* end of cuddHashTableQuit */
int cuddHeapProfile | ( | DdManager * | dd | ) |
Function********************************************************************
Synopsis [Prints information about the heap.]
Description [Prints to the manager's stdout the number of live nodes for each level of the DD heap that contains at least one live node. It also prints a summary containing:
If more than one table contains the maximum number of live nodes, only the one of lowest index is reported. Returns 1 in case of success and 0 otherwise.]
SideEffects [None]
SeeAlso []
Definition at line 635 of file cuddCheck.c.
00637 { 00638 int ntables = dd->size; 00639 DdSubtable *subtables = dd->subtables; 00640 int i, /* loop index */ 00641 nodes, /* live nodes in i-th layer */ 00642 retval, /* return value of fprintf */ 00643 largest = -1, /* index of the table with most live nodes */ 00644 maxnodes = -1, /* maximum number of live nodes in a table */ 00645 nonempty = 0; /* number of tables with live nodes */ 00646 00647 /* Print header. */ 00648 #if SIZEOF_VOID_P == 8 00649 retval = fprintf(dd->out,"*** DD heap profile for 0x%lx ***\n", 00650 (ptruint) dd); 00651 #else 00652 retval = fprintf(dd->out,"*** DD heap profile for 0x%x ***\n", 00653 (ptruint) dd); 00654 #endif 00655 if (retval == EOF) return 0; 00656 00657 /* Print number of live nodes for each nonempty table. */ 00658 for (i=0; i<ntables; i++) { 00659 nodes = subtables[i].keys - subtables[i].dead; 00660 if (nodes) { 00661 nonempty++; 00662 retval = fprintf(dd->out,"%5d: %5d nodes\n", i, nodes); 00663 if (retval == EOF) return 0; 00664 if (nodes > maxnodes) { 00665 maxnodes = nodes; 00666 largest = i; 00667 } 00668 } 00669 } 00670 00671 nodes = dd->constants.keys - dd->constants.dead; 00672 if (nodes) { 00673 nonempty++; 00674 retval = fprintf(dd->out,"const: %5d nodes\n", nodes); 00675 if (retval == EOF) return 0; 00676 if (nodes > maxnodes) { 00677 maxnodes = nodes; 00678 largest = CUDD_CONST_INDEX; 00679 } 00680 } 00681 00682 /* Print summary. */ 00683 retval = fprintf(dd->out,"Summary: %d tables, %d non-empty, largest: %d ", 00684 ntables+1, nonempty, largest); 00685 if (retval == EOF) return 0; 00686 retval = fprintf(dd->out,"(with %d nodes)\n", maxnodes); 00687 if (retval == EOF) return 0; 00688 00689 return(1); 00690 00691 } /* end of cuddHeapProfile */
int cuddInitCache | ( | DdManager * | unique, | |
unsigned int | cacheSize, | |||
unsigned int | maxCacheSize | |||
) |
AutomaticStart AutomaticEnd Function********************************************************************
Synopsis [Initializes the computed table.]
Description [Initializes the computed table. It is called by Cudd_Init. Returns 1 in case of success; 0 otherwise.]
SideEffects [None]
SeeAlso [Cudd_Init]
Definition at line 132 of file cuddCache.c.
00136 { 00137 int i; 00138 unsigned int logSize; 00139 #ifndef DD_CACHE_PROFILE 00140 DdNodePtr *mem; 00141 ptruint offset; 00142 #endif 00143 00144 /* Round cacheSize to largest power of 2 not greater than the requested 00145 ** initial cache size. */ 00146 logSize = cuddComputeFloorLog2(ddMax(cacheSize,unique->slots/2)); 00147 cacheSize = 1 << logSize; 00148 unique->acache = ALLOC(DdCache,cacheSize+1); 00149 if (unique->acache == NULL) { 00150 unique->errorCode = CUDD_MEMORY_OUT; 00151 return(0); 00152 } 00153 /* If the size of the cache entry is a power of 2, we want to 00154 ** enforce alignment to that power of two. This happens when 00155 ** DD_CACHE_PROFILE is not defined. */ 00156 #ifdef DD_CACHE_PROFILE 00157 unique->cache = unique->acache; 00158 unique->memused += (cacheSize) * sizeof(DdCache); 00159 #else 00160 mem = (DdNodePtr *) unique->acache; 00161 offset = (ptruint) mem & (sizeof(DdCache) - 1); 00162 mem += (sizeof(DdCache) - offset) / sizeof(DdNodePtr); 00163 unique->cache = (DdCache *) mem; 00164 assert(((ptruint) unique->cache & (sizeof(DdCache) - 1)) == 0); 00165 unique->memused += (cacheSize+1) * sizeof(DdCache); 00166 #endif 00167 unique->cacheSlots = cacheSize; 00168 unique->cacheShift = sizeof(int) * 8 - logSize; 00169 unique->maxCacheHard = maxCacheSize; 00170 /* If cacheSlack is non-negative, we can resize. */ 00171 unique->cacheSlack = (int) ddMin(maxCacheSize, 00172 DD_MAX_CACHE_TO_SLOTS_RATIO*unique->slots) - 00173 2 * (int) cacheSize; 00174 Cudd_SetMinHit(unique,DD_MIN_HIT); 00175 /* Initialize to avoid division by 0 and immediate resizing. */ 00176 unique->cacheMisses = (double) (int) (cacheSize * unique->minHit + 1); 00177 unique->cacheHits = 0; 00178 unique->totCachehits = 0; 00179 /* The sum of cacheMisses and totCacheMisses is always correct, 00180 ** even though cacheMisses is larger than it should for the reasons 00181 ** explained above. */ 00182 unique->totCacheMisses = -unique->cacheMisses; 00183 unique->cachecollisions = 0; 00184 unique->cacheinserts = 0; 00185 unique->cacheLastInserts = 0; 00186 unique->cachedeletions = 0; 00187 00188 /* Initialize the cache */ 00189 for (i = 0; (unsigned) i < cacheSize; i++) { 00190 unique->cache[i].h = 0; /* unused slots */ 00191 unique->cache[i].data = NULL; /* invalid entry */ 00192 #ifdef DD_CACHE_PROFILE 00193 unique->cache[i].count = 0; 00194 #endif 00195 } 00196 00197 return(1); 00198 00199 } /* end of cuddInitCache */
int cuddInitInteract | ( | DdManager * | table | ) |
Function********************************************************************
Synopsis [Initializes the interaction matrix.]
Description [Initializes the interaction matrix. The interaction matrix is implemented as a bit vector storing the upper triangle of the symmetric interaction matrix. The bit vector is kept in an array of long integers. The computation is based on a series of depth-first searches, one for each root of the DAG. Two flags are needed: The local visited flag uses the LSB of the then pointer. The global visited flag uses the LSB of the next pointer. Returns 1 if successful; 0 otherwise.]
SideEffects [None]
SeeAlso []
Definition at line 233 of file cuddInteract.c.
00235 { 00236 int i,j,k; 00237 int words; 00238 long *interact; 00239 int *support; 00240 DdNode *f; 00241 DdNode *sentinel = &(table->sentinel); 00242 DdNodePtr *nodelist; 00243 int slots; 00244 int n = table->size; 00245 00246 words = ((n * (n-1)) >> (1 + LOGBPL)) + 1; 00247 table->interact = interact = ALLOC(long,words); 00248 if (interact == NULL) { 00249 table->errorCode = CUDD_MEMORY_OUT; 00250 return(0); 00251 } 00252 for (i = 0; i < words; i++) { 00253 interact[i] = 0; 00254 } 00255 00256 support = ALLOC(int,n); 00257 if (support == NULL) { 00258 table->errorCode = CUDD_MEMORY_OUT; 00259 FREE(interact); 00260 return(0); 00261 } 00262 00263 for (i = 0; i < n; i++) { 00264 nodelist = table->subtables[i].nodelist; 00265 slots = table->subtables[i].slots; 00266 for (j = 0; j < slots; j++) { 00267 f = nodelist[j]; 00268 while (f != sentinel) { 00269 /* A node is a root of the DAG if it cannot be 00270 ** reached by nodes above it. If a node was never 00271 ** reached during the previous depth-first searches, 00272 ** then it is a root, and we start a new depth-first 00273 ** search from it. 00274 */ 00275 if (!Cudd_IsComplement(f->next)) { 00276 for (k = 0; k < n; k++) { 00277 support[k] = 0; 00278 } 00279 ddSuppInteract(f,support); 00280 ddClearLocal(f); 00281 ddUpdateInteract(table,support); 00282 } 00283 f = Cudd_Regular(f->next); 00284 } 00285 } 00286 } 00287 ddClearGlobal(table); 00288 00289 FREE(support); 00290 return(1); 00291 00292 } /* end of cuddInitInteract */
int cuddInitLinear | ( | DdManager * | table | ) |
Function********************************************************************
Synopsis [Initializes the linear transform matrix.]
Description [Initializes the linear transform matrix. Returns 1 if successful; 0 otherwise.]
SideEffects [none]
SeeAlso []
Definition at line 755 of file cuddLinear.c.
00757 { 00758 int words; 00759 int wordsPerRow; 00760 int nvars; 00761 int word; 00762 int bit; 00763 int i; 00764 long *linear; 00765 00766 nvars = table->size; 00767 wordsPerRow = ((nvars - 1) >> LOGBPL) + 1; 00768 words = wordsPerRow * nvars; 00769 table->linear = linear = ALLOC(long,words); 00770 if (linear == NULL) { 00771 table->errorCode = CUDD_MEMORY_OUT; 00772 return(0); 00773 } 00774 table->memused += words * sizeof(long); 00775 table->linearSize = nvars; 00776 for (i = 0; i < words; i++) linear[i] = 0; 00777 for (i = 0; i < nvars; i++) { 00778 word = wordsPerRow * i + (i >> LOGBPL); 00779 bit = i & (BPL-1); 00780 linear[word] = 1 << bit; 00781 } 00782 return(1); 00783 00784 } /* end of cuddInitLinear */
DdManager* cuddInitTable | ( | unsigned int | numVars, | |
unsigned int | numVarsZ, | |||
unsigned int | numSlots, | |||
unsigned int | looseUpTo | |||
) |
Function********************************************************************
Synopsis [Creates and initializes the unique table.]
Description [Creates and initializes the unique table. Returns a pointer to the table if successful; NULL otherwise.]
SideEffects [None]
SeeAlso [Cudd_Init cuddFreeTable]
Definition at line 341 of file cuddTable.c.
00346 { 00347 DdManager *unique = ALLOC(DdManager,1); 00348 int i, j; 00349 DdNodePtr *nodelist; 00350 DdNode *sentinel; 00351 unsigned int slots; 00352 int shift; 00353 00354 if (unique == NULL) { 00355 return(NULL); 00356 } 00357 sentinel = &(unique->sentinel); 00358 sentinel->ref = 0; 00359 sentinel->index = 0; 00360 cuddT(sentinel) = NULL; 00361 cuddE(sentinel) = NULL; 00362 sentinel->next = NULL; 00363 unique->epsilon = DD_EPSILON; 00364 unique->maxGrowth = DD_MAX_REORDER_GROWTH; 00365 unique->maxGrowthAlt = 2.0 * DD_MAX_REORDER_GROWTH; 00366 unique->reordCycle = 0; /* do not use alternate threshold */ 00367 unique->size = numVars; 00368 unique->sizeZ = numVarsZ; 00369 unique->maxSize = ddMax(DD_DEFAULT_RESIZE, numVars); 00370 unique->maxSizeZ = ddMax(DD_DEFAULT_RESIZE, numVarsZ); 00371 00372 /* Adjust the requested number of slots to a power of 2. */ 00373 slots = 8; 00374 while (slots < numSlots) { 00375 slots <<= 1; 00376 } 00377 unique->initSlots = slots; 00378 shift = sizeof(int) * 8 - cuddComputeFloorLog2(slots); 00379 00380 unique->slots = (numVars + numVarsZ + 1) * slots; 00381 unique->keys = 0; 00382 unique->maxLive = ~0; /* very large number */ 00383 unique->keysZ = 0; 00384 unique->dead = 0; 00385 unique->deadZ = 0; 00386 unique->gcFrac = DD_GC_FRAC_HI; 00387 unique->minDead = (unsigned) (DD_GC_FRAC_HI * (double) unique->slots); 00388 unique->looseUpTo = looseUpTo; 00389 unique->gcEnabled = 1; 00390 unique->allocated = 0; 00391 unique->reclaimed = 0; 00392 unique->subtables = ALLOC(DdSubtable,unique->maxSize); 00393 if (unique->subtables == NULL) { 00394 FREE(unique); 00395 return(NULL); 00396 } 00397 unique->subtableZ = ALLOC(DdSubtable,unique->maxSizeZ); 00398 if (unique->subtableZ == NULL) { 00399 FREE(unique->subtables); 00400 FREE(unique); 00401 return(NULL); 00402 } 00403 unique->perm = ALLOC(int,unique->maxSize); 00404 if (unique->perm == NULL) { 00405 FREE(unique->subtables); 00406 FREE(unique->subtableZ); 00407 FREE(unique); 00408 return(NULL); 00409 } 00410 unique->invperm = ALLOC(int,unique->maxSize); 00411 if (unique->invperm == NULL) { 00412 FREE(unique->subtables); 00413 FREE(unique->subtableZ); 00414 FREE(unique->perm); 00415 FREE(unique); 00416 return(NULL); 00417 } 00418 unique->permZ = ALLOC(int,unique->maxSizeZ); 00419 if (unique->permZ == NULL) { 00420 FREE(unique->subtables); 00421 FREE(unique->subtableZ); 00422 FREE(unique->perm); 00423 FREE(unique->invperm); 00424 FREE(unique); 00425 return(NULL); 00426 } 00427 unique->invpermZ = ALLOC(int,unique->maxSizeZ); 00428 if (unique->invpermZ == NULL) { 00429 FREE(unique->subtables); 00430 FREE(unique->subtableZ); 00431 FREE(unique->perm); 00432 FREE(unique->invperm); 00433 FREE(unique->permZ); 00434 FREE(unique); 00435 return(NULL); 00436 } 00437 unique->map = NULL; 00438 unique->stack = ALLOC(DdNodePtr,ddMax(unique->maxSize,unique->maxSizeZ)+1); 00439 if (unique->stack == NULL) { 00440 FREE(unique->subtables); 00441 FREE(unique->subtableZ); 00442 FREE(unique->perm); 00443 FREE(unique->invperm); 00444 FREE(unique->permZ); 00445 FREE(unique->invpermZ); 00446 FREE(unique); 00447 return(NULL); 00448 } 00449 unique->stack[0] = NULL; /* to suppress harmless UMR */ 00450 00451 #ifndef DD_NO_DEATH_ROW 00452 unique->deathRowDepth = 1 << cuddComputeFloorLog2(unique->looseUpTo >> 2); 00453 unique->deathRow = ALLOC(DdNodePtr,unique->deathRowDepth); 00454 if (unique->deathRow == NULL) { 00455 FREE(unique->subtables); 00456 FREE(unique->subtableZ); 00457 FREE(unique->perm); 00458 FREE(unique->invperm); 00459 FREE(unique->permZ); 00460 FREE(unique->invpermZ); 00461 FREE(unique->stack); 00462 FREE(unique); 00463 return(NULL); 00464 } 00465 for (i = 0; i < unique->deathRowDepth; i++) { 00466 unique->deathRow[i] = NULL; 00467 } 00468 unique->nextDead = 0; 00469 unique->deadMask = unique->deathRowDepth - 1; 00470 #endif 00471 00472 for (i = 0; (unsigned) i < numVars; i++) { 00473 unique->subtables[i].slots = slots; 00474 unique->subtables[i].shift = shift; 00475 unique->subtables[i].keys = 0; 00476 unique->subtables[i].dead = 0; 00477 unique->subtables[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; 00478 unique->subtables[i].bindVar = 0; 00479 unique->subtables[i].varType = CUDD_VAR_PRIMARY_INPUT; 00480 unique->subtables[i].pairIndex = 0; 00481 unique->subtables[i].varHandled = 0; 00482 unique->subtables[i].varToBeGrouped = CUDD_LAZY_NONE; 00483 00484 nodelist = unique->subtables[i].nodelist = ALLOC(DdNodePtr,slots); 00485 if (nodelist == NULL) { 00486 for (j = 0; j < i; j++) { 00487 FREE(unique->subtables[j].nodelist); 00488 } 00489 FREE(unique->subtables); 00490 FREE(unique->subtableZ); 00491 FREE(unique->perm); 00492 FREE(unique->invperm); 00493 FREE(unique->permZ); 00494 FREE(unique->invpermZ); 00495 FREE(unique->stack); 00496 FREE(unique); 00497 return(NULL); 00498 } 00499 for (j = 0; (unsigned) j < slots; j++) { 00500 nodelist[j] = sentinel; 00501 } 00502 unique->perm[i] = i; 00503 unique->invperm[i] = i; 00504 } 00505 for (i = 0; (unsigned) i < numVarsZ; i++) { 00506 unique->subtableZ[i].slots = slots; 00507 unique->subtableZ[i].shift = shift; 00508 unique->subtableZ[i].keys = 0; 00509 unique->subtableZ[i].dead = 0; 00510 unique->subtableZ[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; 00511 nodelist = unique->subtableZ[i].nodelist = ALLOC(DdNodePtr,slots); 00512 if (nodelist == NULL) { 00513 for (j = 0; (unsigned) j < numVars; j++) { 00514 FREE(unique->subtables[j].nodelist); 00515 } 00516 FREE(unique->subtables); 00517 for (j = 0; j < i; j++) { 00518 FREE(unique->subtableZ[j].nodelist); 00519 } 00520 FREE(unique->subtableZ); 00521 FREE(unique->perm); 00522 FREE(unique->invperm); 00523 FREE(unique->permZ); 00524 FREE(unique->invpermZ); 00525 FREE(unique->stack); 00526 FREE(unique); 00527 return(NULL); 00528 } 00529 for (j = 0; (unsigned) j < slots; j++) { 00530 nodelist[j] = NULL; 00531 } 00532 unique->permZ[i] = i; 00533 unique->invpermZ[i] = i; 00534 } 00535 unique->constants.slots = slots; 00536 unique->constants.shift = shift; 00537 unique->constants.keys = 0; 00538 unique->constants.dead = 0; 00539 unique->constants.maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; 00540 nodelist = unique->constants.nodelist = ALLOC(DdNodePtr,slots); 00541 if (nodelist == NULL) { 00542 for (j = 0; (unsigned) j < numVars; j++) { 00543 FREE(unique->subtables[j].nodelist); 00544 } 00545 FREE(unique->subtables); 00546 for (j = 0; (unsigned) j < numVarsZ; j++) { 00547 FREE(unique->subtableZ[j].nodelist); 00548 } 00549 FREE(unique->subtableZ); 00550 FREE(unique->perm); 00551 FREE(unique->invperm); 00552 FREE(unique->permZ); 00553 FREE(unique->invpermZ); 00554 FREE(unique->stack); 00555 FREE(unique); 00556 return(NULL); 00557 } 00558 for (j = 0; (unsigned) j < slots; j++) { 00559 nodelist[j] = NULL; 00560 } 00561 00562 unique->memoryList = NULL; 00563 unique->nextFree = NULL; 00564 00565 unique->memused = sizeof(DdManager) + (unique->maxSize + unique->maxSizeZ) 00566 * (sizeof(DdSubtable) + 2 * sizeof(int)) + (numVars + 1) * 00567 slots * sizeof(DdNodePtr) + 00568 (ddMax(unique->maxSize,unique->maxSizeZ) + 1) * sizeof(DdNodePtr); 00569 #ifndef DD_NO_DEATH_ROW 00570 unique->memused += unique->deathRowDepth * sizeof(DdNodePtr); 00571 #endif 00572 00573 /* Initialize fields concerned with automatic dynamic reordering */ 00574 unique->reorderings = 0; 00575 unique->autoDyn = 0; /* initially disabled */ 00576 unique->autoDynZ = 0; /* initially disabled */ 00577 unique->realign = 0; /* initially disabled */ 00578 unique->realignZ = 0; /* initially disabled */ 00579 unique->reordered = 0; 00580 unique->autoMethod = CUDD_REORDER_SIFT; 00581 unique->autoMethodZ = CUDD_REORDER_SIFT; 00582 unique->nextDyn = DD_FIRST_REORDER; 00583 unique->countDead = ~0; 00584 unique->siftMaxVar = DD_SIFT_MAX_VAR; 00585 unique->siftMaxSwap = DD_SIFT_MAX_SWAPS; 00586 unique->tree = NULL; 00587 unique->treeZ = NULL; 00588 unique->groupcheck = CUDD_GROUP_CHECK7; 00589 unique->recomb = DD_DEFAULT_RECOMB; 00590 unique->symmviolation = 0; 00591 unique->arcviolation = 0; 00592 unique->populationSize = 0; 00593 unique->numberXovers = 0; 00594 unique->linear = NULL; 00595 unique->linearSize = 0; 00596 00597 /* Initialize ZDD universe. */ 00598 unique->univ = (DdNodePtr *)NULL; 00599 00600 /* Initialize auxiliary fields. */ 00601 unique->localCaches = NULL; 00602 unique->preGCHook = NULL; 00603 unique->postGCHook = NULL; 00604 unique->preReorderingHook = NULL; 00605 unique->postReorderingHook = NULL; 00606 unique->out = stdout; 00607 unique->err = stderr; 00608 unique->errorCode = CUDD_NO_ERROR; 00609 00610 /* Initialize statistical counters. */ 00611 unique->maxmemhard = ~ 0UL; 00612 unique->garbageCollections = 0; 00613 unique->GCTime = 0; 00614 unique->reordTime = 0; 00615 #ifdef DD_STATS 00616 unique->nodesDropped = 0; 00617 unique->nodesFreed = 0; 00618 #endif 00619 unique->peakLiveNodes = 0; 00620 #ifdef DD_UNIQUE_PROFILE 00621 unique->uniqueLookUps = 0; 00622 unique->uniqueLinks = 0; 00623 #endif 00624 #ifdef DD_COUNT 00625 unique->recursiveCalls = 0; 00626 unique->swapSteps = 0; 00627 #ifdef DD_STATS 00628 unique->nextSample = 250000; 00629 #endif 00630 #endif 00631 00632 return(unique); 00633 00634 } /* end of cuddInitTable */
int cuddInsertSubtables | ( | DdManager * | unique, | |
int | n, | |||
int | level | |||
) |
Function********************************************************************
Synopsis [Inserts n new subtables in a unique table at level.]
Description [Inserts n new subtables in a unique table at level. The number n should be positive, and level should be an existing level. Returns 1 if successful; 0 otherwise.]
SideEffects [None]
SeeAlso [cuddDestroySubtables]
Definition at line 1780 of file cuddTable.c.
01784 { 01785 DdSubtable *newsubtables; 01786 DdNodePtr *newnodelist; 01787 DdNodePtr *newvars; 01788 DdNode *sentinel = &(unique->sentinel); 01789 int oldsize,newsize; 01790 int i,j,index,reorderSave; 01791 unsigned int numSlots = unique->initSlots; 01792 int *newperm, *newinvperm, *newmap; 01793 DdNode *one, *zero; 01794 01795 #ifdef DD_DEBUG 01796 assert(n > 0 && level < unique->size); 01797 #endif 01798 01799 oldsize = unique->size; 01800 /* Easy case: there is still room in the current table. */ 01801 if (oldsize + n <= unique->maxSize) { 01802 /* Shift the tables at and below level. */ 01803 for (i = oldsize - 1; i >= level; i--) { 01804 unique->subtables[i+n].slots = unique->subtables[i].slots; 01805 unique->subtables[i+n].shift = unique->subtables[i].shift; 01806 unique->subtables[i+n].keys = unique->subtables[i].keys; 01807 unique->subtables[i+n].maxKeys = unique->subtables[i].maxKeys; 01808 unique->subtables[i+n].dead = unique->subtables[i].dead; 01809 unique->subtables[i+n].nodelist = unique->subtables[i].nodelist; 01810 unique->subtables[i+n].bindVar = unique->subtables[i].bindVar; 01811 unique->subtables[i+n].varType = unique->subtables[i].varType; 01812 unique->subtables[i+n].pairIndex = unique->subtables[i].pairIndex; 01813 unique->subtables[i+n].varHandled = unique->subtables[i].varHandled; 01814 unique->subtables[i+n].varToBeGrouped = 01815 unique->subtables[i].varToBeGrouped; 01816 01817 index = unique->invperm[i]; 01818 unique->invperm[i+n] = index; 01819 unique->perm[index] += n; 01820 } 01821 /* Create new subtables. */ 01822 for (i = 0; i < n; i++) { 01823 unique->subtables[level+i].slots = numSlots; 01824 unique->subtables[level+i].shift = sizeof(int) * 8 - 01825 cuddComputeFloorLog2(numSlots); 01826 unique->subtables[level+i].keys = 0; 01827 unique->subtables[level+i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY; 01828 unique->subtables[level+i].dead = 0; 01829 unique->subtables[level+i].bindVar = 0; 01830 unique->subtables[level+i].varType = CUDD_VAR_PRIMARY_INPUT; 01831 unique->subtables[level+i].pairIndex = 0; 01832 unique->subtables[level+i].varHandled = 0; 01833 unique->subtables[level+i].varToBeGrouped = CUDD_LAZY_NONE; 01834 01835 unique->perm[oldsize+i] = level + i; 01836 unique->invperm[level+i] = oldsize + i; 01837 newnodelist = unique->subtables[level+i].nodelist = 01838 ALLOC(DdNodePtr, numSlots); 01839 if (newnodelist == NULL) { 01840 unique->errorCode = CUDD_MEMORY_OUT; 01841 return(0); 01842 } 01843 for (j = 0; (unsigned) j < numSlots; j++) { 01844 newnodelist[j] = sentinel; 01845 } 01846 } 01847 if (unique->map != NULL) { 01848 for (i = 0; i < n; i++) { 01849 unique->map[oldsize+i] = oldsize + i; 01850 } 01851 } 01852 } else { 01853 /* The current table is too small: we need to allocate a new, 01854 ** larger one; move all old subtables, and initialize the new 01855 ** subtables. 01856 */ 01857 newsize = oldsize + n + DD_DEFAULT_RESIZE; 01858 #ifdef DD_VERBOSE 01859 (void) fprintf(unique->err, 01860 "Increasing the table size from %d to %d\n", 01861 unique->maxSize, newsize); 01862 #endif 01863 /* Allocate memory for new arrays (except nodelists). */ 01864 newsubtables = ALLOC(DdSubtable,newsize); 01865 if (newsubtables == NULL) { 01866 unique->errorCode = CUDD_MEMORY_OUT; 01867 return(0); 01868 } 01869 newvars = ALLOC(DdNodePtr,newsize); 01870 if (newvars == NULL) { 01871 unique->errorCode = CUDD_MEMORY_OUT; 01872 FREE(newsubtables); 01873 return(0); 01874 } 01875 newperm = ALLOC(int,newsize); 01876 if (newperm == NULL) { 01877 unique->errorCode = CUDD_MEMORY_OUT; 01878 FREE(newsubtables); 01879 FREE(newvars); 01880 return(0); 01881 } 01882 newinvperm = ALLOC(int,newsize); 01883 if (newinvperm == NULL) { 01884 unique->errorCode = CUDD_MEMORY_OUT; 01885 FREE(newsubtables); 01886 FREE(newvars); 01887 FREE(newperm); 01888 return(0); 01889 } 01890 if (unique->map != NULL) { 01891 newmap = ALLOC(int,newsize); 01892 if (newmap == NULL) { 01893 unique->errorCode = CUDD_MEMORY_OUT; 01894 FREE(newsubtables); 01895 FREE(newvars); 01896 FREE(newperm); 01897 FREE(newinvperm); 01898 return(0); 01899 } 01900 unique->memused += (newsize - unique->maxSize) * sizeof(int); 01901 } 01902 unique->memused += (newsize - unique->maxSize) * ((numSlots+1) * 01903 sizeof(DdNode *) + 2 * sizeof(int) + sizeof(DdSubtable)); 01904 /* Copy levels before insertion points from old tables. */ 01905 for (i = 0; i < level; i++) { 01906 newsubtables[i].slots = unique->subtables[i].slots; 01907 newsubtables[i].shift = unique->subtables[i].shift; 01908 newsubtables[i].keys = unique->subtables[i].keys; 01909 newsubtables[i].maxKeys = unique->subtables[i].maxKeys; 01910 newsubtables[i].dead = unique->subtables[i].dead; 01911 newsubtables[i].nodelist = unique->subtables[i].nodelist; 01912 newsubtables[i].bindVar = unique->subtables[i].bindVar; 01913 newsubtables[i].varType = unique->subtables[i].varType; 01914 newsubtables[i].pairIndex = unique->subtables[i].pairIndex; 01915 newsubtables[i].varHandled = unique->subtables[i].varHandled; 01916 newsubtables[i].varToBeGrouped = unique->subtables[i].varToBeGrouped; 01917 01918 newvars[i] = unique->vars[i]; 01919 newperm[i] = unique->perm[i]; 01920 newinvperm[i] = unique->invperm[i]; 01921 } 01922 /* Finish initializing permutation for new table to old one. */ 01923 for (i = level; i < oldsize; i++) { 01924 newperm[i] = unique->perm[i]; 01925 } 01926 /* Initialize new levels. */ 01927 for (i = level; i < level + n; i++) { 01928 newsubtables[i].slots = numSlots; 01929 newsubtables[i].shift = sizeof(int) * 8 - 01930 cuddComputeFloorLog2(numSlots); 01931 newsubtables[i].keys = 0; 01932 newsubtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY; 01933 newsubtables[i].dead = 0; 01934 newsubtables[i].bindVar = 0; 01935 newsubtables[i].varType = CUDD_VAR_PRIMARY_INPUT; 01936 newsubtables[i].pairIndex = 0; 01937 newsubtables[i].varHandled = 0; 01938 newsubtables[i].varToBeGrouped = CUDD_LAZY_NONE; 01939 01940 newperm[oldsize + i - level] = i; 01941 newinvperm[i] = oldsize + i - level; 01942 newnodelist = newsubtables[i].nodelist = ALLOC(DdNodePtr, numSlots); 01943 if (newnodelist == NULL) { 01944 /* We are going to leak some memory. We should clean up. */ 01945 unique->errorCode = CUDD_MEMORY_OUT; 01946 return(0); 01947 } 01948 for (j = 0; (unsigned) j < numSlots; j++) { 01949 newnodelist[j] = sentinel; 01950 } 01951 } 01952 /* Copy the old tables for levels past the insertion point. */ 01953 for (i = level; i < oldsize; i++) { 01954 newsubtables[i+n].slots = unique->subtables[i].slots; 01955 newsubtables[i+n].shift = unique->subtables[i].shift; 01956 newsubtables[i+n].keys = unique->subtables[i].keys; 01957 newsubtables[i+n].maxKeys = unique->subtables[i].maxKeys; 01958 newsubtables[i+n].dead = unique->subtables[i].dead; 01959 newsubtables[i+n].nodelist = unique->subtables[i].nodelist; 01960 newsubtables[i+n].bindVar = unique->subtables[i].bindVar; 01961 newsubtables[i+n].varType = unique->subtables[i].varType; 01962 newsubtables[i+n].pairIndex = unique->subtables[i].pairIndex; 01963 newsubtables[i+n].varHandled = unique->subtables[i].varHandled; 01964 newsubtables[i+n].varToBeGrouped = 01965 unique->subtables[i].varToBeGrouped; 01966 01967 newvars[i] = unique->vars[i]; 01968 index = unique->invperm[i]; 01969 newinvperm[i+n] = index; 01970 newperm[index] += n; 01971 } 01972 /* Update the map. */ 01973 if (unique->map != NULL) { 01974 for (i = 0; i < oldsize; i++) { 01975 newmap[i] = unique->map[i]; 01976 } 01977 for (i = oldsize; i < oldsize + n; i++) { 01978 newmap[i] = i; 01979 } 01980 FREE(unique->map); 01981 unique->map = newmap; 01982 } 01983 /* Install the new tables and free the old ones. */ 01984 FREE(unique->subtables); 01985 unique->subtables = newsubtables; 01986 unique->maxSize = newsize; 01987 FREE(unique->vars); 01988 unique->vars = newvars; 01989 FREE(unique->perm); 01990 unique->perm = newperm; 01991 FREE(unique->invperm); 01992 unique->invperm = newinvperm; 01993 /* Update the stack for iterative procedures. */ 01994 if (newsize > unique->maxSizeZ) { 01995 FREE(unique->stack); 01996 unique->stack = ALLOC(DdNodePtr,newsize + 1); 01997 if (unique->stack == NULL) { 01998 unique->errorCode = CUDD_MEMORY_OUT; 01999 return(0); 02000 } 02001 unique->stack[0] = NULL; /* to suppress harmless UMR */ 02002 unique->memused += 02003 (newsize - ddMax(unique->maxSize,unique->maxSizeZ)) 02004 * sizeof(DdNode *); 02005 } 02006 } 02007 /* Update manager parameters to account for the new subtables. */ 02008 unique->slots += n * numSlots; 02009 ddFixLimits(unique); 02010 unique->size += n; 02011 02012 /* Now that the table is in a coherent state, create the new 02013 ** projection functions. We need to temporarily disable reordering, 02014 ** because we cannot reorder without projection functions in place. 02015 **/ 02016 one = unique->one; 02017 zero = Cudd_Not(one); 02018 02019 reorderSave = unique->autoDyn; 02020 unique->autoDyn = 0; 02021 for (i = oldsize; i < oldsize + n; i++) { 02022 unique->vars[i] = cuddUniqueInter(unique,i,one,zero); 02023 if (unique->vars[i] == NULL) { 02024 unique->autoDyn = reorderSave; 02025 /* Shift everything back so table remains coherent. */ 02026 for (j = oldsize; j < i; j++) { 02027 Cudd_IterDerefBdd(unique,unique->vars[j]); 02028 cuddDeallocNode(unique,unique->vars[j]); 02029 unique->vars[j] = NULL; 02030 } 02031 for (j = level; j < oldsize; j++) { 02032 unique->subtables[j].slots = unique->subtables[j+n].slots; 02033 unique->subtables[j].slots = unique->subtables[j+n].slots; 02034 unique->subtables[j].shift = unique->subtables[j+n].shift; 02035 unique->subtables[j].keys = unique->subtables[j+n].keys; 02036 unique->subtables[j].maxKeys = 02037 unique->subtables[j+n].maxKeys; 02038 unique->subtables[j].dead = unique->subtables[j+n].dead; 02039 FREE(unique->subtables[j].nodelist); 02040 unique->subtables[j].nodelist = 02041 unique->subtables[j+n].nodelist; 02042 unique->subtables[j+n].nodelist = NULL; 02043 unique->subtables[j].bindVar = 02044 unique->subtables[j+n].bindVar; 02045 unique->subtables[j].varType = 02046 unique->subtables[j+n].varType; 02047 unique->subtables[j].pairIndex = 02048 unique->subtables[j+n].pairIndex; 02049 unique->subtables[j].varHandled = 02050 unique->subtables[j+n].varHandled; 02051 unique->subtables[j].varToBeGrouped = 02052 unique->subtables[j+n].varToBeGrouped; 02053 index = unique->invperm[j+n]; 02054 unique->invperm[j] = index; 02055 unique->perm[index] -= n; 02056 } 02057 unique->size = oldsize; 02058 unique->slots -= n * numSlots; 02059 ddFixLimits(unique); 02060 (void) Cudd_DebugCheck(unique); 02061 return(0); 02062 } 02063 cuddRef(unique->vars[i]); 02064 } 02065 if (unique->tree != NULL) { 02066 unique->tree->size += n; 02067 unique->tree->index = unique->invperm[0]; 02068 ddPatchTree(unique,unique->tree); 02069 } 02070 unique->autoDyn = reorderSave; 02071 02072 return(1); 02073 02074 } /* end of cuddInsertSubtables */
Function********************************************************************
Synopsis [Checks whether a node is in the death row.]
Description [Checks whether a node is in the death row. Returns the position of the first occurrence if the node is present; -1 otherwise.]
SideEffects [None]
SeeAlso [Cudd_DelayedDerefBdd cuddClearDeathRow]
Definition at line 758 of file cuddRef.c.
00761 { 00762 #ifndef DD_NO_DEATH_ROW 00763 int i; 00764 00765 for (i = 0; i < dd->deathRowDepth; i++) { 00766 if (f == dd->deathRow[i]) { 00767 return(i); 00768 } 00769 } 00770 #endif 00771 00772 return(-1); 00773 00774 } /* end of cuddIsInDeathRow */
void cuddLevelQueueDequeue | ( | DdLevelQueue * | queue, | |
int | level | |||
) |
Function********************************************************************
Synopsis [Remove an item from the front of a level queue.]
Description [Remove an item from the front of a level queue.]
SideEffects [None]
SeeAlso [cuddLevelQueueEnqueue]
Definition at line 350 of file cuddLevelQ.c.
00353 { 00354 DdQueueItem *item = (DdQueueItem *) queue->first; 00355 00356 /* Delete from the hash table. */ 00357 hashDelete(queue,item); 00358 00359 /* Since we delete from the front, if this is the last item for 00360 ** its level, there are no other items for the same level. */ 00361 if (queue->last[level] == item) 00362 queue->last[level] = NULL; 00363 00364 queue->first = item->next; 00365 /* Put item on the free list. */ 00366 item->next = queue->freelist; 00367 queue->freelist = item; 00368 /* Update stats. */ 00369 queue->size--; 00370 return; 00371 00372 } /* end of cuddLevelQueueDequeue */
void* cuddLevelQueueEnqueue | ( | DdLevelQueue * | queue, | |
void * | key, | |||
int | level | |||
) |
Function********************************************************************
Synopsis [Inserts a new key in a level queue.]
Description [Inserts a new key in a level queue. A new entry is created in the queue only if the node is not already enqueued. Returns a pointer to the queue item if successful; NULL otherwise.]
SideEffects [None]
SeeAlso [cuddLevelQueueInit cuddLevelQueueDequeue]
Definition at line 278 of file cuddLevelQ.c.
00282 { 00283 int plevel; 00284 DdQueueItem *item; 00285 00286 #ifdef DD_DEBUG 00287 assert(level < queue->levels); 00288 #endif 00289 /* Check whether entry for this node exists. */ 00290 item = hashLookup(queue,key); 00291 if (item != NULL) return(item); 00292 00293 /* Get a free item from either the free list or the memory manager. */ 00294 if (queue->freelist == NULL) { 00295 item = (DdQueueItem *) ALLOC(char, queue->itemsize); 00296 if (item == NULL) 00297 return(NULL); 00298 } else { 00299 item = queue->freelist; 00300 queue->freelist = item->next; 00301 } 00302 /* Initialize. */ 00303 memset(item, 0, queue->itemsize); 00304 item->key = key; 00305 /* Update stats. */ 00306 queue->size++; 00307 00308 if (queue->last[level]) { 00309 /* There are already items for this level in the queue. */ 00310 item->next = queue->last[level]->next; 00311 queue->last[level]->next = item; 00312 } else { 00313 /* There are no items at the current level. Look for the first 00314 ** non-empty level preceeding this one. */ 00315 plevel = level; 00316 while (plevel != 0 && queue->last[plevel] == NULL) 00317 plevel--; 00318 if (queue->last[plevel] == NULL) { 00319 /* No element precedes this one in the queue. */ 00320 item->next = (DdQueueItem *) queue->first; 00321 queue->first = item; 00322 } else { 00323 item->next = queue->last[plevel]->next; 00324 queue->last[plevel]->next = item; 00325 } 00326 } 00327 queue->last[level] = item; 00328 00329 /* Insert entry for the key in the hash table. */ 00330 if (hashInsert(queue,item) == 0) { 00331 return(NULL); 00332 } 00333 return(item); 00334 00335 } /* end of cuddLevelQueueEnqueue */
DdLevelQueue* cuddLevelQueueInit | ( | int | levels, | |
int | itemSize, | |||
int | numBuckets | |||
) |
AutomaticEnd Function********************************************************************
Synopsis [Initializes a level queue.]
Description [Initializes a level queue. A level queue is a queue where inserts are based on the levels of the nodes. Within each level the policy is FIFO. Level queues are useful in traversing a BDD top-down. Queue items are kept in a free list when dequeued for efficiency. Returns a pointer to the new queue if successful; NULL otherwise.]
SideEffects [None]
SeeAlso [cuddLevelQueueQuit cuddLevelQueueEnqueue cuddLevelQueueDequeue]
Definition at line 165 of file cuddLevelQ.c.
00169 { 00170 DdLevelQueue *queue; 00171 int logSize; 00172 00173 queue = ALLOC(DdLevelQueue,1); 00174 if (queue == NULL) 00175 return(NULL); 00176 #ifdef __osf__ 00177 #pragma pointer_size save 00178 #pragma pointer_size short 00179 #endif 00180 /* Keep pointers to the insertion points for all levels. */ 00181 queue->last = ALLOC(DdQueueItem *, levels); 00182 #ifdef __osf__ 00183 #pragma pointer_size restore 00184 #endif 00185 if (queue->last == NULL) { 00186 FREE(queue); 00187 return(NULL); 00188 } 00189 /* Use a hash table to test for uniqueness. */ 00190 if (numBuckets < 2) numBuckets = 2; 00191 logSize = cuddComputeFloorLog2(numBuckets); 00192 queue->numBuckets = 1 << logSize; 00193 queue->shift = sizeof(int) * 8 - logSize; 00194 #ifdef __osf__ 00195 #pragma pointer_size save 00196 #pragma pointer_size short 00197 #endif 00198 queue->buckets = ALLOC(DdQueueItem *, queue->numBuckets); 00199 #ifdef __osf__ 00200 #pragma pointer_size restore 00201 #endif 00202 if (queue->buckets == NULL) { 00203 FREE(queue->last); 00204 FREE(queue); 00205 return(NULL); 00206 } 00207 #ifdef __osf__ 00208 #pragma pointer_size save 00209 #pragma pointer_size short 00210 #endif 00211 memset(queue->last, 0, levels * sizeof(DdQueueItem *)); 00212 memset(queue->buckets, 0, queue->numBuckets * sizeof(DdQueueItem *)); 00213 #ifdef __osf__ 00214 #pragma pointer_size restore 00215 #endif 00216 queue->first = NULL; 00217 queue->freelist = NULL; 00218 queue->levels = levels; 00219 queue->itemsize = itemSize; 00220 queue->size = 0; 00221 queue->maxsize = queue->numBuckets * DD_MAX_SUBTABLE_DENSITY; 00222 return(queue); 00223 00224 } /* end of cuddLevelQueueInit */
void cuddLevelQueueQuit | ( | DdLevelQueue * | queue | ) |
Function********************************************************************
Synopsis [Shuts down a level queue.]
Description [Shuts down a level queue and releases all the associated memory.]
SideEffects [None]
SeeAlso [cuddLevelQueueInit]
Definition at line 240 of file cuddLevelQ.c.
00242 { 00243 DdQueueItem *item; 00244 00245 while (queue->freelist != NULL) { 00246 item = queue->freelist; 00247 queue->freelist = item->next; 00248 FREE(item); 00249 } 00250 while (queue->first != NULL) { 00251 item = (DdQueueItem *) queue->first; 00252 queue->first = item->next; 00253 FREE(item); 00254 } 00255 FREE(queue->buckets); 00256 FREE(queue->last); 00257 FREE(queue); 00258 return; 00259 00260 } /* end of cuddLevelQueueQuit */
int cuddLinearAndSifting | ( | DdManager * | table, | |
int | lower, | |||
int | upper | |||
) |
Function********************************************************************
Synopsis [BDD reduction based on combination of sifting and linear transformations.]
Description [BDD reduction based on combination of sifting and linear transformations. Assumes that no dead nodes are present.
Returns 1 if successful; 0 otherwise.]
SideEffects [None]
Definition at line 236 of file cuddLinear.c.
00240 { 00241 int i; 00242 int *var; 00243 int size; 00244 int x; 00245 int result; 00246 #ifdef DD_STATS 00247 int previousSize; 00248 #endif 00249 00250 #ifdef DD_STATS 00251 ddTotalNumberLinearTr = 0; 00252 #endif 00253 00254 size = table->size; 00255 00256 var = NULL; 00257 entry = NULL; 00258 if (table->linear == NULL) { 00259 result = cuddInitLinear(table); 00260 if (result == 0) goto cuddLinearAndSiftingOutOfMem; 00261 #if 0 00262 (void) fprintf(table->out,"\n"); 00263 result = Cudd_PrintLinear(table); 00264 if (result == 0) goto cuddLinearAndSiftingOutOfMem; 00265 #endif 00266 } else if (table->size != table->linearSize) { 00267 result = cuddResizeLinear(table); 00268 if (result == 0) goto cuddLinearAndSiftingOutOfMem; 00269 #if 0 00270 (void) fprintf(table->out,"\n"); 00271 result = Cudd_PrintLinear(table); 00272 if (result == 0) goto cuddLinearAndSiftingOutOfMem; 00273 #endif 00274 } 00275 00276 /* Find order in which to sift variables. */ 00277 entry = ALLOC(int,size); 00278 if (entry == NULL) { 00279 table->errorCode = CUDD_MEMORY_OUT; 00280 goto cuddLinearAndSiftingOutOfMem; 00281 } 00282 var = ALLOC(int,size); 00283 if (var == NULL) { 00284 table->errorCode = CUDD_MEMORY_OUT; 00285 goto cuddLinearAndSiftingOutOfMem; 00286 } 00287 00288 for (i = 0; i < size; i++) { 00289 x = table->perm[i]; 00290 entry[i] = table->subtables[x].keys; 00291 var[i] = i; 00292 } 00293 00294 qsort((void *)var,size,sizeof(int),(DD_QSFP)ddLinearUniqueCompare); 00295 00296 /* Now sift. */ 00297 for (i = 0; i < ddMin(table->siftMaxVar,size); i++) { 00298 x = table->perm[var[i]]; 00299 if (x < lower || x > upper) continue; 00300 #ifdef DD_STATS 00301 previousSize = table->keys - table->isolated; 00302 #endif 00303 result = ddLinearAndSiftingAux(table,x,lower,upper); 00304 if (!result) goto cuddLinearAndSiftingOutOfMem; 00305 #ifdef DD_STATS 00306 if (table->keys < (unsigned) previousSize + table->isolated) { 00307 (void) fprintf(table->out,"-"); 00308 } else if (table->keys > (unsigned) previousSize + table->isolated) { 00309 (void) fprintf(table->out,"+"); /* should never happen */ 00310 (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keys - table->isolated, var[i]); 00311 } else { 00312 (void) fprintf(table->out,"="); 00313 } 00314 fflush(table->out); 00315 #endif 00316 #ifdef DD_DEBUG 00317 (void) Cudd_DebugCheck(table); 00318 #endif 00319 } 00320 00321 FREE(var); 00322 FREE(entry); 00323 00324 #ifdef DD_STATS 00325 (void) fprintf(table->out,"\n#:L_LINSIFT %8d: linear trans.", 00326 ddTotalNumberLinearTr); 00327 #endif 00328 00329 return(1); 00330 00331 cuddLinearAndSiftingOutOfMem: 00332 00333 if (entry != NULL) FREE(entry); 00334 if (var != NULL) FREE(var); 00335 00336 return(0); 00337 00338 } /* end of cuddLinearAndSifting */
int cuddLinearInPlace | ( | DdManager * | table, | |
int | x, | |||
int | y | |||
) |
Function********************************************************************
Synopsis [Linearly combines two adjacent variables.]
Description [Linearly combines two adjacent variables. Specifically, replaces the top variable with the exclusive nor of the two variables. It assumes that no dead nodes are present on entry to this procedure. The procedure then guarantees that no dead nodes will be present when it terminates. cuddLinearInPlace assumes that x < y. Returns the number of keys in the table if successful; 0 otherwise.]
SideEffects [The two subtables corrresponding to variables x and y are modified. The global counters of the unique table are also affected.]
SeeAlso [cuddSwapInPlace]
Definition at line 360 of file cuddLinear.c.
00364 { 00365 DdNodePtr *xlist, *ylist; 00366 int xindex, yindex; 00367 int xslots, yslots; 00368 int xshift, yshift; 00369 int oldxkeys, oldykeys; 00370 int newxkeys, newykeys; 00371 int comple, newcomplement; 00372 int i; 00373 int posn; 00374 int isolated; 00375 DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10,*newf1,*newf0; 00376 DdNode *g,*next,*last; 00377 DdNodePtr *previousP; 00378 DdNode *tmp; 00379 DdNode *sentinel = &(table->sentinel); 00380 #ifdef DD_DEBUG 00381 int count, idcheck; 00382 #endif 00383 00384 #ifdef DD_DEBUG 00385 assert(x < y); 00386 assert(cuddNextHigh(table,x) == y); 00387 assert(table->subtables[x].keys != 0); 00388 assert(table->subtables[y].keys != 0); 00389 assert(table->subtables[x].dead == 0); 00390 assert(table->subtables[y].dead == 0); 00391 #endif 00392 00393 xindex = table->invperm[x]; 00394 yindex = table->invperm[y]; 00395 00396 if (cuddTestInteract(table,xindex,yindex)) { 00397 #ifdef DD_STATS 00398 ddTotalNumberLinearTr++; 00399 #endif 00400 /* Get parameters of x subtable. */ 00401 xlist = table->subtables[x].nodelist; 00402 oldxkeys = table->subtables[x].keys; 00403 xslots = table->subtables[x].slots; 00404 xshift = table->subtables[x].shift; 00405 00406 /* Get parameters of y subtable. */ 00407 ylist = table->subtables[y].nodelist; 00408 oldykeys = table->subtables[y].keys; 00409 yslots = table->subtables[y].slots; 00410 yshift = table->subtables[y].shift; 00411 00412 newxkeys = 0; 00413 newykeys = oldykeys; 00414 00415 /* Check whether the two projection functions involved in this 00416 ** swap are isolated. At the end, we'll be able to tell how many 00417 ** isolated projection functions are there by checking only these 00418 ** two functions again. This is done to eliminate the isolated 00419 ** projection functions from the node count. 00420 */ 00421 isolated = - ((table->vars[xindex]->ref == 1) + 00422 (table->vars[yindex]->ref == 1)); 00423 00424 /* The nodes in the x layer are put in a chain. 00425 ** The chain is handled as a FIFO; g points to the beginning and 00426 ** last points to the end. 00427 */ 00428 g = NULL; 00429 #ifdef DD_DEBUG 00430 last = NULL; 00431 #endif 00432 for (i = 0; i < xslots; i++) { 00433 f = xlist[i]; 00434 if (f == sentinel) continue; 00435 xlist[i] = sentinel; 00436 if (g == NULL) { 00437 g = f; 00438 } else { 00439 last->next = f; 00440 } 00441 while ((next = f->next) != sentinel) { 00442 f = next; 00443 } /* while there are elements in the collision chain */ 00444 last = f; 00445 } /* for each slot of the x subtable */ 00446 #ifdef DD_DEBUG 00447 /* last is always assigned in the for loop because there is at 00448 ** least one key */ 00449 assert(last != NULL); 00450 #endif 00451 last->next = NULL; 00452 00453 #ifdef DD_COUNT 00454 table->swapSteps += oldxkeys; 00455 #endif 00456 /* Take care of the x nodes that must be re-expressed. 00457 ** They form a linked list pointed by g. 00458 */ 00459 f = g; 00460 while (f != NULL) { 00461 next = f->next; 00462 /* Find f1, f0, f11, f10, f01, f00. */ 00463 f1 = cuddT(f); 00464 #ifdef DD_DEBUG 00465 assert(!(Cudd_IsComplement(f1))); 00466 #endif 00467 if ((int) f1->index == yindex) { 00468 f11 = cuddT(f1); f10 = cuddE(f1); 00469 } else { 00470 f11 = f10 = f1; 00471 } 00472 #ifdef DD_DEBUG 00473 assert(!(Cudd_IsComplement(f11))); 00474 #endif 00475 f0 = cuddE(f); 00476 comple = Cudd_IsComplement(f0); 00477 f0 = Cudd_Regular(f0); 00478 if ((int) f0->index == yindex) { 00479 f01 = cuddT(f0); f00 = cuddE(f0); 00480 } else { 00481 f01 = f00 = f0; 00482 } 00483 if (comple) { 00484 f01 = Cudd_Not(f01); 00485 f00 = Cudd_Not(f00); 00486 } 00487 /* Decrease ref count of f1. */ 00488 cuddSatDec(f1->ref); 00489 /* Create the new T child. */ 00490 if (f11 == f00) { 00491 newf1 = f11; 00492 cuddSatInc(newf1->ref); 00493 } else { 00494 /* Check ylist for triple (yindex,f11,f00). */ 00495 posn = ddHash(f11, f00, yshift); 00496 /* For each element newf1 in collision list ylist[posn]. */ 00497 previousP = &(ylist[posn]); 00498 newf1 = *previousP; 00499 while (f11 < cuddT(newf1)) { 00500 previousP = &(newf1->next); 00501 newf1 = *previousP; 00502 } 00503 while (f11 == cuddT(newf1) && f00 < cuddE(newf1)) { 00504 previousP = &(newf1->next); 00505 newf1 = *previousP; 00506 } 00507 if (cuddT(newf1) == f11 && cuddE(newf1) == f00) { 00508 cuddSatInc(newf1->ref); 00509 } else { /* no match */ 00510 newf1 = cuddDynamicAllocNode(table); 00511 if (newf1 == NULL) 00512 goto cuddLinearOutOfMem; 00513 newf1->index = yindex; newf1->ref = 1; 00514 cuddT(newf1) = f11; 00515 cuddE(newf1) = f00; 00516 /* Insert newf1 in the collision list ylist[posn]; 00517 ** increase the ref counts of f11 and f00. 00518 */ 00519 newykeys++; 00520 newf1->next = *previousP; 00521 *previousP = newf1; 00522 cuddSatInc(f11->ref); 00523 tmp = Cudd_Regular(f00); 00524 cuddSatInc(tmp->ref); 00525 } 00526 } 00527 cuddT(f) = newf1; 00528 #ifdef DD_DEBUG 00529 assert(!(Cudd_IsComplement(newf1))); 00530 #endif 00531 00532 /* Do the same for f0, keeping complement dots into account. */ 00533 /* decrease ref count of f0 */ 00534 tmp = Cudd_Regular(f0); 00535 cuddSatDec(tmp->ref); 00536 /* create the new E child */ 00537 if (f01 == f10) { 00538 newf0 = f01; 00539 tmp = Cudd_Regular(newf0); 00540 cuddSatInc(tmp->ref); 00541 } else { 00542 /* make sure f01 is regular */ 00543 newcomplement = Cudd_IsComplement(f01); 00544 if (newcomplement) { 00545 f01 = Cudd_Not(f01); 00546 f10 = Cudd_Not(f10); 00547 } 00548 /* Check ylist for triple (yindex,f01,f10). */ 00549 posn = ddHash(f01, f10, yshift); 00550 /* For each element newf0 in collision list ylist[posn]. */ 00551 previousP = &(ylist[posn]); 00552 newf0 = *previousP; 00553 while (f01 < cuddT(newf0)) { 00554 previousP = &(newf0->next); 00555 newf0 = *previousP; 00556 } 00557 while (f01 == cuddT(newf0) && f10 < cuddE(newf0)) { 00558 previousP = &(newf0->next); 00559 newf0 = *previousP; 00560 } 00561 if (cuddT(newf0) == f01 && cuddE(newf0) == f10) { 00562 cuddSatInc(newf0->ref); 00563 } else { /* no match */ 00564 newf0 = cuddDynamicAllocNode(table); 00565 if (newf0 == NULL) 00566 goto cuddLinearOutOfMem; 00567 newf0->index = yindex; newf0->ref = 1; 00568 cuddT(newf0) = f01; 00569 cuddE(newf0) = f10; 00570 /* Insert newf0 in the collision list ylist[posn]; 00571 ** increase the ref counts of f01 and f10. 00572 */ 00573 newykeys++; 00574 newf0->next = *previousP; 00575 *previousP = newf0; 00576 cuddSatInc(f01->ref); 00577 tmp = Cudd_Regular(f10); 00578 cuddSatInc(tmp->ref); 00579 } 00580 if (newcomplement) { 00581 newf0 = Cudd_Not(newf0); 00582 } 00583 } 00584 cuddE(f) = newf0; 00585 00586 /* Re-insert the modified f in xlist. 00587 ** The modified f does not already exists in xlist. 00588 ** (Because of the uniqueness of the cofactors.) 00589 */ 00590 posn = ddHash(newf1, newf0, xshift); 00591 newxkeys++; 00592 previousP = &(xlist[posn]); 00593 tmp = *previousP; 00594 while (newf1 < cuddT(tmp)) { 00595 previousP = &(tmp->next); 00596 tmp = *previousP; 00597 } 00598 while (newf1 == cuddT(tmp) && newf0 < cuddE(tmp)) { 00599 previousP = &(tmp->next); 00600 tmp = *previousP; 00601 } 00602 f->next = *previousP; 00603 *previousP = f; 00604 f = next; 00605 } /* while f != NULL */ 00606 00607 /* GC the y layer. */ 00608 00609 /* For each node f in ylist. */ 00610 for (i = 0; i < yslots; i++) { 00611 previousP = &(ylist[i]); 00612 f = *previousP; 00613 while (f != sentinel) { 00614 next = f->next; 00615 if (f->ref == 0) { 00616 tmp = cuddT(f); 00617 cuddSatDec(tmp->ref); 00618 tmp = Cudd_Regular(cuddE(f)); 00619 cuddSatDec(tmp->ref); 00620 cuddDeallocNode(table,f); 00621 newykeys--; 00622 } else { 00623 *previousP = f; 00624 previousP = &(f->next); 00625 } 00626 f = next; 00627 } /* while f */ 00628 *previousP = sentinel; 00629 } /* for every collision list */ 00630 00631 #ifdef DD_DEBUG 00632 #if 0 00633 (void) fprintf(table->out,"Linearly combining %d and %d\n",x,y); 00634 #endif 00635 count = 0; 00636 idcheck = 0; 00637 for (i = 0; i < yslots; i++) { 00638 f = ylist[i]; 00639 while (f != sentinel) { 00640 count++; 00641 if (f->index != (DdHalfWord) yindex) 00642 idcheck++; 00643 f = f->next; 00644 } 00645 } 00646 if (count != newykeys) { 00647 fprintf(table->err,"Error in finding newykeys\toldykeys = %d\tnewykeys = %d\tactual = %d\n",oldykeys,newykeys,count); 00648 } 00649 if (idcheck != 0) 00650 fprintf(table->err,"Error in id's of ylist\twrong id's = %d\n",idcheck); 00651 count = 0; 00652 idcheck = 0; 00653 for (i = 0; i < xslots; i++) { 00654 f = xlist[i]; 00655 while (f != sentinel) { 00656 count++; 00657 if (f->index != (DdHalfWord) xindex) 00658 idcheck++; 00659 f = f->next; 00660 } 00661 } 00662 if (count != newxkeys || newxkeys != oldxkeys) { 00663 fprintf(table->err,"Error in finding newxkeys\toldxkeys = %d \tnewxkeys = %d \tactual = %d\n",oldxkeys,newxkeys,count); 00664 } 00665 if (idcheck != 0) 00666 fprintf(table->err,"Error in id's of xlist\twrong id's = %d\n",idcheck); 00667 #endif 00668 00669 isolated += (table->vars[xindex]->ref == 1) + 00670 (table->vars[yindex]->ref == 1); 00671 table->isolated += isolated; 00672 00673 /* Set the appropriate fields in table. */ 00674 table->subtables[y].keys = newykeys; 00675 00676 /* Here we should update the linear combination table 00677 ** to record that x <- x EXNOR y. This is done by complementing 00678 ** the (x,y) entry of the table. 00679 */ 00680 00681 table->keys += newykeys - oldykeys; 00682 00683 cuddXorLinear(table,xindex,yindex); 00684 } 00685 00686 #ifdef DD_DEBUG 00687 if (zero) { 00688 (void) Cudd_DebugCheck(table); 00689 } 00690 #endif 00691 00692 return(table->keys - table->isolated); 00693 00694 cuddLinearOutOfMem: 00695 (void) fprintf(table->err,"Error: cuddLinearInPlace out of memory\n"); 00696 00697 return (0); 00698 00699 } /* end of cuddLinearInPlace */
void cuddLocalCacheClearAll | ( | DdManager * | manager | ) |
Function********************************************************************
Synopsis [Clears the local caches of a manager.]
Description [Clears the local caches of a manager. Used before reordering.]
SideEffects [None]
SeeAlso []
Definition at line 400 of file cuddLCache.c.
00402 { 00403 DdLocalCache *cache = manager->localCaches; 00404 00405 while (cache != NULL) { 00406 memset(cache->item, 0, cache->slots * cache->itemsize); 00407 cache = cache->next; 00408 } 00409 return; 00410 00411 } /* end of cuddLocalCacheClearAll */
void cuddLocalCacheClearDead | ( | DdManager * | manager | ) |
Function********************************************************************
Synopsis [Clears the dead entries of the local caches of a manager.]
Description [Clears the dead entries of the local caches of a manager. Used during garbage collection.]
SideEffects [None]
SeeAlso []
Definition at line 348 of file cuddLCache.c.
00350 { 00351 DdLocalCache *cache = manager->localCaches; 00352 unsigned int keysize; 00353 unsigned int itemsize; 00354 unsigned int slots; 00355 DdLocalCacheItem *item; 00356 DdNodePtr *key; 00357 unsigned int i, j; 00358 00359 while (cache != NULL) { 00360 keysize = cache->keysize; 00361 itemsize = cache->itemsize; 00362 slots = cache->slots; 00363 item = cache->item; 00364 for (i = 0; i < slots; i++) { 00365 if (item->value != NULL) { 00366 if (Cudd_Regular(item->value)->ref == 0) { 00367 item->value = NULL; 00368 } else { 00369 key = item->key; 00370 for (j = 0; j < keysize; j++) { 00371 if (Cudd_Regular(key[j])->ref == 0) { 00372 item->value = NULL; 00373 break; 00374 } 00375 } 00376 } 00377 } 00378 item = (DdLocalCacheItem *) ((char *) item + itemsize); 00379 } 00380 cache = cache->next; 00381 } 00382 return; 00383 00384 } /* end of cuddLocalCacheClearDead */
DdLocalCache* cuddLocalCacheInit | ( | DdManager * | manager, | |
unsigned int | keySize, | |||
unsigned int | cacheSize, | |||
unsigned int | maxCacheSize | |||
) |
AutomaticEnd Function********************************************************************
Synopsis [Initializes a local computed table.]
Description [Initializes a computed table. Returns a pointer the the new local cache in case of success; NULL otherwise.]
SideEffects [None]
SeeAlso [cuddInitCache]
Definition at line 179 of file cuddLCache.c.
00184 { 00185 DdLocalCache *cache; 00186 int logSize; 00187 00188 cache = ALLOC(DdLocalCache,1); 00189 if (cache == NULL) { 00190 manager->errorCode = CUDD_MEMORY_OUT; 00191 return(NULL); 00192 } 00193 cache->manager = manager; 00194 cache->keysize = keySize; 00195 cache->itemsize = (keySize + 1) * sizeof(DdNode *); 00196 #ifdef DD_CACHE_PROFILE 00197 cache->itemsize += sizeof(ptrint); 00198 #endif 00199 logSize = cuddComputeFloorLog2(ddMax(cacheSize,manager->slots/2)); 00200 cacheSize = 1 << logSize; 00201 cache->item = (DdLocalCacheItem *) 00202 ALLOC(char, cacheSize * cache->itemsize); 00203 if (cache->item == NULL) { 00204 manager->errorCode = CUDD_MEMORY_OUT; 00205 FREE(cache); 00206 return(NULL); 00207 } 00208 cache->slots = cacheSize; 00209 cache->shift = sizeof(int) * 8 - logSize; 00210 cache->maxslots = ddMin(maxCacheSize,manager->slots); 00211 cache->minHit = manager->minHit; 00212 /* Initialize to avoid division by 0 and immediate resizing. */ 00213 cache->lookUps = (double) (int) (cacheSize * cache->minHit + 1); 00214 cache->hits = 0; 00215 manager->memused += cacheSize * cache->itemsize + sizeof(DdLocalCache); 00216 00217 /* Initialize the cache. */ 00218 memset(cache->item, 0, cacheSize * cache->itemsize); 00219 00220 /* Add to manager's list of local caches for GC. */ 00221 cuddLocalCacheAddToList(cache); 00222 00223 return(cache); 00224 00225 } /* end of cuddLocalCacheInit */
void cuddLocalCacheInsert | ( | DdLocalCache * | cache, | |
DdNodePtr * | key, | |||
DdNode * | value | |||
) |
Function********************************************************************
Synopsis [Inserts a result in a local cache.]
Description []
SideEffects [None]
SeeAlso []
Definition at line 268 of file cuddLCache.c.
00272 { 00273 unsigned int posn; 00274 DdLocalCacheItem *entry; 00275 00276 posn = ddLCHash(key,cache->keysize,cache->shift); 00277 entry = (DdLocalCacheItem *) ((char *) cache->item + 00278 posn * cache->itemsize); 00279 memcpy(entry->key,key,cache->keysize * sizeof(DdNode *)); 00280 entry->value = value; 00281 #ifdef DD_CACHE_PROFILE 00282 entry->count++; 00283 #endif 00284 00285 } /* end of cuddLocalCacheInsert */
DdNode* cuddLocalCacheLookup | ( | DdLocalCache * | cache, | |
DdNodePtr * | key | |||
) |
Function********************************************************************
Synopsis [Looks up in a local cache.]
Description [Looks up in a local cache. Returns the result if found; it returns NULL if no result is found.]
SideEffects [None]
SeeAlso []
Definition at line 301 of file cuddLCache.c.
00304 { 00305 unsigned int posn; 00306 DdLocalCacheItem *entry; 00307 DdNode *value; 00308 00309 cache->lookUps++; 00310 posn = ddLCHash(key,cache->keysize,cache->shift); 00311 entry = (DdLocalCacheItem *) ((char *) cache->item + 00312 posn * cache->itemsize); 00313 if (entry->value != NULL && 00314 memcmp(key,entry->key,cache->keysize*sizeof(DdNode *)) == 0) { 00315 cache->hits++; 00316 value = Cudd_Regular(entry->value); 00317 if (value->ref == 0) { 00318 cuddReclaim(cache->manager,value); 00319 } 00320 return(entry->value); 00321 } 00322 00323 /* Cache miss: decide whether to resize */ 00324 00325 if (cache->slots < cache->maxslots && 00326 cache->hits > cache->lookUps * cache->minHit) { 00327 cuddLocalCacheResize(cache); 00328 } 00329 00330 return(NULL); 00331 00332 } /* end of cuddLocalCacheLookup */
void cuddLocalCacheQuit | ( | DdLocalCache * | cache | ) |
Function********************************************************************
Synopsis [Shuts down a local computed table.]
Description [Initializes the computed table. It is called by Cudd_Init. Returns a pointer the the new local cache in case of success; NULL otherwise.]
SideEffects [None]
SeeAlso [cuddLocalCacheInit]
Definition at line 242 of file cuddLCache.c.
00244 { 00245 cache->manager->memused -= 00246 cache->slots * cache->itemsize + sizeof(DdLocalCache); 00247 cuddLocalCacheRemoveFromList(cache); 00248 FREE(cache->item); 00249 FREE(cache); 00250 00251 return; 00252 00253 } /* end of cuddLocalCacheQuit */
Function********************************************************************
Synopsis [Converts a ZDD cover to a BDD graph.]
Description [Converts a ZDD cover to a BDD graph. If successful, it returns a BDD node, otherwise it returns NULL. It is a recursive algorithm as the following. First computes 3 cofactors of a ZDD cover; f1, f0 and fd. Second, compute BDDs(b1, b0 and bd) of f1, f0 and fd. Third, compute T=b1+bd and E=b0+bd. Fourth, compute ITE(v,T,E) where v is the variable which has the index of the top node of the ZDD cover. In this case, since the index of v can be larger than either one of T or one of E, cuddUniqueInterIVO is called, here IVO stands for independent variable ordering.]
SideEffects []
SeeAlso [Cudd_MakeBddFromZddCover]
Definition at line 796 of file cuddZddIsop.c.
00799 { 00800 DdNode *neW; 00801 int v; 00802 DdNode *f1, *f0, *fd; 00803 DdNode *b1, *b0, *bd; 00804 DdNode *T, *E; 00805 00806 statLine(dd); 00807 if (node == dd->one) 00808 return(dd->one); 00809 if (node == dd->zero) 00810 return(Cudd_Not(dd->one)); 00811 00812 /* Check cache */ 00813 neW = cuddCacheLookup1(dd, cuddMakeBddFromZddCover, node); 00814 if (neW) 00815 return(neW); 00816 00817 v = Cudd_Regular(node)->index; /* either yi or zi */ 00818 if (cuddZddGetCofactors3(dd, node, v, &f1, &f0, &fd)) return(NULL); 00819 Cudd_Ref(f1); 00820 Cudd_Ref(f0); 00821 Cudd_Ref(fd); 00822 00823 b1 = cuddMakeBddFromZddCover(dd, f1); 00824 if (!b1) { 00825 Cudd_RecursiveDerefZdd(dd, f1); 00826 Cudd_RecursiveDerefZdd(dd, f0); 00827 Cudd_RecursiveDerefZdd(dd, fd); 00828 return(NULL); 00829 } 00830 Cudd_Ref(b1); 00831 b0 = cuddMakeBddFromZddCover(dd, f0); 00832 if (!b0) { 00833 Cudd_RecursiveDerefZdd(dd, f1); 00834 Cudd_RecursiveDerefZdd(dd, f0); 00835 Cudd_RecursiveDerefZdd(dd, fd); 00836 Cudd_RecursiveDeref(dd, b1); 00837 return(NULL); 00838 } 00839 Cudd_Ref(b0); 00840 Cudd_RecursiveDerefZdd(dd, f1); 00841 Cudd_RecursiveDerefZdd(dd, f0); 00842 if (fd != dd->zero) { 00843 bd = cuddMakeBddFromZddCover(dd, fd); 00844 if (!bd) { 00845 Cudd_RecursiveDerefZdd(dd, fd); 00846 Cudd_RecursiveDeref(dd, b1); 00847 Cudd_RecursiveDeref(dd, b0); 00848 return(NULL); 00849 } 00850 Cudd_Ref(bd); 00851 Cudd_RecursiveDerefZdd(dd, fd); 00852 00853 T = cuddBddAndRecur(dd, Cudd_Not(b1), Cudd_Not(bd)); 00854 if (!T) { 00855 Cudd_RecursiveDeref(dd, b1); 00856 Cudd_RecursiveDeref(dd, b0); 00857 Cudd_RecursiveDeref(dd, bd); 00858 return(NULL); 00859 } 00860 T = Cudd_NotCond(T, T != NULL); 00861 Cudd_Ref(T); 00862 Cudd_RecursiveDeref(dd, b1); 00863 E = cuddBddAndRecur(dd, Cudd_Not(b0), Cudd_Not(bd)); 00864 if (!E) { 00865 Cudd_RecursiveDeref(dd, b0); 00866 Cudd_RecursiveDeref(dd, bd); 00867 Cudd_RecursiveDeref(dd, T); 00868 return(NULL); 00869 } 00870 E = Cudd_NotCond(E, E != NULL); 00871 Cudd_Ref(E); 00872 Cudd_RecursiveDeref(dd, b0); 00873 Cudd_RecursiveDeref(dd, bd); 00874 } 00875 else { 00876 Cudd_RecursiveDerefZdd(dd, fd); 00877 T = b1; 00878 E = b0; 00879 } 00880 00881 if (Cudd_IsComplement(T)) { 00882 neW = cuddUniqueInterIVO(dd, v / 2, Cudd_Not(T), Cudd_Not(E)); 00883 if (!neW) { 00884 Cudd_RecursiveDeref(dd, T); 00885 Cudd_RecursiveDeref(dd, E); 00886 return(NULL); 00887 } 00888 neW = Cudd_Not(neW); 00889 } 00890 else { 00891 neW = cuddUniqueInterIVO(dd, v / 2, T, E); 00892 if (!neW) { 00893 Cudd_RecursiveDeref(dd, T); 00894 Cudd_RecursiveDeref(dd, E); 00895 return(NULL); 00896 } 00897 } 00898 Cudd_Ref(neW); 00899 Cudd_RecursiveDeref(dd, T); 00900 Cudd_RecursiveDeref(dd, E); 00901 00902 cuddCacheInsert1(dd, cuddMakeBddFromZddCover, node, neW); 00903 Cudd_Deref(neW); 00904 return(neW); 00905 00906 } /* end of cuddMakeBddFromZddCover */
int cuddNextHigh | ( | DdManager * | table, | |
int | x | |||
) |
Function********************************************************************
Synopsis [Finds the next subtable with a larger index.]
Description [Finds the next subtable with a larger index. Returns the index.]
SideEffects [None]
SeeAlso [cuddNextLow]
Definition at line 707 of file cuddReorder.c.
int cuddNextLow | ( | DdManager * | table, | |
int | x | |||
) |
Function********************************************************************
Synopsis [Finds the next subtable with a smaller index.]
Description [Finds the next subtable with a smaller index. Returns the index.]
SideEffects [None]
SeeAlso [cuddNextHigh]
Definition at line 729 of file cuddReorder.c.
Function********************************************************************
Synopsis [Recursively collects all the nodes of a DD in an array.]
Description [Traverses the DD f and collects all its nodes in an array. The caller should free the array returned by cuddNodeArray. Returns a pointer to the array of nodes in case of success; NULL otherwise. The nodes are collected in reverse topological order, so that a node is always preceded in the array by all its descendants.]
SideEffects [The number of nodes is returned as a side effect.]
SeeAlso [Cudd_FirstNode]
Definition at line 2975 of file cuddUtil.c.
02978 { 02979 DdNodePtr *table; 02980 int size, retval; 02981 02982 size = ddDagInt(Cudd_Regular(f)); 02983 table = ALLOC(DdNodePtr, size); 02984 if (table == NULL) { 02985 ddClearFlag(Cudd_Regular(f)); 02986 return(NULL); 02987 } 02988 02989 retval = cuddNodeArrayRecur(f, table, 0); 02990 assert(retval == size); 02991 02992 *n = size; 02993 return(table); 02994 02995 } /* cuddNodeArray */
Function********************************************************************
Synopsis [Prints a DD to the standard output. One line per node is printed.]
Description [Prints a DD to the standard output. One line per node is printed. Returns 1 if successful; 0 otherwise.]
SideEffects [None]
SeeAlso [Cudd_PrintDebug]
Definition at line 2862 of file cuddUtil.c.
02865 { 02866 int retval; 02867 st_table *table = st_init_table(st_ptrcmp,st_ptrhash); 02868 02869 if (table == NULL) return(0); 02870 02871 retval = dp2(dd,f,table); 02872 st_free_table(table); 02873 (void) fputc('\n',dd->out); 02874 return(retval); 02875 02876 } /* end of cuddP */
void cuddPrintNode | ( | DdNode * | f, | |
FILE * | fp | |||
) |
Function********************************************************************
Synopsis [Prints out information on a node.]
Description [Prints out information on a node.]
SideEffects [None]
SeeAlso []
Definition at line 706 of file cuddCheck.c.
00709 { 00710 f = Cudd_Regular(f); 00711 #if SIZEOF_VOID_P == 8 00712 (void) fprintf(fp," node 0x%lx, id = %u, ref = %u, then = 0x%lx, else = 0x%lx\n",(ptruint)f,f->index,f->ref,(ptruint)cuddT(f),(ptruint)cuddE(f)); 00713 #else 00714 (void) fprintf(fp," node 0x%x, id = %hu, ref = %hu, then = 0x%x, else = 0x%x\n",(ptruint)f,f->index,f->ref,(ptruint)cuddT(f),(ptruint)cuddE(f)); 00715 #endif 00716 00717 } /* end of cuddPrintNode */
Function********************************************************************
Synopsis [Prints the variable groups as a parenthesized list.]
Description [Prints the variable groups as a parenthesized list. For each group the level range that it represents is printed. After each group, the group's flags are printed, preceded by a `|'. For each flag (except MTR_TERMINAL) a character is printed.
The second argument, silent, if different from 0, causes Cudd_PrintVarGroups to only check the syntax of the group tree.]
SideEffects [None]
SeeAlso []
Definition at line 743 of file cuddCheck.c.
00746 : BDD; 1: ZDD */, 00747 int silent /* flag to check tree syntax only */) 00748 { 00749 MtrNode *node; 00750 int level; 00751 00752 assert(root != NULL); 00753 assert(root->younger == NULL || root->younger->elder == root); 00754 assert(root->elder == NULL || root->elder->younger == root); 00755 if (zdd) { 00756 level = dd->permZ[root->index]; 00757 } else { 00758 level = dd->perm[root->index]; 00759 } 00760 if (!silent) (void) printf("(%d",level); 00761 if (MTR_TEST(root,MTR_TERMINAL) || root->child == NULL) { 00762 if (!silent) (void) printf(","); 00763 } else { 00764 node = root->child; 00765 while (node != NULL) { 00766 assert(node->low >= root->low && (int) (node->low + node->size) <= (int) (root->low + root->size)); 00767 assert(node->parent == root); 00768 cuddPrintVarGroups(dd,node,zdd,silent); 00769 node = node->younger; 00770 } 00771 } 00772 if (!silent) { 00773 (void) printf("%d", (int) (level + root->size - 1)); 00774 if (root->flags != MTR_DEFAULT) { 00775 (void) printf("|"); 00776 if (MTR_TEST(root,MTR_FIXED)) (void) printf("F"); 00777 if (MTR_TEST(root,MTR_NEWNODE)) (void) printf("N"); 00778 if (MTR_TEST(root,MTR_SOFT)) (void) printf("S"); 00779 } 00780 (void) printf(")"); 00781 if (root->parent == NULL) (void) printf("\n"); 00782 } 00783 assert((root->flags &~(MTR_TERMINAL | MTR_SOFT | MTR_FIXED | MTR_NEWNODE)) == 0); 00784 return; 00785 00786 } /* end of cuddPrintVarGroups */
Function********************************************************************
Synopsis [Brings children of a dead node back.]
Description []
SideEffects [None]
SeeAlso [cuddReclaimZdd]
Definition at line 580 of file cuddRef.c.
00583 { 00584 DdNode *N; 00585 int ord; 00586 DdNodePtr *stack = table->stack; 00587 int SP = 1; 00588 double initialDead = table->dead; 00589 00590 N = Cudd_Regular(n); 00591 00592 #ifdef DD_DEBUG 00593 assert(N->ref == 0); 00594 #endif 00595 00596 do { 00597 if (N->ref == 0) { 00598 N->ref = 1; 00599 table->dead--; 00600 if (cuddIsConstant(N)) { 00601 table->constants.dead--; 00602 N = stack[--SP]; 00603 } else { 00604 ord = table->perm[N->index]; 00605 stack[SP++] = Cudd_Regular(cuddE(N)); 00606 table->subtables[ord].dead--; 00607 N = cuddT(N); 00608 } 00609 } else { 00610 cuddSatInc(N->ref); 00611 N = stack[--SP]; 00612 } 00613 } while (SP != 0); 00614 00615 N = Cudd_Regular(n); 00616 cuddSatDec(N->ref); 00617 table->reclaimed += initialDead - table->dead; 00618 00619 } /* end of cuddReclaim */
Function********************************************************************
Synopsis [Brings children of a dead ZDD node back.]
Description []
SideEffects [None]
SeeAlso [cuddReclaim]
Definition at line 634 of file cuddRef.c.
00637 { 00638 DdNode *N; 00639 int ord; 00640 DdNodePtr *stack = table->stack; 00641 int SP = 1; 00642 00643 N = n; 00644 00645 #ifdef DD_DEBUG 00646 assert(N->ref == 0); 00647 #endif 00648 00649 do { 00650 cuddSatInc(N->ref); 00651 00652 if (N->ref == 1) { 00653 table->deadZ--; 00654 table->reclaimed++; 00655 #ifdef DD_DEBUG 00656 assert(!cuddIsConstant(N)); 00657 #endif 00658 ord = table->permZ[N->index]; 00659 stack[SP++] = cuddE(N); 00660 table->subtableZ[ord].dead--; 00661 N = cuddT(N); 00662 } else { 00663 N = stack[--SP]; 00664 } 00665 } while (SP != 0); 00666 00667 cuddSatDec(n->ref); 00668 00669 } /* end of cuddReclaimZdd */
void cuddRehash | ( | DdManager * | unique, | |
int | i | |||
) |
Function********************************************************************
Synopsis [Rehashes a unique subtable.]
Description [Doubles the size of a unique subtable and rehashes its contents.]
SideEffects [None]
SeeAlso []
Definition at line 1515 of file cuddTable.c.
01518 { 01519 unsigned int slots, oldslots; 01520 int shift, oldshift; 01521 int j, pos; 01522 DdNodePtr *nodelist, *oldnodelist; 01523 DdNode *node, *next; 01524 DdNode *sentinel = &(unique->sentinel); 01525 hack split; 01526 extern DD_OOMFP MMoutOfMemory; 01527 DD_OOMFP saveHandler; 01528 01529 if (unique->gcFrac == DD_GC_FRAC_HI && unique->slots > unique->looseUpTo) { 01530 unique->gcFrac = DD_GC_FRAC_LO; 01531 unique->minDead = (unsigned) (DD_GC_FRAC_LO * (double) unique->slots); 01532 #ifdef DD_VERBOSE 01533 (void) fprintf(unique->err,"GC fraction = %.2f\t", DD_GC_FRAC_LO); 01534 (void) fprintf(unique->err,"minDead = %d\n", unique->minDead); 01535 #endif 01536 } 01537 01538 if (unique->gcFrac != DD_GC_FRAC_MIN && unique->memused > unique->maxmem) { 01539 unique->gcFrac = DD_GC_FRAC_MIN; 01540 unique->minDead = (unsigned) (DD_GC_FRAC_MIN * (double) unique->slots); 01541 #ifdef DD_VERBOSE 01542 (void) fprintf(unique->err,"GC fraction = %.2f\t", DD_GC_FRAC_MIN); 01543 (void) fprintf(unique->err,"minDead = %d\n", unique->minDead); 01544 #endif 01545 cuddShrinkDeathRow(unique); 01546 if (cuddGarbageCollect(unique,1) > 0) return; 01547 } 01548 01549 if (i != CUDD_CONST_INDEX) { 01550 oldslots = unique->subtables[i].slots; 01551 oldshift = unique->subtables[i].shift; 01552 oldnodelist = unique->subtables[i].nodelist; 01553 01554 /* Compute the new size of the subtable. */ 01555 slots = oldslots << 1; 01556 shift = oldshift - 1; 01557 01558 saveHandler = MMoutOfMemory; 01559 MMoutOfMemory = Cudd_OutOfMem; 01560 nodelist = ALLOC(DdNodePtr, slots); 01561 MMoutOfMemory = saveHandler; 01562 if (nodelist == NULL) { 01563 (void) fprintf(unique->err, 01564 "Unable to resize subtable %d for lack of memory\n", 01565 i); 01566 /* Prevent frequent resizing attempts. */ 01567 (void) cuddGarbageCollect(unique,1); 01568 if (unique->stash != NULL) { 01569 FREE(unique->stash); 01570 unique->stash = NULL; 01571 /* Inhibit resizing of tables. */ 01572 cuddSlowTableGrowth(unique); 01573 } 01574 return; 01575 } 01576 unique->subtables[i].nodelist = nodelist; 01577 unique->subtables[i].slots = slots; 01578 unique->subtables[i].shift = shift; 01579 unique->subtables[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; 01580 01581 /* Move the nodes from the old table to the new table. 01582 ** This code depends on the type of hash function. 01583 ** It assumes that the effect of doubling the size of the table 01584 ** is to retain one more bit of the 32-bit hash value. 01585 ** The additional bit is the LSB. */ 01586 for (j = 0; (unsigned) j < oldslots; j++) { 01587 DdNodePtr *evenP, *oddP; 01588 node = oldnodelist[j]; 01589 evenP = &(nodelist[j<<1]); 01590 oddP = &(nodelist[(j<<1)+1]); 01591 while (node != sentinel) { 01592 next = node->next; 01593 pos = ddHash(cuddT(node), cuddE(node), shift); 01594 if (pos & 1) { 01595 *oddP = node; 01596 oddP = &(node->next); 01597 } else { 01598 *evenP = node; 01599 evenP = &(node->next); 01600 } 01601 node = next; 01602 } 01603 *evenP = *oddP = sentinel; 01604 } 01605 FREE(oldnodelist); 01606 01607 #ifdef DD_VERBOSE 01608 (void) fprintf(unique->err, 01609 "rehashing layer %d: keys %d dead %d new size %d\n", 01610 i, unique->subtables[i].keys, 01611 unique->subtables[i].dead, slots); 01612 #endif 01613 } else { 01614 oldslots = unique->constants.slots; 01615 oldshift = unique->constants.shift; 01616 oldnodelist = unique->constants.nodelist; 01617 01618 /* The constant subtable is never subjected to reordering. 01619 ** Therefore, when it is resized, it is because it has just 01620 ** reached the maximum load. We can safely just double the size, 01621 ** with no need for the loop we use for the other tables. 01622 */ 01623 slots = oldslots << 1; 01624 shift = oldshift - 1; 01625 saveHandler = MMoutOfMemory; 01626 MMoutOfMemory = Cudd_OutOfMem; 01627 nodelist = ALLOC(DdNodePtr, slots); 01628 MMoutOfMemory = saveHandler; 01629 if (nodelist == NULL) { 01630 (void) fprintf(unique->err, 01631 "Unable to resize constant subtable for lack of memory\n"); 01632 (void) cuddGarbageCollect(unique,1); 01633 for (j = 0; j < unique->size; j++) { 01634 unique->subtables[j].maxKeys <<= 1; 01635 } 01636 unique->constants.maxKeys <<= 1; 01637 return; 01638 } 01639 unique->constants.slots = slots; 01640 unique->constants.shift = shift; 01641 unique->constants.maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; 01642 unique->constants.nodelist = nodelist; 01643 for (j = 0; (unsigned) j < slots; j++) { 01644 nodelist[j] = NULL; 01645 } 01646 for (j = 0; (unsigned) j < oldslots; j++) { 01647 node = oldnodelist[j]; 01648 while (node != NULL) { 01649 next = node->next; 01650 split.value = cuddV(node); 01651 pos = ddHash(split.bits[0], split.bits[1], shift); 01652 node->next = nodelist[pos]; 01653 nodelist[pos] = node; 01654 node = next; 01655 } 01656 } 01657 FREE(oldnodelist); 01658 01659 #ifdef DD_VERBOSE 01660 (void) fprintf(unique->err, 01661 "rehashing constants: keys %d dead %d new size %d\n", 01662 unique->constants.keys,unique->constants.dead,slots); 01663 #endif 01664 } 01665 01666 /* Update global data */ 01667 01668 unique->memused += (slots - oldslots) * sizeof(DdNodePtr); 01669 unique->slots += (slots - oldslots); 01670 ddFixLimits(unique); 01671 01672 } /* end of cuddRehash */
DdNode* cuddRemapUnderApprox | ( | DdManager * | dd, | |
DdNode * | f, | |||
int | numVars, | |||
int | threshold, | |||
double | quality | |||
) |
Function********************************************************************
Synopsis [Applies the remapping underappoximation algorithm.]
Description [Applies the remapping underappoximation algorithm. Proceeds in three phases:
Returns the approximated BDD if successful; NULL otherwise.]
SideEffects [None]
SeeAlso [Cudd_RemapUnderApprox]
Definition at line 597 of file cuddApprox.c.
00603 { 00604 ApproxInfo *info; 00605 DdNode *subset; 00606 int result; 00607 00608 if (f == NULL) { 00609 fprintf(dd->err, "Cannot subset, nil object\n"); 00610 dd->errorCode = CUDD_INVALID_ARG; 00611 return(NULL); 00612 } 00613 00614 if (Cudd_IsConstant(f)) { 00615 return(f); 00616 } 00617 00618 /* Create table where node data are accessible via a hash table. */ 00619 info = gatherInfo(dd, f, numVars, TRUE); 00620 if (info == NULL) { 00621 (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); 00622 dd->errorCode = CUDD_MEMORY_OUT; 00623 return(NULL); 00624 } 00625 00626 /* Mark nodes that should be replaced by zero. */ 00627 result = RAmarkNodes(dd, f, info, threshold, quality); 00628 if (result == 0) { 00629 (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); 00630 FREE(info->page); 00631 st_free_table(info->table); 00632 FREE(info); 00633 dd->errorCode = CUDD_MEMORY_OUT; 00634 return(NULL); 00635 } 00636 00637 /* Build the result. */ 00638 subset = RAbuildSubset(dd, f, info); 00639 #if 1 00640 if (subset && info->size < Cudd_DagSize(subset)) 00641 (void) fprintf(dd->err, "Wrong prediction: %d versus actual %d\n", 00642 info->size, Cudd_DagSize(subset)); 00643 #endif 00644 FREE(info->page); 00645 st_free_table(info->table); 00646 FREE(info); 00647 00648 #ifdef DD_DEBUG 00649 if (subset != NULL) { 00650 cuddRef(subset); 00651 #if 0 00652 (void) Cudd_DebugCheck(dd); 00653 (void) Cudd_CheckKeys(dd); 00654 #endif 00655 if (!Cudd_bddLeq(dd, subset, f)) { 00656 (void) fprintf(dd->err, "Wrong subset\n"); 00657 } 00658 cuddDeref(subset); 00659 dd->errorCode = CUDD_INTERNAL_ERROR; 00660 } 00661 #endif 00662 return(subset); 00663 00664 } /* end of cuddRemapUnderApprox */
int cuddResizeLinear | ( | DdManager * | table | ) |
Function********************************************************************
Synopsis [Resizes the linear transform matrix.]
Description [Resizes the linear transform matrix. Returns 1 if successful; 0 otherwise.]
SideEffects [none]
SeeAlso []
Definition at line 800 of file cuddLinear.c.
00802 { 00803 int words,oldWords; 00804 int wordsPerRow,oldWordsPerRow; 00805 int nvars,oldNvars; 00806 int word,oldWord; 00807 int bit; 00808 int i,j; 00809 long *linear,*oldLinear; 00810 00811 oldNvars = table->linearSize; 00812 oldWordsPerRow = ((oldNvars - 1) >> LOGBPL) + 1; 00813 oldWords = oldWordsPerRow * oldNvars; 00814 oldLinear = table->linear; 00815 00816 nvars = table->size; 00817 wordsPerRow = ((nvars - 1) >> LOGBPL) + 1; 00818 words = wordsPerRow * nvars; 00819 table->linear = linear = ALLOC(long,words); 00820 if (linear == NULL) { 00821 table->errorCode = CUDD_MEMORY_OUT; 00822 return(0); 00823 } 00824 table->memused += (words - oldWords) * sizeof(long); 00825 for (i = 0; i < words; i++) linear[i] = 0; 00826 00827 /* Copy old matrix. */ 00828 for (i = 0; i < oldNvars; i++) { 00829 for (j = 0; j < oldWordsPerRow; j++) { 00830 oldWord = oldWordsPerRow * i + j; 00831 word = wordsPerRow * i + j; 00832 linear[word] = oldLinear[oldWord]; 00833 } 00834 } 00835 FREE(oldLinear); 00836 00837 /* Add elements to the diagonal. */ 00838 for (i = oldNvars; i < nvars; i++) { 00839 word = wordsPerRow * i + (i >> LOGBPL); 00840 bit = i & (BPL-1); 00841 linear[word] = 1 << bit; 00842 } 00843 table->linearSize = nvars; 00844 00845 return(1); 00846 00847 } /* end of cuddResizeLinear */
int cuddResizeTableZdd | ( | DdManager * | unique, | |
int | index | |||
) |
Function********************************************************************
Synopsis [Increases the number of ZDD subtables in a unique table so that it meets or exceeds index.]
Description [Increases the number of ZDD subtables in a unique table so that it meets or exceeds index. When new ZDD variables are created, it is possible to preserve the functions unchanged, or it is possible to preserve the covers unchanged, but not both. cuddResizeTableZdd preserves the covers. Returns 1 if successful; 0 otherwise.]
SideEffects [None]
SeeAlso [ddResizeTable]
Definition at line 2226 of file cuddTable.c.
02229 { 02230 DdSubtable *newsubtables; 02231 DdNodePtr *newnodelist; 02232 int oldsize,newsize; 02233 int i,j,reorderSave; 02234 unsigned int numSlots = unique->initSlots; 02235 int *newperm, *newinvperm; 02236 02237 oldsize = unique->sizeZ; 02238 /* Easy case: there is still room in the current table. */ 02239 if (index < unique->maxSizeZ) { 02240 for (i = oldsize; i <= index; i++) { 02241 unique->subtableZ[i].slots = numSlots; 02242 unique->subtableZ[i].shift = sizeof(int) * 8 - 02243 cuddComputeFloorLog2(numSlots); 02244 unique->subtableZ[i].keys = 0; 02245 unique->subtableZ[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY; 02246 unique->subtableZ[i].dead = 0; 02247 unique->permZ[i] = i; 02248 unique->invpermZ[i] = i; 02249 newnodelist = unique->subtableZ[i].nodelist = 02250 ALLOC(DdNodePtr, numSlots); 02251 if (newnodelist == NULL) { 02252 unique->errorCode = CUDD_MEMORY_OUT; 02253 return(0); 02254 } 02255 for (j = 0; (unsigned) j < numSlots; j++) { 02256 newnodelist[j] = NULL; 02257 } 02258 } 02259 } else { 02260 /* The current table is too small: we need to allocate a new, 02261 ** larger one; move all old subtables, and initialize the new 02262 ** subtables up to index included. 02263 */ 02264 newsize = index + DD_DEFAULT_RESIZE; 02265 #ifdef DD_VERBOSE 02266 (void) fprintf(unique->err, 02267 "Increasing the ZDD table size from %d to %d\n", 02268 unique->maxSizeZ, newsize); 02269 #endif 02270 newsubtables = ALLOC(DdSubtable,newsize); 02271 if (newsubtables == NULL) { 02272 unique->errorCode = CUDD_MEMORY_OUT; 02273 return(0); 02274 } 02275 newperm = ALLOC(int,newsize); 02276 if (newperm == NULL) { 02277 unique->errorCode = CUDD_MEMORY_OUT; 02278 return(0); 02279 } 02280 newinvperm = ALLOC(int,newsize); 02281 if (newinvperm == NULL) { 02282 unique->errorCode = CUDD_MEMORY_OUT; 02283 return(0); 02284 } 02285 unique->memused += (newsize - unique->maxSizeZ) * ((numSlots+1) * 02286 sizeof(DdNode *) + 2 * sizeof(int) + sizeof(DdSubtable)); 02287 if (newsize > unique->maxSize) { 02288 FREE(unique->stack); 02289 unique->stack = ALLOC(DdNodePtr,newsize + 1); 02290 if (unique->stack == NULL) { 02291 unique->errorCode = CUDD_MEMORY_OUT; 02292 return(0); 02293 } 02294 unique->stack[0] = NULL; /* to suppress harmless UMR */ 02295 unique->memused += 02296 (newsize - ddMax(unique->maxSize,unique->maxSizeZ)) 02297 * sizeof(DdNode *); 02298 } 02299 for (i = 0; i < oldsize; i++) { 02300 newsubtables[i].slots = unique->subtableZ[i].slots; 02301 newsubtables[i].shift = unique->subtableZ[i].shift; 02302 newsubtables[i].keys = unique->subtableZ[i].keys; 02303 newsubtables[i].maxKeys = unique->subtableZ[i].maxKeys; 02304 newsubtables[i].dead = unique->subtableZ[i].dead; 02305 newsubtables[i].nodelist = unique->subtableZ[i].nodelist; 02306 newperm[i] = unique->permZ[i]; 02307 newinvperm[i] = unique->invpermZ[i]; 02308 } 02309 for (i = oldsize; i <= index; i++) { 02310 newsubtables[i].slots = numSlots; 02311 newsubtables[i].shift = sizeof(int) * 8 - 02312 cuddComputeFloorLog2(numSlots); 02313 newsubtables[i].keys = 0; 02314 newsubtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY; 02315 newsubtables[i].dead = 0; 02316 newperm[i] = i; 02317 newinvperm[i] = i; 02318 newnodelist = newsubtables[i].nodelist = ALLOC(DdNodePtr, numSlots); 02319 if (newnodelist == NULL) { 02320 unique->errorCode = CUDD_MEMORY_OUT; 02321 return(0); 02322 } 02323 for (j = 0; (unsigned) j < numSlots; j++) { 02324 newnodelist[j] = NULL; 02325 } 02326 } 02327 FREE(unique->subtableZ); 02328 unique->subtableZ = newsubtables; 02329 unique->maxSizeZ = newsize; 02330 FREE(unique->permZ); 02331 unique->permZ = newperm; 02332 FREE(unique->invpermZ); 02333 unique->invpermZ = newinvperm; 02334 } 02335 unique->slots += (index + 1 - unique->sizeZ) * numSlots; 02336 ddFixLimits(unique); 02337 unique->sizeZ = index + 1; 02338 02339 /* Now that the table is in a coherent state, update the ZDD 02340 ** universe. We need to temporarily disable reordering, 02341 ** because we cannot reorder without universe in place. 02342 */ 02343 02344 reorderSave = unique->autoDynZ; 02345 unique->autoDynZ = 0; 02346 cuddZddFreeUniv(unique); 02347 if (!cuddZddInitUniv(unique)) { 02348 unique->autoDynZ = reorderSave; 02349 return(0); 02350 } 02351 unique->autoDynZ = reorderSave; 02352 02353 return(1); 02354 02355 } /* end of cuddResizeTableZdd */
void cuddSetInteract | ( | DdManager * | table, | |
int | x, | |||
int | y | |||
) |
AutomaticEnd Function********************************************************************
Synopsis [Set interaction matrix entries.]
Description [Given a pair of variables 0 <= x < y < table->size, sets the corresponding bit of the interaction matrix to 1.]
SideEffects [None]
SeeAlso []
Definition at line 152 of file cuddInteract.c.
00156 { 00157 int posn, word, bit; 00158 00159 #ifdef DD_DEBUG 00160 assert(x < y); 00161 assert(y < table->size); 00162 assert(x >= 0); 00163 #endif 00164 00165 posn = ((((table->size << 1) - x - 3) * x) >> 1) + y - 1; 00166 word = posn >> LOGBPL; 00167 bit = posn & (BPL-1); 00168 table->interact[word] |= 1L << bit; 00169 00170 } /* end of cuddSetInteract */
void cuddShrinkDeathRow | ( | DdManager * | table | ) |
Function********************************************************************
Synopsis [Shrinks the death row.]
Description [Shrinks the death row by a factor of four.]
SideEffects [None]
SeeAlso [cuddClearDeathRow]
Definition at line 684 of file cuddRef.c.
00686 { 00687 #ifndef DD_NO_DEATH_ROW 00688 int i; 00689 00690 if (table->deathRowDepth > 3) { 00691 for (i = table->deathRowDepth/4; i < table->deathRowDepth; i++) { 00692 if (table->deathRow[i] == NULL) break; 00693 Cudd_IterDerefBdd(table,table->deathRow[i]); 00694 table->deathRow[i] = NULL; 00695 } 00696 table->deathRowDepth /= 4; 00697 table->deadMask = table->deathRowDepth - 1; 00698 if ((unsigned) table->nextDead > table->deadMask) { 00699 table->nextDead = 0; 00700 } 00701 table->deathRow = REALLOC(DdNodePtr, table->deathRow, 00702 table->deathRowDepth); 00703 } 00704 #endif 00705 00706 } /* end of cuddShrinkDeathRow */
void cuddShrinkSubtable | ( | DdManager * | unique, | |
int | i | |||
) |
Function********************************************************************
Synopsis [Shrinks a subtable.]
Description [Shrinks a subtable.]
SideEffects [None]
SeeAlso [cuddRehash]
Definition at line 1687 of file cuddTable.c.
01690 { 01691 int j; 01692 int shift, posn; 01693 DdNodePtr *nodelist, *oldnodelist; 01694 DdNode *node, *next; 01695 DdNode *sentinel = &(unique->sentinel); 01696 unsigned int slots, oldslots; 01697 extern DD_OOMFP MMoutOfMemory; 01698 DD_OOMFP saveHandler; 01699 01700 oldnodelist = unique->subtables[i].nodelist; 01701 oldslots = unique->subtables[i].slots; 01702 slots = oldslots >> 1; 01703 saveHandler = MMoutOfMemory; 01704 MMoutOfMemory = Cudd_OutOfMem; 01705 nodelist = ALLOC(DdNodePtr, slots); 01706 MMoutOfMemory = saveHandler; 01707 if (nodelist == NULL) { 01708 return; 01709 } 01710 unique->subtables[i].nodelist = nodelist; 01711 unique->subtables[i].slots = slots; 01712 unique->subtables[i].shift++; 01713 unique->subtables[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; 01714 #ifdef DD_VERBOSE 01715 (void) fprintf(unique->err, 01716 "shrunk layer %d (%d keys) from %d to %d slots\n", 01717 i, unique->subtables[i].keys, oldslots, slots); 01718 #endif 01719 01720 for (j = 0; (unsigned) j < slots; j++) { 01721 nodelist[j] = sentinel; 01722 } 01723 shift = unique->subtables[i].shift; 01724 for (j = 0; (unsigned) j < oldslots; j++) { 01725 node = oldnodelist[j]; 01726 while (node != sentinel) { 01727 DdNode *looking, *T, *E; 01728 DdNodePtr *previousP; 01729 next = node->next; 01730 posn = ddHash(cuddT(node), cuddE(node), shift); 01731 previousP = &(nodelist[posn]); 01732 looking = *previousP; 01733 T = cuddT(node); 01734 E = cuddE(node); 01735 while (T < cuddT(looking)) { 01736 previousP = &(looking->next); 01737 looking = *previousP; 01738 #ifdef DD_UNIQUE_PROFILE 01739 unique->uniqueLinks++; 01740 #endif 01741 } 01742 while (T == cuddT(looking) && E < cuddE(looking)) { 01743 previousP = &(looking->next); 01744 looking = *previousP; 01745 #ifdef DD_UNIQUE_PROFILE 01746 unique->uniqueLinks++; 01747 #endif 01748 } 01749 node->next = *previousP; 01750 *previousP = node; 01751 node = next; 01752 } 01753 } 01754 FREE(oldnodelist); 01755 01756 unique->memused += ((long) slots - (long) oldslots) * sizeof(DdNode *); 01757 unique->slots += slots - oldslots; 01758 unique->minDead = (unsigned) (unique->gcFrac * (double) unique->slots); 01759 unique->cacheSlack = (int) 01760 ddMin(unique->maxCacheHard,DD_MAX_CACHE_TO_SLOTS_RATIO * unique->slots) 01761 - 2 * (int) unique->cacheSlots; 01762 01763 } /* end of cuddShrinkSubtable */
int cuddSifting | ( | DdManager * | table, | |
int | lower, | |||
int | upper | |||
) |
Function********************************************************************
Synopsis [Implementation of Rudell's sifting algorithm.]
Description [Implementation of Rudell's sifting algorithm. Assumes that no dead nodes are present.
Returns 1 if successful; 0 otherwise.]
SideEffects [None]
Definition at line 499 of file cuddReorder.c.
00503 { 00504 int i; 00505 int *var; 00506 int size; 00507 int x; 00508 int result; 00509 #ifdef DD_STATS 00510 int previousSize; 00511 #endif 00512 00513 size = table->size; 00514 00515 /* Find order in which to sift variables. */ 00516 var = NULL; 00517 entry = ALLOC(int,size); 00518 if (entry == NULL) { 00519 table->errorCode = CUDD_MEMORY_OUT; 00520 goto cuddSiftingOutOfMem; 00521 } 00522 var = ALLOC(int,size); 00523 if (var == NULL) { 00524 table->errorCode = CUDD_MEMORY_OUT; 00525 goto cuddSiftingOutOfMem; 00526 } 00527 00528 for (i = 0; i < size; i++) { 00529 x = table->perm[i]; 00530 entry[i] = table->subtables[x].keys; 00531 var[i] = i; 00532 } 00533 00534 qsort((void *)var,size,sizeof(int),(DD_QSFP)ddUniqueCompare); 00535 00536 /* Now sift. */ 00537 for (i = 0; i < ddMin(table->siftMaxVar,size); i++) { 00538 if (ddTotalNumberSwapping >= table->siftMaxSwap) 00539 break; 00540 x = table->perm[var[i]]; 00541 00542 if (x < lower || x > upper || table->subtables[x].bindVar == 1) 00543 continue; 00544 #ifdef DD_STATS 00545 previousSize = table->keys - table->isolated; 00546 #endif 00547 result = ddSiftingAux(table, x, lower, upper); 00548 if (!result) goto cuddSiftingOutOfMem; 00549 #ifdef DD_STATS 00550 if (table->keys < (unsigned) previousSize + table->isolated) { 00551 (void) fprintf(table->out,"-"); 00552 } else if (table->keys > (unsigned) previousSize + table->isolated) { 00553 (void) fprintf(table->out,"+"); /* should never happen */ 00554 (void) fprintf(table->err,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keys - table->isolated, var[i]); 00555 } else { 00556 (void) fprintf(table->out,"="); 00557 } 00558 fflush(table->out); 00559 #endif 00560 } 00561 00562 FREE(var); 00563 FREE(entry); 00564 00565 return(1); 00566 00567 cuddSiftingOutOfMem: 00568 00569 if (entry != NULL) FREE(entry); 00570 if (var != NULL) FREE(var); 00571 00572 return(0); 00573 00574 } /* end of cuddSifting */
void cuddSlowTableGrowth | ( | DdManager * | unique | ) |
Function********************************************************************
Synopsis [Adjusts parameters of a table to slow down its growth.]
Description []
SideEffects [None]
SeeAlso []
Definition at line 2370 of file cuddTable.c.
02372 { 02373 int i; 02374 02375 unique->maxCacheHard = unique->cacheSlots - 1; 02376 unique->cacheSlack = - (int) (unique->cacheSlots + 1); 02377 for (i = 0; i < unique->size; i++) { 02378 unique->subtables[i].maxKeys <<= 2; 02379 } 02380 unique->gcFrac = DD_GC_FRAC_MIN; 02381 unique->minDead = (unsigned) (DD_GC_FRAC_MIN * (double) unique->slots); 02382 cuddShrinkDeathRow(unique); 02383 (void) fprintf(unique->err,"Slowing down table growth: "); 02384 (void) fprintf(unique->err,"GC fraction = %.2f\t", unique->gcFrac); 02385 (void) fprintf(unique->err,"minDead = %u\n", unique->minDead); 02386 02387 } /* end of cuddSlowTableGrowth */
DdNode* cuddSolveEqnRecur | ( | DdManager * | bdd, | |
DdNode * | F, | |||
DdNode * | Y, | |||
DdNode ** | G, | |||
int | n, | |||
int * | yIndex, | |||
int | i | |||
) |
Function********************************************************************
Synopsis [Implements the recursive step of Cudd_SolveEqn.]
Description [Implements the recursive step of Cudd_SolveEqn. Returns NULL if the intermediate solution blows up or reordering occurs. The parametric solutions are stored in the array G.]
SideEffects [none]
SeeAlso [Cudd_SolveEqn, Cudd_VerifySol]
Definition at line 206 of file cuddSolve.c.
00214 { 00215 DdNode *Fn, *Fm1, *Fv, *Fvbar, *T, *w, *nextY, *one; 00216 DdNodePtr *variables; 00217 00218 int j; 00219 00220 statLine(bdd); 00221 variables = bdd->vars; 00222 one = DD_ONE(bdd); 00223 00224 /* Base condition. */ 00225 if (Y == one) { 00226 return F; 00227 } 00228 00229 /* Cofactor of Y. */ 00230 yIndex[i] = Y->index; 00231 nextY = Cudd_T(Y); 00232 00233 /* Universal abstraction of F with respect to the top variable index. */ 00234 Fm1 = cuddBddExistAbstractRecur(bdd, Cudd_Not(F), variables[yIndex[i]]); 00235 if (Fm1) { 00236 Fm1 = Cudd_Not(Fm1); 00237 cuddRef(Fm1); 00238 } else { 00239 return(NULL); 00240 } 00241 00242 Fn = cuddSolveEqnRecur(bdd, Fm1, nextY, G, n, yIndex, i+1); 00243 if (Fn) { 00244 cuddRef(Fn); 00245 } else { 00246 Cudd_RecursiveDeref(bdd, Fm1); 00247 return(NULL); 00248 } 00249 00250 Fv = cuddCofactorRecur(bdd, F, variables[yIndex[i]]); 00251 if (Fv) { 00252 cuddRef(Fv); 00253 } else { 00254 Cudd_RecursiveDeref(bdd, Fm1); 00255 Cudd_RecursiveDeref(bdd, Fn); 00256 return(NULL); 00257 } 00258 00259 Fvbar = cuddCofactorRecur(bdd, F, Cudd_Not(variables[yIndex[i]])); 00260 if (Fvbar) { 00261 cuddRef(Fvbar); 00262 } else { 00263 Cudd_RecursiveDeref(bdd, Fm1); 00264 Cudd_RecursiveDeref(bdd, Fn); 00265 Cudd_RecursiveDeref(bdd, Fv); 00266 return(NULL); 00267 } 00268 00269 /* Build i-th component of the solution. */ 00270 w = cuddBddIteRecur(bdd, variables[yIndex[i]], Cudd_Not(Fv), Fvbar); 00271 if (w) { 00272 cuddRef(w); 00273 } else { 00274 Cudd_RecursiveDeref(bdd, Fm1); 00275 Cudd_RecursiveDeref(bdd, Fn); 00276 Cudd_RecursiveDeref(bdd, Fv); 00277 Cudd_RecursiveDeref(bdd, Fvbar); 00278 return(NULL); 00279 } 00280 00281 T = cuddBddRestrictRecur(bdd, w, Cudd_Not(Fm1)); 00282 if(T) { 00283 cuddRef(T); 00284 } else { 00285 Cudd_RecursiveDeref(bdd, Fm1); 00286 Cudd_RecursiveDeref(bdd, Fn); 00287 Cudd_RecursiveDeref(bdd, Fv); 00288 Cudd_RecursiveDeref(bdd, Fvbar); 00289 Cudd_RecursiveDeref(bdd, w); 00290 return(NULL); 00291 } 00292 00293 Cudd_RecursiveDeref(bdd,Fm1); 00294 Cudd_RecursiveDeref(bdd,w); 00295 Cudd_RecursiveDeref(bdd,Fv); 00296 Cudd_RecursiveDeref(bdd,Fvbar); 00297 00298 /* Substitute components of solution already found into solution. */ 00299 for (j = n-1; j > i; j--) { 00300 w = cuddBddComposeRecur(bdd,T, G[j], variables[yIndex[j]]); 00301 if(w) { 00302 cuddRef(w); 00303 } else { 00304 Cudd_RecursiveDeref(bdd, Fn); 00305 Cudd_RecursiveDeref(bdd, T); 00306 return(NULL); 00307 } 00308 Cudd_RecursiveDeref(bdd,T); 00309 T = w; 00310 } 00311 G[i] = T; 00312 00313 Cudd_Deref(Fn); 00314 00315 return(Fn); 00316 00317 } /* end of cuddSolveEqnRecur */
Function********************************************************************
Synopsis [The main procedure that returns a subset by choosing the heavier branch in the BDD.]
Description [Here a subset BDD is built by throwing away one of the children. Starting at root, annotate each node with the number of minterms (in terms of the total number of variables specified - numVars), number of nodes taken by the DAG rooted at this node and number of additional nodes taken by the child that has the lesser minterms. The child with the lower number of minterms is thrown away and a dyanmic count of the nodes of the subset is kept. Once the threshold is reached the subset is returned to the calling procedure.]
SideEffects [None]
SeeAlso [Cudd_SubsetHeavyBranch]
Definition at line 301 of file cuddSubsetHB.c.
00306 { 00307 00308 int i, *size; 00309 st_table *visitedTable; 00310 int numNodes; 00311 NodeData_t *currNodeQual; 00312 DdNode *subset; 00313 st_table *storeTable, *approxTable; 00314 char *key, *value; 00315 st_generator *stGen; 00316 00317 if (f == NULL) { 00318 fprintf(dd->err, "Cannot subset, nil object\n"); 00319 dd->errorCode = CUDD_INVALID_ARG; 00320 return(NULL); 00321 } 00322 00323 one = Cudd_ReadOne(dd); 00324 zero = Cudd_Not(one); 00325 00326 /* If user does not know numVars value, set it to the maximum 00327 * exponent that the pow function can take. The -1 is due to the 00328 * discrepancy in the value that pow takes and the value that 00329 * log gives. 00330 */ 00331 if (numVars == 0) { 00332 /* set default value */ 00333 numVars = DBL_MAX_EXP - 1; 00334 } 00335 00336 if (Cudd_IsConstant(f)) { 00337 return(f); 00338 } 00339 00340 max = pow(2.0, (double)numVars); 00341 00342 /* Create visited table where structures for node data are allocated and 00343 stored in a st_table */ 00344 visitedTable = SubsetCountMinterm(f, numVars); 00345 if ((visitedTable == NULL) || memOut) { 00346 (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); 00347 dd->errorCode = CUDD_MEMORY_OUT; 00348 return(0); 00349 } 00350 numNodes = SubsetCountNodes(f, visitedTable, numVars); 00351 if (memOut) { 00352 (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); 00353 dd->errorCode = CUDD_MEMORY_OUT; 00354 return(0); 00355 } 00356 00357 if (st_lookup(visitedTable, f, &currNodeQual) == 0) { 00358 fprintf(dd->err, 00359 "Something is wrong, ought to be node quality table\n"); 00360 dd->errorCode = CUDD_INTERNAL_ERROR; 00361 } 00362 00363 size = ALLOC(int, 1); 00364 if (size == NULL) { 00365 dd->errorCode = CUDD_MEMORY_OUT; 00366 return(NULL); 00367 } 00368 *size = numNodes; 00369 00370 #ifdef DEBUG 00371 num_calls = 0; 00372 #endif 00373 /* table to store nodes being created. */ 00374 storeTable = st_init_table(st_ptrcmp, st_ptrhash); 00375 /* insert the constant */ 00376 cuddRef(one); 00377 if (st_insert(storeTable, (char *)Cudd_ReadOne(dd), NIL(char)) == 00378 ST_OUT_OF_MEM) { 00379 fprintf(dd->out, "Something wrong, st_table insert failed\n"); 00380 } 00381 /* table to store approximations of nodes */ 00382 approxTable = st_init_table(st_ptrcmp, st_ptrhash); 00383 subset = (DdNode *)BuildSubsetBdd(dd, f, size, visitedTable, threshold, 00384 storeTable, approxTable); 00385 if (subset != NULL) { 00386 cuddRef(subset); 00387 } 00388 00389 stGen = st_init_gen(approxTable); 00390 if (stGen == NULL) { 00391 st_free_table(approxTable); 00392 return(NULL); 00393 } 00394 while(st_gen(stGen, (char **)&key, (char **)&value)) { 00395 Cudd_RecursiveDeref(dd, (DdNode *)value); 00396 } 00397 st_free_gen(stGen); stGen = NULL; 00398 st_free_table(approxTable); 00399 00400 stGen = st_init_gen(storeTable); 00401 if (stGen == NULL) { 00402 st_free_table(storeTable); 00403 return(NULL); 00404 } 00405 while(st_gen(stGen, (char **)&key, (char **)&value)) { 00406 Cudd_RecursiveDeref(dd, (DdNode *)key); 00407 } 00408 st_free_gen(stGen); stGen = NULL; 00409 st_free_table(storeTable); 00410 00411 for (i = 0; i <= page; i++) { 00412 FREE(mintermPages[i]); 00413 } 00414 FREE(mintermPages); 00415 for (i = 0; i <= page; i++) { 00416 FREE(nodePages[i]); 00417 } 00418 FREE(nodePages); 00419 for (i = 0; i <= page; i++) { 00420 FREE(lightNodePages[i]); 00421 } 00422 FREE(lightNodePages); 00423 for (i = 0; i <= nodeDataPage; i++) { 00424 FREE(nodeDataPages[i]); 00425 } 00426 FREE(nodeDataPages); 00427 st_free_table(visitedTable); 00428 FREE(size); 00429 #if 0 00430 (void) Cudd_DebugCheck(dd); 00431 (void) Cudd_CheckKeys(dd); 00432 #endif 00433 00434 if (subset != NULL) { 00435 #ifdef DD_DEBUG 00436 if (!Cudd_bddLeq(dd, subset, f)) { 00437 fprintf(dd->err, "Wrong subset\n"); 00438 dd->errorCode = CUDD_INTERNAL_ERROR; 00439 return(NULL); 00440 } 00441 #endif 00442 cuddDeref(subset); 00443 return(subset); 00444 } else { 00445 return(NULL); 00446 } 00447 } /* end of cuddSubsetHeavyBranch */
DdNode* cuddSubsetShortPaths | ( | DdManager * | dd, | |
DdNode * | f, | |||
int | numVars, | |||
int | threshold, | |||
int | hardlimit | |||
) |
Function********************************************************************
Synopsis [The outermost procedure to return a subset of the given BDD with the shortest path lengths.]
Description [The outermost procedure to return a subset of the given BDD with the largest cubes. The path lengths are calculated, the maximum allowable path length is determined and the number of nodes of this path length that can be used to build a subset. If the threshold is larger than the size of the original BDD, the original BDD is returned. ]
SideEffects [None]
SeeAlso [Cudd_SubsetShortPaths]
Definition at line 312 of file cuddSubsetSP.c.
00318 { 00319 st_table *pathTable; 00320 DdNode *N, *subset; 00321 00322 unsigned int *pathLengthArray; 00323 unsigned int maxpath, oddLen, evenLen, pathLength, *excess; 00324 int i; 00325 NodeDist_t *nodeStat; 00326 struct AssortedInfo *info; 00327 st_table *subsetNodeTable; 00328 00329 one = DD_ONE(dd); 00330 zero = Cudd_Not(one); 00331 00332 if (numVars == 0) { 00333 /* set default value */ 00334 numVars = Cudd_ReadSize(dd); 00335 } 00336 00337 if (threshold > numVars) { 00338 threshold = threshold - numVars; 00339 } 00340 if (f == NULL) { 00341 fprintf(dd->err, "Cannot partition, nil object\n"); 00342 dd->errorCode = CUDD_INVALID_ARG; 00343 return(NULL); 00344 } 00345 if (Cudd_IsConstant(f)) 00346 return (f); 00347 00348 pathLengthArray = ALLOC(unsigned int, numVars+1); 00349 for (i = 0; i < numVars+1; i++) pathLengthArray[i] = 0; 00350 00351 00352 #ifdef DD_DEBUG 00353 numCalls = 0; 00354 #endif 00355 00356 pathTable = CreatePathTable(f, pathLengthArray, dd->err); 00357 00358 if ((pathTable == NULL) || (memOut)) { 00359 if (pathTable != NULL) 00360 st_free_table(pathTable); 00361 FREE(pathLengthArray); 00362 return (NIL(DdNode)); 00363 } 00364 00365 excess = ALLOC(unsigned int, 1); 00366 *excess = 0; 00367 maxpath = AssessPathLength(pathLengthArray, threshold, numVars, excess, 00368 dd->err); 00369 00370 if (maxpath != (unsigned) (numVars + 1)) { 00371 00372 info = ALLOC(struct AssortedInfo, 1); 00373 info->maxpath = maxpath; 00374 info->findShortestPath = 0; 00375 info->thresholdReached = *excess; 00376 info->maxpathTable = st_init_table(st_ptrcmp, st_ptrhash); 00377 info->threshold = threshold; 00378 00379 #ifdef DD_DEBUG 00380 (void) fprintf(dd->out, "Path length array\n"); 00381 for (i = 0; i < (numVars+1); i++) { 00382 if (pathLengthArray[i]) 00383 (void) fprintf(dd->out, "%d ",i); 00384 } 00385 (void) fprintf(dd->out, "\n"); 00386 for (i = 0; i < (numVars+1); i++) { 00387 if (pathLengthArray[i]) 00388 (void) fprintf(dd->out, "%d ",pathLengthArray[i]); 00389 } 00390 (void) fprintf(dd->out, "\n"); 00391 (void) fprintf(dd->out, "Maxpath = %d, Thresholdreached = %d\n", 00392 maxpath, info->thresholdReached); 00393 #endif 00394 00395 N = Cudd_Regular(f); 00396 if (!st_lookup(pathTable, N, &nodeStat)) { 00397 fprintf(dd->err, "Something wrong, root node must be in table\n"); 00398 dd->errorCode = CUDD_INTERNAL_ERROR; 00399 FREE(excess); 00400 FREE(info); 00401 return(NULL); 00402 } else { 00403 if ((nodeStat->oddTopDist != MAXSHORTINT) && 00404 (nodeStat->oddBotDist != MAXSHORTINT)) 00405 oddLen = (nodeStat->oddTopDist + nodeStat->oddBotDist); 00406 else 00407 oddLen = MAXSHORTINT; 00408 00409 if ((nodeStat->evenTopDist != MAXSHORTINT) && 00410 (nodeStat->evenBotDist != MAXSHORTINT)) 00411 evenLen = (nodeStat->evenTopDist +nodeStat->evenBotDist); 00412 else 00413 evenLen = MAXSHORTINT; 00414 00415 pathLength = (oddLen <= evenLen) ? oddLen : evenLen; 00416 if (pathLength > maxpath) { 00417 (void) fprintf(dd->err, "All computations are bogus, since root has path length greater than max path length within threshold %u, %u\n", maxpath, pathLength); 00418 dd->errorCode = CUDD_INTERNAL_ERROR; 00419 return(NULL); 00420 } 00421 } 00422 00423 #ifdef DD_DEBUG 00424 numCalls = 0; 00425 hits = 0; 00426 thishit = 0; 00427 #endif 00428 /* initialize a table to store computed nodes */ 00429 if (hardlimit) { 00430 subsetNodeTable = st_init_table(st_ptrcmp, st_ptrhash); 00431 } else { 00432 subsetNodeTable = NIL(st_table); 00433 } 00434 subset = BuildSubsetBdd(dd, pathTable, f, info, subsetNodeTable); 00435 if (subset != NULL) { 00436 cuddRef(subset); 00437 } 00438 /* record the number of times a computed result for a node is hit */ 00439 00440 #ifdef DD_DEBUG 00441 (void) fprintf(dd->out, "Hits = %d, New==Node = %d, NumCalls = %d\n", 00442 hits, thishit, numCalls); 00443 #endif 00444 00445 if (subsetNodeTable != NIL(st_table)) { 00446 st_free_table(subsetNodeTable); 00447 } 00448 st_free_table(info->maxpathTable); 00449 st_foreach(pathTable, stPathTableDdFree, (char *)dd); 00450 00451 FREE(info); 00452 00453 } else {/* if threshold larger than size of dd */ 00454 subset = f; 00455 cuddRef(subset); 00456 } 00457 FREE(excess); 00458 st_free_table(pathTable); 00459 FREE(pathLengthArray); 00460 for (i = 0; i <= nodeDistPage; i++) FREE(nodeDistPages[i]); 00461 FREE(nodeDistPages); 00462 00463 #ifdef DD_DEBUG 00464 /* check containment of subset in f */ 00465 if (subset != NULL) { 00466 DdNode *check; 00467 check = Cudd_bddIteConstant(dd, subset, f, one); 00468 if (check != one) { 00469 (void) fprintf(dd->err, "Wrong partition\n"); 00470 dd->errorCode = CUDD_INTERNAL_ERROR; 00471 return(NULL); 00472 } 00473 } 00474 #endif 00475 00476 if (subset != NULL) { 00477 cuddDeref(subset); 00478 return(subset); 00479 } else { 00480 return(NULL); 00481 } 00482 00483 } /* end of cuddSubsetShortPaths */
int cuddSwapInPlace | ( | DdManager * | table, | |
int | x, | |||
int | y | |||
) |
Function********************************************************************
Synopsis [Swaps two adjacent variables.]
Description [Swaps two adjacent variables. It assumes that no dead nodes are present on entry to this procedure. The procedure then guarantees that no dead nodes will be present when it terminates. cuddSwapInPlace assumes that x < y. Returns the number of keys in the table if successful; 0 otherwise.]
SideEffects [None]
Definition at line 752 of file cuddReorder.c.
00756 { 00757 DdNodePtr *xlist, *ylist; 00758 int xindex, yindex; 00759 int xslots, yslots; 00760 int xshift, yshift; 00761 int oldxkeys, oldykeys; 00762 int newxkeys, newykeys; 00763 int comple, newcomplement; 00764 int i; 00765 Cudd_VariableType varType; 00766 Cudd_LazyGroupType groupType; 00767 int posn; 00768 int isolated; 00769 DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10,*newf1,*newf0; 00770 DdNode *g,*next; 00771 DdNodePtr *previousP; 00772 DdNode *tmp; 00773 DdNode *sentinel = &(table->sentinel); 00774 extern DD_OOMFP MMoutOfMemory; 00775 DD_OOMFP saveHandler; 00776 00777 #ifdef DD_DEBUG 00778 int count,idcheck; 00779 #endif 00780 00781 #ifdef DD_DEBUG 00782 assert(x < y); 00783 assert(cuddNextHigh(table,x) == y); 00784 assert(table->subtables[x].keys != 0); 00785 assert(table->subtables[y].keys != 0); 00786 assert(table->subtables[x].dead == 0); 00787 assert(table->subtables[y].dead == 0); 00788 #endif 00789 00790 ddTotalNumberSwapping++; 00791 00792 /* Get parameters of x subtable. */ 00793 xindex = table->invperm[x]; 00794 xlist = table->subtables[x].nodelist; 00795 oldxkeys = table->subtables[x].keys; 00796 xslots = table->subtables[x].slots; 00797 xshift = table->subtables[x].shift; 00798 00799 /* Get parameters of y subtable. */ 00800 yindex = table->invperm[y]; 00801 ylist = table->subtables[y].nodelist; 00802 oldykeys = table->subtables[y].keys; 00803 yslots = table->subtables[y].slots; 00804 yshift = table->subtables[y].shift; 00805 00806 if (!cuddTestInteract(table,xindex,yindex)) { 00807 #ifdef DD_STATS 00808 ddTotalNISwaps++; 00809 #endif 00810 newxkeys = oldxkeys; 00811 newykeys = oldykeys; 00812 } else { 00813 newxkeys = 0; 00814 newykeys = oldykeys; 00815 00816 /* Check whether the two projection functions involved in this 00817 ** swap are isolated. At the end, we'll be able to tell how many 00818 ** isolated projection functions are there by checking only these 00819 ** two functions again. This is done to eliminate the isolated 00820 ** projection functions from the node count. 00821 */ 00822 isolated = - ((table->vars[xindex]->ref == 1) + 00823 (table->vars[yindex]->ref == 1)); 00824 00825 /* The nodes in the x layer that do not depend on 00826 ** y will stay there; the others are put in a chain. 00827 ** The chain is handled as a LIFO; g points to the beginning. 00828 */ 00829 g = NULL; 00830 if ((oldxkeys >= xslots || (unsigned) xslots == table->initSlots) && 00831 oldxkeys <= DD_MAX_SUBTABLE_DENSITY * xslots) { 00832 for (i = 0; i < xslots; i++) { 00833 previousP = &(xlist[i]); 00834 f = *previousP; 00835 while (f != sentinel) { 00836 next = f->next; 00837 f1 = cuddT(f); f0 = cuddE(f); 00838 if (f1->index != (DdHalfWord) yindex && 00839 Cudd_Regular(f0)->index != (DdHalfWord) yindex) { 00840 /* stays */ 00841 newxkeys++; 00842 *previousP = f; 00843 previousP = &(f->next); 00844 } else { 00845 f->index = yindex; 00846 f->next = g; 00847 g = f; 00848 } 00849 f = next; 00850 } /* while there are elements in the collision chain */ 00851 *previousP = sentinel; 00852 } /* for each slot of the x subtable */ 00853 } else { /* resize xlist */ 00854 DdNode *h = NULL; 00855 DdNodePtr *newxlist; 00856 unsigned int newxslots; 00857 int newxshift; 00858 /* Empty current xlist. Nodes that stay go to list h; 00859 ** nodes that move go to list g. */ 00860 for (i = 0; i < xslots; i++) { 00861 f = xlist[i]; 00862 while (f != sentinel) { 00863 next = f->next; 00864 f1 = cuddT(f); f0 = cuddE(f); 00865 if (f1->index != (DdHalfWord) yindex && 00866 Cudd_Regular(f0)->index != (DdHalfWord) yindex) { 00867 /* stays */ 00868 f->next = h; 00869 h = f; 00870 newxkeys++; 00871 } else { 00872 f->index = yindex; 00873 f->next = g; 00874 g = f; 00875 } 00876 f = next; 00877 } /* while there are elements in the collision chain */ 00878 } /* for each slot of the x subtable */ 00879 /* Decide size of new subtable. */ 00880 newxshift = xshift; 00881 newxslots = xslots; 00882 while ((unsigned) oldxkeys > DD_MAX_SUBTABLE_DENSITY * newxslots) { 00883 newxshift--; 00884 newxslots <<= 1; 00885 } 00886 while ((unsigned) oldxkeys < newxslots && 00887 newxslots > table->initSlots) { 00888 newxshift++; 00889 newxslots >>= 1; 00890 } 00891 /* Try to allocate new table. Be ready to back off. */ 00892 saveHandler = MMoutOfMemory; 00893 MMoutOfMemory = Cudd_OutOfMem; 00894 newxlist = ALLOC(DdNodePtr, newxslots); 00895 MMoutOfMemory = saveHandler; 00896 if (newxlist == NULL) { 00897 (void) fprintf(table->err, "Unable to resize subtable %d for lack of memory\n", i); 00898 newxlist = xlist; 00899 newxslots = xslots; 00900 newxshift = xshift; 00901 } else { 00902 table->slots += ((int) newxslots - xslots); 00903 table->minDead = (unsigned) 00904 (table->gcFrac * (double) table->slots); 00905 table->cacheSlack = (int) 00906 ddMin(table->maxCacheHard, DD_MAX_CACHE_TO_SLOTS_RATIO 00907 * table->slots) - 2 * (int) table->cacheSlots; 00908 table->memused += 00909 ((int) newxslots - xslots) * sizeof(DdNodePtr); 00910 FREE(xlist); 00911 xslots = newxslots; 00912 xshift = newxshift; 00913 xlist = newxlist; 00914 } 00915 /* Initialize new subtable. */ 00916 for (i = 0; i < xslots; i++) { 00917 xlist[i] = sentinel; 00918 } 00919 /* Move nodes that were parked in list h to their new home. */ 00920 f = h; 00921 while (f != NULL) { 00922 next = f->next; 00923 f1 = cuddT(f); 00924 f0 = cuddE(f); 00925 /* Check xlist for pair (f11,f01). */ 00926 posn = ddHash(f1, f0, xshift); 00927 /* For each element tmp in collision list xlist[posn]. */ 00928 previousP = &(xlist[posn]); 00929 tmp = *previousP; 00930 while (f1 < cuddT(tmp)) { 00931 previousP = &(tmp->next); 00932 tmp = *previousP; 00933 } 00934 while (f1 == cuddT(tmp) && f0 < cuddE(tmp)) { 00935 previousP = &(tmp->next); 00936 tmp = *previousP; 00937 } 00938 f->next = *previousP; 00939 *previousP = f; 00940 f = next; 00941 } 00942 } 00943 00944 #ifdef DD_COUNT 00945 table->swapSteps += oldxkeys - newxkeys; 00946 #endif 00947 /* Take care of the x nodes that must be re-expressed. 00948 ** They form a linked list pointed by g. Their index has been 00949 ** already changed to yindex. 00950 */ 00951 f = g; 00952 while (f != NULL) { 00953 next = f->next; 00954 /* Find f1, f0, f11, f10, f01, f00. */ 00955 f1 = cuddT(f); 00956 #ifdef DD_DEBUG 00957 assert(!(Cudd_IsComplement(f1))); 00958 #endif 00959 if ((int) f1->index == yindex) { 00960 f11 = cuddT(f1); f10 = cuddE(f1); 00961 } else { 00962 f11 = f10 = f1; 00963 } 00964 #ifdef DD_DEBUG 00965 assert(!(Cudd_IsComplement(f11))); 00966 #endif 00967 f0 = cuddE(f); 00968 comple = Cudd_IsComplement(f0); 00969 f0 = Cudd_Regular(f0); 00970 if ((int) f0->index == yindex) { 00971 f01 = cuddT(f0); f00 = cuddE(f0); 00972 } else { 00973 f01 = f00 = f0; 00974 } 00975 if (comple) { 00976 f01 = Cudd_Not(f01); 00977 f00 = Cudd_Not(f00); 00978 } 00979 /* Decrease ref count of f1. */ 00980 cuddSatDec(f1->ref); 00981 /* Create the new T child. */ 00982 if (f11 == f01) { 00983 newf1 = f11; 00984 cuddSatInc(newf1->ref); 00985 } else { 00986 /* Check xlist for triple (xindex,f11,f01). */ 00987 posn = ddHash(f11, f01, xshift); 00988 /* For each element newf1 in collision list xlist[posn]. */ 00989 previousP = &(xlist[posn]); 00990 newf1 = *previousP; 00991 while (f11 < cuddT(newf1)) { 00992 previousP = &(newf1->next); 00993 newf1 = *previousP; 00994 } 00995 while (f11 == cuddT(newf1) && f01 < cuddE(newf1)) { 00996 previousP = &(newf1->next); 00997 newf1 = *previousP; 00998 } 00999 if (cuddT(newf1) == f11 && cuddE(newf1) == f01) { 01000 cuddSatInc(newf1->ref); 01001 } else { /* no match */ 01002 newf1 = cuddDynamicAllocNode(table); 01003 if (newf1 == NULL) 01004 goto cuddSwapOutOfMem; 01005 newf1->index = xindex; newf1->ref = 1; 01006 cuddT(newf1) = f11; 01007 cuddE(newf1) = f01; 01008 /* Insert newf1 in the collision list xlist[posn]; 01009 ** increase the ref counts of f11 and f01. 01010 */ 01011 newxkeys++; 01012 newf1->next = *previousP; 01013 *previousP = newf1; 01014 cuddSatInc(f11->ref); 01015 tmp = Cudd_Regular(f01); 01016 cuddSatInc(tmp->ref); 01017 } 01018 } 01019 cuddT(f) = newf1; 01020 #ifdef DD_DEBUG 01021 assert(!(Cudd_IsComplement(newf1))); 01022 #endif 01023 01024 /* Do the same for f0, keeping complement dots into account. */ 01025 /* Decrease ref count of f0. */ 01026 tmp = Cudd_Regular(f0); 01027 cuddSatDec(tmp->ref); 01028 /* Create the new E child. */ 01029 if (f10 == f00) { 01030 newf0 = f00; 01031 tmp = Cudd_Regular(newf0); 01032 cuddSatInc(tmp->ref); 01033 } else { 01034 /* make sure f10 is regular */ 01035 newcomplement = Cudd_IsComplement(f10); 01036 if (newcomplement) { 01037 f10 = Cudd_Not(f10); 01038 f00 = Cudd_Not(f00); 01039 } 01040 /* Check xlist for triple (xindex,f10,f00). */ 01041 posn = ddHash(f10, f00, xshift); 01042 /* For each element newf0 in collision list xlist[posn]. */ 01043 previousP = &(xlist[posn]); 01044 newf0 = *previousP; 01045 while (f10 < cuddT(newf0)) { 01046 previousP = &(newf0->next); 01047 newf0 = *previousP; 01048 } 01049 while (f10 == cuddT(newf0) && f00 < cuddE(newf0)) { 01050 previousP = &(newf0->next); 01051 newf0 = *previousP; 01052 } 01053 if (cuddT(newf0) == f10 && cuddE(newf0) == f00) { 01054 cuddSatInc(newf0->ref); 01055 } else { /* no match */ 01056 newf0 = cuddDynamicAllocNode(table); 01057 if (newf0 == NULL) 01058 goto cuddSwapOutOfMem; 01059 newf0->index = xindex; newf0->ref = 1; 01060 cuddT(newf0) = f10; 01061 cuddE(newf0) = f00; 01062 /* Insert newf0 in the collision list xlist[posn]; 01063 ** increase the ref counts of f10 and f00. 01064 */ 01065 newxkeys++; 01066 newf0->next = *previousP; 01067 *previousP = newf0; 01068 cuddSatInc(f10->ref); 01069 tmp = Cudd_Regular(f00); 01070 cuddSatInc(tmp->ref); 01071 } 01072 if (newcomplement) { 01073 newf0 = Cudd_Not(newf0); 01074 } 01075 } 01076 cuddE(f) = newf0; 01077 01078 /* Insert the modified f in ylist. 01079 ** The modified f does not already exists in ylist. 01080 ** (Because of the uniqueness of the cofactors.) 01081 */ 01082 posn = ddHash(newf1, newf0, yshift); 01083 newykeys++; 01084 previousP = &(ylist[posn]); 01085 tmp = *previousP; 01086 while (newf1 < cuddT(tmp)) { 01087 previousP = &(tmp->next); 01088 tmp = *previousP; 01089 } 01090 while (newf1 == cuddT(tmp) && newf0 < cuddE(tmp)) { 01091 previousP = &(tmp->next); 01092 tmp = *previousP; 01093 } 01094 f->next = *previousP; 01095 *previousP = f; 01096 f = next; 01097 } /* while f != NULL */ 01098 01099 /* GC the y layer. */ 01100 01101 /* For each node f in ylist. */ 01102 for (i = 0; i < yslots; i++) { 01103 previousP = &(ylist[i]); 01104 f = *previousP; 01105 while (f != sentinel) { 01106 next = f->next; 01107 if (f->ref == 0) { 01108 tmp = cuddT(f); 01109 cuddSatDec(tmp->ref); 01110 tmp = Cudd_Regular(cuddE(f)); 01111 cuddSatDec(tmp->ref); 01112 cuddDeallocNode(table,f); 01113 newykeys--; 01114 } else { 01115 *previousP = f; 01116 previousP = &(f->next); 01117 } 01118 f = next; 01119 } /* while f */ 01120 *previousP = sentinel; 01121 } /* for i */ 01122 01123 #ifdef DD_DEBUG 01124 #if 0 01125 (void) fprintf(table->out,"Swapping %d and %d\n",x,y); 01126 #endif 01127 count = 0; 01128 idcheck = 0; 01129 for (i = 0; i < yslots; i++) { 01130 f = ylist[i]; 01131 while (f != sentinel) { 01132 count++; 01133 if (f->index != (DdHalfWord) yindex) 01134 idcheck++; 01135 f = f->next; 01136 } 01137 } 01138 if (count != newykeys) { 01139 (void) fprintf(table->out, 01140 "Error in finding newykeys\toldykeys = %d\tnewykeys = %d\tactual = %d\n", 01141 oldykeys,newykeys,count); 01142 } 01143 if (idcheck != 0) 01144 (void) fprintf(table->out, 01145 "Error in id's of ylist\twrong id's = %d\n", 01146 idcheck); 01147 count = 0; 01148 idcheck = 0; 01149 for (i = 0; i < xslots; i++) { 01150 f = xlist[i]; 01151 while (f != sentinel) { 01152 count++; 01153 if (f->index != (DdHalfWord) xindex) 01154 idcheck++; 01155 f = f->next; 01156 } 01157 } 01158 if (count != newxkeys) { 01159 (void) fprintf(table->out, 01160 "Error in finding newxkeys\toldxkeys = %d \tnewxkeys = %d \tactual = %d\n", 01161 oldxkeys,newxkeys,count); 01162 } 01163 if (idcheck != 0) 01164 (void) fprintf(table->out, 01165 "Error in id's of xlist\twrong id's = %d\n", 01166 idcheck); 01167 #endif 01168 01169 isolated += (table->vars[xindex]->ref == 1) + 01170 (table->vars[yindex]->ref == 1); 01171 table->isolated += isolated; 01172 } 01173 01174 /* Set the appropriate fields in table. */ 01175 table->subtables[x].nodelist = ylist; 01176 table->subtables[x].slots = yslots; 01177 table->subtables[x].shift = yshift; 01178 table->subtables[x].keys = newykeys; 01179 table->subtables[x].maxKeys = yslots * DD_MAX_SUBTABLE_DENSITY; 01180 i = table->subtables[x].bindVar; 01181 table->subtables[x].bindVar = table->subtables[y].bindVar; 01182 table->subtables[y].bindVar = i; 01183 /* Adjust filds for lazy sifting. */ 01184 varType = table->subtables[x].varType; 01185 table->subtables[x].varType = table->subtables[y].varType; 01186 table->subtables[y].varType = varType; 01187 i = table->subtables[x].pairIndex; 01188 table->subtables[x].pairIndex = table->subtables[y].pairIndex; 01189 table->subtables[y].pairIndex = i; 01190 i = table->subtables[x].varHandled; 01191 table->subtables[x].varHandled = table->subtables[y].varHandled; 01192 table->subtables[y].varHandled = i; 01193 groupType = table->subtables[x].varToBeGrouped; 01194 table->subtables[x].varToBeGrouped = table->subtables[y].varToBeGrouped; 01195 table->subtables[y].varToBeGrouped = groupType; 01196 01197 table->subtables[y].nodelist = xlist; 01198 table->subtables[y].slots = xslots; 01199 table->subtables[y].shift = xshift; 01200 table->subtables[y].keys = newxkeys; 01201 table->subtables[y].maxKeys = xslots * DD_MAX_SUBTABLE_DENSITY; 01202 01203 table->perm[xindex] = y; table->perm[yindex] = x; 01204 table->invperm[x] = yindex; table->invperm[y] = xindex; 01205 01206 table->keys += newxkeys + newykeys - oldxkeys - oldykeys; 01207 01208 return(table->keys - table->isolated); 01209 01210 cuddSwapOutOfMem: 01211 (void) fprintf(table->err,"Error: cuddSwapInPlace out of memory\n"); 01212 01213 return (0); 01214 01215 } /* end of cuddSwapInPlace */
int cuddSwapping | ( | DdManager * | table, | |
int | lower, | |||
int | upper, | |||
Cudd_ReorderingType | heuristic | |||
) |
Function********************************************************************
Synopsis [Reorders variables by a sequence of (non-adjacent) swaps.]
Description [Implementation of Plessier's algorithm that reorders variables by a sequence of (non-adjacent) swaps.
Returns 1 in case of success; 0 otherwise.]
SideEffects [None]
Definition at line 596 of file cuddReorder.c.
00601 { 00602 int i, j; 00603 int max, keys; 00604 int nvars; 00605 int x, y; 00606 int iterate; 00607 int previousSize; 00608 Move *moves, *move; 00609 int pivot; 00610 int modulo; 00611 int result; 00612 00613 #ifdef DD_DEBUG 00614 /* Sanity check */ 00615 assert(lower >= 0 && upper < table->size && lower <= upper); 00616 #endif 00617 00618 nvars = upper - lower + 1; 00619 iterate = nvars; 00620 00621 for (i = 0; i < iterate; i++) { 00622 if (ddTotalNumberSwapping >= table->siftMaxSwap) 00623 break; 00624 if (heuristic == CUDD_REORDER_RANDOM_PIVOT) { 00625 max = -1; 00626 for (j = lower; j <= upper; j++) { 00627 if ((keys = table->subtables[j].keys) > max) { 00628 max = keys; 00629 pivot = j; 00630 } 00631 } 00632 00633 modulo = upper - pivot; 00634 if (modulo == 0) { 00635 y = pivot; 00636 } else{ 00637 y = pivot + 1 + ((int) Cudd_Random() % modulo); 00638 } 00639 00640 modulo = pivot - lower - 1; 00641 if (modulo < 1) { 00642 x = lower; 00643 } else{ 00644 do { 00645 x = (int) Cudd_Random() % modulo; 00646 } while (x == y); 00647 } 00648 } else { 00649 x = ((int) Cudd_Random() % nvars) + lower; 00650 do { 00651 y = ((int) Cudd_Random() % nvars) + lower; 00652 } while (x == y); 00653 } 00654 previousSize = table->keys - table->isolated; 00655 moves = ddSwapAny(table,x,y); 00656 if (moves == NULL) goto cuddSwappingOutOfMem; 00657 result = ddSiftingBackward(table,previousSize,moves); 00658 if (!result) goto cuddSwappingOutOfMem; 00659 while (moves != NULL) { 00660 move = moves->next; 00661 cuddDeallocMove(table, moves); 00662 moves = move; 00663 } 00664 #ifdef DD_STATS 00665 if (table->keys < (unsigned) previousSize + table->isolated) { 00666 (void) fprintf(table->out,"-"); 00667 } else if (table->keys > (unsigned) previousSize + table->isolated) { 00668 (void) fprintf(table->out,"+"); /* should never happen */ 00669 } else { 00670 (void) fprintf(table->out,"="); 00671 } 00672 fflush(table->out); 00673 #endif 00674 #if 0 00675 (void) fprintf(table->out,"#:t_SWAPPING %8d: tmp size\n", 00676 table->keys - table->isolated); 00677 #endif 00678 } 00679 00680 return(1); 00681 00682 cuddSwappingOutOfMem: 00683 while (moves != NULL) { 00684 move = moves->next; 00685 cuddDeallocMove(table, moves); 00686 moves = move; 00687 } 00688 00689 return(0); 00690 00691 } /* end of cuddSwapping */
int cuddSymmCheck | ( | DdManager * | table, | |
int | x, | |||
int | y | |||
) |
Function********************************************************************
Synopsis [Checks for symmetry of x and y.]
Description [Checks for symmetry of x and y. Ignores projection functions, unless they are isolated. Returns 1 in case of symmetry; 0 otherwise.]
SideEffects [None]
Definition at line 188 of file cuddSymmetry.c.
00192 { 00193 DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10; 00194 int comple; /* f0 is complemented */ 00195 int xsymmy; /* x and y may be positively symmetric */ 00196 int xsymmyp; /* x and y may be negatively symmetric */ 00197 int arccount; /* number of arcs from layer x to layer y */ 00198 int TotalRefCount; /* total reference count of layer y minus 1 */ 00199 int yindex; 00200 int i; 00201 DdNodePtr *list; 00202 int slots; 00203 DdNode *sentinel = &(table->sentinel); 00204 #ifdef DD_DEBUG 00205 int xindex; 00206 #endif 00207 00208 /* Checks that x and y are not the projection functions. 00209 ** For x it is sufficient to check whether there is only one 00210 ** node; indeed, if there is one node, it is the projection function 00211 ** and it cannot point to y. Hence, if y isn't just the projection 00212 ** function, it has one arc coming from a layer different from x. 00213 */ 00214 if (table->subtables[x].keys == 1) { 00215 return(0); 00216 } 00217 yindex = table->invperm[y]; 00218 if (table->subtables[y].keys == 1) { 00219 if (table->vars[yindex]->ref == 1) 00220 return(0); 00221 } 00222 00223 xsymmy = xsymmyp = 1; 00224 arccount = 0; 00225 slots = table->subtables[x].slots; 00226 list = table->subtables[x].nodelist; 00227 for (i = 0; i < slots; i++) { 00228 f = list[i]; 00229 while (f != sentinel) { 00230 /* Find f1, f0, f11, f10, f01, f00. */ 00231 f1 = cuddT(f); 00232 f0 = Cudd_Regular(cuddE(f)); 00233 comple = Cudd_IsComplement(cuddE(f)); 00234 if ((int) f1->index == yindex) { 00235 arccount++; 00236 f11 = cuddT(f1); f10 = cuddE(f1); 00237 } else { 00238 if ((int) f0->index != yindex) { 00239 /* If f is an isolated projection function it is 00240 ** allowed to bypass layer y. 00241 */ 00242 if (f1 != DD_ONE(table) || f0 != DD_ONE(table) || f->ref != 1) 00243 return(0); /* f bypasses layer y */ 00244 } 00245 f11 = f10 = f1; 00246 } 00247 if ((int) f0->index == yindex) { 00248 arccount++; 00249 f01 = cuddT(f0); f00 = cuddE(f0); 00250 } else { 00251 f01 = f00 = f0; 00252 } 00253 if (comple) { 00254 f01 = Cudd_Not(f01); 00255 f00 = Cudd_Not(f00); 00256 } 00257 00258 if (f1 != DD_ONE(table) || f0 != DD_ONE(table) || f->ref != 1) { 00259 xsymmy &= f01 == f10; 00260 xsymmyp &= f11 == f00; 00261 if ((xsymmy == 0) && (xsymmyp == 0)) 00262 return(0); 00263 } 00264 00265 f = f->next; 00266 } /* while */ 00267 } /* for */ 00268 00269 /* Calculate the total reference counts of y */ 00270 TotalRefCount = -1; /* -1 for projection function */ 00271 slots = table->subtables[y].slots; 00272 list = table->subtables[y].nodelist; 00273 for (i = 0; i < slots; i++) { 00274 f = list[i]; 00275 while (f != sentinel) { 00276 TotalRefCount += f->ref; 00277 f = f->next; 00278 } 00279 } 00280 00281 #if defined(DD_DEBUG) && defined(DD_VERBOSE) 00282 if (arccount == TotalRefCount) { 00283 xindex = table->invperm[x]; 00284 (void) fprintf(table->out, 00285 "Found symmetry! x =%d\ty = %d\tPos(%d,%d)\n", 00286 xindex,yindex,x,y); 00287 } 00288 #endif 00289 00290 return(arccount == TotalRefCount); 00291 00292 } /* end of cuddSymmCheck */
int cuddSymmSifting | ( | DdManager * | table, | |
int | lower, | |||
int | upper | |||
) |
Function********************************************************************
Synopsis [Symmetric sifting algorithm.]
Description [Symmetric sifting algorithm. Assumes that no dead nodes are present.
Returns 1 plus the number of symmetric variables if successful; 0 otherwise.]
SideEffects [None]
SeeAlso [cuddSymmSiftingConv]
Definition at line 318 of file cuddSymmetry.c.
00322 { 00323 int i; 00324 int *var; 00325 int size; 00326 int x; 00327 int result; 00328 int symvars; 00329 int symgroups; 00330 #ifdef DD_STATS 00331 int previousSize; 00332 #endif 00333 00334 size = table->size; 00335 00336 /* Find order in which to sift variables. */ 00337 var = NULL; 00338 entry = ALLOC(int,size); 00339 if (entry == NULL) { 00340 table->errorCode = CUDD_MEMORY_OUT; 00341 goto ddSymmSiftingOutOfMem; 00342 } 00343 var = ALLOC(int,size); 00344 if (var == NULL) { 00345 table->errorCode = CUDD_MEMORY_OUT; 00346 goto ddSymmSiftingOutOfMem; 00347 } 00348 00349 for (i = 0; i < size; i++) { 00350 x = table->perm[i]; 00351 entry[i] = table->subtables[x].keys; 00352 var[i] = i; 00353 } 00354 00355 qsort((void *)var,size,sizeof(int),(DD_QSFP)ddSymmUniqueCompare); 00356 00357 /* Initialize the symmetry of each subtable to itself. */ 00358 for (i = lower; i <= upper; i++) { 00359 table->subtables[i].next = i; 00360 } 00361 00362 for (i = 0; i < ddMin(table->siftMaxVar,size); i++) { 00363 if (ddTotalNumberSwapping >= table->siftMaxSwap) 00364 break; 00365 x = table->perm[var[i]]; 00366 #ifdef DD_STATS 00367 previousSize = table->keys - table->isolated; 00368 #endif 00369 if (x < lower || x > upper) continue; 00370 if (table->subtables[x].next == (unsigned) x) { 00371 result = ddSymmSiftingAux(table,x,lower,upper); 00372 if (!result) goto ddSymmSiftingOutOfMem; 00373 #ifdef DD_STATS 00374 if (table->keys < (unsigned) previousSize + table->isolated) { 00375 (void) fprintf(table->out,"-"); 00376 } else if (table->keys > (unsigned) previousSize + 00377 table->isolated) { 00378 (void) fprintf(table->out,"+"); /* should never happen */ 00379 } else { 00380 (void) fprintf(table->out,"="); 00381 } 00382 fflush(table->out); 00383 #endif 00384 } 00385 } 00386 00387 FREE(var); 00388 FREE(entry); 00389 00390 ddSymmSummary(table, lower, upper, &symvars, &symgroups); 00391 00392 #ifdef DD_STATS 00393 (void) fprintf(table->out, "\n#:S_SIFTING %8d: symmetric variables\n", 00394 symvars); 00395 (void) fprintf(table->out, "#:G_SIFTING %8d: symmetric groups", 00396 symgroups); 00397 #endif 00398 00399 return(1+symvars); 00400 00401 ddSymmSiftingOutOfMem: 00402 00403 if (entry != NULL) FREE(entry); 00404 if (var != NULL) FREE(var); 00405 00406 return(0); 00407 00408 } /* end of cuddSymmSifting */
int cuddSymmSiftingConv | ( | DdManager * | table, | |
int | lower, | |||
int | upper | |||
) |
Function********************************************************************
Synopsis [Symmetric sifting to convergence algorithm.]
Description [Symmetric sifting to convergence algorithm. Assumes that no dead nodes are present.
Returns 1 plus the number of symmetric variables if successful; 0 otherwise.]
SideEffects [None]
SeeAlso [cuddSymmSifting]
Definition at line 435 of file cuddSymmetry.c.
00439 { 00440 int i; 00441 int *var; 00442 int size; 00443 int x; 00444 int result; 00445 int symvars; 00446 int symgroups; 00447 int classes; 00448 int initialSize; 00449 #ifdef DD_STATS 00450 int previousSize; 00451 #endif 00452 00453 initialSize = table->keys - table->isolated; 00454 00455 size = table->size; 00456 00457 /* Find order in which to sift variables. */ 00458 var = NULL; 00459 entry = ALLOC(int,size); 00460 if (entry == NULL) { 00461 table->errorCode = CUDD_MEMORY_OUT; 00462 goto ddSymmSiftingConvOutOfMem; 00463 } 00464 var = ALLOC(int,size); 00465 if (var == NULL) { 00466 table->errorCode = CUDD_MEMORY_OUT; 00467 goto ddSymmSiftingConvOutOfMem; 00468 } 00469 00470 for (i = 0; i < size; i++) { 00471 x = table->perm[i]; 00472 entry[i] = table->subtables[x].keys; 00473 var[i] = i; 00474 } 00475 00476 qsort((void *)var,size,sizeof(int),(DD_QSFP)ddSymmUniqueCompare); 00477 00478 /* Initialize the symmetry of each subtable to itself 00479 ** for first pass of converging symmetric sifting. 00480 */ 00481 for (i = lower; i <= upper; i++) { 00482 table->subtables[i].next = i; 00483 } 00484 00485 for (i = 0; i < ddMin(table->siftMaxVar, table->size); i++) { 00486 if (ddTotalNumberSwapping >= table->siftMaxSwap) 00487 break; 00488 x = table->perm[var[i]]; 00489 if (x < lower || x > upper) continue; 00490 /* Only sift if not in symmetry group already. */ 00491 if (table->subtables[x].next == (unsigned) x) { 00492 #ifdef DD_STATS 00493 previousSize = table->keys - table->isolated; 00494 #endif 00495 result = ddSymmSiftingAux(table,x,lower,upper); 00496 if (!result) goto ddSymmSiftingConvOutOfMem; 00497 #ifdef DD_STATS 00498 if (table->keys < (unsigned) previousSize + table->isolated) { 00499 (void) fprintf(table->out,"-"); 00500 } else if (table->keys > (unsigned) previousSize + 00501 table->isolated) { 00502 (void) fprintf(table->out,"+"); 00503 } else { 00504 (void) fprintf(table->out,"="); 00505 } 00506 fflush(table->out); 00507 #endif 00508 } 00509 } 00510 00511 /* Sifting now until convergence. */ 00512 while ((unsigned) initialSize > table->keys - table->isolated) { 00513 initialSize = table->keys - table->isolated; 00514 #ifdef DD_STATS 00515 (void) fprintf(table->out,"\n"); 00516 #endif 00517 /* Here we consider only one representative for each symmetry class. */ 00518 for (x = lower, classes = 0; x <= upper; x++, classes++) { 00519 while ((unsigned) x < table->subtables[x].next) { 00520 x = table->subtables[x].next; 00521 } 00522 /* Here x is the largest index in a group. 00523 ** Groups consist of adjacent variables. 00524 ** Hence, the next increment of x will move it to a new group. 00525 */ 00526 i = table->invperm[x]; 00527 entry[i] = table->subtables[x].keys; 00528 var[classes] = i; 00529 } 00530 00531 qsort((void *)var,classes,sizeof(int),(DD_QSFP)ddSymmUniqueCompare); 00532 00533 /* Now sift. */ 00534 for (i = 0; i < ddMin(table->siftMaxVar,classes); i++) { 00535 if (ddTotalNumberSwapping >= table->siftMaxSwap) 00536 break; 00537 x = table->perm[var[i]]; 00538 if ((unsigned) x >= table->subtables[x].next) { 00539 #ifdef DD_STATS 00540 previousSize = table->keys - table->isolated; 00541 #endif 00542 result = ddSymmSiftingConvAux(table,x,lower,upper); 00543 if (!result ) goto ddSymmSiftingConvOutOfMem; 00544 #ifdef DD_STATS 00545 if (table->keys < (unsigned) previousSize + table->isolated) { 00546 (void) fprintf(table->out,"-"); 00547 } else if (table->keys > (unsigned) previousSize + 00548 table->isolated) { 00549 (void) fprintf(table->out,"+"); 00550 } else { 00551 (void) fprintf(table->out,"="); 00552 } 00553 fflush(table->out); 00554 #endif 00555 } 00556 } /* for */ 00557 } 00558 00559 ddSymmSummary(table, lower, upper, &symvars, &symgroups); 00560 00561 #ifdef DD_STATS 00562 (void) fprintf(table->out, "\n#:S_SIFTING %8d: symmetric variables\n", 00563 symvars); 00564 (void) fprintf(table->out, "#:G_SIFTING %8d: symmetric groups", 00565 symgroups); 00566 #endif 00567 00568 FREE(var); 00569 FREE(entry); 00570 00571 return(1+symvars); 00572 00573 ddSymmSiftingConvOutOfMem: 00574 00575 if (entry != NULL) FREE(entry); 00576 if (var != NULL) FREE(var); 00577 00578 return(0); 00579 00580 } /* end of cuddSymmSiftingConv */
int cuddTestInteract | ( | DdManager * | table, | |
int | x, | |||
int | y | |||
) |
Function********************************************************************
Synopsis [Test interaction matrix entries.]
Description [Given a pair of variables 0 <= x < y < table->size, tests whether the corresponding bit of the interaction matrix is 1. Returns the value of the bit.]
SideEffects [None]
SeeAlso []
Definition at line 187 of file cuddInteract.c.
00191 { 00192 int posn, word, bit, result; 00193 00194 if (x > y) { 00195 int tmp = x; 00196 x = y; 00197 y = tmp; 00198 } 00199 #ifdef DD_DEBUG 00200 assert(x < y); 00201 assert(y < table->size); 00202 assert(x >= 0); 00203 #endif 00204 00205 posn = ((((table->size << 1) - x - 3) * x) >> 1) + y - 1; 00206 word = posn >> LOGBPL; 00207 bit = posn & (BPL-1); 00208 result = (table->interact[word] >> bit) & 1L; 00209 return(result); 00210 00211 } /* end of cuddTestInteract */
Function********************************************************************
Synopsis [Counts how many times a node is in the death row.]
Description []
SideEffects [None]
SeeAlso [Cudd_DelayedDerefBdd cuddClearDeathRow cuddIsInDeathRow]
Definition at line 789 of file cuddRef.c.
00792 { 00793 int count = 0; 00794 #ifndef DD_NO_DEATH_ROW 00795 int i; 00796 00797 for (i = 0; i < dd->deathRowDepth; i++) { 00798 count += f == dd->deathRow[i]; 00799 } 00800 #endif 00801 00802 return(count); 00803 00804 } /* end of cuddTimesInDeathRow */
int cuddTreeSifting | ( | DdManager * | table, | |
Cudd_ReorderingType | method | |||
) |
Function********************************************************************
Synopsis [Tree sifting algorithm.]
Description [Tree sifting algorithm. Assumes that a tree representing a group hierarchy is passed as a parameter. It then reorders each group in postorder fashion by calling ddTreeSiftingAux. Assumes that no dead nodes are present. Returns 1 if successful; 0 otherwise.]
SideEffects [None]
Definition at line 270 of file cuddGroup.c.
00273 { 00274 int i; 00275 int nvars; 00276 int result; 00277 int tempTree; 00278 00279 /* If no tree is provided we create a temporary one in which all 00280 ** variables are in a single group. After reordering this tree is 00281 ** destroyed. 00282 */ 00283 tempTree = table->tree == NULL; 00284 if (tempTree) { 00285 table->tree = Mtr_InitGroupTree(0,table->size); 00286 table->tree->index = table->invperm[0]; 00287 } 00288 nvars = table->size; 00289 00290 #ifdef DD_DEBUG 00291 if (pr > 0 && !tempTree) (void) fprintf(table->out,"cuddTreeSifting:"); 00292 Mtr_PrintGroups(table->tree,pr <= 0); 00293 #endif 00294 00295 #ifdef DD_STATS 00296 extsymmcalls = 0; 00297 extsymm = 0; 00298 secdiffcalls = 0; 00299 secdiff = 0; 00300 secdiffmisfire = 0; 00301 00302 (void) fprintf(table->out,"\n"); 00303 if (!tempTree) 00304 (void) fprintf(table->out,"#:IM_NODES %8d: group tree nodes\n", 00305 ddCountInternalMtrNodes(table,table->tree)); 00306 #endif 00307 00308 /* Initialize the group of each subtable to itself. Initially 00309 ** there are no groups. Groups are created according to the tree 00310 ** structure in postorder fashion. 00311 */ 00312 for (i = 0; i < nvars; i++) 00313 table->subtables[i].next = i; 00314 00315 00316 /* Reorder. */ 00317 result = ddTreeSiftingAux(table, table->tree, method); 00318 00319 #ifdef DD_STATS /* print stats */ 00320 if (!tempTree && method == CUDD_REORDER_GROUP_SIFT && 00321 (table->groupcheck == CUDD_GROUP_CHECK7 || 00322 table->groupcheck == CUDD_GROUP_CHECK5)) { 00323 (void) fprintf(table->out,"\nextsymmcalls = %d\n",extsymmcalls); 00324 (void) fprintf(table->out,"extsymm = %d",extsymm); 00325 } 00326 if (!tempTree && method == CUDD_REORDER_GROUP_SIFT && 00327 table->groupcheck == CUDD_GROUP_CHECK7) { 00328 (void) fprintf(table->out,"\nsecdiffcalls = %d\n",secdiffcalls); 00329 (void) fprintf(table->out,"secdiff = %d\n",secdiff); 00330 (void) fprintf(table->out,"secdiffmisfire = %d",secdiffmisfire); 00331 } 00332 #endif 00333 00334 if (tempTree) 00335 Cudd_FreeTree(table); 00336 return(result); 00337 00338 } /* end of cuddTreeSifting */
DdNode* cuddUnderApprox | ( | DdManager * | dd, | |
DdNode * | f, | |||
int | numVars, | |||
int | threshold, | |||
int | safe, | |||
double | quality | |||
) |
Function********************************************************************
Synopsis [Applies Tom Shiple's underappoximation algorithm.]
Description [Applies Tom Shiple's underappoximation algorithm. Proceeds in three phases:
Returns the approximated BDD if successful; NULL otherwise.]
SideEffects [None]
SeeAlso [Cudd_UnderApprox]
Definition at line 507 of file cuddApprox.c.
00514 { 00515 ApproxInfo *info; 00516 DdNode *subset; 00517 int result; 00518 00519 if (f == NULL) { 00520 fprintf(dd->err, "Cannot subset, nil object\n"); 00521 return(NULL); 00522 } 00523 00524 if (Cudd_IsConstant(f)) { 00525 return(f); 00526 } 00527 00528 /* Create table where node data are accessible via a hash table. */ 00529 info = gatherInfo(dd, f, numVars, safe); 00530 if (info == NULL) { 00531 (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); 00532 dd->errorCode = CUDD_MEMORY_OUT; 00533 return(NULL); 00534 } 00535 00536 /* Mark nodes that should be replaced by zero. */ 00537 result = UAmarkNodes(dd, f, info, threshold, safe, quality); 00538 if (result == 0) { 00539 (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); 00540 FREE(info->page); 00541 st_free_table(info->table); 00542 FREE(info); 00543 dd->errorCode = CUDD_MEMORY_OUT; 00544 return(NULL); 00545 } 00546 00547 /* Build the result. */ 00548 subset = UAbuildSubset(dd, f, info); 00549 #if 1 00550 if (subset && info->size < Cudd_DagSize(subset)) 00551 (void) fprintf(dd->err, "Wrong prediction: %d versus actual %d\n", 00552 info->size, Cudd_DagSize(subset)); 00553 #endif 00554 FREE(info->page); 00555 st_free_table(info->table); 00556 FREE(info); 00557 00558 #ifdef DD_DEBUG 00559 if (subset != NULL) { 00560 cuddRef(subset); 00561 #if 0 00562 (void) Cudd_DebugCheck(dd); 00563 (void) Cudd_CheckKeys(dd); 00564 #endif 00565 if (!Cudd_bddLeq(dd, subset, f)) { 00566 (void) fprintf(dd->err, "Wrong subset\n"); 00567 dd->errorCode = CUDD_INTERNAL_ERROR; 00568 } 00569 cuddDeref(subset); 00570 } 00571 #endif 00572 return(subset); 00573 00574 } /* end of cuddUnderApprox */
Function********************************************************************
Synopsis [Checks the unique table for the existence of a constant node.]
Description [Checks the unique table for the existence of a constant node. If it does not exist, it creates a new one. Does not modify the reference count of whatever is returned. A newly created internal node comes back with a reference count 0. Returns a pointer to the new node.]
SideEffects [None]
Definition at line 1435 of file cuddTable.c.
01438 { 01439 int pos; 01440 DdNodePtr *nodelist; 01441 DdNode *looking; 01442 hack split; 01443 01444 #ifdef DD_UNIQUE_PROFILE 01445 unique->uniqueLookUps++; 01446 #endif 01447 01448 if (unique->constants.keys > unique->constants.maxKeys) { 01449 if (unique->gcEnabled && ((unique->dead > unique->minDead) || 01450 (10 * unique->constants.dead > 9 * unique->constants.keys))) { /* too many dead */ 01451 (void) cuddGarbageCollect(unique,1); 01452 } else { 01453 cuddRehash(unique,CUDD_CONST_INDEX); 01454 } 01455 } 01456 01457 cuddAdjust(value); /* for the case of crippled infinities */ 01458 01459 if (ddAbs(value) < unique->epsilon) { 01460 value = 0.0; 01461 } 01462 split.value = value; 01463 01464 pos = ddHash(split.bits[0], split.bits[1], unique->constants.shift); 01465 nodelist = unique->constants.nodelist; 01466 looking = nodelist[pos]; 01467 01468 /* Here we compare values both for equality and for difference less 01469 * than epsilon. The first comparison is required when values are 01470 * infinite, since Infinity - Infinity is NaN and NaN < X is 0 for 01471 * every X. 01472 */ 01473 while (looking != NULL) { 01474 if (looking->type.value == value || 01475 ddEqualVal(looking->type.value,value,unique->epsilon)) { 01476 if (looking->ref == 0) { 01477 cuddReclaim(unique,looking); 01478 } 01479 return(looking); 01480 } 01481 looking = looking->next; 01482 #ifdef DD_UNIQUE_PROFILE 01483 unique->uniqueLinks++; 01484 #endif 01485 } 01486 01487 unique->keys++; 01488 unique->constants.keys++; 01489 01490 looking = cuddAllocNode(unique); 01491 if (looking == NULL) return(NULL); 01492 looking->index = CUDD_CONST_INDEX; 01493 looking->type.value = value; 01494 looking->next = nodelist[pos]; 01495 nodelist[pos] = looking; 01496 01497 return(looking); 01498 01499 } /* end of cuddUniqueConst */
Function********************************************************************
Synopsis [Checks the unique table for the existence of an internal node.]
Description [Checks the unique table for the existence of an internal node. If it does not exist, it creates a new one. Does not modify the reference count of whatever is returned. A newly created internal node comes back with a reference count 0. For a newly created node, increments the reference counts of what T and E point to. Returns a pointer to the new node if successful; NULL if memory is exhausted or if reordering took place.]
SideEffects [None]
SeeAlso [cuddUniqueInterZdd]
Definition at line 1115 of file cuddTable.c.
01120 { 01121 int pos; 01122 unsigned int level; 01123 int retval; 01124 DdNodePtr *nodelist; 01125 DdNode *looking; 01126 DdNodePtr *previousP; 01127 DdSubtable *subtable; 01128 int gcNumber; 01129 01130 #ifdef DD_UNIQUE_PROFILE 01131 unique->uniqueLookUps++; 01132 #endif 01133 01134 if (index >= unique->size) { 01135 if (!ddResizeTable(unique,index)) return(NULL); 01136 } 01137 01138 level = unique->perm[index]; 01139 subtable = &(unique->subtables[level]); 01140 01141 #ifdef DD_DEBUG 01142 assert(level < (unsigned) cuddI(unique,T->index)); 01143 assert(level < (unsigned) cuddI(unique,Cudd_Regular(E)->index)); 01144 #endif 01145 01146 pos = ddHash(T, E, subtable->shift); 01147 nodelist = subtable->nodelist; 01148 previousP = &(nodelist[pos]); 01149 looking = *previousP; 01150 01151 while (T < cuddT(looking)) { 01152 previousP = &(looking->next); 01153 looking = *previousP; 01154 #ifdef DD_UNIQUE_PROFILE 01155 unique->uniqueLinks++; 01156 #endif 01157 } 01158 while (T == cuddT(looking) && E < cuddE(looking)) { 01159 previousP = &(looking->next); 01160 looking = *previousP; 01161 #ifdef DD_UNIQUE_PROFILE 01162 unique->uniqueLinks++; 01163 #endif 01164 } 01165 if (T == cuddT(looking) && E == cuddE(looking)) { 01166 if (looking->ref == 0) { 01167 cuddReclaim(unique,looking); 01168 } 01169 return(looking); 01170 } 01171 01172 /* countDead is 0 if deads should be counted and ~0 if they should not. */ 01173 if (unique->autoDyn && 01174 unique->keys - (unique->dead & unique->countDead) >= unique->nextDyn) { 01175 #ifdef DD_DEBUG 01176 retval = Cudd_DebugCheck(unique); 01177 if (retval != 0) return(NULL); 01178 retval = Cudd_CheckKeys(unique); 01179 if (retval != 0) return(NULL); 01180 #endif 01181 retval = Cudd_ReduceHeap(unique,unique->autoMethod,10); /* 10 = whatever */ 01182 if (retval == 0) unique->reordered = 2; 01183 #ifdef DD_DEBUG 01184 retval = Cudd_DebugCheck(unique); 01185 if (retval != 0) unique->reordered = 2; 01186 retval = Cudd_CheckKeys(unique); 01187 if (retval != 0) unique->reordered = 2; 01188 #endif 01189 return(NULL); 01190 } 01191 01192 if (subtable->keys > subtable->maxKeys) { 01193 if (unique->gcEnabled && 01194 ((unique->dead > unique->minDead) || 01195 ((unique->dead > unique->minDead / 2) && 01196 (subtable->dead > subtable->keys * 0.95)))) { /* too many dead */ 01197 (void) cuddGarbageCollect(unique,1); 01198 } else { 01199 cuddRehash(unique,(int)level); 01200 } 01201 /* Update pointer to insertion point. In the case of rehashing, 01202 ** the slot may have changed. In the case of garbage collection, 01203 ** the predecessor may have been dead. */ 01204 pos = ddHash(T, E, subtable->shift); 01205 nodelist = subtable->nodelist; 01206 previousP = &(nodelist[pos]); 01207 looking = *previousP; 01208 01209 while (T < cuddT(looking)) { 01210 previousP = &(looking->next); 01211 looking = *previousP; 01212 #ifdef DD_UNIQUE_PROFILE 01213 unique->uniqueLinks++; 01214 #endif 01215 } 01216 while (T == cuddT(looking) && E < cuddE(looking)) { 01217 previousP = &(looking->next); 01218 looking = *previousP; 01219 #ifdef DD_UNIQUE_PROFILE 01220 unique->uniqueLinks++; 01221 #endif 01222 } 01223 } 01224 01225 gcNumber = unique->garbageCollections; 01226 looking = cuddAllocNode(unique); 01227 if (looking == NULL) { 01228 return(NULL); 01229 } 01230 unique->keys++; 01231 subtable->keys++; 01232 01233 if (gcNumber != unique->garbageCollections) { 01234 DdNode *looking2; 01235 pos = ddHash(T, E, subtable->shift); 01236 nodelist = subtable->nodelist; 01237 previousP = &(nodelist[pos]); 01238 looking2 = *previousP; 01239 01240 while (T < cuddT(looking2)) { 01241 previousP = &(looking2->next); 01242 looking2 = *previousP; 01243 #ifdef DD_UNIQUE_PROFILE 01244 unique->uniqueLinks++; 01245 #endif 01246 } 01247 while (T == cuddT(looking2) && E < cuddE(looking2)) { 01248 previousP = &(looking2->next); 01249 looking2 = *previousP; 01250 #ifdef DD_UNIQUE_PROFILE 01251 unique->uniqueLinks++; 01252 #endif 01253 } 01254 } 01255 looking->index = index; 01256 cuddT(looking) = T; 01257 cuddE(looking) = E; 01258 looking->next = *previousP; 01259 *previousP = looking; 01260 cuddSatInc(T->ref); /* we know T is a regular pointer */ 01261 cuddRef(E); 01262 01263 #ifdef DD_DEBUG 01264 cuddCheckCollisionOrdering(unique,level,pos); 01265 #endif 01266 01267 return(looking); 01268 01269 } /* end of cuddUniqueInter */
Function********************************************************************
Synopsis [Wrapper for cuddUniqueInter that is independent of variable ordering.]
Description [Wrapper for cuddUniqueInter that is independent of variable ordering (IVO). This function does not require parameter index to precede the indices of the top nodes of T and E in the variable order. Returns a pointer to the result node under normal conditions; NULL if reordering occurred or memory was exhausted.]
SideEffects [None]
SeeAlso [cuddUniqueInter Cudd_MakeBddFromZddCover]
Definition at line 1289 of file cuddTable.c.
01294 { 01295 DdNode *result; 01296 DdNode *v; 01297 01298 v = cuddUniqueInter(unique, index, DD_ONE(unique), 01299 Cudd_Not(DD_ONE(unique))); 01300 if (v == NULL) 01301 return(NULL); 01302 cuddRef(v); 01303 result = cuddBddIteRecur(unique, v, T, E); 01304 Cudd_RecursiveDeref(unique, v); 01305 return(result); 01306 }
Function********************************************************************
Synopsis [Checks the unique table for the existence of an internal ZDD node.]
Description [Checks the unique table for the existence of an internal ZDD node. If it does not exist, it creates a new one. Does not modify the reference count of whatever is returned. A newly created internal node comes back with a reference count 0. For a newly created node, increments the reference counts of what T and E point to. Returns a pointer to the new node if successful; NULL if memory is exhausted or if reordering took place.]
SideEffects [None]
SeeAlso [cuddUniqueInter]
Definition at line 1328 of file cuddTable.c.
01333 { 01334 int pos; 01335 unsigned int level; 01336 int retval; 01337 DdNodePtr *nodelist; 01338 DdNode *looking; 01339 DdSubtable *subtable; 01340 01341 #ifdef DD_UNIQUE_PROFILE 01342 unique->uniqueLookUps++; 01343 #endif 01344 01345 if (index >= unique->sizeZ) { 01346 if (!cuddResizeTableZdd(unique,index)) return(NULL); 01347 } 01348 01349 level = unique->permZ[index]; 01350 subtable = &(unique->subtableZ[level]); 01351 01352 #ifdef DD_DEBUG 01353 assert(level < (unsigned) cuddIZ(unique,T->index)); 01354 assert(level < (unsigned) cuddIZ(unique,Cudd_Regular(E)->index)); 01355 #endif 01356 01357 if (subtable->keys > subtable->maxKeys) { 01358 if (unique->gcEnabled && ((unique->deadZ > unique->minDead) || 01359 (10 * subtable->dead > 9 * subtable->keys))) { /* too many dead */ 01360 (void) cuddGarbageCollect(unique,1); 01361 } else { 01362 ddRehashZdd(unique,(int)level); 01363 } 01364 } 01365 01366 pos = ddHash(T, E, subtable->shift); 01367 nodelist = subtable->nodelist; 01368 looking = nodelist[pos]; 01369 01370 while (looking != NULL) { 01371 if (cuddT(looking) == T && cuddE(looking) == E) { 01372 if (looking->ref == 0) { 01373 cuddReclaimZdd(unique,looking); 01374 } 01375 return(looking); 01376 } 01377 looking = looking->next; 01378 #ifdef DD_UNIQUE_PROFILE 01379 unique->uniqueLinks++; 01380 #endif 01381 } 01382 01383 /* countDead is 0 if deads should be counted and ~0 if they should not. */ 01384 if (unique->autoDynZ && 01385 unique->keysZ - (unique->deadZ & unique->countDead) >= unique->nextDyn) { 01386 #ifdef DD_DEBUG 01387 retval = Cudd_DebugCheck(unique); 01388 if (retval != 0) return(NULL); 01389 retval = Cudd_CheckKeys(unique); 01390 if (retval != 0) return(NULL); 01391 #endif 01392 retval = Cudd_zddReduceHeap(unique,unique->autoMethodZ,10); /* 10 = whatever */ 01393 if (retval == 0) unique->reordered = 2; 01394 #ifdef DD_DEBUG 01395 retval = Cudd_DebugCheck(unique); 01396 if (retval != 0) unique->reordered = 2; 01397 retval = Cudd_CheckKeys(unique); 01398 if (retval != 0) unique->reordered = 2; 01399 #endif 01400 return(NULL); 01401 } 01402 01403 unique->keysZ++; 01404 subtable->keys++; 01405 01406 looking = cuddAllocNode(unique); 01407 if (looking == NULL) return(NULL); 01408 looking->index = index; 01409 cuddT(looking) = T; 01410 cuddE(looking) = E; 01411 looking->next = nodelist[pos]; 01412 nodelist[pos] = looking; 01413 cuddRef(T); 01414 cuddRef(E); 01415 01416 return(looking); 01417 01418 } /* end of cuddUniqueInterZdd */
void cuddUpdateInteractionMatrix | ( | DdManager * | table, | |
int | xindex, | |||
int | yindex | |||
) |
Function********************************************************************
Synopsis [Updates the interaction matrix.]
Description []
SideEffects [none]
SeeAlso []
Definition at line 714 of file cuddLinear.c.
00718 { 00719 int i; 00720 for (i = 0; i < yindex; i++) { 00721 if (i != xindex && cuddTestInteract(table,i,yindex)) { 00722 if (i < xindex) { 00723 cuddSetInteract(table,i,xindex); 00724 } else { 00725 cuddSetInteract(table,xindex,i); 00726 } 00727 } 00728 } 00729 for (i = yindex+1; i < table->size; i++) { 00730 if (i != xindex && cuddTestInteract(table,yindex,i)) { 00731 if (i < xindex) { 00732 cuddSetInteract(table,i,xindex); 00733 } else { 00734 cuddSetInteract(table,xindex,i); 00735 } 00736 } 00737 } 00738 00739 } /* end of cuddUpdateInteractionMatrix */
Function********************************************************************
Synopsis [Implements the recursive step of Cudd_VerifySol. ]
Description []
SideEffects [none]
SeeAlso [Cudd_VerifySol]
Definition at line 332 of file cuddSolve.c.
00338 { 00339 DdNode *w, *R; 00340 00341 int j; 00342 00343 R = F; 00344 cuddRef(R); 00345 for(j = n - 1; j >= 0; j--) { 00346 w = Cudd_bddCompose(bdd, R, G[j], yIndex[j]); 00347 if (w) { 00348 cuddRef(w); 00349 } else { 00350 return(NULL); 00351 } 00352 Cudd_RecursiveDeref(bdd,R); 00353 R = w; 00354 } 00355 00356 cuddDeref(R); 00357 00358 return(R); 00359 00360 } /* end of cuddVerifySol */
int cuddWindowReorder | ( | DdManager * | table, | |
int | low, | |||
int | high, | |||
Cudd_ReorderingType | submethod | |||
) |
AutomaticEnd Function********************************************************************
Synopsis [Reorders by applying the method of the sliding window.]
Description [Reorders by applying the method of the sliding window. Tries all possible permutations to the variables in a window that slides from low to high. The size of the window is determined by submethod. Assumes that no dead nodes are present. Returns 1 in case of success; 0 otherwise.]
SideEffects [None]
Definition at line 138 of file cuddWindow.c.
00143 { 00144 00145 int res; 00146 #ifdef DD_DEBUG 00147 int supposedOpt; 00148 #endif 00149 00150 switch (submethod) { 00151 case CUDD_REORDER_WINDOW2: 00152 res = ddWindow2(table,low,high); 00153 break; 00154 case CUDD_REORDER_WINDOW3: 00155 res = ddWindow3(table,low,high); 00156 break; 00157 case CUDD_REORDER_WINDOW4: 00158 res = ddWindow4(table,low,high); 00159 break; 00160 case CUDD_REORDER_WINDOW2_CONV: 00161 res = ddWindowConv2(table,low,high); 00162 break; 00163 case CUDD_REORDER_WINDOW3_CONV: 00164 res = ddWindowConv3(table,low,high); 00165 #ifdef DD_DEBUG 00166 supposedOpt = table->keys - table->isolated; 00167 res = ddWindow3(table,low,high); 00168 if (table->keys - table->isolated != (unsigned) supposedOpt) { 00169 (void) fprintf(table->err, "Convergence failed! (%d != %d)\n", 00170 table->keys - table->isolated, supposedOpt); 00171 } 00172 #endif 00173 break; 00174 case CUDD_REORDER_WINDOW4_CONV: 00175 res = ddWindowConv4(table,low,high); 00176 #ifdef DD_DEBUG 00177 supposedOpt = table->keys - table->isolated; 00178 res = ddWindow4(table,low,high); 00179 if (table->keys - table->isolated != (unsigned) supposedOpt) { 00180 (void) fprintf(table->err,"Convergence failed! (%d != %d)\n", 00181 table->keys - table->isolated, supposedOpt); 00182 } 00183 #endif 00184 break; 00185 default: return(0); 00186 } 00187 00188 return(res); 00189 00190 } /* end of cuddWindowReorder */
int cuddZddAlignToBdd | ( | DdManager * | table | ) |
Function********************************************************************
Synopsis [Reorders ZDD variables according to the order of the BDD variables.]
Description [Reorders ZDD variables according to the order of the BDD variables. This function can be called at the end of BDD reordering to insure that the order of the ZDD variables is consistent with the order of the BDD variables. The number of ZDD variables must be a multiple of the number of BDD variables. Let M
be the ratio of the two numbers. cuddZddAlignToBdd then considers the ZDD variables from M*i
to (M+1)*i-1
as corresponding to BDD variable i
. This function should be normally called from Cudd_ReduceHeap, which clears the cache. Returns 1 in case of success; 0 otherwise.]
SideEffects [Changes the ZDD variable order for all diagrams and performs garbage collection of the ZDD unique table.]
SeeAlso [Cudd_zddShuffleHeap Cudd_ReduceHeap]
Definition at line 348 of file cuddZddReord.c.
00350 { 00351 int *invpermZ; /* permutation array */ 00352 int M; /* ratio of ZDD variables to BDD variables */ 00353 int i,j; /* loop indices */ 00354 int result; /* return value */ 00355 00356 /* We assume that a ratio of 0 is OK. */ 00357 if (table->sizeZ == 0) 00358 return(1); 00359 00360 empty = table->zero; 00361 M = table->sizeZ / table->size; 00362 /* Check whether the number of ZDD variables is a multiple of the 00363 ** number of BDD variables. 00364 */ 00365 if (M * table->size != table->sizeZ) 00366 return(0); 00367 /* Create and initialize the inverse permutation array. */ 00368 invpermZ = ALLOC(int,table->sizeZ); 00369 if (invpermZ == NULL) { 00370 table->errorCode = CUDD_MEMORY_OUT; 00371 return(0); 00372 } 00373 for (i = 0; i < table->size; i++) { 00374 int index = table->invperm[i]; 00375 int indexZ = index * M; 00376 int levelZ = table->permZ[indexZ]; 00377 levelZ = (levelZ / M) * M; 00378 for (j = 0; j < M; j++) { 00379 invpermZ[M * i + j] = table->invpermZ[levelZ + j]; 00380 } 00381 } 00382 /* Eliminate dead nodes. Do not scan the cache again, because we 00383 ** assume that Cudd_ReduceHeap has already cleared it. 00384 */ 00385 cuddGarbageCollect(table,0); 00386 00387 result = zddShuffle(table, invpermZ); 00388 FREE(invpermZ); 00389 /* Fix the ZDD variable group tree. */ 00390 zddFixTree(table,table->treeZ); 00391 return(result); 00392 00393 } /* end of cuddZddAlignToBdd */
Function********************************************************************
Synopsis [Substitutes a variable with its complement in a ZDD.]
Description [Substitutes a variable with its complement in a ZDD. returns a pointer to the result if successful; NULL otherwise. cuddZddChange performs the same function as Cudd_zddChange, but does not restart if reordering has taken place. Therefore it can be called from within a recursive procedure.]
SideEffects [None]
SeeAlso [Cudd_zddChange]
Definition at line 967 of file cuddZddSetop.c.
00971 { 00972 DdNode *zvar, *res; 00973 00974 zvar = cuddUniqueInterZdd(dd, var, DD_ONE(dd), DD_ZERO(dd)); 00975 if (zvar == NULL) return(NULL); 00976 cuddRef(zvar); 00977 00978 res = cuddZddChangeAux(dd, P, zvar); 00979 if (res == NULL) { 00980 Cudd_RecursiveDerefZdd(dd,zvar); 00981 return(NULL); 00982 } 00983 cuddRef(res); 00984 Cudd_RecursiveDerefZdd(dd,zvar); 00985 cuddDeref(res); 00986 return(res); 00987 00988 } /* end of cuddZddChange */
Function********************************************************************
Synopsis [Performs the recursive step of Cudd_zddChange.]
Description []
SideEffects [None]
SeeAlso []
Definition at line 795 of file cuddZddSetop.c.
00799 { 00800 int top_var, level; 00801 DdNode *res, *t, *e; 00802 DdNode *base = DD_ONE(zdd); 00803 DdNode *empty = DD_ZERO(zdd); 00804 00805 statLine(zdd); 00806 if (P == empty) 00807 return(empty); 00808 if (P == base) 00809 return(zvar); 00810 00811 /* Check cache. */ 00812 res = cuddCacheLookup2Zdd(zdd, cuddZddChangeAux, P, zvar); 00813 if (res != NULL) 00814 return(res); 00815 00816 top_var = zdd->permZ[P->index]; 00817 level = zdd->permZ[zvar->index]; 00818 00819 if (top_var > level) { 00820 res = cuddZddGetNode(zdd, zvar->index, P, DD_ZERO(zdd)); 00821 if (res == NULL) return(NULL); 00822 } else if (top_var == level) { 00823 res = cuddZddGetNode(zdd, zvar->index, cuddE(P), cuddT(P)); 00824 if (res == NULL) return(NULL); 00825 } else { 00826 t = cuddZddChangeAux(zdd, cuddT(P), zvar); 00827 if (t == NULL) return(NULL); 00828 cuddRef(t); 00829 e = cuddZddChangeAux(zdd, cuddE(P), zvar); 00830 if (e == NULL) { 00831 Cudd_RecursiveDerefZdd(zdd, t); 00832 return(NULL); 00833 } 00834 cuddRef(e); 00835 res = cuddZddGetNode(zdd, P->index, t, e); 00836 if (res == NULL) { 00837 Cudd_RecursiveDerefZdd(zdd, t); 00838 Cudd_RecursiveDerefZdd(zdd, e); 00839 return(NULL); 00840 } 00841 cuddDeref(t); 00842 cuddDeref(e); 00843 } 00844 00845 cuddCacheInsert2(zdd, cuddZddChangeAux, P, zvar, res); 00846 00847 return(res); 00848 00849 } /* end of cuddZddChangeAux */
Function********************************************************************
Synopsis [Computes a complement of a ZDD node.]
Description [Computes the complement of a ZDD node. So far, since we couldn't find a direct way to get the complement of a ZDD cover, we first convert a ZDD cover to a BDD, then make the complement of the ZDD cover from the complement of the BDD node by using ISOP.]
SideEffects [The result depends on current variable order.]
SeeAlso []
Definition at line 1518 of file cuddZddFuncs.c.
01521 { 01522 DdNode *b, *isop, *zdd_I; 01523 01524 /* Check cache */ 01525 zdd_I = cuddCacheLookup1Zdd(dd, cuddZddComplement, node); 01526 if (zdd_I) 01527 return(zdd_I); 01528 01529 b = cuddMakeBddFromZddCover(dd, node); 01530 if (!b) 01531 return(NULL); 01532 cuddRef(b); 01533 isop = cuddZddIsop(dd, Cudd_Not(b), Cudd_Not(b), &zdd_I); 01534 if (!isop) { 01535 Cudd_RecursiveDeref(dd, b); 01536 return(NULL); 01537 } 01538 cuddRef(isop); 01539 cuddRef(zdd_I); 01540 Cudd_RecursiveDeref(dd, b); 01541 Cudd_RecursiveDeref(dd, isop); 01542 01543 cuddCacheInsert1(dd, cuddZddComplement, node, zdd_I); 01544 cuddDeref(zdd_I); 01545 return(zdd_I); 01546 } /* end of cuddZddComplement */
Function********************************************************************
Synopsis [Performs the recursive step of Cudd_zddDiff.]
Description []
SideEffects [None]
SeeAlso []
Definition at line 713 of file cuddZddSetop.c.
00717 { 00718 int p_top, q_top; 00719 DdNode *empty = DD_ZERO(zdd), *t, *e, *res; 00720 DdManager *table = zdd; 00721 00722 statLine(zdd); 00723 if (P == empty) 00724 return(empty); 00725 if (Q == empty) 00726 return(P); 00727 if (P == Q) 00728 return(empty); 00729 00730 /* Check cache. The cache is shared by Cudd_zddDiffConst(). */ 00731 res = cuddCacheLookup2Zdd(table, cuddZddDiff, P, Q); 00732 if (res != NULL && res != DD_NON_CONSTANT) 00733 return(res); 00734 00735 if (cuddIsConstant(P)) 00736 p_top = P->index; 00737 else 00738 p_top = zdd->permZ[P->index]; 00739 if (cuddIsConstant(Q)) 00740 q_top = Q->index; 00741 else 00742 q_top = zdd->permZ[Q->index]; 00743 if (p_top < q_top) { 00744 e = cuddZddDiff(zdd, cuddE(P), Q); 00745 if (e == NULL) return(NULL); 00746 cuddRef(e); 00747 res = cuddZddGetNode(zdd, P->index, cuddT(P), e); 00748 if (res == NULL) { 00749 Cudd_RecursiveDerefZdd(table, e); 00750 return(NULL); 00751 } 00752 cuddDeref(e); 00753 } else if (p_top > q_top) { 00754 res = cuddZddDiff(zdd, P, cuddE(Q)); 00755 if (res == NULL) return(NULL); 00756 } else { 00757 t = cuddZddDiff(zdd, cuddT(P), cuddT(Q)); 00758 if (t == NULL) return(NULL); 00759 cuddRef(t); 00760 e = cuddZddDiff(zdd, cuddE(P), cuddE(Q)); 00761 if (e == NULL) { 00762 Cudd_RecursiveDerefZdd(table, t); 00763 return(NULL); 00764 } 00765 cuddRef(e); 00766 res = cuddZddGetNode(zdd, P->index, t, e); 00767 if (res == NULL) { 00768 Cudd_RecursiveDerefZdd(table, t); 00769 Cudd_RecursiveDerefZdd(table, e); 00770 return(NULL); 00771 } 00772 cuddDeref(t); 00773 cuddDeref(e); 00774 } 00775 00776 cuddCacheInsert2(table, cuddZddDiff, P, Q, res); 00777 00778 return(res); 00779 00780 } /* end of cuddZddDiff */
Function********************************************************************
Synopsis [Performs the recursive step of Cudd_zddDivide.]
Description []
SideEffects [None]
SeeAlso [Cudd_zddDivide]
Definition at line 1155 of file cuddZddFuncs.c.
01159 { 01160 int v; 01161 DdNode *one = DD_ONE(dd); 01162 DdNode *zero = DD_ZERO(dd); 01163 DdNode *f0, *f1, *g0, *g1; 01164 DdNode *q, *r, *tmp; 01165 int flag; 01166 01167 statLine(dd); 01168 if (g == one) 01169 return(f); 01170 if (f == zero || f == one) 01171 return(zero); 01172 if (f == g) 01173 return(one); 01174 01175 /* Check cache. */ 01176 r = cuddCacheLookup2Zdd(dd, cuddZddDivide, f, g); 01177 if (r) 01178 return(r); 01179 01180 v = g->index; 01181 01182 flag = cuddZddGetCofactors2(dd, f, v, &f1, &f0); 01183 if (flag == 1) 01184 return(NULL); 01185 Cudd_Ref(f1); 01186 Cudd_Ref(f0); 01187 flag = cuddZddGetCofactors2(dd, g, v, &g1, &g0); /* g1 != zero */ 01188 if (flag == 1) { 01189 Cudd_RecursiveDerefZdd(dd, f1); 01190 Cudd_RecursiveDerefZdd(dd, f0); 01191 return(NULL); 01192 } 01193 Cudd_Ref(g1); 01194 Cudd_Ref(g0); 01195 01196 r = cuddZddDivide(dd, f1, g1); 01197 if (r == NULL) { 01198 Cudd_RecursiveDerefZdd(dd, f1); 01199 Cudd_RecursiveDerefZdd(dd, f0); 01200 Cudd_RecursiveDerefZdd(dd, g1); 01201 Cudd_RecursiveDerefZdd(dd, g0); 01202 return(NULL); 01203 } 01204 Cudd_Ref(r); 01205 01206 if (r != zero && g0 != zero) { 01207 tmp = r; 01208 q = cuddZddDivide(dd, f0, g0); 01209 if (q == NULL) { 01210 Cudd_RecursiveDerefZdd(dd, f1); 01211 Cudd_RecursiveDerefZdd(dd, f0); 01212 Cudd_RecursiveDerefZdd(dd, g1); 01213 Cudd_RecursiveDerefZdd(dd, g0); 01214 return(NULL); 01215 } 01216 Cudd_Ref(q); 01217 r = cuddZddIntersect(dd, r, q); 01218 if (r == NULL) { 01219 Cudd_RecursiveDerefZdd(dd, f1); 01220 Cudd_RecursiveDerefZdd(dd, f0); 01221 Cudd_RecursiveDerefZdd(dd, g1); 01222 Cudd_RecursiveDerefZdd(dd, g0); 01223 Cudd_RecursiveDerefZdd(dd, q); 01224 return(NULL); 01225 } 01226 Cudd_Ref(r); 01227 Cudd_RecursiveDerefZdd(dd, q); 01228 Cudd_RecursiveDerefZdd(dd, tmp); 01229 } 01230 01231 Cudd_RecursiveDerefZdd(dd, f1); 01232 Cudd_RecursiveDerefZdd(dd, f0); 01233 Cudd_RecursiveDerefZdd(dd, g1); 01234 Cudd_RecursiveDerefZdd(dd, g0); 01235 01236 cuddCacheInsert2(dd, cuddZddDivide, f, g, r); 01237 Cudd_Deref(r); 01238 return(r); 01239 01240 } /* end of cuddZddDivide */
Function********************************************************************
Synopsis [Performs the recursive step of Cudd_zddDivideF.]
Description []
SideEffects [None]
SeeAlso [Cudd_zddDivideF]
Definition at line 1255 of file cuddZddFuncs.c.
01259 { 01260 int v; 01261 DdNode *one = DD_ONE(dd); 01262 DdNode *zero = DD_ZERO(dd); 01263 DdNode *f0, *f1, *g0, *g1; 01264 DdNode *q, *r, *tmp; 01265 int flag; 01266 01267 statLine(dd); 01268 if (g == one) 01269 return(f); 01270 if (f == zero || f == one) 01271 return(zero); 01272 if (f == g) 01273 return(one); 01274 01275 /* Check cache. */ 01276 r = cuddCacheLookup2Zdd(dd, cuddZddDivideF, f, g); 01277 if (r) 01278 return(r); 01279 01280 v = g->index; 01281 01282 flag = cuddZddGetCofactors2(dd, f, v, &f1, &f0); 01283 if (flag == 1) 01284 return(NULL); 01285 Cudd_Ref(f1); 01286 Cudd_Ref(f0); 01287 flag = cuddZddGetCofactors2(dd, g, v, &g1, &g0); /* g1 != zero */ 01288 if (flag == 1) { 01289 Cudd_RecursiveDerefZdd(dd, f1); 01290 Cudd_RecursiveDerefZdd(dd, f0); 01291 return(NULL); 01292 } 01293 Cudd_Ref(g1); 01294 Cudd_Ref(g0); 01295 01296 r = cuddZddDivideF(dd, f1, g1); 01297 if (r == NULL) { 01298 Cudd_RecursiveDerefZdd(dd, f1); 01299 Cudd_RecursiveDerefZdd(dd, f0); 01300 Cudd_RecursiveDerefZdd(dd, g1); 01301 Cudd_RecursiveDerefZdd(dd, g0); 01302 return(NULL); 01303 } 01304 Cudd_Ref(r); 01305 01306 if (r != zero && g0 != zero) { 01307 tmp = r; 01308 q = cuddZddDivideF(dd, f0, g0); 01309 if (q == NULL) { 01310 Cudd_RecursiveDerefZdd(dd, f1); 01311 Cudd_RecursiveDerefZdd(dd, f0); 01312 Cudd_RecursiveDerefZdd(dd, g1); 01313 Cudd_RecursiveDerefZdd(dd, g0); 01314 return(NULL); 01315 } 01316 Cudd_Ref(q); 01317 r = cuddZddIntersect(dd, r, q); 01318 if (r == NULL) { 01319 Cudd_RecursiveDerefZdd(dd, f1); 01320 Cudd_RecursiveDerefZdd(dd, f0); 01321 Cudd_RecursiveDerefZdd(dd, g1); 01322 Cudd_RecursiveDerefZdd(dd, g0); 01323 Cudd_RecursiveDerefZdd(dd, q); 01324 return(NULL); 01325 } 01326 Cudd_Ref(r); 01327 Cudd_RecursiveDerefZdd(dd, q); 01328 Cudd_RecursiveDerefZdd(dd, tmp); 01329 } 01330 01331 Cudd_RecursiveDerefZdd(dd, f1); 01332 Cudd_RecursiveDerefZdd(dd, f0); 01333 Cudd_RecursiveDerefZdd(dd, g1); 01334 Cudd_RecursiveDerefZdd(dd, g0); 01335 01336 cuddCacheInsert2(dd, cuddZddDivideF, f, g, r); 01337 Cudd_Deref(r); 01338 return(r); 01339 01340 } /* end of cuddZddDivideF */
void cuddZddFreeUniv | ( | DdManager * | zdd | ) |
Function********************************************************************
Synopsis [Frees the ZDD universe.]
Description [Frees the ZDD universe.]
SideEffects [None]
SeeAlso [cuddZddInitUniv]
Definition at line 294 of file cuddInit.c.
00296 { 00297 if (zdd->univ) { 00298 Cudd_RecursiveDerefZdd(zdd, zdd->univ[0]); 00299 FREE(zdd->univ); 00300 } 00301 00302 } /* end of cuddZddFreeUniv */
Function********************************************************************
Synopsis [Computes the two-way decomposition of f w.r.t. v.]
Description []
SideEffects [The results are returned in f1 and f0.]
SeeAlso [cuddZddGetCofactors3]
Definition at line 1483 of file cuddZddFuncs.c.
01489 { 01490 *f1 = cuddZddSubset1(dd, f, v); 01491 if (*f1 == NULL) 01492 return(1); 01493 *f0 = cuddZddSubset0(dd, f, v); 01494 if (*f0 == NULL) { 01495 Cudd_RecursiveDerefZdd(dd, *f1); 01496 return(1); 01497 } 01498 return(0); 01499 01500 } /* end of cuddZddGetCofactors2 */
int cuddZddGetCofactors3 | ( | DdManager * | dd, | |
DdNode * | f, | |||
int | v, | |||
DdNode ** | f1, | |||
DdNode ** | f0, | |||
DdNode ** | fd | |||
) |
Function********************************************************************
Synopsis [Computes the three-way decomposition of f w.r.t. v.]
Description [Computes the three-way decomposition of function f (represented by a ZDD) wit respect to variable v. Returns 0 if successful; 1 otherwise.]
SideEffects [The results are returned in f1, f0, and fd.]
SeeAlso [cuddZddGetCofactors2]
Definition at line 1356 of file cuddZddFuncs.c.
01363 { 01364 DdNode *pc, *nc; 01365 DdNode *zero = DD_ZERO(dd); 01366 int top, hv, ht, pv, nv; 01367 int level; 01368 01369 top = dd->permZ[f->index]; 01370 level = dd->permZ[v]; 01371 hv = level >> 1; 01372 ht = top >> 1; 01373 01374 if (hv < ht) { 01375 *f1 = zero; 01376 *f0 = zero; 01377 *fd = f; 01378 } 01379 else { 01380 pv = cuddZddGetPosVarIndex(dd, v); 01381 nv = cuddZddGetNegVarIndex(dd, v); 01382 01383 /* not to create intermediate ZDD node */ 01384 if (cuddZddGetPosVarLevel(dd, v) < cuddZddGetNegVarLevel(dd, v)) { 01385 pc = cuddZddSubset1(dd, f, pv); 01386 if (pc == NULL) 01387 return(1); 01388 Cudd_Ref(pc); 01389 nc = cuddZddSubset0(dd, f, pv); 01390 if (nc == NULL) { 01391 Cudd_RecursiveDerefZdd(dd, pc); 01392 return(1); 01393 } 01394 Cudd_Ref(nc); 01395 01396 *f1 = cuddZddSubset0(dd, pc, nv); 01397 if (*f1 == NULL) { 01398 Cudd_RecursiveDerefZdd(dd, pc); 01399 Cudd_RecursiveDerefZdd(dd, nc); 01400 return(1); 01401 } 01402 Cudd_Ref(*f1); 01403 *f0 = cuddZddSubset1(dd, nc, nv); 01404 if (*f0 == NULL) { 01405 Cudd_RecursiveDerefZdd(dd, pc); 01406 Cudd_RecursiveDerefZdd(dd, nc); 01407 Cudd_RecursiveDerefZdd(dd, *f1); 01408 return(1); 01409 } 01410 Cudd_Ref(*f0); 01411 01412 *fd = cuddZddSubset0(dd, nc, nv); 01413 if (*fd == NULL) { 01414 Cudd_RecursiveDerefZdd(dd, pc); 01415 Cudd_RecursiveDerefZdd(dd, nc); 01416 Cudd_RecursiveDerefZdd(dd, *f1); 01417 Cudd_RecursiveDerefZdd(dd, *f0); 01418 return(1); 01419 } 01420 Cudd_Ref(*fd); 01421 } else { 01422 pc = cuddZddSubset1(dd, f, nv); 01423 if (pc == NULL) 01424 return(1); 01425 Cudd_Ref(pc); 01426 nc = cuddZddSubset0(dd, f, nv); 01427 if (nc == NULL) { 01428 Cudd_RecursiveDerefZdd(dd, pc); 01429 return(1); 01430 } 01431 Cudd_Ref(nc); 01432 01433 *f0 = cuddZddSubset0(dd, pc, pv); 01434 if (*f0 == NULL) { 01435 Cudd_RecursiveDerefZdd(dd, pc); 01436 Cudd_RecursiveDerefZdd(dd, nc); 01437 return(1); 01438 } 01439 Cudd_Ref(*f0); 01440 *f1 = cuddZddSubset1(dd, nc, pv); 01441 if (*f1 == NULL) { 01442 Cudd_RecursiveDerefZdd(dd, pc); 01443 Cudd_RecursiveDerefZdd(dd, nc); 01444 Cudd_RecursiveDerefZdd(dd, *f0); 01445 return(1); 01446 } 01447 Cudd_Ref(*f1); 01448 01449 *fd = cuddZddSubset0(dd, nc, pv); 01450 if (*fd == NULL) { 01451 Cudd_RecursiveDerefZdd(dd, pc); 01452 Cudd_RecursiveDerefZdd(dd, nc); 01453 Cudd_RecursiveDerefZdd(dd, *f1); 01454 Cudd_RecursiveDerefZdd(dd, *f0); 01455 return(1); 01456 } 01457 Cudd_Ref(*fd); 01458 } 01459 01460 Cudd_RecursiveDerefZdd(dd, pc); 01461 Cudd_RecursiveDerefZdd(dd, nc); 01462 Cudd_Deref(*f1); 01463 Cudd_Deref(*f0); 01464 Cudd_Deref(*fd); 01465 } 01466 return(0); 01467 01468 } /* end of cuddZddGetCofactors3 */
int cuddZddGetNegVarIndex | ( | DdManager * | dd, | |
int | index | |||
) |
Function********************************************************************
Synopsis [Returns the index of negative ZDD variable.]
Description [Returns the index of negative ZDD variable.]
SideEffects []
SeeAlso []
Definition at line 1582 of file cuddZddFuncs.c.
int cuddZddGetNegVarLevel | ( | DdManager * | dd, | |
int | index | |||
) |
Function********************************************************************
Synopsis [Returns the level of negative ZDD variable.]
Description [Returns the level of negative ZDD variable.]
SideEffects []
SeeAlso []
Definition at line 1624 of file cuddZddFuncs.c.
01627 { 01628 int nv = cuddZddGetNegVarIndex(dd, index); 01629 return(dd->permZ[nv]); 01630 } /* end of cuddZddGetNegVarLevel */
Function********************************************************************
Synopsis [Wrapper for cuddUniqueInterZdd.]
Description [Wrapper for cuddUniqueInterZdd, which applies the ZDD reduction rule. Returns a pointer to the result node under normal conditions; NULL if reordering occurred or memory was exhausted.]
SideEffects [None]
SeeAlso [cuddUniqueInterZdd]
Definition at line 1028 of file cuddTable.c.
01033 { 01034 DdNode *node; 01035 01036 if (T == DD_ZERO(zdd)) 01037 return(E); 01038 node = cuddUniqueInterZdd(zdd, id, T, E); 01039 return(node); 01040 01041 } /* end of cuddZddGetNode */
Function********************************************************************
Synopsis [Wrapper for cuddUniqueInterZdd that is independent of variable ordering.]
Description [Wrapper for cuddUniqueInterZdd that is independent of variable ordering (IVO). This function does not require parameter index to precede the indices of the top nodes of g and h in the variable order. Returns a pointer to the result node under normal conditions; NULL if reordering occurred or memory was exhausted.]
SideEffects [None]
SeeAlso [cuddZddGetNode cuddZddIsop]
Definition at line 1061 of file cuddTable.c.
01066 { 01067 DdNode *f, *r, *t; 01068 DdNode *zdd_one = DD_ONE(dd); 01069 DdNode *zdd_zero = DD_ZERO(dd); 01070 01071 f = cuddUniqueInterZdd(dd, index, zdd_one, zdd_zero); 01072 if (f == NULL) { 01073 return(NULL); 01074 } 01075 cuddRef(f); 01076 t = cuddZddProduct(dd, f, g); 01077 if (t == NULL) { 01078 Cudd_RecursiveDerefZdd(dd, f); 01079 return(NULL); 01080 } 01081 cuddRef(t); 01082 Cudd_RecursiveDerefZdd(dd, f); 01083 r = cuddZddUnion(dd, t, h); 01084 if (r == NULL) { 01085 Cudd_RecursiveDerefZdd(dd, t); 01086 return(NULL); 01087 } 01088 cuddRef(r); 01089 Cudd_RecursiveDerefZdd(dd, t); 01090 01091 cuddDeref(r); 01092 return(r); 01093 01094 } /* end of cuddZddGetNodeIVO */
int cuddZddGetPosVarIndex | ( | DdManager * | dd, | |
int | index | |||
) |
Function********************************************************************
Synopsis [Returns the index of positive ZDD variable.]
Description [Returns the index of positive ZDD variable.]
SideEffects []
SeeAlso []
Definition at line 1561 of file cuddZddFuncs.c.
int cuddZddGetPosVarLevel | ( | DdManager * | dd, | |
int | index | |||
) |
Function********************************************************************
Synopsis [Returns the level of positive ZDD variable.]
Description [Returns the level of positive ZDD variable.]
SideEffects []
SeeAlso []
Definition at line 1603 of file cuddZddFuncs.c.
01606 { 01607 int pv = cuddZddGetPosVarIndex(dd, index); 01608 return(dd->permZ[pv]); 01609 } /* end of cuddZddGetPosVarLevel */
int cuddZddInitUniv | ( | DdManager * | zdd | ) |
Function********************************************************************
Synopsis [Initializes the ZDD universe.]
Description [Initializes the ZDD universe. Returns 1 if successful; 0 otherwise.]
SideEffects [None]
SeeAlso [cuddZddFreeUniv]
Definition at line 245 of file cuddInit.c.
00247 { 00248 DdNode *p, *res; 00249 int i; 00250 00251 zdd->univ = ALLOC(DdNodePtr, zdd->sizeZ); 00252 if (zdd->univ == NULL) { 00253 zdd->errorCode = CUDD_MEMORY_OUT; 00254 return(0); 00255 } 00256 00257 res = DD_ONE(zdd); 00258 cuddRef(res); 00259 for (i = zdd->sizeZ - 1; i >= 0; i--) { 00260 unsigned int index = zdd->invpermZ[i]; 00261 p = res; 00262 res = cuddUniqueInterZdd(zdd, index, p, p); 00263 if (res == NULL) { 00264 Cudd_RecursiveDerefZdd(zdd,p); 00265 FREE(zdd->univ); 00266 return(0); 00267 } 00268 cuddRef(res); 00269 cuddDeref(p); 00270 zdd->univ[i] = res; 00271 } 00272 00273 #ifdef DD_VERBOSE 00274 cuddZddP(zdd, zdd->univ[0]); 00275 #endif 00276 00277 return(1); 00278 00279 } /* end of cuddZddInitUniv */
Function********************************************************************
Synopsis [Performs the recursive step of Cudd_zddIntersect.]
Description []
SideEffects [None]
SeeAlso []
Definition at line 638 of file cuddZddSetop.c.
00642 { 00643 int p_top, q_top; 00644 DdNode *empty = DD_ZERO(zdd), *t, *e, *res; 00645 DdManager *table = zdd; 00646 00647 statLine(zdd); 00648 if (P == empty) 00649 return(empty); 00650 if (Q == empty) 00651 return(empty); 00652 if (P == Q) 00653 return(P); 00654 00655 /* Check cache. */ 00656 res = cuddCacheLookup2Zdd(table, cuddZddIntersect, P, Q); 00657 if (res != NULL) 00658 return(res); 00659 00660 if (cuddIsConstant(P)) 00661 p_top = P->index; 00662 else 00663 p_top = zdd->permZ[P->index]; 00664 if (cuddIsConstant(Q)) 00665 q_top = Q->index; 00666 else 00667 q_top = zdd->permZ[Q->index]; 00668 if (p_top < q_top) { 00669 res = cuddZddIntersect(zdd, cuddE(P), Q); 00670 if (res == NULL) return(NULL); 00671 } else if (p_top > q_top) { 00672 res = cuddZddIntersect(zdd, P, cuddE(Q)); 00673 if (res == NULL) return(NULL); 00674 } else { 00675 t = cuddZddIntersect(zdd, cuddT(P), cuddT(Q)); 00676 if (t == NULL) return(NULL); 00677 cuddRef(t); 00678 e = cuddZddIntersect(zdd, cuddE(P), cuddE(Q)); 00679 if (e == NULL) { 00680 Cudd_RecursiveDerefZdd(table, t); 00681 return(NULL); 00682 } 00683 cuddRef(e); 00684 res = cuddZddGetNode(zdd, P->index, t, e); 00685 if (res == NULL) { 00686 Cudd_RecursiveDerefZdd(table, t); 00687 Cudd_RecursiveDerefZdd(table, e); 00688 return(NULL); 00689 } 00690 cuddDeref(t); 00691 cuddDeref(e); 00692 } 00693 00694 cuddCacheInsert2(table, cuddZddIntersect, P, Q, res); 00695 00696 return(res); 00697 00698 } /* end of cuddZddIntersect */
Function********************************************************************
Synopsis [Performs the recursive step of Cudd_zddIsop.]
Description []
SideEffects [None]
SeeAlso [Cudd_zddIsop]
Definition at line 230 of file cuddZddIsop.c.
00235 { 00236 DdNode *one = DD_ONE(dd); 00237 DdNode *zero = Cudd_Not(one); 00238 DdNode *zdd_one = DD_ONE(dd); 00239 DdNode *zdd_zero = DD_ZERO(dd); 00240 int v, top_l, top_u; 00241 DdNode *Lsub0, *Usub0, *Lsub1, *Usub1, *Ld, *Ud; 00242 DdNode *Lsuper0, *Usuper0, *Lsuper1, *Usuper1; 00243 DdNode *Isub0, *Isub1, *Id; 00244 DdNode *zdd_Isub0, *zdd_Isub1, *zdd_Id; 00245 DdNode *x; 00246 DdNode *term0, *term1, *sum; 00247 DdNode *Lv, *Uv, *Lnv, *Unv; 00248 DdNode *r, *y, *z; 00249 int index; 00250 DD_CTFP cacheOp; 00251 00252 statLine(dd); 00253 if (L == zero) { 00254 *zdd_I = zdd_zero; 00255 return(zero); 00256 } 00257 if (U == one) { 00258 *zdd_I = zdd_one; 00259 return(one); 00260 } 00261 00262 if (U == zero || L == one) { 00263 printf("*** ERROR : illegal condition for ISOP (U < L).\n"); 00264 exit(1); 00265 } 00266 00267 /* Check the cache. We store two results for each recursive call. 00268 ** One is the BDD, and the other is the ZDD. Both are needed. 00269 ** Hence we need a double hit in the cache to terminate the 00270 ** recursion. Clearly, collisions may evict only one of the two 00271 ** results. */ 00272 cacheOp = (DD_CTFP) cuddZddIsop; 00273 r = cuddCacheLookup2(dd, cuddBddIsop, L, U); 00274 if (r) { 00275 *zdd_I = cuddCacheLookup2Zdd(dd, cacheOp, L, U); 00276 if (*zdd_I) 00277 return(r); 00278 else { 00279 /* The BDD result may have been dead. In that case 00280 ** cuddCacheLookup2 would have called cuddReclaim, 00281 ** whose effects we now have to undo. */ 00282 cuddRef(r); 00283 Cudd_RecursiveDeref(dd, r); 00284 } 00285 } 00286 00287 top_l = dd->perm[Cudd_Regular(L)->index]; 00288 top_u = dd->perm[Cudd_Regular(U)->index]; 00289 v = ddMin(top_l, top_u); 00290 00291 /* Compute cofactors. */ 00292 if (top_l == v) { 00293 index = Cudd_Regular(L)->index; 00294 Lv = Cudd_T(L); 00295 Lnv = Cudd_E(L); 00296 if (Cudd_IsComplement(L)) { 00297 Lv = Cudd_Not(Lv); 00298 Lnv = Cudd_Not(Lnv); 00299 } 00300 } 00301 else { 00302 index = Cudd_Regular(U)->index; 00303 Lv = Lnv = L; 00304 } 00305 00306 if (top_u == v) { 00307 Uv = Cudd_T(U); 00308 Unv = Cudd_E(U); 00309 if (Cudd_IsComplement(U)) { 00310 Uv = Cudd_Not(Uv); 00311 Unv = Cudd_Not(Unv); 00312 } 00313 } 00314 else { 00315 Uv = Unv = U; 00316 } 00317 00318 Lsub0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Uv)); 00319 if (Lsub0 == NULL) 00320 return(NULL); 00321 Cudd_Ref(Lsub0); 00322 Usub0 = Unv; 00323 Lsub1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Unv)); 00324 if (Lsub1 == NULL) { 00325 Cudd_RecursiveDeref(dd, Lsub0); 00326 return(NULL); 00327 } 00328 Cudd_Ref(Lsub1); 00329 Usub1 = Uv; 00330 00331 Isub0 = cuddZddIsop(dd, Lsub0, Usub0, &zdd_Isub0); 00332 if (Isub0 == NULL) { 00333 Cudd_RecursiveDeref(dd, Lsub0); 00334 Cudd_RecursiveDeref(dd, Lsub1); 00335 return(NULL); 00336 } 00337 /* 00338 if ((!cuddIsConstant(Cudd_Regular(Isub0))) && 00339 (Cudd_Regular(Isub0)->index != zdd_Isub0->index / 2 || 00340 dd->permZ[index * 2] > dd->permZ[zdd_Isub0->index])) { 00341 printf("*** ERROR : illegal permutation in ZDD. ***\n"); 00342 } 00343 */ 00344 Cudd_Ref(Isub0); 00345 Cudd_Ref(zdd_Isub0); 00346 Isub1 = cuddZddIsop(dd, Lsub1, Usub1, &zdd_Isub1); 00347 if (Isub1 == NULL) { 00348 Cudd_RecursiveDeref(dd, Lsub0); 00349 Cudd_RecursiveDeref(dd, Lsub1); 00350 Cudd_RecursiveDeref(dd, Isub0); 00351 Cudd_RecursiveDerefZdd(dd, zdd_Isub0); 00352 return(NULL); 00353 } 00354 /* 00355 if ((!cuddIsConstant(Cudd_Regular(Isub1))) && 00356 (Cudd_Regular(Isub1)->index != zdd_Isub1->index / 2 || 00357 dd->permZ[index * 2] > dd->permZ[zdd_Isub1->index])) { 00358 printf("*** ERROR : illegal permutation in ZDD. ***\n"); 00359 } 00360 */ 00361 Cudd_Ref(Isub1); 00362 Cudd_Ref(zdd_Isub1); 00363 Cudd_RecursiveDeref(dd, Lsub0); 00364 Cudd_RecursiveDeref(dd, Lsub1); 00365 00366 Lsuper0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Isub0)); 00367 if (Lsuper0 == NULL) { 00368 Cudd_RecursiveDeref(dd, Isub0); 00369 Cudd_RecursiveDerefZdd(dd, zdd_Isub0); 00370 Cudd_RecursiveDeref(dd, Isub1); 00371 Cudd_RecursiveDerefZdd(dd, zdd_Isub1); 00372 return(NULL); 00373 } 00374 Cudd_Ref(Lsuper0); 00375 Lsuper1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Isub1)); 00376 if (Lsuper1 == NULL) { 00377 Cudd_RecursiveDeref(dd, Isub0); 00378 Cudd_RecursiveDerefZdd(dd, zdd_Isub0); 00379 Cudd_RecursiveDeref(dd, Isub1); 00380 Cudd_RecursiveDerefZdd(dd, zdd_Isub1); 00381 Cudd_RecursiveDeref(dd, Lsuper0); 00382 return(NULL); 00383 } 00384 Cudd_Ref(Lsuper1); 00385 Usuper0 = Unv; 00386 Usuper1 = Uv; 00387 00388 /* Ld = Lsuper0 + Lsuper1 */ 00389 Ld = cuddBddAndRecur(dd, Cudd_Not(Lsuper0), Cudd_Not(Lsuper1)); 00390 if (Ld == NULL) { 00391 Cudd_RecursiveDeref(dd, Isub0); 00392 Cudd_RecursiveDerefZdd(dd, zdd_Isub0); 00393 Cudd_RecursiveDeref(dd, Isub1); 00394 Cudd_RecursiveDerefZdd(dd, zdd_Isub1); 00395 Cudd_RecursiveDeref(dd, Lsuper0); 00396 Cudd_RecursiveDeref(dd, Lsuper1); 00397 return(NULL); 00398 } 00399 Ld = Cudd_Not(Ld); 00400 Cudd_Ref(Ld); 00401 /* Ud = Usuper0 * Usuper1 */ 00402 Ud = cuddBddAndRecur(dd, Usuper0, Usuper1); 00403 if (Ud == NULL) { 00404 Cudd_RecursiveDeref(dd, Isub0); 00405 Cudd_RecursiveDerefZdd(dd, zdd_Isub0); 00406 Cudd_RecursiveDeref(dd, Isub1); 00407 Cudd_RecursiveDerefZdd(dd, zdd_Isub1); 00408 Cudd_RecursiveDeref(dd, Lsuper0); 00409 Cudd_RecursiveDeref(dd, Lsuper1); 00410 Cudd_RecursiveDeref(dd, Ld); 00411 return(NULL); 00412 } 00413 Cudd_Ref(Ud); 00414 Cudd_RecursiveDeref(dd, Lsuper0); 00415 Cudd_RecursiveDeref(dd, Lsuper1); 00416 00417 Id = cuddZddIsop(dd, Ld, Ud, &zdd_Id); 00418 if (Id == NULL) { 00419 Cudd_RecursiveDeref(dd, Isub0); 00420 Cudd_RecursiveDerefZdd(dd, zdd_Isub0); 00421 Cudd_RecursiveDeref(dd, Isub1); 00422 Cudd_RecursiveDerefZdd(dd, zdd_Isub1); 00423 Cudd_RecursiveDeref(dd, Ld); 00424 Cudd_RecursiveDeref(dd, Ud); 00425 return(NULL); 00426 } 00427 /* 00428 if ((!cuddIsConstant(Cudd_Regular(Id))) && 00429 (Cudd_Regular(Id)->index != zdd_Id->index / 2 || 00430 dd->permZ[index * 2] > dd->permZ[zdd_Id->index])) { 00431 printf("*** ERROR : illegal permutation in ZDD. ***\n"); 00432 } 00433 */ 00434 Cudd_Ref(Id); 00435 Cudd_Ref(zdd_Id); 00436 Cudd_RecursiveDeref(dd, Ld); 00437 Cudd_RecursiveDeref(dd, Ud); 00438 00439 x = cuddUniqueInter(dd, index, one, zero); 00440 if (x == NULL) { 00441 Cudd_RecursiveDeref(dd, Isub0); 00442 Cudd_RecursiveDerefZdd(dd, zdd_Isub0); 00443 Cudd_RecursiveDeref(dd, Isub1); 00444 Cudd_RecursiveDerefZdd(dd, zdd_Isub1); 00445 Cudd_RecursiveDeref(dd, Id); 00446 Cudd_RecursiveDerefZdd(dd, zdd_Id); 00447 return(NULL); 00448 } 00449 Cudd_Ref(x); 00450 /* term0 = x * Isub0 */ 00451 term0 = cuddBddAndRecur(dd, Cudd_Not(x), Isub0); 00452 if (term0 == NULL) { 00453 Cudd_RecursiveDeref(dd, Isub0); 00454 Cudd_RecursiveDerefZdd(dd, zdd_Isub0); 00455 Cudd_RecursiveDeref(dd, Isub1); 00456 Cudd_RecursiveDerefZdd(dd, zdd_Isub1); 00457 Cudd_RecursiveDeref(dd, Id); 00458 Cudd_RecursiveDerefZdd(dd, zdd_Id); 00459 Cudd_RecursiveDeref(dd, x); 00460 return(NULL); 00461 } 00462 Cudd_Ref(term0); 00463 Cudd_RecursiveDeref(dd, Isub0); 00464 /* term1 = x * Isub1 */ 00465 term1 = cuddBddAndRecur(dd, x, Isub1); 00466 if (term1 == NULL) { 00467 Cudd_RecursiveDerefZdd(dd, zdd_Isub0); 00468 Cudd_RecursiveDeref(dd, Isub1); 00469 Cudd_RecursiveDerefZdd(dd, zdd_Isub1); 00470 Cudd_RecursiveDeref(dd, Id); 00471 Cudd_RecursiveDerefZdd(dd, zdd_Id); 00472 Cudd_RecursiveDeref(dd, x); 00473 Cudd_RecursiveDeref(dd, term0); 00474 return(NULL); 00475 } 00476 Cudd_Ref(term1); 00477 Cudd_RecursiveDeref(dd, x); 00478 Cudd_RecursiveDeref(dd, Isub1); 00479 /* sum = term0 + term1 */ 00480 sum = cuddBddAndRecur(dd, Cudd_Not(term0), Cudd_Not(term1)); 00481 if (sum == NULL) { 00482 Cudd_RecursiveDerefZdd(dd, zdd_Isub0); 00483 Cudd_RecursiveDerefZdd(dd, zdd_Isub1); 00484 Cudd_RecursiveDeref(dd, Id); 00485 Cudd_RecursiveDerefZdd(dd, zdd_Id); 00486 Cudd_RecursiveDeref(dd, term0); 00487 Cudd_RecursiveDeref(dd, term1); 00488 return(NULL); 00489 } 00490 sum = Cudd_Not(sum); 00491 Cudd_Ref(sum); 00492 Cudd_RecursiveDeref(dd, term0); 00493 Cudd_RecursiveDeref(dd, term1); 00494 /* r = sum + Id */ 00495 r = cuddBddAndRecur(dd, Cudd_Not(sum), Cudd_Not(Id)); 00496 r = Cudd_NotCond(r, r != NULL); 00497 if (r == NULL) { 00498 Cudd_RecursiveDerefZdd(dd, zdd_Isub0); 00499 Cudd_RecursiveDerefZdd(dd, zdd_Isub1); 00500 Cudd_RecursiveDeref(dd, Id); 00501 Cudd_RecursiveDerefZdd(dd, zdd_Id); 00502 Cudd_RecursiveDeref(dd, sum); 00503 return(NULL); 00504 } 00505 Cudd_Ref(r); 00506 Cudd_RecursiveDeref(dd, sum); 00507 Cudd_RecursiveDeref(dd, Id); 00508 00509 if (zdd_Isub0 != zdd_zero) { 00510 z = cuddZddGetNodeIVO(dd, index * 2 + 1, zdd_Isub0, zdd_Id); 00511 if (z == NULL) { 00512 Cudd_RecursiveDerefZdd(dd, zdd_Isub0); 00513 Cudd_RecursiveDerefZdd(dd, zdd_Isub1); 00514 Cudd_RecursiveDerefZdd(dd, zdd_Id); 00515 Cudd_RecursiveDeref(dd, r); 00516 return(NULL); 00517 } 00518 } 00519 else { 00520 z = zdd_Id; 00521 } 00522 Cudd_Ref(z); 00523 if (zdd_Isub1 != zdd_zero) { 00524 y = cuddZddGetNodeIVO(dd, index * 2, zdd_Isub1, z); 00525 if (y == NULL) { 00526 Cudd_RecursiveDerefZdd(dd, zdd_Isub0); 00527 Cudd_RecursiveDerefZdd(dd, zdd_Isub1); 00528 Cudd_RecursiveDerefZdd(dd, zdd_Id); 00529 Cudd_RecursiveDeref(dd, r); 00530 Cudd_RecursiveDerefZdd(dd, z); 00531 return(NULL); 00532 } 00533 } 00534 else 00535 y = z; 00536 Cudd_Ref(y); 00537 00538 Cudd_RecursiveDerefZdd(dd, zdd_Isub0); 00539 Cudd_RecursiveDerefZdd(dd, zdd_Isub1); 00540 Cudd_RecursiveDerefZdd(dd, zdd_Id); 00541 Cudd_RecursiveDerefZdd(dd, z); 00542 00543 cuddCacheInsert2(dd, cuddBddIsop, L, U, r); 00544 cuddCacheInsert2(dd, cacheOp, L, U, y); 00545 00546 Cudd_Deref(r); 00547 Cudd_Deref(y); 00548 *zdd_I = y; 00549 /* 00550 if (Cudd_Regular(r)->index != y->index / 2) { 00551 printf("*** ERROR : mismatch in indices between BDD and ZDD. ***\n"); 00552 } 00553 */ 00554 return(r); 00555 00556 } /* end of cuddZddIsop */
Function********************************************************************
Synopsis [Performs the recursive step of Cudd_zddIte.]
Description []
SideEffects [None]
SeeAlso []
Definition at line 423 of file cuddZddSetop.c.
00428 { 00429 DdNode *tautology, *empty; 00430 DdNode *r,*Gv,*Gvn,*Hv,*Hvn,*t,*e; 00431 unsigned int topf,topg,toph,v,top; 00432 int index; 00433 00434 statLine(dd); 00435 /* Trivial cases. */ 00436 /* One variable cases. */ 00437 if (f == (empty = DD_ZERO(dd))) { /* ITE(0,G,H) = H */ 00438 return(h); 00439 } 00440 topf = cuddIZ(dd,f->index); 00441 topg = cuddIZ(dd,g->index); 00442 toph = cuddIZ(dd,h->index); 00443 v = ddMin(topg,toph); 00444 top = ddMin(topf,v); 00445 00446 tautology = (top == CUDD_MAXINDEX) ? DD_ONE(dd) : dd->univ[top]; 00447 if (f == tautology) { /* ITE(1,G,H) = G */ 00448 return(g); 00449 } 00450 00451 /* From now on, f is known to not be a constant. */ 00452 zddVarToConst(f,&g,&h,tautology,empty); 00453 00454 /* Check remaining one variable cases. */ 00455 if (g == h) { /* ITE(F,G,G) = G */ 00456 return(g); 00457 } 00458 00459 if (g == tautology) { /* ITE(F,1,0) = F */ 00460 if (h == empty) return(f); 00461 } 00462 00463 /* Check cache. */ 00464 r = cuddCacheLookupZdd(dd,DD_ZDD_ITE_TAG,f,g,h); 00465 if (r != NULL) { 00466 return(r); 00467 } 00468 00469 /* Recompute these because they may have changed in zddVarToConst. */ 00470 topg = cuddIZ(dd,g->index); 00471 toph = cuddIZ(dd,h->index); 00472 v = ddMin(topg,toph); 00473 00474 if (topf < v) { 00475 r = cuddZddIte(dd,cuddE(f),g,h); 00476 if (r == NULL) return(NULL); 00477 } else if (topf > v) { 00478 if (topg > v) { 00479 Gvn = g; 00480 index = h->index; 00481 } else { 00482 Gvn = cuddE(g); 00483 index = g->index; 00484 } 00485 if (toph > v) { 00486 Hv = empty; Hvn = h; 00487 } else { 00488 Hv = cuddT(h); Hvn = cuddE(h); 00489 } 00490 e = cuddZddIte(dd,f,Gvn,Hvn); 00491 if (e == NULL) return(NULL); 00492 cuddRef(e); 00493 r = cuddZddGetNode(dd,index,Hv,e); 00494 if (r == NULL) { 00495 Cudd_RecursiveDerefZdd(dd,e); 00496 return(NULL); 00497 } 00498 cuddDeref(e); 00499 } else { 00500 index = f->index; 00501 if (topg > v) { 00502 Gv = empty; Gvn = g; 00503 } else { 00504 Gv = cuddT(g); Gvn = cuddE(g); 00505 } 00506 if (toph > v) { 00507 Hv = empty; Hvn = h; 00508 } else { 00509 Hv = cuddT(h); Hvn = cuddE(h); 00510 } 00511 e = cuddZddIte(dd,cuddE(f),Gvn,Hvn); 00512 if (e == NULL) return(NULL); 00513 cuddRef(e); 00514 t = cuddZddIte(dd,cuddT(f),Gv,Hv); 00515 if (t == NULL) { 00516 Cudd_RecursiveDerefZdd(dd,e); 00517 return(NULL); 00518 } 00519 cuddRef(t); 00520 r = cuddZddGetNode(dd,index,t,e); 00521 if (r == NULL) { 00522 Cudd_RecursiveDerefZdd(dd,e); 00523 Cudd_RecursiveDerefZdd(dd,t); 00524 return(NULL); 00525 } 00526 cuddDeref(t); 00527 cuddDeref(e); 00528 } 00529 00530 cuddCacheInsert(dd,DD_ZDD_ITE_TAG,f,g,h,r); 00531 00532 return(r); 00533 00534 } /* end of cuddZddIte */
int cuddZddLinearSifting | ( | DdManager * | table, | |
int | lower, | |||
int | upper | |||
) |
AutomaticEnd Function********************************************************************
Synopsis [Implementation of the linear sifting algorithm for ZDDs.]
Description [Implementation of the linear sifting algorithm for ZDDs. Assumes that no dead nodes are present.
Returns 1 if successful; 0 otherwise.]
SideEffects [None]
SeeAlso []
Definition at line 152 of file cuddZddLin.c.
00156 { 00157 int i; 00158 int *var; 00159 int size; 00160 int x; 00161 int result; 00162 #ifdef DD_STATS 00163 int previousSize; 00164 #endif 00165 00166 size = table->sizeZ; 00167 empty = table->zero; 00168 00169 /* Find order in which to sift variables. */ 00170 var = NULL; 00171 zdd_entry = ALLOC(int, size); 00172 if (zdd_entry == NULL) { 00173 table->errorCode = CUDD_MEMORY_OUT; 00174 goto cuddZddSiftingOutOfMem; 00175 } 00176 var = ALLOC(int, size); 00177 if (var == NULL) { 00178 table->errorCode = CUDD_MEMORY_OUT; 00179 goto cuddZddSiftingOutOfMem; 00180 } 00181 00182 for (i = 0; i < size; i++) { 00183 x = table->permZ[i]; 00184 zdd_entry[i] = table->subtableZ[x].keys; 00185 var[i] = i; 00186 } 00187 00188 qsort((void *)var, size, sizeof(int), (DD_QSFP)cuddZddUniqueCompare); 00189 00190 /* Now sift. */ 00191 for (i = 0; i < ddMin(table->siftMaxVar, size); i++) { 00192 if (zddTotalNumberSwapping >= table->siftMaxSwap) 00193 break; 00194 x = table->permZ[var[i]]; 00195 if (x < lower || x > upper) continue; 00196 #ifdef DD_STATS 00197 previousSize = table->keysZ; 00198 #endif 00199 result = cuddZddLinearAux(table, x, lower, upper); 00200 if (!result) 00201 goto cuddZddSiftingOutOfMem; 00202 #ifdef DD_STATS 00203 if (table->keysZ < (unsigned) previousSize) { 00204 (void) fprintf(table->out,"-"); 00205 } else if (table->keysZ > (unsigned) previousSize) { 00206 (void) fprintf(table->out,"+"); /* should never happen */ 00207 (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ , var[i]); 00208 } else { 00209 (void) fprintf(table->out,"="); 00210 } 00211 fflush(table->out); 00212 #endif 00213 } 00214 00215 FREE(var); 00216 FREE(zdd_entry); 00217 00218 return(1); 00219 00220 cuddZddSiftingOutOfMem: 00221 00222 if (zdd_entry != NULL) FREE(zdd_entry); 00223 if (var != NULL) FREE(var); 00224 00225 return(0); 00226 00227 } /* end of cuddZddLinearSifting */
int cuddZddNextHigh | ( | DdManager * | table, | |
int | x | |||
) |
Function********************************************************************
Synopsis [Finds the next subtable with a larger index.]
Description [Finds the next subtable with a larger index. Returns the index.]
SideEffects [None]
SeeAlso []
Definition at line 409 of file cuddZddReord.c.
int cuddZddNextLow | ( | DdManager * | table, | |
int | x | |||
) |
Function********************************************************************
Synopsis [Finds the next subtable with a smaller index.]
Description [Finds the next subtable with a smaller index. Returns the index.]
SideEffects [None]
SeeAlso []
Definition at line 431 of file cuddZddReord.c.
Function********************************************************************
Synopsis [Prints a ZDD to the standard output. One line per node is printed.]
Description [Prints a ZDD to the standard output. One line per node is printed. Returns 1 if successful; 0 otherwise.]
SideEffects [None]
SeeAlso [Cudd_zddPrintDebug]
Definition at line 818 of file cuddZddUtil.c.
00821 { 00822 int retval; 00823 st_table *table = st_init_table(st_ptrcmp, st_ptrhash); 00824 00825 if (table == NULL) return(0); 00826 00827 retval = zp2(zdd, f, table); 00828 st_free_table(table); 00829 (void) fputc('\n', zdd->out); 00830 return(retval); 00831 00832 } /* end of cuddZddP */
Function********************************************************************
Synopsis [Performs the recursive step of Cudd_zddProduct.]
Description []
SideEffects [None]
SeeAlso [Cudd_zddProduct]
Definition at line 376 of file cuddZddFuncs.c.
00380 { 00381 int v, top_f, top_g; 00382 DdNode *tmp, *term1, *term2, *term3; 00383 DdNode *f0, *f1, *fd, *g0, *g1, *gd; 00384 DdNode *R0, *R1, *Rd, *N0, *N1; 00385 DdNode *r; 00386 DdNode *one = DD_ONE(dd); 00387 DdNode *zero = DD_ZERO(dd); 00388 int flag; 00389 int pv, nv; 00390 00391 statLine(dd); 00392 if (f == zero || g == zero) 00393 return(zero); 00394 if (f == one) 00395 return(g); 00396 if (g == one) 00397 return(f); 00398 00399 top_f = dd->permZ[f->index]; 00400 top_g = dd->permZ[g->index]; 00401 00402 if (top_f > top_g) 00403 return(cuddZddProduct(dd, g, f)); 00404 00405 /* Check cache */ 00406 r = cuddCacheLookup2Zdd(dd, cuddZddProduct, f, g); 00407 if (r) 00408 return(r); 00409 00410 v = f->index; /* either yi or zi */ 00411 flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd); 00412 if (flag == 1) 00413 return(NULL); 00414 Cudd_Ref(f1); 00415 Cudd_Ref(f0); 00416 Cudd_Ref(fd); 00417 flag = cuddZddGetCofactors3(dd, g, v, &g1, &g0, &gd); 00418 if (flag == 1) { 00419 Cudd_RecursiveDerefZdd(dd, f1); 00420 Cudd_RecursiveDerefZdd(dd, f0); 00421 Cudd_RecursiveDerefZdd(dd, fd); 00422 return(NULL); 00423 } 00424 Cudd_Ref(g1); 00425 Cudd_Ref(g0); 00426 Cudd_Ref(gd); 00427 pv = cuddZddGetPosVarIndex(dd, v); 00428 nv = cuddZddGetNegVarIndex(dd, v); 00429 00430 Rd = cuddZddProduct(dd, fd, gd); 00431 if (Rd == NULL) { 00432 Cudd_RecursiveDerefZdd(dd, f1); 00433 Cudd_RecursiveDerefZdd(dd, f0); 00434 Cudd_RecursiveDerefZdd(dd, fd); 00435 Cudd_RecursiveDerefZdd(dd, g1); 00436 Cudd_RecursiveDerefZdd(dd, g0); 00437 Cudd_RecursiveDerefZdd(dd, gd); 00438 return(NULL); 00439 } 00440 Cudd_Ref(Rd); 00441 00442 term1 = cuddZddProduct(dd, f0, g0); 00443 if (term1 == NULL) { 00444 Cudd_RecursiveDerefZdd(dd, f1); 00445 Cudd_RecursiveDerefZdd(dd, f0); 00446 Cudd_RecursiveDerefZdd(dd, fd); 00447 Cudd_RecursiveDerefZdd(dd, g1); 00448 Cudd_RecursiveDerefZdd(dd, g0); 00449 Cudd_RecursiveDerefZdd(dd, gd); 00450 Cudd_RecursiveDerefZdd(dd, Rd); 00451 return(NULL); 00452 } 00453 Cudd_Ref(term1); 00454 term2 = cuddZddProduct(dd, f0, gd); 00455 if (term2 == NULL) { 00456 Cudd_RecursiveDerefZdd(dd, f1); 00457 Cudd_RecursiveDerefZdd(dd, f0); 00458 Cudd_RecursiveDerefZdd(dd, fd); 00459 Cudd_RecursiveDerefZdd(dd, g1); 00460 Cudd_RecursiveDerefZdd(dd, g0); 00461 Cudd_RecursiveDerefZdd(dd, gd); 00462 Cudd_RecursiveDerefZdd(dd, Rd); 00463 Cudd_RecursiveDerefZdd(dd, term1); 00464 return(NULL); 00465 } 00466 Cudd_Ref(term2); 00467 term3 = cuddZddProduct(dd, fd, g0); 00468 if (term3 == NULL) { 00469 Cudd_RecursiveDerefZdd(dd, f1); 00470 Cudd_RecursiveDerefZdd(dd, f0); 00471 Cudd_RecursiveDerefZdd(dd, fd); 00472 Cudd_RecursiveDerefZdd(dd, g1); 00473 Cudd_RecursiveDerefZdd(dd, g0); 00474 Cudd_RecursiveDerefZdd(dd, gd); 00475 Cudd_RecursiveDerefZdd(dd, Rd); 00476 Cudd_RecursiveDerefZdd(dd, term1); 00477 Cudd_RecursiveDerefZdd(dd, term2); 00478 return(NULL); 00479 } 00480 Cudd_Ref(term3); 00481 Cudd_RecursiveDerefZdd(dd, f0); 00482 Cudd_RecursiveDerefZdd(dd, g0); 00483 tmp = cuddZddUnion(dd, term1, term2); 00484 if (tmp == NULL) { 00485 Cudd_RecursiveDerefZdd(dd, f1); 00486 Cudd_RecursiveDerefZdd(dd, fd); 00487 Cudd_RecursiveDerefZdd(dd, g1); 00488 Cudd_RecursiveDerefZdd(dd, gd); 00489 Cudd_RecursiveDerefZdd(dd, Rd); 00490 Cudd_RecursiveDerefZdd(dd, term1); 00491 Cudd_RecursiveDerefZdd(dd, term2); 00492 Cudd_RecursiveDerefZdd(dd, term3); 00493 return(NULL); 00494 } 00495 Cudd_Ref(tmp); 00496 Cudd_RecursiveDerefZdd(dd, term1); 00497 Cudd_RecursiveDerefZdd(dd, term2); 00498 R0 = cuddZddUnion(dd, tmp, term3); 00499 if (R0 == NULL) { 00500 Cudd_RecursiveDerefZdd(dd, f1); 00501 Cudd_RecursiveDerefZdd(dd, fd); 00502 Cudd_RecursiveDerefZdd(dd, g1); 00503 Cudd_RecursiveDerefZdd(dd, gd); 00504 Cudd_RecursiveDerefZdd(dd, Rd); 00505 Cudd_RecursiveDerefZdd(dd, term3); 00506 Cudd_RecursiveDerefZdd(dd, tmp); 00507 return(NULL); 00508 } 00509 Cudd_Ref(R0); 00510 Cudd_RecursiveDerefZdd(dd, tmp); 00511 Cudd_RecursiveDerefZdd(dd, term3); 00512 N0 = cuddZddGetNode(dd, nv, R0, Rd); /* nv = zi */ 00513 if (N0 == NULL) { 00514 Cudd_RecursiveDerefZdd(dd, f1); 00515 Cudd_RecursiveDerefZdd(dd, fd); 00516 Cudd_RecursiveDerefZdd(dd, g1); 00517 Cudd_RecursiveDerefZdd(dd, gd); 00518 Cudd_RecursiveDerefZdd(dd, Rd); 00519 Cudd_RecursiveDerefZdd(dd, R0); 00520 return(NULL); 00521 } 00522 Cudd_Ref(N0); 00523 Cudd_RecursiveDerefZdd(dd, R0); 00524 Cudd_RecursiveDerefZdd(dd, Rd); 00525 00526 term1 = cuddZddProduct(dd, f1, g1); 00527 if (term1 == NULL) { 00528 Cudd_RecursiveDerefZdd(dd, f1); 00529 Cudd_RecursiveDerefZdd(dd, fd); 00530 Cudd_RecursiveDerefZdd(dd, g1); 00531 Cudd_RecursiveDerefZdd(dd, gd); 00532 Cudd_RecursiveDerefZdd(dd, N0); 00533 return(NULL); 00534 } 00535 Cudd_Ref(term1); 00536 term2 = cuddZddProduct(dd, f1, gd); 00537 if (term2 == NULL) { 00538 Cudd_RecursiveDerefZdd(dd, f1); 00539 Cudd_RecursiveDerefZdd(dd, fd); 00540 Cudd_RecursiveDerefZdd(dd, g1); 00541 Cudd_RecursiveDerefZdd(dd, gd); 00542 Cudd_RecursiveDerefZdd(dd, N0); 00543 Cudd_RecursiveDerefZdd(dd, term1); 00544 return(NULL); 00545 } 00546 Cudd_Ref(term2); 00547 term3 = cuddZddProduct(dd, fd, g1); 00548 if (term3 == NULL) { 00549 Cudd_RecursiveDerefZdd(dd, f1); 00550 Cudd_RecursiveDerefZdd(dd, fd); 00551 Cudd_RecursiveDerefZdd(dd, g1); 00552 Cudd_RecursiveDerefZdd(dd, gd); 00553 Cudd_RecursiveDerefZdd(dd, N0); 00554 Cudd_RecursiveDerefZdd(dd, term1); 00555 Cudd_RecursiveDerefZdd(dd, term2); 00556 return(NULL); 00557 } 00558 Cudd_Ref(term3); 00559 Cudd_RecursiveDerefZdd(dd, f1); 00560 Cudd_RecursiveDerefZdd(dd, g1); 00561 Cudd_RecursiveDerefZdd(dd, fd); 00562 Cudd_RecursiveDerefZdd(dd, gd); 00563 tmp = cuddZddUnion(dd, term1, term2); 00564 if (tmp == NULL) { 00565 Cudd_RecursiveDerefZdd(dd, N0); 00566 Cudd_RecursiveDerefZdd(dd, term1); 00567 Cudd_RecursiveDerefZdd(dd, term2); 00568 Cudd_RecursiveDerefZdd(dd, term3); 00569 return(NULL); 00570 } 00571 Cudd_Ref(tmp); 00572 Cudd_RecursiveDerefZdd(dd, term1); 00573 Cudd_RecursiveDerefZdd(dd, term2); 00574 R1 = cuddZddUnion(dd, tmp, term3); 00575 if (R1 == NULL) { 00576 Cudd_RecursiveDerefZdd(dd, N0); 00577 Cudd_RecursiveDerefZdd(dd, term3); 00578 Cudd_RecursiveDerefZdd(dd, tmp); 00579 return(NULL); 00580 } 00581 Cudd_Ref(R1); 00582 Cudd_RecursiveDerefZdd(dd, tmp); 00583 Cudd_RecursiveDerefZdd(dd, term3); 00584 N1 = cuddZddGetNode(dd, pv, R1, N0); /* pv = yi */ 00585 if (N1 == NULL) { 00586 Cudd_RecursiveDerefZdd(dd, N0); 00587 Cudd_RecursiveDerefZdd(dd, R1); 00588 return(NULL); 00589 } 00590 Cudd_Ref(N1); 00591 Cudd_RecursiveDerefZdd(dd, R1); 00592 Cudd_RecursiveDerefZdd(dd, N0); 00593 00594 cuddCacheInsert2(dd, cuddZddProduct, f, g, N1); 00595 Cudd_Deref(N1); 00596 return(N1); 00597 00598 } /* end of cuddZddProduct */
int cuddZddSifting | ( | DdManager * | table, | |
int | lower, | |||
int | upper | |||
) |
Function********************************************************************
Synopsis [Implementation of Rudell's sifting algorithm.]
Description [Implementation of Rudell's sifting algorithm. Assumes that no dead nodes are present.
Returns 1 if successful; 0 otherwise.]
SideEffects [None]
SeeAlso []
Definition at line 863 of file cuddZddReord.c.
00867 { 00868 int i; 00869 int *var; 00870 int size; 00871 int x; 00872 int result; 00873 #ifdef DD_STATS 00874 int previousSize; 00875 #endif 00876 00877 size = table->sizeZ; 00878 00879 /* Find order in which to sift variables. */ 00880 var = NULL; 00881 zdd_entry = ALLOC(int, size); 00882 if (zdd_entry == NULL) { 00883 table->errorCode = CUDD_MEMORY_OUT; 00884 goto cuddZddSiftingOutOfMem; 00885 } 00886 var = ALLOC(int, size); 00887 if (var == NULL) { 00888 table->errorCode = CUDD_MEMORY_OUT; 00889 goto cuddZddSiftingOutOfMem; 00890 } 00891 00892 for (i = 0; i < size; i++) { 00893 x = table->permZ[i]; 00894 zdd_entry[i] = table->subtableZ[x].keys; 00895 var[i] = i; 00896 } 00897 00898 qsort((void *)var, size, sizeof(int), (DD_QSFP)cuddZddUniqueCompare); 00899 00900 /* Now sift. */ 00901 for (i = 0; i < ddMin(table->siftMaxVar, size); i++) { 00902 if (zddTotalNumberSwapping >= table->siftMaxSwap) 00903 break; 00904 x = table->permZ[var[i]]; 00905 if (x < lower || x > upper) continue; 00906 #ifdef DD_STATS 00907 previousSize = table->keysZ; 00908 #endif 00909 result = cuddZddSiftingAux(table, x, lower, upper); 00910 if (!result) 00911 goto cuddZddSiftingOutOfMem; 00912 #ifdef DD_STATS 00913 if (table->keysZ < (unsigned) previousSize) { 00914 (void) fprintf(table->out,"-"); 00915 } else if (table->keysZ > (unsigned) previousSize) { 00916 (void) fprintf(table->out,"+"); /* should never happen */ 00917 (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ , var[i]); 00918 } else { 00919 (void) fprintf(table->out,"="); 00920 } 00921 fflush(table->out); 00922 #endif 00923 } 00924 00925 FREE(var); 00926 FREE(zdd_entry); 00927 00928 return(1); 00929 00930 cuddZddSiftingOutOfMem: 00931 00932 if (zdd_entry != NULL) FREE(zdd_entry); 00933 if (var != NULL) FREE(var); 00934 00935 return(0); 00936 00937 } /* end of cuddZddSifting */
Function********************************************************************
Synopsis [Computes the negative cofactor of a ZDD w.r.t. a variable.]
Description [Computes the negative cofactor of a ZDD w.r.t. a variable. In terms of combinations, the result is the set of all combinations in which the variable is negated. Returns a pointer to the result if successful; NULL otherwise. cuddZddSubset0 performs the same function as Cudd_zddSubset0, but does not restart if reordering has taken place. Therefore it can be called from within a recursive procedure.]
SideEffects [None]
SeeAlso [cuddZddSubset1 Cudd_zddSubset0]
Definition at line 919 of file cuddZddSetop.c.
00923 { 00924 DdNode *zvar, *r; 00925 DdNode *base, *empty; 00926 00927 base = DD_ONE(dd); 00928 empty = DD_ZERO(dd); 00929 00930 zvar = cuddUniqueInterZdd(dd, var, base, empty); 00931 if (zvar == NULL) { 00932 return(NULL); 00933 } else { 00934 cuddRef(zvar); 00935 r = zdd_subset0_aux(dd, P, zvar); 00936 if (r == NULL) { 00937 Cudd_RecursiveDerefZdd(dd, zvar); 00938 return(NULL); 00939 } 00940 cuddRef(r); 00941 Cudd_RecursiveDerefZdd(dd, zvar); 00942 } 00943 00944 cuddDeref(r); 00945 return(r); 00946 00947 } /* end of cuddZddSubset0 */
Function********************************************************************
Synopsis [Computes the positive cofactor of a ZDD w.r.t. a variable.]
Description [Computes the positive cofactor of a ZDD w.r.t. a variable. In terms of combinations, the result is the set of all combinations in which the variable is asserted. Returns a pointer to the result if successful; NULL otherwise. cuddZddSubset1 performs the same function as Cudd_zddSubset1, but does not restart if reordering has taken place. Therefore it can be called from within a recursive procedure.]
SideEffects [None]
SeeAlso [cuddZddSubset0 Cudd_zddSubset1]
Definition at line 870 of file cuddZddSetop.c.
00874 { 00875 DdNode *zvar, *r; 00876 DdNode *base, *empty; 00877 00878 base = DD_ONE(dd); 00879 empty = DD_ZERO(dd); 00880 00881 zvar = cuddUniqueInterZdd(dd, var, base, empty); 00882 if (zvar == NULL) { 00883 return(NULL); 00884 } else { 00885 cuddRef(zvar); 00886 r = zdd_subset1_aux(dd, P, zvar); 00887 if (r == NULL) { 00888 Cudd_RecursiveDerefZdd(dd, zvar); 00889 return(NULL); 00890 } 00891 cuddRef(r); 00892 Cudd_RecursiveDerefZdd(dd, zvar); 00893 } 00894 00895 cuddDeref(r); 00896 return(r); 00897 00898 } /* end of cuddZddSubset1 */
int cuddZddSwapInPlace | ( | DdManager * | table, | |
int | x, | |||
int | y | |||
) |
Function********************************************************************
Synopsis [Swaps two adjacent variables.]
Description [Swaps two adjacent variables. It assumes that no dead nodes are present on entry to this procedure. The procedure then guarantees that no dead nodes will be present when it terminates. cuddZddSwapInPlace assumes that x < y. Returns the number of keys in the table if successful; 0 otherwise.]
SideEffects [None]
SeeAlso []
Definition at line 480 of file cuddZddReord.c.
00484 { 00485 DdNodePtr *xlist, *ylist; 00486 int xindex, yindex; 00487 int xslots, yslots; 00488 int xshift, yshift; 00489 int oldxkeys, oldykeys; 00490 int newxkeys, newykeys; 00491 int i; 00492 int posn; 00493 DdNode *f, *f1, *f0, *f11, *f10, *f01, *f00; 00494 DdNode *newf1, *newf0, *next; 00495 DdNodePtr g, *lastP, *previousP; 00496 00497 #ifdef DD_DEBUG 00498 assert(x < y); 00499 assert(cuddZddNextHigh(table,x) == y); 00500 assert(table->subtableZ[x].keys != 0); 00501 assert(table->subtableZ[y].keys != 0); 00502 assert(table->subtableZ[x].dead == 0); 00503 assert(table->subtableZ[y].dead == 0); 00504 #endif 00505 00506 zddTotalNumberSwapping++; 00507 00508 /* Get parameters of x subtable. */ 00509 xindex = table->invpermZ[x]; 00510 xlist = table->subtableZ[x].nodelist; 00511 oldxkeys = table->subtableZ[x].keys; 00512 xslots = table->subtableZ[x].slots; 00513 xshift = table->subtableZ[x].shift; 00514 newxkeys = 0; 00515 00516 yindex = table->invpermZ[y]; 00517 ylist = table->subtableZ[y].nodelist; 00518 oldykeys = table->subtableZ[y].keys; 00519 yslots = table->subtableZ[y].slots; 00520 yshift = table->subtableZ[y].shift; 00521 newykeys = oldykeys; 00522 00523 /* The nodes in the x layer that don't depend on y directly 00524 ** will stay there; the others are put in a chain. 00525 ** The chain is handled as a FIFO; g points to the beginning and 00526 ** last points to the end. 00527 */ 00528 00529 g = NULL; 00530 lastP = &g; 00531 for (i = 0; i < xslots; i++) { 00532 previousP = &(xlist[i]); 00533 f = *previousP; 00534 while (f != NULL) { 00535 next = f->next; 00536 f1 = cuddT(f); f0 = cuddE(f); 00537 if ((f1->index != (DdHalfWord) yindex) && 00538 (f0->index != (DdHalfWord) yindex)) { /* stays */ 00539 newxkeys++; 00540 *previousP = f; 00541 previousP = &(f->next); 00542 } else { 00543 f->index = yindex; 00544 *lastP = f; 00545 lastP = &(f->next); 00546 } 00547 f = next; 00548 } /* while there are elements in the collision chain */ 00549 *previousP = NULL; 00550 } /* for each slot of the x subtable */ 00551 *lastP = NULL; 00552 00553 00554 #ifdef DD_COUNT 00555 table->swapSteps += oldxkeys - newxkeys; 00556 #endif 00557 /* Take care of the x nodes that must be re-expressed. 00558 ** They form a linked list pointed by g. Their index has been 00559 ** changed to yindex already. 00560 */ 00561 f = g; 00562 while (f != NULL) { 00563 next = f->next; 00564 /* Find f1, f0, f11, f10, f01, f00. */ 00565 f1 = cuddT(f); 00566 if ((int) f1->index == yindex) { 00567 f11 = cuddT(f1); f10 = cuddE(f1); 00568 } else { 00569 f11 = empty; f10 = f1; 00570 } 00571 f0 = cuddE(f); 00572 if ((int) f0->index == yindex) { 00573 f01 = cuddT(f0); f00 = cuddE(f0); 00574 } else { 00575 f01 = empty; f00 = f0; 00576 } 00577 00578 /* Decrease ref count of f1. */ 00579 cuddSatDec(f1->ref); 00580 /* Create the new T child. */ 00581 if (f11 == empty) { 00582 if (f01 != empty) { 00583 newf1 = f01; 00584 cuddSatInc(newf1->ref); 00585 } 00586 /* else case was already handled when finding nodes 00587 ** with both children below level y 00588 */ 00589 } else { 00590 /* Check xlist for triple (xindex, f11, f01). */ 00591 posn = ddHash(f11, f01, xshift); 00592 /* For each element newf1 in collision list xlist[posn]. */ 00593 newf1 = xlist[posn]; 00594 while (newf1 != NULL) { 00595 if (cuddT(newf1) == f11 && cuddE(newf1) == f01) { 00596 cuddSatInc(newf1->ref); 00597 break; /* match */ 00598 } 00599 newf1 = newf1->next; 00600 } /* while newf1 */ 00601 if (newf1 == NULL) { /* no match */ 00602 newf1 = cuddDynamicAllocNode(table); 00603 if (newf1 == NULL) 00604 goto zddSwapOutOfMem; 00605 newf1->index = xindex; newf1->ref = 1; 00606 cuddT(newf1) = f11; 00607 cuddE(newf1) = f01; 00608 /* Insert newf1 in the collision list xlist[pos]; 00609 ** increase the ref counts of f11 and f01 00610 */ 00611 newxkeys++; 00612 newf1->next = xlist[posn]; 00613 xlist[posn] = newf1; 00614 cuddSatInc(f11->ref); 00615 cuddSatInc(f01->ref); 00616 } 00617 } 00618 cuddT(f) = newf1; 00619 00620 /* Do the same for f0. */ 00621 /* Decrease ref count of f0. */ 00622 cuddSatDec(f0->ref); 00623 /* Create the new E child. */ 00624 if (f10 == empty) { 00625 newf0 = f00; 00626 cuddSatInc(newf0->ref); 00627 } else { 00628 /* Check xlist for triple (xindex, f10, f00). */ 00629 posn = ddHash(f10, f00, xshift); 00630 /* For each element newf0 in collision list xlist[posn]. */ 00631 newf0 = xlist[posn]; 00632 while (newf0 != NULL) { 00633 if (cuddT(newf0) == f10 && cuddE(newf0) == f00) { 00634 cuddSatInc(newf0->ref); 00635 break; /* match */ 00636 } 00637 newf0 = newf0->next; 00638 } /* while newf0 */ 00639 if (newf0 == NULL) { /* no match */ 00640 newf0 = cuddDynamicAllocNode(table); 00641 if (newf0 == NULL) 00642 goto zddSwapOutOfMem; 00643 newf0->index = xindex; newf0->ref = 1; 00644 cuddT(newf0) = f10; cuddE(newf0) = f00; 00645 /* Insert newf0 in the collision list xlist[posn]; 00646 ** increase the ref counts of f10 and f00. 00647 */ 00648 newxkeys++; 00649 newf0->next = xlist[posn]; 00650 xlist[posn] = newf0; 00651 cuddSatInc(f10->ref); 00652 cuddSatInc(f00->ref); 00653 } 00654 } 00655 cuddE(f) = newf0; 00656 00657 /* Insert the modified f in ylist. 00658 ** The modified f does not already exists in ylist. 00659 ** (Because of the uniqueness of the cofactors.) 00660 */ 00661 posn = ddHash(newf1, newf0, yshift); 00662 newykeys++; 00663 f->next = ylist[posn]; 00664 ylist[posn] = f; 00665 f = next; 00666 } /* while f != NULL */ 00667 00668 /* GC the y layer. */ 00669 00670 /* For each node f in ylist. */ 00671 for (i = 0; i < yslots; i++) { 00672 previousP = &(ylist[i]); 00673 f = *previousP; 00674 while (f != NULL) { 00675 next = f->next; 00676 if (f->ref == 0) { 00677 cuddSatDec(cuddT(f)->ref); 00678 cuddSatDec(cuddE(f)->ref); 00679 cuddDeallocNode(table, f); 00680 newykeys--; 00681 } else { 00682 *previousP = f; 00683 previousP = &(f->next); 00684 } 00685 f = next; 00686 } /* while f */ 00687 *previousP = NULL; 00688 } /* for i */ 00689 00690 /* Set the appropriate fields in table. */ 00691 table->subtableZ[x].nodelist = ylist; 00692 table->subtableZ[x].slots = yslots; 00693 table->subtableZ[x].shift = yshift; 00694 table->subtableZ[x].keys = newykeys; 00695 table->subtableZ[x].maxKeys = yslots * DD_MAX_SUBTABLE_DENSITY; 00696 00697 table->subtableZ[y].nodelist = xlist; 00698 table->subtableZ[y].slots = xslots; 00699 table->subtableZ[y].shift = xshift; 00700 table->subtableZ[y].keys = newxkeys; 00701 table->subtableZ[y].maxKeys = xslots * DD_MAX_SUBTABLE_DENSITY; 00702 00703 table->permZ[xindex] = y; table->permZ[yindex] = x; 00704 table->invpermZ[x] = yindex; table->invpermZ[y] = xindex; 00705 00706 table->keysZ += newxkeys + newykeys - oldxkeys - oldykeys; 00707 00708 /* Update univ section; univ[x] remains the same. */ 00709 table->univ[y] = cuddT(table->univ[x]); 00710 00711 return (table->keysZ); 00712 00713 zddSwapOutOfMem: 00714 (void) fprintf(table->err, "Error: cuddZddSwapInPlace out of memory\n"); 00715 00716 return (0); 00717 00718 } /* end of cuddZddSwapInPlace */
int cuddZddSwapping | ( | DdManager * | table, | |
int | lower, | |||
int | upper, | |||
Cudd_ReorderingType | heuristic | |||
) |
Function********************************************************************
Synopsis [Reorders variables by a sequence of (non-adjacent) swaps.]
Description [Implementation of Plessier's algorithm that reorders variables by a sequence of (non-adjacent) swaps.
Returns 1 in case of success; 0 otherwise.]
SideEffects [None]
SeeAlso []
Definition at line 742 of file cuddZddReord.c.
00747 { 00748 int i, j; 00749 int max, keys; 00750 int nvars; 00751 int x, y; 00752 int iterate; 00753 int previousSize; 00754 Move *moves, *move; 00755 int pivot; 00756 int modulo; 00757 int result; 00758 00759 #ifdef DD_DEBUG 00760 /* Sanity check */ 00761 assert(lower >= 0 && upper < table->sizeZ && lower <= upper); 00762 #endif 00763 00764 nvars = upper - lower + 1; 00765 iterate = nvars; 00766 00767 for (i = 0; i < iterate; i++) { 00768 if (heuristic == CUDD_REORDER_RANDOM_PIVOT) { 00769 /* Find pivot <= id with maximum keys. */ 00770 for (max = -1, j = lower; j <= upper; j++) { 00771 if ((keys = table->subtableZ[j].keys) > max) { 00772 max = keys; 00773 pivot = j; 00774 } 00775 } 00776 00777 modulo = upper - pivot; 00778 if (modulo == 0) { 00779 y = pivot; /* y = nvars-1 */ 00780 } else { 00781 /* y = random # from {pivot+1 .. nvars-1} */ 00782 y = pivot + 1 + (int) (Cudd_Random() % modulo); 00783 } 00784 00785 modulo = pivot - lower - 1; 00786 if (modulo < 1) { /* if pivot = 1 or 0 */ 00787 x = lower; 00788 } else { 00789 do { /* x = random # from {0 .. pivot-2} */ 00790 x = (int) Cudd_Random() % modulo; 00791 } while (x == y); 00792 /* Is this condition really needed, since x and y 00793 are in regions separated by pivot? */ 00794 } 00795 } else { 00796 x = (int) (Cudd_Random() % nvars) + lower; 00797 do { 00798 y = (int) (Cudd_Random() % nvars) + lower; 00799 } while (x == y); 00800 } 00801 00802 previousSize = table->keysZ; 00803 moves = zddSwapAny(table, x, y); 00804 if (moves == NULL) 00805 goto cuddZddSwappingOutOfMem; 00806 00807 result = cuddZddSiftingBackward(table, moves, previousSize); 00808 if (!result) 00809 goto cuddZddSwappingOutOfMem; 00810 00811 while (moves != NULL) { 00812 move = moves->next; 00813 cuddDeallocMove(table, moves); 00814 moves = move; 00815 } 00816 #ifdef DD_STATS 00817 if (table->keysZ < (unsigned) previousSize) { 00818 (void) fprintf(table->out,"-"); 00819 } else if (table->keysZ > (unsigned) previousSize) { 00820 (void) fprintf(table->out,"+"); /* should never happen */ 00821 } else { 00822 (void) fprintf(table->out,"="); 00823 } 00824 fflush(table->out); 00825 #endif 00826 } 00827 00828 return(1); 00829 00830 cuddZddSwappingOutOfMem: 00831 while (moves != NULL) { 00832 move = moves->next; 00833 cuddDeallocMove(table, moves); 00834 moves = move; 00835 } 00836 return(0); 00837 00838 } /* end of cuddZddSwapping */
int cuddZddSymmCheck | ( | DdManager * | table, | |
int | x, | |||
int | y | |||
) |
Function********************************************************************
Synopsis [Checks for symmetry of x and y.]
Description [Checks for symmetry of x and y. Ignores projection functions, unless they are isolated. Returns 1 in case of symmetry; 0 otherwise.]
SideEffects [None]
SeeAlso []
Definition at line 193 of file cuddZddSymm.c.
00197 { 00198 int i; 00199 DdNode *f, *f0, *f1, *f01, *f00, *f11, *f10; 00200 int yindex; 00201 int xsymmy = 1; 00202 int xsymmyp = 1; 00203 int arccount = 0; 00204 int TotalRefCount = 0; 00205 int symm_found; 00206 00207 empty = table->zero; 00208 00209 yindex = table->invpermZ[y]; 00210 for (i = table->subtableZ[x].slots - 1; i >= 0; i--) { 00211 f = table->subtableZ[x].nodelist[i]; 00212 while (f != NULL) { 00213 /* Find f1, f0, f11, f10, f01, f00 */ 00214 f1 = cuddT(f); 00215 f0 = cuddE(f); 00216 if ((int) f1->index == yindex) { 00217 f11 = cuddT(f1); 00218 f10 = cuddE(f1); 00219 if (f10 != empty) 00220 arccount++; 00221 } else { 00222 if ((int) f0->index != yindex) { 00223 return(0); /* f bypasses layer y */ 00224 } 00225 f11 = empty; 00226 f10 = f1; 00227 } 00228 if ((int) f0->index == yindex) { 00229 f01 = cuddT(f0); 00230 f00 = cuddE(f0); 00231 if (f00 != empty) 00232 arccount++; 00233 } else { 00234 f01 = empty; 00235 f00 = f0; 00236 } 00237 if (f01 != f10) 00238 xsymmy = 0; 00239 if (f11 != f00) 00240 xsymmyp = 0; 00241 if ((xsymmy == 0) && (xsymmyp == 0)) 00242 return(0); 00243 00244 f = f->next; 00245 } /* for each element of the collision list */ 00246 } /* for each slot of the subtable */ 00247 00248 /* Calculate the total reference counts of y 00249 ** whose else arc is not empty. 00250 */ 00251 for (i = table->subtableZ[y].slots - 1; i >= 0; i--) { 00252 f = table->subtableZ[y].nodelist[i]; 00253 while (f != NIL(DdNode)) { 00254 if (cuddE(f) != empty) 00255 TotalRefCount += f->ref; 00256 f = f->next; 00257 } 00258 } 00259 00260 symm_found = (arccount == TotalRefCount); 00261 #if defined(DD_DEBUG) && defined(DD_VERBOSE) 00262 if (symm_found) { 00263 int xindex = table->invpermZ[x]; 00264 (void) fprintf(table->out, 00265 "Found symmetry! x =%d\ty = %d\tPos(%d,%d)\n", 00266 xindex,yindex,x,y); 00267 } 00268 #endif 00269 00270 return(symm_found); 00271 00272 } /* end cuddZddSymmCheck */
int cuddZddSymmSifting | ( | DdManager * | table, | |
int | lower, | |||
int | upper | |||
) |
Function********************************************************************
Synopsis [Symmetric sifting algorithm for ZDDs.]
Description [Symmetric sifting algorithm. Assumes that no dead nodes are present.
Returns 1 plus the number of symmetric variables if successful; 0 otherwise.]
SideEffects [None]
SeeAlso [cuddZddSymmSiftingConv]
Definition at line 298 of file cuddZddSymm.c.
00302 { 00303 int i; 00304 int *var; 00305 int nvars; 00306 int x; 00307 int result; 00308 int symvars; 00309 int symgroups; 00310 int iteration; 00311 #ifdef DD_STATS 00312 int previousSize; 00313 #endif 00314 00315 nvars = table->sizeZ; 00316 00317 /* Find order in which to sift variables. */ 00318 var = NULL; 00319 zdd_entry = ALLOC(int, nvars); 00320 if (zdd_entry == NULL) { 00321 table->errorCode = CUDD_MEMORY_OUT; 00322 goto cuddZddSymmSiftingOutOfMem; 00323 } 00324 var = ALLOC(int, nvars); 00325 if (var == NULL) { 00326 table->errorCode = CUDD_MEMORY_OUT; 00327 goto cuddZddSymmSiftingOutOfMem; 00328 } 00329 00330 for (i = 0; i < nvars; i++) { 00331 x = table->permZ[i]; 00332 zdd_entry[i] = table->subtableZ[x].keys; 00333 var[i] = i; 00334 } 00335 00336 qsort((void *)var, nvars, sizeof(int), (DD_QSFP)cuddZddUniqueCompare); 00337 00338 /* Initialize the symmetry of each subtable to itself. */ 00339 for (i = lower; i <= upper; i++) 00340 table->subtableZ[i].next = i; 00341 00342 iteration = ddMin(table->siftMaxVar, nvars); 00343 for (i = 0; i < iteration; i++) { 00344 if (zddTotalNumberSwapping >= table->siftMaxSwap) 00345 break; 00346 x = table->permZ[var[i]]; 00347 #ifdef DD_STATS 00348 previousSize = table->keysZ; 00349 #endif 00350 if (x < lower || x > upper) continue; 00351 if (table->subtableZ[x].next == (unsigned) x) { 00352 result = cuddZddSymmSiftingAux(table, x, lower, upper); 00353 if (!result) 00354 goto cuddZddSymmSiftingOutOfMem; 00355 #ifdef DD_STATS 00356 if (table->keysZ < (unsigned) previousSize) { 00357 (void) fprintf(table->out,"-"); 00358 } else if (table->keysZ > (unsigned) previousSize) { 00359 (void) fprintf(table->out,"+"); 00360 #ifdef DD_VERBOSE 00361 (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]); 00362 #endif 00363 } else { 00364 (void) fprintf(table->out,"="); 00365 } 00366 fflush(table->out); 00367 #endif 00368 } 00369 } 00370 00371 FREE(var); 00372 FREE(zdd_entry); 00373 00374 cuddZddSymmSummary(table, lower, upper, &symvars, &symgroups); 00375 00376 #ifdef DD_STATS 00377 (void) fprintf(table->out,"\n#:S_SIFTING %8d: symmetric variables\n",symvars); 00378 (void) fprintf(table->out,"#:G_SIFTING %8d: symmetric groups\n",symgroups); 00379 #endif 00380 00381 return(1+symvars); 00382 00383 cuddZddSymmSiftingOutOfMem: 00384 00385 if (zdd_entry != NULL) 00386 FREE(zdd_entry); 00387 if (var != NULL) 00388 FREE(var); 00389 00390 return(0); 00391 00392 } /* end of cuddZddSymmSifting */
int cuddZddSymmSiftingConv | ( | DdManager * | table, | |
int | lower, | |||
int | upper | |||
) |
Function********************************************************************
Synopsis [Symmetric sifting to convergence algorithm for ZDDs.]
Description [Symmetric sifting to convergence algorithm for ZDDs. Assumes that no dead nodes are present.
Returns 1 plus the number of symmetric variables if successful; 0 otherwise.]
SideEffects [None]
SeeAlso [cuddZddSymmSifting]
Definition at line 419 of file cuddZddSymm.c.
00423 { 00424 int i; 00425 int *var; 00426 int nvars; 00427 int initialSize; 00428 int x; 00429 int result; 00430 int symvars; 00431 int symgroups; 00432 int classes; 00433 int iteration; 00434 #ifdef DD_STATS 00435 int previousSize; 00436 #endif 00437 00438 initialSize = table->keysZ; 00439 00440 nvars = table->sizeZ; 00441 00442 /* Find order in which to sift variables. */ 00443 var = NULL; 00444 zdd_entry = ALLOC(int, nvars); 00445 if (zdd_entry == NULL) { 00446 table->errorCode = CUDD_MEMORY_OUT; 00447 goto cuddZddSymmSiftingConvOutOfMem; 00448 } 00449 var = ALLOC(int, nvars); 00450 if (var == NULL) { 00451 table->errorCode = CUDD_MEMORY_OUT; 00452 goto cuddZddSymmSiftingConvOutOfMem; 00453 } 00454 00455 for (i = 0; i < nvars; i++) { 00456 x = table->permZ[i]; 00457 zdd_entry[i] = table->subtableZ[x].keys; 00458 var[i] = i; 00459 } 00460 00461 qsort((void *)var, nvars, sizeof(int), (DD_QSFP)cuddZddUniqueCompare); 00462 00463 /* Initialize the symmetry of each subtable to itself 00464 ** for first pass of converging symmetric sifting. 00465 */ 00466 for (i = lower; i <= upper; i++) 00467 table->subtableZ[i].next = i; 00468 00469 iteration = ddMin(table->siftMaxVar, table->sizeZ); 00470 for (i = 0; i < iteration; i++) { 00471 if (zddTotalNumberSwapping >= table->siftMaxSwap) 00472 break; 00473 x = table->permZ[var[i]]; 00474 if (x < lower || x > upper) continue; 00475 /* Only sift if not in symmetry group already. */ 00476 if (table->subtableZ[x].next == (unsigned) x) { 00477 #ifdef DD_STATS 00478 previousSize = table->keysZ; 00479 #endif 00480 result = cuddZddSymmSiftingAux(table, x, lower, upper); 00481 if (!result) 00482 goto cuddZddSymmSiftingConvOutOfMem; 00483 #ifdef DD_STATS 00484 if (table->keysZ < (unsigned) previousSize) { 00485 (void) fprintf(table->out,"-"); 00486 } else if (table->keysZ > (unsigned) previousSize) { 00487 (void) fprintf(table->out,"+"); 00488 #ifdef DD_VERBOSE 00489 (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]); 00490 #endif 00491 } else { 00492 (void) fprintf(table->out,"="); 00493 } 00494 fflush(table->out); 00495 #endif 00496 } 00497 } 00498 00499 /* Sifting now until convergence. */ 00500 while ((unsigned) initialSize > table->keysZ) { 00501 initialSize = table->keysZ; 00502 #ifdef DD_STATS 00503 (void) fprintf(table->out,"\n"); 00504 #endif 00505 /* Here we consider only one representative for each symmetry class. */ 00506 for (x = lower, classes = 0; x <= upper; x++, classes++) { 00507 while ((unsigned) x < table->subtableZ[x].next) 00508 x = table->subtableZ[x].next; 00509 /* Here x is the largest index in a group. 00510 ** Groups consists of adjacent variables. 00511 ** Hence, the next increment of x will move it to a new group. 00512 */ 00513 i = table->invpermZ[x]; 00514 zdd_entry[i] = table->subtableZ[x].keys; 00515 var[classes] = i; 00516 } 00517 00518 qsort((void *)var,classes,sizeof(int),(DD_QSFP)cuddZddUniqueCompare); 00519 00520 /* Now sift. */ 00521 iteration = ddMin(table->siftMaxVar, nvars); 00522 for (i = 0; i < iteration; i++) { 00523 if (zddTotalNumberSwapping >= table->siftMaxSwap) 00524 break; 00525 x = table->permZ[var[i]]; 00526 if ((unsigned) x >= table->subtableZ[x].next) { 00527 #ifdef DD_STATS 00528 previousSize = table->keysZ; 00529 #endif 00530 result = cuddZddSymmSiftingConvAux(table, x, lower, upper); 00531 if (!result) 00532 goto cuddZddSymmSiftingConvOutOfMem; 00533 #ifdef DD_STATS 00534 if (table->keysZ < (unsigned) previousSize) { 00535 (void) fprintf(table->out,"-"); 00536 } else if (table->keysZ > (unsigned) previousSize) { 00537 (void) fprintf(table->out,"+"); 00538 #ifdef DD_VERBOSE 00539 (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]); 00540 #endif 00541 } else { 00542 (void) fprintf(table->out,"="); 00543 } 00544 fflush(table->out); 00545 #endif 00546 } 00547 } /* for */ 00548 } 00549 00550 cuddZddSymmSummary(table, lower, upper, &symvars, &symgroups); 00551 00552 #ifdef DD_STATS 00553 (void) fprintf(table->out,"\n#:S_SIFTING %8d: symmetric variables\n", 00554 symvars); 00555 (void) fprintf(table->out,"#:G_SIFTING %8d: symmetric groups\n", 00556 symgroups); 00557 #endif 00558 00559 FREE(var); 00560 FREE(zdd_entry); 00561 00562 return(1+symvars); 00563 00564 cuddZddSymmSiftingConvOutOfMem: 00565 00566 if (zdd_entry != NULL) 00567 FREE(zdd_entry); 00568 if (var != NULL) 00569 FREE(var); 00570 00571 return(0); 00572 00573 } /* end of cuddZddSymmSiftingConv */
int cuddZddTreeSifting | ( | DdManager * | table, | |
Cudd_ReorderingType | method | |||
) |
Function********************************************************************
Synopsis [Tree sifting algorithm for ZDDs.]
Description [Tree sifting algorithm for ZDDs. Assumes that a tree representing a group hierarchy is passed as a parameter. It then reorders each group in postorder fashion by calling zddTreeSiftingAux. Assumes that no dead nodes are present. Returns 1 if successful; 0 otherwise.]
SideEffects [None]
Definition at line 228 of file cuddZddGroup.c.
00231 { 00232 int i; 00233 int nvars; 00234 int result; 00235 int tempTree; 00236 00237 /* If no tree is provided we create a temporary one in which all 00238 ** variables are in a single group. After reordering this tree is 00239 ** destroyed. 00240 */ 00241 tempTree = table->treeZ == NULL; 00242 if (tempTree) { 00243 table->treeZ = Mtr_InitGroupTree(0,table->sizeZ); 00244 table->treeZ->index = table->invpermZ[0]; 00245 } 00246 nvars = table->sizeZ; 00247 00248 #ifdef DD_DEBUG 00249 if (pr > 0 && !tempTree) 00250 (void) fprintf(table->out,"cuddZddTreeSifting:"); 00251 Mtr_PrintGroups(table->treeZ,pr <= 0); 00252 #endif 00253 #if 0 00254 /* Debugging code. */ 00255 if (table->tree && table->treeZ) { 00256 (void) fprintf(table->out,"\n"); 00257 Mtr_PrintGroups(table->tree, 0); 00258 cuddPrintVarGroups(table,table->tree,0,0); 00259 for (i = 0; i < table->size; i++) { 00260 (void) fprintf(table->out,"%s%d", 00261 (i == 0) ? "" : ",", table->invperm[i]); 00262 } 00263 (void) fprintf(table->out,"\n"); 00264 for (i = 0; i < table->size; i++) { 00265 (void) fprintf(table->out,"%s%d", 00266 (i == 0) ? "" : ",", table->perm[i]); 00267 } 00268 (void) fprintf(table->out,"\n\n"); 00269 Mtr_PrintGroups(table->treeZ,0); 00270 cuddPrintVarGroups(table,table->treeZ,1,0); 00271 for (i = 0; i < table->sizeZ; i++) { 00272 (void) fprintf(table->out,"%s%d", 00273 (i == 0) ? "" : ",", table->invpermZ[i]); 00274 } 00275 (void) fprintf(table->out,"\n"); 00276 for (i = 0; i < table->sizeZ; i++) { 00277 (void) fprintf(table->out,"%s%d", 00278 (i == 0) ? "" : ",", table->permZ[i]); 00279 } 00280 (void) fprintf(table->out,"\n"); 00281 } 00282 /* End of debugging code. */ 00283 #endif 00284 #ifdef DD_STATS 00285 extsymmcalls = 0; 00286 extsymm = 0; 00287 secdiffcalls = 0; 00288 secdiff = 0; 00289 secdiffmisfire = 0; 00290 00291 (void) fprintf(table->out,"\n"); 00292 if (!tempTree) 00293 (void) fprintf(table->out,"#:IM_NODES %8d: group tree nodes\n", 00294 zddCountInternalMtrNodes(table,table->treeZ)); 00295 #endif 00296 00297 /* Initialize the group of each subtable to itself. Initially 00298 ** there are no groups. Groups are created according to the tree 00299 ** structure in postorder fashion. 00300 */ 00301 for (i = 0; i < nvars; i++) 00302 table->subtableZ[i].next = i; 00303 00304 /* Reorder. */ 00305 result = zddTreeSiftingAux(table, table->treeZ, method); 00306 00307 #ifdef DD_STATS /* print stats */ 00308 if (!tempTree && method == CUDD_REORDER_GROUP_SIFT && 00309 (table->groupcheck == CUDD_GROUP_CHECK7 || 00310 table->groupcheck == CUDD_GROUP_CHECK5)) { 00311 (void) fprintf(table->out,"\nextsymmcalls = %d\n",extsymmcalls); 00312 (void) fprintf(table->out,"extsymm = %d",extsymm); 00313 } 00314 if (!tempTree && method == CUDD_REORDER_GROUP_SIFT && 00315 table->groupcheck == CUDD_GROUP_CHECK7) { 00316 (void) fprintf(table->out,"\nsecdiffcalls = %d\n",secdiffcalls); 00317 (void) fprintf(table->out,"secdiff = %d\n",secdiff); 00318 (void) fprintf(table->out,"secdiffmisfire = %d",secdiffmisfire); 00319 } 00320 #endif 00321 00322 if (tempTree) 00323 Cudd_FreeZddTree(table); 00324 return(result); 00325 00326 } /* end of cuddZddTreeSifting */
Function********************************************************************
Synopsis [Performs the recursive step of Cudd_zddUnateProduct.]
Description []
SideEffects [None]
SeeAlso [Cudd_zddUnateProduct]
Definition at line 613 of file cuddZddFuncs.c.
00617 { 00618 int v, top_f, top_g; 00619 DdNode *term1, *term2, *term3, *term4; 00620 DdNode *sum1, *sum2; 00621 DdNode *f0, *f1, *g0, *g1; 00622 DdNode *r; 00623 DdNode *one = DD_ONE(dd); 00624 DdNode *zero = DD_ZERO(dd); 00625 int flag; 00626 00627 statLine(dd); 00628 if (f == zero || g == zero) 00629 return(zero); 00630 if (f == one) 00631 return(g); 00632 if (g == one) 00633 return(f); 00634 00635 top_f = dd->permZ[f->index]; 00636 top_g = dd->permZ[g->index]; 00637 00638 if (top_f > top_g) 00639 return(cuddZddUnateProduct(dd, g, f)); 00640 00641 /* Check cache */ 00642 r = cuddCacheLookup2Zdd(dd, cuddZddUnateProduct, f, g); 00643 if (r) 00644 return(r); 00645 00646 v = f->index; /* either yi or zi */ 00647 flag = cuddZddGetCofactors2(dd, f, v, &f1, &f0); 00648 if (flag == 1) 00649 return(NULL); 00650 Cudd_Ref(f1); 00651 Cudd_Ref(f0); 00652 flag = cuddZddGetCofactors2(dd, g, v, &g1, &g0); 00653 if (flag == 1) { 00654 Cudd_RecursiveDerefZdd(dd, f1); 00655 Cudd_RecursiveDerefZdd(dd, f0); 00656 return(NULL); 00657 } 00658 Cudd_Ref(g1); 00659 Cudd_Ref(g0); 00660 00661 term1 = cuddZddUnateProduct(dd, f1, g1); 00662 if (term1 == NULL) { 00663 Cudd_RecursiveDerefZdd(dd, f1); 00664 Cudd_RecursiveDerefZdd(dd, f0); 00665 Cudd_RecursiveDerefZdd(dd, g1); 00666 Cudd_RecursiveDerefZdd(dd, g0); 00667 return(NULL); 00668 } 00669 Cudd_Ref(term1); 00670 term2 = cuddZddUnateProduct(dd, f1, g0); 00671 if (term2 == NULL) { 00672 Cudd_RecursiveDerefZdd(dd, f1); 00673 Cudd_RecursiveDerefZdd(dd, f0); 00674 Cudd_RecursiveDerefZdd(dd, g1); 00675 Cudd_RecursiveDerefZdd(dd, g0); 00676 Cudd_RecursiveDerefZdd(dd, term1); 00677 return(NULL); 00678 } 00679 Cudd_Ref(term2); 00680 term3 = cuddZddUnateProduct(dd, f0, g1); 00681 if (term3 == NULL) { 00682 Cudd_RecursiveDerefZdd(dd, f1); 00683 Cudd_RecursiveDerefZdd(dd, f0); 00684 Cudd_RecursiveDerefZdd(dd, g1); 00685 Cudd_RecursiveDerefZdd(dd, g0); 00686 Cudd_RecursiveDerefZdd(dd, term1); 00687 Cudd_RecursiveDerefZdd(dd, term2); 00688 return(NULL); 00689 } 00690 Cudd_Ref(term3); 00691 term4 = cuddZddUnateProduct(dd, f0, g0); 00692 if (term4 == NULL) { 00693 Cudd_RecursiveDerefZdd(dd, f1); 00694 Cudd_RecursiveDerefZdd(dd, f0); 00695 Cudd_RecursiveDerefZdd(dd, g1); 00696 Cudd_RecursiveDerefZdd(dd, g0); 00697 Cudd_RecursiveDerefZdd(dd, term1); 00698 Cudd_RecursiveDerefZdd(dd, term2); 00699 Cudd_RecursiveDerefZdd(dd, term3); 00700 return(NULL); 00701 } 00702 Cudd_Ref(term4); 00703 Cudd_RecursiveDerefZdd(dd, f1); 00704 Cudd_RecursiveDerefZdd(dd, f0); 00705 Cudd_RecursiveDerefZdd(dd, g1); 00706 Cudd_RecursiveDerefZdd(dd, g0); 00707 sum1 = cuddZddUnion(dd, term1, term2); 00708 if (sum1 == NULL) { 00709 Cudd_RecursiveDerefZdd(dd, term1); 00710 Cudd_RecursiveDerefZdd(dd, term2); 00711 Cudd_RecursiveDerefZdd(dd, term3); 00712 Cudd_RecursiveDerefZdd(dd, term4); 00713 return(NULL); 00714 } 00715 Cudd_Ref(sum1); 00716 Cudd_RecursiveDerefZdd(dd, term1); 00717 Cudd_RecursiveDerefZdd(dd, term2); 00718 sum2 = cuddZddUnion(dd, sum1, term3); 00719 if (sum2 == NULL) { 00720 Cudd_RecursiveDerefZdd(dd, term3); 00721 Cudd_RecursiveDerefZdd(dd, term4); 00722 Cudd_RecursiveDerefZdd(dd, sum1); 00723 return(NULL); 00724 } 00725 Cudd_Ref(sum2); 00726 Cudd_RecursiveDerefZdd(dd, sum1); 00727 Cudd_RecursiveDerefZdd(dd, term3); 00728 r = cuddZddGetNode(dd, v, sum2, term4); 00729 if (r == NULL) { 00730 Cudd_RecursiveDerefZdd(dd, term4); 00731 Cudd_RecursiveDerefZdd(dd, sum2); 00732 return(NULL); 00733 } 00734 Cudd_Ref(r); 00735 Cudd_RecursiveDerefZdd(dd, sum2); 00736 Cudd_RecursiveDerefZdd(dd, term4); 00737 00738 cuddCacheInsert2(dd, cuddZddUnateProduct, f, g, r); 00739 Cudd_Deref(r); 00740 return(r); 00741 00742 } /* end of cuddZddUnateProduct */
Function********************************************************************
Synopsis [Performs the recursive step of Cudd_zddUnion.]
Description []
SideEffects [None]
SeeAlso []
Definition at line 549 of file cuddZddSetop.c.
00553 { 00554 int p_top, q_top; 00555 DdNode *empty = DD_ZERO(zdd), *t, *e, *res; 00556 DdManager *table = zdd; 00557 00558 statLine(zdd); 00559 if (P == empty) 00560 return(Q); 00561 if (Q == empty) 00562 return(P); 00563 if (P == Q) 00564 return(P); 00565 00566 /* Check cache */ 00567 res = cuddCacheLookup2Zdd(table, cuddZddUnion, P, Q); 00568 if (res != NULL) 00569 return(res); 00570 00571 if (cuddIsConstant(P)) 00572 p_top = P->index; 00573 else 00574 p_top = zdd->permZ[P->index]; 00575 if (cuddIsConstant(Q)) 00576 q_top = Q->index; 00577 else 00578 q_top = zdd->permZ[Q->index]; 00579 if (p_top < q_top) { 00580 e = cuddZddUnion(zdd, cuddE(P), Q); 00581 if (e == NULL) return (NULL); 00582 cuddRef(e); 00583 res = cuddZddGetNode(zdd, P->index, cuddT(P), e); 00584 if (res == NULL) { 00585 Cudd_RecursiveDerefZdd(table, e); 00586 return(NULL); 00587 } 00588 cuddDeref(e); 00589 } else if (p_top > q_top) { 00590 e = cuddZddUnion(zdd, P, cuddE(Q)); 00591 if (e == NULL) return(NULL); 00592 cuddRef(e); 00593 res = cuddZddGetNode(zdd, Q->index, cuddT(Q), e); 00594 if (res == NULL) { 00595 Cudd_RecursiveDerefZdd(table, e); 00596 return(NULL); 00597 } 00598 cuddDeref(e); 00599 } else { 00600 t = cuddZddUnion(zdd, cuddT(P), cuddT(Q)); 00601 if (t == NULL) return(NULL); 00602 cuddRef(t); 00603 e = cuddZddUnion(zdd, cuddE(P), cuddE(Q)); 00604 if (e == NULL) { 00605 Cudd_RecursiveDerefZdd(table, t); 00606 return(NULL); 00607 } 00608 cuddRef(e); 00609 res = cuddZddGetNode(zdd, P->index, t, e); 00610 if (res == NULL) { 00611 Cudd_RecursiveDerefZdd(table, t); 00612 Cudd_RecursiveDerefZdd(table, e); 00613 return(NULL); 00614 } 00615 cuddDeref(t); 00616 cuddDeref(e); 00617 } 00618 00619 cuddCacheInsert2(table, cuddZddUnion, P, Q, res); 00620 00621 return(res); 00622 00623 } /* end of cuddZddUnion */
int cuddZddUniqueCompare | ( | int * | ptr_x, | |
int * | ptr_y | |||
) |
Function********************************************************************
Synopsis [Comparison function used by qsort.]
Description [Comparison function used by qsort to order the variables according to the number of keys in the subtables. Returns the difference in number of keys between the two variables being compared.]
SideEffects [None]
SeeAlso []
Definition at line 455 of file cuddZddReord.c.
Function********************************************************************
Synopsis [Performs the recursive step of Cudd_zddWeakDiv.]
Description []
SideEffects [None]
SeeAlso [Cudd_zddWeakDiv]
Definition at line 757 of file cuddZddFuncs.c.
00761 { 00762 int v; 00763 DdNode *one = DD_ONE(dd); 00764 DdNode *zero = DD_ZERO(dd); 00765 DdNode *f0, *f1, *fd, *g0, *g1, *gd; 00766 DdNode *q, *tmp; 00767 DdNode *r; 00768 int flag; 00769 00770 statLine(dd); 00771 if (g == one) 00772 return(f); 00773 if (f == zero || f == one) 00774 return(zero); 00775 if (f == g) 00776 return(one); 00777 00778 /* Check cache. */ 00779 r = cuddCacheLookup2Zdd(dd, cuddZddWeakDiv, f, g); 00780 if (r) 00781 return(r); 00782 00783 v = g->index; 00784 00785 flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd); 00786 if (flag == 1) 00787 return(NULL); 00788 Cudd_Ref(f1); 00789 Cudd_Ref(f0); 00790 Cudd_Ref(fd); 00791 flag = cuddZddGetCofactors3(dd, g, v, &g1, &g0, &gd); 00792 if (flag == 1) { 00793 Cudd_RecursiveDerefZdd(dd, f1); 00794 Cudd_RecursiveDerefZdd(dd, f0); 00795 Cudd_RecursiveDerefZdd(dd, fd); 00796 return(NULL); 00797 } 00798 Cudd_Ref(g1); 00799 Cudd_Ref(g0); 00800 Cudd_Ref(gd); 00801 00802 q = g; 00803 00804 if (g0 != zero) { 00805 q = cuddZddWeakDiv(dd, f0, g0); 00806 if (q == NULL) { 00807 Cudd_RecursiveDerefZdd(dd, f1); 00808 Cudd_RecursiveDerefZdd(dd, f0); 00809 Cudd_RecursiveDerefZdd(dd, fd); 00810 Cudd_RecursiveDerefZdd(dd, g1); 00811 Cudd_RecursiveDerefZdd(dd, g0); 00812 Cudd_RecursiveDerefZdd(dd, gd); 00813 return(NULL); 00814 } 00815 Cudd_Ref(q); 00816 } 00817 else 00818 Cudd_Ref(q); 00819 Cudd_RecursiveDerefZdd(dd, f0); 00820 Cudd_RecursiveDerefZdd(dd, g0); 00821 00822 if (q == zero) { 00823 Cudd_RecursiveDerefZdd(dd, f1); 00824 Cudd_RecursiveDerefZdd(dd, g1); 00825 Cudd_RecursiveDerefZdd(dd, fd); 00826 Cudd_RecursiveDerefZdd(dd, gd); 00827 cuddCacheInsert2(dd, cuddZddWeakDiv, f, g, zero); 00828 Cudd_Deref(q); 00829 return(zero); 00830 } 00831 00832 if (g1 != zero) { 00833 Cudd_RecursiveDerefZdd(dd, q); 00834 tmp = cuddZddWeakDiv(dd, f1, g1); 00835 if (tmp == NULL) { 00836 Cudd_RecursiveDerefZdd(dd, f1); 00837 Cudd_RecursiveDerefZdd(dd, g1); 00838 Cudd_RecursiveDerefZdd(dd, fd); 00839 Cudd_RecursiveDerefZdd(dd, gd); 00840 return(NULL); 00841 } 00842 Cudd_Ref(tmp); 00843 Cudd_RecursiveDerefZdd(dd, f1); 00844 Cudd_RecursiveDerefZdd(dd, g1); 00845 if (q == g) 00846 q = tmp; 00847 else { 00848 q = cuddZddIntersect(dd, q, tmp); 00849 if (q == NULL) { 00850 Cudd_RecursiveDerefZdd(dd, fd); 00851 Cudd_RecursiveDerefZdd(dd, gd); 00852 return(NULL); 00853 } 00854 Cudd_Ref(q); 00855 Cudd_RecursiveDerefZdd(dd, tmp); 00856 } 00857 } 00858 else { 00859 Cudd_RecursiveDerefZdd(dd, f1); 00860 Cudd_RecursiveDerefZdd(dd, g1); 00861 } 00862 00863 if (q == zero) { 00864 Cudd_RecursiveDerefZdd(dd, fd); 00865 Cudd_RecursiveDerefZdd(dd, gd); 00866 cuddCacheInsert2(dd, cuddZddWeakDiv, f, g, zero); 00867 Cudd_Deref(q); 00868 return(zero); 00869 } 00870 00871 if (gd != zero) { 00872 Cudd_RecursiveDerefZdd(dd, q); 00873 tmp = cuddZddWeakDiv(dd, fd, gd); 00874 if (tmp == NULL) { 00875 Cudd_RecursiveDerefZdd(dd, fd); 00876 Cudd_RecursiveDerefZdd(dd, gd); 00877 return(NULL); 00878 } 00879 Cudd_Ref(tmp); 00880 Cudd_RecursiveDerefZdd(dd, fd); 00881 Cudd_RecursiveDerefZdd(dd, gd); 00882 if (q == g) 00883 q = tmp; 00884 else { 00885 q = cuddZddIntersect(dd, q, tmp); 00886 if (q == NULL) { 00887 Cudd_RecursiveDerefZdd(dd, tmp); 00888 return(NULL); 00889 } 00890 Cudd_Ref(q); 00891 Cudd_RecursiveDerefZdd(dd, tmp); 00892 } 00893 } 00894 else { 00895 Cudd_RecursiveDerefZdd(dd, fd); 00896 Cudd_RecursiveDerefZdd(dd, gd); 00897 } 00898 00899 cuddCacheInsert2(dd, cuddZddWeakDiv, f, g, q); 00900 Cudd_Deref(q); 00901 return(q); 00902 00903 } /* end of cuddZddWeakDiv */
Function********************************************************************
Synopsis [Performs the recursive step of Cudd_zddWeakDivF.]
Description []
SideEffects [None]
SeeAlso [Cudd_zddWeakDivF]
Definition at line 918 of file cuddZddFuncs.c.
00922 { 00923 int v, top_f, top_g, vf, vg; 00924 DdNode *one = DD_ONE(dd); 00925 DdNode *zero = DD_ZERO(dd); 00926 DdNode *f0, *f1, *fd, *g0, *g1, *gd; 00927 DdNode *q, *tmp; 00928 DdNode *r; 00929 DdNode *term1, *term0, *termd; 00930 int flag; 00931 int pv, nv; 00932 00933 statLine(dd); 00934 if (g == one) 00935 return(f); 00936 if (f == zero || f == one) 00937 return(zero); 00938 if (f == g) 00939 return(one); 00940 00941 /* Check cache. */ 00942 r = cuddCacheLookup2Zdd(dd, cuddZddWeakDivF, f, g); 00943 if (r) 00944 return(r); 00945 00946 top_f = dd->permZ[f->index]; 00947 top_g = dd->permZ[g->index]; 00948 vf = top_f >> 1; 00949 vg = top_g >> 1; 00950 v = ddMin(top_f, top_g); 00951 00952 if (v == top_f && vf < vg) { 00953 v = f->index; 00954 flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd); 00955 if (flag == 1) 00956 return(NULL); 00957 Cudd_Ref(f1); 00958 Cudd_Ref(f0); 00959 Cudd_Ref(fd); 00960 00961 pv = cuddZddGetPosVarIndex(dd, v); 00962 nv = cuddZddGetNegVarIndex(dd, v); 00963 00964 term1 = cuddZddWeakDivF(dd, f1, g); 00965 if (term1 == NULL) { 00966 Cudd_RecursiveDerefZdd(dd, f1); 00967 Cudd_RecursiveDerefZdd(dd, f0); 00968 Cudd_RecursiveDerefZdd(dd, fd); 00969 return(NULL); 00970 } 00971 Cudd_Ref(term1); 00972 Cudd_RecursiveDerefZdd(dd, f1); 00973 term0 = cuddZddWeakDivF(dd, f0, g); 00974 if (term0 == NULL) { 00975 Cudd_RecursiveDerefZdd(dd, f0); 00976 Cudd_RecursiveDerefZdd(dd, fd); 00977 Cudd_RecursiveDerefZdd(dd, term1); 00978 return(NULL); 00979 } 00980 Cudd_Ref(term0); 00981 Cudd_RecursiveDerefZdd(dd, f0); 00982 termd = cuddZddWeakDivF(dd, fd, g); 00983 if (termd == NULL) { 00984 Cudd_RecursiveDerefZdd(dd, fd); 00985 Cudd_RecursiveDerefZdd(dd, term1); 00986 Cudd_RecursiveDerefZdd(dd, term0); 00987 return(NULL); 00988 } 00989 Cudd_Ref(termd); 00990 Cudd_RecursiveDerefZdd(dd, fd); 00991 00992 tmp = cuddZddGetNode(dd, nv, term0, termd); /* nv = zi */ 00993 if (tmp == NULL) { 00994 Cudd_RecursiveDerefZdd(dd, term1); 00995 Cudd_RecursiveDerefZdd(dd, term0); 00996 Cudd_RecursiveDerefZdd(dd, termd); 00997 return(NULL); 00998 } 00999 Cudd_Ref(tmp); 01000 Cudd_RecursiveDerefZdd(dd, term0); 01001 Cudd_RecursiveDerefZdd(dd, termd); 01002 q = cuddZddGetNode(dd, pv, term1, tmp); /* pv = yi */ 01003 if (q == NULL) { 01004 Cudd_RecursiveDerefZdd(dd, term1); 01005 Cudd_RecursiveDerefZdd(dd, tmp); 01006 return(NULL); 01007 } 01008 Cudd_Ref(q); 01009 Cudd_RecursiveDerefZdd(dd, term1); 01010 Cudd_RecursiveDerefZdd(dd, tmp); 01011 01012 cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, q); 01013 Cudd_Deref(q); 01014 return(q); 01015 } 01016 01017 if (v == top_f) 01018 v = f->index; 01019 else 01020 v = g->index; 01021 01022 flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd); 01023 if (flag == 1) 01024 return(NULL); 01025 Cudd_Ref(f1); 01026 Cudd_Ref(f0); 01027 Cudd_Ref(fd); 01028 flag = cuddZddGetCofactors3(dd, g, v, &g1, &g0, &gd); 01029 if (flag == 1) { 01030 Cudd_RecursiveDerefZdd(dd, f1); 01031 Cudd_RecursiveDerefZdd(dd, f0); 01032 Cudd_RecursiveDerefZdd(dd, fd); 01033 return(NULL); 01034 } 01035 Cudd_Ref(g1); 01036 Cudd_Ref(g0); 01037 Cudd_Ref(gd); 01038 01039 q = g; 01040 01041 if (g0 != zero) { 01042 q = cuddZddWeakDivF(dd, f0, g0); 01043 if (q == NULL) { 01044 Cudd_RecursiveDerefZdd(dd, f1); 01045 Cudd_RecursiveDerefZdd(dd, f0); 01046 Cudd_RecursiveDerefZdd(dd, fd); 01047 Cudd_RecursiveDerefZdd(dd, g1); 01048 Cudd_RecursiveDerefZdd(dd, g0); 01049 Cudd_RecursiveDerefZdd(dd, gd); 01050 return(NULL); 01051 } 01052 Cudd_Ref(q); 01053 } 01054 else 01055 Cudd_Ref(q); 01056 Cudd_RecursiveDerefZdd(dd, f0); 01057 Cudd_RecursiveDerefZdd(dd, g0); 01058 01059 if (q == zero) { 01060 Cudd_RecursiveDerefZdd(dd, f1); 01061 Cudd_RecursiveDerefZdd(dd, g1); 01062 Cudd_RecursiveDerefZdd(dd, fd); 01063 Cudd_RecursiveDerefZdd(dd, gd); 01064 cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, zero); 01065 Cudd_Deref(q); 01066 return(zero); 01067 } 01068 01069 if (g1 != zero) { 01070 Cudd_RecursiveDerefZdd(dd, q); 01071 tmp = cuddZddWeakDivF(dd, f1, g1); 01072 if (tmp == NULL) { 01073 Cudd_RecursiveDerefZdd(dd, f1); 01074 Cudd_RecursiveDerefZdd(dd, g1); 01075 Cudd_RecursiveDerefZdd(dd, fd); 01076 Cudd_RecursiveDerefZdd(dd, gd); 01077 return(NULL); 01078 } 01079 Cudd_Ref(tmp); 01080 Cudd_RecursiveDerefZdd(dd, f1); 01081 Cudd_RecursiveDerefZdd(dd, g1); 01082 if (q == g) 01083 q = tmp; 01084 else { 01085 q = cuddZddIntersect(dd, q, tmp); 01086 if (q == NULL) { 01087 Cudd_RecursiveDerefZdd(dd, fd); 01088 Cudd_RecursiveDerefZdd(dd, gd); 01089 return(NULL); 01090 } 01091 Cudd_Ref(q); 01092 Cudd_RecursiveDerefZdd(dd, tmp); 01093 } 01094 } 01095 else { 01096 Cudd_RecursiveDerefZdd(dd, f1); 01097 Cudd_RecursiveDerefZdd(dd, g1); 01098 } 01099 01100 if (q == zero) { 01101 Cudd_RecursiveDerefZdd(dd, fd); 01102 Cudd_RecursiveDerefZdd(dd, gd); 01103 cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, zero); 01104 Cudd_Deref(q); 01105 return(zero); 01106 } 01107 01108 if (gd != zero) { 01109 Cudd_RecursiveDerefZdd(dd, q); 01110 tmp = cuddZddWeakDivF(dd, fd, gd); 01111 if (tmp == NULL) { 01112 Cudd_RecursiveDerefZdd(dd, fd); 01113 Cudd_RecursiveDerefZdd(dd, gd); 01114 return(NULL); 01115 } 01116 Cudd_Ref(tmp); 01117 Cudd_RecursiveDerefZdd(dd, fd); 01118 Cudd_RecursiveDerefZdd(dd, gd); 01119 if (q == g) 01120 q = tmp; 01121 else { 01122 q = cuddZddIntersect(dd, q, tmp); 01123 if (q == NULL) { 01124 Cudd_RecursiveDerefZdd(dd, tmp); 01125 return(NULL); 01126 } 01127 Cudd_Ref(q); 01128 Cudd_RecursiveDerefZdd(dd, tmp); 01129 } 01130 } 01131 else { 01132 Cudd_RecursiveDerefZdd(dd, fd); 01133 Cudd_RecursiveDerefZdd(dd, gd); 01134 } 01135 01136 cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, q); 01137 Cudd_Deref(q); 01138 return(q); 01139 01140 } /* end of cuddZddWeakDivF */