src/glpapi06.c
author Alpar Juttner <alpar@cs.elte.hu>
Sun, 05 Dec 2010 17:35:23 +0100
changeset 2 4c8956a7bdf4
permissions -rw-r--r--
Set up CMAKE build environment
alpar@1
     1
/* glpapi06.c (simplex method routines) */
alpar@1
     2
alpar@1
     3
/***********************************************************************
alpar@1
     4
*  This code is part of GLPK (GNU Linear Programming Kit).
alpar@1
     5
*
alpar@1
     6
*  Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
alpar@1
     7
*  2009, 2010 Andrew Makhorin, Department for Applied Informatics,
alpar@1
     8
*  Moscow Aviation Institute, Moscow, Russia. All rights reserved.
alpar@1
     9
*  E-mail: <mao@gnu.org>.
alpar@1
    10
*
alpar@1
    11
*  GLPK is free software: you can redistribute it and/or modify it
alpar@1
    12
*  under the terms of the GNU General Public License as published by
alpar@1
    13
*  the Free Software Foundation, either version 3 of the License, or
alpar@1
    14
*  (at your option) any later version.
alpar@1
    15
*
alpar@1
    16
*  GLPK is distributed in the hope that it will be useful, but WITHOUT
alpar@1
    17
*  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
alpar@1
    18
*  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
alpar@1
    19
*  License for more details.
alpar@1
    20
*
alpar@1
    21
*  You should have received a copy of the GNU General Public License
alpar@1
    22
*  along with GLPK. If not, see <http://www.gnu.org/licenses/>.
alpar@1
    23
***********************************************************************/
alpar@1
    24
alpar@1
    25
#include "glpios.h"
alpar@1
    26
#include "glpnpp.h"
alpar@1
    27
#include "glpspx.h"
alpar@1
    28
alpar@1
    29
/***********************************************************************
alpar@1
    30
*  NAME
alpar@1
    31
*
alpar@1
    32
*  glp_simplex - solve LP problem with the simplex method
alpar@1
    33
*
alpar@1
    34
*  SYNOPSIS
alpar@1
    35
*
alpar@1
    36
*  int glp_simplex(glp_prob *P, const glp_smcp *parm);
alpar@1
    37
*
alpar@1
    38
*  DESCRIPTION
alpar@1
    39
*
alpar@1
    40
*  The routine glp_simplex is a driver to the LP solver based on the
alpar@1
    41
*  simplex method. This routine retrieves problem data from the
alpar@1
    42
*  specified problem object, calls the solver to solve the problem
alpar@1
    43
*  instance, and stores results of computations back into the problem
alpar@1
    44
*  object.
alpar@1
    45
*
alpar@1
    46
*  The simplex solver has a set of control parameters. Values of the
alpar@1
    47
*  control parameters can be passed in a structure glp_smcp, which the
alpar@1
    48
*  parameter parm points to.
alpar@1
    49
*
alpar@1
    50
*  The parameter parm can be specified as NULL, in which case the LP
alpar@1
    51
*  solver uses default settings.
alpar@1
    52
*
alpar@1
    53
*  RETURNS
alpar@1
    54
*
alpar@1
    55
*  0  The LP problem instance has been successfully solved. This code
alpar@1
    56
*     does not necessarily mean that the solver has found optimal
alpar@1
    57
*     solution. It only means that the solution process was successful.
alpar@1
    58
*
alpar@1
    59
*  GLP_EBADB
alpar@1
    60
*     Unable to start the search, because the initial basis specified
alpar@1
    61
*     in the problem object is invalid--the number of basic (auxiliary
alpar@1
    62
*     and structural) variables is not the same as the number of rows in
alpar@1
    63
*     the problem object.
alpar@1
    64
*
alpar@1
    65
*  GLP_ESING
alpar@1
    66
*     Unable to start the search, because the basis matrix correspodning
alpar@1
    67
*     to the initial basis is singular within the working precision.
alpar@1
    68
*
alpar@1
    69
*  GLP_ECOND
alpar@1
    70
*     Unable to start the search, because the basis matrix correspodning
alpar@1
    71
*     to the initial basis is ill-conditioned, i.e. its condition number
alpar@1
    72
*     is too large.
alpar@1
    73
*
alpar@1
    74
*  GLP_EBOUND
alpar@1
    75
*     Unable to start the search, because some double-bounded variables
alpar@1
    76
*     have incorrect bounds.
alpar@1
    77
*
alpar@1
    78
*  GLP_EFAIL
alpar@1
    79
*     The search was prematurely terminated due to the solver failure.
alpar@1
    80
*
alpar@1
    81
*  GLP_EOBJLL
alpar@1
    82
*     The search was prematurely terminated, because the objective
alpar@1
    83
*     function being maximized has reached its lower limit and continues
alpar@1
    84
*     decreasing (dual simplex only).
alpar@1
    85
*
alpar@1
    86
*  GLP_EOBJUL
alpar@1
    87
*     The search was prematurely terminated, because the objective
alpar@1
    88
*     function being minimized has reached its upper limit and continues
alpar@1
    89
*     increasing (dual simplex only).
alpar@1
    90
*
alpar@1
    91
*  GLP_EITLIM
alpar@1
    92
*     The search was prematurely terminated, because the simplex
alpar@1
    93
*     iteration limit has been exceeded.
alpar@1
    94
*
alpar@1
    95
*  GLP_ETMLIM
alpar@1
    96
*     The search was prematurely terminated, because the time limit has
alpar@1
    97
*     been exceeded.
alpar@1
    98
*
alpar@1
    99
*  GLP_ENOPFS
alpar@1
   100
*     The LP problem instance has no primal feasible solution (only if
alpar@1
   101
*     the LP presolver is used).
alpar@1
   102
*
alpar@1
   103
*  GLP_ENODFS
alpar@1
   104
*     The LP problem instance has no dual feasible solution (only if the
alpar@1
   105
*     LP presolver is used). */
alpar@1
   106
