static YAP_Bool equality(void) { YAP_Term arg1, arg2, arg3, out; int varIndex; int value; int i; variable v; DdNode *node, *tmp, *var; arg1 = YAP_ARG1; arg2 = YAP_ARG2; arg3 = YAP_ARG3; varIndex = YAP_IntOfTerm(arg1); value = YAP_IntOfTerm(arg2); v = vars_ex[ex][varIndex]; i = v.firstBoolVar; tmp = Cudd_ReadOne(mgr_ex[ex]); Cudd_Ref(tmp); node = NULL; for (i = v.firstBoolVar; i < v.firstBoolVar + value; i++) { var = Cudd_bddIthVar(mgr_ex[ex], i); node = Cudd_bddAnd(mgr_ex[ex], tmp, Cudd_Not(var)); Cudd_Ref(node); Cudd_RecursiveDeref(mgr_ex[ex], tmp); tmp = node; } if (!(value == v.nVal - 1)) { var = Cudd_bddIthVar(mgr_ex[ex], v.firstBoolVar + value); node = Cudd_bddAnd(mgr_ex[ex], tmp, var); Cudd_Ref(node); Cudd_RecursiveDeref(mgr_ex[ex], tmp); } out = YAP_MkIntTerm((YAP_Int)node); return (YAP_Unify(out, arg3)); }
/**Function************************************************************* Synopsis [Computes the transition relation of the network.] Description [Assumes that the global BDDs are computed.] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Abc_NtkTransitionRelation( DdManager * dd, Abc_Ntk_t * pNtk, int fVerbose ) { DdNode * bRel, * bTemp, * bProd, * bVar, * bInputs; Abc_Obj_t * pNode; int fReorder = 1; int i; // extand the BDD manager to represent NS variables assert( dd->size == Abc_NtkCiNum(pNtk) ); Cudd_bddIthVar( dd, Abc_NtkCiNum(pNtk) + Abc_NtkLatchNum(pNtk) - 1 ); // enable reordering if ( fReorder ) Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); else Cudd_AutodynDisable( dd ); // compute the transition relation bRel = b1; Cudd_Ref( bRel ); Abc_NtkForEachLatch( pNtk, pNode, i ) { bVar = Cudd_bddIthVar( dd, Abc_NtkCiNum(pNtk) + i ); // bProd = Cudd_bddXnor( dd, bVar, pNtk->vFuncsGlob->pArray[i] ); Cudd_Ref( bProd ); bProd = Cudd_bddXnor( dd, bVar, Abc_ObjGlobalBdd(Abc_ObjFanin0(pNode)) ); Cudd_Ref( bProd ); bRel = Cudd_bddAnd( dd, bTemp = bRel, bProd ); Cudd_Ref( bRel ); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bProd ); }
int equalityc(int varIndex, int value) { int i; variable v; DdNode * node, * tmp, *var ; v=vars[varIndex]; i=v.firstBoolVar; node=NULL; tmp=Cudd_ReadOne(mgr); Cudd_Ref(tmp); for (i=v.firstBoolVar; i<v.firstBoolVar+value; i++) { var=Cudd_bddIthVar(mgr,i); node=Cudd_bddAnd(mgr,tmp,Cudd_Not(var)); Cudd_Ref(node); Cudd_RecursiveDeref(mgr,tmp); tmp=node; } if (!(value==v.nVal-1)) { var=Cudd_bddIthVar(mgr,v.firstBoolVar+value); node=Cudd_bddAnd(mgr,tmp,var); Cudd_Ref(node); Cudd_RecursiveDeref(mgr,tmp); } return (int) node; }
/**Function************************************************************* Synopsis [Converts graph to BDD.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Dec_GraphDeriveBdd( DdManager * dd, Dec_Graph_t * pGraph ) { DdNode * bFunc, * bFunc0, * bFunc1; Dec_Node_t * pNode; int i; // sanity checks assert( Dec_GraphLeaveNum(pGraph) >= 0 ); assert( Dec_GraphLeaveNum(pGraph) <= pGraph->nSize ); // check for constant function if ( Dec_GraphIsConst(pGraph) ) return Cudd_NotCond( b1, Dec_GraphIsComplement(pGraph) ); // check for a literal if ( Dec_GraphIsVar(pGraph) ) return Cudd_NotCond( Cudd_bddIthVar(dd, Dec_GraphVarInt(pGraph)), Dec_GraphIsComplement(pGraph) ); // assign the elementary variables Dec_GraphForEachLeaf( pGraph, pNode, i ) pNode->pFunc = Cudd_bddIthVar( dd, i ); // compute the function for each internal node Dec_GraphForEachNode( pGraph, pNode, i ) { bFunc0 = Cudd_NotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); bFunc1 = Cudd_NotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); pNode->pFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( pNode->pFunc ); }
/* preserve the state of unaffected variables */ DdNode* bdd_same(DdManager* m, pos* postab, int var, int proc) { DdNode* ret = Cudd_ReadOne(m); DdNode* var1, *var2, *xnor, *tmp; /* XNOR gate simulates equality */ Cudd_Ref(ret); int i, j; for (i=0; i<postab->num_procs; i++) {/* iterate through all processes */ if (i == proc) continue; /* skip pc of current process */ for (j=0; j<postab->pc_size; j++) {/* iterate through all bits */ var1 = Cudd_bddIthVar(m, postab->pc[i][j]); var2 = Cudd_bddIthVar(m, postab->pc_[i][j]); xnor = Cudd_bddXnor(m, var1, var2); Cudd_Ref(xnor); tmp = Cudd_bddAnd(m, ret, xnor); Cudd_Ref(tmp); Cudd_RecursiveDeref(m, xnor); Cudd_RecursiveDeref(m, ret); ret = tmp; } } for (i=0; i<postab->num_vars; i++) { /* iterate through all globals */ if (i == var) continue; /* skip assignment variable */ var1 = Cudd_bddIthVar(m, i); var2 = Cudd_bddIthVar(m, i+postab->num_vars); xnor = Cudd_bddXnor(m, var1, var2); Cudd_Ref(xnor); tmp = Cudd_bddAnd(m, ret, xnor); Cudd_Ref(tmp); Cudd_RecursiveDeref(m, xnor); Cudd_RecursiveDeref(m, ret); ret = tmp; } return ret; }
BDD::BDD(int v, bool b) { if (b) { node = Cudd_bddIthVar(Cudd::dd,v); } else { node = Cudd_Not(Cudd_bddIthVar(Cudd::dd,v)); } assert(node != NULL); Cudd_Ref(node); }
ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Converts graph to BDD.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Dec_GraphDeriveBdd( DdManager * dd, Dec_Graph_t * pGraph ) { DdNode * bFunc, * bFunc0, * bFunc1; Dec_Node_t * pNode = NULL; // Suppress "might be used uninitialized" int i; // sanity checks assert( Dec_GraphLeaveNum(pGraph) >= 0 ); assert( Dec_GraphLeaveNum(pGraph) <= pGraph->nSize ); // check for constant function if ( Dec_GraphIsConst(pGraph) ) return Cudd_NotCond( b1, Dec_GraphIsComplement(pGraph) ); // check for a literal if ( Dec_GraphIsVar(pGraph) ) return Cudd_NotCond( Cudd_bddIthVar(dd, Dec_GraphVarInt(pGraph)), Dec_GraphIsComplement(pGraph) ); // assign the elementary variables Dec_GraphForEachLeaf( pGraph, pNode, i ) pNode->pFunc = Cudd_bddIthVar( dd, i ); // compute the function for each internal node Dec_GraphForEachNode( pGraph, pNode, i ) { bFunc0 = Cudd_NotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); bFunc1 = Cudd_NotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); pNode->pFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( (DdNode *)pNode->pFunc ); }
/* recursively convert an AST expression into a BDD */ DdNode* bdd_expr(DdManager* m, symbol** symtab, ast_node* expr) { int i; DdNode* ret, *tmp1, *tmp2; switch (expr->tag) { case _id_expr: /* simply return that variable's BDD */ if ((i = symtab_lookup(symtab, expr->name)) < 0) { printf("Error: variable '%s' not found in symbol table\n", expr->name); exit(1); } ret = Cudd_bddIthVar(m, symtab_lookup(symtab, expr->name)); break; case _lit_expr: /* return a BDD 1 or 0 */ ret = expr->val ? Cudd_ReadOne(m) : Cudd_ReadLogicZero(m); break; case _not_expr: /* return complement BDD */ tmp1 = bdd_expr(m, symtab, expr->children[EXPR1]); ret = Cudd_Not(tmp1); Cudd_Ref(ret); Cudd_RecursiveDeref(m, tmp1); break; case _and_expr: /* return logical AND */ tmp1 = bdd_expr(m, symtab, expr->children[EXPR1]); tmp2 = bdd_expr(m, symtab, expr->children[EXPR2]); ret = Cudd_bddAnd(m, tmp1, tmp2); Cudd_Ref(ret); Cudd_RecursiveDeref(m, tmp1); Cudd_RecursiveDeref(m, tmp2); break; case _or_expr: /* return logical OR */ tmp1 = bdd_expr(m, symtab, expr->children[EXPR1]); tmp2 = bdd_expr(m, symtab, expr->children[EXPR2]); ret = Cudd_bddOr(m, tmp1, tmp2); Cudd_Ref(ret); Cudd_RecursiveDeref(m, tmp1); Cudd_RecursiveDeref(m, tmp2); break; case _eq_expr: /* check for equality, return 1 or 0 */ tmp1 = bdd_expr(m, symtab, expr->children[EXPR1]); tmp2 = bdd_expr(m, symtab, expr->children[EXPR2]); if (Cudd_EquivDC(m, tmp1, tmp2, Cudd_ReadLogicZero(m))) ret = Cudd_ReadOne(m); else ret = Cudd_ReadLogicZero(m); Cudd_RecursiveDeref(m, tmp1); Cudd_RecursiveDeref(m, tmp2); break; case _impl_expr: /* return logical implication (!a|b) */ tmp1 = Cudd_Not(bdd_expr(m, symtab, expr->children[EXPR1])); tmp2 = bdd_expr(m, symtab, expr->children[EXPR2]); ret = Cudd_bddOr(m, tmp1, tmp2); Cudd_Ref(ret); Cudd_RecursiveDeref(m, tmp1); Cudd_RecursiveDeref(m, tmp2); break; default: printf("Error: invalid expression\n"); exit(1); } return ret; }
/**Function************************************************************* Synopsis [Derives the truth table for one cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Fpga_TruthsCutBdd( void * dd, Fpga_Cut_t * pCut ) { Fpga_NodeVec_t * vVisited; DdNode * bFunc; int i; assert( pCut->nLeaves > 1 ); // set the leaf variables for ( i = 0; i < pCut->nLeaves; i++ ) pCut->ppLeaves[i]->pCuts->uSign = (unsigned)Cudd_bddIthVar( dd, i ); // recursively compute the function vVisited = Fpga_NodeVecAlloc( 10 ); bFunc = Fpga_TruthsCutBdd_rec( dd, pCut, vVisited ); Cudd_Ref( bFunc ); // clean the intermediate BDDs for ( i = 0; i < pCut->nLeaves; i++ ) pCut->ppLeaves[i]->pCuts->uSign = 0; for ( i = 0; i < vVisited->nSize; i++ ) { pCut = (Fpga_Cut_t *)vVisited->pArray[i]; Cudd_RecursiveDeref( dd, (DdNode*)pCut->uSign ); pCut->uSign = 0; } // printf( "%d ", vVisited->nSize ); Fpga_NodeVecFree( vVisited ); Cudd_Deref( bFunc ); return bFunc; }
/** * @brief Basic test of Cudd_CountMinterm(). * @return 0 if successful; -1 otherwise. */ static int testCount(int verbosity) { DdManager *dd; DdNode *h; int i, ret; int const N = 2044; /* number of variables */ dd = Cudd_Init(N, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0); if (!dd) { if (verbosity) { printf("initialization failed\n"); } return -1; } /* Build a cube with N/2 variables. */ h = Cudd_ReadOne(dd); Cudd_Ref(h); for (i = 0; i < N; i += 2) { DdNode *var, *tmp; var = Cudd_bddIthVar(dd, N-i-1); tmp = Cudd_bddAnd(dd, h, var); if (!tmp) { Cudd_Quit(dd); return -1; } Cudd_Ref(tmp); Cudd_RecursiveDeref(dd, h); h = tmp; } if (verbosity) { printf("h (dbl) "); Cudd_PrintDebug(dd, h, N, 1); printf("h (apa) "); Cudd_PrintSummary(dd, h, N, 1); } Cudd_RecursiveDeref(dd, h); if (verbosity) { printf("one[%d] (dbl) ", N); Cudd_PrintDebug(dd, Cudd_ReadOne(dd), N, 1); printf("one[%d] (apa) ", N); Cudd_PrintSummary(dd, Cudd_ReadOne(dd), N, 1); ret = Cudd_CheckZeroRef(dd); printf("one[%d] (dbl) ", N+1); Cudd_PrintDebug(dd, Cudd_ReadOne(dd), N+1, 1); printf("one[%d] (apa) ", N+1); Cudd_PrintSummary(dd, Cudd_ReadOne(dd), N+1, 1); ret = Cudd_CheckZeroRef(dd); } if (verbosity && ret != 0) { printf("%d non-zero references\n", ret); } Cudd_Quit(dd); return 0; }
/**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; }
/**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Abc_MvReadCube( DdManager * dd, char * pLine, int nVars ) { DdNode * bCube, * bVar, * bTemp; int i; bCube = Cudd_ReadOne(dd); Cudd_Ref( bCube ); for ( i = 0; i < nVars; i++ ) { if ( pLine[i] == '-' ) continue; else if ( pLine[i] == '0' ) // 0 bVar = Cudd_Not( Cudd_bddIthVar(dd, 29-i) ); else if ( pLine[i] == '1' ) // 1 bVar = Cudd_bddIthVar(dd, 29-i); else assert(0); bCube = Cudd_bddAnd( dd, bTemp = bCube, bVar ); Cudd_Ref( bCube ); Cudd_RecursiveDeref( dd, bTemp ); } Cudd_Deref( bCube ); return bCube; }
/**Function************************************************************* Synopsis [Derive BDD of the characteristic function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Abc_ResBuildBdd( Abc_Ntk_t * pNtk, DdManager * dd ) { Vec_Ptr_t * vNodes, * vBdds, * vLocals; Abc_Obj_t * pObj, * pFanin; DdNode * bFunc, * bPart, * bTemp, * bVar; int i, k; assert( Abc_NtkIsSopLogic(pNtk) ); assert( Abc_NtkCoNum(pNtk) <= 3 ); vBdds = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) ); Abc_NtkForEachCi( pNtk, pObj, i ) Vec_PtrWriteEntry( vBdds, Abc_ObjId(pObj), Cudd_bddIthVar(dd, i) ); // create internal node BDDs vNodes = Abc_NtkDfs( pNtk, 0 ); vLocals = Vec_PtrAlloc( 6 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { if ( Abc_ObjFaninNum(pObj) == 0 ) { bFunc = Cudd_NotCond( Cudd_ReadOne(dd), Abc_SopIsConst0((char *)pObj->pData) ); Cudd_Ref( bFunc ); Vec_PtrWriteEntry( vBdds, Abc_ObjId(pObj), bFunc ); continue; } Vec_PtrClear( vLocals ); Abc_ObjForEachFanin( pObj, pFanin, k ) Vec_PtrPush( vLocals, Vec_PtrEntry(vBdds, Abc_ObjId(pFanin)) ); bFunc = Abc_ConvertSopToBdd( dd, (char *)pObj->pData, (DdNode **)Vec_PtrArray(vLocals) ); Cudd_Ref( bFunc ); Vec_PtrWriteEntry( vBdds, Abc_ObjId(pObj), bFunc ); } Vec_PtrFree( vLocals ); // create char function bFunc = Cudd_ReadOne( dd ); Cudd_Ref( bFunc ); Abc_NtkForEachCo( pNtk, pObj, i ) { bVar = Cudd_bddIthVar( dd, i + Abc_NtkCiNum(pNtk) ); bTemp = (DdNode *)Vec_PtrEntry( vBdds, Abc_ObjFaninId0(pObj) ); bPart = Cudd_bddXnor( dd, bTemp, bVar ); Cudd_Ref( bPart ); bFunc = Cudd_bddAnd( dd, bTemp = bFunc, bPart ); Cudd_Ref( bFunc ); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bPart ); }
/**Function************************************************************* Synopsis [Returns the array of constraint candidates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManComputeIndCase( Aig_Man_t * p, DdManager * dd, Vec_Int_t * vNodes ) { Vec_Ptr_t * vBdds; Aig_Obj_t * pObj; DdNode * bFunc; int i, Entry; vBdds = Vec_PtrStart( Aig_ManObjNumMax(p) ); bFunc = Cudd_ReadOne(dd); Cudd_Ref( bFunc ); Vec_PtrWriteEntry( vBdds, Aig_ObjId(Aig_ManConst1(p)), bFunc ); Saig_ManForEachPi( p, pObj, i ) { bFunc = Cudd_bddIthVar( dd, Aig_ManPiNum(p) + i ); Cudd_Ref( bFunc ); Vec_PtrWriteEntry( vBdds, Aig_ObjId(pObj), bFunc ); }
DdNode* compute_EX(DdManager* m, pos* postab, DdNode* R, DdNode* p) { DdNode* tmp; /* rename variables */ int perm[2*(postab->num_procs*postab->pc_size+postab->num_vars)]; int i, j, k; for (i=0; i<postab->num_vars; i++) { perm[i] = i+postab->num_vars; perm[i+postab->num_vars] = i; } for (j=0; j<postab->num_procs; j++) { for (k=0; k<postab->pc_size; k++) { perm[postab->num_vars+i] = postab->pc_[j][k]; perm[postab->num_vars+postab->num_procs*postab->pc_size+i++] = postab->pc[j][k]; } } p = Cudd_bddPermute(m, p, perm); /* construct cube of next state variables */ DdNode* cube = Cudd_ReadOne(m); for (i=0; i<postab->num_vars; i++) { tmp = Cudd_bddAnd(m, cube, Cudd_bddIthVar(m, postab->num_vars+i)); Cudd_Ref(tmp); Cudd_RecursiveDeref(m, cube); cube = tmp; } for (i=0; i<postab->num_procs*postab->pc_size; i++) { tmp = Cudd_bddAnd(m, cube, Cudd_bddIthVar(m, 2*postab->num_vars+postab->num_procs*postab->pc_size+i)); Cudd_Ref(tmp); Cudd_RecursiveDeref(m, cube); cube = tmp; } DdNode* EX_p = Cudd_bddAndAbstract(m, R, p, cube); Cudd_Ref(EX_p); Cudd_RecursiveDeref(m, p); Cudd_RecursiveDeref(m, cube); return EX_p; }
/**Function************************************************************* Synopsis [Create cube with singleton variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Llb_NonlinCreateCube1( Llb_Mgr_t * p, Llb_Prt_t * pPart ) { DdNode * bCube, * bTemp; Llb_Var_t * pVar; int i, TimeStop; TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; bCube = Cudd_ReadOne(p->dd); Cudd_Ref( bCube ); Llb_PartForEachVar( p, pPart, pVar, i ) { assert( Vec_IntSize(pVar->vParts) > 0 ); if ( Vec_IntSize(pVar->vParts) != 1 ) continue; assert( Vec_IntEntry(pVar->vParts, 0) == pPart->iPart ); bCube = Cudd_bddAnd( p->dd, bTemp = bCube, Cudd_bddIthVar(p->dd, pVar->iVar) ); Cudd_Ref( bCube ); Cudd_RecursiveDeref( p->dd, bTemp ); }
/* formula for assignment: pc ^ var' <=> expr ^ pc' ^ same(pc, var) */ DdNode* bdd_mk_assign(DdManager *m, pos* postab, cfg_node* host, int proc) { DdNode* tmp1 = Cudd_bddIthVar(m, symtab_lookup(postab->vars_, host->node->name)); DdNode* tmp2 = bdd_expr(m, postab->vars, host->node->children[EXPR]); DdNode* ret = Cudd_bddXnor(m, tmp1, tmp2); Cudd_Ref(ret); /* encode assignment with XNOR */ Cudd_RecursiveDeref(m, tmp2); ret = bdd_encode_pc(m, ret, postab->pc, postab->pc_size, proc, host->node->id); /* encode program counter */ tmp1 = bdd_same(m, postab, symtab_lookup(postab->vars, host->node->name), proc); /* encode unchanging variables */ tmp2 = ret; ret = Cudd_bddAnd(m, tmp1, tmp2); Cudd_Ref(ret); Cudd_RecursiveDeref(m, tmp1); Cudd_RecursiveDeref(m, tmp2); return ret; }
/** * @brief Basic BDD test. * @return 0 if successful; -1 otherwise. */ static int testBdd(int verbosity) { DdManager *dd; DdNode *f, *var, *tmp; int i, ret; dd = Cudd_Init(0, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0); if (!dd) { if (verbosity) { printf("initialization failed\n"); } return -1; } if (verbosity) { printf("Started CUDD version "); Cudd_PrintVersion(stdout); } f = Cudd_ReadOne(dd); Cudd_Ref(f); for (i = 3; i >= 0; i--) { var = Cudd_bddIthVar(dd, i); tmp = Cudd_bddAnd(dd, Cudd_Not(var), f); if (!tmp) { if (verbosity) { printf("computation failed\n"); } return -1; } Cudd_Ref(tmp); Cudd_RecursiveDeref(dd, f); f = tmp; } if (verbosity) { Cudd_bddPrintCover(dd, f, f); } Cudd_RecursiveDeref(dd, f); ret = Cudd_CheckZeroRef(dd); if (ret != 0 && verbosity) { printf("%d unexpected non-zero references\n", ret); } Cudd_Quit(dd); return 0; }
ref_t shadow_get_variable(shadow_mgr mgr, size_t index) { if (index >= mgr->nvars) { err(fatal, "Invalid variable index %lu", index); index = 0; } ref_t r = 0; DdNode *n = NULL; if (mgr->do_cudd) { n = Cudd_bddIthVar(mgr->bdd_manager, index); reference_dd(mgr, n); } if (do_ref(mgr)) { r = REF_VAR(index); if (!mgr->do_cudd) n = ref2dd(mgr, r); } else { r = dd2ref(n, IS_BDD); } add_ref(mgr, r, n); return r; }
static YAP_Bool add_var(void) { YAP_Term arg1, arg2, arg3, arg4, out, probTerm, probTerm_temp; variable *v; int i; DdNode *node; double p, p0; arg1 = YAP_ARG1; arg2 = YAP_ARG2; arg3 = YAP_ARG3; arg4 = YAP_ARG4; nVars_ex[ex] = nVars_ex[ex] + 1; vars_ex[ex] = (variable *)realloc(vars_ex[ex], nVars_ex[ex] * sizeof(variable)); v = &vars_ex[ex][nVars_ex[ex] - 1]; v->nVal = YAP_IntOfTerm(arg1); v->nRule = YAP_IntOfTerm(arg3); v->firstBoolVar = boolVars_ex[ex]; probs_ex[ex] = (double *)realloc( probs_ex[ex], (((boolVars_ex[ex] + v->nVal - 1) * sizeof(double)))); bVar2mVar_ex[ex] = (int *)realloc( bVar2mVar_ex[ex], ((boolVars_ex[ex] + v->nVal - 1) * sizeof(int))); probTerm = arg2; p0 = 1; for (i = 0; i < v->nVal - 1; i++) { node = Cudd_bddIthVar(mgr_ex[ex], boolVars_ex[ex] + i); p = YAP_FloatOfTerm(YAP_HeadOfTerm(probTerm)); bVar2mVar_ex[ex][boolVars_ex[ex] + i] = nVars_ex[ex] - 1; probs_ex[ex][boolVars_ex[ex] + i] = p / p0; probTerm_temp = YAP_TailOfTerm(probTerm); probTerm = probTerm_temp; p0 = p0 * (1 - p / p0); } boolVars_ex[ex] = boolVars_ex[ex] + v->nVal - 1; rules[v->nRule] = v->nVal; out = YAP_MkIntTerm((YAP_Int)nVars_ex[ex] - 1); return YAP_Unify(out, arg4); }
/* encode the program counter in an array of boolean variables */ DdNode* bdd_encode_pc(DdManager* m, DdNode* node, int** pc_array, int pc_size, int proc, int pc) { int i; DdNode* tmp, *var; DdNode* ret = Cudd_ReadOne(m); Cudd_Ref(ret); for (i=0; i<pc_size; i++) { /* iterate for each bit in pc_size */ var = Cudd_bddIthVar(m, pc_array[proc][i]); if (pc % 2) /* encode true bit */ tmp = Cudd_bddAnd(m, var, ret); else /* encode false bit */ tmp = Cudd_bddAnd(m, Cudd_Not(var), ret); Cudd_Ref(tmp); Cudd_RecursiveDeref(m, ret); /* release the old bdd each time a new */ ret = tmp; /* one is made */ pc /= 2; } tmp = Cudd_bddAnd(m, ret, node); /* add encoding to existing edge */ Cudd_Ref(tmp); Cudd_RecursiveDeref(m, ret); Cudd_RecursiveDeref(m, node); return tmp; /* return updated edge */ }
/**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_MvDecompose( Mv_Man_t * p ) { DdNode * bCofs[16], * bVarCube1, * bVarCube2, * bVarCube, * bCube, * bVar0, * bVar1;//, * bRes; int k, i1, i2, v1, v2;//, c1, c2, Counter; bVar0 = Cudd_bddIthVar(p->dd, 30); bVar1 = Cudd_bddIthVar(p->dd, 31); bCube = Cudd_bddAnd( p->dd, bVar0, bVar1 ); Cudd_Ref( bCube ); for ( k = 0; k < p->nFuncs; k++ ) { printf( "FUNCTION %d\n", k ); for ( i1 = 0; i1 < p->nFuncs; i1++ ) for ( i2 = i1+1; i2 < p->nFuncs; i2++ ) { Vec_Ptr_t * vCofs; for ( v1 = 0; v1 < 4; v1++ ) { bVar0 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 29-2*i1 ), ((v1 & 1) == 0) ); bVar1 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 29-2*i1-1), ((v1 & 2) == 0) ); bVarCube1 = Cudd_bddAnd( p->dd, bVar0, bVar1 ); Cudd_Ref( bVarCube1 ); for ( v2 = 0; v2 < 4; v2++ ) { bVar0 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 29-2*i2 ), ((v2 & 1) == 0) ); bVar1 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 29-2*i2-1), ((v2 & 2) == 0) ); bVarCube2 = Cudd_bddAnd( p->dd, bVar0, bVar1 ); Cudd_Ref( bVarCube2 ); bVarCube = Cudd_bddAnd( p->dd, bVarCube1, bVarCube2 ); Cudd_Ref( bVarCube ); bCofs[v1 * 4 + v2] = Cudd_Cofactor( p->dd, p->bFuncs[k], bVarCube ); Cudd_Ref( bCofs[v1 * 4 + v2] ); Cudd_RecursiveDeref( p->dd, bVarCube ); Cudd_RecursiveDeref( p->dd, bVarCube2 ); } Cudd_RecursiveDeref( p->dd, bVarCube1 ); } /* // check the compatibility of cofactors Counter = 0; for ( c1 = 0; c1 < 16; c1++ ) { for ( c2 = 0; c2 <= c1; c2++ ) printf( " " ); for ( c2 = c1+1; c2 < 16; c2++ ) { bRes = Cudd_bddAndAbstract( p->dd, bCofs[c1], bCofs[c2], bCube ); Cudd_Ref( bRes ); if ( bRes == Cudd_ReadOne(p->dd) ) { printf( "+" ); Counter++; } else { printf( " " ); } Cudd_RecursiveDeref( p->dd, bRes ); } printf( "\n" ); } */ vCofs = Vec_PtrAlloc( 16 ); for ( v1 = 0; v1 < 4; v1++ ) for ( v2 = 0; v2 < 4; v2++ ) Vec_PtrPushUnique( vCofs, bCofs[v1 * 4 + v2] ); printf( "%d ", Vec_PtrSize(vCofs) ); Vec_PtrFree( vCofs ); // free the cofactors for ( v1 = 0; v1 < 4; v1++ ) for ( v2 = 0; v2 < 4; v2++ ) Cudd_RecursiveDeref( p->dd, bCofs[v1 * 4 + v2] ); printf( "\n" ); // printf( "%2d, %2d : %3d\n", i1, i2, Counter ); } } Cudd_RecursiveDeref( p->dd, bCube ); }
/**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_MvRead( Mv_Man_t * p ) { FILE * pFile; char Buffer[1000], * pLine; DdNode * bCube, * bTemp, * bProd, * bVar0, * bVar1, * bCubeSum; int i, v; // start the cube bCubeSum = Cudd_ReadLogicZero(p->dd); Cudd_Ref( bCubeSum ); // start the values for ( i = 0; i < 15; i++ ) for ( v = 0; v < 4; v++ ) { p->bValues[i][v] = Cudd_ReadLogicZero(p->dd); Cudd_Ref( p->bValues[i][v] ); p->bValueDcs[i][v] = Cudd_ReadLogicZero(p->dd); Cudd_Ref( p->bValueDcs[i][v] ); } // read the file pFile = fopen( "input.pla", "r" ); while ( fgets( Buffer, 1000, pFile ) ) { if ( Buffer[0] == '#' ) continue; if ( Buffer[0] == '.' ) { if ( Buffer[1] == 'e' ) break; continue; } // get the cube bCube = Abc_MvReadCube( p->dd, Buffer, 18 ); Cudd_Ref( bCube ); // add it to the values of the output functions pLine = Buffer + 19; for ( i = 0; i < 15; i++ ) { if ( pLine[2*i] == '-' && pLine[2*i+1] == '-' ) { for ( v = 0; v < 4; v++ ) { p->bValueDcs[i][v] = Cudd_bddOr( p->dd, bTemp = p->bValueDcs[i][v], bCube ); Cudd_Ref( p->bValueDcs[i][v] ); Cudd_RecursiveDeref( p->dd, bTemp ); } continue; } else if ( pLine[2*i] == '0' && pLine[2*i+1] == '0' ) // 0 v = 0; else if ( pLine[2*i] == '1' && pLine[2*i+1] == '0' ) // 1 v = 1; else if ( pLine[2*i] == '0' && pLine[2*i+1] == '1' ) // 2 v = 2; else if ( pLine[2*i] == '1' && pLine[2*i+1] == '1' ) // 3 v = 3; else assert( 0 ); // add the value p->bValues[i][v] = Cudd_bddOr( p->dd, bTemp = p->bValues[i][v], bCube ); Cudd_Ref( p->bValues[i][v] ); Cudd_RecursiveDeref( p->dd, bTemp ); } // add the cube bCubeSum = Cudd_bddOr( p->dd, bTemp = bCubeSum, bCube ); Cudd_Ref( bCubeSum ); Cudd_RecursiveDeref( p->dd, bTemp ); Cudd_RecursiveDeref( p->dd, bCube ); } // add the complement of the domain to all values for ( i = 0; i < 15; i++ ) for ( v = 0; v < 4; v++ ) { if ( p->bValues[i][v] == Cudd_Not(Cudd_ReadOne(p->dd)) ) continue; p->bValues[i][v] = Cudd_bddOr( p->dd, bTemp = p->bValues[i][v], p->bValueDcs[i][v] ); Cudd_Ref( p->bValues[i][v] ); Cudd_RecursiveDeref( p->dd, bTemp ); p->bValues[i][v] = Cudd_bddOr( p->dd, bTemp = p->bValues[i][v], Cudd_Not(bCubeSum) ); Cudd_Ref( p->bValues[i][v] ); Cudd_RecursiveDeref( p->dd, bTemp ); } printf( "Domain = %5.2f %%.\n", 100.0*Cudd_CountMinterm(p->dd, bCubeSum, 32)/Cudd_CountMinterm(p->dd, Cudd_ReadOne(p->dd), 32) ); Cudd_RecursiveDeref( p->dd, bCubeSum ); // create each output function for ( i = 0; i < 15; i++ ) { p->bFuncs[i] = Cudd_ReadLogicZero(p->dd); Cudd_Ref( p->bFuncs[i] ); for ( v = 0; v < 4; v++ ) { bVar0 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 30), ((v & 1) == 0) ); bVar1 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 31), ((v & 2) == 0) ); bCube = Cudd_bddAnd( p->dd, bVar0, bVar1 ); Cudd_Ref( bCube ); bProd = Cudd_bddAnd( p->dd, p->bValues[i][v], bCube ); Cudd_Ref( bProd ); Cudd_RecursiveDeref( p->dd, bCube ); // add the value p->bFuncs[i] = Cudd_bddOr( p->dd, bTemp = p->bFuncs[i], bProd ); Cudd_Ref( p->bFuncs[i] ); Cudd_RecursiveDeref( p->dd, bTemp ); Cudd_RecursiveDeref( p->dd, bProd ); } } }
/** * @brief Basic test of long double and EPD minterm computation. * @return 0 if successful; -1 otherwise. */ static int testLdbl(int verbosity) { DdManager *dd; DdNode *f, *g; int i, ret; int const N = 12; /* half the number of variables */ long double cnt; dd = Cudd_Init(2*N, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0); if (!dd) { if (verbosity) { printf("initialization failed\n"); } return -1; } f = g = Cudd_ReadOne(dd); Cudd_Ref(f); Cudd_Ref(g); for (i = 0; i < N; i++) { DdNode *var1, *var2, *clause, *tmp; var1 = Cudd_bddIthVar(dd, i); var2 = Cudd_bddIthVar(dd, i+N); clause = Cudd_bddOr(dd, var1, var2); if (!clause) { Cudd_Quit(dd); return -1; } Cudd_Ref(clause); tmp = Cudd_bddAnd(dd, f, clause); if (!tmp) { Cudd_Quit(dd); return -1; } Cudd_Ref(tmp); Cudd_RecursiveDeref(dd, clause); Cudd_RecursiveDeref(dd, f); f = tmp; clause = Cudd_bddOr(dd, Cudd_Not(var1), Cudd_Not(var2)); if (!clause) { Cudd_Quit(dd); return -1; } Cudd_Ref(clause); tmp = Cudd_bddAnd(dd, g, clause); if (!tmp) { Cudd_Quit(dd); return -1; } Cudd_Ref(tmp); Cudd_RecursiveDeref(dd, clause); Cudd_RecursiveDeref(dd, g); g = tmp; } if (verbosity) { printf("f"); Cudd_PrintSummary(dd, f, 2*N, 0); } cnt = Cudd_LdblCountMinterm(dd, f, 2*N); if (verbosity) { printf("f has %Lg minterms\n", cnt); } if (verbosity) { printf("EPD count for f = "); ret = Cudd_EpdPrintMinterm(dd, f, 2*N); printf("\n"); if (!ret) { printf("problem with EPD\n"); } } Cudd_RecursiveDeref(dd, f); if (verbosity) { printf("g"); Cudd_PrintSummary(dd, g, 2*N, 0); } cnt = Cudd_LdblCountMinterm(dd, g, 2*N); if (verbosity) { printf("g has %Lg minterms\n", cnt); } if (verbosity) { printf("EPD count for g = "); ret = Cudd_EpdPrintMinterm(dd, g, 2*N); printf("\n"); if (!ret) { printf("problem with EPD\n"); } } Cudd_RecursiveDeref(dd, g); ret = Cudd_CheckZeroRef(dd); if (verbosity && ret != 0) { printf("%d non-zero references\n", ret); } Cudd_Quit(dd); return 0; }
/** * @brief Basic test of timeout handler. * * @details Sets a short timeout and then tries to build a function * with a large BDD. Strives to avoid leaking nodes. * * @return 0 if successful; -1 otherwise. */ static int testTimeout(int verbosity) { DdManager *dd; /* Declare these "volatile" to prevent clobbering by longjmp. */ DdNode * volatile f; DdNode * volatile clause = NULL; DdNode * var1, * var2; int i, ret, count; int const N = 20; /* half the number of variables in f */ unsigned long timeout = 100UL; /* in milliseconds */ jmp_buf timeoutEnv; dd = Cudd_Init(0, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0); if (!dd) { if (verbosity) { printf("initialization failed\n"); } return -1; } /* Set up timeout handling. */ if (setjmp(timeoutEnv) > 0) { if (verbosity) { printf("caught timeout\n"); } /* The nodes of clause may be leaked if the timeout was * detected while conjoining the clause to f. We set * clause to NULL when it's not in use to be able to * detect this case. */ if (clause) Cudd_RecursiveDeref(dd, clause); goto finally; } (void) Cudd_RegisterTimeoutHandler(dd, timeoutHandler, (void *) &timeoutEnv); (void) Cudd_SetTimeLimit(dd, timeout); /* Try to build function. This is expected to run out of time. */ f = Cudd_ReadOne(dd); Cudd_Ref(f); for (i = 0; i < N; i++) { DdNode * tmp; var1 = Cudd_bddIthVar(dd, i); if (!var1) { if (verbosity) { printf("computation failed\n"); return -1; } } var2 = Cudd_bddIthVar(dd, i+N); if (!var2) { if (verbosity) { printf("computation failed\n"); return -1; } } clause = Cudd_bddOr(dd, var1, var2); if (!clause) { if (verbosity) { printf("computation failed\n"); } return -1; } Cudd_Ref(clause); tmp = Cudd_bddAnd(dd, f, clause); if (!tmp) { if (verbosity) { printf("computation failed\n"); } return -1; } Cudd_Ref(tmp); Cudd_RecursiveDeref(dd, clause); clause = NULL; Cudd_RecursiveDeref(dd, f); f = tmp; } if (verbosity > 1) { Cudd_bddPrintCover(dd, f, f); } finally: if (verbosity) { printf("so far"); Cudd_PrintSummary(dd, f, 2*N, 0); } count = 0; for (i = 0; i < N-1; i += 2) { var1 = Cudd_bddIthVar(dd, i); if (!var1) { printf("computation failed\n"); return -1; } var2 = Cudd_bddIthVar(dd, i+1); if (!var2) { printf("computation failed\n"); return -1; } clause = Cudd_bddOr(dd, var1, var2); if (!clause) { printf("computation failed\n"); return -1; } Cudd_Ref(clause); if (Cudd_bddLeq(dd, f, clause)) { count++; } Cudd_RecursiveDeref(dd, clause); } if (verbosity) { printf("f implies %d clauses\n", count); } Cudd_RecursiveDeref(dd, f); ret = Cudd_CheckZeroRef(dd); if (verbosity) { Cudd_PrintInfo(dd, stdout); if (ret != 0) { printf("%d non-zero references\n", ret); } } Cudd_Quit(dd); return 0; }
variables createVars(YAP_Term t,DdManager * mgr, int create_dot, char inames[1000][20]) /* adds the boolean variables to the BDD and returns the array vars containing them returns also the names of the variables to be used to save the ADD in dot format */ { YAP_Term varTerm,probTerm; int varIndex,nVal,i,b; variable v; char numberVar[10],numberBit[10]; double p; variables vars; vars.varar=NULL; vars.bVar2mVar=NULL; b=0; vars.nVar=0; varIndex=0; while(YAP_IsPairTerm(t)) { varTerm=YAP_HeadOfTerm(t); varIndex=YAP_IntOfTerm(YAP_HeadOfTerm(varTerm)); varTerm=YAP_TailOfTerm(varTerm); nVal=YAP_IntOfTerm(YAP_HeadOfTerm(varTerm)); varTerm=YAP_TailOfTerm(varTerm); probTerm=YAP_HeadOfTerm(varTerm); v.nVal=nVal; v.nBit=(int)ceil(log(nVal)/log(2)); v.probabilities=(double *) malloc(nVal* sizeof(double)); v.booleanVars=(DdNode * *) malloc(v.nBit* sizeof(DdNode *)); for (i=0; i<nVal; i++) { p=YAP_FloatOfTerm(YAP_HeadOfTerm(probTerm)); v.probabilities[i]=p; probTerm=YAP_TailOfTerm(probTerm); } for (i=0; i<v.nBit; i++) { if (create_dot) { strcpy(inames[b+i],"X"); sprintf(numberVar,"%d",varIndex); strcat(inames[b+i],numberVar); strcat(inames[b+i],"_"); sprintf(numberBit,"%d",i); strcat(inames[b+i],numberBit); } v.booleanVars[i]=Cudd_bddIthVar(mgr,b+i); vars.bVar2mVar=(int *)realloc(vars.bVar2mVar,(b+i+1)*sizeof(int)); vars.bVar2mVar[b+i]=varIndex; } Cudd_MakeTreeNode(mgr,b,v.nBit,MTR_FIXED); b=b+v.nBit; vars.varar=(variable *) realloc(vars.varar,(varIndex+1)* sizeof(variable)); vars.varar[varIndex]=v; t=YAP_TailOfTerm(t); } vars.nVar=varIndex+1; vars.nBVar=b; return vars; }
static DdNode *tree2BDD(DdManager *mgr, ACCExpr *expr, VarMap &varMap) { std::string op = expr->value; DdNode *ret = nullptr; if (op == "&&") op = "&"; else if (op == "||") op = "|"; if (checkInteger(expr, "1")) ret = Cudd_ReadOne(mgr); else if (checkInteger(expr, "0")) ret = Cudd_ReadLogicZero(mgr); else if (op == "!") return Cudd_Not(tree2BDD(mgr, expr->operands.front(), varMap)); // Not passes through ref count else if (op != "&" && op != "|" && op != "^") { if ((op == "!=" || op == "==")) { ACCExpr *lhs = getRHS(expr, 0); if (boolPossible(lhs) && boolPossible(getRHS(expr,1))) goto next; // we can analyze relops on booleans if (trace_bool) printf("[%s:%d] boolnot %d %d = %s\n", __FUNCTION__, __LINE__, boolPossible(getRHS(expr,0)), boolPossible(getRHS(expr,1)), tree2str(expr).c_str()); if (isIdChar(lhs->value[0])) { if (trace_bool) printf("[%s:%d] name %s type %s\n", __FUNCTION__, __LINE__, lhs->value.c_str(), refList[lhs->value].type.c_str()); } } if (op == "!=") // normalize comparison strings expr->value = "=="; std::string name = "( " + tree2str(expr) + " )"; if (!varMap[name]) { varMap[name] = new MapItem; varMap[name]->index = varMap.size(); varMap[name]->node = Cudd_bddIthVar(mgr, varMap[name]->index); } ret = varMap[name]->node; if (op == "!=") { // normalize comparison strings expr->value = op; // restore ret = Cudd_Not(ret); } } if (ret) { Cudd_Ref(ret); return ret; } next:; for (auto item: expr->operands) { DdNode *operand = tree2BDD(mgr, item, varMap), *next; if (!ret) ret = operand; else { if (op == "&") next = Cudd_bddAnd(mgr, ret, operand); else if (op == "|") next = Cudd_bddOr(mgr, ret, operand); else if (op == "^" || op == "!=") next = Cudd_bddXor(mgr, ret, operand); else if (op == "==") next = Cudd_bddXnor(mgr, ret, operand); else { printf("[%s:%d] unknown operator\n", __FUNCTION__, __LINE__); exit(-1); } Cudd_Ref(next); Cudd_RecursiveDeref(mgr, operand); Cudd_RecursiveDeref(mgr, ret); ret = next; } } return ret; }
// Returns the variable v. if b is 0 it will be negated DdNode* getVar(DdManager *manager, int v, int b) { return b ? Cudd_bddIthVar(manager,v) : Cudd_Not(Cudd_bddIthVar(manager,v)); }
DdNode *compute_winning_set_BDD( DdManager *manager, DdNode *etrans, DdNode *strans, DdNode **egoals, DdNode **sgoals, unsigned char verbose ) { DdNode *X = NULL, *X_prev = NULL; DdNode *Y = NULL, *Y_exmod = NULL, *Y_prev = NULL; DdNode **Z = NULL, **Z_prev = NULL; bool Z_changed; /* Use to detect occurrence of fixpoint for all Z_i */ /* Fixpoint iteration counters */ int num_it_Z, num_it_Y, num_it_X; DdNode *tmp, *tmp2; int i, j; /* Generic counters */ DdNode **vars, **pvars; int num_env, num_sys; int *cube; /* length will be twice total number of variables (to account for both variables and their primes). */ num_env = tree_size( spc.evar_list ); num_sys = tree_size( spc.svar_list ); /* Allocate cube array, used later for quantifying over variables. */ cube = (int *)malloc( sizeof(int)*2*(num_env+num_sys) ); if (cube == NULL) { perror( __FILE__ ", malloc" ); exit(-1); } /* Define a map in the manager to easily swap variables with their primed selves. */ vars = malloc( (num_env+num_sys)*sizeof(DdNode *) ); pvars = malloc( (num_env+num_sys)*sizeof(DdNode *) ); for (i = 0; i < num_env+num_sys; i++) { *(vars+i) = Cudd_bddIthVar( manager, i ); *(pvars+i) = Cudd_bddIthVar( manager, i+num_env+num_sys ); } if (!Cudd_SetVarMap( manager, vars, pvars, num_env+num_sys )) { fprintf( stderr, "Error: failed to define variable map in CUDD manager.\n" ); free( cube ); return NULL; } free( vars ); free( pvars ); if (spc.num_sgoals > 0) { Z = malloc( spc.num_sgoals*sizeof(DdNode *) ); Z_prev = malloc( spc.num_sgoals*sizeof(DdNode *) ); for (i = 0; i < spc.num_sgoals; i++) { *(Z+i) = NULL; *(Z_prev+i) = NULL; } } /* Initialize */ for (i = 0; i < spc.num_sgoals; i++) { *(Z+i) = Cudd_ReadOne( manager ); Cudd_Ref( *(Z+i) ); } num_it_Z = 0; do { num_it_Z++; if (verbose > 1) { logprint( "Z iteration %d", num_it_Z ); logprint( "Cudd_ReadMemoryInUse (bytes): %d", Cudd_ReadMemoryInUse( manager ) ); } for (i = 0; i < spc.num_sgoals; i++) { if (*(Z_prev+i) != NULL) Cudd_RecursiveDeref( manager, *(Z_prev+i) ); *(Z_prev+i) = *(Z+i); } for (i = 0; i < spc.num_sgoals; i++) { if (i == spc.num_sgoals-1) { *(Z+i) = compute_existsmodal( manager, *Z_prev, etrans, strans, num_env, num_sys, cube ); } else { *(Z+i) = compute_existsmodal( manager, *(Z_prev+i+1), etrans, strans, num_env, num_sys, cube ); } if (*(Z+i) == NULL) { /* fatal error */ return NULL; } /* (Re)initialize Y */ if (Y != NULL) Cudd_RecursiveDeref( manager, Y ); Y = Cudd_Not( Cudd_ReadOne( manager ) ); Cudd_Ref( Y ); num_it_Y = 0; do { num_it_Y++; if (verbose > 1) { logprint( "\tY iteration %d", num_it_Y ); logprint( "\tCudd_ReadMemoryInUse (bytes): %d", Cudd_ReadMemoryInUse( manager ) ); } if (Y_prev != NULL) Cudd_RecursiveDeref( manager, Y_prev ); Y_prev = Y; if (Y_exmod != NULL) Cudd_RecursiveDeref( manager, Y_exmod ); Y_exmod = compute_existsmodal( manager, Y_prev, etrans, strans, num_env, num_sys, cube ); if (Y_exmod == NULL) { /* fatal error */ return NULL; } Y = Cudd_Not( Cudd_ReadOne( manager ) ); Cudd_Ref( Y ); for (j = 0; j < spc.num_egoals; j++) { /* (Re)initialize X */ if (X != NULL) Cudd_RecursiveDeref( manager, X ); X = Cudd_ReadOne( manager ); Cudd_Ref( X ); /* Greatest fixpoint for X, for this env goal */ num_it_X = 0; do { num_it_X++; if (verbose > 1) { logprint( "\t\tX iteration %d", num_it_X ); logprint( "\t\tCudd_ReadMemoryInUse (bytes): %d", Cudd_ReadMemoryInUse( manager ) ); } if (X_prev != NULL) Cudd_RecursiveDeref( manager, X_prev ); X_prev = X; X = compute_existsmodal( manager, X_prev, etrans, strans, num_env, num_sys, cube ); if (X == NULL) { /* fatal error */ return NULL; } tmp = Cudd_bddAnd( manager, *(sgoals+i), *(Z+i) ); Cudd_Ref( tmp ); tmp2 = Cudd_bddOr( manager, tmp, Y_exmod ); Cudd_Ref( tmp2 ); Cudd_RecursiveDeref( manager, tmp ); tmp = Cudd_bddAnd( manager, X, Cudd_Not( *(egoals+j) ) ); Cudd_Ref( tmp ); Cudd_RecursiveDeref( manager, X ); X = Cudd_bddOr( manager, tmp2, tmp ); Cudd_Ref( X ); Cudd_RecursiveDeref( manager, tmp ); Cudd_RecursiveDeref( manager, tmp2 ); tmp = X; X = Cudd_bddAnd( manager, X, X_prev ); Cudd_Ref( X ); Cudd_RecursiveDeref( manager, tmp ); } while (!Cudd_bddLeq( manager, X, X_prev ) || !Cudd_bddLeq( manager, X_prev, X )); tmp = Y; Y = Cudd_bddOr( manager, Y, X ); Cudd_Ref( Y ); Cudd_RecursiveDeref( manager, tmp ); Cudd_RecursiveDeref( manager, X ); X = NULL; Cudd_RecursiveDeref( manager, X_prev ); X_prev = NULL; } tmp2 = Y; Y = Cudd_bddOr( manager, Y, Y_prev ); Cudd_Ref( Y ); Cudd_RecursiveDeref( manager, tmp2 ); } while (!Cudd_bddLeq( manager, Y, Y_prev ) || !Cudd_bddLeq( manager, Y_prev, Y )); Cudd_RecursiveDeref( manager, *(Z+i) ); *(Z+i) = Cudd_bddAnd( manager, Y, *(Z_prev+i) ); Cudd_Ref( *(Z+i) ); Cudd_RecursiveDeref( manager, Y ); Y = NULL; Cudd_RecursiveDeref( manager, Y_prev ); Y_prev = NULL; Cudd_RecursiveDeref( manager, Y_exmod ); Y_exmod = NULL; } Z_changed = False; for (i = 0; i < spc.num_sgoals; i++) { if (!Cudd_bddLeq( manager, *(Z+i), *(Z_prev+i) ) || !Cudd_bddLeq( manager, *(Z_prev+i), *(Z+i) )) { Z_changed = True; break; } } } while (Z_changed); /* Pre-exit clean-up */ tmp = *Z; Cudd_RecursiveDeref( manager, *Z_prev ); for (i = 1; i < spc.num_sgoals; i++) { Cudd_RecursiveDeref( manager, *(Z+i) ); Cudd_RecursiveDeref( manager, *(Z_prev+i) ); } free( Z ); free( Z_prev ); free( cube ); return tmp; }