void dfaStoreState(int ds) { default_state = ds; bdd_kill_cache(aut->bddm); bdd_make_cache(aut->bddm, 8, 4); makebdd(aut->bddm); }
/* unite bddPaths */ bdd_ptr unitePaths(bdd_manager *bddm) { int n; bdd_ptr p = bddPath[0]; bdd_make_cache(bddm, 8, 4); for (n = 1; n < numExceptions; n++) p = bdd_apply2_hashed(bddm, p, bddm, bddPath[n], bddm, &fn_unite); bdd_kill_cache(bddm); return p; }
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); }
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); }