alpar@1
   107
static void trivial_lp(glp_prob *P, const glp_smcp *parm)
alpar@1
   108
{     /* solve trivial LP which has empty constraint matrix */
alpar@1
   109
      GLPROW *row;
alpar@1
   110
      GLPCOL *col;
alpar@1
   111
      int i, j;
alpar@1
   112
      double p_infeas, d_infeas, zeta;
alpar@1
   113
      P->valid = 0;
alpar@1
   114
      P->pbs_stat = P->dbs_stat = GLP_FEAS;
alpar@1
   115
      P->obj_val = P->c0;
alpar@1
   116
      P->some = 0;
alpar@1
   117
      p_infeas = d_infeas = 0.0;
alpar@1
   118
      /* make all auxiliary variables basic */
alpar@1
   119
      for (i = 1; i <= P->m; i++)
alpar@1
   120
      {  row = P->row[i];
alpar@1
   121
         row->stat = GLP_BS;
alpar@1
   122
         row->prim = row->dual = 0.0;
alpar@1
   123
         /* check primal feasibility */
alpar@1
   124
         if (row->type == GLP_LO || row->type == GLP_DB ||
alpar@1
   125
             row->type == GLP_FX)
alpar@1
   126
         {  /* row has lower bound */
alpar@1
   127
            if (row->lb > + parm->tol_bnd)
alpar@1
   128
            {  P->pbs_stat = GLP_NOFEAS;
alpar@1
   129
               if (P->some == 0 && parm->meth != GLP_PRIMAL)
alpar@1
   130
                  P->some = i;
alpar@1
   131
            }
alpar@1
   132
            if (p_infeas < + row->lb)
alpar@1
   133
               p_infeas = + row->lb;
alpar@1
   134
         }
alpar@1
   135
         if (row->type == GLP_UP || row->type == GLP_DB ||
alpar@1
   136
             row->type == GLP_FX)
alpar@1
   137
         {  /* row has upper bound */
alpar@1
   138
            if (row->ub < - parm->tol_bnd)
alpar@1
   139
            {  P->pbs_stat = GLP_NOFEAS;
alpar@1
   140
               if (P->some == 0 && parm->meth != GLP_PRIMAL)
alpar@1
   141
                  P->some = i;
alpar@1
   142
            }
alpar@1
   143
            if (p_infeas < - row->ub)
alpar@1
   144
               p_infeas = - row->ub;
alpar@1
   145
         }
alpar@1
   146
      }
alpar@1
   147
      /* determine scale factor for the objective row */
alpar@1
   148
      zeta = 1.0;
alpar@1
   149
      for (j = 1; j <= P->n; j++)
alpar@1
   150
      {  col = P->col[j];
alpar@1
   151
         if (zeta < fabs(col->coef)) zeta = fabs(col->coef);
alpar@1
   152
      }
alpar@1
   153
      zeta = (P->dir == GLP_MIN ? +1.0 : -1.0) / zeta;
alpar@1
   154
      /* make all structural variables non-basic */
alpar@1
   155
      for (j = 1; j <= P->n; j++)
alpar@1
   156
      {  col = P->col[j];
alpar@1
   157
         if (col->type == GLP_FR)
alpar@1
   158
            col->stat = GLP_NF, col->prim = 0.0;
alpar@1
   159
         else if (col->type == GLP_LO)
alpar@1
   160
lo:         col->stat = GLP_NL, col->prim = col->lb;
alpar@1
   161
         else if (col->type == GLP_UP)
alpar@1
   162
up:         col->stat = GLP_NU, col->prim = col->ub;
alpar@1
   163
         else if (col->type == GLP_DB)
alpar@1
   164
         {  if (zeta * col->coef > 0.0)
alpar@1
   165
               goto lo;
alpar@1
   166
            else if (zeta * col->coef < 0.0)
alpar@1
   167
               goto up;
alpar@1
   168
            else if (fabs(col->lb) <= fabs(col->ub))
alpar@1
   169
               goto lo;
alpar@1
   170
            else
alpar@1
   171
               goto up;
alpar@1
   172
         }
alpar@1
   173
         else if (col->type == GLP_FX)
alpar@1
   174
            col->stat = GLP_NS, col->prim = col->lb;
alpar@1
   175
         col->dual = col->coef;
alpar@1
   176
         P->obj_val += col->coef * col->prim;
alpar@1
   177
         /* check dual feasibility */
alpar@1
   178
         if (col->type == GLP_FR || col->type == GLP_LO)
alpar@1
   179
         {  /* column has no upper bound */
alpar@1
   180
            if (zeta * col->dual < - parm->tol_dj)
alpar@1
   181
            {  P->dbs_stat = GLP_NOFEAS;
alpar@1
   182
               if (P->some == 0 && parm->meth == GLP_PRIMAL)
alpar@1
   183
                  P->some = P->m + j;
alpar@1
   184
            }
alpar@1
   185
            if (d_infeas < - zeta * col->dual)
alpar@1
   186
               d_infeas = - zeta * col->dual;
alpar@1
   187
         }
alpar@1
   188
         if (col->type == GLP_FR || col->type == GLP_UP)
alpar@1
   189
         {  /* column has no lower bound */
alpar@1
   190
            if (zeta * col->dual > + parm->tol_dj)
alpar@1
   191
            {  P->dbs_stat = GLP_NOFEAS;
alpar@1
   192
               if (P->some == 0 && parm->meth == GLP_PRIMAL)
alpar@1
   193
                  P->some = P->m + j;
alpar@1
   194
            }
alpar@1
   195
            if (d_infeas < + zeta * col->dual)
alpar@1
   196
               d_infeas = + zeta * col->dual;
alpar@1
   197
         }
alpar@1
   198
      }
alpar@1
   199
      /* simulate the simplex solver output */
alpar@1
   200
      if (parm->msg_lev >= GLP_MSG_ON && parm->out_dly == 0)
alpar@1
   201
      {  xprintf("~%6d: obj = %17.9e  infeas = %10.3e\n", P->it_cnt,
alpar@1
   202
            P->obj_val, parm->meth == GLP_PRIMAL ? p_infeas : d_infeas);
alpar@1
   203
      }
alpar@1
   204
      if (parm->msg_lev >= GLP_MSG_ALL && parm->out_dly == 0)
alpar@1
   205
      {  if (P->pbs_stat == GLP_FEAS && P->dbs_stat == GLP_FEAS)
alpar@1
   206
            xprintf("OPTIMAL SOLUTION FOUND\n");
alpar@1
   207
         else if (P->pbs_stat == GLP_NOFEAS)
alpar@1
   208
            xprintf("PROBLEM HAS NO FEASIBLE SOLUTION\n");
alpar@1
   209
         else if (parm->meth == GLP_PRIMAL)
alpar@1
   210
            xprintf("PROBLEM HAS UNBOUNDED SOLUTION\n");
alpar@1
   211
         else
alpar@1
   212
            xprintf("PROBLEM HAS NO DUAL FEASIBLE SOLUTION\n");
alpar@1
   213
      }
alpar@1
   214
      return;
alpar@1
   215
}
alpar@1
   216
