Пример #1
0
/**
 * Compute the overlap between the versions of this card and another
 * @param c the current card
 * @param bs the versions of the other card that may overlap those in c
 * @return an allocated set of bits in bs that not in c, or NULL if none
 */
bitset *card_overlap( card *c, bitset *bs )
{
    bitset *overlap = NULL;
    bitset *p_versions = pair_versions( c->p );
    if ( !bitset_equals(bs,p_versions) )
    {
        overlap = bitset_clone( bs );
        bitset_and_not( overlap, p_versions );
        if ( bitset_empty(overlap) )
        {
            bitset_dispose( overlap );
            overlap = NULL;
        }
    }
    return overlap;
}
Пример #2
0
/* 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.
 */
bool DEPRECATED_cnd_estimate_total_cost (struct condition *cc,
				bitset_t *varsneeded,
				float *soln_mincost,
				bitset_t *soln_generators) {
	//
	// First, for all varsneeded, determine their cheapest generator
	//
	struct iter_var_gen ivg;
	ivg.okay = true;
	ivg.vartab = cc->vartab;
	ivg.total_cost = cc->weight;
	ivg.varneed = bitset_clone (varsneeded);
	ivg.generate = soln_generators;
	bitset_empty (ivg.generate);
	bitset_iterate (varsneeded, var_cheap_generator_it, &ivg);
	bitset_destroy (ivg.varneed);
	*soln_mincost = ivg.total_cost;
	return ivg.okay;
}
Пример #3
0
/**
 * Remove some versions from the hint
 * @param h the hint in question
 * @param other the other set of versions to eliminate where they intersect
 * @return 1 if the hint is now empty, else 0
 */
int hint_subtract( hint *h, bitset *other )
{
    bitset_and_not( h->bs, other );
    return bitset_empty( h->bs );
}
Пример #4
0
/* This is a complex, recursive function to determine the cost for
 * calculating a condition after any still-needed variables have been
 * generated.  Cost is measured in terms of the anticipated number of
 * generated new variable sets, as provided by "*float" annotations
 * on generator and condition lines.
 *
 * Call this with a condition and varsneeded.  The soln_xxx fields will
 * be filled with the requested information, namely the total cost
 * and the generators needed to get there.  The soln_generators bitset
 * is assumed to already exist.
 *
 * This function may not always be able to determine a solution; this
 * can be the case if variables are mentioned in conditions but not in
 * generators, for instance.  In such situations, the function returns
 * false.  It is considered a success if all variables that are needed
 * for a condition are resolved by at least one generator.
 *
 * This is an important function when determining the "path of least
 * resistence" from any generator activity; the least costly condition
 * will always be calculated first, then the calculations are redone,
 * and what is then the least will be selected, and so on.  The
 * generators required will be inserted into the path before their
 * dependent conditions, in the order of least-costly ones first.
 *
 * This is a rather heavy form of analysis, but it is executed only
 * once, at startup of the environment.  After that, the SyncRepl
 * updates can ripple through in great speed.  Note that the complexity
 * and time delays of these procedures rise with the (usually modest)
 * degree of interrelationships between generators and conditions.
 */
bool cnd_get_min_total_cost (struct condition *cc, bitset_t *varsneeded,
				float *soln_mincost,
				bitset_t *soln_generators) {
	bool have_soln = false;
	float soln_mincost;
	varnum_t v, v_max;
	gennum_t g, g_max;
	//
	// Allocate bitsets that will be used while cycling, but not
	// across recursive uses.  To that and, a pile or pool of
	// bitsets could come in handy...  TODO: Optimisation
	//
	bitset_t *cand_varsneeded = bitset_new (varsneeded->type);
	bitset_t *cand_generators = bitset_new (soln_generators->type);
	//
	// If there is no need for further variables to calculate this
	// condition, then terminate recursion on this function.  There
	// will be no requirement to include a generator, and so there
	// will be no generator-incurred expenses.  There will only be
	// the cost of the condition itself, which must still compare
	// with other conditions that might be tighter.
	//
	if (bitset_isempty (varsneeded)) {
		/* Recursion ends, so neither generators nor their cost */
		bitset_empty (out_generators);
		return cc->cost;
	}
	//
	// Iterate over the variables that will need to be generated.
	// For each, iterate over the generators producing it.
	// See how this reduces the variable need, and recurse.
	//
	v_max = bitset_max (varsneeded);
	for (v=0; v<v_max; v++) {
		//
		// Skip this loop iteration if v is not actually needed.
		//
		if (!bitset_test (varsneeded, v)) {
			continue;
		}
		//
		// Iterate over generators for this variable.
		// Note that there may be none left?
		//
		bitset_t *vargenerators;
		vargenerators = var_share_generators (cc->vartab, v);
		g_max = bitset_max (vargenerators);
		if (g_max = BITNUM_BAD) {
			// Apparently, there are no generators for v
			// Skip for-loop (and trouble looping to BITNUM_BAD).
			continue;
		}
		for (g=0; g<g_max; g++) {
			bitset_t *cand_generators = NULL;
			bitset_t *generatorvars;
			float cand_cost;
			//
			// Reduce the variable need.
			//
			cand_varsneeded = bitset_copy (varsneeded);
			generatorvars = gen_share_variables (v);
			bitset_subtract (cand_varsneeded, generatorvars);
			//
			// Determine the cost for generating the remainder.
			//
			if (!cnd_get_cost_total (
					cc, cand_varsneeded,
					&cand_cost, cand_generators)) {
				continue;
			}
			cand_mincost *= generator_cost (g);
			if (have_soln && (cand_cost > soln_mincost)) {
				continue;
			}
			tmp_generators = soln_generators;
			soln_generators = cand_generators;
			cand_generators = tmp_generators; // Reuse in loops
			bitset_set (soln_generators, g);
			soln_mincost = cand_mincost;
			have_soln = true;
		}
	}
	//
	// Cleanup temporary allocations.
	//
	bitset_destroy (cand_varsneeded);
	bitset_destroy (cand_generators);
	//
	// Collect results.  Return success only if we do indeed have
	// found a solution.
	//
	return have_soln;
}