/**Function******************************************************************** Synopsis [Substitutes g for x_v in the BDD for f.] Description [Substitutes g for x_v in the BDD for f. v is the index of the variable to be substituted. Cudd_bddCompose passes the corresponding projection function to the recursive procedure, so that the cache may be used. Returns the composed BDD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_addCompose] ******************************************************************************/ DdNode * Cudd_bddCompose( DdManager * dd, DdNode * f, DdNode * g, int v) { DdNode *proj, *res; /* Sanity check. */ if (v < 0 || v > dd->size) return(NULL); proj = dd->vars[v]; do { dd->reordered = 0; res = cuddBddComposeRecur(dd,f,g,proj); } while (dd->reordered == 1); return(res); } /* end of Cudd_bddCompose */
/**Function******************************************************************** Synopsis [Implements the recursive step of Cudd_SolveEqn.] Description [Implements the recursive step of Cudd_SolveEqn. Returns NULL if the intermediate solution blows up or reordering occurs. The parametric solutions are stored in the array G.] SideEffects [none] SeeAlso [Cudd_SolveEqn, Cudd_VerifySol] ******************************************************************************/ DdNode * cuddSolveEqnRecur( DdManager * bdd, DdNode * F /* the left-hand side of the equation */, DdNode * Y /* the cube of remaining y variables */, DdNode ** G /* the array of solutions */, int n /* number of unknowns */, int * yIndex /* array holding the y variable indices */, int i /* level of recursion */) { DdNode *Fn, *Fm1, *Fv, *Fvbar, *T, *w, *nextY, *one; DdNodePtr *variables; int j; statLine(bdd); variables = bdd->vars; one = DD_ONE(bdd); /* Base condition. */ if (Y == one) { return F; } /* Cofactor of Y. */ yIndex[i] = Y->index; nextY = Cudd_T(Y); /* Universal abstraction of F with respect to the top variable index. */ Fm1 = cuddBddExistAbstractRecur(bdd, Cudd_Not(F), variables[yIndex[i]]); if (Fm1) { Fm1 = Cudd_Not(Fm1); cuddRef(Fm1); } else { return(NULL); } Fn = cuddSolveEqnRecur(bdd, Fm1, nextY, G, n, yIndex, i+1); if (Fn) { cuddRef(Fn); } else { Cudd_RecursiveDeref(bdd, Fm1); return(NULL); } Fv = cuddCofactorRecur(bdd, F, variables[yIndex[i]]); if (Fv) { cuddRef(Fv); } else { Cudd_RecursiveDeref(bdd, Fm1); Cudd_RecursiveDeref(bdd, Fn); return(NULL); } Fvbar = cuddCofactorRecur(bdd, F, Cudd_Not(variables[yIndex[i]])); if (Fvbar) { cuddRef(Fvbar); } else { Cudd_RecursiveDeref(bdd, Fm1); Cudd_RecursiveDeref(bdd, Fn); Cudd_RecursiveDeref(bdd, Fv); return(NULL); } /* Build i-th component of the solution. */ w = cuddBddIteRecur(bdd, variables[yIndex[i]], Cudd_Not(Fv), Fvbar); if (w) { cuddRef(w); } else { Cudd_RecursiveDeref(bdd, Fm1); Cudd_RecursiveDeref(bdd, Fn); Cudd_RecursiveDeref(bdd, Fv); Cudd_RecursiveDeref(bdd, Fvbar); return(NULL); } T = cuddBddRestrictRecur(bdd, w, Cudd_Not(Fm1)); if(T) { cuddRef(T); } else { Cudd_RecursiveDeref(bdd, Fm1); Cudd_RecursiveDeref(bdd, Fn); Cudd_RecursiveDeref(bdd, Fv); Cudd_RecursiveDeref(bdd, Fvbar); Cudd_RecursiveDeref(bdd, w); return(NULL); } Cudd_RecursiveDeref(bdd,Fm1); Cudd_RecursiveDeref(bdd,w); Cudd_RecursiveDeref(bdd,Fv); Cudd_RecursiveDeref(bdd,Fvbar); /* Substitute components of solution already found into solution. */ for (j = n-1; j > i; j--) { w = cuddBddComposeRecur(bdd,T, G[j], variables[yIndex[j]]); if(w) { cuddRef(w); } else { Cudd_RecursiveDeref(bdd, Fn); Cudd_RecursiveDeref(bdd, T); return(NULL); } Cudd_RecursiveDeref(bdd,T); T = w; } G[i] = T; Cudd_Deref(Fn); return(Fn); } /* end of cuddSolveEqnRecur */
/**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_bddCompose.] Description [Performs the recursive step of Cudd_bddCompose. Exploits the fact that the composition of f' with g produces the complement of the composition of f with g to better utilize the cache. Returns the composed BDD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddCompose] ******************************************************************************/ DdNode * cuddBddComposeRecur( DdManager * dd, DdNode * f, DdNode * g, DdNode * proj) { DdNode *F, *G, *f1, *f0, *g1, *g0, *r, *t, *e; unsigned int v, topf, topg, topindex; int comple; statLine(dd); v = dd->perm[proj->index]; F = Cudd_Regular(f); topf = cuddI(dd,F->index); /* Terminal case. Subsumes the test for constant f. */ if (topf > v) return(f); /* We solve the problem for a regular pointer, and then complement ** the result if the pointer was originally complemented. */ comple = Cudd_IsComplement(f); /* Check cache. */ r = cuddCacheLookup(dd,DD_BDD_COMPOSE_RECUR_TAG,F,g,proj); if (r != NULL) { return(Cudd_NotCond(r,comple)); } if (topf == v) { /* Compose. */ f1 = cuddT(F); f0 = cuddE(F); r = cuddBddIteRecur(dd, g, f1, f0); if (r == NULL) return(NULL); } else { /* Compute cofactors of f and g. Remember the index of the top ** variable. */ G = Cudd_Regular(g); topg = cuddI(dd,G->index); if (topf > topg) { topindex = G->index; f1 = f0 = F; } else { topindex = F->index; f1 = cuddT(F); f0 = cuddE(F); } if (topg > topf) { g1 = g0 = g; } else { g1 = cuddT(G); g0 = cuddE(G); if (g != G) { g1 = Cudd_Not(g1); g0 = Cudd_Not(g0); } } /* Recursive step. */ t = cuddBddComposeRecur(dd, f1, g1, proj); if (t == NULL) return(NULL); cuddRef(t); e = cuddBddComposeRecur(dd, f0, g0, proj); if (e == NULL) { Cudd_IterDerefBdd(dd, t); return(NULL); } cuddRef(e); r = cuddBddIteRecur(dd, dd->vars[topindex], t, e); if (r == NULL) { Cudd_IterDerefBdd(dd, t); Cudd_IterDerefBdd(dd, e); return(NULL); } cuddRef(r); Cudd_IterDerefBdd(dd, t); /* t & e not necessarily part of r */ Cudd_IterDerefBdd(dd, e); cuddDeref(r); } cuddCacheInsert(dd,DD_BDD_COMPOSE_RECUR_TAG,F,g,proj,r); return(Cudd_NotCond(r,comple)); } /* end of cuddBddComposeRecur */