Saig_ManForEachLi( p, pObj, i ) { bFunc = (DdNode *)pObj->pData; Cudd_Ref( bFunc ); Vec_PtrWriteEntry( vBdds, Aig_ObjId(Saig_ObjLiToLo(p, pObj)), bFunc ); }
/**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 [Deriving the functionality of the gates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mio_GateParseFormula( Mio_Gate_t * pGate ) { DdManager * dd = pGate->pLib->dd; char * pPinNames[100]; char * pPinNamesCopy[100]; Mio_Pin_t * pPin, ** ppPin; int nPins, iPin, i; // set the maximum delay of the gate; count pins pGate->dDelayMax = 0.0; nPins = 0; Mio_GateForEachPin( pGate, pPin ) { // set the maximum delay of the gate if ( pGate->dDelayMax < pPin->dDelayBlockMax ) pGate->dDelayMax = pPin->dDelayBlockMax; // count the pin nPins++; } // check for the gate with const function if ( nPins == 0 ) { if ( strcmp( pGate->pForm, MIO_STRING_CONST0 ) == 0 ) { pGate->bFunc = b0; pGate->pSop = Abc_SopRegister( pGate->pLib->pMmFlex, " 0\n" ); pGate->pLib->pGate0 = pGate; } else if ( strcmp( pGate->pForm, MIO_STRING_CONST1 ) == 0 ) { pGate->bFunc = b1; pGate->pSop = Abc_SopRegister( pGate->pLib->pMmFlex, " 1\n" ); pGate->pLib->pGate1 = pGate; } else { printf( "Cannot parse formula \"%s\" of gate \"%s\".\n", pGate->pForm, pGate->pName ); return 1; } Cudd_Ref( pGate->bFunc ); return 0; } // collect the names as they appear in the formula nPins = Mio_GateCollectNames( pGate->pForm, pPinNames ); if ( nPins == 0 ) { printf( "Cannot read formula \"%s\" of gate \"%s\".\n", pGate->pForm, pGate->pName ); return 1; } // set the number of inputs pGate->nInputs = nPins; // consider the case when all the pins have identical pin info if ( strcmp( pGate->pPins->pName, "*" ) == 0 ) { // get the topmost (generic) pin pPin = pGate->pPins; FREE( pPin->pName ); // create individual pins from the generic pin ppPin = &pPin->pNext; for ( i = 1; i < nPins; i++ ) { // get the new pin *ppPin = Mio_PinDup( pPin ); // set its name (*ppPin)->pName = pPinNames[i]; // prepare the next place in the list ppPin = &((*ppPin)->pNext); } *ppPin = NULL; // set the name of the topmost pin pPin->pName = pPinNames[0]; } else { // reorder the variable names to appear the save way as the pins iPin = 0; Mio_GateForEachPin( pGate, pPin ) { // find the pin with the name pPin->pName for ( i = 0; i < nPins; i++ ) { if ( pPinNames[i] && strcmp( pPinNames[i], pPin->pName ) == 0 ) { // free pPinNames[i] because it is already available as pPin->pName // setting pPinNames[i] to NULL is useful to make sure that // this name is not assigned to two pins in the list FREE( pPinNames[i] ); pPinNamesCopy[iPin++] = pPin->pName; break; } if ( i == nPins ) { printf( "Cannot find pin name \"%s\" in the formula \"%s\" of gate \"%s\".\n", pPin->pName, pGate->pForm, pGate->pName ); return 1; } } } // check for the remaining names for ( i = 0; i < nPins; i++ ) if ( pPinNames[i] ) { printf( "Name \"%s\" appears in the formula \"%s\" of gate \"%s\" but there is no such pin.\n", pPinNames[i], pGate->pForm, pGate->pName ); return 1; } // copy the names back memcpy( pPinNames, pPinNamesCopy, nPins * sizeof(char *) ); } // expand the manager if necessary if ( dd->size < nPins ) { Cudd_Quit( dd ); dd = Cudd_Init( nPins + 10, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); Cudd_zddVarsFromBddVars( dd, 2 ); } // derive the formula as the BDD pGate->bFunc = Parse_FormulaParser( stdout, pGate->pForm, nPins, 0, pPinNames, dd, dd->vars ); Cudd_Ref( pGate->bFunc ); // derive the cover (SOP) pGate->pSop = Abc_ConvertBddToSop( pGate->pLib->pMmFlex, dd, pGate->bFunc, pGate->bFunc, nPins, 0, pGate->pLib->vCube, -1 ); return 0; }
/**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 [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 */
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; }
/* traverse a CFG and encode each edge as a BDD */ DdNode* bdd_convert_cfg(DdManager *m, pos* postab, cfg_node* host, int proc, DdNode* current, DdNode* R, int prev) { DdNode* branch; /* holds branch conditions */ DdNode* tmp1, *tmp2; /* temporary vars for cleanup */ current = bdd_encode_pc(m, current, postab->pc_, postab->pc_size, proc, host->node->id); tmp1 = Cudd_bddOr(m, R, current); /* add the completed edge to the */ Cudd_Ref(tmp1); /* transistion system by disjuncting */ Cudd_RecursiveDeref(m, R); Cudd_RecursiveDeref(m, current); R = tmp1; switch (host->node->tag) { case _assign_stat: /* assignment and skip statements */ case _skip_stat: /* form very similar edges */ if (host->node->tag == _assign_stat) current = bdd_mk_assign(m, postab, host, proc); else if (host->node->tag == _skip_stat) current = bdd_mk_skip(m, postab, host->node->id, proc); break; case _if_then_stat: /* if a branch is encountered, */ case _if_else_stat: /* add the branch condition to the */ case _while_stat: /* edge's encoding and continue */ current = bdd_mk_skip(m, postab, host->node->id, proc); tmp1 = bdd_expr(m, postab->vars, host->node->children[EXPR]); branch = Cudd_bddAnd(m, tmp1, current); Cudd_Ref(branch); /* conjunct branch condition to branch */ tmp2 = Cudd_bddAnd(m, Cudd_Not(tmp1), current); Cudd_Ref(tmp2); /* conjuct complement of the branch */ Cudd_RecursiveDeref(m, tmp1); /* condition to current */ Cudd_RecursiveDeref(m, current); current = tmp2; if (host->node->id < prev) /* terminate after back edge */ return R; else { /* traverse the 'true' branch */ tmp1 = bdd_convert_cfg(m, postab, host->succ[CFG_IF | CFG_WHILE], proc, branch, R, prev); Cudd_RecursiveDeref(m, R); } break; case _await_stat: /* await is both a branch and a skip */ tmp1 = bdd_mk_skip(m, postab, host->node->id, proc); tmp2 = bdd_expr(m, postab->vars, host->node->children[EXPR]); current = Cudd_bddAnd(m, tmp1, tmp2); Cudd_Ref(current); /* conjunct branch condition to current */ branch = Cudd_bddAnd(m, tmp1, Cudd_Not(tmp2)); Cudd_Ref(branch); /* conjuct complement of the branch */ Cudd_RecursiveDeref(m, tmp1); /* condition to branch */ Cudd_RecursiveDeref(m, tmp2); /* branch is a self-referential edge */ branch = bdd_encode_pc(m, branch, postab->pc_, postab->pc_size, proc, host->node->id); tmp1 = Cudd_bddOr(m, R, branch); Cudd_Ref(tmp1); Cudd_RecursiveDeref(m, R); Cudd_RecursiveDeref(m, branch); /* continue edge continues to next node */ break; default: printf("Error: invalid statement in CFG\n"); exit(1); } if (host->succ[CONTINUE]) { /* if the node has a successor */ R = bdd_convert_cfg(m, postab, host->succ[CONTINUE], proc, current, tmp1, host->node->id); Cudd_RecursiveDeref(m, tmp1); /* initiate new edge and call again */ } else { /* if the node terminates a branch */ current = bdd_encode_pc(m, current, postab->pc_, postab->pc_size, proc, host->node->id); R = Cudd_bddOr(m, tmp1, current); Cudd_Ref(R); /* terminate node with an infinite loop */ Cudd_RecursiveDeref(m, tmp1); Cudd_RecursiveDeref(m, current); } return R; /* return complete transition relation */ }
DdNode *compute_winning_set_BDD( DdManager *manager, DdNode *etrans, DdNode *strans, DdNode **egoals, DdNode **sgoals, unsigned char verbose ) { DdNode *X = NULL, *X_prev = NULL; DdNode *Y = NULL, *Y_exmod = NULL, *Y_prev = NULL; DdNode **Z = NULL, **Z_prev = NULL; bool Z_changed; /* Use to detect occurrence of fixpoint for all Z_i */ /* Fixpoint iteration counters */ int num_it_Z, num_it_Y, num_it_X; DdNode *tmp, *tmp2; int i, j; /* Generic counters */ DdNode **vars, **pvars; int num_env, num_sys; int *cube; /* length will be twice total number of variables (to account for both variables and their primes). */ num_env = tree_size( spc.evar_list ); num_sys = tree_size( spc.svar_list ); /* Allocate cube array, used later for quantifying over variables. */ cube = (int *)malloc( sizeof(int)*2*(num_env+num_sys) ); if (cube == NULL) { perror( __FILE__ ", malloc" ); exit(-1); } /* Define a map in the manager to easily swap variables with their primed selves. */ vars = malloc( (num_env+num_sys)*sizeof(DdNode *) ); pvars = malloc( (num_env+num_sys)*sizeof(DdNode *) ); for (i = 0; i < num_env+num_sys; i++) { *(vars+i) = Cudd_bddIthVar( manager, i ); *(pvars+i) = Cudd_bddIthVar( manager, i+num_env+num_sys ); } if (!Cudd_SetVarMap( manager, vars, pvars, num_env+num_sys )) { fprintf( stderr, "Error: failed to define variable map in CUDD manager.\n" ); free( cube ); return NULL; } free( vars ); free( pvars ); if (spc.num_sgoals > 0) { Z = malloc( spc.num_sgoals*sizeof(DdNode *) ); Z_prev = malloc( spc.num_sgoals*sizeof(DdNode *) ); for (i = 0; i < spc.num_sgoals; i++) { *(Z+i) = NULL; *(Z_prev+i) = NULL; } } /* Initialize */ for (i = 0; i < spc.num_sgoals; i++) { *(Z+i) = Cudd_ReadOne( manager ); Cudd_Ref( *(Z+i) ); } num_it_Z = 0; do { num_it_Z++; if (verbose > 1) { logprint( "Z iteration %d", num_it_Z ); logprint( "Cudd_ReadMemoryInUse (bytes): %d", Cudd_ReadMemoryInUse( manager ) ); } for (i = 0; i < spc.num_sgoals; i++) { if (*(Z_prev+i) != NULL) Cudd_RecursiveDeref( manager, *(Z_prev+i) ); *(Z_prev+i) = *(Z+i); } for (i = 0; i < spc.num_sgoals; i++) { if (i == spc.num_sgoals-1) { *(Z+i) = compute_existsmodal( manager, *Z_prev, etrans, strans, num_env, num_sys, cube ); } else { *(Z+i) = compute_existsmodal( manager, *(Z_prev+i+1), etrans, strans, num_env, num_sys, cube ); } if (*(Z+i) == NULL) { /* fatal error */ return NULL; } /* (Re)initialize Y */ if (Y != NULL) Cudd_RecursiveDeref( manager, Y ); Y = Cudd_Not( Cudd_ReadOne( manager ) ); Cudd_Ref( Y ); num_it_Y = 0; do { num_it_Y++; if (verbose > 1) { logprint( "\tY iteration %d", num_it_Y ); logprint( "\tCudd_ReadMemoryInUse (bytes): %d", Cudd_ReadMemoryInUse( manager ) ); } if (Y_prev != NULL) Cudd_RecursiveDeref( manager, Y_prev ); Y_prev = Y; if (Y_exmod != NULL) Cudd_RecursiveDeref( manager, Y_exmod ); Y_exmod = compute_existsmodal( manager, Y_prev, etrans, strans, num_env, num_sys, cube ); if (Y_exmod == NULL) { /* fatal error */ return NULL; } Y = Cudd_Not( Cudd_ReadOne( manager ) ); Cudd_Ref( Y ); for (j = 0; j < spc.num_egoals; j++) { /* (Re)initialize X */ if (X != NULL) Cudd_RecursiveDeref( manager, X ); X = Cudd_ReadOne( manager ); Cudd_Ref( X ); /* Greatest fixpoint for X, for this env goal */ num_it_X = 0; do { num_it_X++; if (verbose > 1) { logprint( "\t\tX iteration %d", num_it_X ); logprint( "\t\tCudd_ReadMemoryInUse (bytes): %d", Cudd_ReadMemoryInUse( manager ) ); } if (X_prev != NULL) Cudd_RecursiveDeref( manager, X_prev ); X_prev = X; X = compute_existsmodal( manager, X_prev, etrans, strans, num_env, num_sys, cube ); if (X == NULL) { /* fatal error */ return NULL; } tmp = Cudd_bddAnd( manager, *(sgoals+i), *(Z+i) ); Cudd_Ref( tmp ); tmp2 = Cudd_bddOr( manager, tmp, Y_exmod ); Cudd_Ref( tmp2 ); Cudd_RecursiveDeref( manager, tmp ); tmp = Cudd_bddAnd( manager, X, Cudd_Not( *(egoals+j) ) ); Cudd_Ref( tmp ); Cudd_RecursiveDeref( manager, X ); X = Cudd_bddOr( manager, tmp2, tmp ); Cudd_Ref( X ); Cudd_RecursiveDeref( manager, tmp ); Cudd_RecursiveDeref( manager, tmp2 ); tmp = X; X = Cudd_bddAnd( manager, X, X_prev ); Cudd_Ref( X ); Cudd_RecursiveDeref( manager, tmp ); } while (!Cudd_bddLeq( manager, X, X_prev ) || !Cudd_bddLeq( manager, X_prev, X )); tmp = Y; Y = Cudd_bddOr( manager, Y, X ); Cudd_Ref( Y ); Cudd_RecursiveDeref( manager, tmp ); Cudd_RecursiveDeref( manager, X ); X = NULL; Cudd_RecursiveDeref( manager, X_prev ); X_prev = NULL; } tmp2 = Y; Y = Cudd_bddOr( manager, Y, Y_prev ); Cudd_Ref( Y ); Cudd_RecursiveDeref( manager, tmp2 ); } while (!Cudd_bddLeq( manager, Y, Y_prev ) || !Cudd_bddLeq( manager, Y_prev, Y )); Cudd_RecursiveDeref( manager, *(Z+i) ); *(Z+i) = Cudd_bddAnd( manager, Y, *(Z_prev+i) ); Cudd_Ref( *(Z+i) ); Cudd_RecursiveDeref( manager, Y ); Y = NULL; Cudd_RecursiveDeref( manager, Y_prev ); Y_prev = NULL; Cudd_RecursiveDeref( manager, Y_exmod ); Y_exmod = NULL; } Z_changed = False; for (i = 0; i < spc.num_sgoals; i++) { if (!Cudd_bddLeq( manager, *(Z+i), *(Z_prev+i) ) || !Cudd_bddLeq( manager, *(Z_prev+i), *(Z+i) )) { Z_changed = True; break; } } } while (Z_changed); /* Pre-exit clean-up */ tmp = *Z; Cudd_RecursiveDeref( manager, *Z_prev ); for (i = 1; i < spc.num_sgoals; i++) { Cudd_RecursiveDeref( manager, *(Z+i) ); Cudd_RecursiveDeref( manager, *(Z_prev+i) ); } free( Z ); free( Z_prev ); free( cube ); return tmp; }
void I_BDD_new_mutex_domain (DdManager *dd, DdNode *node[], unsigned int size) { unsigned int shbuf, vars, ctr; DdNode **ddVar, *one, *newnode, *oldnode, *bitnode; int i,j, extra; /* base cases */ if (size == 0) { return; } one = Cudd_ReadOne(dd); if (size == 1) { node[0] = one; Cudd_Ref (node[0]); return; } for(shbuf = size - 1, vars = 0; shbuf != 0; shbuf >>= 1, vars++); extra = (1 << vars) - size; ddVar = malloc(vars * sizeof(DdNode *)); for (j = 0; j < vars; j++) { ddVar[j] = bitnode = Cudd_bddNewVar (dd); Cudd_Ref (bitnode); } ctr = 0; for (i = 0; i < size; i++, ctr++) { newnode = one; Cudd_Ref (newnode); #ifdef I_BDD_MUTEX_DEBUG printf("i%d:", i); #endif for (j = (extra > 0); j < vars; j++) { bitnode = (ctr & (1 << j)) ? ddVar[j] : Cudd_Not(ddVar[j]); newnode = Cudd_bddAnd (dd, bitnode, oldnode = newnode); Cudd_Ref (newnode); Cudd_RecursiveDeref (dd, oldnode); #ifdef I_BDD_MUTEX_DEBUG if (ctr & (1 << j)) printf("+ v%d ", j); else printf("+ !v%d ", j); #endif } #ifdef I_BDD_MUTEX_DEBUG printf ("\n"); #endif node[i] = newnode; if (extra > 0) { extra--; ctr++; } } #ifdef I_BDD_MUTEX_TEST { DdNode *test, *old_test; int i; test = Cudd_ReadLogicZero(dd); Cudd_Ref (test); for (i = 0; i < size; i++) { if (Cudd_bddIte (dd, test, node[i], zero) != zero) I_punt("I_BDD_new_mutex_complex: not mutex!"); test = Cudd_bddIte(dd, node[i], one, old_test = test); Cudd_Ref (test); Cudd_RecursiveDeref (dd, old_test); } if (test != one) I_punt("I_BDD_new_mutex_complex: not exhaustive!"); Cudd_RecursiveDeref (dd, test); } #endif for (j = 0; j < vars; j++) Cudd_RecursiveDeref (dd, ddVar[j]); free (ddVar); return; }
/**Function******************************************************************** Synopsis [Main function for testcudd.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ int main(int argc, char **argv) { FILE *fp; /* pointer to input file */ char *file = ""; /* input file name */ FILE *dfp = NULL; /* pointer to dump file */ char *dfile; /* file for DD dump */ DdNode *dfunc[2]; /* addresses of the functions to be dumped */ DdManager *dd; /* pointer to DD manager */ DdNode *one, *zero; /* fast access to constant functions */ DdNode *M; DdNode **x; /* pointers to variables */ DdNode **y; /* pointers to variables */ DdNode **xn; /* complements of row variables */ DdNode **yn_; /* complements of column variables */ DdNode **xvars; DdNode **yvars; DdNode *C; /* result of converting from ADD to BDD */ DdNode *ess; /* cube of essential variables */ DdNode *shortP; /* BDD cube of shortest path */ DdNode *largest; /* BDD of largest cube */ DdNode *shortA; /* ADD cube of shortest path */ DdNode *constN; /* value returned by evaluation of ADD */ DdNode *ycube; /* cube of the negated y vars for c-proj */ DdNode *CP; /* C-Projection of C */ DdNode *CPr; /* C-Selection of C */ int length; /* length of the shortest path */ int nx; /* number of variables */ int ny; int maxnx; int maxny; int m; int n; int N; int cmu; /* use CMU multiplication */ int pr; /* verbose printout level */ int harwell; int multiple; /* read multiple matrices */ int ok; int c; /* variable to read in options */ int approach; /* reordering approach */ int autodyn; /* automatic reordering */ int groupcheck; /* option for group sifting */ int profile; /* print heap profile if != 0 */ int keepperm; /* keep track of permutation */ int clearcache; /* clear the cache after each matrix */ int blifOrDot; /* dump format: 0 -> dot, 1 -> blif, ... */ int retval; /* return value */ int i; /* loop index */ long startTime; /* initial time */ long lapTime; int size; unsigned int cacheSize, maxMemory; unsigned int nvars,nslots; startTime = util_cpu_time(); approach = CUDD_REORDER_NONE; autodyn = 0; pr = 0; harwell = 0; multiple = 0; profile = 0; keepperm = 0; cmu = 0; N = 4; nvars = 4; cacheSize = 127; maxMemory = 0; nslots = CUDD_UNIQUE_SLOTS; clearcache = 0; groupcheck = CUDD_GROUP_CHECK7; dfile = NULL; blifOrDot = 0; /* dot format */ /* Parse command line. */ while ((c = util_getopt(argc, argv, "CDHMPS:a:bcd:g:hkmn:p:v:x:X:")) != EOF) { switch(c) { case 'C': cmu = 1; break; case 'D': autodyn = 1; break; case 'H': harwell = 1; break; case 'M': #ifdef MNEMOSYNE (void) mnem_setrecording(0); #endif break; case 'P': profile = 1; break; case 'S': nslots = atoi(util_optarg); break; case 'X': maxMemory = atoi(util_optarg); break; case 'a': approach = atoi(util_optarg); break; case 'b': blifOrDot = 1; /* blif format */ break; case 'c': clearcache = 1; break; case 'd': dfile = util_optarg; break; case 'g': groupcheck = atoi(util_optarg); break; case 'k': keepperm = 1; break; case 'm': multiple = 1; break; case 'n': N = atoi(util_optarg); break; case 'p': pr = atoi(util_optarg); break; case 'v': nvars = atoi(util_optarg); break; case 'x': cacheSize = atoi(util_optarg); break; case 'h': default: usage(argv[0]); break; } } if (argc - util_optind == 0) { file = "-"; } else if (argc - util_optind == 1) { file = argv[util_optind]; } else { usage(argv[0]); } if ((approach<0) || (approach>17)) { (void) fprintf(stderr,"Invalid approach: %d \n",approach); usage(argv[0]); } if (pr >= 0) { (void) printf("# %s\n", TESTCUDD_VERSION); /* Echo command line and arguments. */ (void) printf("#"); for (i = 0; i < argc; i++) { (void) printf(" %s", argv[i]); } (void) printf("\n"); (void) fflush(stdout); } /* Initialize manager and provide easy reference to terminals. */ dd = Cudd_Init(nvars,0,nslots,cacheSize,maxMemory); one = DD_ONE(dd); zero = DD_ZERO(dd); dd->groupcheck = (Cudd_AggregationType) groupcheck; if (autodyn) Cudd_AutodynEnable(dd,CUDD_REORDER_SAME); /* Open input file. */ fp = open_file(file, "r"); /* Open dump file if requested */ if (dfile != NULL) { dfp = open_file(dfile, "w"); } x = y = xn = yn_ = NULL; do { /* We want to start anew for every matrix. */ maxnx = maxny = 0; nx = maxnx; ny = maxny; if (pr>0) lapTime = util_cpu_time(); if (harwell) { if (pr >= 0) (void) printf(":name: "); ok = Cudd_addHarwell(fp, dd, &M, &x, &y, &xn, &yn_, &nx, &ny, &m, &n, 0, 2, 1, 2, pr); } else { ok = Cudd_addRead(fp, dd, &M, &x, &y, &xn, &yn_, &nx, &ny, &m, &n, 0, 2, 1, 2); if (pr >= 0) (void) printf(":name: %s: %d rows %d columns\n", file, m, n); } if (!ok) { (void) fprintf(stderr, "Error reading matrix\n"); exit(1); } if (nx > maxnx) maxnx = nx; if (ny > maxny) maxny = ny; /* Build cube of negated y's. */ ycube = DD_ONE(dd); Cudd_Ref(ycube); for (i = maxny - 1; i >= 0; i--) { DdNode *tmpp; tmpp = Cudd_bddAnd(dd,Cudd_Not(dd->vars[y[i]->index]),ycube); if (tmpp == NULL) exit(2); Cudd_Ref(tmpp); Cudd_RecursiveDeref(dd,ycube); ycube = tmpp; } /* Initialize vectors of BDD variables used by priority func. */ xvars = ALLOC(DdNode *, nx); if (xvars == NULL) exit(2); for (i = 0; i < nx; i++) { xvars[i] = dd->vars[x[i]->index]; } yvars = ALLOC(DdNode *, ny); if (yvars == NULL) exit(2); for (i = 0; i < ny; i++) { yvars[i] = dd->vars[y[i]->index]; } /* Clean up */ for (i=0; i < maxnx; i++) { Cudd_RecursiveDeref(dd, x[i]); Cudd_RecursiveDeref(dd, xn[i]); } FREE(x); FREE(xn); for (i=0; i < maxny; i++) { Cudd_RecursiveDeref(dd, y[i]); Cudd_RecursiveDeref(dd, yn_[i]); } FREE(y); FREE(yn_); if (pr>0) {(void) printf(":1: M"); Cudd_PrintDebug(dd,M,nx+ny,pr);} if (pr>0) (void) printf(":2: time to read the matrix = %s\n", util_print_time(util_cpu_time() - lapTime)); C = Cudd_addBddPattern(dd, M); if (C == 0) exit(2); Cudd_Ref(C); if (pr>0) {(void) printf(":3: C"); Cudd_PrintDebug(dd,C,nx+ny,pr);} /* Test iterators. */ retval = testIterators(dd,M,C,pr); if (retval == 0) exit(2); cuddCacheProfile(dd,stdout); /* Test XOR */ retval = testXor(dd,C,pr,nx+ny); if (retval == 0) exit(2); /* Test Hamming distance functions. */ retval = testHamming(dd,C,pr,nx+ny); if (retval == 0) exit(2); /* Test selection functions. */ CP = Cudd_CProjection(dd,C,ycube); if (CP == NULL) exit(2); Cudd_Ref(CP); if (pr>0) {(void) printf("ycube"); Cudd_PrintDebug(dd,ycube,nx+ny,pr);} if (pr>0) {(void) printf("CP"); Cudd_PrintDebug(dd,CP,nx+ny,pr);} if (nx == ny) { CPr = Cudd_PrioritySelect(dd,C,xvars,yvars,(DdNode **)NULL, (DdNode *)NULL,ny,Cudd_Xgty); if (CPr == NULL) exit(2); Cudd_Ref(CPr); if (pr>0) {(void) printf(":4: CPr"); Cudd_PrintDebug(dd,CPr,nx+ny,pr);} if (CP != CPr) { (void) printf("CP != CPr!\n"); } Cudd_RecursiveDeref(dd, CPr); } FREE(xvars); FREE(yvars); Cudd_RecursiveDeref(dd, CP); Cudd_RecursiveDeref(dd, ycube); /* Test functions for essential variables. */ ess = Cudd_FindEssential(dd,C); if (ess == NULL) exit(2); Cudd_Ref(ess); if (pr>0) {(void) printf(":4: ess"); Cudd_PrintDebug(dd,ess,nx+ny,pr);} Cudd_RecursiveDeref(dd, ess); /* Test functions for shortest paths. */ shortP = Cudd_ShortestPath(dd, M, NULL, NULL, &length); if (shortP == NULL) exit(2); Cudd_Ref(shortP); if (pr>0) { (void) printf(":5: shortP"); Cudd_PrintDebug(dd,shortP,nx+ny,pr); } /* Test functions for largest cubes. */ largest = Cudd_LargestCube(dd, Cudd_Not(C), &length); if (largest == NULL) exit(2); Cudd_Ref(largest); if (pr>0) { (void) printf(":5b: largest"); Cudd_PrintDebug(dd,largest,nx+ny,pr); } Cudd_RecursiveDeref(dd, largest); /* Test Cudd_addEvalConst and Cudd_addIteConstant. */ shortA = Cudd_BddToAdd(dd,shortP); if (shortA == NULL) exit(2); Cudd_Ref(shortA); Cudd_RecursiveDeref(dd, shortP); constN = Cudd_addEvalConst(dd,shortA,M); if (constN == DD_NON_CONSTANT) exit(2); if (Cudd_addIteConstant(dd,shortA,M,constN) != constN) exit(2); if (pr>0) {(void) printf("The value of M along the chosen shortest path is %g\n", cuddV(constN));} Cudd_RecursiveDeref(dd, shortA); shortP = Cudd_ShortestPath(dd, C, NULL, NULL, &length); if (shortP == NULL) exit(2); Cudd_Ref(shortP); if (pr>0) { (void) printf(":6: shortP"); Cudd_PrintDebug(dd,shortP,nx+ny,pr); } /* Test Cudd_bddIteConstant and Cudd_bddLeq. */ if (!Cudd_bddLeq(dd,shortP,C)) exit(2); if (Cudd_bddIteConstant(dd,Cudd_Not(shortP),one,C) != one) exit(2); Cudd_RecursiveDeref(dd, shortP); if (profile) { retval = cuddHeapProfile(dd); } size = dd->size; if (pr>0) { (void) printf("Average distance: %g\n", Cudd_AverageDistance(dd)); } /* Reorder if so requested. */ if (approach != CUDD_REORDER_NONE) { #ifndef DD_STATS retval = Cudd_EnableReorderingReporting(dd); if (retval == 0) { (void) fprintf(stderr,"Error reported by Cudd_EnableReorderingReporting\n"); exit(3); } #endif #ifdef DD_DEBUG retval = Cudd_DebugCheck(dd); if (retval != 0) { (void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n"); exit(3); } retval = Cudd_CheckKeys(dd); if (retval != 0) { (void) fprintf(stderr,"Error reported by Cudd_CheckKeys\n"); exit(3); } #endif retval = Cudd_ReduceHeap(dd,(Cudd_ReorderingType)approach,5); if (retval == 0) { (void) fprintf(stderr,"Error reported by Cudd_ReduceHeap\n"); exit(3); } #ifndef DD_STATS retval = Cudd_DisableReorderingReporting(dd); if (retval == 0) { (void) fprintf(stderr,"Error reported by Cudd_DisableReorderingReporting\n"); exit(3); } #endif #ifdef DD_DEBUG retval = Cudd_DebugCheck(dd); if (retval != 0) { (void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n"); exit(3); } retval = Cudd_CheckKeys(dd); if (retval != 0) { (void) fprintf(stderr,"Error reported by Cudd_CheckKeys\n"); exit(3); } #endif if (approach == CUDD_REORDER_SYMM_SIFT || approach == CUDD_REORDER_SYMM_SIFT_CONV) { Cudd_SymmProfile(dd,0,dd->size-1); } if (pr>0) { (void) printf("Average distance: %g\n", Cudd_AverageDistance(dd)); } if (keepperm) { /* Print variable permutation. */ (void) printf("Variable Permutation:"); for (i=0; i<size; i++) { if (i%20 == 0) (void) printf("\n"); (void) printf("%d ", dd->invperm[i]); } (void) printf("\n"); (void) printf("Inverse Permutation:"); for (i=0; i<size; i++) { if (i%20 == 0) (void) printf("\n"); (void) printf("%d ", dd->perm[i]); } (void) printf("\n"); } if (pr>0) {(void) printf("M"); Cudd_PrintDebug(dd,M,nx+ny,pr);} if (profile) { retval = cuddHeapProfile(dd); } } /* Dump DDs of C and M if so requested. */ if (dfile != NULL) { dfunc[0] = C; dfunc[1] = M; if (blifOrDot == 1) { /* Only dump C because blif cannot handle ADDs */ retval = Cudd_DumpBlif(dd,1,dfunc,NULL,onames,NULL,dfp); } else { retval = Cudd_DumpDot(dd,2,dfunc,NULL,onames,dfp); } if (retval != 1) { (void) fprintf(stderr,"abnormal termination\n"); exit(2); } } Cudd_RecursiveDeref(dd, C); Cudd_RecursiveDeref(dd, M); if (clearcache) { if (pr>0) {(void) printf("Clearing the cache... ");} for (i = dd->cacheSlots - 1; i>=0; i--) { dd->cache[i].data = NIL(DdNode); } if (pr>0) {(void) printf("done\n");} } if (pr>0) { (void) printf("Number of variables = %6d\t",dd->size); (void) printf("Number of slots = %6d\n",dd->slots); (void) printf("Number of keys = %6d\t",dd->keys); (void) printf("Number of min dead = %6d\n",dd->minDead); } } while (multiple && !feof(fp)); fclose(fp); if (dfile != NULL) { fclose(dfp); } /* Second phase: experiment with Walsh matrices. */ if (!testWalsh(dd,N,cmu,approach,pr)) { exit(2); } /* Check variable destruction. */ assert(cuddDestroySubtables(dd,3)); assert(Cudd_DebugCheck(dd) == 0); assert(Cudd_CheckKeys(dd) == 0); retval = Cudd_CheckZeroRef(dd); ok = retval != 0; /* ok == 0 means O.K. */ if (retval != 0) { (void) fprintf(stderr, "%d non-zero DD reference counts after dereferencing\n", retval); } if (pr >= 0) { (void) Cudd_PrintInfo(dd,stdout); } Cudd_Quit(dd); #ifdef MNEMOSYNE mnem_writestats(); #endif if (pr>0) (void) printf("total time = %s\n", util_print_time(util_cpu_time() - startTime)); if (pr >= 0) util_print_cpu_stats(stdout); exit(ok); /* NOTREACHED */ } /* end of main */
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 [Tests Walsh matrix multiplication.] Description [Tests Walsh matrix multiplication. Return 1 if successful; 0 otherwise.] SideEffects [May create new variables in the manager.] SeeAlso [] ******************************************************************************/ static int testWalsh( DdManager *dd /* manager */, int N /* number of variables */, int cmu /* use CMU approach to matrix multiplication */, int approach /* reordering approach */, int pr /* verbosity level */) { DdNode *walsh1, *walsh2, *wtw; DdNode **x, **v, **z; int i, retval; DdNode *one = DD_ONE(dd); DdNode *zero = DD_ZERO(dd); if (N > 3) { x = ALLOC(DdNode *,N); v = ALLOC(DdNode *,N); z = ALLOC(DdNode *,N); for (i = N-1; i >= 0; i--) { Cudd_Ref(x[i]=cuddUniqueInter(dd,3*i,one,zero)); Cudd_Ref(v[i]=cuddUniqueInter(dd,3*i+1,one,zero)); Cudd_Ref(z[i]=cuddUniqueInter(dd,3*i+2,one,zero)); } Cudd_Ref(walsh1 = Cudd_addWalsh(dd,v,z,N)); if (pr>0) {(void) printf("walsh1"); Cudd_PrintDebug(dd,walsh1,2*N,pr);} Cudd_Ref(walsh2 = Cudd_addWalsh(dd,x,v,N)); if (cmu) { Cudd_Ref(wtw = Cudd_addTimesPlus(dd,walsh2,walsh1,v,N)); } else { Cudd_Ref(wtw = Cudd_addMatrixMultiply(dd,walsh2,walsh1,v,N)); } if (pr>0) {(void) printf("wtw"); Cudd_PrintDebug(dd,wtw,2*N,pr);} if (approach != CUDD_REORDER_NONE) { #ifdef DD_DEBUG retval = Cudd_DebugCheck(dd); if (retval != 0) { (void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n"); return(0); } #endif retval = Cudd_ReduceHeap(dd,(Cudd_ReorderingType)approach,5); if (retval == 0) { (void) fprintf(stderr,"Error reported by Cudd_ReduceHeap\n"); return(0); } #ifdef DD_DEBUG retval = Cudd_DebugCheck(dd); if (retval != 0) { (void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n"); return(0); } #endif if (approach == CUDD_REORDER_SYMM_SIFT || approach == CUDD_REORDER_SYMM_SIFT_CONV) { Cudd_SymmProfile(dd,0,dd->size-1); } } /* Clean up. */ Cudd_RecursiveDeref(dd, wtw); Cudd_RecursiveDeref(dd, walsh1); Cudd_RecursiveDeref(dd, walsh2); for (i=0; i < N; i++) { Cudd_RecursiveDeref(dd, x[i]); Cudd_RecursiveDeref(dd, v[i]); Cudd_RecursiveDeref(dd, z[i]); } FREE(x); FREE(v); FREE(z); }
/**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 [Creates the DD from the internal reordering data structure.] Description [It is important that the hash table is lossless.] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * reoTransferUnitsToNodes_rec( reo_man * p, reo_unit * pUnit ) { DdManager * dd = p->dd; DdNode * bRes, * E, * T; int HKey, fComp; fComp = Cudd_IsComplement(pUnit); pUnit = Unit_Regular(pUnit); // check the hash-table if ( pUnit->n != 1 ) { for ( HKey = hashKey2(p->Signature,pUnit,p->nTableSize); p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize ) if ( p->HTable[HKey].Arg1 == pUnit ) { bRes = (DdNode*) p->HTable[HKey].Arg2; assert( bRes ); return Cudd_NotCond( bRes, fComp ); } } // treat the case of constants if ( Unit_IsConstant(pUnit) ) { bRes = cuddUniqueConst( dd, ((double)((int)(pUnit->pE))) ); cuddRef( bRes ); } else { // split and recur on children of this node E = reoTransferUnitsToNodes_rec( p, pUnit->pE ); if ( E == NULL ) return NULL; cuddRef(E); T = reoTransferUnitsToNodes_rec( p, pUnit->pT ); if ( T == NULL ) { Cudd_RecursiveDeref(dd, E); return NULL; } cuddRef(T); // consider the case when Res0 and Res1 are the same node assert( E != T ); assert( !Cudd_IsComplement(T) ); bRes = cuddUniqueInter( dd, p->pMapToDdVarsFinal[pUnit->lev], T, E ); if ( bRes == NULL ) { Cudd_RecursiveDeref(dd,E); Cudd_RecursiveDeref(dd,T); return NULL; } cuddRef( bRes ); cuddDeref( E ); cuddDeref( T ); } // do not keep the result if the ref count is only 1, since it will not be visited again if ( pUnit->n != 1 ) { // while we traversed the diagram, the hash entry to which HKey points, // might have been used. Make sure that its signature is different. for ( ; p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize ); p->HTable[HKey].Sign = p->Signature; p->HTable[HKey].Arg1 = pUnit; p->HTable[HKey].Arg2 = (reo_unit *)bRes; // add the DD to the referenced DD list in order to be able to store it in cache p->pRefNodes[p->nRefNodes++] = bRes; Cudd_Ref( bRes ); // no need to do this, because the garbage collection will not take bRes away // it is held by the diagram in the making } // increment the counter of nodes p->nNodesCur++; cuddDeref( bRes ); return Cudd_NotCond( bRes, fComp ); }
/**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 */
/** * @brief Basic test of long double and EPD minterm computation. * @return 0 if successful; -1 otherwise. */ static int testLdbl(int verbosity) { DdManager *dd; DdNode *f, *g; int i, ret; int const N = 12; /* half the number of variables */ long double cnt; dd = Cudd_Init(2*N, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0); if (!dd) { if (verbosity) { printf("initialization failed\n"); } return -1; } f = g = Cudd_ReadOne(dd); Cudd_Ref(f); Cudd_Ref(g); for (i = 0; i < N; i++) { DdNode *var1, *var2, *clause, *tmp; var1 = Cudd_bddIthVar(dd, i); var2 = Cudd_bddIthVar(dd, i+N); clause = Cudd_bddOr(dd, var1, var2); if (!clause) { Cudd_Quit(dd); return -1; } Cudd_Ref(clause); tmp = Cudd_bddAnd(dd, f, clause); if (!tmp) { Cudd_Quit(dd); return -1; } Cudd_Ref(tmp); Cudd_RecursiveDeref(dd, clause); Cudd_RecursiveDeref(dd, f); f = tmp; clause = Cudd_bddOr(dd, Cudd_Not(var1), Cudd_Not(var2)); if (!clause) { Cudd_Quit(dd); return -1; } Cudd_Ref(clause); tmp = Cudd_bddAnd(dd, g, clause); if (!tmp) { Cudd_Quit(dd); return -1; } Cudd_Ref(tmp); Cudd_RecursiveDeref(dd, clause); Cudd_RecursiveDeref(dd, g); g = tmp; } if (verbosity) { printf("f"); Cudd_PrintSummary(dd, f, 2*N, 0); } cnt = Cudd_LdblCountMinterm(dd, f, 2*N); if (verbosity) { printf("f has %Lg minterms\n", cnt); } if (verbosity) { printf("EPD count for f = "); ret = Cudd_EpdPrintMinterm(dd, f, 2*N); printf("\n"); if (!ret) { printf("problem with EPD\n"); } } Cudd_RecursiveDeref(dd, f); if (verbosity) { printf("g"); Cudd_PrintSummary(dd, g, 2*N, 0); } cnt = Cudd_LdblCountMinterm(dd, g, 2*N); if (verbosity) { printf("g has %Lg minterms\n", cnt); } if (verbosity) { printf("EPD count for g = "); ret = Cudd_EpdPrintMinterm(dd, g, 2*N); printf("\n"); if (!ret) { printf("problem with EPD\n"); } } Cudd_RecursiveDeref(dd, g); ret = Cudd_CheckZeroRef(dd); if (verbosity && ret != 0) { printf("%d non-zero references\n", ret); } Cudd_Quit(dd); return 0; }
/**Function************************************************************* Synopsis [Reorders the DD using REO and CUDD.] Description [This function can be used to test the performance of the reordering package.] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_ShuffleTest( reo_man * pReo, DdManager * dd, DdNode * Func ) { // extern int runtime1, runtime2; DdNode * Temp, * bRemap; int nSuppSize, OffSet, Num, i; clock_t clk; int pOrder[1000], pOrderInv[1000]; assert( dd->size < 1000 ); srand( 0x12341234 ); nSuppSize = Cudd_SupportSize( dd, Func ); if ( nSuppSize < 2 ) return; for ( i = 0; i < nSuppSize; i++ ) pOrder[i] = i; for ( i = 0; i < 120; i++ ) { OffSet = rand() % (nSuppSize - 1); Num = pOrder[OffSet]; pOrder[OffSet] = pOrder[OffSet+1]; pOrder[OffSet+1] = Num; } for ( i = 0; i < nSuppSize; i++ ) pOrderInv[pOrder[i]] = i; /* printf( "Permutation: " ); for ( i = 0; i < nSuppSize; i++ ) printf( "%d ", pOrder[i] ); printf( "\n" ); printf( "Inverse permutation: " ); for ( i = 0; i < nSuppSize; i++ ) printf( "%d ", pOrderInv[i] ); printf( "\n" ); */ // create permutation // Extra_ReorderSetVerification( pReo, 1 ); bRemap = Extra_bddRemapUp( dd, Func ); Cudd_Ref( bRemap ); clk = clock(); Temp = reoShuffle( pReo, dd, bRemap, pOrder, pOrderInv ); Cudd_Ref( Temp ); //runtime1 += clock() - clk; //printf( "Initial = %d. Final = %d.\n", Cudd_DagSize(bRemap), Cudd_DagSize(Temp) ); { DdNode * bFuncPerm; clk = clock(); bFuncPerm = Cudd_bddPermute( dd, bRemap, pOrderInv ); Cudd_Ref( bFuncPerm ); //runtime2 += clock() - clk; if ( bFuncPerm != Temp ) { printf( "REO: Internal verification has failed!\n" ); fflush( stdout ); } Cudd_RecursiveDeref( dd, bFuncPerm ); } Cudd_RecursiveDeref( dd, Temp ); Cudd_RecursiveDeref( dd, bRemap ); }
/** * @brief Basic test of timeout handler. * * @details Sets a short timeout and then tries to build a function * with a large BDD. Strives to avoid leaking nodes. * * @return 0 if successful; -1 otherwise. */ static int testTimeout(int verbosity) { DdManager *dd; /* Declare these "volatile" to prevent clobbering by longjmp. */ DdNode * volatile f; DdNode * volatile clause = NULL; DdNode * var1, * var2; int i, ret, count; int const N = 20; /* half the number of variables in f */ unsigned long timeout = 100UL; /* in milliseconds */ jmp_buf timeoutEnv; dd = Cudd_Init(0, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0); if (!dd) { if (verbosity) { printf("initialization failed\n"); } return -1; } /* Set up timeout handling. */ if (setjmp(timeoutEnv) > 0) { if (verbosity) { printf("caught timeout\n"); } /* The nodes of clause may be leaked if the timeout was * detected while conjoining the clause to f. We set * clause to NULL when it's not in use to be able to * detect this case. */ if (clause) Cudd_RecursiveDeref(dd, clause); goto finally; } (void) Cudd_RegisterTimeoutHandler(dd, timeoutHandler, (void *) &timeoutEnv); (void) Cudd_SetTimeLimit(dd, timeout); /* Try to build function. This is expected to run out of time. */ f = Cudd_ReadOne(dd); Cudd_Ref(f); for (i = 0; i < N; i++) { DdNode * tmp; var1 = Cudd_bddIthVar(dd, i); if (!var1) { if (verbosity) { printf("computation failed\n"); return -1; } } var2 = Cudd_bddIthVar(dd, i+N); if (!var2) { if (verbosity) { printf("computation failed\n"); return -1; } } clause = Cudd_bddOr(dd, var1, var2); if (!clause) { if (verbosity) { printf("computation failed\n"); } return -1; } Cudd_Ref(clause); tmp = Cudd_bddAnd(dd, f, clause); if (!tmp) { if (verbosity) { printf("computation failed\n"); } return -1; } Cudd_Ref(tmp); Cudd_RecursiveDeref(dd, clause); clause = NULL; Cudd_RecursiveDeref(dd, f); f = tmp; } if (verbosity > 1) { Cudd_bddPrintCover(dd, f, f); } finally: if (verbosity) { printf("so far"); Cudd_PrintSummary(dd, f, 2*N, 0); } count = 0; for (i = 0; i < N-1; i += 2) { var1 = Cudd_bddIthVar(dd, i); if (!var1) { printf("computation failed\n"); return -1; } var2 = Cudd_bddIthVar(dd, i+1); if (!var2) { printf("computation failed\n"); return -1; } clause = Cudd_bddOr(dd, var1, var2); if (!clause) { printf("computation failed\n"); return -1; } Cudd_Ref(clause); if (Cudd_bddLeq(dd, f, clause)) { count++; } Cudd_RecursiveDeref(dd, clause); } if (verbosity) { printf("f implies %d clauses\n", count); } Cudd_RecursiveDeref(dd, f); ret = Cudd_CheckZeroRef(dd); if (verbosity) { Cudd_PrintInfo(dd, stdout); if (ret != 0) { printf("%d non-zero references\n", ret); } } Cudd_Quit(dd); return 0; }
anode_t *synthesize( DdManager *manager, unsigned char init_flags, unsigned char verbose ) { anode_t *strategy = NULL; anode_t *this_node_stack = NULL; anode_t *node, *new_node; bool initial; vartype *state; vartype **env_moves; int emoves_len; ptree_t *var_separator; DdNode *W; DdNode *strans_into_W; DdNode *einit, *sinit, *etrans, *strans, **egoals, **sgoals; DdNode *ddval; /* Store result of evaluating a BDD */ DdNode ***Y = NULL; DdNode *Y_i_primed; int *num_sublevels; DdNode ****X_ijr = NULL; DdNode *tmp, *tmp2; int i, j, r, k; /* Generic counters */ int offset; bool env_nogoal_flag = False; /* Indicate environment has no goals */ int loop_mode; int next_mode; int num_env, num_sys; int *cube; /* length will be twice total number of variables (to account for both variables and their primes). */ /* Variables used during CUDD generation (state enumeration). */ DdGen *gen; CUDD_VALUE_TYPE gvalue; int *gcube; /* Set environment goal to True (i.e., any state) if none was given. This simplifies the implementation below. */ if (spc.num_egoals == 0) { env_nogoal_flag = True; spc.num_egoals = 1; spc.env_goals = malloc( sizeof(ptree_t *) ); *spc.env_goals = init_ptree( PT_CONSTANT, NULL, 1 ); } num_env = tree_size( spc.evar_list ); num_sys = tree_size( spc.svar_list ); /* State vector (i.e., valuation of the variables) */ state = malloc( sizeof(vartype)*(num_env+num_sys) ); if (state == NULL) { perror( __FILE__ ", malloc" ); exit(-1); } /* Allocate cube array, used later for quantifying over variables. */ cube = (int *)malloc( sizeof(int)*2*(num_env+num_sys) ); if (cube == NULL) { perror( __FILE__ ", malloc" ); exit(-1); } /* Chain together environment and system variable lists for working with BDD library. */ if (spc.evar_list == NULL) { var_separator = NULL; spc.evar_list = spc.svar_list; /* that this is the deterministic case is indicated by var_separator = NULL. */ } else { var_separator = get_list_item( spc.evar_list, -1 ); if (var_separator == NULL) { fprintf( stderr, "Error: get_list_item failed on environment variables" " list.\n" ); free( state ); free( cube ); return NULL; } var_separator->left = spc.svar_list; } /* Generate BDDs for the various parse trees from the problem spec. */ if (spc.env_init != NULL) { einit = ptree_BDD( spc.env_init, spc.evar_list, manager ); } else { einit = Cudd_ReadOne( manager ); Cudd_Ref( einit ); } if (spc.sys_init != NULL) { sinit = ptree_BDD( spc.sys_init, spc.evar_list, manager ); } else { sinit = Cudd_ReadOne( manager ); Cudd_Ref( sinit ); } if (verbose > 1) logprint( "Building environment transition BDD..." ); etrans = ptree_BDD( spc.env_trans, spc.evar_list, manager ); if (verbose > 1) { logprint( "Done." ); logprint( "Building system transition BDD..." ); } strans = ptree_BDD( spc.sys_trans, spc.evar_list, manager ); if (verbose > 1) logprint( "Done." ); /* Build goal BDDs, if present. */ if (spc.num_egoals > 0) { egoals = malloc( spc.num_egoals*sizeof(DdNode *) ); for (i = 0; i < spc.num_egoals; i++) *(egoals+i) = ptree_BDD( *(spc.env_goals+i), spc.evar_list, manager ); } else { egoals = NULL; } if (spc.num_sgoals > 0) { sgoals = malloc( spc.num_sgoals*sizeof(DdNode *) ); for (i = 0; i < spc.num_sgoals; i++) *(sgoals+i) = ptree_BDD( *(spc.sys_goals+i), spc.evar_list, manager ); } else { sgoals = NULL; } if (var_separator == NULL) { spc.evar_list = NULL; } else { var_separator->left = NULL; } W = compute_winning_set_BDD( manager, etrans, strans, egoals, sgoals, verbose ); if (W == NULL) { fprintf( stderr, "Error synthesize: failed to construct winning set.\n" ); free( state ); free( cube ); return NULL; } Y = compute_sublevel_sets( manager, W, etrans, strans, egoals, spc.num_egoals, sgoals, spc.num_sgoals, &num_sublevels, &X_ijr, verbose ); if (Y == NULL) { fprintf( stderr, "Error synthesize: failed to construct sublevel sets.\n" ); free( state ); free( cube ); return NULL; } /* The sublevel sets are exactly as resulting from the vanilla fixed point formula. Thus for each system goal i, Y_0 = \emptyset, and Y_1 is a union of i-goal states and environment-blocking states. For the purpose of synthesis, it is enough to delete Y_0 and replace Y_1 with the intersection of i-goal states and the winning set, and then shift the indices down (so that Y_1 is now called Y_0, Y_2 is now called Y_1, etc.) */ for (i = 0; i < spc.num_sgoals; i++) { Cudd_RecursiveDeref( manager, *(*(Y+i)) ); Cudd_RecursiveDeref( manager, *(*(Y+i)+1) ); for (r = 0; r < spc.num_egoals; r++) Cudd_RecursiveDeref( manager, *(*(*(X_ijr+i))+r) ); free( *(*(X_ijr+i)) ); *(*(Y+i)+1) = Cudd_bddAnd( manager, *(sgoals+i), W ); Cudd_Ref( *(*(Y+i)+1) ); (*(num_sublevels+i))--; for (j = 0; j < *(num_sublevels+i); j++) { *(*(Y+i)+j) = *(*(Y+i)+j+1); *(*(X_ijr+i)+j) = *(*(X_ijr+i)+j+1); } assert( *(num_sublevels+i) > 0 ); *(Y+i) = realloc( *(Y+i), (*(num_sublevels+i))*sizeof(DdNode *) ); *(X_ijr+i) = realloc( *(X_ijr+i), (*(num_sublevels+i))*sizeof(DdNode **) ); if (*(Y+i) == NULL || *(X_ijr+i) == NULL) { perror( __FILE__ ", realloc" ); exit(-1); } } /* Make primed form of W and take conjunction with system transition (safety) formula, for use while stepping down Y_i sets. Note that we assume the variable map has been appropriately defined in the CUDD manager, after the call to compute_winning_set_BDD above. */ tmp = Cudd_bddVarMap( manager, W ); if (tmp == NULL) { fprintf( stderr, "Error synthesize: Error in swapping variables with primed" " forms.\n" ); free( state ); free( cube ); return NULL; } Cudd_Ref( tmp ); strans_into_W = Cudd_bddAnd( manager, strans, tmp ); Cudd_Ref( strans_into_W ); Cudd_RecursiveDeref( manager, tmp ); /* From each initial state, build strategy by propagating forward toward the next goal (current target goal specified by "mode" of a state), and iterating until every reached state and mode combination has already been encountered (whence the strategy already built). */ if (init_flags == ALL_INIT || (init_flags == ONE_SIDE_INIT && spc.sys_init == NULL)) { if (init_flags == ALL_INIT) { if (verbose > 1) logprint( "Enumerating initial states, given init_flags =" " ALL_INIT" ); tmp = Cudd_bddAnd( manager, einit, sinit ); } else { if (verbose > 1) logprint( "Enumerating initial states, given init_flags =" " ONE_SIDE_INIT and empty SYSINIT" ); tmp = einit; Cudd_Ref( tmp ); } Cudd_Ref( tmp ); Cudd_AutodynDisable( manager ); Cudd_ForeachCube( manager, tmp, gen, gcube, gvalue ) { initialize_cube( state, gcube, num_env+num_sys ); while (!saturated_cube( state, gcube, num_env+num_sys )) { this_node_stack = insert_anode( this_node_stack, 0, -1, False, state, num_env+num_sys ); if (this_node_stack == NULL) { fprintf( stderr, "Error synthesize: building list of initial" " states.\n" ); return NULL; } increment_cube( state, gcube, num_env+num_sys ); } this_node_stack = insert_anode( this_node_stack, 0, -1, False, state, num_env+num_sys ); if (this_node_stack == NULL) { fprintf( stderr, "Error synthesize: building list of initial" " states.\n" ); return NULL; } } Cudd_AutodynEnable( manager, CUDD_REORDER_SAME ); Cudd_RecursiveDeref( manager, tmp ); } else if (init_flags == ALL_ENV_EXIST_SYS_INIT) {
/**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 [Computes shortest paths in a state graph.] Description [Computes shortest paths in the state transition graph of a network. Three methods are availabe: <ul> <li> Bellman-Ford algorithm for single-source shortest paths; the algorithm computes the distance (number of transitions) from the initial states to all states. <li> Floyd-Warshall algorithm for all-pair shortest paths. <li> Repeated squaring algorithm for all-pair shortest paths. </ul> The function returns 1 in case of success; 0 otherwise. ] SideEffects [ADD variables are created in the manager.] SeeAlso [] ******************************************************************************/ int Ntr_ShortestPaths( DdManager * dd, BnetNetwork * net, NtrOptions * option) { NtrPartTR *TR; DdNode *edges, *source, *res, *r, *q, *bddSource; DdNode **xadd, **yadd, **zadd; int i; int pr = option->verb; int algorithm = option->shortPath; int selectiveTrace = option->selectiveTrace; int nvars = net->nlatches; /* Set background to infinity for shortest paths. */ Cudd_SetBackground(dd,Cudd_ReadPlusInfinity(dd)); /* Build the monolithic TR. */ TR = Ntr_buildTR(dd,net,option,NTR_IMAGE_MONO); /* Build the ADD variable vectors for x and y. */ xadd = ALLOC(DdNode *, nvars); yadd = ALLOC(DdNode *, nvars); for(i = 0; i < nvars; i++) { q = Cudd_addIthVar(dd,TR->x[i]->index); Cudd_Ref(q); xadd[i] = q; q = Cudd_addIthVar(dd,TR->y[i]->index); Cudd_Ref(q); yadd[i] = q; } /* Convert the transition relation BDD into an ADD... */ q = Cudd_BddToAdd(dd,TR->part[0]); Cudd_Ref(q); /* ...replacing zeroes with infinities... */ r = Cudd_addIte(dd,q,Cudd_ReadOne(dd),Cudd_ReadPlusInfinity(dd)); Cudd_Ref(r); Cudd_RecursiveDeref(dd,q); /* ...and zeroing the diagonal. */ q = Cudd_addXeqy(dd,nvars,xadd,yadd); Cudd_Ref(q); edges = Cudd_addIte(dd,q,Cudd_ReadZero(dd),r); Cudd_Ref(edges); Cudd_RecursiveDeref(dd,r); Cudd_RecursiveDeref(dd,q); switch(algorithm) { case NTR_SHORT_BELLMAN: bddSource = Ntr_initState(dd,net,option); source = Cudd_BddToAdd(dd,bddSource); Cudd_Ref(source); res = ntrBellman(dd,edges,source,xadd,yadd,nvars,pr); if (res == NULL) return(0); Cudd_Ref(res); Cudd_RecursiveDeref(dd,source); Cudd_RecursiveDeref(dd,bddSource); if (pr >= 0) { (void) fprintf(stdout,"Distance Matrix"); Cudd_PrintDebug(dd,res,nvars,pr); } break; case NTR_SHORT_FLOYD: res = ntrWarshall(dd,edges,xadd,yadd,nvars,pr); if (res == NULL) return(0); Cudd_Ref(res); if (pr >= 0) { (void) fprintf(stdout,"Distance Matrix"); Cudd_PrintDebug(dd,res,2*nvars,pr); } break; case NTR_SHORT_SQUARE: /* Create a third set of ADD variables. */ zadd = ALLOC(DdNode *, nvars); for(i = 0; i < nvars; i++) { int level; level = Cudd_ReadIndex(dd,TR->x[i]->index); q = Cudd_addNewVarAtLevel(dd,level); Cudd_Ref(q); zadd[i] = q; } /* Compute the shortest paths. */ res = ntrSquare(dd,edges,zadd,yadd,xadd,nvars,pr,selectiveTrace); if (res == NULL) return(0); Cudd_Ref(res); /* Dispose of the extra variables. */ for(i = 0; i < nvars; i++) { Cudd_RecursiveDeref(dd,zadd[i]); } FREE(zadd); if (pr >= 0) { (void) fprintf(stdout,"Distance Matrix"); Cudd_PrintDebug(dd,res,2*nvars,pr); } break; default: (void) printf("Unrecognized method. Try again.\n"); return(0); } /* Here we should compute the paths. */ /* Clean up. */ Ntr_freeTR(dd,TR); Cudd_RecursiveDeref(dd,edges); Cudd_RecursiveDeref(dd,res); for(i = 0; i < nvars; i++) { Cudd_RecursiveDeref(dd,xadd[i]); Cudd_RecursiveDeref(dd,yadd[i]); } FREE(xadd); FREE(yadd); if (option->autoDyn & 1) { (void) printf("Order after short path computation\n"); if (!Bnet_PrintOrder(net,dd)) return(0); } return(1); } /* end of Ntr_ShortestPaths */
/**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 */
/**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 [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 */
int main(int argc, char** argv) { unsigned int i; Biddy_Boolean complete; Biddy_Edge tmp; Biddy_Edge r1,r2; unsigned int n1,n2; char *userinput; #ifdef USA_YES unsigned int usaSize = 0; unsigned int **usaEdge; unsigned int *usaOrder; char *usaCodes; Biddy_Edge *usaState; Biddy_Edge *usaGraph; #endif #ifdef EUROPE_YES unsigned int europeSize = 0; unsigned int **europeEdge; unsigned int *europeOrder; char *europeCodes; Biddy_Edge *europeState; Biddy_Edge *europeGraph; #endif setbuf(stdout, NULL); #ifdef USA_YES setDataUSA(&usaSize,&usaEdge,&usaOrder,&usaCodes); #endif #ifdef EUROPE_YES setDataEurope(&europeSize,&europeEdge,&europeOrder,&europeCodes); #endif #ifdef USE_BIDDY /* There is only one unique table in Biddy */ /* There are three caches in Biddy */ /* Unique table grows over the time */ /* The max number of variables is hardcoded in biddyInt. h */ /* biddyVariableTable.usaSize = BIDDYVARMAX = 2048 */ /* The following constants are hardcoded in biddyMain.c */ /* biddyIteCache.usaSize = MEDIUM_TABLE = 262143 */ /* biddyEACache.usaSize = SMALL_TABLE = 65535 */ /* biddyRCCache.usaSize = SMALL_TABLE = 65535 */ /* DEFAULT INIT CALL: Biddy_Init() */ Biddy_Init(); #endif #ifdef USE_CUDD /* In CUDD each variable has its own subtable in the unique table */ /* There is only one cache in CUDD */ /* Subtables grow over the time, you can set limit for fast unique table growth */ /* Cudd_SetLooseUpTo(manager,1048576) */ /* Cache can grow over the time, you can set the max usaSize */ /* Cudd_SetMaxCacheHard(manager,262144) */ /* These two constants are hardcoded in v3.0.0 */ /* CUDD_UNIQUE_SLOTS = 256 (default initial usaSize of each subtable) */ /* CUDD_CACHE_SLOTS = 262144 (default initial usaSize of cache table) */ /* DEFAULT INIT CALL: Cudd_Init(0,0,CUDD_UNIQUE_SLOTS,CUDD_CACHE_SLOTS,0) */ manager = Cudd_Init(0,0,CUDD_UNIQUE_SLOTS,CUDD_CACHE_SLOTS,0); Cudd_SetMaxCacheHard(manager,262144); #endif #ifdef USA_YES usaGraph = (Biddy_Edge *) malloc(usaSize*sizeof(Biddy_Edge *)); usaState = (Biddy_Edge *) malloc(usaSize*sizeof(Biddy_Edge *)); #endif #ifdef EUROPE_YES europeGraph = (Biddy_Edge *) malloc(europeSize*sizeof(Biddy_Edge *)); europeState = (Biddy_Edge *) malloc(europeSize*sizeof(Biddy_Edge *)); #endif i = 0; complete = FALSE; while (!complete) { complete = TRUE; tmp = Biddy_AddVariable(); #ifdef USA_YES if (i < usaSize) { usaState[usaOrder[i]] = tmp; } complete = complete && (i >= (usaSize-1)); #endif #ifdef EUROPE_YES if (i < europeSize) { europeState[europeOrder[i]] = tmp; } complete = complete && (i >= (europeSize-1)); #endif i++; } #ifdef USA_YES createGraph(usaSize,usaEdge,usaState,usaGraph); #endif #ifdef EUROPE_YES createGraph(europeSize,europeEdge,europeState,europeGraph); #endif #ifdef USE_BIDDY Biddy_Clean(); #endif r1 = Biddy_GetConstantZero(); r2 = Biddy_GetConstantZero(); #ifdef USE_CUDD Cudd_Ref(r1); Cudd_Ref(r2); #endif #ifdef USA_YES if (!CALCULATE_KERNELS) { /* CALCULATING INDEPENDENCE SETS FOR USA */ #ifdef USE_CUDD Cudd_RecursiveDeref(manager,r1); #endif r1 = calculateIndependence(usaSize,usaState,usaGraph); } else { /* CALCULATING KERNELS (MAXIMUM INDEPENDENCE SETS) FOR USA */ #ifdef USE_CUDD Cudd_RecursiveDeref(manager,r1); #endif r1 = calculateKernels(usaSize,usaState,usaGraph); } #ifdef USE_BIDDY Biddy_AddPersistentFormula((Biddy_String)"usa",r1); Biddy_Clean(); #endif #ifdef USE_CUDD for (i=0; i<usaSize; i++) { Cudd_RecursiveDeref(manager,usaGraph[i]); } #endif #endif #ifdef EUROPE_YES if (!CALCULATE_KERNELS) { /* CALCULATING INDEPENDENCE SETS FOR EUROPE */ #ifdef USE_CUDD Cudd_RecursiveDeref(manager,r2); #endif r2 = calculateIndependence(europeSize,europeState,europeGraph); } else { /* CALCULATING KERNELS (MAXIMUM INDEPENDENCE SETS) FOR EUROPE */ #ifdef USE_CUDD Cudd_RecursiveDeref(manager,r2); #endif r2 = calculateKernels(europeSize,europeState,europeGraph); } #ifdef USE_BIDDY Biddy_AddPersistentFormula((Biddy_String)"europe",r2); Biddy_Clean(); #endif #ifdef USE_CUDD for (i=0; i<europeSize; i++) { Cudd_RecursiveDeref(manager,europeGraph[i]); } #endif #endif userinput = strdup("..."); while (userinput[0] != 'x') { /* We have problems with passing stdout in the case you compile this file */ /* with MINGW and use biddy.dll generated with Visual Studio. */ /* In such cases, please, use Biddy_PrintInfo(NULL) */ if (userinput[0] == 'r') Biddy_PrintInfo(stdout); /* SIFTING */ #ifdef USE_BIDDY #ifdef CONVERGE if (userinput[0] == 's') Biddy_PurgeAndReorder(NULL,TRUE); #ifdef USA_YES if (userinput[0] == 'u') Biddy_PurgeAndReorder(r1,TRUE); #endif #ifdef EUROPE_YES if (userinput[0] == 'e') Biddy_PurgeAndReorder(r2,TRUE); #endif #else if (userinput[0] == 's') Biddy_PurgeAndReorder(NULL,FALSE); #ifdef USA_YES if (userinput[0] == 'u') Biddy_PurgeAndReorder(r1,FALSE); #endif #ifdef EUROPE_YES if (userinput[0] == 'e') Biddy_PurgeAndReorder(r2,FALSE); #endif #endif #endif #ifdef USE_CUDD #ifdef CONVERGE if (userinput[0] == 's') Cudd_ReduceHeap(manager,CUDD_REORDER_SIFT_CONVERGE,0); #else if (userinput[0] == 's') Cudd_ReduceHeap(manager,CUDD_REORDER_SIFT,0); #endif #endif n1 = Biddy_VariableNumber(r1); n2 = Biddy_VariableNumber(r2); if ((userinput[0] == 's') #ifdef USA_YES || (userinput[0] == 'u') #endif #ifdef EUROPE_YES || (userinput[0] == 'e') #endif ) { #ifdef CONVERGE printf("(CONVERGING SIFTING"); #ifdef USE_BIDDY if (userinput[0] == 'u') { printf(" ON FUNCTION FOR USA"); } if (userinput[0] == 'e') { printf(" ON FUNCTION FOR EUROPE"); } #endif printf(") "); #else printf("(SIFTING"); #ifdef USE_BIDDY if (userinput[0] == 'u') { printf(" ON FUNCTION FOR USA"); } if (userinput[0] == 'e') { printf(" ON FUNCTION FOR EUROPE"); } #endif printf(") "); #endif } printf("Resulting function r1/r2 depends on %u/%u variables.\n",n1,n2); printf("Resulting function r1/r2 has %.0f/%.0f minterms.\n",Biddy_CountMinterm(r1,n1),Biddy_CountMinterm(r2,n2)); #ifdef USE_BIDDY printf("BDD for resulting function r1/r2 has %u/%u nodes (%u/%u nodes if using complement edges).\n", Biddy_NodeNumberPlain(r1),Biddy_NodeNumberPlain(r2),Biddy_NodeNumber(r1),Biddy_NodeNumber(r2)); #endif #ifdef USE_CUDD printf("BDD for resulting function r1/r2 has %u/%u nodes (using complement edges).\n",Biddy_NodeNumber(r1),Biddy_NodeNumber(r2)); #endif #ifdef USE_BIDDY printf("Variable swaps performed so far: %u\n",Biddy_NodeTableSwapNumber()); #endif #ifdef USE_CUDD printf("Variable swaps performed so far: %.0f\n",Cudd_ReadSwapSteps(manager)); #endif #ifdef USA_YES printf("Order for USA: "); writeOrder(r1,usaCodes,usaOrder,usaSize); #endif #ifdef EUROPE_YES printf("Order for Europe: "); writeOrder(r2,europeCodes,europeOrder,europeSize); #endif #ifdef USE_BIDDY printf("E[x]it or [r]eport or "); #ifdef CONVERGE printf("Converging sifting "); #else printf("Sifting "); #endif #if (defined USA_YES) || (defined EUROPE_YES) printf("on [s]ystem or Sifting on function for"); #ifdef USA_YES printf(" [u]SA"); #endif #ifdef EUROPE_YES printf(" [e]urope"); #endif #endif printf(": "); if (!scanf("%s",userinput)) printf("ERROR\n"); #endif #ifdef USE_CUDD printf("E[x]it or [r]eport or "); #ifdef CONVERGE printf("Converging sifting "); #else printf("Sifting "); #endif printf("on [s]ystem: "); if (!scanf("%s",userinput)) printf("ERROR\n"); #endif } free(userinput); /* EXIT */ #ifdef USE_BIDDY Biddy_Exit(); #endif #ifdef USE_CUDD Cudd_RecursiveDeref(manager,r1); Cudd_RecursiveDeref(manager,r2); printf("CUDD: nodes with non-zero reference counts: %d\n",Cudd_CheckZeroRef(manager)); Cudd_Quit(manager); #endif return 0; }
/**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 [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_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 [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 */
ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ #define DD_GET_SYMM_VARS_TAG 0x0a /* former DD_BDD_XOR_EXIST_ABSTRACT_TAG */ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Computes the classical symmetry information for the function.] Description [Returns the symmetry information in the form of Extra_SymmInfo_t structure.] SideEffects [If the ZDD variables are not derived from BDD variables with multiplicity 2, this function may derive them in a wrong way.] SeeAlso [] ******************************************************************************/ Extra_SymmInfo_t * Extra_SymmPairsCompute( DdManager * dd, /* the manager */ DdNode * bFunc) /* the function whose symmetries are computed */ { DdNode * bSupp; DdNode * zRes; Extra_SymmInfo_t * p; bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp ); zRes = Extra_zddSymmPairsCompute( dd, bFunc, bSupp ); Cudd_Ref( zRes ); p = Extra_SymmPairsCreateFromZdd( dd, zRes, bSupp ); Cudd_RecursiveDeref( dd, bSupp ); Cudd_RecursiveDerefZdd( dd, zRes ); return p; } /* end of Extra_SymmPairsCompute */