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; }
int lpx_print_prob(LPX *lp, const char *fname) { XFILE *fp; int m, n, mip, i, j, len, t, type, *ndx; double coef, lb, ub, *val; char *str, name[255+1]; xprintf("lpx_write_prob: writing problem data to `%s'...\n", fname); fp = xfopen(fname, "w"); if (fp == NULL) { xprintf("lpx_write_prob: unable to create `%s' - %s\n", fname, strerror(errno)); goto fail; } m = lpx_get_num_rows(lp); n = lpx_get_num_cols(lp); mip = (lpx_get_class(lp) == LPX_MIP); str = (void *)lpx_get_prob_name(lp); xfprintf(fp, "Problem: %s\n", str == NULL ? "(unnamed)" : str); xfprintf(fp, "Class: %s\n", !mip ? "LP" : "MIP"); xfprintf(fp, "Rows: %d\n", m); if (!mip) xfprintf(fp, "Columns: %d\n", n); else xfprintf(fp, "Columns: %d (%d integer, %d binary)\n", n, lpx_get_num_int(lp), lpx_get_num_bin(lp)); xfprintf(fp, "Non-zeros: %d\n", lpx_get_num_nz(lp)); xfprintf(fp, "\n"); xfprintf(fp, "*** OBJECTIVE FUNCTION ***\n"); xfprintf(fp, "\n"); switch (lpx_get_obj_dir(lp)) { case LPX_MIN: xfprintf(fp, "Minimize:"); break; case LPX_MAX: xfprintf(fp, "Maximize:"); break; default: xassert(lp != lp); } str = (void *)lpx_get_obj_name(lp); xfprintf(fp, " %s\n", str == NULL ? "(unnamed)" : str); coef = lpx_get_obj_coef(lp, 0); if (coef != 0.0) xfprintf(fp, "%*.*g %s\n", DBL_DIG+7, DBL_DIG, coef, "(constant term)"); for (i = 1; i <= m; i++) #if 0 { coef = lpx_get_row_coef(lp, i); #else { coef = 0.0; #endif if (coef != 0.0) xfprintf(fp, "%*.*g %s\n", DBL_DIG+7, DBL_DIG, coef, row_name(lp, i, name)); } for (j = 1; j <= n; j++) { coef = lpx_get_obj_coef(lp, j); if (coef != 0.0) xfprintf(fp, "%*.*g %s\n", DBL_DIG+7, DBL_DIG, coef, col_name(lp, j, name)); } xfprintf(fp, "\n"); xfprintf(fp, "*** ROWS (CONSTRAINTS) ***\n"); ndx = xcalloc(1+n, sizeof(int)); val = xcalloc(1+n, sizeof(double)); for (i = 1; i <= m; i++) { xfprintf(fp, "\n"); xfprintf(fp, "Row %d: %s", i, row_name(lp, i, name)); lpx_get_row_bnds(lp, i, &type, &lb, &ub); switch (type) { case LPX_FR: xfprintf(fp, " free"); break; case LPX_LO: xfprintf(fp, " >= %.*g", DBL_DIG, lb); break; case LPX_UP: xfprintf(fp, " <= %.*g", DBL_DIG, ub); break; case LPX_DB: xfprintf(fp, " >= %.*g <= %.*g", DBL_DIG, lb, DBL_DIG, ub); break; case LPX_FX: xfprintf(fp, " = %.*g", DBL_DIG, lb); break; default: xassert(type != type); } xfprintf(fp, "\n"); #if 0 coef = lpx_get_row_coef(lp, i); #else coef = 0.0; #endif if (coef != 0.0) xfprintf(fp, "%*.*g %s\n", DBL_DIG+7, DBL_DIG, coef, "(objective)"); len = lpx_get_mat_row(lp, i, ndx, val); for (t = 1; t <= len; t++) xfprintf(fp, "%*.*g %s\n", DBL_DIG+7, DBL_DIG, val[t], col_name(lp, ndx[t], name)); } xfree(ndx); xfree(val); xfprintf(fp, "\n"); xfprintf(fp, "*** COLUMNS (VARIABLES) ***\n"); ndx = xcalloc(1+m, sizeof(int)); val = xcalloc(1+m, sizeof(double)); for (j = 1; j <= n; j++) { xfprintf(fp, "\n"); xfprintf(fp, "Col %d: %s", j, col_name(lp, j, name)); if (mip) { switch (lpx_get_col_kind(lp, j)) { case LPX_CV: break; case LPX_IV: xfprintf(fp, " integer"); break; default: xassert(lp != lp); } } lpx_get_col_bnds(lp, j, &type, &lb, &ub); switch (type) { case LPX_FR: xfprintf(fp, " free"); break; case LPX_LO: xfprintf(fp, " >= %.*g", DBL_DIG, lb); break; case LPX_UP: xfprintf(fp, " <= %.*g", DBL_DIG, ub); break; case LPX_DB: xfprintf(fp, " >= %.*g <= %.*g", DBL_DIG, lb, DBL_DIG, ub); break; case LPX_FX: xfprintf(fp, " = %.*g", DBL_DIG, lb); break; default: xassert(type != type); } xfprintf(fp, "\n"); coef = lpx_get_obj_coef(lp, j); if (coef != 0.0) xfprintf(fp, "%*.*g %s\n", DBL_DIG+7, DBL_DIG, coef, "(objective)"); len = lpx_get_mat_col(lp, j, ndx, val); for (t = 1; t <= len; t++) xfprintf(fp, "%*.*g %s\n", DBL_DIG+7, DBL_DIG, val[t], row_name(lp, ndx[t], name)); } xfree(ndx); xfree(val); xfprintf(fp, "\n"); xfprintf(fp, "End of output\n"); xfflush(fp); if (xferror(fp)) { xprintf("lpx_write_prob: write error on `%s' - %s\n", fname, strerror(errno)); goto fail; } xfclose(fp); return 0; fail: if (fp != NULL) xfclose(fp); return 1; } #undef row_name #undef col_name /*---------------------------------------------------------------------- -- lpx_print_sol - write LP problem solution in printable format. -- -- *Synopsis* -- -- #include "glplpx.h" -- int lpx_print_sol(LPX *lp, char *fname); -- -- *Description* -- -- The routine lpx_print_sol writes the current basic solution of an LP -- problem, which is specified by the pointer lp, to a text file, whose -- name is the character string fname, in printable format. -- -- Information reported by the routine lpx_print_sol is intended mainly -- for visual analysis. -- -- *Returns* -- -- If the operation was successful, the routine returns zero. Otherwise -- the routine prints an error message and returns non-zero. */ int lpx_print_sol(LPX *lp, const char *fname) { XFILE *fp; int what, round; xprintf( "lpx_print_sol: writing LP problem solution to `%s'...\n", fname); fp = xfopen(fname, "w"); if (fp == NULL) { xprintf("lpx_print_sol: can't create `%s' - %s\n", fname, strerror(errno)); goto fail; } /* problem name */ { const char *name; name = lpx_get_prob_name(lp); if (name == NULL) name = ""; xfprintf(fp, "%-12s%s\n", "Problem:", name); } /* number of rows (auxiliary variables) */ { int nr; nr = lpx_get_num_rows(lp); xfprintf(fp, "%-12s%d\n", "Rows:", nr); } /* number of columns (structural variables) */ { int nc; nc = lpx_get_num_cols(lp); xfprintf(fp, "%-12s%d\n", "Columns:", nc); } /* number of non-zeros (constraint coefficients) */ { int nz; nz = lpx_get_num_nz(lp); xfprintf(fp, "%-12s%d\n", "Non-zeros:", nz); } /* solution status */ { int status; status = lpx_get_status(lp); xfprintf(fp, "%-12s%s\n", "Status:", status == LPX_OPT ? "OPTIMAL" : status == LPX_FEAS ? "FEASIBLE" : status == LPX_INFEAS ? "INFEASIBLE (INTERMEDIATE)" : status == LPX_NOFEAS ? "INFEASIBLE (FINAL)" : status == LPX_UNBND ? "UNBOUNDED" : status == LPX_UNDEF ? "UNDEFINED" : "???"); } /* objective function */ { char *name; int dir; double obj; name = (void *)lpx_get_obj_name(lp); dir = lpx_get_obj_dir(lp); obj = lpx_get_obj_val(lp); xfprintf(fp, "%-12s%s%s%.10g %s\n", "Objective:", name == NULL ? "" : name, name == NULL ? "" : " = ", obj, dir == LPX_MIN ? "(MINimum)" : dir == LPX_MAX ? "(MAXimum)" : "(" "???" ")"); } /* main sheet */ for (what = 1; what <= 2; what++) { int mn, ij; xfprintf(fp, "\n"); xfprintf(fp, " No. %-12s St Activity Lower bound Upp" "er bound Marginal\n", what == 1 ? " Row name" : "Column name"); xfprintf(fp, "------ ------------ -- ------------- -----------" "-- ------------- -------------\n"); mn = (what == 1 ? lpx_get_num_rows(lp) : lpx_get_num_cols(lp)); for (ij = 1; ij <= mn; ij++) { const char *name; int typx, tagx; double lb, ub, vx, dx; if (what == 1) { name = lpx_get_row_name(lp, ij); if (name == NULL) name = ""; lpx_get_row_bnds(lp, ij, &typx, &lb, &ub); round = lpx_get_int_parm(lp, LPX_K_ROUND); lpx_set_int_parm(lp, LPX_K_ROUND, 1); lpx_get_row_info(lp, ij, &tagx, &vx, &dx); lpx_set_int_parm(lp, LPX_K_ROUND, round); } else { name = lpx_get_col_name(lp, ij); if (name == NULL) name = ""; lpx_get_col_bnds(lp, ij, &typx, &lb, &ub); round = lpx_get_int_parm(lp, LPX_K_ROUND); lpx_set_int_parm(lp, LPX_K_ROUND, 1); lpx_get_col_info(lp, ij, &tagx, &vx, &dx); lpx_set_int_parm(lp, LPX_K_ROUND, round); } /* row/column ordinal number */ xfprintf(fp, "%6d ", ij); /* row column/name */ if (strlen(name) <= 12) xfprintf(fp, "%-12s ", name); else xfprintf(fp, "%s\n%20s", name, ""); /* row/column status */ xfprintf(fp, "%s ", tagx == LPX_BS ? "B " : tagx == LPX_NL ? "NL" : tagx == LPX_NU ? "NU" : tagx == LPX_NF ? "NF" : tagx == LPX_NS ? "NS" : "??"); /* row/column primal activity */ xfprintf(fp, "%13.6g ", vx); /* row/column lower bound */ if (typx == LPX_LO || typx == LPX_DB || typx == LPX_FX) xfprintf(fp, "%13.6g ", lb); else xfprintf(fp, "%13s ", ""); /* row/column upper bound */ if (typx == LPX_UP || typx == LPX_DB) xfprintf(fp, "%13.6g ", ub); else if (typx == LPX_FX) xfprintf(fp, "%13s ", "="); else xfprintf(fp, "%13s ", ""); /* row/column dual activity */ if (tagx != LPX_BS) { if (dx == 0.0) xfprintf(fp, "%13s", "< eps"); else xfprintf(fp, "%13.6g", dx); } /* end of line */ xfprintf(fp, "\n"); } } xfprintf(fp, "\n"); #if 1 if (lpx_get_prim_stat(lp) != LPX_P_UNDEF && lpx_get_dual_stat(lp) != LPX_D_UNDEF) { int m = lpx_get_num_rows(lp); LPXKKT kkt; xfprintf(fp, "Karush-Kuhn-Tucker optimality conditions:\n\n"); lpx_check_kkt(lp, 1, &kkt); xfprintf(fp, "KKT.PE: max.abs.err. = %.2e on row %d\n", kkt.pe_ae_max, kkt.pe_ae_row); xfprintf(fp, " max.rel.err. = %.2e on row %d\n", kkt.pe_re_max, kkt.pe_re_row); switch (kkt.pe_quality) { case 'H': xfprintf(fp, " High quality\n"); break; case 'M': xfprintf(fp, " Medium quality\n"); break; case 'L': xfprintf(fp, " Low quality\n"); break; default: xfprintf(fp, " PRIMAL SOLUTION IS WRONG\n"); break; } xfprintf(fp, "\n"); xfprintf(fp, "KKT.PB: max.abs.err. = %.2e on %s %d\n", kkt.pb_ae_max, kkt.pb_ae_ind <= m ? "row" : "column", kkt.pb_ae_ind <= m ? kkt.pb_ae_ind : kkt.pb_ae_ind - m); xfprintf(fp, " max.rel.err. = %.2e on %s %d\n", kkt.pb_re_max, kkt.pb_re_ind <= m ? "row" : "column", kkt.pb_re_ind <= m ? kkt.pb_re_ind : kkt.pb_re_ind - m); switch (kkt.pb_quality) { case 'H': xfprintf(fp, " High quality\n"); break; case 'M': xfprintf(fp, " Medium quality\n"); break; case 'L': xfprintf(fp, " Low quality\n"); break; default: xfprintf(fp, " PRIMAL SOLUTION IS INFEASIBLE\n"); break; } xfprintf(fp, "\n"); xfprintf(fp, "KKT.DE: max.abs.err. = %.2e on column %d\n", kkt.de_ae_max, kkt.de_ae_col); xfprintf(fp, " max.rel.err. = %.2e on column %d\n", kkt.de_re_max, kkt.de_re_col); switch (kkt.de_quality) { case 'H': xfprintf(fp, " High quality\n"); break; case 'M': xfprintf(fp, " Medium quality\n"); break; case 'L': xfprintf(fp, " Low quality\n"); break; default: xfprintf(fp, " DUAL SOLUTION IS WRONG\n"); break; } xfprintf(fp, "\n"); xfprintf(fp, "KKT.DB: max.abs.err. = %.2e on %s %d\n", kkt.db_ae_max, kkt.db_ae_ind <= m ? "row" : "column", kkt.db_ae_ind <= m ? kkt.db_ae_ind : kkt.db_ae_ind - m); xfprintf(fp, " max.rel.err. = %.2e on %s %d\n", kkt.db_re_max, kkt.db_re_ind <= m ? "row" : "column", kkt.db_re_ind <= m ? kkt.db_re_ind : kkt.db_re_ind - m); switch (kkt.db_quality) { case 'H': xfprintf(fp, " High quality\n"); break; case 'M': xfprintf(fp, " Medium quality\n"); break; case 'L': xfprintf(fp, " Low quality\n"); break; default: xfprintf(fp, " DUAL SOLUTION IS INFEASIBLE\n"); break; } xfprintf(fp, "\n"); } #endif #if 1 if (lpx_get_status(lp) == LPX_UNBND) { int m = lpx_get_num_rows(lp); int k = lpx_get_ray_info(lp); xfprintf(fp, "Unbounded ray: %s %d\n", k <= m ? "row" : "column", k <= m ? k : k - m); xfprintf(fp, "\n"); } #endif xfprintf(fp, "End of output\n"); xfflush(fp); if (xferror(fp)) { xprintf("lpx_print_sol: can't write to `%s' - %s\n", fname, strerror(errno)); goto fail; } xfclose(fp); return 0; fail: if (fp != NULL) xfclose(fp); return 1; }
int lpx_prim_ratio_test(LPX *lp, int len, const int ind[], const double val[], int how, double tol) { int i, k, m, n, p, t, typx, tagx; double alfa_i, abs_alfa_i, big, eps, bbar_i, lb_i, ub_i, temp, teta; if (!lpx_is_b_avail(lp)) xfault("lpx_prim_ratio_test: LP basis is not available\n"); if (lpx_get_prim_stat(lp) != LPX_P_FEAS) xfault("lpx_prim_ratio_test: current basic solution is not pri" "mal feasible\n"); if (!(how == +1 || how == -1)) xfault("lpx_prim_ratio_test: how = %d; invalid parameter\n", how); m = lpx_get_num_rows(lp); n = lpx_get_num_cols(lp); /* compute the largest absolute value of the specified influence coefficients */ big = 0.0; for (t = 1; t <= len; t++) { temp = val[t]; if (temp < 0.0) temp = - temp; if (big < temp) big = temp; } /* compute the absolute tolerance eps used to skip small entries of the column */ if (!(0.0 < tol && tol < 1.0)) xfault("lpx_prim_ratio_test: tol = %g; invalid tolerance\n", tol); eps = tol * (1.0 + big); /* initial settings */ p = 0, teta = DBL_MAX, big = 0.0; /* walk through the entries of the specified column */ for (t = 1; t <= len; t++) { /* get the ordinal number of basic variable */ k = ind[t]; if (!(1 <= k && k <= m+n)) xfault("lpx_prim_ratio_test: ind[%d] = %d; variable number " "out of range\n", t, k); if (k <= m) tagx = lpx_get_row_stat(lp, k); else tagx = lpx_get_col_stat(lp, k-m); if (tagx != LPX_BS) xfault("lpx_prim_ratio_test: ind[%d] = %d; non-basic variab" "le not allowed\n", t, k); /* determine index of the variable x[k] in the vector xB */ if (k <= m) i = lpx_get_row_b_ind(lp, k); else i = lpx_get_col_b_ind(lp, k-m); xassert(1 <= i && i <= m); /* determine unscaled bounds and value of the basic variable xB[i] in the current basic solution */ if (k <= m) { typx = lpx_get_row_type(lp, k); lb_i = lpx_get_row_lb(lp, k); ub_i = lpx_get_row_ub(lp, k); bbar_i = lpx_get_row_prim(lp, k); } else { typx = lpx_get_col_type(lp, k-m); lb_i = lpx_get_col_lb(lp, k-m); ub_i = lpx_get_col_ub(lp, k-m); bbar_i = lpx_get_col_prim(lp, k-m); } /* determine influence coefficient for the basic variable x[k] = xB[i] in the explicitly specified column and turn to the case of increasing the variable y in order to simplify the program logic */ alfa_i = (how > 0 ? +val[t] : -val[t]); abs_alfa_i = (alfa_i > 0.0 ? +alfa_i : -alfa_i); /* analyze main cases */ switch (typx) { case LPX_FR: /* xB[i] is free variable */ continue; case LPX_LO: lo: /* xB[i] has an lower bound */ if (alfa_i > - eps) continue; temp = (lb_i - bbar_i) / alfa_i; break; case LPX_UP: up: /* xB[i] has an upper bound */ if (alfa_i < + eps) continue; temp = (ub_i - bbar_i) / alfa_i; break; case LPX_DB: /* xB[i] has both lower and upper bounds */ if (alfa_i < 0.0) goto lo; else goto up; case LPX_FX: /* xB[i] is fixed variable */ if (abs_alfa_i < eps) continue; temp = 0.0; break; default: xassert(typx != typx); } /* if the value of the variable xB[i] violates its lower or upper bound (slightly, because the current basis is assumed to be primal feasible), temp is negative; we can think this happens due to round-off errors and the value is exactly on the bound; this allows replacing temp by zero */ if (temp < 0.0) temp = 0.0; /* apply the minimal ratio test */ if (teta > temp || teta == temp && big < abs_alfa_i) p = k, teta = temp, big = abs_alfa_i; } /* return the ordinal number of the chosen basic variable */ return p; }