/**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_addOrAbstract.] Description [Performs the recursive step of Cudd_addOrAbstract. Returns the ADD obtained by abstracting the variables of cube from f, if successful; NULL otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode * cuddAddOrAbstractRecur( DdManager * manager, DdNode * f, DdNode * cube) { DdNode *T, *E, *res, *res1, *res2, *one; statLine(manager); one = DD_ONE(manager); /* Cube is guaranteed to be a cube at this point. */ if (cuddIsConstant(f) || cube == one) { return(f); } /* Abstract a variable that does not appear in f. */ if (cuddI(manager,f->index) > cuddI(manager,cube->index)) { res = cuddAddOrAbstractRecur(manager, f, cuddT(cube)); return(res); } if ((res = cuddCacheLookup2(manager, Cudd_addOrAbstract, f, cube)) != NULL) { return(res); } T = cuddT(f); E = cuddE(f); /* If the two indices are the same, so are their levels. */ if (f->index == cube->index) { res1 = cuddAddOrAbstractRecur(manager, T, cuddT(cube)); if (res1 == NULL) return(NULL); cuddRef(res1); if (res1 != one) { res2 = cuddAddOrAbstractRecur(manager, E, cuddT(cube)); if (res2 == NULL) { Cudd_RecursiveDeref(manager,res1); return(NULL); } cuddRef(res2); res = cuddAddApplyRecur(manager, Cudd_addOr, res1, res2); if (res == NULL) { Cudd_RecursiveDeref(manager,res1); Cudd_RecursiveDeref(manager,res2); return(NULL); } cuddRef(res); Cudd_RecursiveDeref(manager,res1); Cudd_RecursiveDeref(manager,res2); } else { res = res1; } cuddCacheInsert2(manager, Cudd_addOrAbstract, f, cube, res); cuddDeref(res); return(res); } else { /* if (cuddI(manager,f->index) < cuddI(manager,cube->index)) */ res1 = cuddAddOrAbstractRecur(manager, T, cube); if (res1 == NULL) return(NULL); cuddRef(res1); res2 = cuddAddOrAbstractRecur(manager, E, cube); if (res2 == NULL) { Cudd_RecursiveDeref(manager,res1); return(NULL); } cuddRef(res2); res = (res1 == res2) ? res1 : cuddUniqueInter(manager, (int) f->index, res1, res2); if (res == NULL) { Cudd_RecursiveDeref(manager,res1); Cudd_RecursiveDeref(manager,res2); return(NULL); } cuddDeref(res1); cuddDeref(res2); cuddCacheInsert2(manager, Cudd_addOrAbstract, f, cube, res); return(res); } } /* end of cuddAddOrAbstractRecur */
/**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_addUnivAbstract.] Description [Performs the recursive step of Cudd_addUnivAbstract. Returns the ADD obtained by abstracting the variables of cube from f, if successful; NULL otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode * cuddAddUnivAbstractRecur( DdManager * manager, DdNode * f, DdNode * cube) { DdNode *T, *E, *res, *res1, *res2, *one, *zero; statLine(manager); one = DD_ONE(manager); zero = DD_ZERO(manager); /* Cube is guaranteed to be a cube at this point. ** zero and one are the only constatnts c such that c*c=c. */ if (f == zero || f == one || cube == one) { return(f); } /* Abstract a variable that does not appear in f. */ if (cuddI(manager,f->index) > cuddI(manager,cube->index)) { res1 = cuddAddUnivAbstractRecur(manager, f, cuddT(cube)); if (res1 == NULL) return(NULL); cuddRef(res1); /* Use the "internal" procedure to be alerted in case of ** dynamic reordering. If dynamic reordering occurs, we ** have to abort the entire abstraction. */ res = cuddAddApplyRecur(manager, Cudd_addTimes, res1, res1); if (res == NULL) { Cudd_RecursiveDeref(manager,res1); return(NULL); } cuddRef(res); Cudd_RecursiveDeref(manager,res1); cuddDeref(res); return(res); } if ((res = cuddCacheLookup2(manager, Cudd_addUnivAbstract, f, cube)) != NULL) { return(res); } T = cuddT(f); E = cuddE(f); /* If the two indices are the same, so are their levels. */ if (f->index == cube->index) { res1 = cuddAddUnivAbstractRecur(manager, T, cuddT(cube)); if (res1 == NULL) return(NULL); cuddRef(res1); res2 = cuddAddUnivAbstractRecur(manager, E, cuddT(cube)); if (res2 == NULL) { Cudd_RecursiveDeref(manager,res1); return(NULL); } cuddRef(res2); res = cuddAddApplyRecur(manager, Cudd_addTimes, res1, res2); if (res == NULL) { Cudd_RecursiveDeref(manager,res1); Cudd_RecursiveDeref(manager,res2); return(NULL); } cuddRef(res); Cudd_RecursiveDeref(manager,res1); Cudd_RecursiveDeref(manager,res2); cuddCacheInsert2(manager, Cudd_addUnivAbstract, f, cube, res); cuddDeref(res); return(res); } else { /* if (cuddI(manager,f->index) < cuddI(manager,cube->index)) */ res1 = cuddAddUnivAbstractRecur(manager, T, cube); if (res1 == NULL) return(NULL); cuddRef(res1); res2 = cuddAddUnivAbstractRecur(manager, E, cube); if (res2 == NULL) { Cudd_RecursiveDeref(manager,res1); return(NULL); } cuddRef(res2); res = (res1 == res2) ? res1 : cuddUniqueInter(manager, (int) f->index, res1, res2); if (res == NULL) { Cudd_RecursiveDeref(manager,res1); Cudd_RecursiveDeref(manager,res2); return(NULL); } cuddDeref(res1); cuddDeref(res2); cuddCacheInsert2(manager, Cudd_addUnivAbstract, f, cube, res); return(res); } } /* end of cuddAddUnivAbstractRecur */
/**Function******************************************************************** Synopsis [Performs the reordering-sensitive step of Extra_bddReedMuller().] Description [Generates in a bottom-up fashion an ADD for all spectral coefficients of the functions represented by a BDD.] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode* extraBddReedMuller( DdManager * dd, /* the manager */ DdNode * bFunc, /* the function whose spectrum is being computed */ DdNode * bVars) /* the variables on which the function depends */ { DdNode * aRes; statLine(dd); /* terminal cases */ if ( bVars == b1 ) { assert( Cudd_IsConstant(bFunc) ); if ( bFunc == b0 ) return a0; else return a1; } /* check cache */ if ( ( aRes = cuddCacheLookup2(dd, extraBddReedMuller, bFunc, bVars) ) ) return aRes; else { DdNode * bFunc0, * bFunc1; /* cofactors of the function */ DdNode * aRes0, * aRes1; /* partial results to be composed by ITE */ DdNode * bFuncR = Cudd_Regular(bFunc); /* the regular pointer to the function */ DdNode * aTemp; /* bFunc cannot depend on a variable that is not in bVars */ assert( cuddI(dd,bFuncR->index) >= cuddI(dd,bVars->index) ); /* cofactor the BDD */ if ( bFuncR->index == bVars->index ) { if ( bFuncR != bFunc ) /* bFunc is complemented */ { bFunc0 = Cudd_Not( cuddE(bFuncR) ); bFunc1 = Cudd_Not( cuddT(bFuncR) ); } else { bFunc0 = cuddE(bFuncR); bFunc1 = cuddT(bFuncR); } } else /* bVars is higher in the variable order */ bFunc0 = bFunc1 = bFunc; /* solve subproblems */ aRes0 = extraBddReedMuller( dd, bFunc0, cuddT(bVars) ); if ( aRes0 == NULL ) return NULL; cuddRef( aRes0 ); aRes1 = extraBddReedMuller( dd, bFunc1, cuddT(bVars) ); if ( aRes1 == NULL ) { Cudd_RecursiveDeref( dd, aRes0 ); return NULL; } cuddRef( aRes1 ); /* compute aRes1 = aRes1 (+) aRes0 */ aRes1 = cuddAddApplyRecur( dd, Cudd_addXor, aTemp = aRes1, aRes0 ); if ( aRes1 == NULL ) { Cudd_RecursiveDeref( dd, aRes0 ); Cudd_RecursiveDeref( dd, aTemp ); return NULL; } cuddRef( aRes1 ); Cudd_RecursiveDeref(dd, aTemp); /* only aRes0 and aRes1 are referenced at this point */ /* consider the case when Res0 and Res1 are the same node */ aRes = (aRes1 == aRes0) ? aRes1 : cuddUniqueInter( dd, bVars->index, aRes1, aRes0 ); if (aRes == NULL) { Cudd_RecursiveDeref(dd, aRes1); Cudd_RecursiveDeref(dd, aRes0); return NULL; } cuddDeref(aRes1); cuddDeref(aRes0); /* insert the result into cache */ cuddCacheInsert2(dd, extraBddReedMuller, bFunc, bVars, aRes); return aRes; } } /* end of extraBddReedMuller */
/**Function******************************************************************** Synopsis [Performs the reordering-sensitive step of Extra_bddHaarInverse().] Description [Generates in a bottom-up fashion an ADD for the inverse Haar.] SideEffects [The third cached argument (bSteps) is the BDD of the elementary variable whose index equal to the number of lazy steps made thus far plus one. On the top-most level it is 0, next it is 1, etc.] SeeAlso [] ******************************************************************************/ DdNode * extraBddHaarInverse( DdManager * dd, /* the manager */ DdNode * aFunc, /* the function whose spectrum is being computed */ DdNode * aSteps, /* the index of this variable indicates the number of previous lazy recursive calls */ DdNode * bVars, /* the variables, on which the function depends */ DdNode * bVarsAll, /* the set of all variables, which will never change through the calls */ int nVarsAll, /* the number of vars in the set */ int * InverseMap ) /* the variable map mapping the var index into its inverse var index */ { DdNode * aRes; DdNode * bCacheCube; statLine(dd); /* terminal cases */ if ( bVars == b1 ) { // return a terminal node with a value equal to cuddV(aFunc) * 2^(nSteps-1) if ( cuddV(aSteps) == 0.0 ) return cuddUniqueConst( dd, cuddV(aFunc) ); else return cuddUniqueConst( dd, cuddV(aFunc) * Extra_Power2( (int)(cuddV(aSteps)-1) ) ); } /* check cache */ /* the last two arguments are derivitives, therefore there are useless for caching */ /* the other two arguments (bVars and bVarsAll) can be combined into one argument */ bCacheCube = extraCachingCube( dd, bVarsAll, bVars ); Cudd_Ref( bCacheCube ); if ( aRes = cuddCacheLookup(dd, DD_ADD_HAAR_INVERSE_TAG, aFunc, aSteps, bCacheCube) ) { Cudd_RecursiveDeref( dd, bCacheCube ); return aRes; } else { DdNode * aFunc0, * aFunc1; /* cofactors of the function */ DdNode * aInvH0, * aInvH1; /* partial solutions of the problem */ DdNode * aRes0, * aRes1; /* partial results to be composed by ITE */ DdNode * aStepNext; /* aFunc cannot depend on a variable that is not in bVars */ assert( cuddI(dd,aFunc->index) >= cuddI(dd,bVars->index) ); /* cofactor the ADD */ if ( aFunc->index == bVars->index ) { aFunc0 = cuddE(aFunc); aFunc1 = cuddT(aFunc); } else /* bVars is higher in the variable order */ aFunc0 = aFunc1 = aFunc; if ( cuddV(aSteps) > 0.0 ) /* meaning that it is a lazy call */ { /* solve subproblems */ aStepNext = cuddUniqueConst( dd, cuddV(aSteps)+1 ); if ( aStepNext == NULL ) return NULL; cuddRef( aStepNext ); aInvH0 = extraBddHaarInverse( dd, aFunc0, aStepNext, cuddT(bVars), bVarsAll, nVarsAll, InverseMap ); if ( aInvH0 == NULL ) { Cudd_RecursiveDeref( dd, aStepNext ); return NULL; } cuddRef( aInvH0 ); aInvH1 = extraBddHaarInverse( dd, aFunc1, aStepNext, cuddT(bVars), bVarsAll, nVarsAll, InverseMap ); if ( aInvH1 == NULL ) { Cudd_RecursiveDeref( dd, aStepNext ); Cudd_RecursiveDeref( dd, aInvH0 ); return NULL; } cuddRef( aInvH1 ); Cudd_RecursiveDeref( dd, aStepNext ); aRes0 = aInvH0; aRes1 = aInvH1; } else // if ( cuddV(aSteps) == 0.0 ) { /* solve subproblems */ aInvH0 = extraBddHaarInverse( dd, aFunc0, aSteps, cuddT(bVars), bVarsAll, nVarsAll, InverseMap ); if ( aInvH0 == NULL ) return NULL; cuddRef( aInvH0 ); aStepNext = cuddUniqueConst( dd, 1.0 ); if ( aStepNext == NULL ) { Cudd_RecursiveDeref( dd, aInvH0 ); return NULL; } cuddRef( aStepNext ); aInvH1 = extraBddHaarInverse( dd, aFunc1, aStepNext, cuddT(bVars), bVarsAll, nVarsAll, InverseMap ); if ( aInvH1 == NULL ) { Cudd_RecursiveDeref( dd, aStepNext ); Cudd_RecursiveDeref( dd, aInvH0 ); return NULL; } cuddRef( aInvH1 ); Cudd_RecursiveDeref( dd, aStepNext ); /* compute aRes0 = aWalsh0 + aWalsh1 */ aRes0 = cuddAddApplyRecur( dd, Cudd_addPlus, aInvH0, aInvH1 ); if ( aRes0 == NULL ) { Cudd_RecursiveDeref( dd, aInvH0 ); Cudd_RecursiveDeref( dd, aInvH1 ); return NULL; } cuddRef( aRes0 ); /* compute aRes1 = aWalsh0 - aWalsh1 */ aRes1 = cuddAddApplyRecur( dd, Cudd_addMinus, aInvH0, aInvH1 ); if ( aRes1 == NULL ) { Cudd_RecursiveDeref( dd, aInvH0 ); Cudd_RecursiveDeref( dd, aInvH1 ); Cudd_RecursiveDeref( dd, aRes0 ); return NULL; } cuddRef( aRes1 ); Cudd_RecursiveDeref(dd, aInvH0); Cudd_RecursiveDeref(dd, aInvH1); } /* only aRes0 and aRes1 are referenced at this point */ /* consider the case when Res0 and Res1 are the same node */ aRes = extraAddIteRecurGeneral( dd, dd->vars[ InverseMap[bVars->index] ], aRes1, aRes0 ); if (aRes == NULL) { Cudd_RecursiveDeref(dd, aRes1); Cudd_RecursiveDeref(dd, aRes0); return NULL; } cuddRef( aRes ); Cudd_RecursiveDeref(dd, aRes1); Cudd_RecursiveDeref(dd, aRes0); cuddDeref( aRes ); /* insert the result into cache */ cuddCacheInsert(dd, DD_ADD_HAAR_INVERSE_TAG, aFunc, aSteps, bCacheCube, aRes); Cudd_RecursiveDeref( dd, bCacheCube ); return aRes; } } /* end of extraBddHaarInverse */
/**Function******************************************************************** Synopsis [Performs the reordering-sensitive step of Extra_bddWalsh().] Description [Generates in a bottom-up fashion an ADD for all spectral coefficients of the functions represented by a BDD.] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode* extraBddWalsh( DdManager * dd, /* the manager */ DdNode * bFunc, /* the function whose spectrum is being computed */ DdNode * bVars) /* the variables on which the function depends */ { DdNode * aRes; statLine(dd); if ( clock() > s_TimeLimit ) return NULL; /* terminal cases */ if ( bVars == b1 ) { assert( Cudd_IsConstant(bFunc) ); if ( bFunc == b0 ) return a1; else return Cudd_addConst(dd,-1.0); } /* check cache */ // if ( bFunc->ref != 1 ) if ( ( aRes = cuddCacheLookup2(dd, extraBddWalsh, bFunc, bVars) ) ) { s_CacheHit++; return aRes; } else { DdNode * bFunc0, * bFunc1; /* cofactors of the function */ DdNode * aWalsh0, * aWalsh1; /* partial solutions of the problem */ DdNode * aRes0, * aRes1; /* partial results to be composed by ITE */ DdNode * bFuncR = Cudd_Regular(bFunc); /* the regular pointer to the function */ s_CacheMiss++; /* bFunc cannot depend on a variable that is not in bVars */ assert( cuddI(dd,bFuncR->index) >= cuddI(dd,bVars->index) ); /* cofactor the BDD */ if ( bFuncR->index == bVars->index ) { if ( bFuncR != bFunc ) /* bFunc is complemented */ { bFunc0 = Cudd_Not( cuddE(bFuncR) ); bFunc1 = Cudd_Not( cuddT(bFuncR) ); } else { bFunc0 = cuddE(bFuncR); bFunc1 = cuddT(bFuncR); } } else /* bVars is higher in the variable order */ bFunc0 = bFunc1 = bFunc; /* solve subproblems */ aWalsh0 = extraBddWalsh( dd, bFunc0, cuddT(bVars) ); if ( aWalsh0 == NULL ) return NULL; cuddRef( aWalsh0 ); aWalsh1 = extraBddWalsh( dd, bFunc1, cuddT(bVars) ); if ( aWalsh1 == NULL ) { Cudd_RecursiveDeref( dd, aWalsh0 ); return NULL; } cuddRef( aWalsh1 ); /* compute aRes0 = aWalsh0 + aWalsh1 */ aRes0 = cuddAddApplyRecur( dd, Cudd_addPlus, aWalsh0, aWalsh1 ); if ( aRes0 == NULL ) { Cudd_RecursiveDeref( dd, aWalsh0 ); Cudd_RecursiveDeref( dd, aWalsh1 ); return NULL; } cuddRef( aRes0 ); /* compute aRes1 = aWalsh0 - aWalsh1 */ aRes1 = cuddAddApplyRecur( dd, Cudd_addMinus, aWalsh0, aWalsh1 ); if ( aRes1 == NULL ) { Cudd_RecursiveDeref( dd, aWalsh0 ); Cudd_RecursiveDeref( dd, aWalsh1 ); Cudd_RecursiveDeref( dd, aRes0 ); return NULL; } cuddRef( aRes1 ); Cudd_RecursiveDeref(dd, aWalsh0); Cudd_RecursiveDeref(dd, aWalsh1); /* only aRes0 and aRes1 are referenced at this point */ /* consider the case when Res0 and Res1 are the same node */ aRes = (aRes1 == aRes0) ? aRes1 : cuddUniqueInter( dd, bVars->index, aRes1, aRes0 ); if (aRes == NULL) { Cudd_RecursiveDeref(dd, aRes1); Cudd_RecursiveDeref(dd, aRes0); return NULL; } cuddDeref(aRes1); cuddDeref(aRes0); /* insert the result into cache */ // if ( bFunc->ref != 1 ) cuddCacheInsert2(dd, extraBddWalsh, bFunc, bVars, aRes); return aRes; } } /* end of extraBddWalsh */