void lpx_get_col_info(glp_prob *lp, int j, int *tagx, double *vx, double *dx) { /* obtain column solution information */ if (tagx != NULL) *tagx = lpx_get_col_stat(lp, j); if (vx != NULL) *vx = lpx_get_col_prim(lp, j); if (dx != NULL) *dx = lpx_get_col_dual(lp, j); return; }
int lpx_dual_ratio_test(LPX *lp, int len, const int ind[], const double val[], int how, double tol) { int k, m, n, t, q, tagx; double dir, alfa_j, abs_alfa_j, big, eps, cbar_j, temp, teta; if (!lpx_is_b_avail(lp)) xfault("lpx_dual_ratio_test: LP basis is not available\n"); if (lpx_get_dual_stat(lp) != LPX_D_FEAS) xfault("lpx_dual_ratio_test: current basic solution is not dua" "l feasible\n"); if (!(how == +1 || how == -1)) xfault("lpx_dual_ratio_test: how = %d; invalid parameter\n", how); m = lpx_get_num_rows(lp); n = lpx_get_num_cols(lp); dir = (lpx_get_obj_dir(lp) == LPX_MIN ? +1.0 : -1.0); /* 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 row */ if (!(0.0 < tol && tol < 1.0)) xfault("lpx_dual_ratio_test: tol = %g; invalid tolerance\n", tol); eps = tol * (1.0 + big); /* initial settings */ q = 0, teta = DBL_MAX, big = 0.0; /* walk through the entries of the specified row */ for (t = 1; t <= len; t++) { /* get ordinal number of non-basic variable */ k = ind[t]; if (!(1 <= k && k <= m+n)) xfault("lpx_dual_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_dual_ratio_test: ind[%d] = %d; basic variable n" "ot allowed\n", t, k); /* determine unscaled reduced cost of the non-basic variable x[k] = xN[j] in the current basic solution */ if (k <= m) cbar_j = lpx_get_row_dual(lp, k); else cbar_j = lpx_get_col_dual(lp, k-m); /* determine influence coefficient at the non-basic variable x[k] = xN[j] in the explicitly specified row and turn to the case of increasing the variable y in order to simplify program logic */ alfa_j = (how > 0 ? +val[t] : -val[t]); abs_alfa_j = (alfa_j > 0.0 ? +alfa_j : -alfa_j); /* analyze main cases */ switch (tagx) { case LPX_NL: /* xN[j] is on its lower bound */ if (alfa_j < +eps) continue; temp = (dir * cbar_j) / alfa_j; break; case LPX_NU: /* xN[j] is on its upper bound */ if (alfa_j > -eps) continue; temp = (dir * cbar_j) / alfa_j; break; case LPX_NF: /* xN[j] is non-basic free variable */ if (abs_alfa_j < eps) continue; temp = 0.0; break; case LPX_NS: /* xN[j] is non-basic fixed variable */ continue; default: xassert(tagx != tagx); } /* if the reduced cost of the variable xN[j] violates its zero bound (slightly, because the current basis is assumed to be dual feasible), temp is negative; we can think this happens due to round-off errors and the reduced cost is exact zero; 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_j) q = k, teta = temp, big = abs_alfa_j; } /* return the ordinal number of the chosen non-basic variable */ return q; }
double lpx_eval_degrad(LPX *lp, int len, int ind[], double val[], int type, double rhs) { int m = lpx_get_num_rows(lp); int n = lpx_get_num_cols(lp); int dir = lpx_get_obj_dir(lp); int q, k; double y, delta; if (lpx_get_dual_stat(lp) != LPX_D_FEAS) fault("lpx_eval_degrad: LP basis is not dual feasible"); if (!(0 <= len && len <= n)) fault("lpx_eval_degrad: len = %d; invalid row length", len); if (!(type == LPX_LO || type == LPX_UP)) fault("lpx_eval_degrad: type = %d; invalid row type", type); /* compute value of the row auxiliary variable */ y = lpx_eval_row(lp, len, ind, val); /* the inequalitiy constraint is assumed to be violated */ if (!(type == LPX_LO && y < rhs || type == LPX_UP && y > rhs)) fault("lpx_eval_degrad: y = %g, rhs = %g; constraint is not vi" "olated", y, rhs); /* transform the row in order to express y through only non-basic variables: y = alfa[1] * xN[1] + ... + alfa[n] * xN[n] */ len = lpx_transform_row(lp, len, ind, val); /* in the adjacent basis y would become non-basic, so in case of '>=' it increases and in case of '<=' it decreases; determine which non-basic variable x[q], 1 <= q <= m+n, should leave the basis to keep dual feasibility */ q = lpx_dual_ratio_test(lp, len, ind, val, type == LPX_LO ? +1 : -1, 1e-7); /* q = 0 means no adjacent dual feasible basis exist */ if (q == 0) return dir == LPX_MIN ? +DBL_MAX : -DBL_MAX; /* find the entry corresponding to x[q] in the list */ for (k = 1; k <= len; k++) if (ind[k] == q) break; insist(k <= len); /* dy = alfa[q] * dx[q], so dx[q] = dy / alfa[q], where dy is a change in y, dx[q] is a change in x[q] */ delta = (rhs - y) / val[k]; #if 0 /* Tomlin noticed that if the variable x[q] is of integer kind, its change cannot be less than one in the magnitude */ if (q > m && lpx_get_col_kind(lp, q-m) == LPX_IV) { /* x[q] is structural integer variable */ if (fabs(delta - floor(delta + 0.5)) > 1e-3) { if (delta > 0.0) delta = ceil(delta); /* +3.14 -> +4 */ else delta = floor(delta); /* -3.14 -> -4 */ } } #endif /* dz = lambda[q] * dx[q], where dz is a change in the objective function, lambda[q] is a reduced cost of x[q] */ if (q <= m) delta *= lpx_get_row_dual(lp, q); else delta *= lpx_get_col_dual(lp, q-m); /* delta must be >= 0 (in case of minimization) or <= 0 (in case of minimization); however, due to round-off errors and finite tolerance used to choose x[q], this condition can be slightly violated */ switch (dir) { case LPX_MIN: if (delta < 0.0) delta = 0.0; break; case LPX_MAX: if (delta > 0.0) delta = 0.0; break; default: insist(dir != dir); } return delta; }