alpar@1
   217
static int solve_lp(glp_prob *P, const glp_smcp *parm)
alpar@1
   218
{     /* solve LP directly without using the preprocessor */
alpar@1
   219
      int ret;
alpar@1
   220
      if (!glp_bf_exists(P))
alpar@1
   221
      {  ret = glp_factorize(P);
alpar@1
   222
         if (ret == 0)
alpar@1
   223
            ;
alpar@1
   224
         else if (ret == GLP_EBADB)
alpar@1
   225
         {  if (parm->msg_lev >= GLP_MSG_ERR)
alpar@1
   226
               xprintf("glp_simplex: initial basis is invalid\n");
alpar@1
   227
         }
alpar@1
   228
         else if (ret == GLP_ESING)
alpar@1
   229
         {  if (parm->msg_lev >= GLP_MSG_ERR)
alpar@1
   230
               xprintf("glp_simplex: initial basis is singular\n");
alpar@1
   231
         }
alpar@1
   232
         else if (ret == GLP_ECOND)
alpar@1
   233
         {  if (parm->msg_lev >= GLP_MSG_ERR)
alpar@1
   234
               xprintf(
alpar@1
   235
                  "glp_simplex: initial basis is ill-conditioned\n");
alpar@1
   236
         }
alpar@1
   237
         else
alpar@1
   238
            xassert(ret != ret);
alpar@1
   239
         if (ret != 0) goto done;
alpar@1
   240
      }
alpar@1
   241
      if (parm->meth == GLP_PRIMAL)
alpar@1
   242
         ret = spx_primal(P, parm);
alpar@1
   243
      else if (parm->meth == GLP_DUALP)
alpar@1
   244
      {  ret = spx_dual(P, parm);
alpar@1
   245
         if (ret == GLP_EFAIL && P->valid)
alpar@1
   246
            ret = spx_primal(P, parm);
alpar@1
   247
      }
alpar@1
   248
      else if (parm->meth == GLP_DUAL)
alpar@1
   249
         ret = spx_dual(P, parm);
alpar@1
   250
      else
alpar@1
   251
         xassert(parm != parm);
alpar@1
   252
done: return ret;
alpar@1
   253
}
alpar@1
   254
alpar@1
   255
