PageRenderTime 59ms CodeModel.GetById 6ms app.highlight 47ms RepoModel.GetById 1ms app.codeStats 1ms

/farmR/src/glpapi06.c

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