www.pudn.com > geosteiner-3.1.zip > cutsubs.c


/***********************************************************************

	File:	cutsubs.c
	Rev:	a-1
	Date:	01/16/2001

	Copyright (c) 1996, 2001 by David M. Warme

************************************************************************

	Processing of violated cutsets.

************************************************************************

	Modification Log:

	a-1:	01/16/2001
		: Split off from cutset.c.  Modified to take cut
		:  vertices rather than set of spanning edges.

************************************************************************/

#include "bb.h"
#include "constrnt.h"
#include "cutset.h"
#include "steiner.h"


/*
 * Global Routines
 */

struct constraint * add_cutset_to_list (bitmap_t *,
					struct constraint *,
					double *,
					bitmap_t *,
					bitmap_t *,
					struct cinfo *);


/*
 * Local Routines
 */

static bool		is_subset (bitmap_t *, bitmap_t *, int);

/*
 * This routine handles all of the details of adding a new cutset to the
 * given list of cutsets.  Any existing constraints that are looser
 * (supersets) are deleted.  The new cutset is ignored if it is looser
 * than any existing cutset.
 */

	struct constraint *
add_cutset_to_list (

bitmap_t *		cutset,		/* IN - new cutset to add */
struct constraint *	cutlist,	/* IN - list to add to */
double *		x,		/* IN - current LP solution */
bitmap_t *		vert_mask,	/* IN - set of valid terminals */
bitmap_t *		edge_mask,	/* IN - set of valid hyperedges */
struct cinfo *		cip		/* IN - compatibility info */
)
{
int			i;
int			j;
int			nedges;
int			nmasks;
int			num_in_cut;
int			count;
int *			vp1;
int *			vp2;
struct constraint *	p;
struct constraint **	hookp;
bitmap_t *		cut_edges;
double			z;

	nedges	= cip -> num_edges;
	nmasks	= cip -> num_edge_masks;

	cut_edges = NEWA (nmasks, bitmap_t);
	memset (cut_edges, 0, nmasks * sizeof (*cut_edges));

	count = 0;
	z = 0.0;
	for (i = 0; i < cip -> num_edges; i++) {
		if (NOT BITON (edge_mask, i)) continue;
		num_in_cut = 0;
		vp1 = cip -> edge [i];
		vp2 = cip -> edge [i + 1];
		while (vp1 < vp2) {
			j = *vp1++;
			if (BITON (cutset, j)) {
				++num_in_cut;
			}
		}
		if (num_in_cut <= 0) {
			/* this hyperedge resides entirely	*/
			/* outside of the cut...  doesn't span!	*/
			continue;
		}
		if (num_in_cut >= cip -> edge_size [i]) {
			/* this hyperedge resides entirely	*/
			/* within the cut...  doesn't span!	*/
			continue;
		}
		SETBIT (cut_edges, i);
		++count;
		z += x [i];
	}

	/* Check for an all-zero cutset.  These occasionally	*/
	/* happen because of numeric issues...			*/

	if (count <= 0) {
		/* Empty cutset!  OOOPS! */
#if 1
		tracef (" %% WARNING!  empty cutset!\n");
#endif
		free ((char *) cut_edges);
		return (cutlist);
	}

	if (z >= 1.0 - FUZZ) {
#if 1
		tracef (" %% WARNING!  bogus cutset!\n");
#endif
		free ((char *) cut_edges);
		return (cutlist);
	}

	/* If this new cutset is a superset of an existing one,	*/
	/* then there is nothing to add, and nothing to delete.	*/
	for (p = cutlist; p NE NULL; p = p -> next) {
		if (is_subset (p -> mask, cut_edges, nmasks)) {
			free (cut_edges);
			return (cutlist);
		}
	}

	/* Delete all current cutsets which have this new one	*/
	/* as a subset.						*/
	hookp = &cutlist;
	while ((p = *hookp) NE NULL) {
		if (p -> type NE CT_CUTSET) {
			hookp = &(p -> next);
		}
		else if (is_subset (cut_edges, p -> mask, nmasks)) {
			*hookp = p -> next;
			free ((char *) (p -> mask));
			free ((char *) p);
		}
		else {
			hookp = &(p -> next);
		}
	}

	p = NEW (struct constraint);
	p -> next	= NULL;
	p -> iteration	= 0;
	p -> type	= CT_CUTSET;
	p -> mask	= cut_edges;
	*hookp = p;

	return (cutlist);
}

/*
 * This routine returns TRUE if-and-only-if the first bit-mask is
 * a subset of the second.
 */

	static
	bool
is_subset (

bitmap_t *	bp1,		/* IN - first set. */
bitmap_t *	bp2,		/* IN - second set. */
int		nmasks		/* IN - number of masks in set. */
)
{
int		i;

	for (i = 0; i < nmasks; i++) {
		if ((*bp1 & *bp2) NE *bp1) return (FALSE);
		++bp1;
		++bp2;
	}

	return (TRUE);
}