/* 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; }
int orc(int nodea, int nodeb) { DdNode * node1,*node2,*nodeout; node1=(DdNode *)nodea; node2=(DdNode *)nodeb; nodeout=Cudd_bddOr(mgr,node1,node2); Cudd_Ref(nodeout); return (int)nodeout; }
DdNode* compute_EF(DdManager* m, pos* postab, DdNode* R, DdNode* p) { DdNode* last = Cudd_ReadOne(m); DdNode* current = p; while (!Cudd_EquivDC(m, last, current, Cudd_ReadLogicZero(m))) { // printf("iterating\n"); last = Cudd_bddAnd(m, current, Cudd_ReadOne(m)); current = Cudd_bddOr(m, p, compute_EX(m, postab, R, current)); } return current; }
static YAP_Bool or (void) { YAP_Term arg1, arg2, arg3, out; DdNode *node1, *node2, *nodeout; arg1 = YAP_ARG1; arg2 = YAP_ARG2; arg3 = YAP_ARG3; node1 = (DdNode *)YAP_IntOfTerm(arg1); node2 = (DdNode *)YAP_IntOfTerm(arg2); nodeout = Cudd_bddOr(mgr_ex[ex], node1, node2); Cudd_Ref(nodeout); out = YAP_MkIntTerm((YAP_Int)nodeout); return (YAP_Unify(out, arg3)); }
DdNode * DdGate::gateFuncElem(DdManager * pDdManager, DdNode * pa, DdNode * pb){ switch(__gate){ case AND: return Cudd_bddAnd(pDdManager, pa, pb); case NAND: return Cudd_bddNand(pDdManager, pa, pb); case OR: return Cudd_bddOr(pDdManager, pa, pb); case NOR: return Cudd_bddNor(pDdManager, pa, pb); case XOR: return Cudd_bddXor(pDdManager, pa, pb); case XNOR: return Cudd_bddXnor(pDdManager, pa, pb); case NOT: return Cudd_bddNand(pDdManager, pa, pa); default: return NULL; } }
/* wrap the CFG to BDD conversion */ DdNode* encode_prog(DdManager* m, pos* postab, cfg_node* proc_list_head) { DdNode* tmp, *proc, *init; DdNode* R = Cudd_ReadLogicZero(m); Cudd_Ref(R); cfg_node* next = proc_list_head; int proc_no = 0; /* all process begin with an 'init' */ while (next) { /* skip node that has id = 0 */ // init = Cudd_ReadOne(m); // init = bdd_encode_pc(m, init, postab->pc, postab->pc_size, proc_no, 0); init = bdd_mk_skip(m, postab, 0, proc_no); proc = bdd_convert_cfg(m, postab, proc_list_head, proc_no, init, R, 0); tmp = Cudd_bddOr(m, R, proc); /* add process to transition relation */ Cudd_Ref(tmp); Cudd_RecursiveDeref(m, R); Cudd_RecursiveDeref(m, proc); R = tmp; next = next->next_proc; /* next process */ ++proc_no; } return R; /* return complete transition relation */ }
/**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 ); } } }
/* traverse a CFG and encode each edge as a BDD */ DdNode* bdd_convert_cfg(DdManager *m, pos* postab, cfg_node* host, int proc, DdNode* current, DdNode* R, int prev) { DdNode* branch; /* holds branch conditions */ DdNode* tmp1, *tmp2; /* temporary vars for cleanup */ current = bdd_encode_pc(m, current, postab->pc_, postab->pc_size, proc, host->node->id); tmp1 = Cudd_bddOr(m, R, current); /* add the completed edge to the */ Cudd_Ref(tmp1); /* transistion system by disjuncting */ Cudd_RecursiveDeref(m, R); Cudd_RecursiveDeref(m, current); R = tmp1; switch (host->node->tag) { case _assign_stat: /* assignment and skip statements */ case _skip_stat: /* form very similar edges */ if (host->node->tag == _assign_stat) current = bdd_mk_assign(m, postab, host, proc); else if (host->node->tag == _skip_stat) current = bdd_mk_skip(m, postab, host->node->id, proc); break; case _if_then_stat: /* if a branch is encountered, */ case _if_else_stat: /* add the branch condition to the */ case _while_stat: /* edge's encoding and continue */ current = bdd_mk_skip(m, postab, host->node->id, proc); tmp1 = bdd_expr(m, postab->vars, host->node->children[EXPR]); branch = Cudd_bddAnd(m, tmp1, current); Cudd_Ref(branch); /* conjunct branch condition to branch */ tmp2 = Cudd_bddAnd(m, Cudd_Not(tmp1), current); Cudd_Ref(tmp2); /* conjuct complement of the branch */ Cudd_RecursiveDeref(m, tmp1); /* condition to current */ Cudd_RecursiveDeref(m, current); current = tmp2; if (host->node->id < prev) /* terminate after back edge */ return R; else { /* traverse the 'true' branch */ tmp1 = bdd_convert_cfg(m, postab, host->succ[CFG_IF | CFG_WHILE], proc, branch, R, prev); Cudd_RecursiveDeref(m, R); } break; case _await_stat: /* await is both a branch and a skip */ tmp1 = bdd_mk_skip(m, postab, host->node->id, proc); tmp2 = bdd_expr(m, postab->vars, host->node->children[EXPR]); current = Cudd_bddAnd(m, tmp1, tmp2); Cudd_Ref(current); /* conjunct branch condition to current */ branch = Cudd_bddAnd(m, tmp1, Cudd_Not(tmp2)); Cudd_Ref(branch); /* conjuct complement of the branch */ Cudd_RecursiveDeref(m, tmp1); /* condition to branch */ Cudd_RecursiveDeref(m, tmp2); /* branch is a self-referential edge */ branch = bdd_encode_pc(m, branch, postab->pc_, postab->pc_size, proc, host->node->id); tmp1 = Cudd_bddOr(m, R, branch); Cudd_Ref(tmp1); Cudd_RecursiveDeref(m, R); Cudd_RecursiveDeref(m, branch); /* continue edge continues to next node */ break; default: printf("Error: invalid statement in CFG\n"); exit(1); } if (host->succ[CONTINUE]) { /* if the node has a successor */ R = bdd_convert_cfg(m, postab, host->succ[CONTINUE], proc, current, tmp1, host->node->id); Cudd_RecursiveDeref(m, tmp1); /* initiate new edge and call again */ } else { /* if the node terminates a branch */ current = bdd_encode_pc(m, current, postab->pc_, postab->pc_size, proc, host->node->id); R = Cudd_bddOr(m, tmp1, current); Cudd_Ref(R); /* terminate node with an infinite loop */ Cudd_RecursiveDeref(m, tmp1); Cudd_RecursiveDeref(m, current); } return R; /* return complete transition relation */ }
/** * @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; }
/** * @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; }
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; }
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; }