/* Make an estimate of the total cost of determining the given condition * with the given set of still-needed variables. Return true on success, * and then also set soln_mincost with the cost of running all generators * and the condition, and set soln_generators (which must be allocated) * to the set of generators used to get to this point. * * This cost estimator assumes that vartab_analyse_cheapest_generators() * has already been run, and it only succeeds when all varsneeded have * a generator assigned to them (which should be caught out by that prior * phase, but it nonetheless returns an OK as a boolean). * * The soln_mincost represents the minimum cost estimation for setting up * all the variables. The soln_generators provides the generators that * need to run before the varsneeded have been generated, ordered by * ascending weight. The soln_generator_count provides the number of * entries filled into this table; the assumption made is that at least * as many entries are available as the number of elements in varsneeded. * Room up to this point may be overwritten by this routine, even if this * exceeds the impression given by a lower soln_generator_count. */ bool cnd_estimate_total_cost (struct cndtab *cctab, cndnum_t cndnum, bitset_t *varsneeded, float *soln_mincost, struct gentab *gentab, unsigned int *soln_generator_count, gennum_t soln_generators []) { bitset_iter_t v; bitset_t *vneeded; *soln_generator_count = 0; // // Find the cheapest generator for each of the varsneeded bitset_iterator_init (&v, varsneeded); while (bitset_iterator_next_one (&v, NULL)) { gennum_t unit_gen; bitset_t *genvars; unsigned int gi = bitset_iterator_bitnum (&v); // // The first step generates a list with the cheapest generators; // this could actually return an ordered _list_ of generators // and would cut off the most expensive ones when varsneeded // are generated as by-products in other generators. // This leads to more accurate estimates, and more efficiency. if (!var_get_cheapest_generator ( vartab_from_type (cctab->vartype), gi, &unit_gen, NULL)) { return false; } soln_generators [*soln_generator_count++] = unit_gen; } // // Now sort the soln_generators by their weight. // // This is a sort for optimisation purposes; if it returns an error, // then the cause is normally memory shortage, in which case the // lost efficiency here is less vital than other things going awry. QSORT_R(soln_generators, *soln_generator_count, sizeof (struct generator *), gentab, _qsort_gen_cmp_weight); // // From the sorted soln_generators list, subtract generated variables // from varsneeded until all are done. Cut off the output list at // that point by returning a possibly lower soln_generator_count. // //TODO// Might be able to skip generators that add nothing of interest *soln_generator_count = 0; *soln_mincost = cnd_get_weight (cctab, cndnum); vneeded = bitset_clone (varsneeded); while (!bitset_isempty (vneeded)) { gennum_t g = soln_generators [*soln_generator_count++]; *soln_mincost *= gen_get_weight (gentab, g); bitset_t *genvars = gen_share_variables (gentab, g); bitset_subtract (vneeded, genvars); } bitset_destroy (vneeded); return true; }
/* Based on the variables needed in each condition, partition the variables. * Initially, each variable is created within its own, size-1 partition. * Conditions that mention multiple variables however, pull variables together * into the same partition. This is done by renumbering one partition to * another partition. */ static void cnd_drive_partitions (struct cndtab *tab, cndnum_t cndnum) { bitset_iter_t bi; varnum_t onevar, othvar; struct vartab *vartab; bitset_iterator_init (&bi, tab->cnds [cndnum].vars_needed); if (!bitset_iterator_next_one (&bi, NULL)) { return; } vartab = vartab_from_type (tab->vartype); onevar = bitset_iterator_bitnum (&bi); while (bitset_iterator_next_one (&bi, NULL)) { othvar = bitset_iterator_bitnum (&bi); vartab_merge_partitions (vartab, onevar, othvar); } }
int bitset_index_init_iterator(struct bitset_index *index, struct bitset_iterator *it, struct bitset_expr *expr) { assert(index != NULL); assert(it != NULL); /* Check that we have all required bitsets */ size_t max = 0; for (size_t c = 0; c < expr->size; c++) { for (size_t b = 0; b < expr->conjs[c].size; b++) { if (expr->conjs[c].bitset_ids[b] > max) { max = expr->conjs[c].bitset_ids[b]; } } } /* Resize the index with empty bitsets */ if (bitset_index_reserve(index, max + 1) != 0) return -1; return bitset_iterator_init(it, expr, index->bitsets, index->capacity); }