⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sec_comp.c

📁 生成直角Steiner树的程序包
💻 C
📖 第 1 页 / 共 4 页
字号:
/***********************************************************************	File:	sec_comp.c	Rev:	b-1	Date:	02/28/2001	Copyright (c) 1996, 2001 by David M. Warme************************************************************************	Routines to decompose SEC separation problems into smaller	and simpler sub-problems.************************************************************************	Modification Log:	a-1:	10/05/96	warme		: Created.	b-1:	02/28/2001	warme		: Changes for 3.1 release.		: Rename many fields in "struct comp".		: Fix incorrect BCC routine.		: Use consistent terminology: prefer "vertex" to		:  "terminal" and "edge" to "full set".		: Use rverts instead of tmasks.		: Completely re-write of merge_chains routine.		: Fix incomplete reduction bug.************************************************************************/#include "bb.h"#include "constrnt.h"#include "dsuf.h"#include "genps.h"#include "sec_comp.h"#include "sec_heur.h"#include "steiner.h"/* * Global Routines */struct constraint *	check_component_subtour (bitmap_t *,						 struct comp *,						 struct constraint *,						 double *,						 bitmap_t *,						 struct bbinfo *);struct comp *	delete_vertex_from_component (int, struct comp *);struct comp *	find_congested_components (double *,					   bitmap_t *,					   bitmap_t *,					   bool,					   struct cinfo *);int		find_least_congested_vertex (bitmap_t *, struct comp *);void		free_congested_component (struct comp *);/* * External References */	/* None *//* * Local Types */struct bc {	struct comp *	comp;		/* component being split */	struct comp *	list;		/* output list of BCC's */	int *		dfs;		/* DFS number of each vertex */	int *		low;		/* lowest DFS num in component */	int *		parent;		/* parents of vertices in DFS tree */	int *		stack;		/* base-address of edge stack */	int *		sp;		/* current stack pointer */	int		counter;	/* DFS number generator */	bitmap_t *	vert_mask;	/* scratch buffer for new components */	bitmap_t *	edge_mask;	/* scratch buffer for new components */	bitmap_t *	edges_seen;	/* edges already pushed */	int		nvmasks;	/* size of vert_mask */	int		nemasks;	/* size of edge_mask */	int		ncomps;		/* number of BCC's split off */	int		max_stack;	/* size of stack */};/* * Local Routines */static struct constraint * add_component_subtour (struct comp *,						  double *,						  bitmap_t *,						  struct cinfo *,						  struct constraint *,						  bitmap_t *);static void		bcc (struct bc *, int);static void		component_verts_to_real_verts (bitmap_t *,						       struct comp *,						       bitmap_t *,						       int);static struct comp *	copy_subcomponent (struct comp *,					   bitmap_t *,					   bitmap_t *);static void		create_masks (struct comp *);static struct comp *	find_first_component (double *,					      bitmap_t *,					      bitmap_t *,					      struct cinfo *);static void		merge_chains (struct comp *);static void		reduce_component_in_place (struct comp *);static struct comp *	simplify_one_component (struct comp *);static struct comp *	split_biconnected_components (struct comp *);static void		split_connected_components (struct comp *);static void		strip_uncongested_vertices (struct comp *);static int		vacuous_component (struct comp *);/* * Compute the smallest possible subsets of the problem on which to * run the SEC separation routines.  We use the following principles * to prune down the vertices and edges examined: * *	- Let S be a set of vertices that define a violated SEC.  Let *	  t be a vertex in S with delta(t) <= 1.  Then there is a *	  subset S' of S that does not contain t, yet still defines a *	  violated SEC.  Therefore, all such vertices t can be *	  iteratively removed from consideration.  (Such vertices are *	  NOT "congested".) * *	- Let the hypergraph of vertices and edges be partitioned *	  into its connected components C1 = (V1,F1), C2 = (V2,F2), ..., *	  Ck = (Vk,Fk).  Let S be any violated SEC.  Then there is at *	  least one i in 1..k for which Si (a subset of *	  [Vi \intersect S]) is a violated SEC. * *	- [Same, but with C1, C2, ..., Ck being biconnected components.] * *	- Let F1 be an edge containing exactly two congested vertices *	  s and t.  Let S be an SEC violation containing s and t.  Define *	  a new hypergraph C' = (V - {s,t} + {u}, F') where u is a new *	  vertex not in V, and F' is derived from F by replacing every *	  reference to s or t with u.  [Resulting edges with fewer than *	  2 distinct vertices are deleted from F'.]  Let S be a *	  violation in C.  Then S' = S - {s,t} + ({u} if s in S or t in S) *	  defines a violation in C'. * * These rules may be applied recursively to arrive at a final set of * congested components that are each usually quit small. */	struct comp *find_congested_components (double *		x,		/* IN - current LP solution */bitmap_t *		vert_mask,	/* IN - set of valid vertices */bitmap_t *		edge_mask,	/* IN - set of valid hyperedges */bool			print_flag,	/* IN - TRUE ==> print info */struct cinfo *		cip		/* IN - compatibility info */){int			i;int			j;int			k;int			n;struct comp *		comp;struct comp *		p;bitmap_t *		bp1;	/* Find the first component by iteratively applying the	*/	/* delta(t) <= 1 rule...				*/	comp = find_first_component (x, vert_mask, edge_mask, cip);	if (comp EQ NULL) return (NULL);	if (print_flag) {		tracef (" %% initially %d congested vertices:\n",			comp -> num_verts);#if 0		k = 0;		for (i = 0; i < comp -> num_verts; i++) {			int * vp1 = comp -> rverts [i];			int * vp2 = comp -> rverts [i + 1];			while (vp1 < vp2) {				j = *vp1++;				if (k EQ 0) {					tracef (" %%	");				}				tracef (" %3d", j);				++k;				if (k >= 16) {					tracef ("\n");					k = 0;				}			}		}		if (k > 0) {			tracef ("\n");		}#endif	}	comp = simplify_one_component (comp);	if (print_flag) {		n = 0;		for (p = comp; p NE NULL; p = p -> next) {			++n;		}		tracef (" %% find_congested_components found %d components:\n",			n);		n = 0;		for (p = comp; p NE NULL; p = p -> next) {			tracef (" %%\tcomponent %d:\t%d verts,\t%d edges\n",				n++, p -> num_verts, p -> num_edges);#if 0			tracef (" %%\t   ");			for (i = 0; i < p -> num_verts; i++) {				int * vp1 = p -> rverts [i];				int * vp2 = p -> rverts [i + 1];				int k = (vp2 - vp1);				if (k NE 1) {					tracef (" {");				}				while (vp1 < vp2) {					j = *vp1++;					tracef (" %d", j);				}				if (k NE 1) {					tracef ("}");				}			}			tracef ("\n");#endif		}	}	return (comp);}/* * This routine finds the initial component by iteratively applying * the delta(t) <= 1 rule.  This normally shrinks the problem down * substantially.  We then convert the problem into "struct comp" * form -- after which we no longer need to refer to the cinfo stuff. */	static	struct comp *find_first_component (double *		x,		/* IN - current LP solution */bitmap_t *		vert_mask,	/* IN - set of valid vertices */bitmap_t *		edge_mask,	/* IN - set of valid hyperedges */struct cinfo *		cip		/* IN - compatibility info */){int			i;int			j;int			k;int			e;int			t;int			nedges;int			nverts;int			nmasks;int			kmasks;int			ecount;int			vcount;int *			vp1;int *			vp2;int *			vp3;int *			ep1;int *			ep2;int *			ep3;double			sum;bool			changed;int *			vleft;int *			sp;int *			new_vnum;int *			new_enum;int *			old_enum;int *			ip1;struct comp *		newp;bitmap_t *		bp1;bitmap_t *		bp2;bitmap_t *		bp3;bitmap_t *		bp4;bitmap_t *		verts_stacked;bitmap_t *		cvmask;int *			stack;double *		B;	nedges = cip -> num_edges;	nverts = cip -> num_verts;	nmasks = cip -> num_edge_masks;	kmasks = cip -> num_vert_masks;	verts_stacked = NEWA (2 * kmasks, bitmap_t);	cvmask	      = verts_stacked + kmasks;	for (i = 0; i < kmasks; i++) {		verts_stacked [i] = 0;	}	/* Compute "vleft" for each valid hyperedge having non-zero	*/	/* weight.  vleft is 1 less than the number of valid vertices	*/	/* in the hyperedge.  We decrement vleft every time we delete a	*/	/* vertex from the hyperedge.  When this count goes to zero, we	*/	/* can delete the hyperedge.  Also count the valid hyperedges	*/	/* with non-zero weight.					*/	vleft = NEWA (nedges, int);	ecount = 0;	for (i = 0; i < nedges; i++) {		vleft [i] = 0;		if (BITON (edge_mask, i) AND (x [i] > FUZZ)) {			k = 0;			vp1 = cip -> edge [i];			vp2 = cip -> edge [i + 1];			while (vp1 < vp2) {				j = *vp1++;				if (BITON (vert_mask, j)) {					++k;				}			}			if (k >= 2) {				vleft [i] = k - 1;				++ecount;			}		}	}	/* Compute the congestion level Bi of each vertex i. */	stack = NEWA (nverts, int);	B = NEWA (nverts, double);	sp = &stack [0];	vcount = 0;	for (i = 0; i < nverts; i++) {		sum = 0.0;		if (BITON (vert_mask, i)) {			++vcount;			ep1 = cip -> term_trees [i];			ep2 = cip -> term_trees [i + 1];			while (ep1 < ep2) {				e = *ep1++;				if (vleft [e] > 0) {					sum += x [e];				}			}		}		B [i] = sum;	}	/* Add every vertex with weight <= 1 to a list of vertices	*/	/* to be deleted...						*/	for (i = 0; i < nverts; i++) {		if (NOT BITON (vert_mask, i)) {			/* Pretend this vertex has already been	*/			/* stacked and deleted (already has weight 0).	*/			SETBIT (verts_stacked, i);		}		else if (B [i] <= (1.0 + FUZZ)) {			/* Schedule this vertex for deletion! */			*sp++ = i;			SETBIT (verts_stacked, i);		}	}	/* Iteratively pop and delete vertices until stack is empty.	*/	while (sp > stack) {		t = *--sp;		/* Prune vertex "t" from the remaining structure... */		--vcount;		B [t] = 0.0;		/* Drop one vertex from every remaining edge that	*/		/* contains vertex "t"...				*/		ep1 = cip -> term_trees [t];		ep2 = cip -> term_trees [t + 1];		while (ep1 < ep2) {			e = *ep1++;			if (vleft [e] <= 0) continue;			--(vleft [e]);			if (vleft [e] > 0) continue;			/* Count for this hyperedge has now gone to	*/			/* zero, so we can delete it.  Find the edge's	*/			/* one remaining vertex j and subtract edge e's	*/			/* weight from Bj.				*/			--ecount;			vp1 = cip -> edge [e];			vp2 = cip -> edge [e + 1];			for (;;) {				if (vp1 >= vp2) {					fatal ("find_first_component: Bug 1.");				}				j = *vp1++;				if (B [j] > FUZZ) break;			}			B [j] -= x [e];			if ((B [j] <= 1.0 + FUZZ) AND			    (NOT BITON (verts_stacked, j))) {				/* Schedule this vertex for deletion... */				*sp++ = j;				SETBIT (verts_stacked, j);			}		}	}	/* Construct a mask of the vertices that are left (the	*/	/* congested vertices).					*/	bp1 = cvmask;	bp2 = bp1 + kmasks;	bp3 = vert_mask;	bp4 = verts_stacked;	while (bp1 < bp2) {		*bp1++ = (*bp3++ & ~(*bp4++));	}	if ((vcount EQ 0) OR (ecount EQ 0)) {		/* Nothing congested left... no components! */		free ((char *) B);		free ((char *) stack);		free ((char *) vleft);		free ((char *) verts_stacked);		return (NULL);	}	/* Now construct the component for what's left... */	newp = NEW (struct comp);	newp -> next		= NULL;	newp -> num_verts	= vcount;	newp -> num_edges	= ecount;	newp -> flags		= CFLG_CONG;	newp -> x		= NEWA (ecount, double);	newp -> everts		= NEWA (ecount + 1, int *);	newp -> vedges		= NEWA (vcount + 1, int *);	newp -> tviol		= NEWA (vcount, double);	newp -> rverts		= NEWA (vcount + 1, int *);	newp -> vert_mask	= NULL;	newp -> edge_mask	= NULL;	newp -> cp		= NULL;	new_vnum = NEWA (nverts, int);	for (i = 0; i < nverts; i++) {		new_vnum [i] = -1;	}	ip1 = NEWA (vcount, int);	k = 0;	for (i = 0; i < nverts; i++) {		if (NOT BITON (cvmask, i)) continue;		/* This vertex was retained... */		new_vnum [i] = k;		newp -> tviol [k] = 0.0;		newp -> rverts [k] = ip1;		*ip1++ = i;		++k;	}	newp -> rverts [k] = ip1;	if (k NE vcount) {		fatal ("find_first_component: Bug 2.");	}	old_enum = NEWA (nedges, int);	new_enum = NEWA (nedges, int);	for (i = 0; i < nedges; i++) {		new_enum [i] = -1;	}	/* Construct hyperedge info, including edge -> vertices map. */	j = 0;	k = 0;	for (i = 0; i < nedges; i++) {		if (vleft [i] < 1) continue;		new_enum [i] = j;		old_enum [j] = i;		newp -> x [j]	= x [i];		k += (1 + vleft [i]);		++j;	}	if (j NE ecount) {		fatal ("find_first_component: Bug 3.");	}	vp3 = NEWA (k, int);	ep3 = NEWA (k, int);	for (j = 0; j < ecount; j++) {		newp -> everts [j] = vp3;		i = old_enum [j];		vp1 = cip -> edge [i];		vp2 = cip -> edge [i + 1];		while (vp1 < vp2) {			t = *vp1++;			if (NOT BITON (cvmask, t)) continue;			t = new_vnum [t];			if (t < 0) {				fatal ("find_first_component: Bug 4.");			}			*vp3++ = t;		}	}	newp -> everts [ecount] = vp3;	if (vp3 NE newp -> everts [0] + k) {		fatal ("find_first_component: Bug 5.");	}	for (i = 0; i < nverts; i++) {		j = new_vnum [i];		if (j < 0) continue;		newp -> vedges [j] = ep3;		ep1 = cip -> term_trees [i];		ep2 = cip -> term_trees [i + 1];		while (ep1 < ep2) {			e = new_enum [*ep1++];			if (e >= 0) {				*ep3++ = e;			}		}	}	newp -> vedges [vcount] = ep3;	if (ep3 NE newp -> vedges [0] + k) {		fatal ("find_first_component: Bug 6.");	}	free ((char *) new_enum);	free ((char *) old_enum);	free ((char *) new_vnum);	free ((char *) B);	free ((char *) stack);	free ((char *) vleft);	free ((char *) verts_stacked);	return (newp);}/* * This routine simplifies a SINGLE COMPONENT, producing 0 or more * simplified components that are concatenated onto the front of the * successors that may follow the given component in the linked list. */	static	struct comp *simplify_one_component (struct comp *		comp		/* IN - component to simplify */){struct comp *		rest;struct comp *		p;struct comp *		temp;struct comp *		done;struct comp **		done_hookp;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -