int CClp_setbnd(CClp *lp, int j, char lower_or_upper, double bnd) { /* SETS the bound on the variable index by j. - lower_or_upper should be either 'L' or 'U'. */ int type; double lo, up; lpx_get_col_bnds(lp->lp, j+1, &type, &lo, &up); if (type == LPX_FR || type == LPX_UP) lo = -DBL_MAX; if (type == LPX_FR || type == LPX_LO) up = +DBL_MAX; switch (lower_or_upper) { case 'L': lo = bnd; break; case 'U': up = bnd; break; default: insist(lower_or_upper != lower_or_upper); } if (lo == -DBL_MAX && up == +DBL_MAX) insist(2 + 2 == 5); else if (up == +DBL_MAX) type = LPX_LO; else if (lo == -DBL_MAX) type = LPX_UP; else if (lo != up) type = LPX_DB; else type = LPX_FX; lpx_set_col_bnds(lp->lp, j+1, type, lo, up); return 0; }
int CClp_load_warmstart(CClp *lp, CClp_warmstart *warm) { /* RESTORES the warmstart information in warm. */ int i, j, m, n, tagx, type, *rstat, *cstat; m = lpx_get_num_rows(lp->lp); n = lpx_get_num_cols(lp->lp); cstat = warm->cstat; rstat = warm->rstat; if (cstat == NULL || rstat == NULL) { print("CClp_load_warmstart: no basis information"); return 0; } for (j = 0; j < n; j++) { if (cstat[j] == IS_BASIC) tagx = LPX_BS; else { lpx_get_col_bnds(lp->lp, j+1, &type, NULL, NULL); switch (type) { case LPX_FR: tagx = LPX_NF; break; case LPX_LO: tagx = LPX_NL; break; case LPX_UP: tagx = LPX_NU; break; case LPX_DB: tagx = (cstat[j] == AT_UPPER ? LPX_NU : LPX_NL); break; case LPX_FX: tagx = LPX_NS; break; default: insist(type != type); } } lpx_set_col_stat(lp->lp, j+1, tagx); } for (i = 0; i < m; i++) { if (rstat[i] == IS_BASIC) tagx = LPX_BS; else { lpx_get_row_bnds(lp->lp, i+1, &type, NULL, NULL); switch (type) { case LPX_FR: tagx = LPX_NF; break; case LPX_LO: tagx = LPX_NL; break; case LPX_UP: tagx = LPX_NU; break; case LPX_DB: tagx = (rstat[i] == AT_UPPER ? LPX_NU : LPX_NL); break; case LPX_FX: tagx = LPX_NS; break; default: insist(type != type); } } lpx_set_row_stat(lp->lp, i+1, tagx); } return 0; }
void lpp_unload_sol(LPP *lpp, LPX *orig) { int i, j, k, m, n, typx, tagx; m = lpp->orig_m; n = lpp->orig_n; insist(m == lpx_get_num_rows(orig)); insist(n == lpx_get_num_cols(orig)); insist(lpp->orig_dir == lpx_get_obj_dir(orig)); /* check row and column statuses */ insist(m <= lpp->nrows); insist(n <= lpp->ncols); for (k = 1; k <= m+n; k++) { tagx = (k <= m ? lpp->row_stat[k] : lpp->col_stat[k-m]); if (tagx != LPX_BS) { if (k <= m) lpx_get_row_bnds(orig, k, &typx, NULL, NULL); else lpx_get_col_bnds(orig, k-m, &typx, NULL, NULL); switch (typx) { case LPX_FR: insist(tagx == LPX_NF); break; case LPX_LO: insist(tagx == LPX_NL); break; case LPX_UP: insist(tagx == LPX_NU); break; case LPX_DB: insist(tagx == LPX_NL || tagx == LPX_NU); break; case LPX_FX: insist(tagx == LPX_NS); break; default: insist(orig != orig); } } } /* if the original problem is maximization, change signs of dual values */ if (lpp->orig_dir == LPX_MAX) { for (i = 1; i <= m; i++) lpp->row_dual[i] = -lpp->row_dual[i]; for (j = 1; j <= n; j++) lpp->col_dual[j] = -lpp->col_dual[j]; } /* store solution components into the original problem object (it is assumed that the recovered solution is optimal) */ lpx_put_solution(orig, LPX_P_FEAS, LPX_D_FEAS, lpp->row_stat, lpp->row_prim, lpp->row_dual, lpp->col_stat, lpp->col_prim, lpp->col_dual); return; }
void lpp_load_orig(LPP *lpp, LPX *orig) { LPPROW *row; LPPCOL *col, **map; int i, j, t, len, typx, *ndx; double lb, ub, temp, *c, *val; /* save some information about the original problem */ lpp->orig_m = lpx_get_num_rows(orig); lpp->orig_n = lpx_get_num_cols(orig); lpp->orig_nnz = lpx_get_num_nz(orig); lpp->orig_dir = lpx_get_obj_dir(orig); /* allocate working arrays */ c = ucalloc(1+lpp->orig_n, sizeof(double)); ndx = ucalloc(1+lpp->orig_n, sizeof(int)); val = ucalloc(1+lpp->orig_n, sizeof(double)); /* auxiliary variables (i.e. rows) in the original problem may have non-zero objective coefficients; so, we substitute these auxiliary variables into the objective function in order that it depends only on structural variables (i.e. columns); the resultant vector of objective coefficients is accumulated in the working array c */ for (j = 1; j <= lpp->orig_n; j++) c[j] = lpx_get_col_coef(orig, j); for (i = 1; i <= lpp->orig_m; i++) { /* obtain an objective coefficient at i-th row */ temp = lpx_get_row_coef(orig, i); /* substitute i-th row into the objective function */ if (temp != 0.0) { len = lpx_get_mat_row(orig, i, ndx, val); for (t = 1; t <= len; t++) c[ndx[t]] += val[t] * temp; } } /* copy rows of the original problem into the workspace; each row created in the workspace is assigned a reference number, which is its ordinal number in the original problem */ for (i = 1; i <= lpp->orig_m; i++) { lpx_get_row_bnds(orig, i, &typx, &lb, &ub); if (typx == LPX_FR || typx == LPX_UP) lb = -DBL_MAX; if (typx == LPX_FR || typx == LPX_LO) ub = +DBL_MAX; if (typx == LPX_FX) ub = lb; lpp_add_row(lpp, lb, ub); } /* copy columns of the original problem into the workspace; each column created in the workspace is assigned a reference number, which its ordinal number in the original problem */ for (j = 1; j <= lpp->orig_n; j++) { lpx_get_col_bnds(orig, j, &typx, &lb, &ub); if (typx == LPX_FR || typx == LPX_UP) lb = -DBL_MAX; if (typx == LPX_FR || typx == LPX_LO) ub = +DBL_MAX; if (typx == LPX_FX) ub = lb; lpp_add_col(lpp, lb, ub, c[j]); } /* copy the constant term of the original objective function */ lpp->c0 = lpx_get_obj_c0(orig); /* if the original problem is maximization, change the sign of the objective function, because the transformed problem to be processed by the presolver must be minimization */ if (lpp->orig_dir == LPX_MAX) { for (col = lpp->col_ptr; col != NULL; col = col->next) col->c = - col->c; lpp->c0 = - lpp->c0; } /* build an auxiliary array to map column ordinal numbers to the corresponding pointers */ insist(sizeof(LPPCOL *) <= sizeof(double)); map = (LPPCOL **)c; for (col = lpp->col_ptr; col != NULL; col = col->next) map[col->j] = col; /* copy the original constraint matrix into the workspace */ for (row = lpp->row_ptr; row != NULL; row = row->next) #if 1 { len = lpx_get_mat_row(orig, row->i, ndx, val); for (t = 1; t <= len; t++) lpp_add_aij(lpp, row, map[ndx[t]], val[t]); } #else /* 27/XI-2003 (the problem persists) */ { double big, eps; len = lpx_get_mat_row(orig, row->i, ndx, val); big = 0.0; for (t = 1; t <= len; t++) if (big < fabs(val[t])) big = fabs(val[t]); eps = 1e-10 * big; for (t = 1; t <= len; t++) { if (fabs(val[t]) < eps) continue; lpp_add_aij(lpp, row, map[ndx[t]], val[t]); } } #endif /* free working arrays */ ufree(c); ufree(ndx); ufree(val); return; }
int lpx_write_cpxlp(LPX *lp, const char *fname) { /* write problem data in CPLEX LP format */ FILE *fp; int nrows, ncols, i, j, t, len, typx, flag, kind, *ind; double lb, ub, temp, *val; char line[1023+1], term[1023+1], rname[255+1], cname[255+1]; print("lpx_write_cpxlp: writing problem data to `%s'...", fname); /* open the output text file */ fp = xfopen(fname, "w"); if (fp == NULL) { print("lpx_write_cpxlp: unable to create `%s' - %s", fname, strerror(errno)); goto fail; } /* determine the number of rows and columns */ nrows = lpx_get_num_rows(lp); ncols = lpx_get_num_cols(lp); /* the problem should contain at least one row and one column */ if (!(nrows > 0 && ncols > 0)) fault("lpx_write_cpxlp: problem has no rows/columns"); /* write problem name */ { const char *name = lpx_get_prob_name(lp); if (name == NULL) name = "Unknown"; fprintf(fp, "\\* Problem: %s *\\\n", name); fprintf(fp, "\n"); } /* allocate working arrays */ ind = xcalloc(1+ncols, sizeof(int)); val = xcalloc(1+ncols, sizeof(double)); /* write the objective function definition and the constraints section */ for (i = 0; i <= nrows; i++) { if (i == 0) { switch (lpx_get_obj_dir(lp)) { case LPX_MIN: fprintf(fp, "Minimize\n"); break; case LPX_MAX: fprintf(fp, "Maximize\n"); break; default: xassert(lp != lp); } } else if (i == 1) { temp = lpx_get_obj_coef(lp, 0); if (temp != 0.0) fprintf(fp, "\\* constant term = %.*g *\\\n", DBL_DIG, temp); fprintf(fp, "\n"); fprintf(fp, "Subject To\n"); } row_name(lp, i, rname); if (i == 0) { len = 0; for (j = 1; j <= ncols; j++) { temp = lpx_get_obj_coef(lp, j); if (temp != 0.0) len++, ind[len] = j, val[len] = temp; } } else { lpx_get_row_bnds(lp, i, &typx, &lb, &ub); if (typx == LPX_FR) continue; len = lpx_get_mat_row(lp, i, ind, val); } flag = 0; more: if (!flag) sprintf(line, " %s:", rname); else sprintf(line, " %*s ", strlen(rname), ""); for (t = 1; t <= len; t++) { col_name(lp, ind[t], cname); if (val[t] == +1.0) sprintf(term, " + %s", cname); else if (val[t] == -1.0) sprintf(term, " - %s", cname); else if (val[t] > 0.0) sprintf(term, " + %.*g %s", DBL_DIG, +val[t], cname); else if (val[t] < 0.0) sprintf(term, " - %.*g %s", DBL_DIG, -val[t], cname); else xassert(lp != lp); if (strlen(line) + strlen(term) > 72) fprintf(fp, "%s\n", line), line[0] = '\0'; strcat(line, term); } if (len == 0) { /* empty row */ sprintf(term, " 0 %s", col_name(lp, 1, cname)); strcat(line, term); } if (i > 0) { switch (typx) { case LPX_LO: case LPX_DB: sprintf(term, " >= %.*g", DBL_DIG, lb); break; case LPX_UP: sprintf(term, " <= %.*g", DBL_DIG, ub); break; case LPX_FX: sprintf(term, " = %.*g", DBL_DIG, lb); break; default: xassert(typx != typx); } if (strlen(line) + strlen(term) > 72) fprintf(fp, "%s\n", line), line[0] = '\0'; strcat(line, term); } fprintf(fp, "%s\n", line); if (i > 0 && typx == LPX_DB) { /* double-bounded row needs a copy for its upper bound */ flag = 1; typx = LPX_UP; goto more; } } /* free working arrays */ xfree(ind); xfree(val); /* write the bounds section */ flag = 0; for (j = 1; j <= ncols; j++) { col_name(lp, j, cname); lpx_get_col_bnds(lp, j, &typx, &lb, &ub); if (typx == LPX_LO && lb == 0.0) continue; if (!flag) { fprintf(fp, "\n"); fprintf(fp, "Bounds\n"); flag = 1; } switch (typx) { case LPX_FR: fprintf(fp, " %s free\n", cname); break; case LPX_LO: fprintf(fp, " %s >= %.*g\n", cname, DBL_DIG, lb); break; case LPX_UP: fprintf(fp, " %s <= %.*g\n", cname, DBL_DIG, ub); break; case LPX_DB: fprintf(fp, " %.*g <= %s <= %.*g\n", DBL_DIG, lb, cname, DBL_DIG, ub); break; case LPX_FX: fprintf(fp, " %s = %.*g\n", cname, DBL_DIG, lb); break; default: xassert(typx != typx); } } /* write the general section */ if (lpx_get_class(lp) == LPX_MIP) { flag = 0; for (j = 1; j <= ncols; j++) { kind = lpx_get_col_kind(lp, j); if (kind == LPX_CV) continue; xassert(kind == LPX_IV); if (!flag) { fprintf(fp, "\n"); fprintf(fp, "Generals\n"); flag = 1; } fprintf(fp, " %s\n", col_name(lp, j, cname)); } } /* write the end keyword */ fprintf(fp, "\n"); fprintf(fp, "End\n"); /* close the output text file */ fflush(fp); if (ferror(fp)) { print("lpx_write_cpxlp: write error on `%s' - %s", fname, strerror(errno)); goto fail; } xfclose(fp); /* return to the calling program */ return 0; fail: /* the operation failed */ if (fp != NULL) xfclose(fp); return 1; }
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_print_mip(LPX *lp, const char *fname) { XFILE *fp; int what, round; #if 0 if (lpx_get_class(lp) != LPX_MIP) fault("lpx_print_mip: error -- not a MIP problem"); #endif xprintf( "lpx_print_mip: writing MIP problem solution to `%s'...\n", fname); fp = xfopen(fname, "w"); if (fp == NULL) { xprintf("lpx_print_mip: 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_int, nc_bin; nc = lpx_get_num_cols(lp); nc_int = lpx_get_num_int(lp); nc_bin = lpx_get_num_bin(lp); xfprintf(fp, "%-12s%d (%d integer, %d binary)\n", "Columns:", nc, nc_int, nc_bin); } /* 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_mip_status(lp); xfprintf(fp, "%-12s%s\n", "Status:", status == LPX_I_UNDEF ? "INTEGER UNDEFINED" : status == LPX_I_OPT ? "INTEGER OPTIMAL" : status == LPX_I_FEAS ? "INTEGER NON-OPTIMAL" : status == LPX_I_NOFEAS ? "INTEGER EMPTY" : "???"); } /* objective function */ { char *name; int dir; double mip_obj; name = (void *)lpx_get_obj_name(lp); dir = lpx_get_obj_dir(lp); mip_obj = lpx_mip_obj_val(lp); xfprintf(fp, "%-12s%s%s%.10g %s\n", "Objective:", name == NULL ? "" : name, name == NULL ? "" : " = ", mip_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 Activity Lower bound Upp" "er bound\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 kind, typx; double lb, ub, vx; if (what == 1) { name = lpx_get_row_name(lp, ij); if (name == NULL) name = ""; kind = LPX_CV; 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); vx = lpx_mip_row_val(lp, ij); lpx_set_int_parm(lp, LPX_K_ROUND, round); } else { name = lpx_get_col_name(lp, ij); if (name == NULL) name = ""; kind = lpx_get_col_kind(lp, ij); 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); vx = lpx_mip_col_val(lp, ij); 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 kind */ xfprintf(fp, "%s ", kind == LPX_CV ? " " : kind == LPX_IV ? "*" : "?"); /* row/column primal activity */ xfprintf(fp, "%13.6g", vx); /* row/column lower and upper bounds */ switch (typx) { case LPX_FR: break; case LPX_LO: xfprintf(fp, " %13.6g", lb); break; case LPX_UP: xfprintf(fp, " %13s %13.6g", "", ub); break; case LPX_DB: xfprintf(fp, " %13.6g %13.6g", lb, ub); break; case LPX_FX: xfprintf(fp, " %13.6g %13s", lb, "="); break; default: xassert(typx != typx); } /* end of line */ xfprintf(fp, "\n"); } } xfprintf(fp, "\n"); #if 1 if (lpx_mip_status(lp) != LPX_I_UNDEF) { int m = lpx_get_num_rows(lp); LPXKKT kkt; xfprintf(fp, "Integer feasibility conditions:\n\n"); lpx_check_int(lp, &kkt); xfprintf(fp, "INT.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, " SOLUTION IS WRONG\n"); break; } xfprintf(fp, "\n"); xfprintf(fp, "INT.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, " SOLUTION IS INFEASIBLE\n"); break; } xfprintf(fp, "\n"); } #endif xfprintf(fp, "End of output\n"); xfflush(fp); if (xferror(fp)) { xprintf("lpx_print_mip: 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_print_ips(LPX *lp, const char *fname) { XFILE *fp; int what, round; xprintf("lpx_print_ips: writing LP problem solution to `%s'...\n", fname); fp = xfopen(fname, "w"); if (fp == NULL) { xprintf("lpx_print_ips: 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_ipt_status(lp); xfprintf(fp, "%-12s%s\n", "Status:", status == LPX_T_UNDEF ? "INTERIOR UNDEFINED" : status == LPX_T_OPT ? "INTERIOR OPTIMAL" : "???"); } /* objective function */ { char *name; int dir; double obj; name = (void *)lpx_get_obj_name(lp); dir = lpx_get_obj_dir(lp); obj = lpx_ipt_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 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); vx = lpx_ipt_row_prim(lp, ij); dx = lpx_ipt_row_dual(lp, ij); 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); vx = lpx_ipt_col_prim(lp, ij); dx = lpx_ipt_col_dual(lp, ij); 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, ""); /* two positions are currently not used */ xfprintf(fp, " "); /* 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 */ xfprintf(fp, "%13.6g", dx); /* end of line */ xfprintf(fp, "\n"); } } xfprintf(fp, "\n"); xfprintf(fp, "End of output\n"); xfflush(fp); if (xferror(fp)) { xprintf("lpx_print_ips: can't write to `%s' - %s\n", fname, strerror(errno)); goto fail; } xfclose(fp); return 0; fail: if (fp != NULL) xfclose(fp); return 1; }
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; }
void adv_basis(glp_prob *lp) { int m = lpx_get_num_rows(lp); int n = lpx_get_num_cols(lp); int i, j, jj, k, size; int *rn, *cn, *rn_inv, *cn_inv; int typx, *tagx = xcalloc(1+m+n, sizeof(int)); double lb, ub; xprintf("Crashing...\n"); if (m == 0) xerror("glp_adv_basis: problem has no rows\n"); if (n == 0) xerror("glp_adv_basis: problem has no columns\n"); /* use the routine triang (see above) to find maximal triangular part of the augmented constraint matrix A~ = (I|-A); in order to prevent columns of fixed variables to be included in the triangular part, such columns are implictly removed from the matrix A~ by the routine adv_mat */ rn = xcalloc(1+m, sizeof(int)); cn = xcalloc(1+m+n, sizeof(int)); size = triang(m, m+n, lp, mat, rn, cn); if (lpx_get_int_parm(lp, LPX_K_MSGLEV) >= 3) xprintf("Size of triangular part = %d\n", size); /* the first size rows and columns of the matrix P*A~*Q (where P and Q are permutation matrices defined by the arrays rn and cn) form a lower triangular matrix; build the arrays (rn_inv and cn_inv), which define the matrices inv(P) and inv(Q) */ rn_inv = xcalloc(1+m, sizeof(int)); cn_inv = xcalloc(1+m+n, sizeof(int)); for (i = 1; i <= m; i++) rn_inv[rn[i]] = i; for (j = 1; j <= m+n; j++) cn_inv[cn[j]] = j; /* include the columns of the matrix A~, which correspond to the first size columns of the matrix P*A~*Q, in the basis */ for (k = 1; k <= m+n; k++) tagx[k] = -1; for (jj = 1; jj <= size; jj++) { j = cn_inv[jj]; /* the j-th column of A~ is the jj-th column of P*A~*Q */ tagx[j] = LPX_BS; } /* if size < m, we need to add appropriate columns of auxiliary variables to the basis */ for (jj = size + 1; jj <= m; jj++) { /* the jj-th column of P*A~*Q should be replaced by the column of the auxiliary variable, for which the only unity element is placed in the position [jj,jj] */ i = rn_inv[jj]; /* the jj-th row of P*A~*Q is the i-th row of A~, but in the i-th row of A~ the unity element belongs to the i-th column of A~; therefore the disired column corresponds to the i-th auxiliary variable (note that this column doesn't belong to the triangular part found by the routine triang) */ xassert(1 <= i && i <= m); xassert(cn[i] > size); tagx[i] = LPX_BS; } /* free working arrays */ xfree(rn); xfree(cn); xfree(rn_inv); xfree(cn_inv); /* build tags of non-basic variables */ for (k = 1; k <= m+n; k++) { if (tagx[k] != LPX_BS) { if (k <= m) lpx_get_row_bnds(lp, k, &typx, &lb, &ub); else lpx_get_col_bnds(lp, k-m, &typx, &lb, &ub); switch (typx) { case LPX_FR: tagx[k] = LPX_NF; break; case LPX_LO: tagx[k] = LPX_NL; break; case LPX_UP: tagx[k] = LPX_NU; break; case LPX_DB: tagx[k] = (fabs(lb) <= fabs(ub) ? LPX_NL : LPX_NU); break; case LPX_FX: tagx[k] = LPX_NS; break; default: xassert(typx != typx); } } } for (k = 1; k <= m+n; k++) { if (k <= m) lpx_set_row_stat(lp, k, tagx[k]); else lpx_set_col_stat(lp, k-m, tagx[k]); } xfree(tagx); return; }
static int mat(void *info, int k, int ndx[]) { /* this auxiliary routine returns the pattern of a given row or a given column of the augmented constraint matrix A~ = (I|-A), in which columns of fixed variables are implicitly cleared */ LPX *lp = info; int m = lpx_get_num_rows(lp); int n = lpx_get_num_cols(lp); int typx, i, j, lll, len = 0; if (k > 0) { /* the pattern of the i-th row is required */ i = +k; xassert(1 <= i && i <= m); #if 0 /* 22/XII-2003 */ /* if the auxiliary variable x[i] is non-fixed, include its element (placed in the i-th column) in the pattern */ lpx_get_row_bnds(lp, i, &typx, NULL, NULL); if (typx != LPX_FX) ndx[++len] = i; /* include in the pattern elements placed in columns, which correspond to non-fixed structural varables */ i_beg = aa_ptr[i]; i_end = i_beg + aa_len[i] - 1; for (i_ptr = i_beg; i_ptr <= i_end; i_ptr++) { j = m + sv_ndx[i_ptr]; lpx_get_col_bnds(lp, j-m, &typx, NULL, NULL); if (typx != LPX_FX) ndx[++len] = j; } #else lll = lpx_get_mat_row(lp, i, ndx, NULL); for (k = 1; k <= lll; k++) { lpx_get_col_bnds(lp, ndx[k], &typx, NULL, NULL); if (typx != LPX_FX) ndx[++len] = m + ndx[k]; } lpx_get_row_bnds(lp, i, &typx, NULL, NULL); if (typx != LPX_FX) ndx[++len] = i; #endif } else { /* the pattern of the j-th column is required */ j = -k; xassert(1 <= j && j <= m+n); /* if the (auxiliary or structural) variable x[j] is fixed, the pattern of its column is empty */ if (j <= m) lpx_get_row_bnds(lp, j, &typx, NULL, NULL); else lpx_get_col_bnds(lp, j-m, &typx, NULL, NULL); if (typx != LPX_FX) { if (j <= m) { /* x[j] is non-fixed auxiliary variable */ ndx[++len] = j; } else { /* x[j] is non-fixed structural variables */ #if 0 /* 22/XII-2003 */ j_beg = aa_ptr[j]; j_end = j_beg + aa_len[j] - 1; for (j_ptr = j_beg; j_ptr <= j_end; j_ptr++) ndx[++len] = sv_ndx[j_ptr]; #else len = lpx_get_mat_col(lp, j-m, ndx, NULL); #endif } } } /* return the length of the row/column pattern */ return len; }
int lpx_print_sens_bnds(LPX *lp, char *fname) { FILE *fp = NULL; int what, round; print("lpx_print_sens_bnds: writing LP problem solution bounds to" " `%s'...", fname); #if 1 /* added by mao */ /* this routine needs factorization of the current basis matrix which, however, does not exist if the basic solution was obtained by the lp presolver; therefore we should warm up the basis to be sure that the factorization is valid (note that if the factorization exists, lpx_warm_up does nothing) */ lpx_warm_up(lp); #endif #if 0 /* 21/XII-2003 by mao */ if (lp->b_stat == LPX_B_UNDEF) #else if (!lpx_is_b_avail(lp)) #endif { print("lpx_print_sens_bnds: basis information not available (m" "ay be a presolve issue)"); goto fail; } fp = ufopen(fname, "w"); if (fp == NULL) { print("lpx_print_sens_bnds: can't create `%s' - %s", fname, strerror(errno)); goto fail; } /* problem name */ { char *name; name = lpx_get_prob_name(lp); if (name == NULL) name = ""; fprintf(fp, "%-12s%s\n", "Problem:", name); } /* number of rows (auxiliary variables) */ { int nr; nr = lpx_get_num_rows(lp); fprintf(fp, "%-12s%d\n", "Rows:", nr); } /* number of columns (structural variables) */ { int nc; nc = lpx_get_num_cols(lp); fprintf(fp, "%-12s%d\n", "Columns:", nc); } /* number of non-zeros (constraint coefficients) */ { int nz; nz = lpx_get_num_nz(lp); fprintf(fp, "%-12s%d\n", "Non-zeros:", nz); } /* solution status */ { int status; status = lpx_get_status(lp); fprintf(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" : "???"); } /* explanation/warning */ { fprintf(fp, "\nExplanation: This file presents amounts by whi" "ch objective coefficients,\n"); fprintf(fp, "constraint bounds, and variable bounds may be cha" "nged in the original problem\n"); fprintf(fp, "while the optimal basis remains the same. Note t" "hat the optimal solution\n"); fprintf(fp, "and objective value may change even though the ba" "sis remains the same.\n"); fprintf(fp, "These bounds assume that all parameters remain fi" "xed except the one in\n"); fprintf(fp, "question. If more than one parameter is changed," " it is possible for the\n"); fprintf(fp, "optimal basis to change even though each paramete" "r stays within its bounds.\n"); fprintf(fp, "For more details, consult a text on linear progra" "mming.\n"); } /* Sensitivity ranges if solution was optimal */ { int status; status = lpx_get_status(lp); if (status == LPX_OPT) { int i,j,k,m,n; int dir; double max_inc, max_dec; int *index; double *val; fprintf(fp, "\nObjective Coefficient Analysis\n"); fprintf(fp, " No. Column name St Value Max incr" "ease Max decrease\n"); fprintf(fp, "------ ------------ -- ------------- ---------" "---- ------------- \n"); n = lpx_get_num_cols(lp); m = lpx_get_num_rows(lp); dir = lpx_get_obj_dir(lp); /* allocate memory for index and val arrays */ index = ucalloc(1+n+m, sizeof(int)); val = ucalloc(1+n+m, sizeof(double)); for (j = 1; j <= n; j++) { char *name; int typx, tagx; double lb, ub, vx, dx; name = lpx_get_col_name(lp, j); if (name == NULL) name = ""; lpx_get_col_bnds(lp, j, &typx, &lb, &ub); #if 0 /* 21/XII-2003 by mao */ round = lp->round, lp->round = 1; lpx_get_col_info(lp, j, &tagx, &vx, &dx); lp->round = round; #else round = lpx_get_int_parm(lp, LPX_K_ROUND); lpx_set_int_parm(lp, LPX_K_ROUND, 1); lpx_get_col_info(lp, j, &tagx, &vx, &dx); lpx_set_int_parm(lp, LPX_K_ROUND, round); #endif /* row/column ordinal number */ fprintf(fp, "%6d ", j); /* row column/name */ if (strlen(name) <= 12) fprintf(fp, "%-12s ", name); else fprintf(fp, "%s\n%20s", name, ""); /* row/column status */ fprintf(fp, "%s ", tagx == LPX_BS ? "B " : tagx == LPX_NL ? "NL" : tagx == LPX_NU ? "NU" : tagx == LPX_NF ? "NF" : tagx == LPX_NS ? "NS" : "??"); /* objective coefficient */ fprintf(fp, "%13.6g ", lpx_get_obj_coef(lp, j)); if (tagx == LPX_NL) { if (dir==LPX_MIN) { /* reduced cost must be positive */ max_inc = DBL_MAX; /* really represents infinity */ max_dec = dx; } else { /* reduced cost must be negative */ max_inc = -dx; max_dec = DBL_MAX; /* means infinity */ } } if (tagx == LPX_NU) { if (dir==LPX_MIN) { /* reduced cost must be negative */ max_inc = -dx; max_dec = DBL_MAX; } else { max_inc = DBL_MAX; max_dec = dx; } } if (tagx == LPX_NF) { /* can't change nonbasic free variables' cost */ max_inc = 0.0; max_dec = 0.0; } if (tagx == LPX_NS) { /* doesn't matter what happens to the cost */ max_inc = DBL_MAX; max_dec = DBL_MAX; } if (tagx == LPX_BS) { int len; /* We need to see how this objective coefficient affects reduced costs of other variables */ len = lpx_eval_tab_row(lp, m+j, index, val); max_inc = DBL_MAX; max_dec = DBL_MAX; for (i = 1; i <= len; i++) { /*int stat;*/ int tagx2; double vx2, dx2; double delta; if (index[i]>m) lpx_get_col_info(lp, index[i]-m, &tagx2, &vx2, &dx2); else lpx_get_row_info(lp, index[i], &tagx2, &vx2, &dx2); if (tagx2 == LPX_NL) { if (val[i] != 0.0) { delta = dx2 / val[i]; if (delta < 0 && -delta < max_inc) max_inc = -delta; else if (delta >0 && delta < max_dec) max_dec = delta; } } if (tagx2 == LPX_NU) { if (val[i] != 0.0) { delta = dx2 / val[i]; if (delta < 0 && -delta < max_inc) max_inc = -delta; else if (delta > 0 && delta < max_dec) max_dec = delta; } } if (tagx2 == LPX_NF) { if (val[i] != 0.0) { max_inc = 0.0; max_dec = 0.0; } } } } if (max_inc == -0.0) max_inc = 0.0; if (max_dec == -0.0) max_dec = 0.0; if (max_inc == DBL_MAX) fprintf(fp, "%13s ", "infinity"); else if (max_inc < 1.0e-12 && max_inc > 0) fprintf(fp, "%13s ", "< eps"); else fprintf(fp, "%13.6g ", max_inc); if (max_dec == DBL_MAX) fprintf(fp, "%13s ", "infinity"); else if (max_dec < 1.0e-12 && max_dec > 0) fprintf(fp, "%13s ", "< eps"); else fprintf(fp, "%13.6g ", max_dec); fprintf(fp, "\n"); } for (what = 1; what <= 2; what++) { int ij, mn; fprintf(fp, "\n"); fprintf(fp, "%s Analysis\n", what==1? "Constraint Bounds":"Variable Bounds"); fprintf(fp, " No. %12s St Value Max increase " " Max decrease\n", what==1 ? " Row name":"Column name"); fprintf(fp, "------ ------------ -- ------------- ------" "------- ------------- \n"); mn = what==1 ? m : n; for (ij = 1; ij <= mn; ij++) { char *name; int typx, tagx; double lb, ub, vx, dx; if (what==1) name = lpx_get_row_name(lp, ij); else name = lpx_get_col_name(lp, ij); if (name == NULL) name = ""; #if 0 /* 21/XII-2003 by mao */ if (what==1) { lpx_get_row_bnds(lp, ij, &typx, &lb, &ub); round = lp->round, lp->round = 1; lpx_get_row_info(lp, ij, &tagx, &vx, &dx); lp->round = round; } else { lpx_get_col_bnds(lp, ij, &typx, &lb, &ub); round = lp->round, lp->round = 1; lpx_get_col_info(lp, ij, &tagx, &vx, &dx); lp->round = round; } #else round = lpx_get_int_parm(lp, LPX_K_ROUND); lpx_set_int_parm(lp, LPX_K_ROUND, 1); if (what==1) { lpx_get_row_bnds(lp, ij, &typx, &lb, &ub); lpx_get_row_info(lp, ij, &tagx, &vx, &dx); } else { lpx_get_col_bnds(lp, ij, &typx, &lb, &ub); lpx_get_col_info(lp, ij, &tagx, &vx, &dx); } lpx_set_int_parm(lp, LPX_K_ROUND, round); #endif /* row/column ordinal number */ fprintf(fp, "%6d ", ij); /* row column/name */ if (strlen(name) <= 12) fprintf(fp, "%-12s ", name); else fprintf(fp, "%s\n%20s", name, ""); /* row/column status */ fprintf(fp, "%s ", tagx == LPX_BS ? "B " : tagx == LPX_NL ? "NL" : tagx == LPX_NU ? "NU" : tagx == LPX_NF ? "NF" : tagx == LPX_NS ? "NS" : "??"); fprintf(fp, "\n"); /* first check lower bound */ if (typx == LPX_LO || typx == LPX_DB || typx == LPX_FX) { int at_lower; at_lower = 0; if (tagx == LPX_BS || tagx == LPX_NU) { max_inc = vx - lb; max_dec = DBL_MAX; } if (tagx == LPX_NS) { max_inc = 0.0; max_dec = 0.0; if (dir == LPX_MIN && dx > 0) at_lower = 1; if (dir == LPX_MAX && dx < 0) at_lower = 1; } if (tagx == LPX_NL || at_lower == 1) { int len; /* we have to see how it affects basic variables */ len = lpx_eval_tab_col(lp, what==1?ij:ij+m, index, val); k = lpx_prim_ratio_test(lp, len, index, val, 1, 10e-7); max_inc = DBL_MAX; if (k != 0) { /*int stat;*/ int tagx2, typx2; double vx2, dx2, lb2, ub2; /*double delta;*/ double alpha; int l; for (l = 1; l <= len; l++) if (index[l] == k) alpha = val[l]; if (k>m) { lpx_get_col_info(lp, k-m, &tagx2, &vx2, &dx2); lpx_get_col_bnds(lp, k-m, &typx2, &lb2, &ub2); } else { lpx_get_row_info(lp, k, &tagx2, &vx2, &dx2); lpx_get_row_bnds(lp, k, &typx2, &lb2, &ub2); } /* Check which direction; remember this is upper bound */ if (alpha > 0) max_inc = (ub2 - vx2)/ alpha; else max_inc = (lb2 - vx2)/ alpha; } /* now check lower bound */ k = lpx_prim_ratio_test(lp, len, index, val, -1, 10e-7); max_dec = DBL_MAX; if (k != 0) { /*int stat;*/ int tagx2, typx2; double vx2, dx2, lb2, ub2; /*double delta;*/ double alpha; int l; for (l = 1; l <= len; l++) if (index[l] == k) alpha = val[l]; if (k>m) { lpx_get_col_info(lp, k-m, &tagx2, &vx2, &dx2); lpx_get_col_bnds(lp, k-m, &typx2, &lb2, &ub2); } else { lpx_get_row_info(lp, k, &tagx2, &vx2, &dx2); lpx_get_row_bnds(lp, k, &typx2, &lb2, &ub2); } /* Check which direction; remember this is lower bound */ if (alpha > 0) max_dec = (vx2 - lb2)/ alpha; else max_dec = (vx2 - ub2)/ alpha; } } /* bound */ if (typx == LPX_DB || typx == LPX_FX) { if (max_inc > ub - lb) max_inc = ub - lb; } fprintf(fp, " LOWER %13.6g ", lb); if (max_inc == -0.0) max_inc = 0.0; if (max_dec == -0.0) max_dec = 0.0; if (max_inc == DBL_MAX) fprintf(fp, "%13s ", "infinity"); else if (max_inc < 1.0e-12 && max_inc > 0) fprintf(fp, "%13s ", "< eps"); else fprintf(fp, "%13.6g ", max_inc); if (max_dec == DBL_MAX) fprintf(fp, "%13s ", "infinity"); else if (max_dec < 1.0e-12 && max_dec > 0) fprintf(fp, "%13s ", "< eps"); else fprintf(fp, "%13.6g ", max_dec); fprintf(fp, "\n"); } /* now check upper bound */ if (typx == LPX_UP || typx == LPX_DB || typx == LPX_FX) { int at_upper; at_upper = 0; if (tagx == LPX_BS || tagx == LPX_NL) { max_inc = DBL_MAX; max_dec = ub - vx; } if (tagx == LPX_NS) { max_inc = 0.0; max_dec = 0.0; if (dir == LPX_MIN && dx < 0) at_upper = 1; if (dir == LPX_MAX && dx > 0) at_upper = 1; } if (tagx == LPX_NU || at_upper == 1) { int len; /* we have to see how it affects basic variables */ len = lpx_eval_tab_col(lp, what==1?ij:ij+m, index, val); k = lpx_prim_ratio_test(lp, len, index, val, 1, 10e-7); max_inc = DBL_MAX; if (k != 0) { /*int stat;*/ int tagx2, typx2; double vx2, dx2, lb2, ub2; /*double delta;*/ double alpha; int l; for (l = 1; l <= len; l++) if (index[l] == k) alpha = val[l]; if (k>m) { lpx_get_col_info(lp, k-m, &tagx2, &vx2, &dx2); lpx_get_col_bnds(lp, k-m, &typx2, &lb2, &ub2); } else { lpx_get_row_info(lp, k, &tagx2, &vx2, &dx2); lpx_get_row_bnds(lp, k, &typx2, &lb2, &ub2); } /* Check which direction; remember this is upper bound */ if (alpha > 0) max_inc = (ub2 - vx2)/ alpha; else max_inc = (lb2 - vx2)/ alpha; } /* now check lower bound */ k = lpx_prim_ratio_test(lp, len, index, val, -1, 10e-7); max_dec = DBL_MAX; if (k != 0) { /*int stat;*/ int tagx2, typx2; double vx2, dx2, lb2, ub2; /*double delta;*/ double alpha; int l; for (l = 1; l <= len; l++) if (index[l] == k) alpha = val[l]; if (k>m) { lpx_get_col_info(lp, k-m, &tagx2, &vx2, &dx2); lpx_get_col_bnds(lp, k-m, &typx2, &lb2, &ub2); } else { lpx_get_row_info(lp, k, &tagx2, &vx2, &dx2); lpx_get_row_bnds(lp, k, &typx2, &lb2, &ub2); } /* Check which direction; remember this is lower bound */ if (alpha > 0) max_dec = (vx2 - lb2)/ alpha; else max_dec = (vx2 - ub2)/ alpha; } } if (typx == LPX_DB || typx == LPX_FX) { if (max_dec > ub - lb) max_dec = ub - lb; } /* bound */ fprintf(fp, " UPPER %13.6g ", ub); if (max_inc == -0.0) max_inc = 0.0; if (max_dec == -0.0) max_dec = 0.0; if (max_inc == DBL_MAX) fprintf(fp, "%13s ", "infinity"); else if (max_inc < 1.0e-12 && max_inc > 0) fprintf(fp, "%13s ", "< eps"); else fprintf(fp, "%13.6g ", max_inc); if (max_dec == DBL_MAX) fprintf(fp, "%13s ", "infinity"); else if (max_dec < 1.0e-12 && max_dec > 0) fprintf(fp, "%13s ", "< eps"); else fprintf(fp, "%13.6g ", max_dec); fprintf(fp, "\n"); } } } /* free the memory we used */ ufree(index); ufree(val); } else fprintf(fp, "No range information since solution is not o" "ptimal.\n"); } fprintf(fp, "\n"); fprintf(fp, "End of output\n"); fflush(fp); if (ferror(fp)) { print("lpx_print_sens_bnds: can't write to `%s' - %s", fname, strerror(errno)); goto fail; } ufclose(fp); return 0; fail: if (fp != NULL) ufclose(fp); return 1; }