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

📄 prunefst.c

📁 生成直角Steiner树的程序包
💻 C
📖 第 1 页 / 共 4 页
字号:
/***********************************************************************	File:	prunefst.c	Rev:	a-1	Date:	11/22/2000	Copyright (c) 2000, 2001 by Martin Zachariasen & David M. Warme************************************************************************	Pruning of Euclidean and rectilinear FSTs using method	originally proposed by Fossmeier & Kaufmann.	Use implementation similar to the one suggested by Althaus,	but with significant improvements in the compatibility tests.************************************************************************	Modification Log:	a-1:	11/22/2000	martinz		: Created.************************************************************************/#include "bb.h"#include "bsd.h"#include "btsearch.h"#include "dsuf.h"#include "efuncs.h"#include "emptyr.h"#include "p1io.h"#include "steiner.h"/* * Global Routines */int			main (int, char **);/* * External References */	/* none *//* * Local Macros */#ifndef MIN #define MIN(a,b)	(((a) < (b)) ? (a) : (b))#endif#ifndef MAX #define MAX(a,b)	(((a) > (b)) ? (a) : (b))#endif/* * Local Types */struct pg_edge {	dist_t				len; /* Length of edge */	int				fst; /* Corresponding FST */	int				p1;  /* First vertex */	int				p2;  /* Second vertex */};struct clt_info {	dist_t				dist;	int				term;	int				aterm1;	int				aterm2;};struct pinfo {	struct cinfo *			cip;	int				num_pg_edges;	int				num_pg_verts;	struct pg_edge *		pg_edges;	int *				steiner_index;	struct clt_info **		clt_info;	int *				clt_count;	bitmap_t *			compat_mask;	double				eps;};struct incompat {	struct incompat *		next;	int				fst;};struct bc3 {	struct cinfo *	cip;		/* problem data */	int		kmasks;		/* size of vert_mask */	int		nmasks;		/* size of edge_mask */	int *		dfs;		/* DFS number of each vertex */	int *		low;		/* lowest DFS num in component */	int *		parent;		/* parents of vertices in DFS tree */	int		max_stack;	/* size of stack */	int *		stack;		/* base-address of edge stack */	int *		sp;		/* current stack pointer */	int		counter;	/* DFS number generator */	bitmap_t *	bcc_vmask;	/* scratch buffer for new BCCs */	bitmap_t *	bcc_emask;	/* scratch buffer for new BCCs */	bitmap_t *	edges_seen;	/* edges already pushed */	int *		bcc_vlist;	/* scratch vertex list buffer */	int *		degree;		/* temp vertex degree counter */	int *		made_req;	/* caller's list of required edges */	int		req_count;	/* cur index into made-req */};/* * Local Routines */static void		add_incompat (struct incompat **, int, int, int *);static int		bcc_find_required (struct cinfo *, int *, int);static void		bcc3 (struct bc3 *, int);static int		comp_ints (const void *, const void *);static int		comp_pg_edges (const void *, const void *);static int		comp_clt (const void *, const void *);static void		compute_incompatibility_info (struct pinfo *, struct bsd *);static void		compute_pruning_info (struct cinfo *, struct pinfo *);static void		convert_delta_cpu_time (char *);static void		decode_params (int, char**);static cpu_time_t	get_delta_cpu_time (void);static bool		passes_upper_bound_tests (struct pinfo *, struct bsd *, int, int,						  struct pset *, bitmap_t *, int *, bitmap_t *);static void		process_bcc3 (struct bc3 *, int *, int *);static void		prune_fsts(struct cinfo *, struct bsd *, double);static bool		prune_this_fst (struct cinfo *, struct pinfo *, int);static dist_t		terminal_edge_distance(struct cinfo *, struct point *,						struct point *, struct point *,						struct point *,						dist_t *, dist_t *);static void		test_close_terminal (struct pinfo *,					     int, int, struct clt_info **);static void		usage ();static void		zap_deleted_fsts(struct cinfo *);/* * Local Variables */static char *		description = NULL;static int		EpsilonFactor = 32;static char *		me;static int		output_version = CURRENT_P1IO_VERSION;static bool		Print_Detailed_Timings = FALSE;static cpu_time_t	T0;static cpu_time_t	Tn;/* * Function Prototypes. */extern int		bmst (struct pset *, struct bsd *, struct edge *);extern dist_t		smith_lee_liebman(struct pset *);extern dist_t		greedy_heuristic(struct pset *, struct bsd *);/* * The main routine for the "prunefst" program.	 It takes the output from * the Euclidean or rectilinear FST generator, prunes FSTs that cannot * appear in an optimal solution and outputs the pruned set of FSTs * to the backend (FST concatenation procedure). */	intmain (int		argc,char **		argv){int			nedges;int			fpsave;char			buf1 [32];struct cinfo		cinfo;struct bsd *		bsd;struct edge *		mst_edges;cpu_time_t		Tzap;bitmap_t *		empty_rect;double			eps;	fpsave = set_floating_point_double_precision ();	setbuf (stdout, NULL);	decode_params (argc, argv);	init_tables ();	/* Read FST data */	read_phase_1_data (&cinfo);	if ((cinfo.metric NE RECTILINEAR) AND (cinfo.metric NE EUCLIDEAN)) {		fprintf (stderr, "Can only prune geometric (Euclidean or rectilinear) FSTs\n");		exit (1);	}	startup_lp_solver ();	initialize_btsearch ();	T0 = get_cpu_time ();	Tn = T0;	/* Compute minimum spanning tree */	mst_edges = NEWA (cinfo.pts -> n, struct edge);	eps = 0.0;	nedges	  = 0;	if (cinfo.metric EQ EUCLIDEAN) {		eps	= ((double) EpsilonFactor) * DBL_EPSILON;		nedges	= euclidean_mst (cinfo.pts, mst_edges);	}	else if (cinfo.metric EQ RECTILINEAR) {		empty_rect = init_empty_rectangles (cinfo.pts, NULL);		nedges	   = rect_mst (cinfo.pts, mst_edges, empty_rect);		free ((char *) empty_rect);	}	if (nedges NE cinfo.pts -> n - 1) {		fatal ("prunefst: bug 1.");	}	if (Print_Detailed_Timings) {		convert_delta_cpu_time (buf1);		fprintf (stderr, "Compute MST:            %s\n", buf1);	}	/* Compute bottleneck Steiner distances */	bsd = compute_bsd (nedges, mst_edges, 0);	free ((char *) mst_edges);	if (Print_Detailed_Timings) {		convert_delta_cpu_time (buf1);		fprintf (stderr, "Compute BSD:            %s\n", buf1);	}	/* Prune FSTs */	prune_fsts (&cinfo, bsd, eps);	if (Print_Detailed_Timings) {		convert_delta_cpu_time (buf1);		fprintf (stderr, "Pruning FSTs:           %s\n", buf1);	}	/* Remove deleted FSTs permanently */	zap_deleted_fsts (&cinfo);	/* Measure zap time.  This also sets Tn so that Tn-T0 is   */	/* the total processing time.				   */	Tzap = get_delta_cpu_time ();	if (Print_Detailed_Timings) {		convert_cpu_time (Tzap, buf1);		fprintf (stderr, "Zap deleted FSTs:       %s\n", buf1);		convert_cpu_time (Tn - T0, buf1);		fprintf (stderr, "Total:                  %s\n", buf1);	}	cinfo.p1time += (Tn - T0);	if (description NE NULL) {		free ((char *) cinfo.description);		cinfo.description = gst_strdup (description);	}	/* Print pruned FST data */	print_phase_1_data (&cinfo, output_version);	shutdown_bsd (bsd);	shutdown_lp_solver ();	free_phase_1_data (&cinfo);	restore_floating_point_precision (fpsave);	exit (0);}/* * This routine decodes the various command-line arguments. */	static	voiddecode_params (int		argc,char **		argv){char *		ap;char		c;	--argc;	me = *argv++;	while (argc > 0) {		ap = *argv++;		if (*ap NE '-') {			usage ();		}		++ap;		while ((c = *ap++) NE '\0') {			switch (c) {			case 'd':				if (*ap EQ '\0') {					if (argc <= 0) {						usage ();					}					ap = *argv++;					--argc;				}				if (strlen (ap) >= 80) {					fprintf (stderr,						"Description must be less"						" than 80 characters.\n");					usage ();				}				description = ap;				/* Change newlines to spaces... */				for (;;) {					ap = strchr (ap, '\n');					if (ap EQ NULL) break;					*ap++ = ' ';				}				ap = "";				break;			case 'f':				/* Epsilon multiplication factor */				if (*ap EQ '\0') {					if (argc <= 0) {						usage ();					}					ap = *argv++;					--argc;				}				EpsilonFactor = atoi (ap);				ap = "";				break;			case 't':				Print_Detailed_Timings = TRUE;				break;			default:				usage ();				break;			}		}		--argc;	}}/* * This routine prints out the proper usage and exits. */static char *	arg_doc [] = {	"",	"\t-d txt\tDescription of problem instance.",	"\t-f F\tEpsilon multiplication factor F for floating point number",	"\t\tcomparisons (default: 32).",	"\t-t\tPrint detailed timings on stderr.",	"",	NULL};	static	voidusage (void){char **		pp;char *		p;	(void) fprintf (stderr,			"\nUsage: %s [-t] [-d description] [-f F]",			me);	pp = &arg_doc [0];	while ((p = *pp++) NE NULL) {		(void) fprintf (stderr, "%s\n", p);	}	exit (1);}/* * Main pruning procedure. We use a method proposed by Fossmeier and Kaufmann * based on thesing whether is advantageous to extend a given FST with a * terminal no currently spanned. If so, the FST is discarded. */	static	voidprune_fsts (struct cinfo *		cip,	/* IN/OUT - compatibility info */struct bsd *		bsd,	/* IN	  - BSD data structure	*/double			eps	/* IN	  - epsilon value */){int			i, j, t, r1, r2;int			tcomp;int			fsave;int			pruned_total;int			required_total;int			old_pruned_total;int			scan;int			nverts;int			kmasks;int			nedges;int			nmasks;int			adj_edge;int			del_comps_count;int *			ep1;int *			ep2;int *			vp;int *			vp1;int *			vp2;int *			comps_edge;int *			made_req;int			req_count;bool			first_2edge;bool			this_2edge;struct dsuf		comps;struct dsuf		del_comps;struct pinfo		pinfo;struct pset *		ltlist;bitmap_t *		ltmask;int *			lflist;bitmap_t *		lfmask;	nverts = cip -> num_verts;	kmasks = cip -> num_vert_masks;	nmasks = cip -> num_edge_masks;	nedges = cip -> num_edges;	pinfo.cip = cip;	pinfo.eps = eps;	pinfo.compat_mask = NEWA (nmasks, bitmap_t);	memset (pinfo.compat_mask, 0, nmasks * sizeof (bitmap_t));	/* The following are only used for calling upper bound procedure */	ltlist	  = NEW_PSET (nverts);	ltmask	  = NEWA (kmasks, bitmap_t);	lflist	  = NEWA (nedges, int);	lfmask	  = NEWA (nmasks, bitmap_t);	/* Initialize masks */	for (i = 0; i < kmasks; i++) {		ltmask [i] = 0;	}	for (i = 0; i < nmasks; i++) {		lfmask [i] = 0;	}	/* Perform thorough upper bound test for every not-yet pruned FST */	pruned_total = 0;	for (i = 0; i < nedges; i++) {		if (BITON (cip -> initial_edge_mask, i)) {			if (NOT passes_upper_bound_tests (&pinfo, bsd, i, -1,							  ltlist, ltmask, lflist, lfmask)) {				CLRBIT (cip -> initial_edge_mask, i);				pruned_total++;			}			else {				SETBIT (pinfo.compat_mask, i);			}		}		else {			pruned_total++;		}	}	/* Compute basic compatibility */	/* CHANGE: USE COMP INFO THAT IS ALREADY THERE? */	compute_incompatibility_info (&pinfo, bsd);	/* Compute pruning information */	compute_pruning_info(cip, &pinfo);	/* Build union-find structure */	dsuf_create (&comps, cip -> num_verts);	for (t = 0; t < cip -> num_verts; t++) {		dsuf_makeset (&comps, t);	}	comps_edge = NEWA (cip -> num_verts, int);	made_req   = NEWA (nedges, int);	/* Perform actual pruning */	if (Print_Detailed_Timings) {		fprintf(stderr, "- scan 0 finished. %6d FSTs pruned\n", pruned_total);	}	required_total = 0;	for (scan = 1; scan < nedges; scan++) {		old_pruned_total   = pruned_total;		for (i = 0; i < nedges; i++) {			if ((BITON (cip -> initial_edge_mask, i)) AND			   (NOT BITON (cip -> required_edges, i))) {				/* Set up mask of compatible FSTs */				ep1 = cip -> inc_edges [i];				ep2 = cip -> inc_edges [i + 1];				while (ep1 < ep2) {					j = *ep1++;					CLRBIT (pinfo.compat_mask, j);				}				/* Test if FST can be pruned */				if (prune_this_fst(cip, &pinfo, i)) {					CLRBIT (cip -> initial_edge_mask, i);					CLRBIT (pinfo.compat_mask, i);					pruned_total++;				}				/* Reset mask */				ep1 = cip -> inc_edges [i];				while (ep1 < ep2) {					j = *ep1++;					if (BITON (cip -> initial_edge_mask, j))						SETBIT (pinfo.compat_mask, j);				}			}		}		/* Test if any connected component (initially one		   for each terminal) only has one adjacent FST */	try_again:		req_count = 0;		for (t = 0; t < cip -> num_verts; t++) {			comps_edge [t] = -1;		}		/* First find the number of adjacent FSTs... */		for (t = 0; t < cip -> num_verts; t++) {			tcomp = dsuf_find (&comps, t); /* t's component */			if (comps_edge [tcomp] EQ -2) continue;			ep1 = cip -> term_trees [t];			ep2 = cip -> term_trees [t + 1];			while (ep1 < ep2) {				i = *ep1++;				if ((BITON (cip -> initial_edge_mask, i)) AND				    (NOT BITON (cip -> required_edges, i))) {					adj_edge = comps_edge [tcomp];					if (adj_edge EQ -2) break;					if (adj_edge EQ -1) {						/* First FST */						comps_edge [tcomp] = i;					}					else {						/* Second (or more) FST */						first_2edge = (cip -> edge_size [adj_edge] EQ 2);						this_2edge  = (cip -> edge_size [i] EQ 2);						/* If all adjacent edges have been 2-edges, */						/* then pick the shortest (if equal then take edge */						/* with minimum index) */						if (first_2edge AND this_2edge) {							if ((cip -> cost [i] < cip -> cost [adj_edge]) OR							    ((cip -> cost [i] EQ cip -> cost [adj_edge]) AND							     (i < adj_edge))) {								comps_edge [tcomp] = i;							}						}						else {							comps_edge [tcomp] = -2; break;						}					}				}			}		}		/* ... then check the counts */		for (t = 0; t < cip -> num_verts; t++) {			fsave = comps_edge [t];			if ((fsave >= 0) AND

⌨️ 快捷键说明

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