📄 glpapi06.c
字号:
/* glpapi06.c (simplex method routines) *//************************************************************************ This code is part of GLPK (GNU Linear Programming Kit).** Copyright (C) 2000,01,02,03,04,05,06,07,08,2009 Andrew Makhorin,* Department for Applied Informatics, Moscow Aviation Institute,* Moscow, Russia. All rights reserved. E-mail: <mao@mai2.rcnet.ru>.** GLPK is free software: you can redistribute it and/or modify it* under the terms of the GNU General Public License as published by* the Free Software Foundation, either version 3 of the License, or* (at your option) any later version.** GLPK is distributed in the hope that it will be useful, but WITHOUT* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public* License for more details.** You should have received a copy of the GNU General Public License* along with GLPK. If not, see <http://www.gnu.org/licenses/>.***********************************************************************/#include "glpapi.h"#include "glplpp.h"#include "glpspx.h"/************************************************************************ NAME** glp_simplex - solve LP problem with the simplex method** SYNOPSIS** int glp_simplex(glp_prob *lp, const glp_smcp *parm);** DESCRIPTION** The routine glp_simplex is a driver to the LP solver based on the* simplex method. This routine retrieves problem data from the* specified problem object, calls the solver to solve the problem* instance, and stores results of computations back into the problem* object.** The simplex solver has a set of control parameters. Values of the* control parameters can be passed in a structure glp_smcp, which the* parameter parm points to.** The parameter parm can be specified as NULL, in which case the LP* solver uses default settings.** RETURNS** 0 The LP problem instance has been successfully solved. This code* does not necessarily mean that the solver has found optimal* solution. It only means that the solution process was successful.** GLP_EBADB* Unable to start the search, because the initial basis specified* in the problem object is invalid--the number of basic (auxiliary* and structural) variables is not the same as the number of rows in* the problem object.** GLP_ESING* Unable to start the search, because the basis matrix correspodning* to the initial basis is singular within the working precision.** GLP_ECOND* Unable to start the search, because the basis matrix correspodning* to the initial basis is ill-conditioned, i.e. its condition number* is too large.** GLP_EBOUND* Unable to start the search, because some double-bounded variables* have incorrect bounds.** GLP_EFAIL* The search was prematurely terminated due to the solver failure.** GLP_EOBJLL* The search was prematurely terminated, because the objective* function being maximized has reached its lower limit and continues* decreasing (dual simplex only).** GLP_EOBJUL* The search was prematurely terminated, because the objective* function being minimized has reached its upper limit and continues* increasing (dual simplex only).** GLP_EITLIM* The search was prematurely terminated, because the simplex* iteration limit has been exceeded.** GLP_ETMLIM* The search was prematurely terminated, because the time limit has* been exceeded.** GLP_ENOPFS* The LP problem instance has no primal feasible solution (only if* the LP presolver is used).** GLP_ENODFS* The LP problem instance has no dual feasible solution (only if the* LP presolver is used). */static void trivial1(glp_prob *lp, const glp_smcp *parm){ /* solve trivial LP problem which has no rows */ int j; double dir; xassert(lp->m == 0); switch (lp->dir) { case GLP_MIN: dir = +1.0; break; case GLP_MAX: dir = -1.0; break; default: xassert(lp != lp); } lp->pbs_stat = lp->dbs_stat = GLP_FEAS; lp->obj_val = lp->c0; lp->some = 0; for (j = 1; j <= lp->n; j++) { GLPCOL *col = lp->col[j]; col->dual = col->coef; switch (col->type) { case GLP_FR: if (dir * col->dual < -1e-7) lp->dbs_stat = GLP_NOFEAS; if (dir * col->dual > +1e-7) lp->dbs_stat = GLP_NOFEAS; col->stat = GLP_NF; col->prim = 0.0; break; case GLP_LO: if (dir * col->dual < -1e-7) lp->dbs_stat = GLP_NOFEAS;lo: col->stat = GLP_NL; col->prim = col->lb; break; case GLP_UP: if (dir * col->dual > +1e-7) lp->dbs_stat = GLP_NOFEAS;up: col->stat = GLP_NU; col->prim = col->ub; break; case GLP_DB: if (dir * col->dual < 0.0) goto up; if (dir * col->dual > 0.0) goto lo; if (fabs(col->lb) <= fabs(col->ub)) goto lo; else goto up; case GLP_FX: col->stat = GLP_NS; col->prim = col->lb; break; default: xassert(lp != lp); } lp->obj_val += col->coef * col->prim; if (lp->dbs_stat == GLP_NOFEAS && lp->some == 0) lp->some = j; } if (parm->msg_lev >= GLP_MSG_ON && parm->out_dly == 0) { xprintf("~%6d: objval = %17.9e infeas = %17.9e\n", lp->it_cnt, lp->obj_val, 0.0); if (parm->msg_lev >= GLP_MSG_ALL) { if (lp->dbs_stat == GLP_FEAS) xprintf("OPTIMAL SOLUTION FOUND\n"); else xprintf("PROBLEM HAS UNBOUNDED SOLUTION\n"); } } return;}static void trivial2(glp_prob *lp, const glp_smcp *parm){ /* solve trivial LP problem which has no columns */ int i; xassert(lp->n == 0); lp->pbs_stat = lp->dbs_stat = GLP_FEAS; lp->obj_val = lp->c0; lp->some = 0; for (i = 1; i <= lp->m; i++) { GLPROW *row = lp->row[i]; row->stat = GLP_BS; row->prim = row->dual = 0.0; switch (row->type) { case GLP_FR: break; case GLP_LO: if (row->lb > +1e-8) lp->pbs_stat = GLP_NOFEAS; break; case GLP_UP: if (row->ub < -1e-8) lp->pbs_stat = GLP_NOFEAS; break; case GLP_DB: case GLP_FX: if (row->lb > +1e-8) lp->pbs_stat = GLP_NOFEAS; if (row->ub < -1e-8) lp->pbs_stat = GLP_NOFEAS; break; default: xassert(lp != lp); } } if (parm->msg_lev >= GLP_MSG_ON && parm->out_dly == 0) { xprintf("~%6d: objval = %17.9e infeas = %17.9e\n", lp->it_cnt, lp->obj_val); if (parm->msg_lev >= GLP_MSG_ALL) { if (lp->pbs_stat == GLP_FEAS) xprintf("OPTIMAL SOLUTION FOUND\n"); else xprintf("PROBLEM HAS NO FEASIBLE SOLUTION\n"); } } return;}#if 1 /* 18/VIII-2008 */static int simplex1(glp_prob *lp, const glp_smcp *parm){ /* base driver which does not use LP presolver */ int ret; if (!glp_bf_exists(lp)) { ret = glp_factorize(lp); switch (ret) { case 0: break; case GLP_EBADB: if (parm->msg_lev >= GLP_MSG_ERR) xprintf("glp_simplex: initial basis is invalid\n"); goto done; case GLP_ESING: if (parm->msg_lev >= GLP_MSG_ERR) xprintf("glp_simplex: initial basis is singular\n"); goto done; case GLP_ECOND: if (parm->msg_lev >= GLP_MSG_ERR) xprintf("glp_simplex: initial basis is ill-conditione" "d\n"); goto done; default: xassert(ret != ret); } } switch (parm->meth) { case GLP_PRIMAL: ret = spx_primal(lp, parm); break; case GLP_DUALP: { glp_smcp parm1 = *parm;#if 0 parm1.msg_lev = GLP_MSG_DBG; parm1.out_frq = 1; parm1.out_dly = 0;#endif ret = spx_dual(lp, &parm1);#if 1 if (ret == GLP_EFAIL && lp->valid) ret = spx_primal(lp, parm);#endif } break; case GLP_DUAL: ret = spx_dual(lp, parm); break; default: xassert(parm != parm); }done: return ret;}#endifstatic int simplex2(glp_prob *orig, const glp_smcp *parm){ /* extended driver which uses LP presolver */ LPP *lpp; glp_prob *prob; glp_bfcp bfcp; int orig_m, orig_n, orig_nnz, ret; orig_m = glp_get_num_rows(orig); orig_n = glp_get_num_cols(orig); orig_nnz = glp_get_num_nz(orig); if (parm->msg_lev >= GLP_MSG_ALL) { xprintf("glp_simplex: original LP has %d row%s, %d column%s, %" "d non-zero%s\n", orig_m, orig_m == 1 ? "" : "s", orig_n, orig_n == 1 ? "" : "s", orig_nnz, orig_nnz == 1 ? "" : "s"); } /* the problem must have at least one row and one column */ xassert(orig_m > 0 && orig_n > 0); /* create LP presolver workspace */ lpp = lpp_create_wksp(); /* load the original problem into LP presolver workspace */ lpp_load_orig(lpp, orig); /* perform LP presolve analysis */ ret = lpp_presolve(lpp); switch (ret) { case 0: /* presolving has been successfully completed */ break; case 1: /* the original problem is primal infeasible */ if (parm->msg_lev >= GLP_MSG_ALL) xprintf("PROBLEM HAS NO PRIMAL FEASIBLE SOLUTION\n"); lpp_delete_wksp(lpp); return GLP_ENOPFS; case 2: /* the original problem is dual infeasible */ if (parm->msg_lev >= GLP_MSG_ALL) xprintf("PROBLEM HAS NO DUAL FEASIBLE SOLUTION\n"); lpp_delete_wksp(lpp); return GLP_ENODFS; default: xassert(ret != ret); } /* if the resultant problem is empty, it has an empty solution, which is optimal */ if (lpp->row_ptr == NULL || lpp->col_ptr == NULL) { xassert(lpp->row_ptr == NULL); xassert(lpp->col_ptr == NULL); if (parm->msg_lev >= GLP_MSG_ALL) { xprintf("Objective value = %.10g\n", lpp->orig_dir == LPX_MIN ? + lpp->c0 : - lpp->c0); xprintf("OPTIMAL SOLUTION FOUND BY LP PRESOLVER\n"); } /* allocate recovered solution segment */ lpp_alloc_sol(lpp); goto post; } /* build resultant LP problem object */ prob = lpp_build_prob(lpp); if (parm->msg_lev >= GLP_MSG_ALL) { int m = glp_get_num_rows(prob); int n = glp_get_num_cols(prob); int nnz = glp_get_num_nz(prob); xprintf("glp_simplex: presolved LP has %d row%s, %d column%s, " "%d non-zero%s\n", m, m == 1 ? "" : "s", n, n == 1 ? "" : "s", nnz, nnz == 1 ? "" : "s"); } /* inherit basis factorization control parameters */ glp_get_bfcp(orig, &bfcp); glp_set_bfcp(prob, &bfcp); /* scale the resultant problem */ { LIBENV *env = lib_link_env(); int term_out = env->term_out; if (!term_out || parm->msg_lev < GLP_MSG_ALL) env->term_out = GLP_OFF; else env->term_out = GLP_ON; glp_scale_prob(prob, GLP_SF_AUTO); env->term_out = term_out; } /* build advanced initial basis */ { LIBENV *env = lib_link_env(); int term_out = env->term_out; if (!term_out || parm->msg_lev < GLP_MSG_ALL) env->term_out = GLP_OFF; else env->term_out = GLP_ON; lpx_adv_basis(prob); env->term_out = term_out; } /* try to solve the resultant problem */ prob->it_cnt = orig->it_cnt; ret = simplex1(prob, parm); orig->it_cnt = prob->it_cnt; /* check if the optimal solution has been found */ if (glp_get_status(prob) != GLP_OPT) { if (parm->msg_lev >= GLP_MSG_ERR) xprintf("glp_simplex: cannot recover undefined or non-optim" "al solution\n"); if (ret == 0) { if (glp_get_prim_stat(prob) == GLP_NOFEAS) ret = GLP_ENOPFS; else if (glp_get_dual_stat(prob) == GLP_NOFEAS) ret = GLP_ENODFS; } glp_delete_prob(prob); lpp_delete_wksp(lpp); return ret; } /* allocate recovered solution segment */ lpp_alloc_sol(lpp); /* load basic solution of the resultant problem into LP presolver workspace */ lpp_load_sol(lpp, prob); /* the resultant problem object is no longer needed */ glp_delete_prob(prob);post: /* perform LP postsolve processing */ lpp_postsolve(lpp); /* unload recovered basic solution and store it into the original problem object */ lpp_unload_sol(lpp, orig); /* delete LP presolver workspace */ lpp_delete_wksp(lpp); /* the original problem has been successfully solved */ return 0;}int glp_simplex(glp_prob *lp, const glp_smcp *parm){ glp_smcp _parm; int i, j, ret; if (parm == NULL) parm = &_parm, glp_init_smcp((glp_smcp *)parm); /* check control parameters */ if (!(parm->msg_lev == GLP_MSG_OFF || parm->msg_lev == GLP_MSG_ERR || parm->msg_lev == GLP_MSG_ON || parm->msg_lev == GLP_MSG_ALL)) xerror("glp_simplex: msg_lev = %d; invalid parameter\n", parm->msg_lev); if (!(parm->meth == GLP_PRIMAL || parm->meth == GLP_DUALP || parm->meth == GLP_DUAL)) xerror("glp_simplex: meth = %d; invalid parameter\n", parm->meth); if (!(parm->pricing == GLP_PT_STD ||
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -