static bddp hit_z2b_rec(zddp f, my_hash *h) { if(f == zdd_top()) return bdd_bot(); if(f == zdd_bot()) return bdd_top(); bddp r; if(ht_search((uintptr_t)f, (uintptr_t*)&r, h)) return r; INC_RECDEPTH(recdepth); bddp r0 = hit_z2b_rec(zdd_lo(f), h); bddp r1 = hit_z2b_rec(zdd_hi(f), h); DEC_RECDEPTH(recdepth); bddp t = bdd_node(zdd_itemval(f), r1, bdd_top()); ENSURE_TRUE_MSG(t != BDD_NULL, "BDD operation failed"); r = bdd_and(r0, t); ENSURE_TRUE_MSG(r != BDD_NULL, "BDD operation failed"); ht_insert((uintptr_t)f, (uintptr_t)r, h); #ifdef SIZE_LOG const uintmax_t insize = zdd_size(f); const uintmax_t outsize = bdd_size(r); fprintf(sizelog, "%ju\t%ju\n", insize, outsize); if(maxsize < outsize) maxsize = outsize; #endif /*SIZE_LOG*/ return r; }
void print_stat(GTA *g) { unsigned s; int dfasize = 0, bddsize = 0; for (s = 0; s < guide.numSs; s++) { dfasize += g->ss[s].size; bddsize += bdd_size(g->ss[s].bddm); } cout << "(" << dfasize << "," << bddsize << ")"; }
void update_largest(GTA *g) { unsigned s; int states = 0, nodes = 0; for (s = 0; s < guide.numSs; s++) { states += g->ss[s].size; nodes += bdd_size(g->ss[s].bddm); } if (states > largest_states) largest_states = states; if (nodes > largest_bdd) largest_bdd = nodes; }
DFA *dfaProduct(DFA* a1, DFA* a2, dfaProductType ff) { DFA *b; int i; unsigned *root_ptr; char binfun[4]; int make_a_loop; unsigned size_estimate = 4 + 4 * (bdd_size(a1->bddm) > bdd_size(a2->bddm) ? bdd_size(a1->bddm) : bdd_size(a2->bddm)); bdd_manager *bddm; /* #define _AUTOMATON_HASHED_IN_PRODUCT_ */ #ifdef _AUTOMATON_HASHED_IN_PRODUCT_ /*prepare hashed access */ bddm = bdd_new_manager(size_estimate, size_estimate/8 + 2); bdd_make_cache(bddm, size_estimate, size_estimate/8 + 2); bddm->cache_erase_on_doubling = TRUE ; #else /*prepare sequential access*/ bddm = bdd_new_manager(size_estimate, 0); bdd_make_cache(bddm, size_estimate, size_estimate/8 + 2); #endif binfun[0] = ff&1; binfun[1] = (ff&2)>>1; /* The binary function */ binfun[2] = (ff&4)>>2; binfun[3] = (ff&8)>>3; qst = qh = qt = new_list(a1->s, a2->s, (list) 0); htbl = new_hash_tab(&hash2, &eq2); insert_in_hash_tab(htbl, a1->s, a2->s, (void *) 1); last_state = 1; /* Careful here! Bdd's start at 0, hashtbl at 1 */ while(qh) { /* Our main loop, nice and tight */ make_a_loop = make_a_loop_status(is_loop(a1->bddm, qh->li1, a1->q[qh->li1]), a1->f[qh->li1], is_loop(a2->bddm, qh->li2, a2->q[qh->li2]), a2->f[qh->li2], binfun); if (make_a_loop != 2) make_loop(bddm, qh->li1, qh->li2); else { #ifdef _AUTOMATON_HASHED_IN_PRODUCT_ (void) bdd_apply2_hashed (a1->bddm, a1->q[qh->li1], a2->bddm, a2->q[qh->li2], bddm, &prod_term_fn); #else (void) bdd_apply2_sequential (a1->bddm, a1->q[qh->li1], a2->bddm, a2->q[qh->li2], bddm, &prod_term_fn); #endif } qh = qh->next; } b = dfaMakeNoBddm(last_state); /* Return the result */ b->s = 0; /* Always first on list */ b->bddm = bddm; for (i=0, root_ptr = bdd_roots(bddm); i < last_state; root_ptr++, i++) { list qnxt; b->q[i] = *root_ptr; b->f[i] = ((a1->f[qst->li1] != 0) && (a2->f[qst->li2] != 0)) ? /* both states are non-bottom, use "binfun" */ BOOL_TO_STATUS(binfun[STATUS_TO_BOOL(a1->f[qst->li1])*2 + STATUS_TO_BOOL(a2->f[qst->li2])]) : /* at least one is bottom */ 0; qnxt = qst->next; mem_free(qst); /* Free the list */ qst = qnxt; } free_hash_tab(htbl); bdd_update_statistics(bddm, (unsigned) PRODUCT); bdd_kill_cache(b->bddm); return(b); }
int main () { GTA* G; char **free_vars; int *orders; unsigned numvars; SSSet *statespaces; /*read the automaton from a file, the TRUE argument means that the guide is being defined by the automaton description in the file */ G = gtaImport("html.gta", &free_vars, &orders, &statespaces, TRUE); if(!G) { printf("error: file 'html.gta' not found (run 'mona -n html.mona')\n"); exit(1); } printf("Guide: number of state spaces is %d\n", guide.numSs); /* illustrate use of state space names */ { SsId d; for (d = 0; d < guide.numSs; d++) printf("State space %s is numbered %d\n", guide.ssName[d], d); } /* illustrate use of inherited acceptance information */ { SsId d; State p; int s; boolean ***inheritedAcceptance = gtaCalcInheritedAcceptance(G); for (d = 0; d < guide.numSs; d++) { printf("State space %d\n", d); for (p = 0; p < G->ss[d].size; p++) for (s = 1; s >= -1; s--) printf(" State %d can%s lead to %s\n", p, inheritedAcceptance[d][p][s]? "": " not", (s==1)? "accept":(s==0)? "don't care": "reject"); } gtaFreeInheritedAcceptance(inheritedAcceptance); } /* illustrate how to find indices of free variables and how to find out about their order (Boolean, first-order, or second-order) */ { unsigned i; numvars = 0; while (free_vars[numvars] != 0) numvars++; printf("Number of free variables: %d\n", numvars); if (numvars != 6) { printf("Oops\n"); exit(1); } /* get table index of variable G1 */ for (i = 0; i < numvars; i++) if (strcmp(free_vars[i], "G1")==0) break; if (i == numvars) printf("G1 not found\n"); else { printf("G1 has index %d and is %d. order\n", i, orders[i]); } } /* illustrate how to analyze the BDD associated with an entry in the transition table */ { /* lookup, say, transition corresponding to state space 1, state pair (left, right) = (4,3) */ unsigned i; bdd_ptr my_bdd_ptr = BDD_ROOT(G->ss[1].bddm, BEH(G->ss[1], 4, 3)); char var_is_used[MAXVARS]; /* var_is_used[i] is true iff variable i is the index of some BDD node in the DAG rooted in my_bdd_ptr */ printf("State space 0 goes to (%d, %d)\n", guide.muLeft[0], guide.muRight[0]); printf("State space 1 goes to (%d, %d)\n", guide.muLeft[1], guide.muRight[1]); printf("Number of BDD nodes in state space 1: %d\n", bdd_size(G->ss[1].bddm)); for (i = 0; i < numvars; i++) var_is_used[i] = 0; bdd_prepare_apply1(G->ss[1].bddm); my_global_variable = var_is_used; global_bddm = (G->ss[1].bddm); bdd_operate_on_nodes(G->ss[1].bddm, my_bdd_ptr, &check_off_index); for (i = 0; i < numvars; i++) if (var_is_used[i]) printf("Variable %s in use for transitions from (4,3) in state space 1\n", free_vars[i]); } /* illustrate how to perform a lookup in the transition table */ { char bit_vector[6] = {0, 1, 1, 0, 1, 0}; bdd_manager *bddm = G->ss[1].bddm; bdd_ptr my_bdd_ptr = BDD_ROOT(bddm, BEH(G->ss[1], 0, 2)); while (!bdd_is_leaf(bddm, my_bdd_ptr)) { my_bdd_ptr = (bit_vector[bdd_ifindex(bddm, my_bdd_ptr)])? bdd_then(bddm, my_bdd_ptr): bdd_else(bddm, my_bdd_ptr); } printf("State reached from (0,2) on {0, 1, 1, 0, 1, 0} is %d\n", bdd_leaf_value(bddm, my_bdd_ptr)); } return 0; }
int main() { bdd_manager *bddm, *bddm1; bdd_ptr zero, one; bdd_handle var2, var7; bdd_ptr and_2_7, nand_2_7; /*bdd_handle handle;*/ bdd_init(); /* needed since we're using statistics */ bddm = bdd_new_manager(100,50); /* get a BDD pointer to a node that is the leaf with value 0 */ zero = bdd_find_leaf_hashed_add_root(bddm, 0); /* and a leaf with value 1 */ one = bdd_find_leaf_hashed_add_root(bddm, 1); /* note already at this point "zero" could have been invalidated if the table doubled, but we know that there is room for a 100 nodes---anyway, this is really very bad style, so we go on in a more appropriate manner */ /* "then" part is one, "else" part is zero */ var2 = bdd_handle_find_node_hashed_add_root(bddm, zero, one, 2); var7 = bdd_handle_find_node_hashed_add_root(bddm, zero, one, 7); /* check node pointers and handles */ assert(zero == BDD_ROOT(bddm, 0)); /* since table was not doubled */ assert(one == BDD_ROOT(bddm, 1)); assert(var2 == 2); assert(var7 == 3); bddm1 = bdd_new_manager(100,50); /* make room for at least 100 nodes, overflow increment is 50 */ bdd_make_cache(bddm1, 100, 50); /* apply2 needs a result cache, here the size is a hundred with increment 50 */ /* apply operation on var2 and var7 in bddm; the result is a completely fresh bdd in bddm1 and a BDD pointer, named "and_2_7" */ and_2_7 = bdd_apply2_hashed(bddm, BDD_ROOT(bddm, var2), /* BDD #1 */ bddm, BDD_ROOT(bddm, var7), /* BDD #2 */ bddm1, /* result BDD */ &and); /* leaf operation */ bdd_update_statistics(bddm, 0); /* update statics group "0" with data from bddm before killing the manager */ printf("Size of bddm: %d\n\n", bdd_size(bddm)); /* let's see the number of nodes created */ bdd_kill_manager(bddm); printf("Size of bddm1: %d\n\n", bdd_size(bddm1)); /*handle = BDD_LAST_HANDLE(bddm1);*/ /* assert(handle == 0); assert(BDD_ROOT(bddm1, handle) == and_2_7); */ /* reset all mark fields in bddm1 before an apply1 operation */ bdd_prepare_apply1(bddm1); /* a new bdd (which as an unlabelled graph is isomorphic to old one) in bddm1 is the result of the following apply operation */ /* it's safe here to use and_2_7 since no operations were performed after it was calculated that could have entailed doubling of table */ nand_2_7 = bdd_apply1(bddm1, and_2_7, bddm1, ¬); bdd_update_statistics(bddm1, 1); printf("Size of bddm1: %d\n\n", bdd_size(bddm1)); print_bdd(bddm1, and_2_7); printf("\n\n"); print_bdd(bddm1, nand_2_7); printf("\n\n"); bdd_kill_manager(bddm1); bdd_print_statistics(0, "bddm"); /* print group 0 statistics with heading "bddm" */ bdd_print_statistics(1, "bddm1"); /* print group 1 statistics with heading "bddm1" */ return 0; }