double CountMintermFractionRecurr(DdNode* node, NodeTable& table) { double frac = std::numeric_limits<double>::quiet_NaN(); auto iter = table.find(node); if(iter != table.end()) { //Use sub-problem from table frac = iter->second; } else { if(Cudd_IsConstant(node)) { assert(Cudd_V(node) == 1); //Base case (leaf node) if(Cudd_IsComplement(node)) { //At the false node frac = 0.; } else { assert(!Cudd_IsComplement(node)); //At the true node frac = 1.; } } else { //Recursive case (internal node) assert(!Cudd_IsConstant(node)); DdNode* then_node = (Cudd_IsComplement(node)) ? Cudd_Not(Cudd_T(node)) : Cudd_T(node); double frac_then = CountMintermFractionRecurr(then_node, table); DdNode* else_node = (Cudd_IsComplement(node)) ? Cudd_Not(Cudd_E(node)) : Cudd_E(node); double frac_else = CountMintermFractionRecurr(else_node, table); // Using identity: // |f| = (|f0| + |f1|) / 2 // // where |f| is the number of minterms // and f0 and f1 are the co-factors of f frac = (frac_then + frac_else) / 2.; } //Store sub-problem answer in table auto result = table.insert(std::make_pair(node, frac)); assert(result.second); //Was inserted } return frac; }
void UpdateForward(DdNode *node, int nex) { int index, position, mVarIndex; DdNode *T, *E, *nodereg; variable v; double *value_p, *value_p_T, *value_p_F, p; if (Cudd_IsConstant(node)) { return; } else { index = Cudd_NodeReadIndex(node); mVarIndex = bVar2mVar_ex[nex][index]; v = vars_ex[nex][mVarIndex]; p = probs_ex[nex][index]; nodereg = Cudd_Regular(node); value_p = get_value(nodesF, nodereg); if (value_p == NULL) { printf("Error\n"); return; } else { T = Cudd_T(node); E = Cudd_E(node); if (!Cudd_IsConstant(T)) { value_p_T = get_value(nodesF, T); if (value_p_T != NULL) { *value_p_T = *value_p_T + *value_p * p; } else { add_or_replace_node(nodesF, Cudd_Regular(T), *value_p * p); index = Cudd_NodeReadIndex(T); position = Cudd_ReadPerm(mgr_ex[nex], index); nodesToVisit[position] = (DdNode **)realloc( nodesToVisit[position], (NnodesToVisit[position] + 1) * sizeof(DdNode *)); nodesToVisit[position][NnodesToVisit[position]] = T; NnodesToVisit[position] = NnodesToVisit[position] + 1; } } if (!Cudd_IsConstant(E)) { value_p_F = get_value(nodesF, Cudd_Regular(E)); if (value_p_F != NULL) { *value_p_F = *value_p_F + *value_p * (1 - p); } else { add_or_replace_node(nodesF, Cudd_Regular(E), *value_p * (1 - p)); index = Cudd_NodeReadIndex(E); position = Cudd_ReadPerm(mgr_ex[nex], index); nodesToVisit[position] = (DdNode **)realloc( nodesToVisit[position], (NnodesToVisit[position] + 1) * sizeof(DdNode *)); nodesToVisit[position][NnodesToVisit[position]] = E; NnodesToVisit[position] = NnodesToVisit[position] + 1; } } return; } } }
double Prob(DdNode *node ) /* compute the probability of the expression rooted at node nodes is used to store nodes for which the probability has alread been computed so that it is not recomputed */ { int comp; int index; double res,resT,resF; double p; double * value_p; DdNode **key,*T,*F,*nodereg; double *rp; comp=Cudd_IsComplement(node); if (Cudd_IsConstant(node)) { if (comp) return 0.0; else return 1.0; } else { nodereg=Cudd_Regular(node); value_p=g_hash_table_lookup(nodes,&node); if (value_p!=NULL) { if (comp) return 1-*value_p; else return *value_p; } else { index=Cudd_NodeReadIndex(node); p=probs[index]; T = Cudd_T(node); F = Cudd_E(node); resT=Prob(T); resF=Prob(F); res=p*resT+(1-p)*resF; key=(DdNode **)malloc(sizeof(DdNode *)); *key=nodereg; rp=(double *)malloc(sizeof(double)); *rp=res; g_hash_table_insert(nodes, key, rp); if (comp) return 1-res; else return res; } } }
uint Synth::walk(DdNode *a_dd) { /** Walk given DdNode node (recursively). If a given node requires intermediate AND gates for its representation, the function adds them. Literal representing given input node is `not` added to the spec. :returns: literal representing input node **/ // caching static hmap<DdNode*, uint> cache; { auto cached_lit = cache.find(Cudd_Regular(a_dd)); if (cached_lit != cache.end()) return Cudd_IsComplement(a_dd) ? NEGATED(cached_lit->second) : cached_lit->second; } // end of caching if (Cudd_IsConstant(a_dd)) return (uint) (a_dd == cudd.bddOne().getNode()); // in aiger: 0 is False and 1 is True // get an index of the variable uint a_lit = aiger_by_cudd[Cudd_NodeReadIndex(a_dd)]; DdNode *t_bdd = Cudd_T(a_dd); DdNode *e_bdd = Cudd_E(a_dd); uint t_lit = walk(t_bdd); uint e_lit = walk(e_bdd); // ite(a_bdd, then_bdd, else_bdd) // = a*then + !a*else // = !(!(a*then) * !(!a*else)) // -> in general case we need 3 more ANDs uint a_t_lit = get_optimized_and_lit(a_lit, t_lit); uint na_e_lit = get_optimized_and_lit(NEGATED(a_lit), e_lit); uint n_a_t_lit = NEGATED(a_t_lit); uint n_na_e_lit = NEGATED(na_e_lit); uint and_lit = get_optimized_and_lit(n_a_t_lit, n_na_e_lit); uint res = NEGATED(and_lit); cache[Cudd_Regular(a_dd)] = res; if (Cudd_IsComplement(a_dd)) res = NEGATED(res); return res; }
double Prob(DdNode *node, int comp_par) /* compute the probability of the expression rooted at node. table is used to store nodeB for which the probability has alread been computed so that it is not recomputed */ { int index, mVarIndex, comp, pos; variable v; double res; double p, pt, pf, BChild0, BChild1; double *value_p; DdNode *nodekey, *T, *F; comp = Cudd_IsComplement(node); comp = (comp && !comp_par) || (!comp && comp_par); if (Cudd_IsConstant(node)) { if (comp) return 0.0; else return 1.0; } else { nodekey = Cudd_Regular(node); value_p = get_value(table, nodekey); if (value_p != NULL) return *value_p; else { index = Cudd_NodeReadIndex(node); // Returns the index of the node. The // node pointer can be either regular or // complemented. // The index field holds the name of the variable that labels the node. // The index of a variable is a permanent attribute that reflects the // order of creation. p = probs_ex[ex][index]; T = Cudd_T(node); F = Cudd_E(node); pf = Prob(F, comp); pt = Prob(T, comp); BChild0 = pf * (1 - p); BChild1 = pt * p; mVarIndex = bVar2mVar_ex[ex][index]; v = vars_ex[ex][mVarIndex]; pos = index - v.firstBoolVar; res = BChild0 + BChild1; add_node(table, nodekey, res); return res; } } }
double ProbBool(extmanager MyManager, DdNode *node, int bits, int nBit,int posBVar,variable v, int comp) /* explores a group of binary variables making up the multivalued variable v */ { DdNode *T,*F; double p,res; double * probs; int index; probs=v.probabilities; if (nBit==0) { if (bits>=v.nVal) { return 0.0; } else { p=probs[bits]; res=p*Prob(MyManager,node,comp); return res; } } else { index=Cudd_NodeReadIndex(node); if (correctPosition(index,v,posBVar)) { T = Cudd_T(node); F = Cudd_E(node); bits=bits<<1; res=ProbBool(MyManager,T,bits+1,nBit-1,posBVar+1,v,comp); comp=(!comp && Cudd_IsComplement(F)) || (comp && !Cudd_IsComplement(F)); res=res+ ProbBool(MyManager,F,bits,nBit-1,posBVar+1,v,comp); return res; } else { bits=bits<<1; res=ProbBool(MyManager,node,bits+1,nBit-1,posBVar+1,v,comp); res=res+ ProbBool(MyManager,node,bits,nBit-1,posBVar+1,v,comp); return res; } } }
/**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 [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 */
double ProbPath(DdNode *node, int comp_par, int nex) { int index, mVarIndex, comp, pos, position, boolVarIndex; variable v; double res; double value, p, pt, pf, BChild0, BChild1, e0, e1; double *value_p, **eta_rule; DdNode *nodekey, *T, *F; comp = Cudd_IsComplement(node); comp = (comp && !comp_par) || (!comp && comp_par); if (Cudd_IsConstant(node)) { value = Cudd_V(node); if (comp) { return 0.0; } else { return 1.0; } } else { nodekey = Cudd_Regular(node); value_p = get_value(nodesB, nodekey); if (value_p != NULL) { return *value_p; } else { index = Cudd_NodeReadIndex(node); p = probs_ex[nex][index]; T = Cudd_T(node); F = Cudd_E(node); pf = ProbPath(F, comp, nex); pt = ProbPath(T, comp, nex); BChild0 = pf * (1 - p); BChild1 = pt * p; value_p = get_value(nodesF, nodekey); e0 = (*value_p) * BChild0; e1 = (*value_p) * BChild1; mVarIndex = bVar2mVar_ex[nex][index]; v = vars_ex[nex][mVarIndex]; pos = index - v.firstBoolVar; eta_rule = eta_temp[v.nRule]; eta_rule[pos][0] = eta_rule[pos][0] + e0; eta_rule[pos][1] = eta_rule[pos][1] + e1; res = BChild0 + BChild1; add_node(nodesB, nodekey, res); position = Cudd_ReadPerm(mgr_ex[nex], index); position = position + 1; boolVarIndex = Cudd_ReadInvPerm( mgr_ex[nex], position); // Returns the index of the variable currently // in the i-th position of the order. if (position < boolVars_ex[nex]) { sigma[position] = sigma[position] + e0 + e1; } if (!Cudd_IsConstant(T)) { index = Cudd_NodeReadIndex(T); position = Cudd_ReadPerm(mgr_ex[nex], index); sigma[position] = sigma[position] - e1; } if (!Cudd_IsConstant(F)) { index = Cudd_NodeReadIndex(F); position = Cudd_ReadPerm(mgr_ex[nex], index); sigma[position] = sigma[position] - e0; } return res; } } }
/**Function******************************************************************** Synopsis [Performs the recursive step of Cuddaux_addConstrain.] Description [Performs the recursive step of Cuddaux_addConstrain. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cuddaux_addConstrain] ******************************************************************************/ DdNode * cuddauxAddConstrainRecur( DdManager * dd, DdNode * f, DdNode * c) { DdNode *Fv, *Fnv, *Cv, *Cnv, *t, *e, *res; DdNode *one, *zero; unsigned int topf, topc; int index; one = DD_ONE(dd); zero = Cudd_Not(one); /* Trivial cases. */ if (c == one) return(f); if (c == zero){ fprintf(stderr,"CuddauxAddConstrainRecur: warning: false careset\n"); return(DD_BACKGROUND(dd)); } if (Cudd_IsConstant(f)) return(f); /* Now f and c are non-constant. */ /* Check the cache. */ res = cuddCacheLookup2(dd, Cuddaux_addConstrain, f, c); if (res != NULL) { return(res); } /* Recursive step. */ topf = dd->perm[f->index]; topc = dd->perm[Cudd_Regular(c)->index]; if (topf <= topc) { index = f->index; Fv = cuddT(f); Fnv = cuddE(f); } else { index = Cudd_Regular(c)->index; Fv = Fnv = f; } if (topc <= topf) { Cv = Cudd_T(c); Cnv = Cudd_E(c); if (Cudd_IsComplement(c)) { Cv = Cudd_Not(Cv); Cnv = Cudd_Not(Cnv); } } else { Cv = Cnv = c; } if (!Cudd_IsConstant(Cv)) { t = cuddauxAddConstrainRecur(dd, Fv, Cv); if (t == NULL) return(NULL); } else if (Cv == one) { t = Fv; } else { /* Cv == zero: return Fnv @ Cnv */ if (Cnv == one) { res = Fnv; } else { res = cuddauxAddConstrainRecur(dd, Fnv, Cnv); if (res == NULL) return(NULL); } return(res); } cuddRef(t); if (!Cudd_IsConstant(Cnv)) { e = cuddauxAddConstrainRecur(dd, Fnv, Cnv); if (e == NULL) { Cudd_RecursiveDeref(dd, t); return(NULL); } } else if (Cnv == one) { e = Fnv; } else { /* Cnv == zero: return Fv @ Cv previously computed */ cuddDeref(t); return(t); } cuddRef(e); res = (t == e) ? t : cuddUniqueInter(dd, index, t, e); if (res == NULL) { Cudd_RecursiveDeref(dd, e); Cudd_RecursiveDeref(dd, t); return(NULL); } cuddDeref(t); cuddDeref(e); cuddCacheInsert2(dd, Cuddaux_addConstrain, f, c, res); return(res); } /* end of cuddauxAddConstrainRecur */
/**Function******************************************************************** Synopsis [Performs the recursive step of Cuddaux_addRestrict.] Description [Performs the recursive step of Cuddaux_addRestrict. Returns the restricted ADD if successful; otherwise NULL.] SideEffects [None] SeeAlso [Cudd_addRestrict] ******************************************************************************/ DdNode * cuddauxAddRestrictRecur( DdManager * dd, DdNode * f, DdNode * c) { DdNode *Fv, *Fnv, *Cv, *Cnv, *t, *e, *res, *one, *zero; unsigned int topf, topc; int index; one = DD_ONE(dd); zero = Cudd_Not(one); /* Trivial cases */ if (c == one) return(f); if (c == zero){ fprintf(stderr,"CuddauxAddRestrictRecur: warning: false careset\n"); return(DD_BACKGROUND(dd)); } if (Cudd_IsConstant(f)) return(f); /* Now f and c are non-constant. */ /* Check the cache. */ res = cuddCacheLookup2(dd, Cuddaux_addRestrict, f, c); if (res != NULL) { return(res); } topf = dd->perm[f->index]; topc = dd->perm[Cudd_Regular(c)->index]; if (topc < topf) { /* abstract top variable from c */ DdNode *d, *s1, *s2; /* Take the OR by applying DeMorgan. */ /* Find complements of cofactors of c. */ if (Cudd_IsComplement(c)) { s1 = cuddT(Cudd_Regular(c)); s2 = cuddE(Cudd_Regular(c)); } else { s1 = Cudd_Not(cuddT(c)); s2 = Cudd_Not(cuddE(c)); } /* Take the AND and negate */ d = cuddBddAndRecur(dd, s1, s2); if (d == NULL) return(NULL); d = Cudd_Not(d); cuddRef(d); res = cuddauxAddRestrictRecur(dd, f, d); if (res == NULL) { Cudd_IterDerefBdd(dd, d); return(NULL); } cuddRef(res); Cudd_IterDerefBdd(dd, d); cuddDeref(res); cuddCacheInsert2(dd, Cuddaux_addRestrict, f, c, res); return(res); } /* Recursive step. Here topf <= topc. */ index = f->index; Fv = cuddT(f); Fnv = cuddE(f); if (topc == topf) { Cv = Cudd_T(c); Cnv = Cudd_E(c); if (Cudd_IsComplement(c)) { Cv = Cudd_Not(Cv); Cnv = Cudd_Not(Cnv); } } else { Cv = Cnv = c; } if (!Cudd_IsConstant(Cv)) { t = cuddauxAddRestrictRecur(dd, Fv, Cv); if (t == NULL) return(NULL); } else if (Cv == one) { t = Fv; } else { /* Cv == zero: return(Fnv @ Cnv) */ if (Cnv == one) { res = Fnv; } else { res = cuddauxAddRestrictRecur(dd, Fnv, Cnv); if (res == NULL) return(NULL); } return(res); } cuddRef(t); if (!Cudd_IsConstant(Cnv)) { e = cuddauxAddRestrictRecur(dd, Fnv, Cnv); if (e == NULL) { Cudd_RecursiveDeref(dd, t); return(NULL); } } else if (Cnv == one) { e = Fnv; } else { /* Cnv == zero: return (Fv @ Cv) previously computed */ cuddDeref(t); return(t); } cuddRef(e); res = (t == e) ? t : cuddUniqueInter(dd, index, t, e); if (res == NULL) { Cudd_RecursiveDeref(dd, e); Cudd_RecursiveDeref(dd, t); return(NULL); } cuddDeref(t); cuddDeref(e); cuddCacheInsert2(dd, Cuddaux_addRestrict, f, c, res); return(res); } /* end of cuddauxAddRestrictRecur */