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

📄 bb.c

📁 生成直角Steiner树的程序包
💻 C
📖 第 1 页 / 共 5 页
字号:
			/* Finished the root node... */			statp -> root_z = node -> z;			statp -> root_lps = statp -> num_lps;			/* Slack rows should have already been deleted... */			statp -> cs_root.num_prows = cpool -> nrows;			statp -> cs_root.num_lprows =				GET_LP_NUM_ROWS (bbip -> lp);			statp -> cs_root.num_pnz = cpool -> num_nz;			statp -> cs_root.num_lpnz =				GET_LP_NUM_NZ (bbip -> lp);			statp -> root_opt = node -> optimal;			t1 = get_cpu_time ();			statp -> root_time = t1 - bbip -> t0;			if ((status EQ LB_FRACTIONAL) AND Print_Root_LP) {				print_root_lp (bbip);			}			if (Check_Root_Constraints) {				check_root_constraints (bbip);			}		}		node_to_free = NULL;	/* Default is no node to free... */		switch (status) {		case LB_INFEASIBLE:			/* Node is fathomed! */			trace_node (bbip, ' ', "infeasible");			node_to_free = node;			break;		case LB_CUTOFF:			/* Node is fathomed! */			trace_node (bbip, ' ', "cutoff");			node_to_free = node;			break;		case LB_INTEGRAL:			if (node -> z >= bbip -> best_z) {				trace_node (bbip, ' ', "cutoff");				break;			}			/* We have a new best feasible integer solution! */			for (i = 0; i < nmasks; i++) {				smt [i] = 0;			}			x = node -> x;			for (i = 0; i < nedges; i++) {				if (x [i] >= 0.5) {					SETBIT (smt, i);				}			}			new_upper_bound (node -> z, bbip);			trace_node (bbip, '*', NULL);			node_to_free = node;			break;		case LB_FRACTIONAL:			j = choose_branching_variable (bbip, &z0, &z1);			if (j < 0) {				/* At least one variable was fixed due	*/				/* to cutoff or infeasibility.  It is	*/				/* possible that the entire node is now	*/				/* cutoff...				*/				if (node -> z >= bbip -> best_z) {					trace_node (bbip, ' ', "cutoff");					node_to_free = node;					break;				}				goto suspend;			}			/* Create two nodes... */			if (z0 < z1) {				add_bbnode (bbip, j, 0, z0);				add_bbnode (bbip, j, 1, z1);			}			else if (z1 < z0) {				add_bbnode (bbip, j, 1, z1);				add_bbnode (bbip, j, 0, z0);			}			else if (UP_FIRST) {	/* To break ties... */				add_bbnode (bbip, j, 0, z0);				add_bbnode (bbip, j, 1, z1);			}			else {				add_bbnode (bbip, j, 1, z1);				add_bbnode (bbip, j, 0, z0);			}			trace_node (bbip, ' ', NULL);			/* This node is done (became 2 children), free it. */			node_to_free = node;			break;		case LB_PREEMPTED:suspend:			tracef ("%% suspending node %d at %24.20f\n",				node -> num,				UNSCALE (node -> z, &(cip -> scale)));			/* This node is no longer the best.  Put it	*/			/* back into the heap and get another one...	*/			node2 = bbtree -> first;			if (node2 NE NULL) {				node2 -> prev = node;			}			node -> next = node2;			node -> prev = NULL;			bbtree -> first = node;			bbheap_insert (node, bbtree, BEST_NODE_HEAP);			bbheap_insert (node, bbtree, WORST_NODE_HEAP);			/* Deactivating this node -- remember the basis */			save_node_basis (node, bbip);			/* Do NOT free this node! */			break;		}		/* If there is a node to free, do so now... */		if (node_to_free NE NULL) {			/* Free up saved basis info and decrement	*/			/* constraint reference counts before freeing.	*/			destroy_node_basis (node_to_free, bbip);			node_to_free -> next = bbtree -> free;			bbtree -> free = node_to_free;		}	}	statp -> cs_final.num_prows	= cpool -> nrows;	statp -> cs_final.num_lprows	= GET_LP_NUM_ROWS (bbip -> lp);	statp -> cs_final.num_pnz	= cpool -> num_nz;	statp -> cs_final.num_lpnz	= GET_LP_NUM_NZ (bbip -> lp);	/* New lower bound! */	new_lower_bound (bbip -> best_z, bbip);	t1 = get_cpu_time ();	statp -> p2time = t1 - bbip -> t0;	statp -> z = bbip -> best_z;	/* Restore normal handling of SIGTERM... */	(void) signal (SIGTERM, save_sigterm);#if CPLEX	free ((char *) b_bd);	free ((char *) b_lu);	free ((char *) b_index);#endif	free ((char *) delta);	free ((char *) value);	free ((char *) fixed);#if CPLEX	CPXsetdblparam (cplex_env, CPX_PARAM_OBJULIM, save_objlim);#endif	/* Return length of final tree... */	return ((dist_t) bbip -> best_z);}/* * A handler for the SIGTERM signal.  When we receive this signal we * stop generating constraints for the current node and branch instead. */	static	RETSIGTYPEforce_branch_signal_handler (int		sig		/* IN - signal being handled */){	/* Stop generating constraints and force a branch instead. */	force_branch_flag = TRUE;	/* Prepare to handle the signal again... */	(void) signal (SIGTERM, force_branch_signal_handler);}/* * This routine selects the next node to process from the given * branch-and-bound tree.  This is where we implement the specific * search policy. */	static	struct bbnode *select_next_node (struct bbtree *		tp	/* IN - branch-and-bound tree */){struct bbnode *		p;	if (tp -> first EQ NULL) {		/* No more nodes! */		return (NULL);	}	switch (tp -> node_policy) {	case NN_DEPTH_FIRST:		/* Get node created most recently... */		p = tp -> first;		break;	case NN_BEST_NODE:		/* Get node with lowest objective function value... */		p = tp -> heap [BEST_NODE_HEAP].array [0];		break;	default:		fatal ("select_next_node: Bug 1.");	}	delete_node_from_bbtree (p, tp);	return (p);}/* * This routine traces the result for a given node. */	static	voidtrace_node (struct bbinfo *		bbip,	/* IN - the branch-and-bound info */char			c1,	/* IN - space or * char */char *			msg	/* IN - message OR NULL */){struct bbnode *		p;struct bbtree *		tp;struct bbheap *		hp;double			lowz;char *			p1;char *			p2;char			c2;char			buf1 [32];char			buf2 [32];char			buf3 [32];char			buf4 [32];char			buf5 [32];char			buf6 [32];char			line [136];	p	= bbip -> node;	tp	= bbip -> bbtree;	if (msg EQ NULL) {		(void) sprintf (buf1, "%14.4f", p -> z);	}	else {		(void) sprintf (buf1, "%14s", msg);	}	if (bbip -> best_z EQ DBL_MAX) {		buf2 [0] = '\0';	}	else {		(void) sprintf (buf2, "%14.4f", bbip -> best_z);	}	hp = &(tp -> heap [BEST_NODE_HEAP]);	if (hp -> nheap > 0) {		(void) sprintf (buf3,				"%14.4f",				hp -> array [0] -> z);	}	else {		buf3 [0] = '\0';	}	if (p -> var < 0) {		buf4 [0] = '\0';		c2 = ' ';	}	else {		(void) sprintf (buf4, "x%d", p -> var);		c2 = (p -> dir EQ 0) ? 'D' : 'U';	}	if (p -> parent < 0) {		buf5 [0] = '\0';	}	else {		(void) sprintf (buf5, "%d", p -> parent);	}	if (p -> depth <= 0) {		buf6 [0] = '\0';	}	else {		(void) sprintf (buf6, "%d", p -> depth);	}	(void) sprintf (line,			"%c%6d%6d%14s%14s%14s%6s %c%6s%6s",			c1,		/* space or * */			p -> num,	/* node number */			hp -> nheap,	/* nodes left */			buf1,		/* objective/cutoff/infeas */			buf2,		/* best integer soln */			buf3,		/* best node */			buf4,		/* variable name */			c2,		/* branch direction */			buf5,		/* parent node number */			buf6);		/* node depth */	p1 = line;	for (p2 = p1; *p2 NE '\0'; p2++) {	}	while ((p2 > p1) AND (p2 [-1] EQ ' ')) {		--p2;	}	*p2 = '\0';	(void) tracef ("  %% %s\n", line);}/* * This routine plots the LP relaxation solution for the root node.  We * do this whenever -r is specified and we get an optimal LP relaxation * solution that is fractional. */	static	voidprint_root_lp (struct bbinfo *		bbip		/* IN - branch-and-bound info */){struct cinfo *		cip;struct bbnode *		nodep;struct bbstats *	statp;char *			descr;char			buf1 [32];char			buf2 [32];char			title [256];	cip	= bbip -> cip;	nodep	= bbip -> node;	statp	= bbip -> statp;	convert_cpu_time (statp -> root_time, buf1);	dist_to_string (buf2, nodep -> z, &(cip -> scale));	descr = "Steiner Minimal Tree";	if ((cip -> description NE NULL) AND	    (cip -> description [0] NE '\0')) {		descr = cip -> description;	}	sprintf (title,		 "%s:  %lu points,  Root Node, LP %d,  length = %s,  %s seconds",		 descr,		 cip -> num_verts,		 nodep -> iter,		 buf2,		 buf1);	plot_lp_solution (title, bbip -> node -> x, cip, BIG_PLOT);}/* * This routine chooses the next variable to branch on at this * node. */	static	intchoose_branching_variable (struct bbinfo *		bbip,		/* IN - branch-and-bound info */double *		z0,		/* OUT - value to give Xi=0 node */double *		z1		/* OUT - value to give Xi=1 node */){int			i;int			nedges;int			best_var;struct cinfo *		cip;struct bbnode *		nodep;double *		x;bitmap_t *		fset_mask;double			xi;double			max_infeas;double			infeas;	if (Choose_Branch_Vars_Carefully) {		/* Do it very carefully! */		return (carefully_choose_branching_variable (bbip, z0, z1));	}	/* There are LOTS of things that we MIGHT do here in	*/	/* the FUTURE!  For right now, just take the variable	*/	/* that is closest to 1/2 -- take larger variables in	*/	/* the event of a tie...				*/	cip		= bbip -> cip;	nodep		= bbip -> node;	x		= nodep -> x;	fset_mask	= bbip -> fset_mask;	nedges	= cip -> num_edges;	best_var	= -1;	max_infeas	= 0.0;	for (i = nedges - 1; i >= 0; i--) {		if (NOT BITON (fset_mask, i)) continue;		xi = x [i];		if (xi <= FUZZ) continue;		if (xi + FUZZ >= 1.0) continue;		infeas = 1.0 - xi;		if (xi < infeas) {			infeas = xi;		}		if (infeas > max_infeas) {			best_var = i;			max_infeas = infeas;		}	}	if (best_var < 0) {		fatal ("choose_branching_variable: Bug 1.");	}	/* Give both nodes the same value... */	*z0	= nodep -> z;	*z1	= nodep -> z;	return (best_var);}/* * This routine does a very careful job of choosing the next variable * to branch on.  For each fractional variable Xi, we solve the LP * first with Xi=0 and then Xi=1, yielding objective values Zi0 and Zi1 * correspondingly.  We then choose variable Xi for which the value * min(Zi0, Zi1) is MAXIMIZED.  This provides us with the best possible * "one-branch/no-cuts" improvement in the lower bound. */	static	intcarefully_choose_branching_variable (struct bbinfo *		bbip,		/* IN - branch-and-bound info */double *		node_z0,	/* OUT - value for Xi=0 node */double *		node_z1		/* OUT - value for Xi=1 node */){int			i;int			j;int			n;int			nedges;int			nfrac;int			limit;int			new_limit;int			logn;int			failure_limit;int			num_failures;struct cinfo *		cip;struct bbnode *		nodep;double *		x;double *		rank;bitmap_t *		edge_mask;int *			fvars;bool			fixed;bool			cur_var_is_better;double			xi;double			z0;double			z1;double			z;double			delta;double			test_2nd_val;double			num;double			den;struct bvar		best;struct basis_save	bsave;	cip		= bbip -> cip;	nodep		= bbip -> node;	x		= nodep -> x;	edge_mask	= bbip -> fset_mask;	nedges	= cip -> num_edges;	fvars = NEWA (nedges, int);start_all_over:	nfrac = 0;	for (i = 0; i < nedges; i++) {		if (NOT BITON (edge_mask, i)) continue;		xi = x [i];		if (xi <= FUZZ) continue;		if (xi + FUZZ >= 1.0) continue;		fvars [nfrac++] = i;	}#if 1	tracef ("\n %% Carefully choosing branching variable, nfrac = %d\n",		nfrac);#endif	/* Compute final heuristic ranking of the candidate branch	*/	/* variables.  We multiply the node's "bheur" values by a	*/	/* "complexity factor" that is 1 for variables sitting at 0.5,	*/	/* and increases as the variable's "rational" value becomes	*/	/* more complicated.  Thus, we prefer vars stuck at 1/2, and	*/	/* then prefer vars stuck at 1/3 or 2/3, vars stuck at 1/4 or	*/	/* 3/4, etc.							*/	rank = NEWA (nedges, double);	memcpy (rank, nodep -> bheur, nedges * sizeof (double));	for (j = 0; j < nfrac; j++) {		i = fvars [j];		/* Compute closest rational approximation. */		(void) cra (x [i], &num, &den);		/* Factor is 1 + the denominator's "distance" from 1/2	*/		/* + the numerator's "distance" from 1/2.		*/		rank [i] *= ((den - 1.0) + fabs (num - 0.5 * den));	}	/* Sort the fractional variables so that good branch choices	*/	/* appear first with high probability.				*/	sort_branching_vars (fvars, nfrac, rank);#if 0	tracef (" %% Branch Variable Info:\n");	for (j = 0; j < nfrac; j++) {		i = fvars [j];		tracef (" %% %d:\tx%d\t= %.6f,\tbheur = %g,\trank = %g\n",			j, i, x [i], nodep -> bheur [i], rank [i]);	}#endif	free ((char *) rank);	/* Snapshot the current basis so that we can quickly	*/	/* get back to it each time...				*/	save_LP_basis (bbip -> lp, &bsave);	/* Compute the non-improvement limit.  When we have tested this	*/	/* many consecutive variables without finding a better choice,	*/	/* we punt.  We use 2 * log(N), where N is the number of	*/	/* fractional vars, and log(x) is the floor of the base-2 log.	*/	failure_limit = nfrac;	if (nfrac >= 20) {		logn = 0;		for (n = nfrac; n > 1; n >>= 1) {			++logn;		}		failure_limit = 2 * Check_Branch_Vars_Thoroughly * logn;	}	best.var	= -1;	best.z0		= nodep -> z;	best.z1		= nodep -> z;	test_2nd_val	= -DBL_MAX;	/* Do a quick scan without forcing anything to determine the	*/	/* best initial choice of branch variable.			*/	for (j = 0; j < nfrac; j++) {		i = fvars [j];		if (i < 0) continue;	/* var was fixed! */		cur_var_is_better = compare_branch_vars (bbip, i, &best);		if (cur_var_is_better) {			test_2nd_val = best.test_2nd_val;		}	}#if 1	if (best.var >= 0) {

⌨️ 快捷键说明

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