/**Function******************************************************************** Synopsis [Implements ITE(f,g,h).] Description [Implements ITE(f,g,h). This procedure assumes that f is a 0-1 ADD. Returns a pointer to the resulting ADD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddIte Cudd_addIteConstant Cudd_addApply] ******************************************************************************/ DdNode * Cudd_addIte( DdManager * dd, DdNode * f, DdNode * g, DdNode * h) { DdNode *res; do { dd->reordered = 0; res = cuddAddIteRecur(dd,f,g,h); } while (dd->reordered == 1); return(res); } /* end of Cudd_addIte */
/**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_addCompose.] Description [Performs the recursive step of Cudd_addCompose. Returns the composed BDD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_addCompose] ******************************************************************************/ DdNode * cuddAddComposeRecur( DdManager * dd, DdNode * f, DdNode * g, DdNode * proj) { DdNode *f1, *f0, *g1, *g0, *r, *t, *e; unsigned int v, topf, topg, topindex; statLine(dd); v = dd->perm[proj->index]; topf = cuddI(dd,f->index); /* Terminal case. Subsumes the test for constant f. */ if (topf > v) return(f); /* Check cache. */ r = cuddCacheLookup(dd,DD_ADD_COMPOSE_RECUR_TAG,f,g,proj); if (r != NULL) { return(r); } if (topf == v) { /* Compose. */ f1 = cuddT(f); f0 = cuddE(f); r = cuddAddIteRecur(dd, g, f1, f0); if (r == NULL) return(NULL); } else { /* Compute cofactors of f and g. Remember the index of the top ** variable. */ 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); } /* Recursive step. */ t = cuddAddComposeRecur(dd, f1, g1, proj); if (t == NULL) return(NULL); cuddRef(t); e = cuddAddComposeRecur(dd, f0, g0, proj); if (e == NULL) { Cudd_RecursiveDeref(dd, t); return(NULL); } cuddRef(e); if (t == e) { r = t; } else { r = cuddUniqueInter(dd, (int) topindex, t, e); if (r == NULL) { Cudd_RecursiveDeref(dd, t); Cudd_RecursiveDeref(dd, e); return(NULL); } } cuddDeref(t); cuddDeref(e); } cuddCacheInsert(dd,DD_ADD_COMPOSE_RECUR_TAG,f,g,proj,r); return(r); } /* end of cuddAddComposeRecur */
/**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_addNonSimCompose.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ static DdNode * cuddAddNonSimComposeRecur( DdManager * dd, DdNode * f, DdNode ** vector, DdNode * key, DdNode * cube, int lastsub) { DdNode *f1, *f0, *key1, *key0, *cube1, *var; DdNode *T,*E; DdNode *r; unsigned int top, topf, topk, topc; unsigned int index; int i; DdNode **vect1; DdNode **vect0; statLine(dd); /* If we are past the deepest substitution, return f. */ if (cube == DD_ONE(dd) || cuddIsConstant(f)) { return(f); } /* If problem already solved, look up answer and return. */ r = cuddCacheLookup(dd,DD_ADD_NON_SIM_COMPOSE_TAG,f,key,cube); if (r != NULL) { return(r); } /* Find top variable. we just need to look at f, key, and cube, ** because all the varibles in the gi are in key. */ topf = cuddI(dd,f->index); topk = cuddI(dd,key->index); top = ddMin(topf,topk); topc = cuddI(dd,cube->index); top = ddMin(top,topc); index = dd->invperm[top]; /* Compute the cofactors. */ if (topf == top) { f1 = cuddT(f); f0 = cuddE(f); } else { f1 = f0 = f; } if (topc == top) { cube1 = cuddT(cube); /* We want to eliminate vector[index] from key. Otherwise ** cache performance is severely affected. Hence we ** existentially quantify the variable with index "index" from key. */ var = Cudd_addIthVar(dd, (int) index); if (var == NULL) { return(NULL); } cuddRef(var); key1 = cuddAddExistAbstractRecur(dd, key, var); if (key1 == NULL) { Cudd_RecursiveDeref(dd,var); return(NULL); } cuddRef(key1); Cudd_RecursiveDeref(dd,var); key0 = key1; } else { cube1 = cube; if (topk == top) { key1 = cuddT(key); key0 = cuddE(key); } else { key1 = key0 = key; } cuddRef(key1); } /* Allocate two new vectors for the cofactors of vector. */ vect1 = ALLOC(DdNode *,lastsub); if (vect1 == NULL) { dd->errorCode = CUDD_MEMORY_OUT; Cudd_RecursiveDeref(dd,key1); return(NULL); } vect0 = ALLOC(DdNode *,lastsub); if (vect0 == NULL) { dd->errorCode = CUDD_MEMORY_OUT; Cudd_RecursiveDeref(dd,key1); FREE(vect1); return(NULL); } /* Cofactor the gi. Eliminate vect1[index] and vect0[index], because ** we do not need them. */ for (i = 0; i < lastsub; i++) { DdNode *gi = vector[i]; if (gi == NULL) { vect1[i] = vect0[i] = NULL; } else if (gi->index == index) { vect1[i] = cuddT(gi); vect0[i] = cuddE(gi); } else { vect1[i] = vect0[i] = gi; } } vect1[index] = vect0[index] = NULL; /* Recur on children. */ T = cuddAddNonSimComposeRecur(dd,f1,vect1,key1,cube1,lastsub); FREE(vect1); if (T == NULL) { Cudd_RecursiveDeref(dd,key1); FREE(vect0); return(NULL); } cuddRef(T); E = cuddAddNonSimComposeRecur(dd,f0,vect0,key0,cube1,lastsub); FREE(vect0); if (E == NULL) { Cudd_RecursiveDeref(dd,key1); Cudd_RecursiveDeref(dd,T); return(NULL); } cuddRef(E); Cudd_RecursiveDeref(dd,key1); /* Retrieve the 0-1 ADD for the current top variable from vector, ** and call cuddAddIteRecur with the T and E we just created. */ r = cuddAddIteRecur(dd,vector[index],T,E); if (r == NULL) { Cudd_RecursiveDeref(dd,T); Cudd_RecursiveDeref(dd,E); return(NULL); } cuddRef(r); Cudd_RecursiveDeref(dd,T); Cudd_RecursiveDeref(dd,E); cuddDeref(r); /* Store answer to trim recursion. */ cuddCacheInsert(dd,DD_ADD_NON_SIM_COMPOSE_TAG,f,key,cube,r); return(r); } /* end of cuddAddNonSimComposeRecur */
/**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_addVectorCompose.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ static DdNode * cuddAddVectorComposeRecur( DdManager * dd /* DD manager */, DdHashTable * table /* computed table */, DdNode * f /* ADD in which to compose */, DdNode ** vector /* functions to substitute */, int deepest /* depth of deepest substitution */) { DdNode *T,*E; DdNode *res; statLine(dd); /* If we are past the deepest substitution, return f. */ if (cuddI(dd,f->index) > deepest) { return(f); } if ((res = cuddHashTableLookup1(table,f)) != NULL) { #ifdef DD_DEBUG addVectorComposeHits++; #endif return(res); } /* Split and recur on children of this node. */ T = cuddAddVectorComposeRecur(dd,table,cuddT(f),vector,deepest); if (T == NULL) return(NULL); cuddRef(T); E = cuddAddVectorComposeRecur(dd,table,cuddE(f),vector,deepest); if (E == NULL) { Cudd_RecursiveDeref(dd, T); return(NULL); } cuddRef(E); /* Retrieve the 0-1 ADD for the current top variable and call ** cuddAddIteRecur with the T and E we just created. */ res = cuddAddIteRecur(dd,vector[f->index],T,E); if (res == NULL) { Cudd_RecursiveDeref(dd, T); Cudd_RecursiveDeref(dd, E); return(NULL); } cuddRef(res); Cudd_RecursiveDeref(dd, T); Cudd_RecursiveDeref(dd, E); /* Do not keep the result if the reference count is only 1, since ** it will not be visited again */ if (f->ref != 1) { ptrint fanout = (ptrint) f->ref; cuddSatDec(fanout); if (!cuddHashTableInsert1(table,f,res,fanout)) { Cudd_RecursiveDeref(dd, res); return(NULL); } } cuddDeref(res); return(res); } /* end of cuddAddVectorComposeRecur */
/**Function******************************************************************** Synopsis [Implements the recursive step of Cudd_addPermute.] Description [ Recursively puts the ADD in the order given in the array permut. Checks for trivial cases to terminate recursion, then splits on the children of this node. Once the solutions for the children are obtained, it puts into the current position the node from the rest of the ADD that should be here. Then returns this ADD. The key here is that the node being visited is NOT put in its proper place by this instance, but rather is switched when its proper position is reached in the recursion tree.<p> The DdNode * that is returned is the same ADD as passed in as node, but in the new order.] SideEffects [None] SeeAlso [Cudd_addPermute cuddBddPermuteRecur] ******************************************************************************/ static DdNode * cuddAddPermuteRecur( DdManager * manager /* DD manager */, DdHashTable * table /* computed table */, DdNode * node /* ADD to be reordered */, int * permut /* permutation array */) { DdNode *T,*E; DdNode *res,*var; int index; statLine(manager); /* Check for terminal case of constant node. */ if (cuddIsConstant(node)) { return(node); } /* If problem already solved, look up answer and return. */ if (node->ref != 1 && (res = cuddHashTableLookup1(table,node)) != NULL) { #ifdef DD_DEBUG addPermuteRecurHits++; #endif return(res); } /* Split and recur on children of this node. */ T = cuddAddPermuteRecur(manager,table,cuddT(node),permut); if (T == NULL) return(NULL); cuddRef(T); E = cuddAddPermuteRecur(manager,table,cuddE(node),permut); if (E == NULL) { Cudd_RecursiveDeref(manager, T); return(NULL); } cuddRef(E); /* Move variable that should be in this position to this position ** by creating a single var ADD for that variable, and calling ** cuddAddIteRecur with the T and E we just created. */ index = permut[node->index]; var = cuddUniqueInter(manager,index,DD_ONE(manager),DD_ZERO(manager)); if (var == NULL) return(NULL); cuddRef(var); res = cuddAddIteRecur(manager,var,T,E); if (res == NULL) { Cudd_RecursiveDeref(manager,var); Cudd_RecursiveDeref(manager, T); Cudd_RecursiveDeref(manager, E); return(NULL); } cuddRef(res); Cudd_RecursiveDeref(manager,var); Cudd_RecursiveDeref(manager, T); Cudd_RecursiveDeref(manager, E); /* Do not keep the result if the reference count is only 1, since ** it will not be visited again. */ if (node->ref != 1) { ptrint fanout = (ptrint) node->ref; cuddSatDec(fanout); if (!cuddHashTableInsert1(table,node,res,fanout)) { Cudd_RecursiveDeref(manager, res); return(NULL); } } cuddDeref(res); return(res); } /* end of cuddAddPermuteRecur */
/**Function******************************************************************** Synopsis [Implements the recursive step of Cudd_addIte(f,g,h).] Description [Implements the recursive step of Cudd_addIte(f,g,h). Returns a pointer to the resulting ADD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_addIte] ******************************************************************************/ DdNode * cuddAddIteRecur( DdManager * dd, DdNode * f, DdNode * g, DdNode * h) { DdNode *one,*zero; DdNode *r,*Fv,*Fnv,*Gv,*Gnv,*Hv,*Hnv,*t,*e; unsigned int topf,topg,toph,v; int index; statLine(dd); /* Trivial cases. */ /* One variable cases. */ if (f == (one = DD_ONE(dd))) { /* ITE(1,G,H) = G */ return(g); } if (f == (zero = DD_ZERO(dd))) { /* ITE(0,G,H) = H */ return(h); } /* From now on, f is known to not be a constant. */ addVarToConst(f,&g,&h,one,zero); /* Check remaining one variable cases. */ if (g == h) { /* ITE(F,G,G) = G */ return(g); } if (g == one) { /* ITE(F,1,0) = F */ if (h == zero) return(f); } topf = cuddI(dd,f->index); topg = cuddI(dd,g->index); toph = cuddI(dd,h->index); v = ddMin(topg,toph); /* A shortcut: ITE(F,G,H) = (x,G,H) if F=(x,1,0), x < top(G,H). */ if (topf < v && cuddT(f) == one && cuddE(f) == zero) { r = cuddUniqueInter(dd,(int)f->index,g,h); return(r); } if (topf < v && cuddT(f) == zero && cuddE(f) == one) { r = cuddUniqueInter(dd,(int)f->index,h,g); return(r); } /* Check cache. */ r = cuddCacheLookup(dd,DD_ADD_ITE_TAG,f,g,h); if (r != NULL) { return(r); } /* Compute cofactors. */ if (topf <= v) { v = ddMin(topf,v); /* v = top_var(F,G,H) */ index = f->index; Fv = cuddT(f); Fnv = cuddE(f); } else { Fv = Fnv = f; } if (topg == v) { index = g->index; Gv = cuddT(g); Gnv = cuddE(g); } else { Gv = Gnv = g; } if (toph == v) { index = h->index; Hv = cuddT(h); Hnv = cuddE(h); } else { Hv = Hnv = h; } /* Recursive step. */ t = cuddAddIteRecur(dd,Fv,Gv,Hv); if (t == NULL) return(NULL); cuddRef(t); e = cuddAddIteRecur(dd,Fnv,Gnv,Hnv); if (e == NULL) { Cudd_RecursiveDeref(dd,t); return(NULL); } cuddRef(e); r = (t == e) ? t : cuddUniqueInter(dd,index,t,e); if (r == NULL) { Cudd_RecursiveDeref(dd,t); Cudd_RecursiveDeref(dd,e); return(NULL); } cuddDeref(t); cuddDeref(e); cuddCacheInsert(dd,DD_ADD_ITE_TAG,f,g,h,r); return(r); } /* end of cuddAddIteRecur */