static void restore(struct dsa *dsa, double row_pval[], double row_dval[], double col_pval[], double col_dval[]) { /* restore solution of original LP */ LPX *lp = dsa->lp; int orig_m = dsa->orig_m; int orig_n = dsa->orig_n; int *ref = dsa->ref; int m = dsa->m; double *x = dsa->x; double *y = dsa->y; int dir = lpx_get_obj_dir(lp); int i, j, k, type, t, len, *ind; double lb, ub, rii, sjj, temp, *val; /* compute primal values of structural variables */ for (k = 1; k <= orig_n; k++) { j = ref[orig_m+k]; type = lpx_get_col_type(lp, k); sjj = lpx_get_sjj(lp, k); lb = lpx_get_col_lb(lp, k) / sjj; ub = lpx_get_col_ub(lp, k) / sjj; switch (type) { case LPX_FR: /* source: -inf < x < +inf */ /* result: x = x' - x'', x' >= 0, x'' >= 0 */ col_pval[k] = x[j] - x[j+1]; break; case LPX_LO: /* source: lb <= x < +inf */ /* result: x = lb + x', x' >= 0 */ col_pval[k] = lb + x[j]; break; case LPX_UP: /* source: -inf < x <= ub */ /* result: x = ub - x', x' >= 0 */ col_pval[k] = ub - x[j]; break; case LPX_DB: /* source: lb <= x <= ub */ /* result: x = lb + x', x' + x'' = ub - lb */ col_pval[k] = lb + x[j]; break; case LPX_FX: /* source: x = lb */ /* result: just substitute */ col_pval[k] = lb; break; default: insist(type != type); } } /* compute primal values of auxiliary variables */ /* xR = A * xS */ ind = ucalloc(1+orig_n, sizeof(int)); val = ucalloc(1+orig_n, sizeof(double)); for (k = 1; k <= orig_m; k++) { rii = lpx_get_rii(lp, k); temp = 0.0; len = lpx_get_mat_row(lp, k, ind, val); for (t = 1; t <= len; t++) { sjj = lpx_get_sjj(lp, ind[t]); temp += (rii * val[t] * sjj) * col_pval[ind[t]]; } row_pval[k] = temp; } ufree(ind); ufree(val); /* compute dual values of auxiliary variables */ for (k = 1; k <= orig_m; k++) { type = lpx_get_row_type(lp, k); i = ref[k]; switch (type) { case LPX_FR: insist(i == 0); row_dval[k] = 0.0; break; case LPX_LO: case LPX_UP: case LPX_DB: case LPX_FX: insist(1 <= i && i <= m); row_dval[k] = (dir == LPX_MIN ? +1.0 : -1.0) * y[i]; break; default: insist(type != type); } } /* compute dual values of structural variables */ /* dS = cS - A' * (dR - cR) */ ind = ucalloc(1+orig_m, sizeof(int)); val = ucalloc(1+orig_m, sizeof(double)); for (k = 1; k <= orig_n; k++) { sjj = lpx_get_sjj(lp, k); temp = lpx_get_obj_coef(lp, k) / sjj; len = lpx_get_mat_col(lp, k, ind, val); for (t = 1; t <= len; t++) { rii = lpx_get_rii(lp, ind[t]); temp -= (rii * val[t] * sjj) * row_dval[ind[t]]; } col_dval[k] = temp; } ufree(ind); ufree(val); /* unscale solution of original LP */ for (i = 1; i <= orig_m; i++) { rii = lpx_get_rii(lp, i); row_pval[i] /= rii; row_dval[i] *= rii; } for (j = 1; j <= orig_n; j++) { sjj = lpx_get_sjj(lp, j); col_pval[j] *= sjj; col_dval[j] /= sjj; } return; }
void lpx_check_kkt(LPX *lp, int scaled, LPXKKT *kkt) { int m = lpx_get_num_rows(lp); int n = lpx_get_num_cols(lp); #if 0 /* 21/XII-2003 */ int *typx = lp->typx; double *lb = lp->lb; double *ub = lp->ub; double *rs = lp->rs; #else int typx, tagx; double lb, ub; #endif int dir = lpx_get_obj_dir(lp); #if 0 /* 21/XII-2003 */ double *coef = lp->coef; #endif #if 0 /* 22/XII-2003 */ int *A_ptr = lp->A->ptr; int *A_len = lp->A->len; int *A_ndx = lp->A->ndx; double *A_val = lp->A->val; #endif int *A_ndx; double *A_val; #if 0 /* 21/XII-2003 */ int *tagx = lp->tagx; int *posx = lp->posx; int *indx = lp->indx; double *bbar = lp->bbar; double *cbar = lp->cbar; #endif int beg, end, i, j, k, t; double cR_i, cS_j, c_k, xR_i, xS_j, x_k, dR_i, dS_j, d_k; double g_i, h_k, u_j, v_k, temp, rii, sjj; if (lpx_get_prim_stat(lp) == LPX_P_UNDEF) xfault("lpx_check_kkt: primal basic solution is undefined\n"); if (lpx_get_dual_stat(lp) == LPX_D_UNDEF) xfault("lpx_check_kkt: dual basic solution is undefined\n"); /*--------------------------------------------------------------*/ /* compute largest absolute and relative errors and corresponding row indices for the condition (KKT.PE) */ kkt->pe_ae_max = 0.0, kkt->pe_ae_row = 0; kkt->pe_re_max = 0.0, kkt->pe_re_row = 0; A_ndx = xcalloc(1+n, sizeof(int)); A_val = xcalloc(1+n, sizeof(double)); for (i = 1; i <= m; i++) { /* determine xR[i] */ #if 0 /* 21/XII-2003 */ if (tagx[i] == LPX_BS) xR_i = bbar[posx[i]]; else xR_i = spx_eval_xn_j(lp, posx[i] - m); #else lpx_get_row_info(lp, i, NULL, &xR_i, NULL); xR_i *= lpx_get_rii(lp, i); #endif /* g[i] := xR[i] */ g_i = xR_i; /* g[i] := g[i] - (i-th row of A) * xS */ beg = 1; end = lpx_get_mat_row(lp, i, A_ndx, A_val); for (t = beg; t <= end; t++) { j = m + A_ndx[t]; /* a[i,j] != 0 */ /* determine xS[j] */ #if 0 /* 21/XII-2003 */ if (tagx[j] == LPX_BS) xS_j = bbar[posx[j]]; else xS_j = spx_eval_xn_j(lp, posx[j] - m); #else lpx_get_col_info(lp, j-m, NULL, &xS_j, NULL); xS_j /= lpx_get_sjj(lp, j-m); #endif /* g[i] := g[i] - a[i,j] * xS[j] */ rii = lpx_get_rii(lp, i); sjj = lpx_get_sjj(lp, j-m); g_i -= (rii * A_val[t] * sjj) * xS_j; } /* unscale xR[i] and g[i] (if required) */ if (!scaled) { rii = lpx_get_rii(lp, i); xR_i /= rii, g_i /= rii; } /* determine absolute error */ temp = fabs(g_i); if (kkt->pe_ae_max < temp) kkt->pe_ae_max = temp, kkt->pe_ae_row = i; /* determine relative error */ temp /= (1.0 + fabs(xR_i)); if (kkt->pe_re_max < temp) kkt->pe_re_max = temp, kkt->pe_re_row = i; } xfree(A_ndx); xfree(A_val); /* estimate the solution quality */ if (kkt->pe_re_max <= 1e-9) kkt->pe_quality = 'H'; else if (kkt->pe_re_max <= 1e-6) kkt->pe_quality = 'M'; else if (kkt->pe_re_max <= 1e-3) kkt->pe_quality = 'L'; else kkt->pe_quality = '?'; /*--------------------------------------------------------------*/ /* compute largest absolute and relative errors and corresponding variable indices for the condition (KKT.PB) */ kkt->pb_ae_max = 0.0, kkt->pb_ae_ind = 0; kkt->pb_re_max = 0.0, kkt->pb_re_ind = 0; for (k = 1; k <= m+n; k++) { /* determine x[k] */ if (k <= m) { lpx_get_row_bnds(lp, k, &typx, &lb, &ub); rii = lpx_get_rii(lp, k); lb *= rii; ub *= rii; lpx_get_row_info(lp, k, &tagx, &x_k, NULL); x_k *= rii; } else { lpx_get_col_bnds(lp, k-m, &typx, &lb, &ub); sjj = lpx_get_sjj(lp, k-m); lb /= sjj; ub /= sjj; lpx_get_col_info(lp, k-m, &tagx, &x_k, NULL); x_k /= sjj; } /* skip non-basic variable */ if (tagx != LPX_BS) continue; /* compute h[k] */ h_k = 0.0; switch (typx) { case LPX_FR: break; case LPX_LO: if (x_k < lb) h_k = x_k - lb; break; case LPX_UP: if (x_k > ub) h_k = x_k - ub; break; case LPX_DB: case LPX_FX: if (x_k < lb) h_k = x_k - lb; if (x_k > ub) h_k = x_k - ub; break; default: xassert(typx != typx); } /* unscale x[k] and h[k] (if required) */ if (!scaled) { if (k <= m) { rii = lpx_get_rii(lp, k); x_k /= rii, h_k /= rii; } else { sjj = lpx_get_sjj(lp, k-m); x_k *= sjj, h_k *= sjj; } } /* determine absolute error */ temp = fabs(h_k); if (kkt->pb_ae_max < temp) kkt->pb_ae_max = temp, kkt->pb_ae_ind = k; /* determine relative error */ temp /= (1.0 + fabs(x_k)); if (kkt->pb_re_max < temp) kkt->pb_re_max = temp, kkt->pb_re_ind = k; } /* estimate the solution quality */ if (kkt->pb_re_max <= 1e-9) kkt->pb_quality = 'H'; else if (kkt->pb_re_max <= 1e-6) kkt->pb_quality = 'M'; else if (kkt->pb_re_max <= 1e-3) kkt->pb_quality = 'L'; else kkt->pb_quality = '?'; /*--------------------------------------------------------------*/ /* compute largest absolute and relative errors and corresponding column indices for the condition (KKT.DE) */ kkt->de_ae_max = 0.0, kkt->de_ae_col = 0; kkt->de_re_max = 0.0, kkt->de_re_col = 0; A_ndx = xcalloc(1+m, sizeof(int)); A_val = xcalloc(1+m, sizeof(double)); for (j = m+1; j <= m+n; j++) { /* determine cS[j] */ #if 0 /* 21/XII-2003 */ cS_j = coef[j]; #else sjj = lpx_get_sjj(lp, j-m); cS_j = lpx_get_obj_coef(lp, j-m) * sjj; #endif /* determine dS[j] */ #if 0 /* 21/XII-2003 */ if (tagx[j] == LPX_BS) dS_j = 0.0; else dS_j = cbar[posx[j] - m]; #else lpx_get_col_info(lp, j-m, NULL, NULL, &dS_j); dS_j *= sjj; #endif /* u[j] := dS[j] - cS[j] */ u_j = dS_j - cS_j; /* u[j] := u[j] + (j-th column of A) * (dR - cR) */ beg = 1; end = lpx_get_mat_col(lp, j-m, A_ndx, A_val); for (t = beg; t <= end; t++) { i = A_ndx[t]; /* a[i,j] != 0 */ /* determine cR[i] */ #if 0 /* 21/XII-2003 */ cR_i = coef[i]; #else cR_i = 0.0; #endif /* determine dR[i] */ #if 0 /* 21/XII-2003 */ if (tagx[i] == LPX_BS) dR_i = 0.0; else dR_i = cbar[posx[i] - m]; #else lpx_get_row_info(lp, i, NULL, NULL, &dR_i); rii = lpx_get_rii(lp, i); dR_i /= rii; #endif /* u[j] := u[j] + a[i,j] * (dR[i] - cR[i]) */ rii = lpx_get_rii(lp, i); sjj = lpx_get_sjj(lp, j-m); u_j += (rii * A_val[t] * sjj) * (dR_i - cR_i); } /* unscale cS[j], dS[j], and u[j] (if required) */ if (!scaled) { sjj = lpx_get_sjj(lp, j-m); cS_j /= sjj, dS_j /= sjj, u_j /= sjj; } /* determine absolute error */ temp = fabs(u_j); if (kkt->de_ae_max < temp) kkt->de_ae_max = temp, kkt->de_ae_col = j - m; /* determine relative error */ temp /= (1.0 + fabs(dS_j - cS_j)); if (kkt->de_re_max < temp) kkt->de_re_max = temp, kkt->de_re_col = j - m; } xfree(A_ndx); xfree(A_val); /* estimate the solution quality */ if (kkt->de_re_max <= 1e-9) kkt->de_quality = 'H'; else if (kkt->de_re_max <= 1e-6) kkt->de_quality = 'M'; else if (kkt->de_re_max <= 1e-3) kkt->de_quality = 'L'; else kkt->de_quality = '?'; /*--------------------------------------------------------------*/ /* compute largest absolute and relative errors and corresponding variable indices for the condition (KKT.DB) */ kkt->db_ae_max = 0.0, kkt->db_ae_ind = 0; kkt->db_re_max = 0.0, kkt->db_re_ind = 0; for (k = 1; k <= m+n; k++) { /* determine c[k] */ #if 0 /* 21/XII-2003 */ c_k = coef[k]; #else if (k <= m) c_k = 0.0; else { sjj = lpx_get_sjj(lp, k-m); c_k = lpx_get_obj_coef(lp, k-m) / sjj; } #endif /* determine d[k] */ #if 0 /* 21/XII-2003 */ d_k = cbar[j-m]; #else if (k <= m) { lpx_get_row_info(lp, k, &tagx, NULL, &d_k); rii = lpx_get_rii(lp, k); d_k /= rii; } else { lpx_get_col_info(lp, k-m, &tagx, NULL, &d_k); sjj = lpx_get_sjj(lp, k-m); d_k *= sjj; } #endif /* skip basic variable */ if (tagx == LPX_BS) continue; /* compute v[k] */ v_k = 0.0; switch (tagx) { case LPX_NL: switch (dir) { case LPX_MIN: if (d_k < 0.0) v_k = d_k; break; case LPX_MAX: if (d_k > 0.0) v_k = d_k; break; default: xassert(dir != dir); } break; case LPX_NU: switch (dir) { case LPX_MIN: if (d_k > 0.0) v_k = d_k; break; case LPX_MAX: if (d_k < 0.0) v_k = d_k; break; default: xassert(dir != dir); } break; case LPX_NF: v_k = d_k; break; case LPX_NS: break; default: xassert(tagx != tagx); } /* unscale c[k], d[k], and v[k] (if required) */ if (!scaled) { if (k <= m) { rii = lpx_get_rii(lp, k); c_k *= rii, d_k *= rii, v_k *= rii; } else { sjj = lpx_get_sjj(lp, k-m); c_k /= sjj, d_k /= sjj, v_k /= sjj; } } /* determine absolute error */ temp = fabs(v_k); if (kkt->db_ae_max < temp) kkt->db_ae_max = temp, kkt->db_ae_ind = k; /* determine relative error */ temp /= (1.0 + fabs(d_k - c_k)); if (kkt->db_re_max < temp) kkt->db_re_max = temp, kkt->db_re_ind = k; } /* estimate the solution quality */ if (kkt->db_re_max <= 1e-9) kkt->db_quality = 'H'; else if (kkt->db_re_max <= 1e-6) kkt->db_quality = 'M'; else if (kkt->db_re_max <= 1e-3) kkt->db_quality = 'L'; else kkt->db_quality = '?'; /* complementary slackness is always satisfied by definition for any basic solution, so not checked */ kkt->cs_ae_max = 0.0, kkt->cs_ae_ind = 0; kkt->cs_re_max = 0.0, kkt->cs_re_ind = 0; kkt->cs_quality = 'H'; return; }
static void transform(struct dsa *dsa) { /* transform original LP to standard formulation */ LPX *lp = dsa->lp; int orig_m = dsa->orig_m; int orig_n = dsa->orig_n; int *ref = dsa->ref; int m = dsa->m; int n = dsa->n; double *b = dsa->b; double *c = dsa->c; int i, j, k, type, t, ii, len, *ind; double lb, ub, coef, rii, sjj, *val; /* initialize components of transformed LP */ dsa->ne = 0; for (i = 1; i <= m; i++) b[i] = 0.0; c[0] = lpx_get_obj_coef(lp, 0); for (j = 1; j <= n; j++) c[j] = 0.0; /* i and j are, respectively, ordinal number of current row and ordinal number of current column in transformed LP */ i = j = 0; /* transform rows (auxiliary variables) */ for (k = 1; k <= orig_m; k++) { type = lpx_get_row_type(lp, k); rii = lpx_get_rii(lp, k); lb = lpx_get_row_lb(lp, k) * rii; ub = lpx_get_row_ub(lp, k) * rii; switch (type) { case LPX_FR: /* source: -inf < (L.F.) < +inf */ /* result: ignore free row */ ref[k] = 0; break; case LPX_LO: /* source: lb <= (L.F.) < +inf */ /* result: (L.F.) - x' = lb, x' >= 0 */ i++; j++; ref[k] = i; new_coef(dsa, i, j, -1.0); b[i] = lb; break; case LPX_UP: /* source: -inf < (L.F.) <= ub */ /* result: (L.F.) + x' = ub, x' >= 0 */ i++; j++; ref[k] = i; new_coef(dsa, i, j, +1.0); b[i] = ub; break; case LPX_DB: /* source: lb <= (L.F.) <= ub */ /* result: (L.F.) - x' = lb, x' + x'' = ub - lb */ i++; j++; ref[k] = i; new_coef(dsa, i, j, -1.0); b[i] = lb; i++; new_coef(dsa, i, j, +1.0); j++; new_coef(dsa, i, j, +1.0); b[i] = ub - lb; break; case LPX_FX: /* source: (L.F.) = lb */ /* result: (L.F.) = lb */ i++; ref[k] = i; b[i] = lb; break; default: insist(type != type); } } /* transform columns (structural variables) */ ind = ucalloc(1+orig_m, sizeof(int)); val = ucalloc(1+orig_m, sizeof(double)); for (k = 1; k <= orig_n; k++) { type = lpx_get_col_type(lp, k); sjj = lpx_get_sjj(lp, k); lb = lpx_get_col_lb(lp, k) / sjj; ub = lpx_get_col_ub(lp, k) / sjj; coef = lpx_get_obj_coef(lp, k) * sjj; len = lpx_get_mat_col(lp, k, ind, val); for (t = 1; t <= len; t++) val[t] *= (lpx_get_rii(lp, ind[t]) * sjj); switch (type) { case LPX_FR: /* source: -inf < x < +inf */ /* result: x = x' - x'', x' >= 0, x'' >= 0 */ j++; ref[orig_m+k] = j; for (t = 1; t <= len; t++) { ii = ref[ind[t]]; if (ii != 0) new_coef(dsa, ii, j, +val[t]); } c[j] = +coef; j++; for (t = 1; t <= len; t++) { ii = ref[ind[t]]; if (ii != 0) new_coef(dsa, ii, j, -val[t]); } c[j] = -coef; break; case LPX_LO: /* source: lb <= x < +inf */ /* result: x = lb + x', x' >= 0 */ j++; ref[orig_m+k] = j; for (t = 1; t <= len; t++) { ii = ref[ind[t]]; if (ii != 0) { new_coef(dsa, ii, j, val[t]); b[ii] -= val[t] * lb; } } c[j] = +coef; c[0] += c[j] * lb; break; case LPX_UP: /* source: -inf < x <= ub */ /* result: x = ub - x', x' >= 0 */ j++; ref[orig_m+k] = j; for (t = 1; t <= len; t++) { ii = ref[ind[t]]; if (ii != 0) { new_coef(dsa, ii, j, -val[t]); b[ii] -= val[t] * ub; } } c[j] = -coef; c[0] -= c[j] * ub; break; case LPX_DB: /* source: lb <= x <= ub */ /* result: x = lb + x', x' + x'' = ub - lb */ j++; ref[orig_m+k] = j; for (t = 1; t <= len; t++) { ii = ref[ind[t]]; if (ii != 0) { new_coef(dsa, ii, j, val[t]); b[ii] -= val[t] * lb; } } c[j] = +coef; c[0] += c[j] * lb; i++; new_coef(dsa, i, j, +1.0); j++; new_coef(dsa, i, j, +1.0); b[i] = ub - lb; break; case LPX_FX: /* source: x = lb */ /* result: just substitute */ ref[orig_m+k] = 0; for (t = 1; t <= len; t++) { ii = ref[ind[t]]; if (ii != 0) b[ii] -= val[t] * lb; } c[0] += coef * lb; break; default: insist(type != type); } } ufree(ind); ufree(val); /* end of transformation */ insist(i == m && j == n); /* change the objective sign in case of maximization */ if (lpx_get_obj_dir(lp) == LPX_MAX) for (j = 0; j <= n; j++) c[j] = -c[j]; return; }
int lpx_integer(LPX *mip) { int m = lpx_get_num_rows(mip); int n = lpx_get_num_cols(mip); MIPTREE *tree; LPX *lp; int ret, i, j, stat, type, len, *ind; double lb, ub, coef, *val; #if 0 /* the problem must be of MIP class */ if (lpx_get_class(mip) != LPX_MIP) { print("lpx_integer: problem is not of MIP class"); ret = LPX_E_FAULT; goto done; } #endif /* an optimal solution of LP relaxation must be known */ if (lpx_get_status(mip) != LPX_OPT) { print("lpx_integer: optimal solution of LP relaxation required" ); ret = LPX_E_FAULT; goto done; } /* bounds of all integer variables must be integral */ for (j = 1; j <= n; j++) { if (lpx_get_col_kind(mip, j) != LPX_IV) continue; type = lpx_get_col_type(mip, j); if (type == LPX_LO || type == LPX_DB || type == LPX_FX) { lb = lpx_get_col_lb(mip, j); if (lb != floor(lb)) { print("lpx_integer: integer column %d has non-integer lo" "wer bound or fixed value %g", j, lb); ret = LPX_E_FAULT; goto done; } } if (type == LPX_UP || type == LPX_DB) { ub = lpx_get_col_ub(mip, j); if (ub != floor(ub)) { print("lpx_integer: integer column %d has non-integer up" "per bound %g", j, ub); ret = LPX_E_FAULT; goto done; } } } /* it seems all is ok */ if (lpx_get_int_parm(mip, LPX_K_MSGLEV) >= 2) print("Integer optimization begins..."); /* create the branch-and-bound tree */ tree = mip_create_tree(m, n, lpx_get_obj_dir(mip)); /* set up column kinds */ for (j = 1; j <= n; j++) tree->int_col[j] = (lpx_get_col_kind(mip, j) == LPX_IV); /* access the LP relaxation template */ lp = tree->lp; /* set up the objective function */ tree->int_obj = 1; for (j = 0; j <= tree->n; j++) { coef = lpx_get_obj_coef(mip, j); lpx_set_obj_coef(lp, j, coef); if (coef != 0.0 && !(tree->int_col[j] && coef == floor(coef))) tree->int_obj = 0; } if (lpx_get_int_parm(mip, LPX_K_MSGLEV) >= 2 && tree->int_obj) print("Objective function is integral"); /* set up the constraint matrix */ ind = xcalloc(1+n, sizeof(int)); val = xcalloc(1+n, sizeof(double)); for (i = 1; i <= m; i++) { len = lpx_get_mat_row(mip, i, ind, val); lpx_set_mat_row(lp, i, len, ind, val); } xfree(ind); xfree(val); /* set up scaling matrices */ for (i = 1; i <= m; i++) lpx_set_rii(lp, i, lpx_get_rii(mip, i)); for (j = 1; j <= n; j++) lpx_set_sjj(lp, j, lpx_get_sjj(mip, j)); /* revive the root subproblem */ mip_revive_node(tree, 1); /* set up row attributes for the root subproblem */ for (i = 1; i <= m; i++) { type = lpx_get_row_type(mip, i); lb = lpx_get_row_lb(mip, i); ub = lpx_get_row_ub(mip, i); stat = lpx_get_row_stat(mip, i); lpx_set_row_bnds(lp, i, type, lb, ub); lpx_set_row_stat(lp, i, stat); } /* set up column attributes for the root subproblem */ for (j = 1; j <= n; j++) { type = lpx_get_col_type(mip, j); lb = lpx_get_col_lb(mip, j); ub = lpx_get_col_ub(mip, j); stat = lpx_get_col_stat(mip, j); lpx_set_col_bnds(lp, j, type, lb, ub); lpx_set_col_stat(lp, j, stat); } /* freeze the root subproblem */ mip_freeze_node(tree); /* inherit some control parameters and statistics */ tree->msg_lev = lpx_get_int_parm(mip, LPX_K_MSGLEV); if (tree->msg_lev > 2) tree->msg_lev = 2; tree->branch = lpx_get_int_parm(mip, LPX_K_BRANCH); tree->btrack = lpx_get_int_parm(mip, LPX_K_BTRACK); tree->tol_int = lpx_get_real_parm(mip, LPX_K_TOLINT); tree->tol_obj = lpx_get_real_parm(mip, LPX_K_TOLOBJ); tree->tm_lim = lpx_get_real_parm(mip, LPX_K_TMLIM); lpx_set_int_parm(lp, LPX_K_BFTYPE, lpx_get_int_parm(mip, LPX_K_BFTYPE)); lpx_set_int_parm(lp, LPX_K_PRICE, lpx_get_int_parm(mip, LPX_K_PRICE)); lpx_set_real_parm(lp, LPX_K_RELAX, lpx_get_real_parm(mip, LPX_K_RELAX)); lpx_set_real_parm(lp, LPX_K_TOLBND, lpx_get_real_parm(mip, LPX_K_TOLBND)); lpx_set_real_parm(lp, LPX_K_TOLDJ, lpx_get_real_parm(mip, LPX_K_TOLDJ)); lpx_set_real_parm(lp, LPX_K_TOLPIV, lpx_get_real_parm(mip, LPX_K_TOLPIV)); lpx_set_int_parm(lp, LPX_K_ITLIM, lpx_get_int_parm(mip, LPX_K_ITLIM)); lpx_set_int_parm(lp, LPX_K_ITCNT, lpx_get_int_parm(mip, LPX_K_ITCNT)); /* reset the status of MIP solution */ lpx_put_mip_soln(mip, LPX_I_UNDEF, NULL, NULL); /* try solving the problem */ ret = mip_driver(tree); /* if an integer feasible solution has been found, copy it to the MIP problem object */ if (tree->found) lpx_put_mip_soln(mip, LPX_I_FEAS, &tree->mipx[0], &tree->mipx[m]); /* copy back statistics about spent resources */ lpx_set_real_parm(mip, LPX_K_TMLIM, tree->tm_lim); lpx_set_int_parm(mip, LPX_K_ITLIM, lpx_get_int_parm(lp, LPX_K_ITLIM)); lpx_set_int_parm(mip, LPX_K_ITCNT, lpx_get_int_parm(lp, LPX_K_ITCNT)); /* analyze exit code reported by the mip driver */ switch (ret) { case MIP_E_OK: if (tree->found) { if (lpx_get_int_parm(mip, LPX_K_MSGLEV) >= 3) print("INTEGER OPTIMAL SOLUTION FOUND"); lpx_put_mip_soln(mip, LPX_I_OPT, NULL, NULL); } else { if (lpx_get_int_parm(mip, LPX_K_MSGLEV) >= 3) print("PROBLEM HAS NO INTEGER FEASIBLE SOLUTION"); lpx_put_mip_soln(mip, LPX_I_NOFEAS, NULL, NULL); } ret = LPX_E_OK; break; case MIP_E_ITLIM: if (lpx_get_int_parm(mip, LPX_K_MSGLEV) >= 3) print("ITERATIONS LIMIT EXCEEDED; SEARCH TERMINATED"); ret = LPX_E_ITLIM; break; case MIP_E_TMLIM: if (lpx_get_int_parm(mip, LPX_K_MSGLEV) >= 3) print("TIME LIMIT EXCEEDED; SEARCH TERMINATED"); ret = LPX_E_TMLIM; break; case MIP_E_ERROR: if (lpx_get_int_parm(mip, LPX_K_MSGLEV) >= 1) print("lpx_integer: cannot solve current LP relaxation"); ret = LPX_E_SING; break; default: xassert(ret != ret); } /* delete the branch-and-bound tree */ mip_delete_tree(tree); done: /* return to the application program */ return ret; }