void getActionAndValue(Pair & dval, Pair & aval, int whichPolicy) { // query the whichPolicy policy action and value with the current values of varvals // fprintf(stderr,"querying policy and action diagrams %d\n",whichPolicy); // build an array varass of 1s and 0s over the variables v // with assignments corresponding to the varvals (values for the original variables ov) // then call *(Cudd_V(Cudd_Eval(dd,act, varass))) int *varass = new int[2*nvars]; int i,j,nbv,tmp,nbvals; for (i=0; i<nvars*2; i++) varass[i] = 0; for (i=0; i<novars; i++) { nbv = ov[i].nbvars; nbvals = int(pow(2.0,nbv)); tmp = nbvals-varvals[i]-1; for (j=nbv-1; j>=0; j--) { varass[Cudd_NodeReadIndex(v[ov[i].var1index+j].add_var)] = tmp%2; tmp = tmp/2; } } dval = *(Cudd_V(Cudd_Eval(dd,val[whichPolicy],varass))); aval = *(Cudd_V(Cudd_Eval(dd,act[whichPolicy],varass))); delete [] varass; }
/** * @brief Basic ADD test. * @return 0 if successful; -1 otherwise. */ static int testAdd(int verbosity) { DdManager *manager; DdNode *f, *var, *tmp, *bg; int i, ret; CUDD_VALUE_TYPE pinf; manager = Cudd_Init(0, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0); if (!manager) { if (verbosity) { printf("initialization failed\n"); } return -1; } pinf = Cudd_V(Cudd_ReadPlusInfinity(manager)); if (verbosity) { printf("Plus infinity is %g\n", pinf); } f = Cudd_addConst(manager,5); Cudd_Ref(f); for (i = 3; i >= 0; i--) { var = Cudd_addIthVar(manager,i); Cudd_Ref(var); tmp = Cudd_addApply(manager,Cudd_addTimes,var,f); Cudd_Ref(tmp); Cudd_RecursiveDeref(manager,f); Cudd_RecursiveDeref(manager,var); f = tmp; } if (verbosity) { Cudd_PrintMinterm(manager, f); printf("\n"); } Cudd_RecursiveDeref(manager, f); bg = Cudd_ReadBackground(manager); if (verbosity) { printf("background (%g) minterms : ", Cudd_V(bg)); Cudd_ApaPrintMinterm(Cudd_ReadStdout(manager), manager, bg, 0); } ret = Cudd_CheckZeroRef(manager); if (ret != 0 && verbosity) { printf("%d non-zero ADD reference counts after dereferencing\n", ret); } Cudd_Quit(manager); return ret != 0; }
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; }
double Prob(extmanager MyManager, DdNode *node, int comp) /* 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 mVarIndex,nBit,index; variable v; hisnode *Found; double res; double value; if (Cudd_IsConstant(node)) { value=Cudd_V(node); if (comp) { return 0.0; } else { return 1.0; } } else { Found = GetNode1(MyManager.varmap.bVar2mVar,MyManager.his, MyManager.varmap.varstart, node); if (Found!=NULL) { return Found->dvalue; } else { index=Cudd_NodeReadIndex(node); mVarIndex=MyManager.varmap.bVar2mVar[index]; v=MyManager.varmap.mvars[mVarIndex]; nBit=v.nBit; res=ProbBool(MyManager,node,0,nBit,0,v,comp); AddNode1(MyManager.varmap.bVar2mVar,MyManager.his, MyManager.varmap.varstart, node, res, 0, NULL); return res; } } }
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 [Repeated squaring algorithm for all-pairs shortest paths.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ static DdNode * ntrSquare( DdManager *dd /* manager */, DdNode *D /* D(z,y): distance matrix */, DdNode **x /* array of x variables */, DdNode **y /* array of y variables */, DdNode **z /* array of z variables */, int vars /* number of variables in each of the three arrays */, int pr /* verbosity level */, int st /* use the selective trace algorithm */) { DdNode *zero; DdNode *I; /* identity matirix */ DdNode *w, *V, *P, *M, *R, *RT; DdNode *diff, *min, *minDiag; int n; int neg; long start_time; zero = Cudd_ReadZero(dd); /* Make a working copy of the original matrix. */ R = D; Cudd_Ref(R); I = Cudd_addXeqy(dd,vars,z,y); /* identity matrix */ Cudd_Ref(I); /* Make a copy of the matrix for the selective trace algorithm. */ diff = R; Cudd_Ref(diff); start_time = util_cpu_time(); for (n = vars; n >= 0; n--) { printf("Starting iteration %d at time %s\n",vars-n, util_print_time(util_cpu_time() - start_time)); /* Check for negative cycles: They are identified by negative ** elements on the diagonal. */ /* Extract values from the diagonal. */ Cudd_Ref(w = Cudd_addIte(dd,I,R,zero)); minDiag = Cudd_addFindMin(dd,w); /* no need to ref */ neg = Cudd_V(minDiag) < 0; Cudd_RecursiveDeref(dd,w); if (neg) { Cudd_RecursiveDeref(dd,diff); (void) printf("Negative cycle after %d iterations!\n",vars-n); break; } /* Prepare the first operand of matrix multiplication: ** diff(z,y) -> RT(x,y) -> V(x,z) */ /* RT(x,y) */ Cudd_Ref(RT = Cudd_addSwapVariables(dd,diff,x,z,vars)); Cudd_RecursiveDeref(dd,diff); /* V(x,z) */ Cudd_Ref(V = Cudd_addSwapVariables(dd,RT,y,z,vars)); Cudd_RecursiveDeref(dd,RT); if (pr > 0) { double pathcount; (void) printf("V"); Cudd_PrintDebug(dd,V,2*vars,pr); pathcount = Cudd_CountPath(V); (void) printf("Path count = %g\n", pathcount); } /* V(x,z) * R(z,y) -> P(x,y) */ Cudd_Ref(P = Cudd_addTriangle(dd,V,R,z,vars)); Cudd_RecursiveDeref(dd,V); /* P(x,y) => M(z,y) */ Cudd_Ref(M = Cudd_addSwapVariables(dd,P,x,z,vars)); Cudd_RecursiveDeref(dd,P); if (pr>0) {(void) printf("M"); Cudd_PrintDebug(dd,M,2*vars,pr);} /* min(z,y) */ Cudd_Ref(min = Cudd_addApply(dd,Cudd_addMinimum,R,M)); Cudd_RecursiveDeref(dd,M); if (R == min) { Cudd_RecursiveDeref(dd,min); if (pr>0) {printf("Done after %d iterations\n",vars-n+1); } break; } /* diff(z,y) */ if (st) { Cudd_Ref(diff = Cudd_addApply(dd,Cudd_addDiff,min,R)); } else { Cudd_Ref(diff = min); } Cudd_RecursiveDeref(dd,R); R = min; /* keep a copy of matrix at current iter. */ if (pr > 0) { double pathcount; (void) printf("R"); Cudd_PrintDebug(dd,R,2*vars,pr); pathcount = Cudd_CountPath(R); (void) printf("Path count = %g\n", pathcount); } if (n == 0) { (void) printf("Negative cycle!\n"); break; } } Cudd_RecursiveDeref(dd,I); Cudd_Deref(R); return(R); } /* end of ntrSquare */
double maximum(ADD a) { return Cudd_V(a.FindMax().getNode()); }
/**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_addOuterSum.] Description [Performs the recursive step of Cudd_addOuterSum. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ static DdNode * cuddAddOuterSumRecur( DdManager *dd, DdNode *M, DdNode *r, DdNode *c) { DdNode *P, *R, *Mt, *Me, *rt, *re, *ct, *ce, *Rt, *Re; int topM, topc, topr; int v, index; statLine(dd); /* Check special cases. */ if (r == DD_PLUS_INFINITY(dd) || c == DD_PLUS_INFINITY(dd)) return(M); if (cuddIsConstant(c) && cuddIsConstant(r)) { R = cuddUniqueConst(dd,Cudd_V(c)+Cudd_V(r)); cuddRef(R); if (cuddIsConstant(M)) { if (cuddV(R) <= cuddV(M)) { cuddDeref(R); return(R); } else { Cudd_RecursiveDeref(dd,R); return(M); } } else { P = Cudd_addApply(dd,Cudd_addMinimum,R,M); cuddRef(P); Cudd_RecursiveDeref(dd,R); cuddDeref(P); return(P); } } /* Check the cache. */ R = cuddCacheLookup(dd,DD_ADD_OUT_SUM_TAG,M,r,c); if (R != NULL) return(R); topM = cuddI(dd,M->index); topr = cuddI(dd,r->index); topc = cuddI(dd,c->index); v = ddMin(topM,ddMin(topr,topc)); /* Compute cofactors. */ if (topM == v) { Mt = cuddT(M); Me = cuddE(M); } else { Mt = Me = M; } if (topr == v) { rt = cuddT(r); re = cuddE(r); } else { rt = re = r; } if (topc == v) { ct = cuddT(c); ce = cuddE(c); } else { ct = ce = c; } /* Recursively solve. */ Rt = cuddAddOuterSumRecur(dd,Mt,rt,ct); if (Rt == NULL) return(NULL); cuddRef(Rt); Re = cuddAddOuterSumRecur(dd,Me,re,ce); if (Re == NULL) { Cudd_RecursiveDeref(dd, Rt); return(NULL); } cuddRef(Re); index = dd->invperm[v]; R = (Rt == Re) ? Rt : cuddUniqueInter(dd,index,Rt,Re); if (R == NULL) { Cudd_RecursiveDeref(dd, Rt); Cudd_RecursiveDeref(dd, Re); return(NULL); } cuddDeref(Rt); cuddDeref(Re); /* Store the result in the cache. */ cuddCacheInsert(dd,DD_ADD_OUT_SUM_TAG,M,r,c,R); return(R); } /* end of cuddAddOuterSumRecur */
char* DumpDoth(DdManager *dd, DdNode *add, onum *orig_vars, int rovar, char ** lnames, FILE *fp, FILE *nfp, int *hmn) { // descend the add through the root_ovar's binary variables and recursively // write out the nodes for all sub-adds DdNode *temp, *branch, *newadd; char *nodename, *newnodename; char namestr[1024]; // make up a new name for this node // and write it to fp nodename = new char[256]; newnodename = new char[256]; sprintf(newnodename,"a%d",*hmn); (*hmn)++; // we're at a leaf if (Cudd_IsConstant(add)) { //write the node to nfp fprintf(fp,"{ rank = same; node [shape=box, style=filled, color=goldenrod];\"%s\" ",newnodename); if (lnames == NULL) { fprintf(fp," [label = \"%s \"];}\n",(*Cudd_V(add)).toString()); } else { strcpy(namestr,""); aconvert(namestr,lnames,(*Cudd_V(add)).get_min()); fprintf(fp,"[label = \"%s \"];}\n",namestr); } return newnodename; } else { // move down to the rovar which is at the root of this ADD while (Cudd_NodeReadIndex(vars[orig_vars[rovar].var1index].add_var) < Cudd_NodeReadIndex(add) && Cudd_NodeReadIndex(vars[orig_vars[rovar].var1index+orig_vars[rovar].nbvars-1].add_var) < Cudd_NodeReadIndex(add)) rovar++; // fprintf(fp,"{ rank = same; node [shape=ellipse, style=filled, color=cornflowerblue];\"%s\" [label=\"%s\"];}\n", newnodename,orig_vars[rovar].name); } onum root_ovar = orig_vars[rovar]; int next_rovar_index; onum next_rovar; if (rovar+1 < numorigvars) { next_rovar_index = orig_vars[rovar+1].var1index; } else { next_rovar_index = -1; } next_rovar_index *= 2; int nbv(root_ovar.nbvars),tmp; int nbvals = int(pow(2.0,nbv)); int *phase = new int[nbv]; DdNode **arrayofvars = new DdNode*[nbv]; DdNode *subadds[MAXVALS]; temp = add; Cudd_Ref(temp); int coval =0,i; // go over all the branches at this node. // we want to figure out the add rooted at each branch of the original // variable and then write the parent pointing to that branch. while (coval<root_ovar.nvals) { for (i=0; i<nbv; i++) phase[i] = 0; tmp = nbvals-coval-1; i=nbv-1; // get the branch in binary while (tmp > 0 && i >=0) { phase[i--] = tmp%2; tmp = tmp/2; } i=0; int shit; // descend the add to find that branch. However ,not all the variables will be present in the add in general. // therefore, we have to skip all the ones which are not there until we find one, and then skip // all the ones missing at the end. Do this by checking to see if the either // (a) the add is a constant node (then we've gone far enough) // (b) the index of the node is in the next original variable's domain (gone far enough) while (i < nbv && ( !Cudd_IsConstant(temp) && (next_rovar_index < 0 || Cudd_NodeReadIndex(temp) < next_rovar_index))) { if (Cudd_NodeReadIndex(temp) == 2*(orig_vars[rovar].var1index+i)+1) { if (phase[i]) branch = Cudd_Then(temp); else branch = Cudd_Else(temp); Cudd_Ref(branch); Cudd_RecursiveDeref(gbm,temp); temp = branch; } i++; } // now check if its the same as one we've done so far bool different(true); for (i=0; i<numbranches && different; i++) different = (temp != branches[i]); if (different) { // recursive call - writes this branch to nfp nodename = DumpDoth(dd,temp,orig_vars,rovar+1,lnames,fp,nfp,hmn); branches[numbranches] = temp; Cudd_Ref(branches[numbranches]); branchnodenames[numbranches] = nodename; numbranches++; // may need more space than expected so check for that // this would work better with a list if (numbranches >= numexpbranches) { // need more space // save old branches DdNode ** newbranches = new DdNode *[numbranches*2]; for (i=0; i<numbranches; i++) newbranches[i] = branches[i]; // delete old delete [] branches; // re-allocoate numexpbranches = 2*numbranches; branches = new DdNode *[numexpbranches]; for (i=0; i<numbranches; i++) branches[i] = newbranches[i]; delete [] newbranches; } } else { nodename = branchnodenames[i-1]; } //now write our current node pointing to this one fprintf(nfp,"\"%s\" -> \"%s\" [label = \"%s\"];\n",newnodename,nodename,root_ovar.valname[coval]); coval++; // start back at top Cudd_RecursiveDeref(gbm,temp); temp = add; Cudd_Ref(temp); } return newnodename; delete [] phase; }