void ipp_load_sol(IPP *ipp, LPX *prob) { IPPCOL *col; int j; xassert(lpx_mip_status(prob) != LPX_I_UNDEF); ipp->col_stat = xcalloc(1+ipp->ncols, sizeof(int)); ipp->col_mipx = xcalloc(1+ipp->ncols, sizeof(double)); for (j = 1; j <= ipp->ncols; j++) ipp->col_stat[j] = 0; /* columns in the problem object follow in the same order as in the column list (see ipp_build_prob) */ j = 0; for (col = ipp->col_ptr; col != NULL; col = col->next) { j++; ipp->col_stat[col->j] = 1; ipp->col_mipx[col->j] = lpx_mip_col_val(prob, j); } return; }
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; }
OptSolutionData* GLPKRunSolver(int ProbType) { OptSolutionData* NewSolution = NULL; int NumVariables = lpx_get_num_cols(GLPKModel); int Status = 0; if (ProbType == MILP) { Status = lpx_simplex(GLPKModel); if (Status != LPX_E_OK) { FErrorFile() << "Failed to optimize problem." << endl; FlushErrorFile(); return NULL; } Status = lpx_integer(GLPKModel); if (Status != LPX_E_OK) { FErrorFile() << "Failed to optimize problem." << endl; FlushErrorFile(); return NULL; } NewSolution = new OptSolutionData; Status = lpx_mip_status(GLPKModel); if (Status == LPX_I_UNDEF || Status == LPX_I_NOFEAS) { NewSolution->Status = INFEASIBLE; return NewSolution; } else if (Status == LPX_I_FEAS) { NewSolution->Status = UNBOUNDED; return NewSolution; } else if (Status == LPX_I_OPT) { NewSolution->Status = SUCCESS; } else { delete NewSolution; FErrorFile() << "Problem status unrecognized." << endl; FlushErrorFile(); return NULL; } NewSolution->Objective = lpx_mip_obj_val(GLPKModel); NewSolution->SolutionData.resize(NumVariables); for (int i=0; i < NumVariables; i++) { NewSolution->SolutionData[i] = lpx_mip_col_val(GLPKModel, i+1); } } else if (ProbType == LP) { //First we check the basis matrix to ensure it is not sigular if (lpx_warm_up(GLPKModel) != LPX_E_OK) { lpx_adv_basis(GLPKModel); } Status = lpx_simplex(GLPKModel); if (Status == LPX_E_FAULT) { Status = lpx_warm_up(GLPKModel); if (Status == LPX_E_BADB) { /* the basis is invalid; build some valid basis */ lpx_adv_basis(GLPKModel); Status = lpx_simplex(GLPKModel); } } if (Status != LPX_E_OK) { FErrorFile() << "Failed to optimize problem." << endl; FlushErrorFile(); return NULL; } NewSolution = new OptSolutionData; Status = lpx_get_status(GLPKModel); if (Status == LPX_INFEAS || Status == LPX_NOFEAS || Status == LPX_UNDEF) { cout << "Model is infeasible" << endl; FErrorFile() << "Model is infeasible" << endl; FlushErrorFile(); NewSolution->Status = INFEASIBLE; return NewSolution; } else if (Status == LPX_FEAS || Status == LPX_UNBND) { cout << "Model is unbounded" << endl; FErrorFile() << "Model is unbounded" << endl; FlushErrorFile(); NewSolution->Status = UNBOUNDED; return NewSolution; } else if (Status == LPX_OPT) { NewSolution->Status = SUCCESS; } else { delete NewSolution; FErrorFile() << "Problem status unrecognized." << endl; FlushErrorFile(); return NULL; } NewSolution->Objective = lpx_get_obj_val(GLPKModel); NewSolution->SolutionData.resize(NumVariables); for (int i=0; i < NumVariables; i++) { NewSolution->SolutionData[i] = lpx_get_col_prim(GLPKModel, i+1); } } else { FErrorFile() << "Optimization problem type cannot be handled by GLPK solver." << endl; FlushErrorFile(); return NULL; } return NewSolution; }
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; }