static int preprocess_and_solve_lp(glp_prob *P, const glp_smcp *parm)
alpar@1
   256
{     /* solve LP using the preprocessor */
alpar@1
   257
      NPP *npp;
alpar@1
   258
      glp_prob *lp = NULL;
alpar@1
   259
      glp_bfcp bfcp;
alpar@1
   260
      int ret;
alpar@1
   261
      if (parm->msg_lev >= GLP_MSG_ALL)
alpar@1
   262
         xprintf("Preprocessing...\n");
alpar@1
   263
      /* create preprocessor workspace */
alpar@1
   264
      npp = npp_create_wksp();
alpar@1
   265
      /* load original problem into the preprocessor workspace */
alpar@1
   266
      npp_load_prob(npp, P, GLP_OFF, GLP_SOL, GLP_OFF);
alpar@1
   267
      /* process LP prior to applying primal/dual simplex method */
alpar@1
   268
      ret = npp_simplex(npp, parm);
alpar@1
   269
      if (ret == 0)
alpar@1
   270
         ;
alpar@1
   271
      else if (ret == GLP_ENOPFS)
alpar@1
   272
      {  if (parm->msg_lev >= GLP_MSG_ALL)
alpar@1
   273
            xprintf("PROBLEM HAS NO PRIMAL FEASIBLE SOLUTION\n");
alpar@1
   274
      }
alpar@1
   275
      else if (ret == GLP_ENODFS)
alpar@1
   276
      {  if (parm->msg_lev >= GLP_MSG_ALL)
alpar@1
   277
            xprintf("PROBLEM HAS NO DUAL FEASIBLE SOLUTION\n");
alpar@1
   278
      }
alpar@1
   279
      else
alpar@1
   280
         xassert(ret != ret);
alpar@1
   281
      if (ret != 0) goto done;
alpar@1
   282
      /* build transformed LP */
alpar@1
   283
      lp = glp_create_prob();
alpar@1
   284
      npp_build_prob(npp, lp);
alpar@1
   285
      /* if the transformed LP is empty, it has empty solution, which
alpar@1
   286
         is optimal */
alpar@1
   287
      if (lp->m == 0 && lp->n == 0)
alpar@1
   288
      {  lp->pbs_stat = lp->dbs_stat = GLP_FEAS;
alpar@1
   289
         lp->obj_val = lp->c0;
alpar@1
   290
         if (parm->msg_lev >= GLP_MSG_ON && parm->out_dly == 0)
alpar@1
   291
         {  xprintf("~%6d: obj = %17.9e  infeas = %10.3e\n", P->it_cnt,
alpar@1
   292
               lp->obj_val, 0.0);
alpar@1
   293
         }
alpar@1
   294
         if (parm->msg_lev >= GLP_MSG_ALL)
alpar@1
   295
            xprintf("OPTIMAL SOLUTION FOUND BY LP PREPROCESSOR\n");
alpar@1
   296
         goto post;
alpar@1
   297
      }
alpar@1
   298
      if (parm->msg_lev >= GLP_MSG_ALL)
alpar@1
   299
      {  xprintf("%d row%s, %d column%s, %d non-zero%s\n",
alpar@1
   300
            lp->m, lp->m == 1 ? "" : "s", lp->n, lp->n == 1 ? "" : "s",
alpar@1
   301
            lp->nnz, lp->nnz == 1 ? "" : "s");
alpar@1
   302
      }
alpar@1
   303
      /* inherit basis factorization control parameters */
alpar@1
   304
      glp_get_bfcp(P, &bfcp);
alpar@1
   305
      glp_set_bfcp(lp, &bfcp);
alpar@1
   306
      /* scale the transformed problem */
alpar@1
   307
      {  ENV *env = get_env_ptr();
alpar@1
   308
         int term_out = env->term_out;
alpar@1
   309
         if (!term_out || parm->msg_lev < GLP_MSG_ALL)
alpar@1
   310
            env->term_out = GLP_OFF;
alpar@1
   311
         else
alpar@1
   312
            env->term_out = GLP_ON;
alpar@1
   313
         glp_scale_prob(lp, GLP_SF_AUTO);
alpar@1
   314
         env->term_out = term_out;
alpar@1
   315
      }
alpar@1
   316
      /* build advanced initial basis */
alpar@1
   317
      {  ENV *env = get_env_ptr();
alpar@1
   318
         int term_out = env->term_out;
alpar@1
   319
         if (!term_out || parm->msg_lev < GLP_MSG_ALL)
alpar@1
   320
            env->term_out = GLP_OFF;
alpar@1
   321
         else
alpar@1
   322
            env->term_out = GLP_ON;
alpar@1
   323
         glp_adv_basis(lp, 0);
alpar@1
   324
         env->term_out = term_out;
alpar@1
   325
      }
alpar@1
   326
      /* solve the transformed LP */
alpar@1
   327
      lp->it_cnt = P->it_cnt;
alpar@1
   328
      ret = solve_lp(lp, parm);
alpar@1
   329
      P->it_cnt = lp->it_cnt;
alpar@1
   330
      /* only optimal solution can be postprocessed */
alpar@1
   331
      if (!(ret == 0 && lp->pbs_stat == GLP_FEAS && lp->dbs_stat ==
alpar@1
   332
            GLP_FEAS))
alpar@1
   333
      {  if (parm->msg_lev >= GLP_MSG_ERR)
alpar@1
   334
            xprintf("glp_simplex: unable to recover undefined or non-op"
alpar@1
   335
               "timal solution\n");
alpar@1
   336
         if (ret == 0)
alpar@1
   337
         {  if (lp->pbs_stat == GLP_NOFEAS)
alpar@1
   338
               ret = GLP_ENOPFS;
alpar@1
   339
            else if (lp->dbs_stat == GLP_NOFEAS)
alpar@1
   340
               ret = GLP_ENODFS;
alpar@1
   341
            else
alpar@1
   342
               xassert(lp != lp);
alpar@1
   343
         }
alpar@1
   344
         goto done;
alpar@1
   345
      }
alpar@1
   346
post: /* postprocess solution from the transformed LP */
alpar@1
   347
      npp_postprocess(npp, lp);
alpar@1
   348
      /* the transformed LP is no longer needed */
alpar@1
   349
      glp_delete_prob(lp), lp = NULL;
alpar@1
   350
      /* store solution to the original problem */
alpar@1
   351
      npp_unload_sol(npp, P);
alpar@1
   352
      /* the original LP has been successfully solved */
alpar@1
   353
      ret = 0;
alpar@1
   354
done: /* delete the transformed LP, if it exists */
alpar@1
   355
      if (lp != NULL) glp_delete_prob(lp);
alpar@1
   356
      /* delete preprocessor workspace */
alpar@1
   357
      npp_delete_wksp(npp);
alpar@1
   358
      return ret;
alpar@1
   359
}
alpar@1
   360
alpar@1
   361
int glp_simplex(glp_prob *P, const glp_smcp *parm)
alpar@1
   362
{     /* solve LP problem with the simplex method */
alpar@1
   363
      glp_smcp _parm;
alpar@1
   364
      int i, j, ret;
alpar@1
   365
      /* check problem object */
alpar@1
   366
      if (P == NULL || P->magic != GLP_PROB_MAGIC)
alpar@1
   367
         xerror("glp_simplex: P = %p; invalid problem object\n", P);
alpar@1
   368
      if (P->tree != NULL && P->tree->reason != 0)
alpar@1
   369
         xerror("glp_simplex: operation not allowed\n");
alpar@1
   370
      /* check control parameters */
alpar@1
   371
      if (parm == NULL)
alpar@1
   372
         parm = &_parm, glp_init_smcp((glp_smcp *)parm);
alpar@1
   373
      if (!(parm->msg_lev == GLP_MSG_OFF ||
alpar@1
   374
            parm->msg_lev == GLP_MSG_ERR ||
alpar@1
   375
            parm->msg_lev == GLP_MSG_ON  ||
alpar@1
   376
            parm->msg_lev == GLP_MSG_ALL ||
alpar@1
   377
            parm->msg_lev == GLP_MSG_DBG))
alpar@1
   378
         xerror("glp_simplex: msg_lev = %d; invalid parameter\n",
alpar@1
   379
            parm->msg_lev);
alpar@1
   380
      if (!(parm->meth == GLP_PRIMAL ||
alpar@1
   381
            parm->meth == GLP_DUALP  ||
alpar@1
   382
            parm->meth == GLP_DUAL))
alpar@1
   383
         xerror("glp_simplex: meth = %d; invalid parameter\n",
alpar@1
   384
            parm->meth);
alpar@1
   385
      if (!(parm->pricing == GLP_PT_STD ||
alpar@1
   386
            parm->pricing == GLP_PT_PSE))
alpar@1
   387
         xerror("glp_simplex: pricing = %d; invalid parameter\n",
alpar@1
   388
            parm->pricing);
alpar@1
   389
      if (!(parm->r_test == GLP_RT_STD ||
alpar@1
   390
            parm->r_test == GLP_RT_HAR))
alpar@1
   391
         xerror("glp_simplex: r_test = %d; invalid parameter\n",
alpar@1
   392
            parm->r_test);
alpar@1
   393
      if (!(0.0 < parm->tol_bnd && parm->tol_bnd < 1.0))
alpar@1
   394
         xerror("glp_simplex: tol_bnd = %g; invalid parameter\n",
alpar@1
   395
            parm->tol_bnd);
alpar@1
   396
      if (!(0.0 < parm->tol_dj && parm->tol_dj < 1.0))
alpar@1
   397
         xerror("glp_simplex: tol_dj = %g; invalid parameter\n",
alpar@1
   398
            parm->tol_dj);
alpar@1
   399
      if (!(0.0 < parm->tol_piv && parm->tol_piv < 1.0))
alpar@1
   400
         xerror("glp_simplex: tol_piv = %g; invalid parameter\n",
alpar@1
   401
            parm->tol_piv);
alpar@1
   402
      if (parm->it_lim < 0)
alpar@1
   403
         xerror("glp_simplex: it_lim = %d; invalid parameter\n",
alpar@1
   404
            parm->it_lim);
alpar@1
   405
      if (parm->tm_lim < 0)
alpar@1
   406
         xerror("glp_simplex: tm_lim = %d; invalid parameter\n",
alpar@1
   407
            parm->tm_lim);
alpar@1
   408
      if (parm->out_frq < 1)
alpar@1
   409
         xerror("glp_simplex: out_frq = %d; invalid parameter\n",
alpar@1
   410
            parm->out_frq);
alpar@1
   411
      if (parm->out_dly < 0)
alpar@1
   412
         xerror("glp_simplex: out_dly = %d; invalid parameter\n",
alpar@1
   413
            parm->out_dly);
alpar@1
   414
      if (!(parm->presolve == GLP_ON || parm->presolve == GLP_OFF))
alpar@1
   415
         xerror("glp_simplex: presolve = %d; invalid parameter\n",
alpar@1
   416
            parm->presolve);
alpar@1
   417
      /* basic solution is currently undefined */
alpar@1
   418
      P->pbs_stat = P->dbs_stat = GLP_UNDEF;
alpar@1
   419
      P->obj_val = 0.0;
alpar@1
   420
      P->some = 0;
alpar@1
   421
      /* check bounds of double-bounded variables */
alpar@1
   422
      for (i = 1; i <= P->m; i++)
alpar@1
   423
      {  GLPROW *row = P->row[i];
alpar@1
   424
         if (row->type == GLP_DB && row->lb >= row->ub)
alpar@1
   425
         {  if (parm->msg_lev >= GLP_MSG_ERR)
alpar@1
   426
               xprintf("glp_simplex: row %d: lb = %g, ub = %g; incorrec"
alpar@1
   427
                  "t bounds\n", i, row->lb, row->ub);
alpar@1
   428
            ret = GLP_EBOUND;
alpar@1
   429
            goto done;
alpar@1
   430
         }
alpar@1
   431
      }
alpar@1
   432
      for (j = 1; j <= P->n; j++)
alpar@1
   433
      {  GLPCOL *col = P->col[j];
alpar@1
   434
         if (col->type == GLP_DB && col->lb >= col->ub)
alpar@1
   435
         {  if (parm->msg_lev >= GLP_MSG_ERR)
alpar@1
   436
               xprintf("glp_simplex: column %d: lb = %g, ub = %g; incor"
alpar@1
   437
                  "rect bounds\n", j, col->lb, col->ub);
alpar@1
   438
            ret = GLP_EBOUND;
alpar@1
   439
            goto done;
alpar@1
   440
         }
alpar@1
   441
      }
alpar@1
   442
      /* solve LP problem */
alpar@1
   443
      if (parm->msg_lev >= GLP_MSG_ALL)
alpar@1
   444
      {  xprintf("GLPK Simplex Optimizer, v%s\n", glp_version());
alpar@1
   445
         xprintf("%d row%s, %d column%s, %d non-zero%s\n",
alpar@1
   446
            P->m, P->m == 1 ? "" : "s", P->n, P->n == 1 ? "" : "s",
alpar@1
   447
            P->nnz, P->nnz == 1 ? "" : "s");
alpar@1
   448
      }
alpar@1
   449
      if (P->nnz == 0)
alpar@1
   450
         trivial_lp(P, parm), ret = 0;
alpar@1
   451
      else if (!parm->presolve)
alpar@1
   452
         ret = solve_lp(P, parm);
alpar@1
   453
      else
alpar@1
   454
         ret = preprocess_and_solve_lp(P, parm);
alpar@1
   455
done: /* return to the application program */
alpar@1
   456
      return ret;
alpar@1
   457
}
alpar@1
   458
alpar@1
   459
/***********************************************************************
alpar@1
   460
*  NAME
alpar@1
   461
*
alpar@1
   462
*  glp_init_smcp - initialize simplex method control parameters
alpar@1
   463
*
alpar@1
   464
*  SYNOPSIS
alpar@1
   465
*
alpar@1
   466
*  void glp_init_smcp(glp_smcp *parm);
alpar@1
   467
*
alpar@1
   468
*  DESCRIPTION
alpar@1
   469
*
alpar@1
   470
*  The routine glp_init_smcp initializes control parameters, which are
alpar@1
   471
*  used by the simplex solver, with default values.
alpar@1
   472
*
alpar@1
   473
*  Default values of the control parameters are stored in a glp_smcp
alpar@1
   474
*  structure, which the parameter parm points to. */
alpar@1
   475
