Example #1
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.
 *
 * 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;
}
Example #2
0
// this is slower, because each call needs to malloc, but it is reentrant
float dselip(unsigned long k, unsigned long n, const float *arr) {
    float* sorted_data = malloc(sizeof(float) * n);
    memcpy(sorted_data, arr, sizeof(float)*n);
    QSORT_R(sorted_data, n, sizeof(float), NULL, compare_floats_asc_r);
    float kth_item = sorted_data[k];
    free(sorted_data);
    return kth_item;
}
Example #3
0
int* permuted_sort(const void* realarray, int array_stride,
                   int (*compare)(const void*, const void*),
                   int* perm, int N) {
    permsort_t ps;
	if (!perm)
		perm = permutation_init(perm, N);

    ps.compare = compare;
    ps.data_array = realarray;
    ps.data_array_stride = array_stride;

    QSORT_R(perm, N, sizeof(int), &ps, compare_permuted);

    return perm;
}
Example #4
0
static void bl_sort_rec(bl* list, void* pivot,
						int (*compare)(const void* v1, const void* v2, void* userdata),
						void* userdata) {
	bl* less;
	bl* equal;
	bl* greater;
	int i;
    bl_node* node;

	// Empty case
	if (!list->head)
		return;

	// Base case: list with only one block.
	if (list->head == list->tail) {
		bl_node* node;
		struct funcandtoken ft;
		ft.compare = compare;
		ft.userdata = userdata;
		node = list->head;
		QSORT_R(NODE_DATA(node), node->N, list->datasize, &ft, qcompare);
		return;
	}

	less = bl_new(list->blocksize, list->datasize);
	equal = bl_new(list->blocksize, list->datasize);
	greater = bl_new(list->blocksize, list->datasize);
	for (node=list->head; node; node=node->next) {
		char* data = NODE_CHARDATA(node);
		for (i=0; i<node->N; i++) {
			int val = compare(data, pivot, userdata);
			if (val < 0)
				bl_append(less, data);
			else if (val > 0)
				bl_append(greater, data);
			else
				bl_append(equal, data);
			data += list->datasize;
		}
	}

    // recurse before freeing anything...
	bl_sort_with_userdata(less, compare, userdata);
	bl_sort_with_userdata(greater, compare, userdata);

	for (node=list->head; node;) {
        bl_node* next;
		next = node->next;
		bl_free_node(node);
		node = next;
    }
	list->head = NULL;
	list->tail = NULL;
	list->N = 0;
	list->last_access = NULL;
	list->last_access_n = 0;

	if (less->N) {
		list->head = less->head;
		list->tail = less->tail;
		list->N = less->N;
	}
	if (equal->N) {
		if (list->N) {
			list->tail->next = equal->head;
			list->tail = equal->tail;
		} else {
			list->head = equal->head;
			list->tail = equal->tail;
		}
		list->N += equal->N;
	}
	if (greater->N) {
		if (list->N) {
			list->tail->next = greater->head;
			list->tail = greater->tail;
		} else {
			list->head = greater->head;
			list->tail = greater->tail;
		}
		list->N += greater->N;
	}
	// note, these are supposed to be "free", not "bl_free"; we've stolen
	// the blocks, we're just freeing the headers.
	free(less);
	free(equal);
	free(greater);
}
Example #5
0
// solve vp problem using Permutation Pack or Choose Pack
vp_solution_t solve_hvp_problem_MCB(vp_problem_t vp_prob, int args[],
    qsort_cmp_func *cmp_item_idxs, qsort_cmp_func *cmp_bin_idxs)
{
    int i, j;
    int isCP = args[0];
    int w = MIN(args[1], vp_prob->num_dims);

    int dims[vp_prob->num_dims];
    int vector_dims[vp_prob->num_items][w];

    int unmapped_vectors[vp_prob->num_items];
    int num_unmapped_vectors = vp_prob->num_items;

    int b, v, best_v, best_v_idx, cmp_val;

    int bin_dim_ranks[vp_prob->num_dims];

    int *v_perm, *best_perm, *tmp_perm;

    int bin_idxs[vp_prob->num_bins];
    int *open_bins = bin_idxs;
    int num_open_bins = vp_prob->num_bins;

    vp_solution_t vp_soln = new_vp_solution(vp_prob);

    // initialize dims
    for (j = 0; j < vp_prob->num_dims; j++) dims[j] = j;

    // initialize unmapped vectors and vector dims
    for (i = 0; i < vp_prob->num_items; i++) {
        unmapped_vectors[i] = i;
        QSORT_R(dims, vp_prob->num_dims, sizeof(int), 
            vp_prob->items[i]->totals, rcmp_double_array_idxs);
        for (j = 0; j < w; j++) vector_dims[i][j] = dims[j];
    }

    // initialize open bins
    for (i = 0; i < vp_prob->num_bins; i++) open_bins[i] = i;

    if (cmp_bin_idxs)
        QSORT_R(open_bins, num_open_bins, sizeof(int), vp_prob->bins, 
            cmp_bin_idxs);

    // initialize pointers to v_perm and best_perm
    v_perm = (int *)calloc(w, sizeof(int));
    best_perm = (int *)calloc(w, sizeof(int));

    while (num_open_bins > 0 && num_unmapped_vectors > 0) {

        b = *open_bins;

        best_v = -1;
        best_v_idx = -1;

        // Find the first vector that can be put in the bin
        for (i = 0; i < num_unmapped_vectors; i++) {
            v = unmapped_vectors[i];
            if (vp_item_can_fit_in_bin(vp_soln, v, b)) {
                best_v = v;
                best_v_idx = i;
                break;
            }
        }

        // This probably over-complicates things, but check and make sure that 
        // there are at least 2 vectors before doing all the PP/CP stuff
        for (i++; i < num_unmapped_vectors; i++) {
            v = unmapped_vectors[i];
            if (vp_item_can_fit_in_bin(vp_soln, v, b)) {
                break;
            }
        }

        if (i < num_unmapped_vectors) {

            // compute bin permutation
            QSORT_R(dims, vp_prob->num_dims, sizeof(int),
                vp_soln->capacities[b], rcmp_double_array_idxs);

            // compute bin dim positions
            bin_dim_ranks[dims[0]] = 0; // make sure j > 0
            j = 1;
            // CP treats first w positions as the same...
            if (isCP) for (; j < w; j++) bin_dim_ranks[dims[j]] = 0;

            // we assume j > 0 from above...
            for (; j < vp_prob->num_dims; j++) {
                if (vp_soln->capacities[b][dims[j-1]] == 
                    vp_soln->capacities[b][dims[j]]) {
                    bin_dim_ranks[dims[j]] = bin_dim_ranks[dims[j-1]];
                } else {
                    bin_dim_ranks[dims[j]] = bin_dim_ranks[dims[j-1]]+1;
                }
            }

            // apply bin key inverse to best vector key to get how it permutes
            // the bin key in the first w elements...
            for (j = 0; j < w; j++) 
                best_perm[j] = bin_dim_ranks[vector_dims[best_v][j]];

            // CP ignores position
            if (isCP) qsort(best_perm, w, sizeof(int), cmp_ints);

            // start with the current vector and look for the "best" one by the
            // CP/PP and secondary criteria...
            for (; i < num_unmapped_vectors; i++) {

                v = unmapped_vectors[i];

                if (!vp_item_can_fit_in_bin(vp_soln, v, b)) continue;

                // apply bin key inverse to vector keys to get how they permute 
                // the bin key in the first w elements...
                for (j = 0; j < w; j++) 
                    v_perm[j] = bin_dim_ranks[vector_dims[v][j]];

                // CP ignores position of the first w
                if (isCP) qsort(v_perm, w, sizeof(int), cmp_ints);

                cmp_val = cmp_int_arrays_lex(w, v_perm, best_perm);

                if (cmp_val < 0 || (0 == cmp_val && cmp_item_idxs &&
                    QSORT_CMP_CALL(cmp_item_idxs, vp_prob->items, &v, &best_v) 
                    < 0)) 
                {
                    best_v = v;
                    best_v_idx = i;
                    tmp_perm = best_perm;
                    best_perm = v_perm;
                    v_perm = tmp_perm;
                }

            }

        }

        // if we found a vector put it in the bin and delete from the list of
        // unmapped vectors -- otherwise advance to the next bin
        if (best_v > -1) {
            vp_put_item_in_bin(vp_soln, best_v, b);
            num_unmapped_vectors--;
            unmapped_vectors[best_v_idx] = 
                unmapped_vectors[num_unmapped_vectors];
        } else {
            open_bins++;
            num_open_bins--;
        }

    }

    free(v_perm);
    free(best_perm);

    if (!num_unmapped_vectors) return vp_soln;

    free_vp_solution(vp_soln);

    return NULL;
}
Example #6
0
vp_solution_t solve_hvp_problem_FITD(vp_problem_t vp_prob, int args[],
    qsort_cmp_func *cmp_item_idxs, qsort_cmp_func *cmp_bin_idxs)
{
    int fit_type = args[0];
    int i, j, k;
    int v, b;
    int item_sortmap[vp_prob->num_items];
    int bin_sortmap[vp_prob->num_bins];
    double sumcapacities[vp_prob->num_bins];
    vp_solution_t vp_soln = new_vp_solution(vp_prob);

    // set up vector sort map
    for (i = 0; i < vp_prob->num_items; i++) item_sortmap[i] = i;
    if (cmp_item_idxs)
        QSORT_R(item_sortmap, vp_prob->num_items, sizeof(int), vp_prob->items, 
            cmp_item_idxs);

    // set up bin sort map
    for (j = 0; j < vp_prob->num_bins; j++) bin_sortmap[j] = j;
    if (cmp_bin_idxs)
        QSORT_R(bin_sortmap, vp_prob->num_bins, sizeof(int), vp_prob->bins, 
            cmp_bin_idxs);

    // Place vectors into bins
    switch(fit_type) {
        case FIRST_FIT:
        for (i = 0; i < vp_prob->num_items; i++) {
            v = item_sortmap[i];
            for (j = 0; j < vp_prob->num_bins; j++) {
                b = bin_sortmap[j];
                if (!vp_put_item_in_bin_safe(vp_soln, v, b)) break;
            }
            if (j >= vp_prob->num_bins) {
                free_vp_solution(vp_soln);
                return NULL; 
            }
        }
        break;
        case BEST_FIT:
        for (i = 0; i < vp_prob->num_items; i++) {
            v = item_sortmap[i];
            for (j = 0; j < vp_prob->num_bins; j++) {
                b = bin_sortmap[j];
                if (vp_item_can_fit_in_bin(vp_soln, v, b)) {
                    sumcapacities[b] = 0.0;
                    for (k = 0; k < vp_prob->num_dims; k++) {
                        sumcapacities[b] += vp_soln->capacities[b][k];
                    }
                } else {
                    sumcapacities[b] = 2.0 * vp_prob->num_dims + 1.0;
                }
            }
            b = double_array_argmin(sumcapacities, vp_prob->num_bins);
            if (sumcapacities[j] > 2.0 * vp_prob->num_dims || 
                vp_put_item_in_bin_safe(vp_soln, v, b)) {
                free_vp_solution(vp_soln);
                return NULL;
            }
        }
        break;
        default:
        fprintf(stderr,"Invalid VP fit type '%d'\n", fit_type);
        exit(1);
    }

    return vp_soln;
}
Example #7
0
// solve vp problem using Permutation Pack or Choose Pack
vp_solution_t solve_hvp_problem_MinCD(vp_problem_t vp_prob, int args[],
    qsort_cmp_func *cmp_item_idxs, qsort_cmp_func *cmp_bin_idxs)
{
    int i, j;

    int unmapped_vectors[vp_prob->num_items];
    int num_unmapped_vectors = vp_prob->num_items;

    int b, v, best_v, best_v_idx;
    double best_val, val;

    int bin_idxs[vp_prob->num_bins];
    int *open_bins = bin_idxs;
    int num_open_bins = vp_prob->num_bins;

    vp_solution_t vp_soln = new_vp_solution(vp_prob);

    // initialize unmapped vectors and vector dims
    for (i = 0; i < vp_prob->num_items; i++) unmapped_vectors[i] = i;

    // initialize open bins
    for (i = 0; i < vp_prob->num_bins; i++) open_bins[i] = i;

    if (cmp_bin_idxs)
        QSORT_R(open_bins, num_open_bins, sizeof(int), vp_prob->bins, 
            cmp_bin_idxs);

    while (num_open_bins > 0 && num_unmapped_vectors > 0) {

        b = *open_bins;

        best_v = -1;
        best_v_idx = -1;

        // Find the first vector that can be put in the bin
        for (i = 0; i < num_unmapped_vectors; i++) {
            v = unmapped_vectors[i];
            if (vp_item_can_fit_in_bin(vp_soln, v, b)) {
                best_v = v;
                best_v_idx = i;
                best_val = pairwise_distance(vp_soln, b, v);
                break;
            }
        }

        for (i++; i < num_unmapped_vectors; i++) {
            v = unmapped_vectors[i];
            if (!vp_item_can_fit_in_bin(vp_soln, v, b)) continue;

            val = pairwise_distance(vp_soln, b, v);

            // FIXME: pick the one that minimizes pairwise distance...
            if (val < best_val || (val == best_val && cmp_item_idxs &&
                QSORT_CMP_CALL(cmp_item_idxs, vp_prob->items, &v, &best_v) < 0))
            {
                best_v = v;
                best_v_idx = i;
                best_val = val;
            }
        }

        // if we found a vector put it in the bin and delete from the list of
        // unmapped vectors -- otherwise advance to the next bin
        if (best_v > -1) {
            vp_put_item_in_bin(vp_soln, best_v, b);
            num_unmapped_vectors--;
            unmapped_vectors[best_v_idx] = 
                unmapped_vectors[num_unmapped_vectors];
        } else {
            open_bins++;
            num_open_bins--;
        }

    }

    if (!num_unmapped_vectors) return vp_soln;

    free_vp_solution(vp_soln);

    return NULL;
}