/**Function************************************************************* Synopsis [Derives the truth table for one cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Fpga_TruthsCutBdd( void * dd, Fpga_Cut_t * pCut ) { Fpga_NodeVec_t * vVisited; DdNode * bFunc; int i; assert( pCut->nLeaves > 1 ); // set the leaf variables for ( i = 0; i < pCut->nLeaves; i++ ) pCut->ppLeaves[i]->pCuts->uSign = (unsigned)Cudd_bddIthVar( dd, i ); // recursively compute the function vVisited = Fpga_NodeVecAlloc( 10 ); bFunc = Fpga_TruthsCutBdd_rec( dd, pCut, vVisited ); Cudd_Ref( bFunc ); // clean the intermediate BDDs for ( i = 0; i < pCut->nLeaves; i++ ) pCut->ppLeaves[i]->pCuts->uSign = 0; for ( i = 0; i < vVisited->nSize; i++ ) { pCut = (Fpga_Cut_t *)vVisited->pArray[i]; Cudd_RecursiveDeref( dd, (DdNode*)pCut->uSign ); pCut->uSign = 0; } // printf( "%d ", vVisited->nSize ); Fpga_NodeVecFree( vVisited ); Cudd_Deref( bFunc ); return bFunc; }
/**Function************************************************************* Synopsis [Performs reordering of the function.] Description [Returns the DD minimized by variable reordering in the REO engine. Takes the CUDD decision diagram manager (dd) and the function (Func) represented as a BDD or ADD (MTBDD). If the variable array (pOrder) is not NULL, returns the resulting variable permutation. The permutation is such that if the resulting function is permuted by Cudd_(add,bdd)Permute() using pOrder as the permutation array, the initial function (Func) results. Several flag set by other interface functions specify reordering options: - Remappig can be set by Extra_ReorderSetRemapping(). Then the resulting DD after reordering is remapped into the topmost levels of the DD manager. Otherwise, the resulting DD after reordering is mapped using the same variables, on which it originally depended, only (possibly) permuted as a result of reordering. - Minimization type can be set by Extra_ReorderSetMinimizationType(). Note that when the BDD is minimized for the total width of the total APL, the number BDD nodes can increase. The total width is defines as sum total of widths on each level. The width on one level is defined as the number of distinct BDD nodes pointed by the nodes situated above the given level. - The number of iterations of sifting can be set by Extra_ReorderSetIterations(). The decision diagram returned by this procedure is not referenced.] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Extra_Reorder( reo_man * p, DdManager * dd, DdNode * Func, int * pOrder ) { DdNode * FuncRes; Extra_ReorderArray( p, dd, &Func, &FuncRes, 1, pOrder ); Cudd_Deref( FuncRes ); return FuncRes; }
/**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 [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * dsdTreeGetPrimeFunction( DdManager * dd, Dsd_Node_t * pNode, int fRemap ) { DdNode * bCof0, * bCof1, * bCube0, * bCube1, * bNewFunc, * bTemp; int i; int fAllBuffs = 1; static int Permute[MAXINPUTS]; assert( pNode ); assert( !Dsd_IsComplement( pNode ) ); assert( pNode->Type == DT_PRIME ); // transform the function of this block to depend on inputs // corresponding to the formal inputs // first, substitute those inputs that have some blocks associated with them // second, remap the inputs to the top of the manager (then, it is easy to output them) // start the function bNewFunc = pNode->G; Cudd_Ref( bNewFunc ); // go over all primary inputs for ( i = 0; i < pNode->nDecs; i++ ) if ( pNode->pDecs[i]->Type != DT_BUF ) // remap only if it is not the buffer { bCube0 = Extra_bddFindOneCube( dd, Cudd_Not(pNode->pDecs[i]->G) ); Cudd_Ref( bCube0 ); bCof0 = Cudd_Cofactor( dd, bNewFunc, bCube0 ); Cudd_Ref( bCof0 ); Cudd_RecursiveDeref( dd, bCube0 ); bCube1 = Extra_bddFindOneCube( dd, pNode->pDecs[i]->G ); Cudd_Ref( bCube1 ); bCof1 = Cudd_Cofactor( dd, bNewFunc, bCube1 ); Cudd_Ref( bCof1 ); Cudd_RecursiveDeref( dd, bCube1 ); Cudd_RecursiveDeref( dd, bNewFunc ); // use the variable in the i-th level of the manager // bNewFunc = Cudd_bddIte( dd, dd->vars[dd->invperm[i]],bCof1,bCof0 ); Cudd_Ref( bNewFunc ); // use the first variale in the support of the component bNewFunc = Cudd_bddIte( dd, dd->vars[pNode->pDecs[i]->S->index],bCof1,bCof0 ); Cudd_Ref( bNewFunc ); Cudd_RecursiveDeref( dd, bCof0 ); Cudd_RecursiveDeref( dd, bCof1 ); } if ( fRemap ) { // remap the function to the top of the manager // remap the function to the first variables of the manager for ( i = 0; i < pNode->nDecs; i++ ) // Permute[ pNode->pDecs[i]->S->index ] = dd->invperm[i]; Permute[ pNode->pDecs[i]->S->index ] = i; bNewFunc = Cudd_bddPermute( dd, bTemp = bNewFunc, Permute ); Cudd_Ref( bNewFunc ); Cudd_RecursiveDeref( dd, bTemp ); } Cudd_Deref( bNewFunc ); return bNewFunc; }
/**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Extra_bddSpaceReduce( DdManager * dd, DdNode * bFunc, DdNode * bCanonVars ) { DdNode * bNegCube; DdNode * bResult; bNegCube = Extra_bddSupportNegativeCube( dd, bCanonVars ); Cudd_Ref( bNegCube ); bResult = Cudd_Cofactor( dd, bFunc, bNegCube ); Cudd_Ref( bResult ); Cudd_RecursiveDeref( dd, bNegCube ); Cudd_Deref( bResult ); return bResult; }
/**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Extra_bddSpaceEquations( DdManager * dd, DdNode * bSpace ) { DdNode * zRes; DdNode * zEquPos; DdNode * zEquNeg; zEquPos = Extra_bddSpaceEquationsPos( dd, bSpace ); Cudd_Ref( zEquPos ); zEquNeg = Extra_bddSpaceEquationsNeg( dd, bSpace ); Cudd_Ref( zEquNeg ); zRes = Cudd_zddUnion( dd, zEquPos, zEquNeg ); Cudd_Ref( zRes ); Cudd_RecursiveDerefZdd( dd, zEquPos ); Cudd_RecursiveDerefZdd( dd, zEquNeg ); Cudd_Deref( zRes ); return zRes; }
/**Function************************************************************* Synopsis [Derives the global BDD for one AIG node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Bbr_NodeGlobalBdds_rec( DdManager * dd, Aig_Obj_t * pNode, int nBddSizeMax, int fDropInternal, ProgressBar * pProgress, int * pCounter, int fVerbose ) { DdNode * bFunc, * bFunc0, * bFunc1; assert( !Aig_IsComplement(pNode) ); if ( Cudd_ReadKeys(dd)-Cudd_ReadDead(dd) > (unsigned)nBddSizeMax ) { // Extra_ProgressBarStop( pProgress ); if ( fVerbose ) printf( "The number of live nodes reached %d.\n", nBddSizeMax ); fflush( stdout ); return NULL; } // if the result is available return if ( Aig_ObjGlobalBdd(pNode) == NULL ) { // compute the result for both branches bFunc0 = Bbr_NodeGlobalBdds_rec( dd, Aig_ObjFanin0(pNode), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); if ( bFunc0 == NULL ) return NULL; Cudd_Ref( bFunc0 ); bFunc1 = Bbr_NodeGlobalBdds_rec( dd, Aig_ObjFanin1(pNode), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); if ( bFunc1 == NULL ) return NULL; Cudd_Ref( bFunc1 ); bFunc0 = Cudd_NotCond( bFunc0, Aig_ObjFaninC0(pNode) ); bFunc1 = Cudd_NotCond( bFunc1, Aig_ObjFaninC1(pNode) ); // get the final result bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc ); Cudd_RecursiveDeref( dd, bFunc0 ); Cudd_RecursiveDeref( dd, bFunc1 ); // add the number of used nodes (*pCounter)++; // set the result assert( Aig_ObjGlobalBdd(pNode) == NULL ); Aig_ObjSetGlobalBdd( pNode, bFunc ); // increment the progress bar // if ( pProgress ) // Extra_ProgressBarUpdate( pProgress, *pCounter, NULL ); } // prepare the return value bFunc = Aig_ObjGlobalBdd(pNode); // dereference BDD at the node if ( --pNode->nRefs == 0 && fDropInternal ) { Cudd_Deref( bFunc ); Aig_ObjSetGlobalBdd( pNode, NULL ); } return bFunc; }
BFBdd BFBddManager::readBDDFromFile(const char *filename, std::vector<BFBdd> &vars) const { FILE *file = fopen (filename,"r"); if (file == NULL){ std::ostringstream os; os << "Error in BFBddManager::readBDDFromFile(const char *filename, std::vector<BFBdd> &vars) - Could not read a BDD from from file '" << filename << "'."; throw std::runtime_error(os.str().c_str()); } int *idMatcher = new int[vars.size()]; for (unsigned int i=0;i<vars.size();i++) { idMatcher[i] = vars[i].readNodeIndex(); } DdNode *node = Dddmp_cuddBddLoad(mgr, DDDMP_VAR_COMPOSEIDS, NULL, NULL, idMatcher, DDDMP_MODE_DEFAULT,NULL,file); fclose(file); delete[] idMatcher; Cudd_Deref(node); return BFBdd(this,node); }
/**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Abc_MvReadCube( DdManager * dd, char * pLine, int nVars ) { DdNode * bCube, * bVar, * bTemp; int i; bCube = Cudd_ReadOne(dd); Cudd_Ref( bCube ); for ( i = 0; i < nVars; i++ ) { if ( pLine[i] == '-' ) continue; else if ( pLine[i] == '0' ) // 0 bVar = Cudd_Not( Cudd_bddIthVar(dd, 29-i) ); else if ( pLine[i] == '1' ) // 1 bVar = Cudd_bddIthVar(dd, 29-i); else assert(0); bCube = Cudd_bddAnd( dd, bTemp = bCube, bVar ); Cudd_Ref( bCube ); Cudd_RecursiveDeref( dd, bTemp ); } Cudd_Deref( bCube ); return bCube; }
/**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Extra_dsdRemap( DdManager * dd, DdNode * bF, st_table * pCache, int * pVar2Form, int * pForm2Var, DdNode * pbCube0[], DdNode * pbCube1[] ) { DdNode * bFR, * bF0, * bF1; DdNode * bRes0, * bRes1, * bRes; int iForm; bFR = Cudd_Regular(bF); if ( cuddIsConstant(bFR) ) return bF; // check the hash-table if ( bFR->ref != 1 ) { if ( st_lookup( pCache, (char *)bF, (char **)&bRes ) ) return bRes; } // get the formal input iForm = pVar2Form[bFR->index]; // get the nodes pointed to by the cube bF0 = Extra_bddNodePointedByCube( dd, bF, pbCube0[iForm] ); bF1 = Extra_bddNodePointedByCube( dd, bF, pbCube1[iForm] ); // call recursively for these nodes bRes0 = Extra_dsdRemap( dd, bF0, pCache, pVar2Form, pForm2Var, pbCube0, pbCube1 ); Cudd_Ref( bRes0 ); bRes1 = Extra_dsdRemap( dd, bF1, pCache, pVar2Form, pForm2Var, pbCube0, pbCube1 ); Cudd_Ref( bRes1 ); // derive the result using ITE bRes = Cudd_bddIte( dd, dd->vars[ pForm2Var[iForm] ], bRes1, bRes0 ); Cudd_Ref( bRes ); Cudd_RecursiveDeref( dd, bRes0 ); Cudd_RecursiveDeref( dd, bRes1 ); // add to the hash table if ( bFR->ref != 1 ) st_insert( pCache, (char *)bF, (char *)bRes ); Cudd_Deref( bRes ); return bRes; }
/**Function******************************************************************** Synopsis [Calculates the product of two matrices represented as ADDs.] Description [Calculates the product of two matrices, A and B, represented as ADDs, using the CMU matrix by matrix multiplication procedure by Clarke et al.. Matrix A has x's as row variables and z's as column variables, while matrix B has z's as row variables and y's as column variables. Returns the pointer to the result if successful; NULL otherwise. The resulting matrix has x's as row variables and y's as column variables.] SideEffects [None] SeeAlso [Cudd_addMatrixMultiply] ******************************************************************************/ DdNode * Cudd_addTimesPlus( DdManager * dd, DdNode * A, DdNode * B, DdNode ** z, int nz) { DdNode *w, *cube, *tmp, *res; int i; tmp = Cudd_addApply(dd,Cudd_addTimes,A,B); if (tmp == NULL) return(NULL); Cudd_Ref(tmp); Cudd_Ref(cube = DD_ONE(dd)); for (i = nz-1; i >= 0; i--) { w = Cudd_addIte(dd,z[i],cube,DD_ZERO(dd)); if (w == NULL) { Cudd_RecursiveDeref(dd,tmp); return(NULL); } Cudd_Ref(w); Cudd_RecursiveDeref(dd,cube); cube = w; } res = Cudd_addExistAbstract(dd,tmp,cube); if (res == NULL) { Cudd_RecursiveDeref(dd,tmp); Cudd_RecursiveDeref(dd,cube); return(NULL); } Cudd_Ref(res); Cudd_RecursiveDeref(dd,cube); Cudd_RecursiveDeref(dd,tmp); Cudd_Deref(res); return(res); } /* end of Cudd_addTimesPlus */
/**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_zddWeakDiv.] Description [] SideEffects [None] SeeAlso [Cudd_zddWeakDiv] ******************************************************************************/ DdNode * cuddZddWeakDiv( DdManager * dd, DdNode * f, DdNode * g) { int v; DdNode *one = DD_ONE(dd); DdNode *zero = DD_ZERO(dd); DdNode *f0, *f1, *fd, *g0, *g1, *gd; DdNode *q, *tmp; DdNode *r; int flag; statLine(dd); if (g == one) return(f); if (f == zero || f == one) return(zero); if (f == g) return(one); /* Check cache. */ r = cuddCacheLookup2Zdd(dd, cuddZddWeakDiv, f, g); if (r) return(r); v = g->index; flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd); if (flag == 1) return(NULL); Cudd_Ref(f1); Cudd_Ref(f0); Cudd_Ref(fd); flag = cuddZddGetCofactors3(dd, g, v, &g1, &g0, &gd); if (flag == 1) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, fd); return(NULL); } Cudd_Ref(g1); Cudd_Ref(g0); Cudd_Ref(gd); q = g; if (g0 != zero) { q = cuddZddWeakDiv(dd, f0, g0); if (q == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, g0); Cudd_RecursiveDerefZdd(dd, gd); return(NULL); } Cudd_Ref(q); } else Cudd_Ref(q); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, g0); if (q == zero) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, gd); cuddCacheInsert2(dd, cuddZddWeakDiv, f, g, zero); Cudd_Deref(q); return(zero); } if (g1 != zero) { Cudd_RecursiveDerefZdd(dd, q); tmp = cuddZddWeakDiv(dd, f1, g1); if (tmp == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, gd); return(NULL); } Cudd_Ref(tmp); Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, g1); if (q == g) q = tmp; else { q = cuddZddIntersect(dd, q, tmp); if (q == NULL) { Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, gd); return(NULL); } Cudd_Ref(q); Cudd_RecursiveDerefZdd(dd, tmp); } } else { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, g1); } if (q == zero) { Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, gd); cuddCacheInsert2(dd, cuddZddWeakDiv, f, g, zero); Cudd_Deref(q); return(zero); } if (gd != zero) { Cudd_RecursiveDerefZdd(dd, q); tmp = cuddZddWeakDiv(dd, fd, gd); if (tmp == NULL) { Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, gd); return(NULL); } Cudd_Ref(tmp); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, gd); if (q == g) q = tmp; else { q = cuddZddIntersect(dd, q, tmp); if (q == NULL) { Cudd_RecursiveDerefZdd(dd, tmp); return(NULL); } Cudd_Ref(q); Cudd_RecursiveDerefZdd(dd, tmp); } } else { Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, gd); } cuddCacheInsert2(dd, cuddZddWeakDiv, f, g, q); Cudd_Deref(q); return(q); } /* end of cuddZddWeakDiv */
/**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] ******************************************************************************/ DdNode * cuddMakeBddFromZddCover( DdManager * dd, DdNode * node) { DdNode *neW; int v; DdNode *f1, *f0, *fd; DdNode *b1, *b0, *bd; DdNode *T, *E; statLine(dd); if (node == dd->one) return(dd->one); if (node == dd->zero) return(Cudd_Not(dd->one)); /* Check cache */ neW = cuddCacheLookup1(dd, cuddMakeBddFromZddCover, node); if (neW) return(neW); v = Cudd_Regular(node)->index; /* either yi or zi */ cuddZddGetCofactors3(dd, node, v, &f1, &f0, &fd); Cudd_Ref(f1); Cudd_Ref(f0); Cudd_Ref(fd); b1 = cuddMakeBddFromZddCover(dd, f1); if (!b1) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, fd); return(NULL); } Cudd_Ref(b1); b0 = cuddMakeBddFromZddCover(dd, f0); if (!b1) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDeref(dd, b1); return(NULL); } Cudd_Ref(b0); Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); if (fd != dd->zero) { bd = cuddMakeBddFromZddCover(dd, fd); if (!bd) { Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDeref(dd, b1); Cudd_RecursiveDeref(dd, b0); return(NULL); } Cudd_Ref(bd); Cudd_RecursiveDerefZdd(dd, fd); T = cuddBddAndRecur(dd, Cudd_Not(b1), Cudd_Not(bd)); if (!T) { Cudd_RecursiveDeref(dd, b1); Cudd_RecursiveDeref(dd, b0); Cudd_RecursiveDeref(dd, bd); return(NULL); } T = Cudd_NotCond(T, T != NULL); Cudd_Ref(T); Cudd_RecursiveDeref(dd, b1); E = cuddBddAndRecur(dd, Cudd_Not(b0), Cudd_Not(bd)); if (!E) { Cudd_RecursiveDeref(dd, b0); Cudd_RecursiveDeref(dd, bd); Cudd_RecursiveDeref(dd, T); return(NULL); } E = Cudd_NotCond(E, E != NULL); Cudd_Ref(E); Cudd_RecursiveDeref(dd, b0); Cudd_RecursiveDeref(dd, bd); } else { Cudd_RecursiveDerefZdd(dd, fd); T = b1; E = b0; } if (Cudd_IsComplement(T)) { neW = cuddUniqueInterIVO(dd, v / 2, Cudd_Not(T), Cudd_Not(E)); if (!neW) { Cudd_RecursiveDeref(dd, T); Cudd_RecursiveDeref(dd, E); return(NULL); } neW = Cudd_Not(neW); } else { neW = cuddUniqueInterIVO(dd, v / 2, T, E); if (!neW) { Cudd_RecursiveDeref(dd, T); Cudd_RecursiveDeref(dd, E); return(NULL); } } Cudd_Ref(neW); Cudd_RecursiveDeref(dd, T); Cudd_RecursiveDeref(dd, E); cuddCacheInsert1(dd, cuddMakeBddFromZddCover, node, neW); Cudd_Deref(neW); return(neW); } /* end of cuddMakeBddFromZddCover */
/**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_bddIsop.] Description [] SideEffects [None] SeeAlso [Cudd_bddIsop] ******************************************************************************/ DdNode * cuddBddIsop( DdManager * dd, DdNode * L, DdNode * U) { DdNode *one = DD_ONE(dd); DdNode *zero = Cudd_Not(one); int v, top_l, top_u; DdNode *Lsub0, *Usub0, *Lsub1, *Usub1, *Ld, *Ud; DdNode *Lsuper0, *Usuper0, *Lsuper1, *Usuper1; DdNode *Isub0, *Isub1, *Id; DdNode *x; DdNode *term0, *term1, *sum; DdNode *Lv, *Uv, *Lnv, *Unv; DdNode *r; int index; statLine(dd); if (L == zero) return(zero); if (U == one) return(one); /* Check cache */ r = cuddCacheLookup2(dd, cuddBddIsop, L, U); if (r) return(r); top_l = dd->perm[Cudd_Regular(L)->index]; top_u = dd->perm[Cudd_Regular(U)->index]; v = ddMin(top_l, top_u); /* Compute cofactors */ if (top_l == v) { index = Cudd_Regular(L)->index; Lv = Cudd_T(L); Lnv = Cudd_E(L); if (Cudd_IsComplement(L)) { Lv = Cudd_Not(Lv); Lnv = Cudd_Not(Lnv); } } else { index = Cudd_Regular(U)->index; Lv = Lnv = L; } if (top_u == v) { Uv = Cudd_T(U); Unv = Cudd_E(U); if (Cudd_IsComplement(U)) { Uv = Cudd_Not(Uv); Unv = Cudd_Not(Unv); } } else { Uv = Unv = U; } Lsub0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Uv)); if (Lsub0 == NULL) return(NULL); Cudd_Ref(Lsub0); Usub0 = Unv; Lsub1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Unv)); if (Lsub1 == NULL) { Cudd_RecursiveDeref(dd, Lsub0); return(NULL); } Cudd_Ref(Lsub1); Usub1 = Uv; Isub0 = cuddBddIsop(dd, Lsub0, Usub0); if (Isub0 == NULL) { Cudd_RecursiveDeref(dd, Lsub0); Cudd_RecursiveDeref(dd, Lsub1); return(NULL); } Cudd_Ref(Isub0); Isub1 = cuddBddIsop(dd, Lsub1, Usub1); if (Isub1 == NULL) { Cudd_RecursiveDeref(dd, Lsub0); Cudd_RecursiveDeref(dd, Lsub1); Cudd_RecursiveDeref(dd, Isub0); return(NULL); } Cudd_Ref(Isub1); Cudd_RecursiveDeref(dd, Lsub0); Cudd_RecursiveDeref(dd, Lsub1); Lsuper0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Isub0)); if (Lsuper0 == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDeref(dd, Isub1); return(NULL); } Cudd_Ref(Lsuper0); Lsuper1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Isub1)); if (Lsuper1 == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDeref(dd, Lsuper0); return(NULL); } Cudd_Ref(Lsuper1); Usuper0 = Unv; Usuper1 = Uv; /* Ld = Lsuper0 + Lsuper1 */ Ld = cuddBddAndRecur(dd, Cudd_Not(Lsuper0), Cudd_Not(Lsuper1)); Ld = Cudd_NotCond(Ld, Ld != NULL); if (Ld == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDeref(dd, Lsuper0); Cudd_RecursiveDeref(dd, Lsuper1); return(NULL); } Cudd_Ref(Ld); Ud = cuddBddAndRecur(dd, Usuper0, Usuper1); if (Ud == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDeref(dd, Lsuper0); Cudd_RecursiveDeref(dd, Lsuper1); Cudd_RecursiveDeref(dd, Ld); return(NULL); } Cudd_Ref(Ud); Cudd_RecursiveDeref(dd, Lsuper0); Cudd_RecursiveDeref(dd, Lsuper1); Id = cuddBddIsop(dd, Ld, Ud); if (Id == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDeref(dd, Ld); Cudd_RecursiveDeref(dd, Ud); return(NULL); } Cudd_Ref(Id); Cudd_RecursiveDeref(dd, Ld); Cudd_RecursiveDeref(dd, Ud); x = cuddUniqueInter(dd, index, one, zero); if (x == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDeref(dd, Id); return(NULL); } Cudd_Ref(x); term0 = cuddBddAndRecur(dd, Cudd_Not(x), Isub0); if (term0 == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDeref(dd, Id); Cudd_RecursiveDeref(dd, x); return(NULL); } Cudd_Ref(term0); Cudd_RecursiveDeref(dd, Isub0); term1 = cuddBddAndRecur(dd, x, Isub1); if (term1 == NULL) { Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDeref(dd, Id); Cudd_RecursiveDeref(dd, x); Cudd_RecursiveDeref(dd, term0); return(NULL); } Cudd_Ref(term1); Cudd_RecursiveDeref(dd, x); Cudd_RecursiveDeref(dd, Isub1); /* sum = term0 + term1 */ sum = cuddBddAndRecur(dd, Cudd_Not(term0), Cudd_Not(term1)); sum = Cudd_NotCond(sum, sum != NULL); if (sum == NULL) { Cudd_RecursiveDeref(dd, Id); Cudd_RecursiveDeref(dd, term0); Cudd_RecursiveDeref(dd, term1); return(NULL); } Cudd_Ref(sum); Cudd_RecursiveDeref(dd, term0); Cudd_RecursiveDeref(dd, term1); /* r = sum + Id */ r = cuddBddAndRecur(dd, Cudd_Not(sum), Cudd_Not(Id)); r = Cudd_NotCond(r, r != NULL); if (r == NULL) { Cudd_RecursiveDeref(dd, Id); Cudd_RecursiveDeref(dd, sum); return(NULL); } Cudd_Ref(r); Cudd_RecursiveDeref(dd, sum); Cudd_RecursiveDeref(dd, Id); cuddCacheInsert2(dd, cuddBddIsop, L, U, r); Cudd_Deref(r); return(r); } /* end of cuddBddIsop */
/**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_zddIsop.] Description [] SideEffects [None] SeeAlso [Cudd_zddIsop] ******************************************************************************/ DdNode * cuddZddIsop( DdManager * dd, DdNode * L, DdNode * U, DdNode ** zdd_I) { DdNode *one = DD_ONE(dd); DdNode *zero = Cudd_Not(one); DdNode *zdd_one = DD_ONE(dd); DdNode *zdd_zero = DD_ZERO(dd); int v, top_l, top_u; DdNode *Lsub0, *Usub0, *Lsub1, *Usub1, *Ld, *Ud; DdNode *Lsuper0, *Usuper0, *Lsuper1, *Usuper1; DdNode *Isub0, *Isub1, *Id; DdNode *zdd_Isub0, *zdd_Isub1, *zdd_Id; DdNode *x; DdNode *term0, *term1, *sum; DdNode *Lv, *Uv, *Lnv, *Unv; DdNode *r, *y, *z; int index; DdNode *(*cacheOp)(DdManager *, DdNode *, DdNode *); statLine(dd); if (L == zero) { *zdd_I = zdd_zero; return(zero); } if (U == one) { *zdd_I = zdd_one; return(one); } if (U == zero || L == one) { printf("*** ERROR : illegal condition for ISOP (U < L).\n"); exit(1); } /* Check the cache. We store two results for each recursive call. ** One is the BDD, and the other is the ZDD. Both are needed. ** Hence we need a double hit in the cache to terminate the ** recursion. Clearly, collisions may evict only one of the two ** results. */ cacheOp = (DdNode *(*)(DdManager *, DdNode *, DdNode *)) cuddZddIsop; r = cuddCacheLookup2(dd, cuddBddIsop, L, U); if (r) { *zdd_I = cuddCacheLookup2Zdd(dd, cacheOp, L, U); if (*zdd_I) return(r); else { /* The BDD result may have been dead. In that case ** cuddCacheLookup2 would have called cuddReclaim, ** whose effects we now have to undo. */ cuddRef(r); Cudd_RecursiveDeref(dd, r); } } top_l = dd->perm[Cudd_Regular(L)->index]; top_u = dd->perm[Cudd_Regular(U)->index]; v = ddMin(top_l, top_u); /* Compute cofactors. */ if (top_l == v) { index = Cudd_Regular(L)->index; Lv = Cudd_T(L); Lnv = Cudd_E(L); if (Cudd_IsComplement(L)) { Lv = Cudd_Not(Lv); Lnv = Cudd_Not(Lnv); } } else { index = Cudd_Regular(U)->index; Lv = Lnv = L; } if (top_u == v) { Uv = Cudd_T(U); Unv = Cudd_E(U); if (Cudd_IsComplement(U)) { Uv = Cudd_Not(Uv); Unv = Cudd_Not(Unv); } } else { Uv = Unv = U; } Lsub0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Uv)); if (Lsub0 == NULL) return(NULL); Cudd_Ref(Lsub0); Usub0 = Unv; Lsub1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Unv)); if (Lsub1 == NULL) { Cudd_RecursiveDeref(dd, Lsub0); return(NULL); } Cudd_Ref(Lsub1); Usub1 = Uv; Isub0 = cuddZddIsop(dd, Lsub0, Usub0, &zdd_Isub0); if (Isub0 == NULL) { Cudd_RecursiveDeref(dd, Lsub0); Cudd_RecursiveDeref(dd, Lsub1); return(NULL); } /* if ((!cuddIsConstant(Cudd_Regular(Isub0))) && (Cudd_Regular(Isub0)->index != zdd_Isub0->index / 2 || dd->permZ[index * 2] > dd->permZ[zdd_Isub0->index])) { printf("*** ERROR : illegal permutation in ZDD. ***\n"); } */ Cudd_Ref(Isub0); Cudd_Ref(zdd_Isub0); Isub1 = cuddZddIsop(dd, Lsub1, Usub1, &zdd_Isub1); if (Isub1 == NULL) { Cudd_RecursiveDeref(dd, Lsub0); Cudd_RecursiveDeref(dd, Lsub1); Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDerefZdd(dd, zdd_Isub0); return(NULL); } /* if ((!cuddIsConstant(Cudd_Regular(Isub1))) && (Cudd_Regular(Isub1)->index != zdd_Isub1->index / 2 || dd->permZ[index * 2] > dd->permZ[zdd_Isub1->index])) { printf("*** ERROR : illegal permutation in ZDD. ***\n"); } */ Cudd_Ref(Isub1); Cudd_Ref(zdd_Isub1); Cudd_RecursiveDeref(dd, Lsub0); Cudd_RecursiveDeref(dd, Lsub1); Lsuper0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Isub0)); if (Lsuper0 == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDerefZdd(dd, zdd_Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDerefZdd(dd, zdd_Isub1); return(NULL); } Cudd_Ref(Lsuper0); Lsuper1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Isub1)); if (Lsuper1 == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDerefZdd(dd, zdd_Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDerefZdd(dd, zdd_Isub1); Cudd_RecursiveDeref(dd, Lsuper0); return(NULL); } Cudd_Ref(Lsuper1); Usuper0 = Unv; Usuper1 = Uv; /* Ld = Lsuper0 + Lsuper1 */ Ld = cuddBddAndRecur(dd, Cudd_Not(Lsuper0), Cudd_Not(Lsuper1)); if (Ld == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDerefZdd(dd, zdd_Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDerefZdd(dd, zdd_Isub1); Cudd_RecursiveDeref(dd, Lsuper0); Cudd_RecursiveDeref(dd, Lsuper1); return(NULL); } Ld = Cudd_Not(Ld); Cudd_Ref(Ld); /* Ud = Usuper0 * Usuper1 */ Ud = cuddBddAndRecur(dd, Usuper0, Usuper1); if (Ud == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDerefZdd(dd, zdd_Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDerefZdd(dd, zdd_Isub1); Cudd_RecursiveDeref(dd, Lsuper0); Cudd_RecursiveDeref(dd, Lsuper1); Cudd_RecursiveDeref(dd, Ld); return(NULL); } Cudd_Ref(Ud); Cudd_RecursiveDeref(dd, Lsuper0); Cudd_RecursiveDeref(dd, Lsuper1); Id = cuddZddIsop(dd, Ld, Ud, &zdd_Id); if (Id == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDerefZdd(dd, zdd_Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDerefZdd(dd, zdd_Isub1); Cudd_RecursiveDeref(dd, Ld); Cudd_RecursiveDeref(dd, Ud); return(NULL); } /* if ((!cuddIsConstant(Cudd_Regular(Id))) && (Cudd_Regular(Id)->index != zdd_Id->index / 2 || dd->permZ[index * 2] > dd->permZ[zdd_Id->index])) { printf("*** ERROR : illegal permutation in ZDD. ***\n"); } */ Cudd_Ref(Id); Cudd_Ref(zdd_Id); Cudd_RecursiveDeref(dd, Ld); Cudd_RecursiveDeref(dd, Ud); x = cuddUniqueInter(dd, index, one, zero); if (x == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDerefZdd(dd, zdd_Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDerefZdd(dd, zdd_Isub1); Cudd_RecursiveDeref(dd, Id); Cudd_RecursiveDerefZdd(dd, zdd_Id); return(NULL); } Cudd_Ref(x); /* term0 = x * Isub0 */ term0 = cuddBddAndRecur(dd, Cudd_Not(x), Isub0); if (term0 == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDerefZdd(dd, zdd_Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDerefZdd(dd, zdd_Isub1); Cudd_RecursiveDeref(dd, Id); Cudd_RecursiveDerefZdd(dd, zdd_Id); Cudd_RecursiveDeref(dd, x); return(NULL); } Cudd_Ref(term0); Cudd_RecursiveDeref(dd, Isub0); /* term1 = x * Isub1 */ term1 = cuddBddAndRecur(dd, x, Isub1); if (term1 == NULL) { Cudd_RecursiveDerefZdd(dd, zdd_Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDerefZdd(dd, zdd_Isub1); Cudd_RecursiveDeref(dd, Id); Cudd_RecursiveDerefZdd(dd, zdd_Id); Cudd_RecursiveDeref(dd, x); Cudd_RecursiveDeref(dd, term0); return(NULL); } Cudd_Ref(term1); Cudd_RecursiveDeref(dd, x); Cudd_RecursiveDeref(dd, Isub1); /* sum = term0 + term1 */ sum = cuddBddAndRecur(dd, Cudd_Not(term0), Cudd_Not(term1)); if (sum == NULL) { Cudd_RecursiveDerefZdd(dd, zdd_Isub0); Cudd_RecursiveDerefZdd(dd, zdd_Isub1); Cudd_RecursiveDeref(dd, Id); Cudd_RecursiveDerefZdd(dd, zdd_Id); Cudd_RecursiveDeref(dd, term0); Cudd_RecursiveDeref(dd, term1); return(NULL); } sum = Cudd_Not(sum); Cudd_Ref(sum); Cudd_RecursiveDeref(dd, term0); Cudd_RecursiveDeref(dd, term1); /* r = sum + Id */ r = cuddBddAndRecur(dd, Cudd_Not(sum), Cudd_Not(Id)); r = Cudd_NotCond(r, r != NULL); if (r == NULL) { Cudd_RecursiveDerefZdd(dd, zdd_Isub0); Cudd_RecursiveDerefZdd(dd, zdd_Isub1); Cudd_RecursiveDeref(dd, Id); Cudd_RecursiveDerefZdd(dd, zdd_Id); Cudd_RecursiveDeref(dd, sum); return(NULL); } Cudd_Ref(r); Cudd_RecursiveDeref(dd, sum); Cudd_RecursiveDeref(dd, Id); if (zdd_Isub0 != zdd_zero) { z = cuddZddGetNodeIVO(dd, index * 2 + 1, zdd_Isub0, zdd_Id); if (z == NULL) { Cudd_RecursiveDerefZdd(dd, zdd_Isub0); Cudd_RecursiveDerefZdd(dd, zdd_Isub1); Cudd_RecursiveDerefZdd(dd, zdd_Id); Cudd_RecursiveDeref(dd, r); return(NULL); } } else { z = zdd_Id; } Cudd_Ref(z); if (zdd_Isub1 != zdd_zero) { y = cuddZddGetNodeIVO(dd, index * 2, zdd_Isub1, z); if (y == NULL) { Cudd_RecursiveDerefZdd(dd, zdd_Isub0); Cudd_RecursiveDerefZdd(dd, zdd_Isub1); Cudd_RecursiveDerefZdd(dd, zdd_Id); Cudd_RecursiveDeref(dd, r); Cudd_RecursiveDerefZdd(dd, z); return(NULL); } } else y = z; Cudd_Ref(y); Cudd_RecursiveDerefZdd(dd, zdd_Isub0); Cudd_RecursiveDerefZdd(dd, zdd_Isub1); Cudd_RecursiveDerefZdd(dd, zdd_Id); Cudd_RecursiveDerefZdd(dd, z); cuddCacheInsert2(dd, cuddBddIsop, L, U, r); cuddCacheInsert2(dd, cacheOp, L, U, y); Cudd_Deref(r); Cudd_Deref(y); *zdd_I = y; /* if (Cudd_Regular(r)->index != y->index / 2) { printf("*** ERROR : mismatch in indices between BDD and ZDD. ***\n"); } */ return(r); } /* end of cuddZddIsop */
/**Function************************************************************* Synopsis [Returns the local function of the DSD node. ] Description [The local function is computed using the global function of the node and the global functions of the formal inputs. The resulting local function is mapped using the topmost N variables of the manager. The number of variables N is equal to the number of formal inputs.] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Dsd_TreeGetPrimeFunction( DdManager * dd, Dsd_Node_t * pNode ) { int * pForm2Var; // the mapping of each formal input into its first var int * pVar2Form; // the mapping of each var into its formal inputs int i, iVar, iLev, * pPermute; DdNode ** pbCube0, ** pbCube1; DdNode * bFunc, * bRes, * bTemp; st_table * pCache; pPermute = ALLOC( int, dd->size ); pVar2Form = ALLOC( int, dd->size ); pForm2Var = ALLOC( int, dd->size ); pbCube0 = ALLOC( DdNode *, dd->size ); pbCube1 = ALLOC( DdNode *, dd->size ); // remap the global function in such a way that // the support variables of each formal input are adjacent iLev = 0; for ( i = 0; i < pNode->nDecs; i++ ) { pForm2Var[i] = dd->invperm[i]; for ( bTemp = pNode->pDecs[i]->S; bTemp != b1; bTemp = cuddT(bTemp) ) { iVar = dd->invperm[iLev]; pPermute[bTemp->index] = iVar; pVar2Form[iVar] = i; iLev++; } // collect the cubes representing each assignment pbCube0[i] = Extra_bddGetOneCube( dd, Cudd_Not(pNode->pDecs[i]->G) ); Cudd_Ref( pbCube0[i] ); pbCube1[i] = Extra_bddGetOneCube( dd, pNode->pDecs[i]->G ); Cudd_Ref( pbCube1[i] ); } // remap the function bFunc = Cudd_bddPermute( dd, pNode->G, pPermute ); Cudd_Ref( bFunc ); // remap the cube for ( i = 0; i < pNode->nDecs; i++ ) { pbCube0[i] = Cudd_bddPermute( dd, bTemp = pbCube0[i], pPermute ); Cudd_Ref( pbCube0[i] ); Cudd_RecursiveDeref( dd, bTemp ); pbCube1[i] = Cudd_bddPermute( dd, bTemp = pbCube1[i], pPermute ); Cudd_Ref( pbCube1[i] ); Cudd_RecursiveDeref( dd, bTemp ); } // remap the function pCache = st_init_table(st_ptrcmp,st_ptrhash); bRes = Extra_dsdRemap( dd, bFunc, pCache, pVar2Form, pForm2Var, pbCube0, pbCube1 ); Cudd_Ref( bRes ); st_free_table( pCache ); Cudd_RecursiveDeref( dd, bFunc ); for ( i = 0; i < pNode->nDecs; i++ ) { Cudd_RecursiveDeref( dd, pbCube0[i] ); Cudd_RecursiveDeref( dd, pbCube1[i] ); } /* //////////// // permute the function once again // in such a way that i-th var stood for i-th formal input for ( i = 0; i < dd->size; i++ ) pPermute[i] = -1; for ( i = 0; i < pNode->nDecs; i++ ) pPermute[dd->invperm[i]] = i; bRes = Cudd_bddPermute( dd, bTemp = bRes, pPermute ); Cudd_Ref( bRes ); Cudd_RecursiveDeref( dd, bTemp ); //////////// */ FREE(pPermute); FREE(pVar2Form); FREE(pForm2Var); FREE(pbCube0); FREE(pbCube1); Cudd_Deref( bRes ); return bRes; }
/**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] ******************************************************************************/ DdNode * cuddSolveEqnRecur( DdManager * bdd, DdNode * F /* the left-hand side of the equation */, DdNode * Y /* the cube of remaining y variables */, DdNode ** G /* the array of solutions */, int n /* number of unknowns */, int * yIndex /* array holding the y variable indices */, int i /* level of recursion */) { DdNode *Fn, *Fm1, *Fv, *Fvbar, *T, *w, *nextY, *one; DdNodePtr *variables; int j; statLine(bdd); variables = bdd->vars; one = DD_ONE(bdd); /* Base condition. */ if (Y == one) { return F; } /* Cofactor of Y. */ yIndex[i] = Y->index; nextY = Cudd_T(Y); /* Universal abstraction of F with respect to the top variable index. */ Fm1 = cuddBddExistAbstractRecur(bdd, Cudd_Not(F), variables[yIndex[i]]); if (Fm1) { Fm1 = Cudd_Not(Fm1); cuddRef(Fm1); } else { return(NULL); } Fn = cuddSolveEqnRecur(bdd, Fm1, nextY, G, n, yIndex, i+1); if (Fn) { cuddRef(Fn); } else { Cudd_RecursiveDeref(bdd, Fm1); return(NULL); } Fv = cuddCofactorRecur(bdd, F, variables[yIndex[i]]); if (Fv) { cuddRef(Fv); } else { Cudd_RecursiveDeref(bdd, Fm1); Cudd_RecursiveDeref(bdd, Fn); return(NULL); } Fvbar = cuddCofactorRecur(bdd, F, Cudd_Not(variables[yIndex[i]])); if (Fvbar) { cuddRef(Fvbar); } else { Cudd_RecursiveDeref(bdd, Fm1); Cudd_RecursiveDeref(bdd, Fn); Cudd_RecursiveDeref(bdd, Fv); return(NULL); } /* Build i-th component of the solution. */ w = cuddBddIteRecur(bdd, variables[yIndex[i]], Cudd_Not(Fv), Fvbar); if (w) { cuddRef(w); } else { Cudd_RecursiveDeref(bdd, Fm1); Cudd_RecursiveDeref(bdd, Fn); Cudd_RecursiveDeref(bdd, Fv); Cudd_RecursiveDeref(bdd, Fvbar); return(NULL); } T = cuddBddRestrictRecur(bdd, w, Cudd_Not(Fm1)); if(T) { cuddRef(T); } else { Cudd_RecursiveDeref(bdd, Fm1); Cudd_RecursiveDeref(bdd, Fn); Cudd_RecursiveDeref(bdd, Fv); Cudd_RecursiveDeref(bdd, Fvbar); Cudd_RecursiveDeref(bdd, w); return(NULL); } Cudd_RecursiveDeref(bdd,Fm1); Cudd_RecursiveDeref(bdd,w); Cudd_RecursiveDeref(bdd,Fv); Cudd_RecursiveDeref(bdd,Fvbar); /* Substitute components of solution already found into solution. */ for (j = n-1; j > i; j--) { w = cuddBddComposeRecur(bdd,T, G[j], variables[yIndex[j]]); if(w) { cuddRef(w); } else { Cudd_RecursiveDeref(bdd, Fn); Cudd_RecursiveDeref(bdd, T); return(NULL); } Cudd_RecursiveDeref(bdd,T); T = w; } G[i] = T; Cudd_Deref(Fn); return(Fn); } /* end of cuddSolveEqnRecur */
ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ /**AutomaticEnd***************************************************************/ /* LinearSpace(f) = Space(f,f) Space(f,g) { if ( f = const ) { if ( f = g ) return 1; else return 0; } if ( g = const ) return 0; return x' * Space(fx',gx') * Space(fx,gx) + x * Space(fx',gx) * Space(fx,gx'); } Equations(s) = Pos(s) + Neg(s); Pos(s) { if ( s = 0 ) return 1; if ( s = 1 ) return 0; if ( sx'= 0 ) return Pos(sx) + x; if ( sx = 0 ) return Pos(sx'); return 1 * [Pos(sx') & Pos(sx)] + x * [Pos(sx') & Neg(sx)]; } Neg(s) { if ( s = 0 ) return 1; if ( s = 1 ) return 0; if ( sx'= 0 ) return Neg(sx); if ( sx = 0 ) return Neg(sx') + x; return 1 * [Neg(sx') & Neg(sx)] + x * [Neg(sx') & Pos(sx)]; } SpaceP(A) { if ( A = 0 ) return 1; if ( A = 1 ) return 1; return x' * SpaceP(Ax') * SpaceP(Ax) + x * SpaceP(Ax') * SpaceN(Ax); } SpaceN(A) { if ( A = 0 ) return 1; if ( A = 1 ) return 0; return x' * SpaceN(Ax') * SpaceN(Ax) + x * SpaceN(Ax') * SpaceP(Ax); } LinInd(A) { if ( A = const ) return 1; if ( !LinInd(Ax') ) return 0; if ( !LinInd(Ax) ) return 0; if ( LinSumOdd(Ax') & LinSumEven(Ax) != 0 ) return 0; if ( LinSumEven(Ax') & LinSumEven(Ax) != 0 ) return 0; return 1; } LinSumOdd(A) { if ( A = 0 ) return 0; // Odd0 ---e-- Odd1 if ( A = 1 ) return 1; // \ o Odd0 = LinSumOdd(Ax'); // x is absent // \ Even0 = LinSumEven(Ax'); // x is absent // / o Odd1 = LinSumOdd(Ax); // x is present // Even0 ---e-- Even1 Even1 = LinSumEven(Ax); // x is absent return 1 * [Odd0 + ExorP(Odd0, Even1)] + x * [Odd1 + ExorP(Odd1, Even0)]; } LinSumEven(A) { if ( A = 0 ) return 0; if ( A = 1 ) return 0; Odd0 = LinSumOdd(Ax'); // x is absent Even0 = LinSumEven(Ax'); // x is absent Odd1 = LinSumOdd(Ax); // x is present Even1 = LinSumEven(Ax); // x is absent return 1 * [Even0 + Even1 + ExorP(Even0, Even1)] + x * [ExorP(Odd0, Odd1)]; } */ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Extra_bddSpaceFromFunctionFast( DdManager * dd, DdNode * bFunc ) { int * pSupport; int * pPermute; int * pPermuteBack; DdNode ** pCompose; DdNode * bCube, * bTemp; DdNode * bSpace, * bFunc1, * bFunc2, * bSpaceShift; int nSupp, Counter; int i, lev; // get the support pSupport = ABC_ALLOC( int, ddMax(dd->size,dd->sizeZ) ); Extra_SupportArray( dd, bFunc, pSupport ); nSupp = 0; for ( i = 0; i < dd->size; i++ ) if ( pSupport[i] ) nSupp++; // make sure the manager has enough variables if ( 2*nSupp > dd->size ) { printf( "Cannot derive linear space, because DD manager does not have enough variables.\n" ); fflush( stdout ); ABC_FREE( pSupport ); return NULL; } // create the permutation arrays pPermute = ABC_ALLOC( int, dd->size ); pPermuteBack = ABC_ALLOC( int, dd->size ); pCompose = ABC_ALLOC( DdNode *, dd->size ); for ( i = 0; i < dd->size; i++ ) { pPermute[i] = i; pPermuteBack[i] = i; pCompose[i] = dd->vars[i]; Cudd_Ref( pCompose[i] ); } // remap the function in such a way that the variables are interleaved Counter = 0; bCube = b1; Cudd_Ref( bCube ); for ( lev = 0; lev < dd->size; lev++ ) if ( pSupport[ dd->invperm[lev] ] ) { // var "dd->invperm[lev]" on level "lev" should go to level 2*Counter; pPermute[ dd->invperm[lev] ] = dd->invperm[2*Counter]; // var from level 2*Counter+1 should go back to the place of this var pPermuteBack[ dd->invperm[2*Counter+1] ] = dd->invperm[lev]; // the permutation should be defined in such a way that variable // on level 2*Counter is replaced by an EXOR of itself and var on the next level Cudd_Deref( pCompose[ dd->invperm[2*Counter] ] ); pCompose[ dd->invperm[2*Counter] ] = Cudd_bddXor( dd, dd->vars[ dd->invperm[2*Counter] ], dd->vars[ dd->invperm[2*Counter+1] ] ); Cudd_Ref( pCompose[ dd->invperm[2*Counter] ] ); // add this variable to the cube bCube = Cudd_bddAnd( dd, bTemp = bCube, dd->vars[ dd->invperm[2*Counter] ] ); Cudd_Ref( bCube ); Cudd_RecursiveDeref( dd, bTemp ); // increment the counter Counter ++; } // permute the functions bFunc1 = Cudd_bddPermute( dd, bFunc, pPermute ); Cudd_Ref( bFunc1 ); // compose to gate the function depending on both vars bFunc2 = Cudd_bddVectorCompose( dd, bFunc1, pCompose ); Cudd_Ref( bFunc2 ); // gate the vector space // L(a) = ForAll x [ F(x) = F(x+a) ] = Not( Exist x [ F(x) (+) F(x+a) ] ) bSpaceShift = Cudd_bddXorExistAbstract( dd, bFunc1, bFunc2, bCube ); Cudd_Ref( bSpaceShift ); bSpaceShift = Cudd_Not( bSpaceShift ); // permute the space back into the original mapping bSpace = Cudd_bddPermute( dd, bSpaceShift, pPermuteBack ); Cudd_Ref( bSpace ); Cudd_RecursiveDeref( dd, bFunc1 ); Cudd_RecursiveDeref( dd, bFunc2 ); Cudd_RecursiveDeref( dd, bSpaceShift ); Cudd_RecursiveDeref( dd, bCube ); for ( i = 0; i < dd->size; i++ ) Cudd_RecursiveDeref( dd, pCompose[i] ); ABC_FREE( pPermute ); ABC_FREE( pPermuteBack ); ABC_FREE( pCompose ); ABC_FREE( pSupport ); Cudd_Deref( bSpace ); return bSpace; }
/**Function******************************************************************** Synopsis [Repeated squaring algorithm for all-pairs shortest paths.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ static DdNode * ntrSquare( DdManager *dd /* manager */, DdNode *D /* D(z,y): distance matrix */, DdNode **x /* array of x variables */, DdNode **y /* array of y variables */, DdNode **z /* array of z variables */, int vars /* number of variables in each of the three arrays */, int pr /* verbosity level */, int st /* use the selective trace algorithm */) { DdNode *zero; DdNode *I; /* identity matirix */ DdNode *w, *V, *P, *M, *R, *RT; DdNode *diff, *min, *minDiag; int n; int neg; long start_time; zero = Cudd_ReadZero(dd); /* Make a working copy of the original matrix. */ R = D; Cudd_Ref(R); I = Cudd_addXeqy(dd,vars,z,y); /* identity matrix */ Cudd_Ref(I); /* Make a copy of the matrix for the selective trace algorithm. */ diff = R; Cudd_Ref(diff); start_time = util_cpu_time(); for (n = vars; n >= 0; n--) { printf("Starting iteration %d at time %s\n",vars-n, util_print_time(util_cpu_time() - start_time)); /* Check for negative cycles: They are identified by negative ** elements on the diagonal. */ /* Extract values from the diagonal. */ Cudd_Ref(w = Cudd_addIte(dd,I,R,zero)); minDiag = Cudd_addFindMin(dd,w); /* no need to ref */ neg = Cudd_V(minDiag) < 0; Cudd_RecursiveDeref(dd,w); if (neg) { Cudd_RecursiveDeref(dd,diff); (void) printf("Negative cycle after %d iterations!\n",vars-n); break; } /* Prepare the first operand of matrix multiplication: ** diff(z,y) -> RT(x,y) -> V(x,z) */ /* RT(x,y) */ Cudd_Ref(RT = Cudd_addSwapVariables(dd,diff,x,z,vars)); Cudd_RecursiveDeref(dd,diff); /* V(x,z) */ Cudd_Ref(V = Cudd_addSwapVariables(dd,RT,y,z,vars)); Cudd_RecursiveDeref(dd,RT); if (pr > 0) { double pathcount; (void) printf("V"); Cudd_PrintDebug(dd,V,2*vars,pr); pathcount = Cudd_CountPath(V); (void) printf("Path count = %g\n", pathcount); } /* V(x,z) * R(z,y) -> P(x,y) */ Cudd_Ref(P = Cudd_addTriangle(dd,V,R,z,vars)); Cudd_RecursiveDeref(dd,V); /* P(x,y) => M(z,y) */ Cudd_Ref(M = Cudd_addSwapVariables(dd,P,x,z,vars)); Cudd_RecursiveDeref(dd,P); if (pr>0) {(void) printf("M"); Cudd_PrintDebug(dd,M,2*vars,pr);} /* min(z,y) */ Cudd_Ref(min = Cudd_addApply(dd,Cudd_addMinimum,R,M)); Cudd_RecursiveDeref(dd,M); if (R == min) { Cudd_RecursiveDeref(dd,min); if (pr>0) {printf("Done after %d iterations\n",vars-n+1); } break; } /* diff(z,y) */ if (st) { Cudd_Ref(diff = Cudd_addApply(dd,Cudd_addDiff,min,R)); } else { Cudd_Ref(diff = min); } Cudd_RecursiveDeref(dd,R); R = min; /* keep a copy of matrix at current iter. */ if (pr > 0) { double pathcount; (void) printf("R"); Cudd_PrintDebug(dd,R,2*vars,pr); pathcount = Cudd_CountPath(R); (void) printf("Path count = %g\n", pathcount); } if (n == 0) { (void) printf("Negative cycle!\n"); break; } } Cudd_RecursiveDeref(dd,I); Cudd_Deref(R); return(R); } /* end of ntrSquare */
/**Function******************************************************************** Synopsis [Floyd-Warshall algorithm for all-pair shortest paths.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ static DdNode * ntrWarshall( DdManager *dd, DdNode *D, DdNode **x, DdNode **y, int vars, int pr) { DdNode *one, *zero; DdNode *xminterm, *w, *V, *V2; DdNode *P, *R; int i; int nodes; int k,u; long start_time; if (vars > 30) nodes = 1000000000; else nodes = 1 << vars; one = DD_ONE(dd); zero = DD_ZERO(dd); Cudd_Ref(R = D); /* make copy of original matrix */ /* Extract pivot row and column from D */ start_time = util_cpu_time(); for (k = 0; k < nodes; k++) { if (k % 10000 == 0) { (void) printf("Starting iteration %d at time %s\n", k,util_print_time(util_cpu_time() - start_time)); } Cudd_Ref(xminterm = one); u = k; for (i = vars-1; i >= 0; i--) { if (u&1) { Cudd_Ref(w = Cudd_addIte(dd,x[i],xminterm,zero)); } else { Cudd_Ref(w = Cudd_addIte(dd,x[i],zero,xminterm)); } Cudd_RecursiveDeref(dd,xminterm); xminterm = w; u >>= 1; } Cudd_Ref(V = Cudd_Cofactor(dd,R,xminterm)); Cudd_RecursiveDeref(dd,xminterm); if (pr>2) {(void) printf("V"); Cudd_PrintDebug(dd,V,vars,pr);} Cudd_Ref(xminterm = one); u = k; for (i = vars-1; i >= 0; i--) { if (u&1) { Cudd_Ref(w = Cudd_addIte(dd,y[i],xminterm,zero)); } else { Cudd_Ref(w = Cudd_addIte(dd,y[i],zero,xminterm)); } Cudd_RecursiveDeref(dd,xminterm); xminterm = w; u >>= 1; } Cudd_Ref(V2 = Cudd_Cofactor(dd,R,xminterm)); Cudd_RecursiveDeref(dd,xminterm); if (pr>2) {(void) printf("V2"); Cudd_PrintDebug(dd,V2,vars,pr);} Cudd_Ref(P = Cudd_addOuterSum(dd,R,V,V2)); Cudd_RecursiveDeref(dd,V); Cudd_RecursiveDeref(dd,V2); Cudd_RecursiveDeref(dd,R); R = P; if (pr>2) {(void) printf("R"); Cudd_PrintDebug(dd,R,vars,pr);} } Cudd_Deref(R); return(R); } /* end of ntrWarshall */
/**Function******************************************************************** Synopsis [Bellman-Ford algorithm for single-source shortest paths.] Description [Bellman-Ford algorithm for single-source shortest paths. Returns the vector of the distances of all states from the initial states. In case of multiple initial states the distance for each state is from the nearest initial state. Negative-weight cycles are detected, though only in the naive way. (Lack of convergence after nodes-1 iterations.) In such a case, a constant ADD with value minus infinity is returned. Bellman-Ford is based on matrix-vector multiplication. The matrix is the distance matrix D(x,y), such that D(a,b) is the length of the arc connecting state a to state b. The vector V(x) stores the distances of all states from the initial states. The actual vector used in the matrix-vector multiplication is diff(x), that holds those distances that have changed during the last update.] SideEffects [] SeeAlso [ntrWarshall ntrSquare] ******************************************************************************/ static DdNode * ntrBellman( DdManager *dd, DdNode *D, DdNode *source, DdNode **x, DdNode **y, int vars, int pr) { DdNode *u, *w, *V, *min, *diff; DdApaNumber i, nodes, one; int digits = vars + 1; /* To avoid overflow when there are many variables, use APA. */ nodes = Cudd_NewApaNumber(digits); Cudd_ApaPowerOfTwo(digits,nodes,vars); i = Cudd_NewApaNumber(digits); one = Cudd_NewApaNumber(digits); Cudd_ApaSetToLiteral(digits,one,1); #if 0 /* Find the distances from the initial state along paths using one ** arc. */ w = Cudd_Cofactor(dd,D,source); /* works only if source is a cube */ Cudd_Ref(w); V = Cudd_addSwapVariables(dd,w,x,y,vars); Cudd_Ref(V); Cudd_RecursiveDeref(dd,w); #endif /* The initial states are at distance 0. The other states are ** initially at infinite distance. */ V = Cudd_addIte(dd,source,Cudd_ReadZero(dd),Cudd_ReadPlusInfinity(dd)); Cudd_Ref(V); /* Selective trace algorithm. For the next update, only consider the ** nodes whose distance has changed in the last update. */ diff = V; Cudd_Ref(diff); for (Cudd_ApaSetToLiteral(digits,i,1); Cudd_ApaCompare(digits,i,digits,nodes) < 0; Cudd_ApaAdd(digits,i,one,i)) { if (pr>2) {(void) printf("V"); Cudd_PrintDebug(dd,V,vars,pr);} /* Compute the distances via triangulation as a function of x. */ w = Cudd_addTriangle(dd,diff,D,x,vars); Cudd_Ref(w); Cudd_RecursiveDeref(dd,diff); u = Cudd_addSwapVariables(dd,w,x,y,vars); Cudd_Ref(u); Cudd_RecursiveDeref(dd,w); if (pr>2) {(void) printf("u"); Cudd_PrintDebug(dd,u,vars,pr);} /* Take the minimum of the previous distances and those just ** computed. */ min = Cudd_addApply(dd,Cudd_addMinimum,V,u); Cudd_Ref(min); Cudd_RecursiveDeref(dd,u); if (pr>2) {(void) printf("min"); Cudd_PrintDebug(dd,min,vars,pr);} if (V == min) { /* convergence */ Cudd_RecursiveDeref(dd,min); if (pr>0) { (void) printf("Terminating after "); Cudd_ApaPrintDecimal(stdout,digits,i); (void) printf(" iterations\n"); } break; } /* Find the distances that decreased. */ diff = Cudd_addApply(dd,Cudd_addDiff,V,min); Cudd_Ref(diff); if (pr>2) {(void) printf("diff"); Cudd_PrintDebug(dd,diff,vars,pr);} Cudd_RecursiveDeref(dd,V); V = min; } /* Negative cycle detection. */ if (Cudd_ApaCompare(digits,i,digits,nodes) == 0 && diff != Cudd_ReadPlusInfinity(dd)) { (void) printf("Negative cycle\n"); Cudd_RecursiveDeref(dd,diff); Cudd_RecursiveDeref(dd,V); V = Cudd_ReadMinusInfinity(dd); Cudd_Ref(V); } Cudd_Deref(V); FREE(i); FREE(nodes); FREE(one); return(V); } /* end of ntrBellman */
ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [This procedure is similar to Cudd_ShuffleHeap() and Cudd_bddPermute().] Description [The first argument is the REO manager. The 2nd/3d arguments are the function and its CUDD manager. The last argument is the permutation to be implemented. The i-th entry of the permutation array contains the index of the variable that should be brought to the i-th level. The size of the array should be equal or greater to the number of variables currently in use (that is, the size of CUDD manager and the size of REO manager).] SideEffects [Note that the resulting BDD is not referenced.] SeeAlso [] ***********************************************************************/ DdNode * reoShuffle( reo_man * p, DdManager * dd, DdNode * bFunc, int * pPerm, int * pPermInv ) { DdNode * bFuncRes = NULL; int i, k, v; if ( Cudd_IsConstant(bFunc) ) return bFunc; // set the initial parameters p->dd = dd; p->nSupp = Cudd_SupportSize( dd, bFunc ); p->nTops = 1; // p->nNodesBeg = Cudd_DagSize( bFunc ); // set the starting permutation for ( i = 0; i < p->nSupp; i++ ) { p->pOrderInt[i] = i; p->pMapToPlanes[ dd->invperm[i] ] = i; p->pMapToDdVarsFinal[i] = dd->invperm[i]; } // set the initial parameters p->nUnitsUsed = 0; p->nNodesCur = 0; p->fThisIsAdd = 0; p->Signature++; // transfer the function from the CUDD package into REO's internal data structure p->pTops[0] = reoTransferNodesToUnits_rec( p, bFunc ); // assert( p->nNodesBeg == p->nNodesCur ); // reorder one variable at a time for ( i = 0; i < p->nSupp; i++ ) { if ( p->pOrderInt[i] == pPerm[i] ) continue; // find where is variable number pPerm[i] for ( k = i + 1; k < p->nSupp; k++ ) if ( pPerm[i] == p->pOrderInt[k] ) break; if ( k == p->nSupp ) { printf( "reoShuffle() Error: Cannot find a variable.\n" ); goto finish; } // move the variable up for ( v = k - 1; v >= i; v-- ) { reoReorderSwapAdjacentVars( p, v, 1 ); // check if the number of nodes is not too large if ( p->nNodesCur > 10000 ) { printf( "reoShuffle() Error: BDD size is too large.\n" ); goto finish; } } assert( p->pOrderInt[i] == pPerm[i] ); } // set the initial parameters p->nRefNodes = 0; p->nNodesCur = 0; p->Signature++; // transfer the BDDs from REO's internal data structure to CUDD bFuncRes = reoTransferUnitsToNodes_rec( p, p->pTops[0] ); Cudd_Ref( bFuncRes ); // undo the DDs referenced for storing in the cache for ( i = 0; i < p->nRefNodes; i++ ) Cudd_RecursiveDeref( dd, p->pRefNodes[i] ); // verify zero refs of the terminal nodes // assert( reoRecursiveDeref( p->pTops[0] ) ); // assert( reoCheckZeroRefs( &(p->pPlanes[p->nSupp]) ) ); // perform verification if ( p->fVerify ) { DdNode * bFuncPerm; bFuncPerm = Cudd_bddPermute( dd, bFunc, pPermInv ); Cudd_Ref( bFuncPerm ); if ( bFuncPerm != bFuncRes ) { printf( "REO: Internal verification has failed!\n" ); fflush( stdout ); } Cudd_RecursiveDeref( dd, bFuncPerm ); } // recycle the data structure for ( i = 0; i <= p->nSupp; i++ ) reoUnitsRecycleUnitList( p, p->pPlanes + i ); finish : if ( bFuncRes ) Cudd_Deref( bFuncRes ); return bFuncRes; }
/**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_zddDivideF.] Description [] SideEffects [None] SeeAlso [Cudd_zddDivideF] ******************************************************************************/ DdNode * cuddZddDivideF( DdManager * dd, DdNode * f, DdNode * g) { int v; DdNode *one = DD_ONE(dd); DdNode *zero = DD_ZERO(dd); DdNode *f0, *f1, *g0, *g1; DdNode *q, *r, *tmp; int flag; statLine(dd); if (g == one) return(f); if (f == zero || f == one) return(zero); if (f == g) return(one); /* Check cache. */ r = cuddCacheLookup2Zdd(dd, cuddZddDivideF, f, g); if (r) return(r); v = g->index; flag = cuddZddGetCofactors2(dd, f, v, &f1, &f0); if (flag == 1) return(NULL); Cudd_Ref(f1); Cudd_Ref(f0); flag = cuddZddGetCofactors2(dd, g, v, &g1, &g0); /* g1 != zero */ if (flag == 1) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); return(NULL); } Cudd_Ref(g1); Cudd_Ref(g0); r = cuddZddDivideF(dd, f1, g1); if (r == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, g0); return(NULL); } Cudd_Ref(r); if (r != zero && g0 != zero) { tmp = r; q = cuddZddDivideF(dd, f0, g0); if (q == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, g0); return(NULL); } Cudd_Ref(q); r = cuddZddIntersect(dd, r, q); if (r == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, g0); Cudd_RecursiveDerefZdd(dd, q); return(NULL); } Cudd_Ref(r); Cudd_RecursiveDerefZdd(dd, q); Cudd_RecursiveDerefZdd(dd, tmp); } Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, g0); cuddCacheInsert2(dd, cuddZddDivideF, f, g, r); Cudd_Deref(r); return(r); } /* end of cuddZddDivideF */
/**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_zddUnateProduct.] Description [] SideEffects [None] SeeAlso [Cudd_zddUnateProduct] ******************************************************************************/ DdNode * cuddZddUnateProduct( DdManager * dd, DdNode * f, DdNode * g) { int v, top_f, top_g; DdNode *term1, *term2, *term3, *term4; DdNode *sum1, *sum2; DdNode *f0, *f1, *g0, *g1; DdNode *r; DdNode *one = DD_ONE(dd); DdNode *zero = DD_ZERO(dd); int flag; statLine(dd); if (f == zero || g == zero) return(zero); if (f == one) return(g); if (g == one) return(f); top_f = dd->permZ[f->index]; top_g = dd->permZ[g->index]; if (top_f > top_g) return(cuddZddUnateProduct(dd, g, f)); /* Check cache */ r = cuddCacheLookup2Zdd(dd, cuddZddUnateProduct, f, g); if (r) return(r); v = f->index; /* either yi or zi */ flag = cuddZddGetCofactors2(dd, f, v, &f1, &f0); if (flag == 1) return(NULL); Cudd_Ref(f1); Cudd_Ref(f0); flag = cuddZddGetCofactors2(dd, g, v, &g1, &g0); if (flag == 1) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); return(NULL); } Cudd_Ref(g1); Cudd_Ref(g0); term1 = cuddZddUnateProduct(dd, f1, g1); if (term1 == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, g0); return(NULL); } Cudd_Ref(term1); term2 = cuddZddUnateProduct(dd, f1, g0); if (term2 == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, g0); Cudd_RecursiveDerefZdd(dd, term1); return(NULL); } Cudd_Ref(term2); term3 = cuddZddUnateProduct(dd, f0, g1); if (term3 == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, g0); Cudd_RecursiveDerefZdd(dd, term1); Cudd_RecursiveDerefZdd(dd, term2); return(NULL); } Cudd_Ref(term3); term4 = cuddZddUnateProduct(dd, f0, g0); if (term4 == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, g0); Cudd_RecursiveDerefZdd(dd, term1); Cudd_RecursiveDerefZdd(dd, term2); Cudd_RecursiveDerefZdd(dd, term3); return(NULL); } Cudd_Ref(term4); Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, g0); sum1 = cuddZddUnion(dd, term1, term2); if (sum1 == NULL) { Cudd_RecursiveDerefZdd(dd, term1); Cudd_RecursiveDerefZdd(dd, term2); Cudd_RecursiveDerefZdd(dd, term3); Cudd_RecursiveDerefZdd(dd, term4); return(NULL); } Cudd_Ref(sum1); Cudd_RecursiveDerefZdd(dd, term1); Cudd_RecursiveDerefZdd(dd, term2); sum2 = cuddZddUnion(dd, sum1, term3); if (sum2 == NULL) { Cudd_RecursiveDerefZdd(dd, term3); Cudd_RecursiveDerefZdd(dd, term4); Cudd_RecursiveDerefZdd(dd, sum1); return(NULL); } Cudd_Ref(sum2); Cudd_RecursiveDerefZdd(dd, sum1); Cudd_RecursiveDerefZdd(dd, term3); r = cuddZddGetNode(dd, v, sum2, term4); if (r == NULL) { Cudd_RecursiveDerefZdd(dd, term4); Cudd_RecursiveDerefZdd(dd, sum2); return(NULL); } Cudd_Ref(r); Cudd_RecursiveDerefZdd(dd, sum2); Cudd_RecursiveDerefZdd(dd, term4); cuddCacheInsert2(dd, cuddZddUnateProduct, f, g, r); Cudd_Deref(r); return(r); } /* end of cuddZddUnateProduct */
/**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_zddProduct.] Description [] SideEffects [None] SeeAlso [Cudd_zddProduct] ******************************************************************************/ DdNode * cuddZddProduct( DdManager * dd, DdNode * f, DdNode * g) { int v, top_f, top_g; DdNode *tmp, *term1, *term2, *term3; DdNode *f0, *f1, *fd, *g0, *g1, *gd; DdNode *R0, *R1, *Rd, *N0, *N1; DdNode *r; DdNode *one = DD_ONE(dd); DdNode *zero = DD_ZERO(dd); int flag; int pv, nv; statLine(dd); if (f == zero || g == zero) return(zero); if (f == one) return(g); if (g == one) return(f); top_f = dd->permZ[f->index]; top_g = dd->permZ[g->index]; if (top_f > top_g) return(cuddZddProduct(dd, g, f)); /* Check cache */ r = cuddCacheLookup2Zdd(dd, cuddZddProduct, f, g); if (r) return(r); v = f->index; /* either yi or zi */ flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd); if (flag == 1) return(NULL); Cudd_Ref(f1); Cudd_Ref(f0); Cudd_Ref(fd); flag = cuddZddGetCofactors3(dd, g, v, &g1, &g0, &gd); if (flag == 1) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, fd); return(NULL); } Cudd_Ref(g1); Cudd_Ref(g0); Cudd_Ref(gd); pv = cuddZddGetPosVarIndex(dd, v); nv = cuddZddGetNegVarIndex(dd, v); Rd = cuddZddProduct(dd, fd, gd); if (Rd == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, g0); Cudd_RecursiveDerefZdd(dd, gd); return(NULL); } Cudd_Ref(Rd); term1 = cuddZddProduct(dd, f0, g0); if (term1 == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, g0); Cudd_RecursiveDerefZdd(dd, gd); Cudd_RecursiveDerefZdd(dd, Rd); return(NULL); } Cudd_Ref(term1); term2 = cuddZddProduct(dd, f0, gd); if (term2 == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, g0); Cudd_RecursiveDerefZdd(dd, gd); Cudd_RecursiveDerefZdd(dd, Rd); Cudd_RecursiveDerefZdd(dd, term1); return(NULL); } Cudd_Ref(term2); term3 = cuddZddProduct(dd, fd, g0); if (term3 == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, g0); Cudd_RecursiveDerefZdd(dd, gd); Cudd_RecursiveDerefZdd(dd, Rd); Cudd_RecursiveDerefZdd(dd, term1); Cudd_RecursiveDerefZdd(dd, term2); return(NULL); } Cudd_Ref(term3); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, g0); tmp = cuddZddUnion(dd, term1, term2); if (tmp == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, gd); Cudd_RecursiveDerefZdd(dd, Rd); Cudd_RecursiveDerefZdd(dd, term1); Cudd_RecursiveDerefZdd(dd, term2); Cudd_RecursiveDerefZdd(dd, term3); return(NULL); } Cudd_Ref(tmp); Cudd_RecursiveDerefZdd(dd, term1); Cudd_RecursiveDerefZdd(dd, term2); R0 = cuddZddUnion(dd, tmp, term3); if (R0 == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, gd); Cudd_RecursiveDerefZdd(dd, Rd); Cudd_RecursiveDerefZdd(dd, term3); Cudd_RecursiveDerefZdd(dd, tmp); return(NULL); } Cudd_Ref(R0); Cudd_RecursiveDerefZdd(dd, tmp); Cudd_RecursiveDerefZdd(dd, term3); N0 = cuddZddGetNode(dd, nv, R0, Rd); /* nv = zi */ if (N0 == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, gd); Cudd_RecursiveDerefZdd(dd, Rd); Cudd_RecursiveDerefZdd(dd, R0); return(NULL); } Cudd_Ref(N0); Cudd_RecursiveDerefZdd(dd, R0); Cudd_RecursiveDerefZdd(dd, Rd); term1 = cuddZddProduct(dd, f1, g1); if (term1 == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, gd); Cudd_RecursiveDerefZdd(dd, N0); return(NULL); } Cudd_Ref(term1); term2 = cuddZddProduct(dd, f1, gd); if (term2 == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, gd); Cudd_RecursiveDerefZdd(dd, N0); Cudd_RecursiveDerefZdd(dd, term1); return(NULL); } Cudd_Ref(term2); term3 = cuddZddProduct(dd, fd, g1); if (term3 == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, gd); Cudd_RecursiveDerefZdd(dd, N0); Cudd_RecursiveDerefZdd(dd, term1); Cudd_RecursiveDerefZdd(dd, term2); return(NULL); } Cudd_Ref(term3); Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, gd); tmp = cuddZddUnion(dd, term1, term2); if (tmp == NULL) { Cudd_RecursiveDerefZdd(dd, N0); Cudd_RecursiveDerefZdd(dd, term1); Cudd_RecursiveDerefZdd(dd, term2); Cudd_RecursiveDerefZdd(dd, term3); return(NULL); } Cudd_Ref(tmp); Cudd_RecursiveDerefZdd(dd, term1); Cudd_RecursiveDerefZdd(dd, term2); R1 = cuddZddUnion(dd, tmp, term3); if (R1 == NULL) { Cudd_RecursiveDerefZdd(dd, N0); Cudd_RecursiveDerefZdd(dd, term3); Cudd_RecursiveDerefZdd(dd, tmp); return(NULL); } Cudd_Ref(R1); Cudd_RecursiveDerefZdd(dd, tmp); Cudd_RecursiveDerefZdd(dd, term3); N1 = cuddZddGetNode(dd, pv, R1, N0); /* pv = yi */ if (N1 == NULL) { Cudd_RecursiveDerefZdd(dd, N0); Cudd_RecursiveDerefZdd(dd, R1); return(NULL); } Cudd_Ref(N1); Cudd_RecursiveDerefZdd(dd, R1); Cudd_RecursiveDerefZdd(dd, N0); cuddCacheInsert2(dd, cuddZddProduct, f, g, N1); Cudd_Deref(N1); return(N1); } /* end of cuddZddProduct */
/**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] ******************************************************************************/ int cuddZddGetCofactors3( DdManager * dd, DdNode * f, int v, DdNode ** f1, DdNode ** f0, DdNode ** fd) { DdNode *pc, *nc; DdNode *zero = DD_ZERO(dd); int top, hv, ht, pv, nv; int level; top = dd->permZ[f->index]; level = dd->permZ[v]; hv = level >> 1; ht = top >> 1; if (hv < ht) { *f1 = zero; *f0 = zero; *fd = f; } else { pv = cuddZddGetPosVarIndex(dd, v); nv = cuddZddGetNegVarIndex(dd, v); /* not to create intermediate ZDD node */ if (cuddZddGetPosVarLevel(dd, v) < cuddZddGetNegVarLevel(dd, v)) { pc = cuddZddSubset1(dd, f, pv); if (pc == NULL) return(1); Cudd_Ref(pc); nc = cuddZddSubset0(dd, f, pv); if (nc == NULL) { Cudd_RecursiveDerefZdd(dd, pc); return(1); } Cudd_Ref(nc); *f1 = cuddZddSubset0(dd, pc, nv); if (*f1 == NULL) { Cudd_RecursiveDerefZdd(dd, pc); Cudd_RecursiveDerefZdd(dd, nc); return(1); } Cudd_Ref(*f1); *f0 = cuddZddSubset1(dd, nc, nv); if (*f0 == NULL) { Cudd_RecursiveDerefZdd(dd, pc); Cudd_RecursiveDerefZdd(dd, nc); Cudd_RecursiveDerefZdd(dd, *f1); return(1); } Cudd_Ref(*f0); *fd = cuddZddSubset0(dd, nc, nv); if (*fd == NULL) { Cudd_RecursiveDerefZdd(dd, pc); Cudd_RecursiveDerefZdd(dd, nc); Cudd_RecursiveDerefZdd(dd, *f1); Cudd_RecursiveDerefZdd(dd, *f0); return(1); } Cudd_Ref(*fd); } else { pc = cuddZddSubset1(dd, f, nv); if (pc == NULL) return(1); Cudd_Ref(pc); nc = cuddZddSubset0(dd, f, nv); if (nc == NULL) { Cudd_RecursiveDerefZdd(dd, pc); return(1); } Cudd_Ref(nc); *f0 = cuddZddSubset0(dd, pc, pv); if (*f0 == NULL) { Cudd_RecursiveDerefZdd(dd, pc); Cudd_RecursiveDerefZdd(dd, nc); return(1); } Cudd_Ref(*f0); *f1 = cuddZddSubset1(dd, nc, pv); if (*f1 == NULL) { Cudd_RecursiveDerefZdd(dd, pc); Cudd_RecursiveDerefZdd(dd, nc); Cudd_RecursiveDerefZdd(dd, *f0); return(1); } Cudd_Ref(*f1); *fd = cuddZddSubset0(dd, nc, pv); if (*fd == NULL) { Cudd_RecursiveDerefZdd(dd, pc); Cudd_RecursiveDerefZdd(dd, nc); Cudd_RecursiveDerefZdd(dd, *f1); Cudd_RecursiveDerefZdd(dd, *f0); return(1); } Cudd_Ref(*fd); } Cudd_RecursiveDerefZdd(dd, pc); Cudd_RecursiveDerefZdd(dd, nc); Cudd_Deref(*f1); Cudd_Deref(*f0); Cudd_Deref(*fd); } return(0); } /* end of cuddZddGetCofactors3 */
bool qbf_skizzo_coret::get_certificate(void) { std::string result_tmp_file="ozziKs.out"; std::string options="-dump qbm=bdd"; std::string log_file = qbf_tmp_file + ".sKizzo.log"; system(("ozziKs " + options + " " + log_file + " > "+result_tmp_file).c_str()); // read result bool result=false; { std::ifstream in(result_tmp_file.c_str()); std::string key=" [OK, VALID,"; while(in) { std::string line; std::getline(in, line); if(line!="" && line[line.size()-1]=='\r') line.resize(line.size()-1); if(line.compare(0, key.size(), key)==0) { result=true; break; } } } if(!result) { messaget::error("Skizzo failed: unknown result"); return true; } remove(result_tmp_file.c_str()); remove(log_file.c_str()); // certificate reconstruction done, now let's load it from the .qbm file int n_e; std::vector<int> e_list; int e_max=0; // check header result=false; { std::ifstream in((qbf_tmp_file+".qbm").c_str()); std::string key="# existentials["; std::string line; std::getline(in, line); assert(line=="# QBM file, 1.3"); while(in) { std::getline(in, line); if(line!="" && line[line.size()-1]=='\r') line.resize(line.size()-1); if(line.compare(0, key.size(), key)==0) { result=true; break; } } size_t ob=line.find('['); std::string n_es=line.substr(ob+1, line.find(']')-ob-1); n_e=atoi(n_es.c_str()); assert(n_e!=0); e_list.resize(n_e); std::string e_lists=line.substr(line.find(':')+2); for(int i=0; i<n_e; i++) { size_t space=e_lists.find(' '); int cur=atoi(e_lists.substr(0, space).c_str()); assert(cur!=0); e_list[i]=cur; if(cur>e_max) e_max=cur; e_lists = e_lists.substr(space+1); } if(!result) throw ("Existential mapping from sKizzo missing"); in.close(); // workaround for long comments system(("sed -e \"s/^#.*$/# no comment/\" -i "+qbf_tmp_file+".qbm").c_str()); } { DdNode **bdds; std::string bdd_file=qbf_tmp_file+".qbm"; // dddmp insists on a non-const string here... char filename[bdd_file.size()+1]; strcpy(filename, bdd_file.c_str()); bdd_manager->AutodynEnable(CUDD_REORDER_SIFT); int nroots = Dddmp_cuddBddArrayLoad(bdd_manager->getManager(), DDDMP_ROOT_MATCHLIST, NULL, DDDMP_VAR_MATCHIDS, NULL, NULL, NULL, DDDMP_MODE_DEFAULT, filename, NULL, &bdds); assert(nroots=2*n_e); // ozziKs documentation guarantees that. model_bdds.resize(e_max+1, NULL); for(unsigned i=0; i<e_list.size(); i++) { int cur=e_list[i]; DdNode *posNode = bdds[2*i]; DdNode *negNode = bdds[2*i+1]; if(Cudd_DagSize(posNode) <= Cudd_DagSize(negNode)) model_bdds[cur]=new BDD(bdd_manager, posNode); else model_bdds[cur]=new BDD(bdd_manager, Cudd_Not(negNode)); } // tell CUDD that we don't need those BDDs anymore. for(int i=0; i<nroots; i++) Cudd_Deref(bdds[i]); free(bdds); bdds=NULL; remove(bdd_file.c_str()); remove((qbf_tmp_file+".qbm").c_str()); } return false; }
/**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_zddWeakDivF.] Description [] SideEffects [None] SeeAlso [Cudd_zddWeakDivF] ******************************************************************************/ DdNode * cuddZddWeakDivF( DdManager * dd, DdNode * f, DdNode * g) { int v, top_f, top_g, vf, vg; DdNode *one = DD_ONE(dd); DdNode *zero = DD_ZERO(dd); DdNode *f0, *f1, *fd, *g0, *g1, *gd; DdNode *q, *tmp; DdNode *r; DdNode *term1, *term0, *termd; int flag; int pv, nv; statLine(dd); if (g == one) return(f); if (f == zero || f == one) return(zero); if (f == g) return(one); /* Check cache. */ r = cuddCacheLookup2Zdd(dd, cuddZddWeakDivF, f, g); if (r) return(r); top_f = dd->permZ[f->index]; top_g = dd->permZ[g->index]; vf = top_f >> 1; vg = top_g >> 1; v = ddMin(top_f, top_g); if (v == top_f && vf < vg) { v = f->index; flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd); if (flag == 1) return(NULL); Cudd_Ref(f1); Cudd_Ref(f0); Cudd_Ref(fd); pv = cuddZddGetPosVarIndex(dd, v); nv = cuddZddGetNegVarIndex(dd, v); term1 = cuddZddWeakDivF(dd, f1, g); if (term1 == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, fd); return(NULL); } Cudd_Ref(term1); Cudd_RecursiveDerefZdd(dd, f1); term0 = cuddZddWeakDivF(dd, f0, g); if (term0 == NULL) { Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, term1); return(NULL); } Cudd_Ref(term0); Cudd_RecursiveDerefZdd(dd, f0); termd = cuddZddWeakDivF(dd, fd, g); if (termd == NULL) { Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, term1); Cudd_RecursiveDerefZdd(dd, term0); return(NULL); } Cudd_Ref(termd); Cudd_RecursiveDerefZdd(dd, fd); tmp = cuddZddGetNode(dd, nv, term0, termd); /* nv = zi */ if (tmp == NULL) { Cudd_RecursiveDerefZdd(dd, term1); Cudd_RecursiveDerefZdd(dd, term0); Cudd_RecursiveDerefZdd(dd, termd); return(NULL); } Cudd_Ref(tmp); Cudd_RecursiveDerefZdd(dd, term0); Cudd_RecursiveDerefZdd(dd, termd); q = cuddZddGetNode(dd, pv, term1, tmp); /* pv = yi */ if (q == NULL) { Cudd_RecursiveDerefZdd(dd, term1); Cudd_RecursiveDerefZdd(dd, tmp); return(NULL); } Cudd_Ref(q); Cudd_RecursiveDerefZdd(dd, term1); Cudd_RecursiveDerefZdd(dd, tmp); cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, q); Cudd_Deref(q); return(q); } if (v == top_f) v = f->index; else v = g->index; flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd); if (flag == 1) return(NULL); Cudd_Ref(f1); Cudd_Ref(f0); Cudd_Ref(fd); flag = cuddZddGetCofactors3(dd, g, v, &g1, &g0, &gd); if (flag == 1) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, fd); return(NULL); } Cudd_Ref(g1); Cudd_Ref(g0); Cudd_Ref(gd); q = g; if (g0 != zero) { q = cuddZddWeakDivF(dd, f0, g0); if (q == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, g0); Cudd_RecursiveDerefZdd(dd, gd); return(NULL); } Cudd_Ref(q); } else Cudd_Ref(q); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, g0); if (q == zero) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, gd); cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, zero); Cudd_Deref(q); return(zero); } if (g1 != zero) { Cudd_RecursiveDerefZdd(dd, q); tmp = cuddZddWeakDivF(dd, f1, g1); if (tmp == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, gd); return(NULL); } Cudd_Ref(tmp); Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, g1); if (q == g) q = tmp; else { q = cuddZddIntersect(dd, q, tmp); if (q == NULL) { Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, gd); return(NULL); } Cudd_Ref(q); Cudd_RecursiveDerefZdd(dd, tmp); } } else { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, g1); } if (q == zero) { Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, gd); cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, zero); Cudd_Deref(q); return(zero); } if (gd != zero) { Cudd_RecursiveDerefZdd(dd, q); tmp = cuddZddWeakDivF(dd, fd, gd); if (tmp == NULL) { Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, gd); return(NULL); } Cudd_Ref(tmp); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, gd); if (q == g) q = tmp; else { q = cuddZddIntersect(dd, q, tmp); if (q == NULL) { Cudd_RecursiveDerefZdd(dd, tmp); return(NULL); } Cudd_Ref(q); Cudd_RecursiveDerefZdd(dd, tmp); } } else { Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, gd); } cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, q); Cudd_Deref(q); return(q); } /* end of cuddZddWeakDivF */