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

📄 ub.c

📁 生成直角Steiner树的程序包
💻 C
📖 第 1 页 / 共 2 页
字号:
/***********************************************************************	File:	ub.c	Rev:	b-1	Date:	02/28/2001	Copyright (c) 1996, 2001 by David M. Warme************************************************************************	Heuristic for turning a fractional LP solution (a lower bound)	into a feasible Steiner tree (an upper bound).  If such a	Steiner tree can be found, and is the best seen so far, it	becomes the new best feasible integer solution.************************************************************************	Modification Log:	a-1:	07/17/96	warme		: Created.	a-2:	09/06/97	warme		: Completely replaced this algorithm with a new one		:  suggested by Martin Zachariasen.	b-1:	02/28/2001	warme		: Changes for 3.1 release.		: Major upgrades to the upper bound heuristic.		: Support multiple rankings.		: Add Martins latest tweaks:		:   Now doing diversification, a number of techniques		:    are supported, including greedy local search (the		:    default).		:   Intensify search if getting close to best known		:    solution.************************************************************************/#include "bb.h"#include "dsuf.h"#include "steiner.h"#include "ub.h"/* * Global Routines */void			compute_heuristic_upper_bound (double *,						       struct bbinfo *);void			shutdown_heuristic_upper_bound (struct ubinfo *);struct ubinfo *		startup_heuristic_upper_bound (struct cinfo *);/* * External References */	/* none *//* * Local Routines */static int *		compute_FST_ranking (int, dist_t *, dist_t *);static void		sort_fst_list_by_lp_and_rank (int *,						      int,						      double *,						      int *);static void		sort_fst_list_by_rank (int *, int, int *);static int *		sorted_mst_edges (struct cinfo *);static void		try_trees (int *, int, struct bbinfo *);static dist_t		ub_kruskal (int *, int, bitmap_t *, struct bbinfo *);/* * This routine pre-computes some useful information for the upper * bound heuristic: * *	- A set of rankings, each of which establishes a total ordering *	  of the FSTs. * *	- The list of all MST edges, in increasing order by length. */	struct ubinfo *startup_heuristic_upper_bound (struct cinfo *		cip		/* IN - compatibility info */){int			i;int			nranks;int			n;int *			ranking;struct ubinfo *		ubip;struct pset *		terms;dist_t *		fst_len;dist_t *		mst_len;	ubip = NEW (struct ubinfo);	n = cip -> num_edges;	fst_len = NEWA (n, dist_t);	mst_len = NEWA (n, dist_t);	/* Get FST lengths into an array... */	for (i = 0; i < n; i++) {		fst_len [i] = cip -> cost [i];	}	/* No rankings yet... */	nranks = 0;	/* Compute MST length of each FST... */	if ((cip -> metric EQ EUCLIDEAN) AND	    (cip -> full_trees NE NULL)) {		for (i = 0; i < n; i++) {			terms = cip -> full_trees [i] -> terminals;			mst_len [i] = euclidean_mst_length (terms);		}		ranking = compute_FST_ranking (n, fst_len, mst_len);		ubip -> rankings [nranks++] = ranking;	}	else if ((cip -> metric EQ RECTILINEAR) AND		 (cip -> full_trees NE NULL)) {		for (i = 0; i < n; i++) {			terms = cip -> full_trees [i] -> terminals;			mst_len [i] = rect_mst_length (terms);		}		ranking = compute_FST_ranking (n, fst_len, mst_len);		ubip -> rankings [nranks++] = ranking;	}	/* Pretend each edge in the MST has length 1... */	for (i = 0; i < n; i++) {		mst_len [i] = cip -> edge_size [i] - 1;	}	ranking = compute_FST_ranking (n, fst_len, mst_len);	ubip -> rankings [nranks++] = ranking;	ubip -> num_rankings = nranks;	ubip -> mst_edges = sorted_mst_edges (cip);	free ((char *) mst_len);	free ((char *) fst_len);	return (ubip);}/* * This routine produces a ranking of the given FSTs, sorted in increasing * order by the given (numerator / denominator) values. */	static	int *compute_FST_ranking (int			n,		/* IN - number of FSTs */dist_t *		num,		/* IN - numerator of values */dist_t *		den		/* IN - denominator of values */){int			i;int			h;int			t1;int			t2;int *			p1;int *			p2;int *			p3;int *			p4;int *			endp;int *			array;int *			ranking;dist_t			key1;dist_t			key2;dist_t			key3;dist_t			key4;	array = NEWA (n, int);	for (i = 0; i < n; i++) {		array [i] = i;	}	endp = &array [n];	for (h = 1; h <= n; h = 3*h+1) {	}	do {		h = h / 3;		p4 = &array [h];		p1 = p4;		while (p1 < endp) {			t1 = *p1;			key1 = num [t1];			key2 = den [t1];			p2 = p1;			while (TRUE) {				p3 = (p2 - h);				t2 = *p3;				key3 = num [t2];				key4 = den [t2];				if (key3 * key2 <= key1 * key4) break;				*p2 = t2;				p2 = p3;				if (p2 < p4) break;			}			*p2 = t1;			++p1;		}	} while (h > 1);	/* Produce array that ranks each FST... */	ranking = NEWA (n, int);	for (i = 0; i < n; i++) {		ranking [array [i]] = i;	}	free ((char *) array);	return (ranking);}/* * This routine finds all of the MST edges (edges of cardinality 2) and * sorts them in increasing order by length. */	static	int *sorted_mst_edges (struct cinfo *		cip		/* IN - compatibility info */){int			i;int			e;int			n;int			h;int			t1;int			t2;int *			mst_edges;int *			p1;int *			p2;int *			p3;int *			p4;int *			endp;dist_t			key1;struct dsuf		sets;	/* Count the cardinality 2 edges. */	n = 0;	for (i = 0; i < cip -> num_edges; i++) {		if (cip -> edge_size [i] EQ 2) {			++n;		}	}	if (n < cip -> num_verts - 1) {		fatal ("sorted_mst_edges: Bug 1.");	}	/* Get the cardinality 2 edges. */	mst_edges = NEWA (n, int);	n = 0;	p1 =  mst_edges;	for (i = 0; i < cip -> num_edges; i++) {		if (cip -> edge_size [i] EQ 2) {			*p1++ = i;			++n;		}	}	endp = &mst_edges [n];	for (h = 1; h <= n; h = 3*h+1) {	}	do {		h = h / 3;		p4 = &mst_edges [h];		p1 = p4;		while (p1 < endp) {			t1 = *p1;			key1 = cip -> cost [t1];			p2 = p1;			while (TRUE) {				p3 = (p2 - h);				t2 = *p3;				if (cip -> cost [t2] <= key1) break;				*p2 = t2;				p2 = p3;				if (p2 < p4) break;			}			*p2 = t1;			++p1;		}	} while (h > 1);	if (n >= cip -> num_verts) {		/* Remove all non-MST edges from the list. */		dsuf_create (&sets, cip -> num_verts);		for (i = 0; i < cip -> num_verts; i++) {			dsuf_makeset (&sets, i);		}		p1 = mst_edges;		for (i = 0; i < n; i++) {			e = mst_edges [i];			p2 = cip -> edge [e];			t1 = dsuf_find (&sets, p2 [0]);			t2 = dsuf_find (&sets, p2 [1]);			if (t1 NE t2) {				*p1++ = e;				dsuf_unite (&sets, t1, t2);			}		}		dsuf_destroy (&sets);		n = p1 - mst_edges;		if (n NE cip -> num_verts - 1) {			fatal ("sorted_mst_edges: Bug 2.");		}		/* Create a properly-sized copy of the edges. */		p1 = NEWA (n, int);		for (i = 0; i < n; i++) {			p1 [i] = mst_edges [i];		}		free ((char *) mst_edges);		mst_edges = p1;	}	return (mst_edges);}/* * Shut down the heuristic upper bound stuff.  Free its permanently * allocated memory. */	voidshutdown_heuristic_upper_bound (struct ubinfo *		ubip		/* IN - global upper bound data */){int			i;int *			ranking;	if (ubip EQ NULL) return;	for (i = 0; i < ubip -> num_rankings; i++) {		ranking = ubip -> rankings [i];		if (ranking NE NULL) {			free ((char *) ranking);		}	}	if (ubip -> mst_edges NE NULL) {		free ((char *) (ubip -> mst_edges));	}	free ((char *) ubip);}/* * This routine takes an existing LP solution (a fractional lower * bound for an optimal Steiner tree) and attempts to perturb it into * a feasible integer solution.  If this succeeds and we discover a * shorter solution than previously known, it becomes the current * best feasible integer solution.  Any existing nodes that exceed * this new upper bound are then cut off. * * We use a greedy heuristic: sort the valid hyperedges into decreasing * order by LP solution weight.  If two edges have the same LP solution * weight, the one with the smaller FST-length/MST-length ratio will be * placed first. * * Greedily add edges from this sorted list to an empty tree, discarding * any edge that would form a cycle.  This is just a variant of Kruskal's * algorithm for MST, extended for hypergraphs. * * The one real efficiency hack is that we use linear time to partition * the edges into those with weight 1, fractional weight, and weight 0. * We then sort each region independently. */	voidcompute_heuristic_upper_bound (double *		x,	/* IN - an LP solution to use */struct bbinfo *		bbip	/* IN - branch-and-bound info */){int			i;int			j;int			n;int			e;int			nverts;int			nedges;int			count_1;int			count_frac;int			count_0;int *			ep1;int *			ep2;int *			ep3;int *			edge_list;int *			temp_edges;int *			edges_1;int *			edges_frac;int *			edges_0;int *			ranking;struct ubinfo *		ubip;struct cinfo *		cip;	cip		= bbip -> cip;	ubip		= bbip -> ubip;	ubip -> best_z	= bbip -> best_z;	nverts		= cip -> num_verts;	nedges		= cip -> num_edges;	/* Generate the list of valid full sets... */	edge_list = NEWA (nedges, int);	/* Put edges of weight 0.0 last, all the rest at the front. */	ep1 = edge_list;	ep2 = edge_list + nedges;	for (i = 0; i < nedges; i++) {		if (x [i] <= FUZZ) {			*--ep2 = i;		}		else {			*ep1++ = i;		}	}	if (ep1 NE ep2) {		fatal ("compute_heuristic_upper_bound: Bug 1.");	}	edges_0 = ep2;	count_0 = nedges - (edges_0 - edge_list);	/* Now re-scan the non-zero edges, putting those of	*/	/* weight 1.0 first.					*/	ep1 = edge_list;	ep3 = ep2;	while (ep1 < ep2) {		/* Scan forward from beginning for a fractional edge. */		i = *ep1;		if (x [i] + FUZZ >= 1.0) {			++ep1;			continue;		}		/* i is a fractional edge.  Scan backward from end	*/		/* for an edge of weight 1.0.				*/		for (;;) {			--ep2;			if (ep1 >= ep2) break;			j = *ep2;			if (x [j] + FUZZ >= 1.0) {				/* i is fractional, j is integral -- swap. */				*ep1 = j;				*ep2 = i;				++ep1;				break;			}		}	}	if (ep1 NE ep2) {		fatal ("compute_heuristic_upper_bound: Bug 2.");	}	edges_1 = edge_list;	edges_frac = ep2;	count_1		= edges_frac - edges_1;	count_frac	= edges_0 - edges_frac;	temp_edges = NEWA (nedges, int);	/* Repeat the greedy heuristic once for each FST rank ordering. */	for (i = 0; i < ubip -> num_rankings; i++) {		ranking = ubip -> rankings [i];		/* Sort the integral FSTs by rank only. */		sort_fst_list_by_rank (edges_1, count_1, ranking);		/* Sort the fractional FSTs by LP weight, and then by rank. */		sort_fst_list_by_lp_and_rank (edges_frac,					      count_frac,					      x,

⌨️ 快捷键说明

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