/**Function******************************************************************** Synopsis [Checks if the two variables are symmetric.] Description [Returns 0 if vars are not symmetric. Return 1 if vars are symmetric.] SideEffects [] SeeAlso [] ******************************************************************************/ int Extra_bddCheckVarsSymmetricNaive( DdManager * dd, /* the DD manager */ DdNode * bF, int iVar1, int iVar2) { DdNode * bCube1, * bCube2; DdNode * bCof01, * bCof10; int Res; assert( iVar1 != iVar2 ); assert( iVar1 < dd->size ); assert( iVar2 < dd->size ); bCube1 = Cudd_bddAnd( dd, Cudd_Not( dd->vars[iVar1] ), dd->vars[iVar2] ); Cudd_Ref( bCube1 ); bCube2 = Cudd_bddAnd( dd, Cudd_Not( dd->vars[iVar2] ), dd->vars[iVar1] ); Cudd_Ref( bCube2 ); bCof01 = Cudd_Cofactor( dd, bF, bCube1 ); Cudd_Ref( bCof01 ); bCof10 = Cudd_Cofactor( dd, bF, bCube2 ); Cudd_Ref( bCof10 ); Res = (int)( bCof10 == bCof01 ); Cudd_RecursiveDeref( dd, bCof01 ); Cudd_RecursiveDeref( dd, bCof10 ); Cudd_RecursiveDeref( dd, bCube1 ); Cudd_RecursiveDeref( dd, bCube2 ); return Res; } /* end of Extra_bddCheckVarsSymmetricNaive */
/**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 [Classifies the variables in the support of two DDs.] Description [Classifies the variables in the support of two DDs <code>f</code> and <code>g</code>, depending on whther they appear in both DDs, only in <code>f</code>, or only in <code>g</code>. Returns 1 if successful; 0 otherwise.] SideEffects [The cubes of the three classes of variables are returned as side effects.] SeeAlso [] ******************************************************************************/ int Cuddaux_ClassifySupport( DdManager * dd /* manager */, DdNode * f /* first DD */, DdNode * g /* second DD */, DdNode ** common /* cube of shared variables */, DdNode ** onlyF /* cube of variables only in f */, DdNode ** onlyG /* cube of variables only in g */) { DdNode *suppF, *suppG; suppF = suppG = *common = *onlyF = *onlyG = NULL; suppF = Cuddaux_Support(dd,f); if (suppF == NULL) goto Cuddaux_ClassifySupport_error; cuddRef(suppF); suppG = Cuddaux_Support(dd,g); if (suppG == NULL) goto Cuddaux_ClassifySupport_error; cuddRef(suppG); *common = Cudd_bddLiteralSetIntersection(dd,suppF,suppG); if (*common == NULL) goto Cuddaux_ClassifySupport_error; cuddRef(*common); *onlyF = Cudd_Cofactor(dd,suppF,*common); if (*onlyF == NULL) goto Cuddaux_ClassifySupport_error; cuddRef(*onlyF); *onlyG = Cudd_Cofactor(dd,suppG,*common); if (*onlyG == NULL) goto Cuddaux_ClassifySupport_error; cuddRef(*onlyG); Cudd_IterDerefBdd(dd,suppF); Cudd_IterDerefBdd(dd,suppG); cuddDeref(*common); cuddDeref(*onlyF); cuddDeref(*onlyG); return 1; Cuddaux_ClassifySupport_error: if (suppF) Cudd_IterDerefBdd(dd,suppF); if (suppG) Cudd_IterDerefBdd(dd,suppG); if (*common){ Cudd_IterDerefBdd(dd,*common); *common = NULL; } if (*onlyF){ Cudd_IterDerefBdd(dd,*onlyF); *onlyF = NULL; } if (*onlyG){ Cudd_IterDerefBdd(dd,*onlyG); *onlyG = NULL; } dd->errorCode = CUDD_MEMORY_OUT; return(0); } /* end of Cuddaux_ClassifySupport */
/**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; }
static keyvalue_table_ptr cudd_restrict(shadow_mgr mgr, set_ptr roots, set_ptr lits) { DdNode *cube = cudd_lit_cube(mgr, lits); keyvalue_table_ptr rtable = word_keyvalue_new(); word_t w; set_iterstart(roots); while (set_iternext(roots, &w)) { ref_t r = (ref_t) w; DdNode *n = get_ddnode(mgr, r); DdNode *nr = Cudd_Cofactor(mgr->bdd_manager, n, cube); reference_dd(mgr, nr); keyvalue_insert(rtable, w, (word_t) nr); } unreference_dd(mgr, cube, IS_BDD); return rtable; }
/**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_MvDecompose( Mv_Man_t * p ) { DdNode * bCofs[16], * bVarCube1, * bVarCube2, * bVarCube, * bCube, * bVar0, * bVar1;//, * bRes; int k, i1, i2, v1, v2;//, c1, c2, Counter; bVar0 = Cudd_bddIthVar(p->dd, 30); bVar1 = Cudd_bddIthVar(p->dd, 31); bCube = Cudd_bddAnd( p->dd, bVar0, bVar1 ); Cudd_Ref( bCube ); for ( k = 0; k < p->nFuncs; k++ ) { printf( "FUNCTION %d\n", k ); for ( i1 = 0; i1 < p->nFuncs; i1++ ) for ( i2 = i1+1; i2 < p->nFuncs; i2++ ) { Vec_Ptr_t * vCofs; for ( v1 = 0; v1 < 4; v1++ ) { bVar0 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 29-2*i1 ), ((v1 & 1) == 0) ); bVar1 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 29-2*i1-1), ((v1 & 2) == 0) ); bVarCube1 = Cudd_bddAnd( p->dd, bVar0, bVar1 ); Cudd_Ref( bVarCube1 ); for ( v2 = 0; v2 < 4; v2++ ) { bVar0 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 29-2*i2 ), ((v2 & 1) == 0) ); bVar1 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 29-2*i2-1), ((v2 & 2) == 0) ); bVarCube2 = Cudd_bddAnd( p->dd, bVar0, bVar1 ); Cudd_Ref( bVarCube2 ); bVarCube = Cudd_bddAnd( p->dd, bVarCube1, bVarCube2 ); Cudd_Ref( bVarCube ); bCofs[v1 * 4 + v2] = Cudd_Cofactor( p->dd, p->bFuncs[k], bVarCube ); Cudd_Ref( bCofs[v1 * 4 + v2] ); Cudd_RecursiveDeref( p->dd, bVarCube ); Cudd_RecursiveDeref( p->dd, bVarCube2 ); } Cudd_RecursiveDeref( p->dd, bVarCube1 ); } /* // check the compatibility of cofactors Counter = 0; for ( c1 = 0; c1 < 16; c1++ ) { for ( c2 = 0; c2 <= c1; c2++ ) printf( " " ); for ( c2 = c1+1; c2 < 16; c2++ ) { bRes = Cudd_bddAndAbstract( p->dd, bCofs[c1], bCofs[c2], bCube ); Cudd_Ref( bRes ); if ( bRes == Cudd_ReadOne(p->dd) ) { printf( "+" ); Counter++; } else { printf( " " ); } Cudd_RecursiveDeref( p->dd, bRes ); } printf( "\n" ); } */ vCofs = Vec_PtrAlloc( 16 ); for ( v1 = 0; v1 < 4; v1++ ) for ( v2 = 0; v2 < 4; v2++ ) Vec_PtrPushUnique( vCofs, bCofs[v1 * 4 + v2] ); printf( "%d ", Vec_PtrSize(vCofs) ); Vec_PtrFree( vCofs ); // free the cofactors for ( v1 = 0; v1 < 4; v1++ ) for ( v2 = 0; v2 < 4; v2++ ) Cudd_RecursiveDeref( p->dd, bCofs[v1 * 4 + v2] ); printf( "\n" ); // printf( "%2d, %2d : %3d\n", i1, i2, Counter ); } } Cudd_RecursiveDeref( p->dd, bCube ); }
/**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 */
/**Function******************************************************************** Synopsis [BDD restrict according to Coudert and Madre's algorithm (ICCAD90).] Description [BDD restrict according to Coudert and Madre's algorithm (ICCAD90). Returns the restricted BDD if successful; otherwise NULL.] SideEffects [None] SeeAlso [Cudd_bddRestrict] ******************************************************************************/ DdNode* Cuddaux_bddRestrict(DdManager * dd, DdNode * f, DdNode * c) { DdNode *one,*zero; DdNode *suppF, *suppC, *commonSupp, *onlyC; DdNode *cplus, *res; int retval; one = DD_ONE(dd); zero = Cudd_Not(one); /* Check terminal cases here to avoid computing supports in trivial cases. ** This also allows us notto check later for the case c == 0, in which ** there is no common support. */ if (c == one) return(f); if (c == zero){ fprintf(stderr,"Cuddaux_bddRestrict: warning: false careset\n"); return(zero); } if (Cudd_IsConstant(f)) return(f); if (f == c) return(one); if (f == Cudd_Not(c)) return(zero); /* Check if supports intersect. */ suppF = Cuddaux_Support(dd,f); if (suppF==NULL) return(NULL); cuddRef(suppF); suppC = Cuddaux_Support(dd,c); if (suppC==NULL){ Cudd_IterDerefBdd(dd,suppF); return(NULL); } cuddRef(suppC); commonSupp = Cudd_bddLiteralSetIntersection(dd,suppF,suppC); if (commonSupp==NULL){ Cudd_IterDerefBdd(dd,suppF); Cudd_IterDerefBdd(dd,suppC); return(NULL); } if (commonSupp == one) { Cudd_IterDerefBdd(dd,suppF); Cudd_IterDerefBdd(dd,suppC); return(f); } cuddRef(commonSupp); Cudd_IterDerefBdd(dd,suppF); /* Abstract from c the variables that do not appear in f. */ onlyC = Cudd_Cofactor(dd,suppC,commonSupp); if (onlyC == NULL) { Cudd_IterDerefBdd(dd,suppC); Cudd_IterDerefBdd(dd,commonSupp); return(NULL); } cuddRef(onlyC); Cudd_IterDerefBdd(dd,suppC); Cudd_IterDerefBdd(dd,commonSupp); cplus = Cudd_bddExistAbstract(dd, c, onlyC); if (cplus == NULL) { Cudd_IterDerefBdd(dd,onlyC); return(NULL); } cuddRef(cplus); Cudd_IterDerefBdd(dd,onlyC); do { dd->reordered = 0; res = cuddBddRestrictRecur(dd, f, cplus); } while (dd->reordered == 1); if (res == NULL) { Cudd_IterDerefBdd(dd,cplus); return(NULL); } cuddRef(res); Cudd_IterDerefBdd(dd,cplus); cuddDeref(res); return(res); } /* end of Cuddaux_bddRestrict */