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

📄 constrnt.c

📁 生成直角Steiner树的程序包
💻 C
📖 第 1 页 / 共 5 页
字号:
struct rcoef *	p;struct rcoef *	p2;struct rcon *	rcp;int *		hookp;struct rblk *	blkp;struct rblk *	blkp2;int *		ip;size_t		nbytes;#define	_HASH(reg,value) \	(reg) ^= (value); \	(reg) = ((reg) < 0) ? ((reg) << 1) + 1 : ((reg) << 1);	verify_pool (pool);	/* Factor out the GCD of the row... */	reduce_constraint (rp);	/* Compute hash value and length of LHS... */	hval = 0;	len = 0;	for (p = rp;; p++) {		var = p -> var;		if (var < RC_VAR_BASE) break;		_HASH (hval, var);		_HASH (hval, p -> val);		++len;	}	hval %= CPOOL_HASH_SIZE;	if (hval < 0) {		hval += CPOOL_HASH_SIZE;	}	if ((hval < 0) OR (hval >= CPOOL_HASH_SIZE)) {		fatal ("add_constraint_to_pool: Bug 0.");	}	nbytes = (len + 1) * sizeof (*rp);	hookp = &(pool -> hash [hval]);	for (row = *hookp; row >= 0;) {		rcp = &(pool -> rows [row]);		if ((rcp -> len EQ len) AND		    (memcmp (rcp -> coefs, rp, nbytes) EQ 0)) {			/* Constraint already here! */			return (FALSE);		}		row = rcp -> next;	}	/* Constraint is not present -- add it.  Start by copying the	*/	/* coefficients...  If no room, grab another block.		*/	blkp = pool -> blocks;	if (blkp EQ NULL) {		fatal ("add_constraint_to_pool: Bug 2.");	}	pool -> num_nz += len;	++len;		/* include op/rhs in length now... */	if (blkp -> nfree < len) {		/* Note: the free space (if any) at the end of the	*/		/* current block NEVER gets used.  This is by design,	*/		/* since this results in better cache behavior while	*/		/* scanning the pool for violations (hitting all of	*/		/* the rcoefs in each rblk in sequence).		*/		/* Grab same number as last time... */		n = (blkp -> ptr - blkp -> base) + blkp -> nfree;		if (n < len) {			n = len;		}		blkp2 = NEW (struct rblk);		blkp2 -> next	= blkp;		blkp2 -> base	= NEWA (n, struct rcoef);		blkp2 -> ptr	= blkp2 -> base;		blkp2 -> nfree	= n;		pool -> blocks = blkp2;		blkp = blkp2;	}	p = blkp -> ptr;	blkp -> ptr	+= len;	blkp -> nfree	-= len;	memcpy (p, rp, len * sizeof (*rp));	/* Now grab a new row header... */	row = (pool -> nrows)++;	if (row >= pool -> maxrows) {		/* Must grab more rows.  Double it...	*/		n = 2 * pool -> maxrows;		rcp = pool -> rows;		pool -> rows = NEWA (n, struct rcon);		pool -> maxrows = n;		memcpy (pool -> rows, rcp, row * sizeof (*rcp));		free ((char *) rcp);		/* Increase size of the lprows array also... */		ip = NEWA (n, int);		memcpy (ip, pool -> lprows, row * sizeof (*ip));		free ((char *) (pool -> lprows));		pool -> lprows = ip;	}	rcp = &(pool -> rows [row]);	rcp -> len	= len - 1;	/* op/rhs not part of length here... */	rcp -> coefs	= p;	rcp -> next	= *hookp;	rcp -> lprow	= -1;	rcp -> biter	= pool -> iter;	/* assume binding (or violated) now */	rcp -> hval	= hval;	rcp -> flags	= 0;	rcp -> uid	= (pool -> uid)++;	rcp -> refc	= 0;		/* no OTHER node references it! */	*hookp = row;	if (add_to_lp) {		/* This row is pending addition to the LP tableaux. */		mark_row_pending_to_LP (pool, row);	}	verify_pool (pool);	return (TRUE);}/* * This routine reduces the given constraint row to lowest terms by * dividing by the GCD. */	static	voidreduce_constraint (struct rcoef *		rp	/* IN - coefficient row */){int			j;int			k;int			rem;int			com_factor;struct rcoef *		p;	/* Initial common factor is first coefficient. */	com_factor = rp -> val;	if (com_factor <= 0) {		if (com_factor EQ 0) {			fatal ("reduce_constraint: Bug 1.");		}		com_factor = - com_factor;	}	if (com_factor EQ 1) return;	for (p = rp + 1; ; p++) {		k = p -> val;		if (k <= 0) {			if (k EQ 0) {				fatal ("reduce_constraint: Bug 2.");			}			k = -k;		}		/* Euclid's algorithm: computes GCD... */		j = com_factor;		while (j > 0) {			rem = k % j;			k = j;			j = rem;		}		com_factor = k;		if (com_factor EQ 1) return;		if (p -> var < RC_VAR_BASE) break;	}	/* We have a row to reduce! */	for (p = rp; ; p++) {		if ((p -> val % com_factor) NE 0) {			fatal ("reduce_constraint: Bug 3.");		}		p -> val /= com_factor;		if (p -> var < RC_VAR_BASE) break;	}}/* * This routine sets up the LP problem instance for the initial * constraints of the LP relaxation. */#if CPLEX	LP_t *build_initial_formulation (struct cpool *		pool,		/* IN - initial constraint pool */bitmap_t *		vert_mask,	/* IN - set of valid vertices */bitmap_t *		edge_mask,	/* IN - set of valid hyperedges */struct cinfo *		cip,		/* IN - compatibility info */struct lpmem *		lpmem		/* OUT - dynamically allocated mem */){int			i, j, k;int			nedges;int			nrows;int			ncoeff;int			row;int			var;int *			tmp;struct rcon *		rcp;struct rcoef *		cp;LP_t *			lp;int			macsz, marsz, maesz, matsz;int			mac, mar, mae;int			objsen;double *		objx;double *		rhsx;char *			senx;double *		bdl;double *		bdu;int *			matbeg;int *			matcnt;int *			matind;double *		matval;cpu_time_t		T0;cpu_time_t		T1;double			min_c, max_c, ci;int			min_exp, max_exp;int			obj_scale;char			tbuf [32];	T0 = get_cpu_time ();	nedges = cip -> num_edges;	/* We know exactly how many columns (variables) we will */	/* ever need.  We never add additional variables. */	macsz = nedges;	mac = macsz;	/* Build the objective function... */	objx = NEWA (macsz, double);	for (i = 0; i < macsz; i++) {		objx [i] = 0.0;	}	for (i = 0; i < nedges; i++) {		if (NOT BITON (edge_mask, i)) continue;		objx [i] = (double) (cip -> cost [i]);	}	/* CPLEX does not behave well if the objective coefficients	*/	/* have very large magnitudes.  (If so, we often get "unscaled	*/	/* infeasibility" error codes.)  Therefore, we scale objx here	*/	/* (by an exact power of two so that the mantissas remain	*/	/* unchanged).  Determine a power of two that brings the objx	*/	/* magnitudes into a reasonable range.				*/	min_c	= DBL_MAX;	max_c	= 0.0;	for (i = 0; i < macsz; i++) {		ci = fabs (objx [i]);		if (ci EQ 0.0) continue;		if (ci < min_c) {			min_c = ci;		}		if (ci > max_c) {			max_c = ci;		}	}	(void) frexp (min_c, &min_exp);	(void) frexp (max_c, &max_exp);	obj_scale = (min_exp + max_exp) / 2;	/* Remember scale factor so we can unscale results. */	lpmem -> obj_scale = obj_scale;	obj_scale = - obj_scale;	for (i = 0; i < macsz; i++) {		objx [i] = ldexp (objx [i], obj_scale);	}	objsen = _MYCPX_MIN;	/* Minimize */	/* Build variable bound arrays... */	bdl = NEWA (macsz, double);	bdu = NEWA (macsz, double);	for (i = 0; i < macsz; i++) {		bdl [i] = 0.0;		bdu [i] = 1.0;	}	mar	= pool -> npend;	if (pool -> hwmrow EQ 0) {		/* Initial allocation.  Allocate space sufficiently	*/		/* large that we are unlikely to need to reallocate the	*/		/* CPLEX problem buffers...				*/		/* Start with the total number of non-zeros in the	*/		/* entire constraint pool...				*/		ncoeff = 0;		nrows = pool -> nrows;		for (i = 0; i < nrows; i++) {			rcp = &(pool -> rows [i]);			ncoeff += rcp -> len;		}		marsz	= 2 * nrows;		matsz	= 4 * ncoeff;	}	else {		/* Reallocating CPLEX problem.  We want a moderate rate	*/		/* of growth, but must trade this off against the	*/		/* frequency of reallocation.  We expand both the rows	*/		/* and the non-zeros by 25% over the largest need seen	*/		/* now or previously.					*/		ncoeff = 0;		for (i = 0; i < pool -> npend; i++) {			row = pool -> lprows [i];			rcp = &(pool -> rows [row]);			ncoeff += rcp -> len;		}		if ((mar > pool -> hwmrow) OR (ncoeff > pool -> hwmnz)) {			/* high-water marks should be updated before! */			fatal ("build_initial_formulation: Bug Z.");		}		marsz = 5 * pool -> hwmrow / 4;		matsz = 5 * pool -> hwmnz / 4;	}	if (marsz < min_cplex_rows) {		marsz = min_cplex_rows;	}	if (matsz < min_cplex_nzs) {		matsz = min_cplex_nzs;	}	tracef (" %% cpx allocation: %d rows, %d cols, %d nz\n",		marsz, macsz, matsz);	/* Allocate arrays for constraint matrix... */	rhsx = NEWA (marsz, double);	senx = NEWA (marsz, char);	matbeg = NEWA (macsz, int);	matcnt = NEWA (macsz, int);	matind = NEWA (matsz, int);	matval = NEWA (matsz, double);	for (i = 0; i < marsz; i++) {		rhsx [i] = 0.0;	}	for (i = 0; i < macsz; i++) {		matbeg [i] = 0;		matcnt [i] = 0;	}	for (i = 0; i < matsz; i++) {		matind [i] = 0;		matval [i] = 0.0;	}	/* Now go through each row k and compute the number of	*/	/* non-zero coefficients for each variable used...	*/	tmp = NEWA (macsz, int);	for (i = 0; i < macsz; i++) {		tmp [i] = 0;	}	for (i = 0; i < pool -> npend; i++) {		row = pool -> lprows [i];		rcp = &(pool -> rows [row]);		for (cp = rcp -> coefs; ; cp++) {			var = cp -> var;			if (var < RC_VAR_BASE) break;			++(tmp [var - RC_VAR_BASE]);		}	}	/* CPLEX wants columns, not rows... */	j = 0;	for (i = 0; i < mac; i++) {		k = tmp [i];		matbeg [i] = j;		tmp [i] = j;		matcnt [i] = k;		j += k;	}	if (j > pool -> hwmnz) {		pool -> hwmnz = j;	}	if (mar > pool -> hwmrow) {		pool -> hwmrow = mar;	}	for (i = 0; i < pool -> npend; i++) {		row = pool -> lprows [i];		rcp = &(pool -> rows [row]);		for (cp = rcp -> coefs; ; cp++) {			var = cp -> var;			if (var < RC_VAR_BASE) break;			j = tmp [var - RC_VAR_BASE];			matind [j] = i;			matval [j] = cp -> val;			++(tmp [var - RC_VAR_BASE]);		}		switch (var) {		case RC_OP_LE:	senx [i] = 'L';		break;		case RC_OP_EQ:	senx [i] = 'E';		break;		case RC_OP_GE:	senx [i] = 'G';		break;		default:			fatal ("build_initial_formulation: Bug 1.");		}		rhsx [i] = cp -> val;		rcp -> lprow = i;	}	/* Verify consistency of what we generated... */	for (i = 0; i < mac; i++) {		if (tmp [i] NE matbeg [i] + matcnt [i]) {			fprintf (stderr,				 " %% i = %d, tmp = %d, matbeg = %d, matcnt = %d\n",				 i, tmp [i], matbeg [i], matcnt [i]);			fatal ("build_initial_formulation: Bug 2.");		}	}	free ((char *) tmp);	pool -> nlprows	= pool -> npend;	pool -> npend	= 0;#if 0	_MYCPX_setadvind (1);		/* continue from previous basis. */#endif	lp = _MYCPX_loadlp ("root",			    mac,			    mar,			    objsen,			    objx,			    rhsx,			    senx,			    matbeg,			    matcnt,			    matind,			    matval,			    bdl,			    bdu,			    NULL,			    macsz,			    marsz,			    matsz);	if (lp EQ NULL) {		fatal ("build_initial_formulation: Bug 3.");	}	/* Remember addresses of each buffer for when we need to free them. */	lpmem -> objx		= objx;	lpmem -> rhsx		= rhsx;	lpmem -> senx		= senx;	lpmem -> matbeg		= matbeg;	lpmem -> matcnt		= matcnt;	lpmem -> matind		= matind;	lpmem -> matval		= matval;	lpmem -> bdl		= bdl;	lpmem -> bdu		= bdu;	T1 = get_cpu_time ();	convert_cpu_time (T1 - T0, tbuf);	tracef (" %% build_initial_formulation: %s seconds.\n", tbuf);	return (lp);}#endif/* * This routine sets up the LP problem instance for the initial * constraints of the LP relaxation. */#if LPSOLVE	LP_t *build_initial_formulation (struct cpool *		pool,		/* IN - initial constraint pool */bitmap_t *		vert_mask,	/* IN - set of valid vertices */bitmap_t *		edge_mask,	/* IN - set of valid hyperedges */struct cinfo *		cip,		/* IN - compatibility info */struct lpmem *		lpmem		/* OUT - dynamically allocated mem */){int			i;int			j;int			k;int			nedges;int			nrows;int			ncols;int			ncoeff;int			nzi;int			row;int			var;struct rcon *		rcp;struct rcoef *		cp;LP_t *			lp;double *		rowvec;double *		rhs;short *			ctype;int *			matbeg;int *			matind;double *		matval;int *			ip1;int *			ip2;cpu_time_t		T0;cpu_time_t		T1;char			tbuf [32];	T0 = get_cpu_time ();	nedges = cip -> num_edges;	/* We know exactly how many columns (variables) we will */	/* ever need.  We never add additional variables. */	ncols = nedges;	/* Compute the total number of non-zeros in the INITIAL	*/	/* constraints of the constraint pool...		*/	ncoeff = 0;	nrows = pool -> npend;	for (i = 0; i < nrows; i++) {		row = pool -> lprows [i];		rcp = &(pool -> rows [row]);		ncoeff += rcp -> len;	}	/* Make the initial LP... */	lp = make_lp (0, ncols);	/* All variables are 0-1 variables... */	for (i = 1; i <= nedges; i++) {		set_bounds (lp, i, 0.0, 1.0);	}	/* Minimize */	set_minim (lp);	/* Build the objective function... */	rowvec = NEWA (ncols + 1, double);	for (i = 0; i <= ncols; i++) {		rowvec [i] = 0.0;	}	for (i = 0; i < nedges; i++) {		if (NOT BITON (edge_mask, i)) continue;		rowvec [i + 1] = (double) (cip -> cost [i]);	}#if 1	inc_mat_space (lp, ncols + 1);#endif	set_obj_fn (lp, rowvec);	free ((char *) rowvec);	/* Allocate arrays for setting the rows... */	rhs	= NEWA (nrows, double);	ctype	= NEWA (nrows, short);	matbeg	= NEWA (nrows + 1, int);	matind	= NEWA (ncoeff, int);	matval	= NEWA (ncoeff, double);	/* Put the rows into the format that LP-solve wants them in...	*/	nzi = 0;

⌨️ 快捷键说明

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