📄 cuddbddite.c
字号:
} /* end of Cudd_bddXor *//**Function******************************************************************** Synopsis [Computes the exclusive NOR of two BDDs f and g.] Description [Computes the exclusive NOR of two BDDs f and g. Returns a pointer to the resulting BDD if successful; NULL if the intermediate result blows up.] SideEffects [None] SeeAlso [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddOr Cudd_bddNand Cudd_bddNor Cudd_bddXor]******************************************************************************/DdNode *Cudd_bddXnor( DdManager * dd, DdNode * f, DdNode * g){ DdNode *res; do { dd->reordered = 0; res = cuddBddXorRecur(dd,f,Cudd_Not(g)); } while (dd->reordered == 1); return(res);} /* end of Cudd_bddXnor *//**Function******************************************************************** Synopsis [Determines whether f is less than or equal to g.] Description [Returns 1 if f is less than or equal to g; 0 otherwise. No new nodes are created.] SideEffects [None] SeeAlso [Cudd_bddIteConstant Cudd_addEvalConst]******************************************************************************/intCudd_bddLeq( DdManager * dd, DdNode * f, DdNode * g){ DdNode *one, *zero, *tmp, *F, *fv, *fvn, *gv, *gvn; unsigned int topf, topg, res; statLine(dd); /* Terminal cases and normalization. */ if (f == g) return(1); if (Cudd_IsComplement(g)) { /* Special case: if f is regular and g is complemented, ** f(1,...,1) = 1 > 0 = g(1,...,1). */ if (!Cudd_IsComplement(f)) return(0); /* Both are complemented: Swap and complement because ** f <= g <=> g' <= f' and we want the second argument to be regular. */ tmp = g; g = Cudd_Not(f); f = Cudd_Not(tmp); } else if (Cudd_IsComplement(f) && g < f) { tmp = g; g = Cudd_Not(f); f = Cudd_Not(tmp); } /* Now g is regular and, if f is not regular, f < g. */ one = DD_ONE(dd); if (g == one) return(1); /* no need to test against zero */ if (f == one) return(0); /* since at this point g != one */ if (Cudd_Not(f) == g) return(0); /* because neither is constant */ zero = Cudd_Not(one); if (f == zero) return(1); /* Here neither f nor g is constant. */ /* Check cache. */ tmp = cuddCacheLookup2(dd,(DdNode * (*)(DdManager *, DdNode *, DdNode *))Cudd_bddLeq,f,g); if (tmp != NULL) { return(tmp == one); } /* Compute cofactors. */ F = Cudd_Regular(f); topf = dd->perm[F->index]; topg = dd->perm[g->index]; if (topf <= topg) { fv = cuddT(F); fvn = cuddE(F); if (f != F) { fv = Cudd_Not(fv); fvn = Cudd_Not(fvn); } } else { fv = fvn = f; } if (topg <= topf) { gv = cuddT(g); gvn = cuddE(g); } else { gv = gvn = g; } /* Recursive calls. Since we want to maximize the probability of ** the special case f(1,...,1) > g(1,...,1), we consider the negative ** cofactors first. Indeed, the complementation parity of the positive ** cofactors is the same as the one of the parent functions. */ res = Cudd_bddLeq(dd,fvn,gvn) && Cudd_bddLeq(dd,fv,gv); /* Store result in cache and return. */ cuddCacheInsert2(dd,(DdNode * (*)(DdManager *, DdNode *, DdNode *))Cudd_bddLeq,f,g,(res ? one : zero)); return(res);} /* end of Cudd_bddLeq *//*---------------------------------------------------------------------------*//* Definition of internal functions *//*---------------------------------------------------------------------------*//**Function******************************************************************** Synopsis [Implements the recursive step of Cudd_bddIte.] Description [Implements the recursive step of Cudd_bddIte. Returns a pointer to the resulting BDD. NULL if the intermediate result blows up or if reordering occurs.] SideEffects [None] SeeAlso []******************************************************************************/DdNode *cuddBddIteRecur( DdManager * dd, DdNode * f, DdNode * g, DdNode * h){ DdNode *one, *zero, *res; DdNode *r, *Fv, *Fnv, *Gv, *Gnv, *H, *Hv, *Hnv, *t, *e; unsigned int topf, topg, toph, v; int index; int comple; statLine(dd); /* Terminal cases. */ /* One variable cases. */ if (f == (one = DD_ONE(dd))) /* ITE(1,G,H) = G */ return(g); if (f == (zero = Cudd_Not(one))) /* ITE(0,G,H) = H */ return(h); /* From now on, f is known not to be a constant. */ if (g == one || f == g) { /* ITE(F,F,H) = ITE(F,1,H) = F + H */ if (h == zero) { /* ITE(F,1,0) = F */ return(f); } else { res = cuddBddAndRecur(dd,Cudd_Not(f),Cudd_Not(h)); return(Cudd_NotCond(res,res != NULL)); } } else if (g == zero || f == Cudd_Not(g)) { /* ITE(F,!F,H) = ITE(F,0,H) = !F * H */ if (h == one) { /* ITE(F,0,1) = !F */ return(Cudd_Not(f)); } else { res = cuddBddAndRecur(dd,Cudd_Not(f),h); return(res); } } if (h == zero || f == h) { /* ITE(F,G,F) = ITE(F,G,0) = F * G */ res = cuddBddAndRecur(dd,f,g); return(res); } else if (h == one || f == Cudd_Not(h)) { /* ITE(F,G,!F) = ITE(F,G,1) = !F + G */ res = cuddBddAndRecur(dd,f,Cudd_Not(g)); return(Cudd_NotCond(res,res != NULL)); } /* Check remaining one variable case. */ if (g == h) { /* ITE(F,G,G) = G */ return(g); } else if (g == Cudd_Not(h)) { /* ITE(F,G,!G) = F <-> G */ res = cuddBddXorRecur(dd,f,h); return(res); } /* From here, there are no constants. */ comple = bddVarToCanonicalSimple(dd, &f, &g, &h, &topf, &topg, &toph); /* f & g are now regular pointers */ v = ddMin(topg, toph); /* A shortcut: ITE(F,G,H) = (v,G,H) if F = (v,1,0), v < top(G,H). */ if (topf < v && cuddT(f) == one && cuddE(f) == zero) { r = cuddUniqueInter(dd, (int) f->index, g, h); return(Cudd_NotCond(r,comple && r != NULL)); } /* Check cache. */ r = cuddCacheLookup(dd, DD_BDD_ITE_TAG, f, g, h); if (r != NULL) { return(Cudd_NotCond(r,comple)); } /* 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) { H = Cudd_Regular(h); index = H->index; Hv = cuddT(H); Hnv = cuddE(H); if (Cudd_IsComplement(h)) { Hv = Cudd_Not(Hv); Hnv = Cudd_Not(Hnv); } } else { Hv = Hnv = h; } /* Recursive step. */ t = cuddBddIteRecur(dd,Fv,Gv,Hv); if (t == NULL) return(NULL); cuddRef(t); e = cuddBddIteRecur(dd,Fnv,Gnv,Hnv); if (e == NULL) { Cudd_IterDerefBdd(dd,t); return(NULL); } cuddRef(e); r = (t == e) ? t : cuddUniqueInter(dd,index,t,e); if (r == NULL) { Cudd_IterDerefBdd(dd,t); Cudd_IterDerefBdd(dd,e); return(NULL); } cuddDeref(t); cuddDeref(e); cuddCacheInsert(dd, DD_BDD_ITE_TAG, f, g, h, r); return(Cudd_NotCond(r,comple));} /* end of cuddBddIteRecur *//**Function******************************************************************** Synopsis [Implements the recursive step of Cudd_bddIntersect.] Description [] SideEffects [None] SeeAlso [Cudd_bddIntersect]******************************************************************************/DdNode *cuddBddIntersectRecur( DdManager * dd, DdNode * f, DdNode * g){ DdNode *res; DdNode *F, *G, *t, *e; DdNode *fv, *fnv, *gv, *gnv; DdNode *one, *zero; unsigned int index, topf, topg; statLine(dd); one = DD_ONE(dd); zero = Cudd_Not(one); /* Terminal cases. */ if (f == zero || g == zero || f == Cudd_Not(g)) return(zero); if (f == g || g == one) return(f); if (f == one) return(g); /* At this point f and g are not constant. */ if (f > g) { DdNode *tmp = f; f = g; g = tmp; } res = cuddCacheLookup2(dd,Cudd_bddIntersect,f,g); if (res != NULL) return(res); /* Find splitting variable. Here we can skip the use of cuddI, ** because the operands are known to be non-constant. */ F = Cudd_Regular(f); topf = dd->perm[F->index]; G = Cudd_Regular(g); topg = dd->perm[G->index]; /* Compute cofactors. */ if (topf <= topg) { index = F->index; fv = cuddT(F); fnv = cuddE(F); if (Cudd_IsComplement(f)) { fv = Cudd_Not(fv); fnv = Cudd_Not(fnv); } } else { index = G->index; fv = fnv = f; } if (topg <= topf) { gv = cuddT(G); gnv = cuddE(G); if (Cudd_IsComplement(g)) { gv = Cudd_Not(gv); gnv = Cudd_Not(gnv); } } else { gv = gnv = g; } /* Compute partial results. */ t = cuddBddIntersectRecur(dd,fv,gv); if (t == NULL) return(NULL); cuddRef(t); if (t != zero) { e = zero; } else { e = cuddBddIntersectRecur(dd,fnv,gnv); if (e == NULL) { Cudd_IterDerefBdd(dd, t); return(NULL); } } cuddRef(e); if (t == e) { /* both equal zero */ res = t; } else if (Cudd_IsComplement(t)) { res = cuddUniqueInter(dd,(int)index,Cudd_Not(t),Cudd_Not(e)); if (res == NULL) { Cudd_IterDerefBdd(dd, t); Cudd_IterDerefBdd(dd, e); return(NULL); } res = Cudd_Not(res); } else { res = cuddUniqueInter(dd,(int)index,t,e); if (res == NULL) { Cudd_IterDerefBdd(dd, t); Cudd_IterDerefBdd(dd, e); return(NULL); } } cuddDeref(e); cuddDeref(t); cuddCacheInsert2(dd,Cudd_bddIntersect,f,g,res); return(res);} /* end of cuddBddIntersectRecur *//**Function******************************************************************** Synopsis [Implements the recursive step of Cudd_bddAnd.] Description [Implements the recursive step of Cudd_bddAnd by taking the conjunction of two BDDs. Returns a pointer to the result is successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddAnd]******************************************************************************/DdNode *cuddBddAndRecur( DdManager * manager, DdNode * f, DdNode * g){ DdNode *F, *fv, *fnv, *G, *gv, *gnv; DdNode *one, *r, *t, *e; unsigned int topf, topg, index; statLine(manager); one = DD_ONE(manager); /* Terminal cases. */ F = Cudd_Regular(f); G = Cudd_Regular(g); if (F == G) { if (f == g) return(f); else return(Cudd_Not(one)); } if (F == one) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -