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

📄 bb.c

📁 生成直角Steiner树的程序包
💻 C
📖 第 1 页 / 共 5 页
字号:
/***********************************************************************	File:	bb.c	Rev:	b-2	Date:	02/28/2001	Copyright (c) 1995, 2001 by David M. Warme************************************************************************	The guts of the branch-and-cut.************************************************************************	Modification Log:	a-1:	11/17/95	warme		: Created.	b-1:	11/14/96	warme		: Renamed this program.		: Split off the cutset stuff into another file.		: Other cleanups for release.	b-2:	02/28/2001	warme		: Numerous changes for 3.1 release.		: Split the main() routine off into bbmain.c.		: Split certain utility routines off into bbsubs.c.		: Major improvements to branch var selection.		: New create_bbinfo routine does setup for		:  branch_and_cut.		: Enable variable fixing code.************************************************************************/#include "bb.h"#include "bbsubs.h"#include "config.h"#include "constrnt.h"#include "cra.h"#include "cutset.h"#include "genps.h"#include "p1io.h"#include "sec2.h"#include "sec_comp.h"#include "sec_heur.h"#include "steiner.h"#include "ub.h"#include <signal.h>/* * Global Routines */dist_t			branch_and_cut (struct bbinfo *);bool			check_for_better_IFS (double *,					      struct bbinfo *,					      double *);struct bbinfo *		create_bbinfo (struct cinfo *);void			new_upper_bound (double, struct bbinfo *);int		Branch_Var_Policy = 1;int		Check_Branch_Vars_Thoroughly = 1;bool		Check_Root_Constraints = FALSE;bool		Choose_Branch_Vars_Carefully = TRUE;double		Initial_Upper_Bound = DBL_MAX;bool		Print_Root_LP = FALSE;volatile bool	force_branch_flag;/* * Local Equates */	/* Lower bound outcomes... */#define	LB_INFEASIBLE		1#define	LB_CUTOFF		2#define	LB_INTEGRAL		3#define	LB_FRACTIONAL		4#define LB_PREEMPTED		5	/* Variable fixing outcomes... */#define	VFIX_NOTHING_FIXED	0#define	VFIX_VARIABLES_FIXED	1#define	VFIX_FIXED_FRACTIONAL	2#define	VFIX_INFEASIBLE		3#define	UP_FIRST	TRUE/* * Local Types */struct bvar {			/* Info about best branch var seen */	int	var;		/* Best branch var, or -1 */	double	z0;		/* Objective when Xj=0 */	double	z1;		/* Objective when Xj=1 */	double	test_2nd_val;	/* Only check 2nd branch if 1st > this. */};#ifdef CPLEXstruct basis_save {	/* Structure to save basis state for CPLEX */	int *		cstat;	int *		rstat;};#endif/* * Local Routines */static int		carefully_choose_branching_variable (struct bbinfo *,							     double *,							     double *);static void		change_var_bounds (LP_t *, int, double, double);static void		check_root_constraints (struct bbinfo *);static int		choose_branching_variable (struct bbinfo *,						   double *,						   double *);static bool		compare_branch_vars (struct bbinfo *,					     int,					     struct bvar *);static int		compute_good_lower_bound (struct bbinfo *);static void		cut_off_existing_nodes (double, struct bbtree *);static struct constraint * do_separations (struct bbinfo *,					   cpu_time_t **);static bool		eval_branch_var (struct bbinfo *,					 int,					 int,					 struct basis_save *,					 double);static int		fix_variables (struct bbinfo *,				       int *, int,				       int *, int);static RETSIGTYPE	force_branch_signal_handler (int);static bool		integer_feasible_solution (double *,						   bitmap_t *,						   bitmap_t *,						   struct cinfo *,						   int *);static void		new_lower_bound (double, struct bbinfo *);static void		print_root_lp (struct bbinfo *);static int		reduced_cost_var_fixing (struct bbinfo *);static struct bbnode *	select_next_node (struct bbtree *);static void		sort_branching_vars (int *, int, double *);static void		trace_node (struct bbinfo *, char, char *);static void		update_node_preempt_value (struct bbinfo *);#ifdef CPLEXstatic void		destroy_LP_basis (struct basis_save *);static double		try_branch (LP_t *,				    int,				    int,				    double *,				    double,				    struct basis_save *);static void		save_LP_basis (LP_t *, struct basis_save *);#endif/* * Local Variables */static FILE *		rcfile;/* * Set up the initial branch-and-bound problem, including the root * node and the initial constraint pool. */	struct bbinfo *create_bbinfo (struct cinfo *		cip		/* IN - compatibility info */){struct bbinfo *		bbip;int			i;int			j;int			k;int			n;int			nmasks;int			nedges;LP_t *			lp;int			status;bitmap_t *		vert_mask;bitmap_t *		edge_mask;bitmap_t *		req_edges;bitmap_t *		fixed;bitmap_t *		value;bitmap_t *		smt;struct cpool *		cpool;struct bbstats *	statp;struct bbtree *		bbtree;struct bbnode *		root;struct lpmem *		lpmem;struct rcon *		rcp;	/* Create the global branch-and-bound info structure... */	bbip = NEW (struct bbinfo);	memset (bbip, 0, sizeof (*bbip));	bbip -> t0 = get_cpu_time ();	nmasks = cip -> num_edge_masks;	nedges = cip -> num_edges;	vert_mask	= cip -> initial_vert_mask;	edge_mask	= cip -> initial_edge_mask;	req_edges	= cip -> required_edges;	/* initialize global pool of constraints. */	cpool = NEW (struct cpool);	initialize_constraint_pool (cpool, vert_mask, edge_mask, cip);	/* Build initial formulation. */	lpmem = NEW (struct lpmem);	lp = build_initial_formulation (cpool,					vert_mask,					edge_mask,					cip,					lpmem);	/* Initialize the branch-and-bound tree... */	bbtree = create_bbtree (nmasks);	/* Create vectors to describe the current problem... */	fixed	= NEWA (nmasks, bitmap_t);	value	= NEWA (nmasks, bitmap_t);	smt	= NEWA (nmasks, bitmap_t);	for (i = 0; i < nmasks; i++) {		fixed [i] = 0;		value [i] = 0;		smt [i]	  = 0;	}	for (i = 0; i < nedges; i++) {		if (NOT BITON (edge_mask, i)) {			/* variables that are outside of the problem */			/* are fixed at zero... */			SETBIT (fixed, i);			change_var_bounds (lp, i, 0.0, 0.0);		}		else if (BITON (req_edges, i)) {			/* Front-end has determined that this hyperedge	*/			/* MUST be present in an optimal solution!	*/			SETBIT (fixed, i);			SETBIT (value, i);			change_var_bounds (lp, i, 1.0, 1.0);		}	}	/* Create the root node... */	root = NEW (struct bbnode);	memset (root, 0, sizeof (*root));	root -> z	= -DBL_MAX;	root -> optimal	= FALSE;	root -> num	= (bbtree -> snum)++;	root -> iter	= 0;	root -> parent	= -1;	for (i = 0; i < NUM_BB_HEAPS; i++) {		root -> index [i] = -1;	}	root -> var	= -1;	root -> dir	= 0;	root -> depth	= 0;	root -> br1cnt	= 0;	root -> x	= NEWA (nedges, double);	root -> cpiter	= -1;		/* x is not current. */	root -> zlb	= NEWA (2 * nedges, double);	root -> fixed	= fixed;	root -> value	= value;	root -> n_uids	= 0;	root -> bc_uids	= NULL;	root -> bc_row	= NULL;	root -> rstat	= NULL;	root -> cstat	= NULL;	root -> bheur	= NEWA (nedges, double);	root -> next	= NULL;	root -> prev	= NULL;	for (i = 0; i < nedges; i++) {		root -> bheur [i] = 0.0;	}	for (i = 0; i < 2*nedges; i++) {		root -> zlb [i] = -DBL_MAX;	}	/* Create the branch-and-bound statistics structure... */	statp = NEW (struct bbstats);	memset (statp, 0, sizeof (*statp));	statp -> n		= cip -> num_verts;	statp -> m		= nedges;	statp -> p1time		= cip -> p1time;	statp -> num_nodes	= 0;	statp -> num_lps	= 0;	statp -> cs_init.num_prows	= cpool -> nrows;	statp -> cs_init.num_lprows	= GET_LP_NUM_ROWS (lp);	statp -> cs_init.num_pnz	= cpool -> num_nz;	statp -> cs_init.num_lpnz	= GET_LP_NUM_NZ (lp);	/* Fill in the global branch-and-bound info structure... */	bbip -> cip		= cip;	bbip -> tmap		= vert_mask;	bbip -> fset_mask	= edge_mask;	bbip -> lp		= lp;	bbip -> lpmem		= lpmem;	bbip -> cpool		= cpool;	bbip -> bbtree		= bbtree;	bbip -> csip		= NULL;	bbip -> preempt_z	= Initial_Upper_Bound;	bbip -> best_z		= Initial_Upper_Bound;	bbip -> smt		= smt;	bbip -> node		= root;	bbip -> slack_size	= 0;	bbip -> slack		= NULL;	bbip -> dj		= NEWA (nedges, double);	bbip -> fixed		= NULL;	bbip -> value		= NULL;	bbip -> statp		= statp;	bbip -> prevlb		= -DBL_MAX;	bbip -> ubip		= NULL;	/* Make the root node inactive by putting it in the bbtree... */	n = cpool -> nlprows;	root -> n_uids	= n;	root -> bc_uids	= NEWA (n, int);	root -> bc_row	= NEWA (n, int);	j = 0;	rcp = &(cpool -> rows [0]);	for (i = 0; i < cpool -> nrows; i++, rcp++) {		k = rcp -> lprow;		if (k < 0) continue;		++(rcp -> refc);		root -> bc_uids [j] = rcp -> uid;		root -> bc_row [j]  = k;		++j;	}	if (j NE n) {		fatal ("create_bbinfo: Bug 1.");	}	root -> next = NULL;	root -> prev = NULL;	bbtree -> first = root;	bbheap_insert (root, bbtree, BEST_NODE_HEAP);	bbheap_insert (root, bbtree, WORST_NODE_HEAP);	return (bbip);}/* * This routine is the top-level of the branch-and-cut. */	dist_tbranch_and_cut (struct bbinfo *		bbip		/* IN - branch-and-bound info */){int			i;int			j;int			nmasks;int			nedges;int			status;bitmap_t *		fixed;bitmap_t *		value;bitmap_t *		delta;bitmap_t *		smt;double *		x;double			z0;double			z1;double			tmpz;cpu_time_t		t1;RETSIGTYPE		(*save_sigterm) (int);struct cinfo *		cip;LP_t *			lp;struct cpool *		cpool;struct bbtree *		bbtree;struct bbstats *	statp;struct bbnode *		node;struct bbnode *		node_to_free;struct bbnode *		node2;#ifdef CPLEXint *			b_index;char *			b_lu;double *		b_bd;double			objlim;double			save_objlim;#endif	cip	= bbip -> cip;	cpool	= bbip -> cpool;	lp	= bbip -> lp;	statp	= bbip -> statp;	smt	= bbip -> smt;	bbtree	= bbip -> bbtree;	nmasks = cip -> num_edge_masks;	nedges = cip -> num_edges;#if CPLEX	/* Save the existing objective limit, and set it to infinity. */	CPXgetdblparam (cplex_env, CPX_PARAM_OBJULIM, &save_objlim);	objlim = DBL_MAX;	CPXsetdblparam (cplex_env, CPX_PARAM_OBJULIM, objlim);#endif	if (Check_Root_Constraints) {		rcfile = fopen ("/tmp/lp.x", "w");		if (rcfile EQ NULL) {			fprintf (stderr,				 "Warning: unable to create /tmp/lp.x\n");			Check_Root_Constraints = FALSE;		}	}	/* Establish handler for the SIGTERM (kill -15) signal... */	force_branch_flag = FALSE;	save_sigterm = signal (SIGTERM, force_branch_signal_handler);	/* Create vectors to describe the current problem... */	fixed	= NEWA (nmasks, bitmap_t);	value	= NEWA (nmasks, bitmap_t);	delta	= NEWA (nmasks, bitmap_t);	/* No variables have been fixed yet... */	for (i = 0; i < nmasks; i++) {		fixed [i] = 0;		value [i] = 0;	}	bbip -> fixed = fixed;	bbip -> value = value;#ifdef CPLEX	/* Create arrays for changing variable bounds... */	b_index	= NEWA (2 * nedges, int);	b_lu	= NEWA (2 * nedges, char);	b_bd	= NEWA (2 * nedges, double);#endif#if 0	/* Build cutset separation formulation. */	bbip -> csip = NEW (struct cs_info);	build_cutset_separation_formulation (vert_mask,					     edge_mask,					     cip,					     bbip -> csip);#endif	/* Init the heuristic upper bound. */	bbip -> ubip = startup_heuristic_upper_bound (bbip -> cip);	/* At this point, all nodes are inactive. */	for (;;) {		/* Select the next node to process. */		node = select_next_node (bbtree);		if (node EQ NULL) break;		/* This is perhaps a new lower bound... */		new_lower_bound (node -> z, bbip);		if (node -> z > -DBL_MAX) {			tracef ("%% Resuming node %d at %24.20f\n",				node -> num,				UNSCALE (node -> z, &(cip -> scale)));		}		else {			tracef ("%% Resuming node %d\n", node -> num);		}		/* Restore the LP tableaux and basis for this node.	*/		/* Decrement the reference counts on this node's	*/		/* binding rows.  Since it is now the ACTIVE node,	*/		/* there is no reason to continue protecting these rows	*/		/* from deletion by other nodes.			*/		restore_node_basis (node, bbip);		/* Determine new preemption value (i.e. the objective	*/		/* value of the next-best node).			*/		update_node_preempt_value (bbip);		/* Modify LP to represent problem from new node. */		for (i = 0; i < nmasks; i++) {			delta [i] =   (fixed [i] ^ node -> fixed [i])				    | (value [i] ^ node -> value [i]);		}#ifdef CPLEX		j = 0;		for (i = 0; i < nedges; i++) {			if (NOT BITON (delta, i)) continue;			/* Force bounds for variable 'i' to be correct... */			b_index [j]	= i;	/* variable i, */			b_lu [j]	= 'L';	/*	lower bound */			b_index [j+1]	= i;	/* variable i, */			b_lu [j+1]	= 'U';	/*	upper bound */			if (NOT BITON (node -> fixed, i)) {				/* new variable is NOT fixed... */				b_bd [j]	= 0.0;				b_bd [j+1]	= 1.0;			}			else if (NOT BITON (node -> value, i)) {				/* new variable is fixed to 0 */				b_bd [j]	= 0.0;				b_bd [j+1]	= 0.0;			}			else {				/* new variable is fixed to 1 */				b_bd [j]	= 1.0;				b_bd [j+1]	= 1.0;			}			j += 2;		}		if (j > 0) {			if (_MYCPX_chgbds (bbip -> lp, j, b_index, b_lu, b_bd) NE 0) {				fatal ("branch_and_cut: Bug 1.");			}#if 0			++(bbip -> cpool -> uid);#endif		}#endif#ifdef LPSOLVE		j = 0;		for (i = 0; i < nedges; i++) {			if (NOT BITON (delta, i)) continue;			++j;			/* Force bounds on variable 'i' to be correct... */			if (NOT BITON (node -> fixed, i)) {				/* variable is NOT fixed... */				set_bounds (lp, i + 1, 0.0, 1.0);			}			else if (NOT BITON (node -> value, i)) {				/* variable is fixed to 0 */				set_bounds (lp, i + 1, 0.0, 0.0);			}			else {				/* variable is fixed to 1 -- must set	*/				/* bounds in this order to avoid	*/				/* lb > ub condition between calls...	*/				set_bounds (lp, i + 1, 1.0, 1.0);			}		}		if (j > 0) {#if 0			++(bbip -> cpool -> uid);#endif		}#endif		for (i = 0; i < nmasks; i++) {			fixed [i] = node -> fixed [i];			value [i] = node -> value [i];		}		/* Set up new node to be processed */		bbip -> node = node;		if (node -> iter <= 0) {			/* Haven't processed this node before	*/			/* -- tally another node...		*/			++(statp -> num_nodes);		}		/* Process the current node... */		status = compute_good_lower_bound (bbip);		if (node -> depth EQ 0) {

⌨️ 快捷键说明

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