/**Function******************************************************************** Synopsis [Computes a complement cover for a ZDD node.] Description [Computes a complement cover for a ZDD node. For lack of a better method, we first extract the function BDD from the ZDD cover, then make the complement of the ZDD cover from the complement of the BDD node by using ISOP. Returns a pointer to the resulting cover if successful; NULL otherwise. The result depends on current variable order.] SideEffects [The result depends on current variable order.] SeeAlso [] ******************************************************************************/ DdNode * Cudd_zddComplement( DdManager *dd, DdNode *node) { DdNode *b, *isop, *zdd_I; /* Check cache */ zdd_I = cuddCacheLookup1Zdd(dd, cuddZddComplement, node); if (zdd_I) return(zdd_I); b = Cudd_MakeBddFromZddCover(dd, node); if (!b) return(NULL); Cudd_Ref(b); isop = Cudd_zddIsop(dd, Cudd_Not(b), Cudd_Not(b), &zdd_I); if (!isop) { Cudd_RecursiveDeref(dd, b); return(NULL); } Cudd_Ref(isop); Cudd_Ref(zdd_I); Cudd_RecursiveDeref(dd, b); Cudd_RecursiveDeref(dd, isop); cuddCacheInsert1(dd, cuddZddComplement, node, zdd_I); Cudd_Deref(zdd_I); return(zdd_I); } /* end of Cudd_zddComplement */
/**Function******************************************************************** Synopsis [Performs the recursive step of Extra_zddSelectOneSubset.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode * extraZddSelectOneSubset( DdManager * dd, DdNode * zS ) // selects one subset from the ZDD zS // returns z0 if and only if zS is an empty set of cubes { DdNode * zRes; if ( zS == z0 ) return z0; if ( zS == z1 ) return z1; // check cache if ( (zRes = cuddCacheLookup1Zdd( dd, extraZddSelectOneSubset, zS )) ) return zRes; else { DdNode * zS0, * zS1, * zTemp; zS0 = cuddE(zS); zS1 = cuddT(zS); if ( zS0 != z0 ) { zRes = extraZddSelectOneSubset( dd, zS0 ); if ( zRes == NULL ) return NULL; } else // if ( zS0 == z0 ) { assert( zS1 != z0 ); zRes = extraZddSelectOneSubset( dd, zS1 ); if ( zRes == NULL ) return NULL; cuddRef( zRes ); zRes = cuddZddGetNode( dd, zS->index, zTemp = zRes, z0 ); if ( zRes == NULL ) { Cudd_RecursiveDerefZdd( dd, zTemp ); return NULL; } cuddDeref( zTemp ); } // insert the result into cache cuddCacheInsert1( dd, extraZddSelectOneSubset, zS, zRes ); return zRes; } } /* end of extraZddSelectOneSubset */
/**Function******************************************************************** Synopsis [Performs a recursive step of Extra_zddGetSingletons.] Description [Returns the set of ZDD singletons, containing those positive polarity ZDD variables that correspond to the BDD variables in bVars.] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode * extraZddGetSingletons( DdManager * dd, /* the DD manager */ DdNode * bVars) /* the set of variables */ { DdNode * zRes; if ( bVars == b1 ) // if ( bVars == b0 ) // bug fixed by Jin Zhang, Jan 23, 2004 return z1; if ( (zRes = cuddCacheLookup1Zdd(dd, extraZddGetSingletons, bVars)) ) return zRes; else { DdNode * zTemp, * zPlus; // solve subproblem zRes = extraZddGetSingletons( dd, cuddT(bVars) ); if ( zRes == NULL ) return NULL; cuddRef( zRes ); zPlus = cuddZddGetNode( dd, 2*bVars->index, z1, z0 ); if ( zPlus == NULL ) { Cudd_RecursiveDerefZdd( dd, zRes ); return NULL; } cuddRef( zPlus ); // add these to the result zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); if ( zRes == NULL ) { Cudd_RecursiveDerefZdd( dd, zTemp ); Cudd_RecursiveDerefZdd( dd, zPlus ); return NULL; } cuddRef( zRes ); Cudd_RecursiveDerefZdd( dd, zTemp ); Cudd_RecursiveDerefZdd( dd, zPlus ); cuddDeref( zRes ); cuddCacheInsert1( dd, extraZddGetSingletons, bVars, zRes ); return zRes; } } /* end of extraZddGetSingletons */
/**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_zddPortFromBdd.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ static DdNode * zddPortFromBddStep( DdManager * dd, DdNode * B, int expected) { DdNode *res, *prevZdd, *t, *e; DdNode *Breg, *Bt, *Be; int id, level; statLine(dd); /* Terminal cases. */ if (B == Cudd_Not(DD_ONE(dd))) return(DD_ZERO(dd)); if (B == DD_ONE(dd)) { if (expected >= dd->sizeZ) { return(DD_ONE(dd)); } else { return(dd->univ[expected]); } } Breg = Cudd_Regular(B); /* Computed table look-up. */ res = cuddCacheLookup1Zdd(dd,Cudd_zddPortFromBdd,B); if (res != NULL) { level = cuddI(dd,Breg->index); /* Adding DC vars. */ if (expected < level) { /* Add suppressed variables. */ cuddRef(res); for (level--; level >= expected; level--) { prevZdd = res; id = dd->invperm[level]; res = cuddZddGetNode(dd, id, prevZdd, prevZdd); if (res == NULL) { Cudd_RecursiveDerefZdd(dd, prevZdd); return(NULL); } cuddRef(res); Cudd_RecursiveDerefZdd(dd, prevZdd); } cuddDeref(res); } return(res); } /* end of cache look-up */ if (Cudd_IsComplement(B)) { Bt = Cudd_Not(cuddT(Breg)); Be = Cudd_Not(cuddE(Breg)); } else { Bt = cuddT(Breg); Be = cuddE(Breg); } id = Breg->index; level = cuddI(dd,id); t = zddPortFromBddStep(dd, Bt, level+1); if (t == NULL) return(NULL); cuddRef(t); e = zddPortFromBddStep(dd, Be, level+1); if (e == NULL) { Cudd_RecursiveDerefZdd(dd, t); return(NULL); } cuddRef(e); res = cuddZddGetNode(dd, id, t, e); if (res == NULL) { Cudd_RecursiveDerefZdd(dd, t); Cudd_RecursiveDerefZdd(dd, e); return(NULL); } cuddRef(res); Cudd_RecursiveDerefZdd(dd, t); Cudd_RecursiveDerefZdd(dd, e); cuddCacheInsert1(dd,Cudd_zddPortFromBdd,B,res); for (level--; level >= expected; level--) { prevZdd = res; id = dd->invperm[level]; res = cuddZddGetNode(dd, id, prevZdd, prevZdd); if (res == NULL) { Cudd_RecursiveDerefZdd(dd, prevZdd); return(NULL); } cuddRef(res); Cudd_RecursiveDerefZdd(dd, prevZdd); } cuddDeref(res); return(res); } /* end of zddPortFromBddStep */
/**Function************************************************************* Synopsis [Performs the recursive step of Extra_bddSpaceEquationsNev().] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * extraBddSpaceEquationsNeg( DdManager * dd, DdNode * bF ) { DdNode * zRes; statLine( dd ); if ( bF == b0 ) return z1; if ( bF == b1 ) return z0; if ( (zRes = cuddCacheLookup1Zdd(dd, extraBddSpaceEquationsNeg, bF)) ) return zRes; else { DdNode * bFR, * bF0, * bF1; DdNode * zPos0, * zPos1, * zNeg1; DdNode * zRes, * zRes0, * zRes1; bFR = Cudd_Regular(bF); if ( bFR != bF ) // bF is complemented { bF0 = Cudd_Not( cuddE(bFR) ); bF1 = Cudd_Not( cuddT(bFR) ); } else { bF0 = cuddE(bFR); bF1 = cuddT(bFR); } if ( bF0 == b0 ) { zRes = extraBddSpaceEquationsNeg( dd, bF1 ); if ( zRes == NULL ) return NULL; } else if ( bF1 == b0 ) { zRes0 = extraBddSpaceEquationsNeg( dd, bF0 ); if ( zRes0 == NULL ) return NULL; cuddRef( zRes0 ); // add the current element to the set zRes = cuddZddGetNode( dd, 2*bFR->index, z1, zRes0 ); if ( zRes == NULL ) { Cudd_RecursiveDerefZdd(dd, zRes0); return NULL; } cuddDeref( zRes0 ); } else { zPos0 = extraBddSpaceEquationsNeg( dd, bF0 ); if ( zPos0 == NULL ) return NULL; cuddRef( zPos0 ); zPos1 = extraBddSpaceEquationsNeg( dd, bF1 ); if ( zPos1 == NULL ) { Cudd_RecursiveDerefZdd(dd, zPos0); return NULL; } cuddRef( zPos1 ); zNeg1 = extraBddSpaceEquationsPos( dd, bF1 ); if ( zNeg1 == NULL ) { Cudd_RecursiveDerefZdd(dd, zPos0); Cudd_RecursiveDerefZdd(dd, zPos1); return NULL; } cuddRef( zNeg1 ); zRes0 = cuddZddIntersect( dd, zPos0, zPos1 ); if ( zRes0 == NULL ) { Cudd_RecursiveDerefZdd(dd, zNeg1); Cudd_RecursiveDerefZdd(dd, zPos0); Cudd_RecursiveDerefZdd(dd, zPos1); return NULL; } cuddRef( zRes0 ); zRes1 = cuddZddIntersect( dd, zPos0, zNeg1 ); if ( zRes1 == NULL ) { Cudd_RecursiveDerefZdd(dd, zRes0); Cudd_RecursiveDerefZdd(dd, zNeg1); Cudd_RecursiveDerefZdd(dd, zPos0); Cudd_RecursiveDerefZdd(dd, zPos1); return NULL; } cuddRef( zRes1 ); Cudd_RecursiveDerefZdd(dd, zNeg1); Cudd_RecursiveDerefZdd(dd, zPos0); Cudd_RecursiveDerefZdd(dd, zPos1); // only zRes0 and zRes1 are refed at this point zRes = cuddZddGetNode( dd, 2*bFR->index, zRes1, zRes0 ); if ( zRes == NULL ) { Cudd_RecursiveDerefZdd(dd, zRes0); Cudd_RecursiveDerefZdd(dd, zRes1); return NULL; } cuddDeref( zRes0 ); cuddDeref( zRes1 ); } cuddCacheInsert1( dd, extraBddSpaceEquationsNeg, bF, zRes ); return zRes; } }