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; } } }
int indexMvar(DdNode *node) { int index, mVarIndex; index = Cudd_NodeReadIndex(node); mVarIndex = bVar2mVar_ex[ex][index]; return mVarIndex; }
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; }
void add_node(tablerow *tab, DdNode *node, double value) { int index = Cudd_NodeReadIndex(node); tab[index].row = (rowel *)realloc(tab[index].row, (tab[index].cnt + 1) * sizeof(rowel)); tab[index].row[tab[index].cnt].key = node; tab[index].row[tab[index].cnt].value = value; tab[index].cnt += 1; }
double *get_value(tablerow *tab, DdNode *node) { int i; int index = Cudd_NodeReadIndex(node); for (i = 0; i < tab[index].cnt; i++) { if (tab[index].row[i].key == node) { return &tab[index].row[i].value; } } return NULL; }
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; } } }
/**Function************************************************************* Synopsis [Constructs the network isomorphic to the given BDD.] Description [Assumes that the BDD depends on the variables whose indexes correspond to the names in the array (pNamesPi). Otherwise, returns NULL. The resulting network comes with one node, whose functionality is equal to the given BDD. To decompose this BDD into the network of multiplexers use Abc_NtkBddToMuxes(). To decompose this BDD into an And-Inverter Graph, use Abc_NtkStrash().] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDeriveFromBdd( void * dd0, void * bFunc, char * pNamePo, Vec_Ptr_t * vNamesPi ) { DdManager * dd = (DdManager *)dd0; Abc_Ntk_t * pNtk; Vec_Ptr_t * vNamesPiFake = NULL; Abc_Obj_t * pNode, * pNodePi, * pNodePo; DdNode * bSupp, * bTemp; char * pName; int i; // supply fake names if real names are not given if ( pNamePo == NULL ) pNamePo = "F"; if ( vNamesPi == NULL ) { vNamesPiFake = Abc_NodeGetFakeNames( dd->size ); vNamesPi = vNamesPiFake; } // make sure BDD depends on the variables whose index // does not exceed the size of the array with PI names bSupp = Cudd_Support( dd, (DdNode *)bFunc ); Cudd_Ref( bSupp ); for ( bTemp = bSupp; bTemp != Cudd_ReadOne(dd); bTemp = cuddT(bTemp) ) if ( (int)Cudd_NodeReadIndex(bTemp) >= Vec_PtrSize(vNamesPi) ) break; Cudd_RecursiveDeref( dd, bSupp ); if ( bTemp != Cudd_ReadOne(dd) ) return NULL; // start the network pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_BDD, 1 ); pNtk->pName = Extra_UtilStrsav(pNamePo); // make sure the new manager has enough inputs Cudd_bddIthVar( (DdManager *)pNtk->pManFunc, Vec_PtrSize(vNamesPi) ); // add the PIs corresponding to the names Vec_PtrForEachEntry( char *, vNamesPi, pName, i ) Abc_ObjAssignName( Abc_NtkCreatePi(pNtk), pName, NULL ); // create the node pNode = Abc_NtkCreateNode( pNtk ); pNode->pData = (DdNode *)Cudd_bddTransfer( dd, (DdManager *)pNtk->pManFunc, (DdNode *)bFunc ); Cudd_Ref((DdNode *)pNode->pData); Abc_NtkForEachPi( pNtk, pNodePi, i ) Abc_ObjAddFanin( pNode, pNodePi ); // create the only PO pNodePo = Abc_NtkCreatePo( pNtk ); Abc_ObjAddFanin( pNodePo, pNode ); Abc_ObjAssignName( pNodePo, pNamePo, NULL ); // make the network minimum base Abc_NtkMinimumBase( pNtk ); if ( vNamesPiFake ) Abc_NodeFreeNames( vNamesPiFake ); if ( !Abc_NtkCheck( pNtk ) ) fprintf( stdout, "Abc_NtkDeriveFromBdd(): Network check has failed.\n" ); return pNtk; }
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; }
void add_or_replace_node(tablerow *tab, DdNode *node, double value) { int i; int index = Cudd_NodeReadIndex(node); for (i = 0; i < tab[index].cnt; i++) { if (tab[index].row[i].key == node) { tab[index].row[i].value = value; return; } } tab[index].row = (rowel *)realloc(tab[index].row, (tab[index].cnt + 1) * sizeof(rowel)); tab[index].row[tab[index].cnt].key = node; tab[index].row[tab[index].cnt].value = value; tab[index].cnt += 1; }
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; } } }
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; } } }
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; }