LPX *lpx_read_cpxlp(const char *fname) { /* read problem data in CPLEX LP format */ struct dsa _dsa, *dsa = &_dsa; if (setjmp(dsa->jump)) goto fail; dsa->lp = NULL; dsa->fname = fname; dsa->fp = NULL; dsa->count = 0; dsa->c = '\n'; dsa->token = T_EOF; dsa->image[0] = '\0'; dsa->imlen = 0; dsa->value = 0.0; dsa->n_max = 100; dsa->map = xcalloc(1+dsa->n_max, sizeof(int)); memset(&dsa->map[1], 0, dsa->n_max * sizeof(int)); dsa->ind = xcalloc(1+dsa->n_max, sizeof(int)); dsa->val = xcalloc(1+dsa->n_max, sizeof(double)); dsa->lb = xcalloc(1+dsa->n_max, sizeof(double)); dsa->ub = xcalloc(1+dsa->n_max, sizeof(double)); print("lpx_read_cpxlp: reading problem data from `%s'...", dsa->fname); dsa->fp = xfopen(dsa->fname, "r"); if (dsa->fp == NULL) { print("lpx_read_cpxlp: unable to open `%s' - %s", dsa->fname, strerror(errno)); goto fail; } dsa->lp = lpx_create_prob(); lpx_create_index(dsa->lp); #if 0 /* read very first character */ read_char(dsa); #endif /* scan very first token */ scan_token(dsa); /* parse definition of the objective function */ if (!(dsa->token == T_MINIMIZE || dsa->token == T_MAXIMIZE)) fatal(dsa, "`minimize' or `maximize' keyword missing"); parse_objective(dsa); /* parse constraints section */ if (dsa->token != T_SUBJECT_TO) fatal(dsa, "constraints section missing"); parse_constraints(dsa); /* parse optional bounds section */ if (dsa->token == T_BOUNDS) parse_bounds(dsa); /* parse optional general, integer, and binary sections */ while (dsa->token == T_GENERAL || dsa->token == T_INTEGER || dsa->token == T_BINARY) parse_integer(dsa); /* check for the keyword 'end' */ if (dsa->token == T_END) scan_token(dsa); else if (dsa->token == T_EOF) print("%s:%d: warning: keyword `end' missing", dsa->fname, dsa->count); else fatal(dsa, "symbol `%s' in wrong position", dsa->image); /* nothing must follow the keyword 'end' (except comments) */ if (dsa->token != T_EOF) fatal(dsa, "extra symbol(s) detected beyond `end'"); /* set bounds of variables */ { int j, type; double lb, ub; for (j = lpx_get_num_cols(dsa->lp); j >= 1; j--) { lb = dsa->lb[j]; ub = dsa->ub[j]; if (lb == +DBL_MAX) lb = 0.0; /* default lb */ if (ub == -DBL_MAX) ub = +DBL_MAX; /* default ub */ if (lb == -DBL_MAX && ub == +DBL_MAX) type = LPX_FR; else if (ub == +DBL_MAX) type = LPX_LO; else if (lb == -DBL_MAX) type = LPX_UP; else if (lb != ub) type = LPX_DB; else type = LPX_FX; lpx_set_col_bnds(dsa->lp, j, type, lb, ub); } } /* print some statistics */ { int m = lpx_get_num_rows(dsa->lp); int n = lpx_get_num_cols(dsa->lp); int nnz = lpx_get_num_nz(dsa->lp); print("lpx_read_cpxlp: %d row%s, %d column%s, %d non-zero%s", m, m == 1 ? "" : "s", n, n == 1 ? "" : "s", nnz, nnz == 1 ? "" : "s"); } if (lpx_get_class(dsa->lp) == LPX_MIP) { int ni = lpx_get_num_int(dsa->lp); int nb = lpx_get_num_bin(dsa->lp); char s[50]; if (nb == 0) strcpy(s, "none of"); else if (ni == 1 && nb == 1) strcpy(s, ""); else if (nb == 1) strcpy(s, "one of"); else if (nb == ni) strcpy(s, "all of"); else sprintf(s, "%d of", nb); print("lpx_read_cpxlp: %d integer column%s, %s which %s binary" , ni, ni == 1 ? "" : "s", s, nb == 1 ? "is" : "are"); } print("lpx_read_cpxlp: %d lines were read", dsa->count); xfclose(dsa->fp); xfree(dsa->map); xfree(dsa->ind); xfree(dsa->val); xfree(dsa->lb); xfree(dsa->ub); lpx_delete_index(dsa->lp); lpx_order_matrix(dsa->lp); return dsa->lp; fail: if (dsa->lp != NULL) lpx_delete_prob(dsa->lp); if (dsa->fp != NULL) xfclose(dsa->fp); if (dsa->map != NULL) xfree(dsa->map); if (dsa->ind != NULL) xfree(dsa->ind); if (dsa->val != NULL) xfree(dsa->val); if (dsa->lb != NULL) xfree(dsa->lb); if (dsa->ub != NULL) xfree(dsa->ub); return NULL; }
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_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_intopt(LPX *_mip) { IPP *ipp = NULL; LPX *orig = _mip, *prob = NULL; int orig_m, orig_n, i, j, ret, i_stat; /* the problem must be of MIP class */ if (lpx_get_class(orig) != LPX_MIP) { print("lpx_intopt: problem is not of MIP class"); ret = LPX_E_FAULT; goto done; } /* the problem must have at least one row and one column */ orig_m = lpx_get_num_rows(orig); orig_n = lpx_get_num_cols(orig); if (!(orig_m > 0 && orig_n > 0)) { print("lpx_intopt: problem has no rows/columns"); ret = LPX_E_FAULT; goto done; } /* check that each double-bounded row and column has bounds */ for (i = 1; i <= orig_m; i++) { if (lpx_get_row_type(orig, i) == LPX_DB) { if (lpx_get_row_lb(orig, i) >= lpx_get_row_ub(orig, i)) { print("lpx_intopt: row %d has incorrect bounds", i); ret = LPX_E_FAULT; goto done; } } } for (j = 1; j <= orig_n; j++) { if (lpx_get_col_type(orig, j) == LPX_DB) { if (lpx_get_col_lb(orig, j) >= lpx_get_col_ub(orig, j)) { print("lpx_intopt: column %d has incorrect bounds", j); ret = LPX_E_FAULT; goto done; } } } /* bounds of all integer variables must be integral */ for (j = 1; j <= orig_n; j++) { int type; double lb, ub; if (lpx_get_col_kind(orig, j) != LPX_IV) continue; type = lpx_get_col_type(orig, j); if (type == LPX_LO || type == LPX_DB || type == LPX_FX) { lb = lpx_get_col_lb(orig, j); if (lb != floor(lb)) { print("lpx_intopt: integer column %d has non-integer low" "er 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(orig, j); if (ub != floor(ub)) { print("lpx_intopt: integer column %d has non-integer upp" "er bound %g", j, ub); ret = LPX_E_FAULT; goto done; } } } /* reset the status of MIP solution */ lpx_put_mip_soln(orig, LPX_I_UNDEF, NULL, NULL); /* create MIP presolver workspace */ ipp = ipp_create_wksp(); /* load the original problem into the presolver workspace */ ipp_load_orig(ipp, orig); /* perform basic MIP presolve analysis */ switch (ipp_basic_tech(ipp)) { case 0: /* no infeasibility is detected */ break; case 1: nopfs: /* primal infeasibility is detected */ print("PROBLEM HAS NO PRIMAL FEASIBLE SOLUTION"); ret = LPX_E_NOPFS; goto done; case 2: /* dual infeasibility is detected */ nodfs: print("LP RELAXATION HAS NO DUAL FEASIBLE SOLUTION"); ret = LPX_E_NODFS; goto done; default: insist(ipp != ipp); } /* reduce column bounds */ switch (ipp_reduce_bnds(ipp)) { case 0: break; case 1: goto nopfs; default: insist(ipp != ipp); } /* perform basic MIP presolve analysis */ switch (ipp_basic_tech(ipp)) { case 0: break; case 1: goto nopfs; case 2: goto nodfs; default: insist(ipp != ipp); } /* replace general integer variables by sum of binary variables, if required */ if (lpx_get_int_parm(orig, LPX_K_BINARIZE)) ipp_binarize(ipp); /* perform coefficient reduction */ ipp_reduction(ipp); /* if the resultant problem is empty, it has an empty solution, which is optimal */ if (ipp->row_ptr == NULL || ipp->col_ptr == NULL) { insist(ipp->row_ptr == NULL); insist(ipp->col_ptr == NULL); print("Objective value = %.10g", ipp->orig_dir == LPX_MIN ? +ipp->c0 : -ipp->c0); print("INTEGER OPTIMAL SOLUTION FOUND BY MIP PRESOLVER"); /* allocate recovered solution segment */ ipp->col_stat = ucalloc(1+ipp->ncols, sizeof(int)); ipp->col_mipx = ucalloc(1+ipp->ncols, sizeof(double)); for (j = 1; j <= ipp->ncols; j++) ipp->col_stat[j] = 0; /* perform MIP postsolve processing */ ipp_postsolve(ipp); /* unload recovered MIP solution and store it in the original problem object */ ipp_unload_sol(ipp, orig, LPX_I_OPT); ret = LPX_E_OK; goto done; } /* build resultant MIP problem object */ prob = ipp_build_prob(ipp); /* display some statistics */ { int m = lpx_get_num_rows(prob); int n = lpx_get_num_cols(prob); int nnz = lpx_get_num_nz(prob); int ni = lpx_get_num_int(prob); int nb = lpx_get_num_bin(prob); char s[50]; print("lpx_intopt: presolved MIP has %d row%s, %d column%s, %d" " non-zero%s", m, m == 1 ? "" : "s", n, n == 1 ? "" : "s", nnz, nnz == 1 ? "" : "s"); if (nb == 0) strcpy(s, "none of"); else if (ni == 1 && nb == 1) strcpy(s, ""); else if (nb == 1) strcpy(s, "one of"); else if (nb == ni) strcpy(s, "all of"); else sprintf(s, "%d of", nb); print("lpx_intopt: %d integer column%s, %s which %s binary", ni, ni == 1 ? "" : "s", s, nb == 1 ? "is" : "are"); } /* inherit some control parameters and statistics */ lpx_set_int_parm(prob, LPX_K_PRICE, lpx_get_int_parm(orig, LPX_K_PRICE)); lpx_set_real_parm(prob, LPX_K_RELAX, lpx_get_real_parm(orig, LPX_K_RELAX)); lpx_set_real_parm(prob, LPX_K_TOLBND, lpx_get_real_parm(orig, LPX_K_TOLBND)); lpx_set_real_parm(prob, LPX_K_TOLDJ, lpx_get_real_parm(orig, LPX_K_TOLDJ)); lpx_set_real_parm(prob, LPX_K_TOLPIV, lpx_get_real_parm(orig, LPX_K_TOLPIV)); lpx_set_int_parm(prob, LPX_K_ITLIM, lpx_get_int_parm(orig, LPX_K_ITLIM)); lpx_set_int_parm(prob, LPX_K_ITCNT, lpx_get_int_parm(orig, LPX_K_ITCNT)); lpx_set_real_parm(prob, LPX_K_TMLIM, lpx_get_real_parm(orig, LPX_K_TMLIM)); lpx_set_int_parm(prob, LPX_K_BRANCH, lpx_get_int_parm(orig, LPX_K_BRANCH)); lpx_set_int_parm(prob, LPX_K_BTRACK, lpx_get_int_parm(orig, LPX_K_BTRACK)); lpx_set_real_parm(prob, LPX_K_TOLINT, lpx_get_real_parm(orig, LPX_K_TOLINT)); lpx_set_real_parm(prob, LPX_K_TOLOBJ, lpx_get_real_parm(orig, LPX_K_TOLOBJ)); /* build an advanced initial basis */ lpx_adv_basis(prob); /* solve LP relaxation */ print("Solving LP relaxation..."); switch (lpx_simplex(prob)) { case LPX_E_OK: break; case LPX_E_ITLIM: ret = LPX_E_ITLIM; goto done; case LPX_E_TMLIM: ret = LPX_E_TMLIM; goto done; default: print("lpx_intopt: cannot solve LP relaxation"); ret = LPX_E_SING; goto done; } /* analyze status of the basic solution */ switch (lpx_get_status(prob)) { case LPX_OPT: break; case LPX_NOFEAS: ret = LPX_E_NOPFS; goto done; case LPX_UNBND: ret = LPX_E_NODFS; goto done; default: insist(prob != prob); } /* generate cutting planes, if necessary */ if (lpx_get_int_parm(orig, LPX_K_USECUTS)) { ret = generate_cuts(prob); if (ret != LPX_E_OK) goto done; } /* call the branch-and-bound solver */ ret = lpx_integer(prob); /* determine status of MIP solution */ i_stat = lpx_mip_status(prob); if (i_stat == LPX_I_OPT || i_stat == LPX_I_FEAS) { /* load MIP solution of the resultant problem into presolver workspace */ ipp_load_sol(ipp, prob); /* perform MIP postsolve processing */ ipp_postsolve(ipp); /* unload recovered MIP solution and store it in the original problem object */ ipp_unload_sol(ipp, orig, i_stat); } else { /* just set the status of MIP solution */ lpx_put_mip_soln(orig, i_stat, NULL, NULL); } done: /* copy back statistics about spent resources */ if (prob != NULL) { lpx_set_int_parm(orig, LPX_K_ITLIM, lpx_get_int_parm(prob, LPX_K_ITLIM)); lpx_set_int_parm(orig, LPX_K_ITCNT, lpx_get_int_parm(prob, LPX_K_ITCNT)); lpx_set_real_parm(orig, LPX_K_TMLIM, lpx_get_real_parm(prob, LPX_K_TMLIM)); } /* delete the resultant problem object */ if (prob != NULL) lpx_delete_prob(prob); /* delete MIP presolver workspace */ if (ipp != NULL) ipp_delete_wksp(ipp); return ret; }