Example #1
0
void 
median (
    struct vtx_data **graph,	/* data structure with vertex weights */
    double *vals,			/* values of which to find median */
    int nvtxs,		/* number of values I own */
    int *active,		/* space for list of nvtxs ints */
    double *goal,			/* desired sizes for sets */
    int using_vwgts,		/* are vertex weights being used? */
    int *sets			/* set each vertex gets assigned to */
)
{
    double   *vptr;		/* loops through vals array */
    double    val;		/* value in vals array */
    double    maxval;		/* largest active value */
    double    minval;		/* smallest active value */
    double    guess;		/* approximate median value */
    double    nearup;		/* lowest guy above guess */
    double    neardown;		/* highest guy below guess */
    double    whigh;		/* total weight of values above maxval */
    double    wlow;		/* total weight of values below minval */
    double    wabove;		/* total weight of active values above guess */
    double    wbelow;		/* total weight of active values below guess */
    double    wexact;		/* weight of vertices exactly at guess */
    double    lweight;		/* desired weight of lower values in set */
    double    uweight;		/* desired weight of upper values in set */
    double    frac;		/* fraction of values I want less than guess */
    int      *aptr;		/* loops through active array */
    int      *aptr2;		/* helps update active array */
    int       myactive;		/* number of active values I own */
    double    wfree;		/* weight of vtxs not yet divided */
    int       removed;		/* number of my values eliminated */
    /*int npass = 0;*/		/* counts passes required to find median */
    int       done;		/* check for termination criteria */
    int       vtx;		/* vertex being considered */
    int       i;		/* loop counters */

    /* Initialize. */

    /* Determine the desired weight sums for the two different sets. */
    lweight = goal[0];
    uweight = goal[1];

    myactive = nvtxs;
    whigh = wlow = 0;

    /* Find largest and smallest values in vector, and construct active list. */
    vptr = vals;
    aptr = active;
    minval = maxval = *(++vptr);
    *aptr++ = 1;
    for (i = 2; i <= nvtxs; i++) {
	*aptr++ = i;
	val = *(++vptr);
	if (val > maxval)
	    maxval = val;
	if (val < minval)
	    minval = val;
    }

    /* Loop until all sets are partitioned correctly. */
    done = FALSE;
    while (!done) {
	/*npass++;*/

	/* Select a potential dividing value. */
	/* Currently, this assumes a linear distribution. */
	wfree = lweight + uweight - (wlow + whigh);
	frac = (lweight - wlow) / wfree;

	/* Overshoot a bit to try to cut into largest set. */
	frac = .5 * (frac + .5);

	guess = minval + frac * (maxval - minval);

	/* Now count the guys above and below this guess. */
	/* Also find nearest values on either side of guess. */
	wabove = wbelow = wexact = 0;
	nearup = maxval;
	neardown = minval;

	aptr = active;
	for (i = 0; i < myactive; i++) {
	    vtx = *aptr++;
	    val = vals[vtx];
	    if (val > guess) {
		if (using_vwgts)
		    wabove += graph[vtx]->vwgt;
		else
		    wabove++;
		if (val < nearup)
		    nearup = val;
	    }
	    else if (val < guess) {
		if (using_vwgts)
		    wbelow += graph[vtx]->vwgt;
		else
		    wbelow++;
		if (val > neardown)
		    neardown = val;
	    }
	    else {
		if (using_vwgts)
		    wexact += graph[vtx]->vwgt;
		else
		    wexact++;
	    }
	}

	/* Select a half to discard. */
	/* And remove discarded vertices from active list. */
	removed = 0;
	if (wlow + wbelow - lweight > whigh + wabove - uweight &&
	    whigh + wabove + wexact < uweight ) {
	    /* Discard upper set. */
	    whigh += wabove + wexact;
	    maxval = neardown;
	    done = FALSE;
	    aptr = aptr2 = active;
	    for (i = 0; i < myactive; i++) {
		if (vals[*aptr] >= guess) {
		    ++removed;
		}
		else
		    *aptr2++ = *aptr;
		aptr++;
	    }
	    myactive -= removed;
	    if (myactive == 0) done = TRUE;
	}
	else if ( whigh + wabove - uweight > wlow + wbelow - lweight &&
	    wlow + wbelow + wexact < lweight ) {
	    /* Discard lower set. */
	    wlow += wbelow + wexact;
	    minval = nearup;
	    done = FALSE;
	    aptr = aptr2 = active;
	    for (i = 0; i < myactive; i++) {
		if (vals[*aptr] <= guess) {
		    ++removed;
		}
		else
		    *aptr2++ = *aptr;
		aptr++;
	    }
	    myactive -= removed;
	    if (myactive == 0) done = TRUE;
	}
	else {			/* Perfect partition! */
	    wlow += wbelow;
	    whigh += wabove;
	    done = TRUE;
	}

	/* Check for alternate termination criteria. */
	if (!done && maxval == minval) {
	    guess = maxval;
	    done = TRUE;
	}
    }
    median_assign(graph, vals, nvtxs, goal, using_vwgts, sets, wlow, whigh, guess);
}
Example #2
0
void 
mapper (
    struct vtx_data **graph,	/* data structure with vertex weights */
    double **xvecs,		/* continuous indicator vectors */
    int nvtxs,		/* number of vtxs in graph */
    int *active,		/* space for nmyvals ints */
    int *sets,			/* returned processor assignment for my vtxs */
    int ndims,		/* number of dimensions being divided into */
    int cube_or_mesh,		/* 0 => hypercube, d => d-dimensional mesh */
    int nsets,		/* number of sets to divide into */
    int mediantype,		/* type of eigenvector partitioning to use */
    double *goal,			/* desired set sizes */
    int vwgt_max		/* largest vertex weight */
)
{
    double    temp_goal[2];	/* combined set goals if using option 1. */
    double    wbelow;		/* weight of vertices with negative values */
    double    wabove;		/* weight of vertices with positive values */
    int      *temp_sets;	/* sets vertices get assigned to */
    int       vweight;		/* weight of a vertex */
    int       using_vwgts;	/* are vertex weights being used? */
    int       bits;		/* bits for assigning set numbers */
    int       i, j;		/* loop counters */

    void      median(), rec_median_k(), rec_median_1(), median_assign();
    void      map2d(), map3d();

    /* NOTE: THIS EXPECTS XVECS, NOT YVECS! */

    using_vwgts = (vwgt_max != 1);

    if (ndims == 1 && mediantype == 1)
	mediantype = 3;		/* simpler call than normal option 1. */

    if (mediantype == 0) {	/* Divide at zero instead of median. */
	bits = 1;
	temp_sets = smalloc((nvtxs + 1) * sizeof(int));
	for (j = 1; j <= nvtxs; j++)
	    sets[j] = 0;

	for (i = 1; i <= ndims; i++) {
	    temp_goal[0] = temp_goal[1] = 0;
	    for (j = 0; j < (1 << ndims); j++) {
		if (bits & j)
		    temp_goal[1] += goal[j];
		else
		    temp_goal[0] += goal[j];
	    }
	    bits <<= 1;

	    wbelow = wabove = 0;
	    vweight = 1;
	    for (j = 1; j <= nvtxs; j++) {
		if (using_vwgts)
		    vweight = graph[j]->vwgt;
		if (xvecs[i][j] < 0)
		    wbelow += vweight;
		else if (xvecs[i][j] > 0)
		    wabove += vweight;
	    }

	    median_assign(graph, xvecs[i], nvtxs, temp_goal, using_vwgts, temp_sets,
			  wbelow, wabove, (double) 0.0);

	    for (j = 1; j <= nvtxs; j++)
		sets[j] = (sets[j] << 1) + temp_sets[j];
	}
    }

    else if (mediantype == 1) {	/* Divide using min-cost assignment. */
	if (ndims == 2)
	    map2d(graph, xvecs, nvtxs, sets, goal, vwgt_max);
	else if (ndims == 3)
	    map3d(graph, xvecs, nvtxs, sets, goal, vwgt_max);
    }


    else if (mediantype == 2) {	/* Divide recursively using medians. */
	rec_median_k(graph, xvecs, nvtxs, active, ndims, cube_or_mesh, goal,
		     using_vwgts, sets);
    }

    else if (mediantype == 3) {	/* Cut with independent medians => unbalanced. */
	bits = 1;
	temp_sets = smalloc((nvtxs + 1) * sizeof(int));
	for (j = 1; j <= nvtxs; j++)
	    sets[j] = 0;

	for (i = 1; i <= ndims; i++) {
	    temp_goal[0] = temp_goal[1] = 0;
	    for (j = 0; j < (1 << ndims); j++) {
		if (bits & j)
		    temp_goal[1] += goal[j];
		else
		    temp_goal[0] += goal[j];
	    }
	    bits <<= 1;

	    median(graph, xvecs[i], nvtxs, active, temp_goal, using_vwgts, temp_sets);
	    for (j = 1; j <= nvtxs; j++)
		sets[j] = (sets[j] << 1) + temp_sets[j];
	}
	sfree(temp_sets);
    }

    if (mediantype == 4) {	/* Stripe the domain. */
	rec_median_1(graph, xvecs[1], nvtxs, active, cube_or_mesh, nsets,
		     goal, using_vwgts, sets, TRUE);
    }
}