alpar@1
   476
void glp_init_smcp(glp_smcp *parm)
alpar@1
   477
{     parm->msg_lev = GLP_MSG_ALL;
alpar@1
   478
      parm->meth = GLP_PRIMAL;
alpar@1
   479
      parm->pricing = GLP_PT_PSE;
alpar@1
   480
      parm->r_test = GLP_RT_HAR;
alpar@1
   481
      parm->tol_bnd = 1e-7;
alpar@1
   482
      parm->tol_dj = 1e-7;
alpar@1
   483
      parm->tol_piv = 1e-10;
alpar@1
   484
      parm->obj_ll = -DBL_MAX;
alpar@1
   485
      parm->obj_ul = +DBL_MAX;
alpar@1
   486
      parm->it_lim = INT_MAX;
alpar@1
   487
      parm->tm_lim = INT_MAX;
alpar@1
   488
      parm->out_frq = 500;
alpar@1
   489
      parm->out_dly = 0;
alpar@1
   490
      parm->presolve = GLP_OFF;
alpar@1
   491
      return;
alpar@1
   492
}
alpar@1
   493
alpar@1
   494
/***********************************************************************
alpar@1
   495
*  NAME
alpar@1
   496
*
alpar@1
   497
*  glp_get_status - retrieve generic status of basic solution
alpar@1
   498
*
alpar@1
   499
*  SYNOPSIS
alpar@1
   500
*
alpar@1
   501
*  int glp_get_status(glp_prob *lp);
alpar@1
   502
*
alpar@1
   503
*  RETURNS
alpar@1
   504
*
alpar@1
   505
*  The routine glp_get_status reports the generic status of the basic
alpar@1
   506
*  solution for the specified problem object as follows:
alpar@1
   507
*
alpar@1
   508
*  GLP_OPT    - solution is optimal;
alpar@1
   509
*  GLP_FEAS   - solution is feasible;
alpar@1
   510
*  GLP_INFEAS - solution is infeasible;
alpar@1
   511
*  GLP_NOFEAS - problem has no feasible solution;
alpar@1
   512
*  GLP_UNBND  - problem has unbounded solution;
alpar@1
   513
*  GLP_UNDEF  - solution is undefined. */
alpar@1
   514
alpar@1
   515
int glp_get_status(glp_prob *lp)
alpar@1
   516
{     int status;
alpar@1
   517
      status = glp_get_prim_stat(lp);
alpar@1
   518
      switch (status)
alpar@1
   519
      {  case GLP_FEAS:
alpar@1
   520
            switch (glp_get_dual_stat(lp))
alpar@1
   521
            {  case GLP_FEAS:
alpar@1
   522
                  status = GLP_OPT;
alpar@1
   523
                  break;
alpar@1
   524
               case GLP_NOFEAS:
alpar@1
   525
                  status = GLP_UNBND;
alpar@1
   526
                  break;
alpar@1
   527
               case GLP_UNDEF:
alpar@1
   528
               case GLP_INFEAS:
alpar@1
   529
                  status = status;
alpar@1
   530
                  break;
alpar@1
   531
               default:
alpar@1
   532
                  xassert(lp != lp);
alpar@1
   533
            }
alpar@1
   534
            break;
alpar@1
   535
         case GLP_UNDEF:
alpar@1
   536
         case GLP_INFEAS:
alpar@1
   537
         case GLP_NOFEAS:
alpar@1
   538
            status = status;
alpar@1
   539
            break;
alpar@1
   540
         default:
alpar@1
   541
            xassert(lp != lp);
alpar@1
   542
      }
alpar@1
   543
      return status;
alpar@1
   544
}
alpar@1
   545
alpar@1
   546
/***********************************************************************
alpar@1
   547
*  NAME
alpar@1
   548
*
alpar@1
   549
*  glp_get_prim_stat - retrieve status of primal basic solution
alpar@1
   550
*
alpar@1
   551
*  SYNOPSIS
alpar@1
   552
*
alpar@1
   553
*  int glp_get_prim_stat(glp_prob *lp);
alpar@1
   554
*
alpar@1
   555
*  RETURNS
alpar@1
   556
*
alpar@1
   557
*  The routine glp_get_prim_stat reports the status of the primal basic
alpar@1
   558
*  solution for the specified problem object as follows:
alpar@1
   559
*
alpar@1
   560
*  GLP_UNDEF  - primal solution is undefined;
alpar@1
   561
*  GLP_FEAS   - primal solution is feasible;
alpar@1
   562
*  GLP_INFEAS - primal solution is infeasible;
alpar@1
   563
*  GLP_NOFEAS - no primal feasible solution exists. */
alpar@1
   564
alpar@1
   565
int glp_get_prim_stat(glp_prob *lp)
alpar@1
   566
{     int pbs_stat = lp->pbs_stat;
alpar@1
   567
      return pbs_stat;
alpar@1
   568
}
alpar@1
   569
alpar@1
   570
/***********************************************************************
alpar@1
   571
*  NAME
alpar@1
   572
*
alpar@1
   573
*  glp_get_dual_stat - retrieve status of dual basic solution
alpar@1
   574
*
alpar@1
   575
*  SYNOPSIS
alpar@1
   576
*
alpar@1
   577
*  int glp_get_dual_stat(glp_prob *lp);
alpar@1
   578
*
alpar@1
   579
*  RETURNS
alpar@1
   580
*
alpar@1
   581
*  The routine glp_get_dual_stat reports the status of the dual basic
alpar@1
   582
*  solution for the specified problem object as follows:
alpar@1
   583
*
alpar@1
   584
*  GLP_UNDEF  - dual solution is undefined;
alpar@1
   585
*  GLP_FEAS   - dual solution is feasible;
alpar@1
   586
*  GLP_INFEAS - dual solution is infeasible;
alpar@1
   587
*  GLP_NOFEAS - no dual feasible solution exists. */
alpar@1
   588
