void gtaReplaceIndices(GTA *P, unsigned map[]) { unsigned i,p1,p2; for (i = 0; i < guide.numSs; i++) { unsigned rs = P->ss[guide.muRight[i]].size; unsigned ls = P->ss[guide.muLeft[i]].size; bdd_prepare_apply1(P->ss[i].bddm); for (p1 = 0; p1 < ls; p1++) for (p2 = 0; p2 < rs; p2++) bdd_replace_indices( P->ss[i].bddm, BDD_ROOT(P->ss[i].bddm, BEH(P->ss[i], p1, p2)), map); } }
/* set default state and make BDD for current state pair */ void gtaStoreDefault(unsigned p) { bdd_ptr united; int n; bdd_manager *tmpBddm; invariant(numExceptions == nextException); defState = p; tmpBddm = bdd_new_manager(100, 10); /* large enough to avoid rehashing??? */ /* COULD AN ASSERTION CHECK THAT REHASHING DOES NOT OCCUR???????? */ /* insert default state as leaf */ def = bdd_find_leaf_hashed_add_root(tmpBddm, defState); /* insert paths for exceptions */ for (exp = 0; exp < numExceptions; exp++) { for (n = 0; n < numOffs; n++) sortedPath[n] = exception[exp].path[sortedIndex[n]]; bddPath[exp] = makePath(tmpBddm, exception[exp].value); } /* unite path roots */ if (numExceptions == 0) united = def; else if (numExceptions == 1) united = bddPath[0]; else united = unitePaths(tmpBddm); /* insert into result BDD manager */ bdd_prepare_apply1(tmpBddm); bdd_apply1(tmpBddm, united, gta->ss[s].bddm, &fn_identity); bdd_kill_manager(tmpBddm); /* set behaviour entry */ BEH(gta->ss[s], left, right) = BDD_LAST_HANDLE(gta->ss[s].bddm); }
void makebdd(bdd_manager *bddm) { bdd_manager *tmp_bddm; bdd_ptr united_bdds, default_ptr; int i; tmp_bddm = bdd_new_manager(8, 4); /* ** insert a leaf with value 'default_state' in tmp_bddm, ** if not already present */ default_ptr = bdd_find_leaf_hashed(tmp_bddm, default_state, SEQUENTIAL_LIST(sub_results), &update_bddpaths); for (exp_count = 0; exp_count < no_exceptions; exp_count++) { for (i = 0; i < offsets_size; i++) sorted_path[i] = exceptions[exp_count].path[sorted_indices[i]]; /* clear the cache */ bdd_kill_cache(tmp_bddm); bdd_make_cache(tmp_bddm, 8, 4); tmp_bddm->cache_erase_on_doubling = TRUE; bddpaths[exp_count] = makepath(tmp_bddm, 0, exceptions[exp_count].value, &update_bddpaths); PUSH_SEQUENTIAL_LIST(tmp_bddm->roots, unsigned, bddpaths[exp_count]); } if (no_exceptions == 0) united_bdds = default_ptr; else if (no_exceptions == 1) united_bdds = TOP_SEQUENTIAL_LIST(tmp_bddm->roots); else united_bdds = unite_roots(tmp_bddm); bdd_prepare_apply1(tmp_bddm); bdd_apply1(tmp_bddm, united_bdds, bddm, &fn_identity); /* store the result in bddm->roots */ bdd_kill_manager(tmp_bddm); }
void double_table_and_cache_hashed(bdd_manager *bddm, unsigned* some_roots, void (*update_fn)(unsigned (*new_place)(unsigned node)), unsigned *p_of_find, unsigned *q_of_find, boolean rehash_p_and_q) { unsigned *p; old_bddm = mem_alloc((size_t) sizeof (bdd_manager)); *old_bddm = *bddm; /*make new bigger table, but only if a bigger one is possible */ if (bddm->table_total_size > BDD_MAX_TOTAL_TABLE_SIZE) { printf("\nBDD too large (>%d nodes)\n", BDD_MAX_TOTAL_TABLE_SIZE); abort(); } bddm->table_log_size++; bddm->table_size *= 2; bddm->table_overflow_increment *= 2; { unsigned desired_size = bddm->table_size + BDD_NUMBER_OF_BINS + bddm->table_overflow_increment; bddm->table_total_size = (desired_size <= BDD_MAX_TOTAL_TABLE_SIZE)? desired_size: BDD_MAX_TOTAL_TABLE_SIZE; } bddm->node_table = (bdd_record*) mem_alloc( (size_t) bddm->table_total_size * (sizeof (bdd_record))); bddm->table_mask = bddm->table_size - BDD_NUMBER_OF_BINS; bddm->table_double_trigger *= 2; bddm->table_overflow = bddm->table_size + BDD_NUMBER_OF_BINS; #ifdef _BDD_STAT_ bddm->number_double++; #endif /* initialize to unused */ bddm->table_elements = 0; mem_zero(&bddm->node_table[BDD_NUMBER_OF_BINS], (size_t) bddm->table_size * (sizeof (bdd_record))); /* initialize bddm roots to the empty list, this new list will contain the rehashed addresses of old_bddm->roots*/ MAKE_SEQUENTIAL_LIST(bddm->roots, unsigned, 1024); /*now rehash all nodes reachable from the old roots; we must be sure that the apply1 operation does not entail doubling of bddm node table: this is achieved by our having just doubled the size of the table*/ bdd_prepare_apply1(old_bddm); for (p = SEQUENTIAL_LIST(old_bddm->roots); *p ; p++) { bdd_apply1(old_bddm, *p, bddm, &double_leaf_fn); } /*also make sure to rehash portion that is accessible from some_roots*/ for (p = some_roots; *p; p++) { if (*p != BDD_UNDEF) *p = bdd_apply1_dont_add_roots(old_bddm, *p, bddm, &double_leaf_fn); } /*and fix values p_of_find and q_of_find if indicated*/ if (rehash_p_and_q) { *p_of_find = bdd_apply1_dont_add_roots(old_bddm, *p_of_find, bddm, &double_leaf_fn); *q_of_find = bdd_apply1_dont_add_roots(old_bddm, *q_of_find, bddm, &double_leaf_fn); } /*perform user supplied updates*/ if (update_fn) (*update_fn)(&get_new_r); /*old_table now contains nodes whose mark field designates the new position of the node*/ if (bddm->cache) { if (bddm->cache_erase_on_doubling) { bdd_kill_cache(bddm); bdd_make_cache(bddm, 2 * bddm->cache_size * CACHE_NUMBER_OF_BINS, 2 * bddm->cache_overflow_increment * CACHE_NUMBER_OF_BINS); } else /*this is only a good idea when bddm is different from the managers the current apply operation is performed over*/ double_cache(bddm, &get_new_r); } old_bddm->cache = (cache_record*) 0; /* old cache has been deallocated by now*/ /*deallocated old table and old roots*/ bdd_kill_manager(old_bddm); }
int dfaExport(DFA *a, char *filename, int num, char *vars[], char orders[]) { Table *table = tableInit(); int i; FILE *file; if (filename) { if ((file = fopen(filename, "w")) == 0) return 0; } else file = stdout; /* remove all marks in a->bddm */ bdd_prepare_apply1(a->bddm); /* build table of tuples (idx,lo,hi) */ for (i = 0; i < a->ns; i++) export(a->bddm, a->q[i], table); /* renumber lo/hi pointers to new table ordering */ for (i = 0; i < table->noelems; i++) { if (table->elms[i].idx != -1) { table->elms[i].lo = bdd_mark(a->bddm, table->elms[i].lo) - 1; table->elms[i].hi = bdd_mark(a->bddm, table->elms[i].hi) - 1; } } /* write to file */ fprintf(file, "MONA DFA\n" "number of variables: %u\n" "variables:", num); for (i = 0; i < num; i++) fprintf(file, " %s", vars[i]); fprintf(file, "\n" "orders:"); for (i = 0; i < num; i++) fprintf(file, " %u", (unsigned) orders[i]); fprintf(file, "\n" "states: %u\n" "initial: %u\n" "bdd nodes: %u\n" "final:", a->ns, a->s, table->noelems); for (i = 0; i < a->ns; i++) fprintf(file, " %d", a->f[i]); fprintf(file, "\nbehaviour:"); for (i = 0; i < a->ns; i++) fprintf(file, " %u", bdd_mark(a->bddm, a->q[i]) - 1); fprintf(file, "\nbdd:\n"); for (i = 0; i < table->noelems; i++) fprintf(file, " %i %u %u\n", table->elms[i].idx, table->elms[i].lo, table->elms[i].hi); fprintf(file, "end\n"); tableFree(table); if (filename) fclose(file); return 1; }
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; }