alpar@1
   589
int glp_get_dual_stat(glp_prob *lp)
alpar@1
   590
{     int dbs_stat = lp->dbs_stat;
alpar@1
   591
      return dbs_stat;
alpar@1
   592
}
alpar@1
   593
alpar@1
   594
/***********************************************************************
alpar@1
   595
*  NAME
alpar@1
   596
*
alpar@1
   597
*  glp_get_obj_val - retrieve objective value (basic solution)
alpar@1
   598
*
alpar@1
   599
*  SYNOPSIS
alpar@1
   600
*
alpar@1
   601
*  double glp_get_obj_val(glp_prob *lp);
alpar@1
   602
*
alpar@1
   603
*  RETURNS
alpar@1
   604
*
alpar@1
   605
*  The routine glp_get_obj_val returns value of the objective function
alpar@1
   606
*  for basic solution. */
alpar@1
   607
alpar@1
   608
double glp_get_obj_val(glp_prob *lp)
alpar@1
   609
{     /*struct LPXCPS *cps = lp->cps;*/
alpar@1
   610
      double z;
alpar@1
   611
      z = lp->obj_val;
alpar@1
   612
      /*if (cps->round && fabs(z) < 1e-9) z = 0.0;*/
alpar@1
   613
      return z;
alpar@1
   614
}
alpar@1
   615
alpar@1
   616
/***********************************************************************
alpar@1
   617
*  NAME
alpar@1
   618
*
alpar@1
   619
*  glp_get_row_stat - retrieve row status
alpar@1
   620
*
alpar@1
   621
*  SYNOPSIS
alpar@1
   622
*
alpar@1
   623
*  int glp_get_row_stat(glp_prob *lp, int i);
alpar@1
   624
*
alpar@1
   625
*  RETURNS
alpar@1
   626
*
alpar@1
   627
*  The routine glp_get_row_stat returns current status assigned to the
alpar@1
   628
*  auxiliary variable associated with i-th row as follows:
alpar@1
   629
*
alpar@1
   630
*  GLP_BS - basic variable;
alpar@1
   631
*  GLP_NL - non-basic variable on its lower bound;
alpar@1
   632
*  GLP_NU - non-basic variable on its upper bound;
alpar@1
   633
*  GLP_NF - non-basic free (unbounded) variable;
alpar@1
   634
*  GLP_NS - non-basic fixed variable. */
alpar@1
   635
alpar@1
   636
int glp_get_row_stat(glp_prob *lp, int i)
alpar@1
   637
{     if (!(1 <= i && i <= lp->m))
alpar@1
   638
         xerror("glp_get_row_stat: i = %d; row number out of range\n",
alpar@1
   639
            i);
alpar@1
   640
      return lp->row[i]->stat;
alpar@1
   641
}
alpar@1
   642
alpar@1
   643
/***********************************************************************
alpar@1
   644
*  NAME
alpar@1
   645
*
alpar@1
   646
*  glp_get_row_prim - retrieve row primal value (basic solution)
alpar@1
   647
*
alpar@1
   648
*  SYNOPSIS
alpar@1
   649
*
alpar@1
   650
*  double glp_get_row_prim(glp_prob *lp, int i);
alpar@1
   651
*
alpar@1
   652
*  RETURNS
alpar@1
   653
*
alpar@1
   654
*  The routine glp_get_row_prim returns primal value of the auxiliary
alpar@1
   655
*  variable associated with i-th row. */
alpar@1
   656
alpar@1
   657
double glp_get_row_prim(glp_prob *lp, int i)
alpar@1
   658
{     /*struct LPXCPS *cps = lp->cps;*/
alpar@1
   659
      double prim;
alpar@1
   660
      if (!(1 <= i && i <= lp->m))
alpar@1
   661
         xerror("glp_get_row_prim: i = %d; row number out of range\n",
alpar@1
   662
            i);
alpar@1
   663
      prim = lp->row[i]->prim;
alpar@1
   664
      /*if (cps->round && fabs(prim) < 1e-9) prim = 0.0;*/
alpar@1
   665
      return prim;
alpar@1
   666
}
alpar@1
   667
alpar@1
   668
/***********************************************************************
alpar@1
   669
*  NAME
alpar@1
   670
*
alpar@1
   671
*  glp_get_row_dual - retrieve row dual value (basic solution)
alpar@1
   672
*
alpar@1
   673
*  SYNOPSIS
alpar@1
   674
*
alpar@1
   675
*  double glp_get_row_dual(glp_prob *lp, int i);
alpar@1
   676
*
alpar@1
   677
*  RETURNS
alpar@1
   678
*
alpar@1
   679
*  The routine glp_get_row_dual returns dual value (i.e. reduced cost)
alpar@1
   680
*  of the auxiliary variable associated with i-th row. */
alpar@1
   681
alpar@1
   682
double glp_get_row_dual(glp_prob *lp, int i)
alpar@1
   683
{     /*struct LPXCPS *cps = lp->cps;*/
alpar@1
   684
      double dual;
alpar@1
   685
      if (!(1 <= i && i <= lp->m))
alpar@1
   686
         xerror("glp_get_row_dual: i = %d; row number out of range\n",
alpar@1
   687
            i);
alpar@1
   688
      dual = lp->row[i]->dual;
alpar@1
   689
      /*if (cps->round && fabs(dual) < 1e-9) dual = 0.0;*/
alpar@1
   690
      return dual;
alpar@1
   691
}
alpar@1
   692
alpar@1
   693
/***********************************************************************
alpar@1
   694
*  NAME
alpar@1
   695
*
alpar@1
   696
*  glp_get_col_stat - retrieve column status
alpar@1
   697
*
alpar@1
   698
*  SYNOPSIS
alpar@1
   699
*
alpar@1
   700
*  int glp_get_col_stat(glp_prob *lp, int j);
alpar@1
   701
*
alpar@1
   702
*  RETURNS
alpar@1
   703
*
alpar@1
   704
*  The routine glp_get_col_stat returns current status assigned to the
alpar@1
   705
*  structural variable associated with j-th column as follows:
alpar@1
   706
*
alpar@1
   707
*  GLP_BS - basic variable;
alpar@1
   708
*  GLP_NL - non-basic variable on its lower bound;
alpar@1
   709
*  GLP_NU - non-basic variable on its upper bound;
alpar@1
   710
*  GLP_NF - non-basic free (unbounded) variable;
alpar@1
   711
*  GLP_NS - non-basic fixed variable. */
alpar@1
   712
alpar@1
   713
int glp_get_col_stat(glp_prob *lp, int j)
alpar@1
   714
{     if (!(1 <= j && j <= lp->n))
alpar@1
   715
         xerror("glp_get_col_stat: j = %d; column number out of range\n"
alpar@1
   716
            , j);
alpar@1
   717
      return lp->col[j]->stat;
alpar@1
   718
}
alpar@1
   719
alpar@1
   720
/***********************************************************************
alpar@1
   721
*  NAME
alpar@1
   722
*
alpar@1
   723
*  glp_get_col_prim - retrieve column primal value (basic solution)
alpar@1
   724
*
alpar@1
   725
*  SYNOPSIS
alpar@1
   726
*
alpar@1
   727
*  double glp_get_col_prim(glp_prob *lp, int j);
alpar@1
   728
*
alpar@1
   729
*  RETURNS
alpar@1
   730
*
alpar@1
   731
*  The routine glp_get_col_prim returns primal value of the structural
alpar@1
   732
*  variable associated with j-th column. */
alpar@1
   733
alpar@1
   734
double glp_get_col_prim(glp_prob *lp, int j)
alpar@1
   735
{     /*struct LPXCPS *cps = lp->cps;*/
alpar@1
   736
      double prim;
alpar@1
   737
      if (!(1 <= j && j <= lp->n))
alpar@1
   738
         xerror("glp_get_col_prim: j = %d; column number out of range\n"
alpar@1
   739
            , j);
alpar@1
   740
      prim = lp->col[j]->prim;
alpar@1
   741
      /*if (cps->round && fabs(prim) < 1e-9) prim = 0.0;*/
alpar@1
   742
      return prim;
alpar@1
   743
}
alpar@1
   744
alpar@1
   745
/***********************************************************************
alpar@1
   746
*  NAME
alpar@1
   747
*
alpar@1
   748
*  glp_get_col_dual - retrieve column dual value (basic solution)
alpar@1
   749
*
alpar@1
   750
*  SYNOPSIS
alpar@1
   751
*
alpar@1
   752
*  double glp_get_col_dual(glp_prob *lp, int j);
alpar@1
   753
*
alpar@1
   754
*  RETURNS
alpar@1
   755
*
alpar@1
   756
*  The routine glp_get_col_dual returns dual value (i.e. reduced cost)
alpar@1
   757
*  of the structural variable associated with j-th column. */
alpar@1
   758
alpar@1
   759
double glp_get_col_dual(glp_prob *lp, int j)
alpar@1
   760
{     /*struct LPXCPS *cps = lp->cps;*/
alpar@1
   761
      double dual;
alpar@1
   762
      if (!(1 <= j && j <= lp->n))
alpar@1
   763
         xerror("glp_get_col_dual: j = %d; column number out of range\n"
alpar@1
   764
            , j);
alpar@1
   765
      dual = lp->col[j]->dual;
alpar@1
   766
      /*if (cps->round && fabs(dual) < 1e-9) dual = 0.0;*/
alpar@1
   767
      return dual;
alpar@1
   768
}
alpar@1
   769
alpar@1
   770
/***********************************************************************
alpar@1
   771
*  NAME
alpar@1
   772
*
alpar@1
   773
*  glp_get_unbnd_ray - determine variable causing unboundedness
alpar@1
   774
*
alpar@1
   775
*  SYNOPSIS
alpar@1
   776
*
alpar@1
   777
*  int glp_get_unbnd_ray(glp_prob *lp);
alpar@1
   778
*
alpar@1
   779
*  RETURNS
alpar@1
   780
*
alpar@1
   781
*  The routine glp_get_unbnd_ray returns the number k of a variable,
alpar@1
   782
*  which causes primal or dual unboundedness. If 1 <= k <= m, it is
alpar@1
   783
*  k-th auxiliary variable, and if m+1 <= k <= m+n, it is (k-m)-th
alpar@1
   784
*  structural variable, where m is the number of rows, n is the number
alpar@1
   785
*  of columns in the problem object. If such variable is not defined,
alpar@1
   786
*  the routine returns 0.
alpar@1
   787
*
alpar@1
   788
*  COMMENTS
alpar@1
   789
*
alpar@1
   790
*  If it is not exactly known which version of the simplex solver
alpar@1
   791
*  detected unboundedness, i.e. whether the unboundedness is primal or
alpar@1
   792
*  dual, it is sufficient to check the status of the variable reported
alpar@1
   793
*  with the routine glp_get_row_stat or glp_get_col_stat. If the
alpar@1
   794
*  variable is non-basic, the unboundedness is primal, otherwise, if
alpar@1
   795
*  the variable is basic, the unboundedness is dual (the latter case
alpar@1
   796
*  means that the problem has no primal feasible dolution). */
alpar@1
   797
alpar@1
   798
int glp_get_unbnd_ray(glp_prob *lp)
alpar@1
   799
{     int k;
alpar@1
   800
      k = lp->some;
alpar@1
   801
      xassert(k >= 0);
alpar@1
   802
      if (k > lp->m + lp->n) k = 0;
alpar@1
   803
      return k;
alpar@1
   804
}
alpar@1
   805
alpar@1
   806
/* eof */