src/glpssx02.c
author Alpar Juttner <alpar@cs.elte.hu>
Mon, 06 Dec 2010 13:09:21 +0100
changeset 1 c445c931472f
permissions -rw-r--r--
Import glpk-4.45

- Generated files and doc/notes are removed
     1 /* glpssx02.c */
     2 
     3 /***********************************************************************
     4 *  This code is part of GLPK (GNU Linear Programming Kit).
     5 *
     6 *  Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
     7 *  2009, 2010 Andrew Makhorin, Department for Applied Informatics,
     8 *  Moscow Aviation Institute, Moscow, Russia. All rights reserved.
     9 *  E-mail: <mao@gnu.org>.
    10 *
    11 *  GLPK is free software: you can redistribute it and/or modify it
    12 *  under the terms of the GNU General Public License as published by
    13 *  the Free Software Foundation, either version 3 of the License, or
    14 *  (at your option) any later version.
    15 *
    16 *  GLPK is distributed in the hope that it will be useful, but WITHOUT
    17 *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    18 *  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
    19 *  License for more details.
    20 *
    21 *  You should have received a copy of the GNU General Public License
    22 *  along with GLPK. If not, see <http://www.gnu.org/licenses/>.
    23 ***********************************************************************/
    24 
    25 #include "glpenv.h"
    26 #include "glpssx.h"
    27 
    28 static void show_progress(SSX *ssx, int phase)
    29 {     /* this auxiliary routine displays information about progress of
    30          the search */
    31       int i, def = 0;
    32       for (i = 1; i <= ssx->m; i++)
    33          if (ssx->type[ssx->Q_col[i]] == SSX_FX) def++;
    34       xprintf("%s%6d:   %s = %22.15g   (%d)\n", phase == 1 ? " " : "*",
    35          ssx->it_cnt, phase == 1 ? "infsum" : "objval",
    36          mpq_get_d(ssx->bbar[0]), def);
    37 #if 0
    38       ssx->tm_lag = utime();
    39 #else
    40       ssx->tm_lag = xtime();
    41 #endif
    42       return;
    43 }
    44 
    45 /*----------------------------------------------------------------------
    46 // ssx_phase_I - find primal feasible solution.
    47 //
    48 // This routine implements phase I of the primal simplex method.
    49 //
    50 // On exit the routine returns one of the following codes:
    51 //
    52 // 0 - feasible solution found;
    53 // 1 - problem has no feasible solution;
    54 // 2 - iterations limit exceeded;
    55 // 3 - time limit exceeded.
    56 ----------------------------------------------------------------------*/
    57 
    58 int ssx_phase_I(SSX *ssx)
    59 {     int m = ssx->m;
    60       int n = ssx->n;
    61       int *type = ssx->type;
    62       mpq_t *lb = ssx->lb;
    63       mpq_t *ub = ssx->ub;
    64       mpq_t *coef = ssx->coef;
    65       int *A_ptr = ssx->A_ptr;
    66       int *A_ind = ssx->A_ind;
    67       mpq_t *A_val = ssx->A_val;
    68       int *Q_col = ssx->Q_col;
    69       mpq_t *bbar = ssx->bbar;
    70       mpq_t *pi = ssx->pi;
    71       mpq_t *cbar = ssx->cbar;
    72       int *orig_type, orig_dir;
    73       mpq_t *orig_lb, *orig_ub, *orig_coef;
    74       int i, k, ret;
    75       /* save components of the original LP problem, which are changed
    76          by the routine */
    77       orig_type = xcalloc(1+m+n, sizeof(int));
    78       orig_lb = xcalloc(1+m+n, sizeof(mpq_t));
    79       orig_ub = xcalloc(1+m+n, sizeof(mpq_t));
    80       orig_coef = xcalloc(1+m+n, sizeof(mpq_t));
    81       for (k = 1; k <= m+n; k++)
    82       {  orig_type[k] = type[k];
    83          mpq_init(orig_lb[k]);
    84          mpq_set(orig_lb[k], lb[k]);
    85          mpq_init(orig_ub[k]);
    86          mpq_set(orig_ub[k], ub[k]);
    87       }
    88       orig_dir = ssx->dir;
    89       for (k = 0; k <= m+n; k++)
    90       {  mpq_init(orig_coef[k]);
    91          mpq_set(orig_coef[k], coef[k]);
    92       }
    93       /* build an artificial basic solution, which is primal feasible,
    94          and also build an auxiliary objective function to minimize the
    95          sum of infeasibilities for the original problem */
    96       ssx->dir = SSX_MIN;
    97       for (k = 0; k <= m+n; k++) mpq_set_si(coef[k], 0, 1);
    98       mpq_set_si(bbar[0], 0, 1);
    99       for (i = 1; i <= m; i++)
   100       {  int t;
   101          k = Q_col[i]; /* x[k] = xB[i] */
   102          t = type[k];
   103          if (t == SSX_LO || t == SSX_DB || t == SSX_FX)
   104          {  /* in the original problem x[k] has lower bound */
   105             if (mpq_cmp(bbar[i], lb[k]) < 0)
   106             {  /* which is violated */
   107                type[k] = SSX_UP;
   108                mpq_set(ub[k], lb[k]);
   109                mpq_set_si(lb[k], 0, 1);
   110                mpq_set_si(coef[k], -1, 1);
   111                mpq_add(bbar[0], bbar[0], ub[k]);
   112                mpq_sub(bbar[0], bbar[0], bbar[i]);
   113             }
   114          }
   115          if (t == SSX_UP || t == SSX_DB || t == SSX_FX)
   116          {  /* in the original problem x[k] has upper bound */
   117             if (mpq_cmp(bbar[i], ub[k]) > 0)
   118             {  /* which is violated */
   119                type[k] = SSX_LO;
   120                mpq_set(lb[k], ub[k]);
   121                mpq_set_si(ub[k], 0, 1);
   122                mpq_set_si(coef[k], +1, 1);
   123                mpq_add(bbar[0], bbar[0], bbar[i]);
   124                mpq_sub(bbar[0], bbar[0], lb[k]);
   125             }
   126          }
   127       }
   128       /* now the initial basic solution should be primal feasible due
   129          to changes of bounds of some basic variables, which turned to
   130          implicit artifical variables */
   131       /* compute simplex multipliers and reduced costs */
   132       ssx_eval_pi(ssx);
   133       ssx_eval_cbar(ssx);
   134       /* display initial progress of the search */
   135       show_progress(ssx, 1);
   136       /* main loop starts here */
   137       for (;;)
   138       {  /* display current progress of the search */
   139 #if 0
   140          if (utime() - ssx->tm_lag >= ssx->out_frq - 0.001)
   141 #else
   142          if (xdifftime(xtime(), ssx->tm_lag) >= ssx->out_frq - 0.001)
   143 #endif
   144             show_progress(ssx, 1);
   145          /* we do not need to wait until all artificial variables have
   146             left the basis */
   147          if (mpq_sgn(bbar[0]) == 0)
   148          {  /* the sum of infeasibilities is zero, therefore the current
   149                solution is primal feasible for the original problem */
   150             ret = 0;
   151             break;
   152          }
   153          /* check if the iterations limit has been exhausted */
   154          if (ssx->it_lim == 0)
   155          {  ret = 2;
   156             break;
   157          }
   158          /* check if the time limit has been exhausted */
   159 #if 0
   160          if (ssx->tm_lim >= 0.0 && ssx->tm_lim <= utime() - ssx->tm_beg)
   161 #else
   162          if (ssx->tm_lim >= 0.0 &&
   163              ssx->tm_lim <= xdifftime(xtime(), ssx->tm_beg))
   164 #endif
   165          {  ret = 3;
   166             break;
   167          }
   168          /* choose non-basic variable xN[q] */
   169          ssx_chuzc(ssx);
   170          /* if xN[q] cannot be chosen, the sum of infeasibilities is
   171             minimal but non-zero; therefore the original problem has no
   172             primal feasible solution */
   173          if (ssx->q == 0)
   174          {  ret = 1;
   175             break;
   176          }
   177          /* compute q-th column of the simplex table */
   178          ssx_eval_col(ssx);
   179          /* choose basic variable xB[p] */
   180          ssx_chuzr(ssx);
   181          /* the sum of infeasibilities cannot be negative, therefore
   182             the auxiliary lp problem cannot have unbounded solution */
   183          xassert(ssx->p != 0);
   184          /* update values of basic variables */
   185          ssx_update_bbar(ssx);
   186          if (ssx->p > 0)
   187          {  /* compute p-th row of the inverse inv(B) */
   188             ssx_eval_rho(ssx);
   189             /* compute p-th row of the simplex table */
   190             ssx_eval_row(ssx);
   191             xassert(mpq_cmp(ssx->aq[ssx->p], ssx->ap[ssx->q]) == 0);
   192             /* update simplex multipliers */
   193             ssx_update_pi(ssx);
   194             /* update reduced costs of non-basic variables */
   195             ssx_update_cbar(ssx);
   196          }
   197          /* xB[p] is leaving the basis; if it is implicit artificial
   198             variable, the corresponding residual vanishes; therefore
   199             bounds of this variable should be restored to the original
   200             values */
   201          if (ssx->p > 0)
   202          {  k = Q_col[ssx->p]; /* x[k] = xB[p] */
   203             if (type[k] != orig_type[k])
   204             {  /* x[k] is implicit artificial variable */
   205                type[k] = orig_type[k];
   206                mpq_set(lb[k], orig_lb[k]);
   207                mpq_set(ub[k], orig_ub[k]);
   208                xassert(ssx->p_stat == SSX_NL || ssx->p_stat == SSX_NU);
   209                ssx->p_stat = (ssx->p_stat == SSX_NL ? SSX_NU : SSX_NL);
   210                if (type[k] == SSX_FX) ssx->p_stat = SSX_NS;
   211                /* nullify the objective coefficient at x[k] */
   212                mpq_set_si(coef[k], 0, 1);
   213                /* since coef[k] has been changed, we need to compute
   214                   new reduced cost of x[k], which it will have in the
   215                   adjacent basis */
   216                /* the formula d[j] = cN[j] - pi' * N[j] is used (note
   217                   that the vector pi is not changed, because it depends
   218                   on objective coefficients at basic variables, but in
   219                   the adjacent basis, for which the vector pi has been
   220                   just recomputed, x[k] is non-basic) */
   221                if (k <= m)
   222                {  /* x[k] is auxiliary variable */
   223                   mpq_neg(cbar[ssx->q], pi[k]);
   224                }
   225                else
   226                {  /* x[k] is structural variable */
   227                   int ptr;
   228                   mpq_t temp;
   229                   mpq_init(temp);
   230                   mpq_set_si(cbar[ssx->q], 0, 1);
   231                   for (ptr = A_ptr[k-m]; ptr < A_ptr[k-m+1]; ptr++)
   232                   {  mpq_mul(temp, pi[A_ind[ptr]], A_val[ptr]);
   233                      mpq_add(cbar[ssx->q], cbar[ssx->q], temp);
   234                   }
   235                   mpq_clear(temp);
   236                }
   237             }
   238          }
   239          /* jump to the adjacent vertex of the polyhedron */
   240          ssx_change_basis(ssx);
   241          /* one simplex iteration has been performed */
   242          if (ssx->it_lim > 0) ssx->it_lim--;
   243          ssx->it_cnt++;
   244       }
   245       /* display final progress of the search */
   246       show_progress(ssx, 1);
   247       /* restore components of the original problem, which were changed
   248          by the routine */
   249       for (k = 1; k <= m+n; k++)
   250       {  type[k] = orig_type[k];
   251          mpq_set(lb[k], orig_lb[k]);
   252          mpq_clear(orig_lb[k]);
   253          mpq_set(ub[k], orig_ub[k]);
   254          mpq_clear(orig_ub[k]);
   255       }
   256       ssx->dir = orig_dir;
   257       for (k = 0; k <= m+n; k++)
   258       {  mpq_set(coef[k], orig_coef[k]);
   259          mpq_clear(orig_coef[k]);
   260       }
   261       xfree(orig_type);
   262       xfree(orig_lb);
   263       xfree(orig_ub);
   264       xfree(orig_coef);
   265       /* return to the calling program */
   266       return ret;
   267 }
   268 
   269 /*----------------------------------------------------------------------
   270 // ssx_phase_II - find optimal solution.
   271 //
   272 // This routine implements phase II of the primal simplex method.
   273 //
   274 // On exit the routine returns one of the following codes:
   275 //
   276 // 0 - optimal solution found;
   277 // 1 - problem has unbounded solution;
   278 // 2 - iterations limit exceeded;
   279 // 3 - time limit exceeded.
   280 ----------------------------------------------------------------------*/
   281 
   282 int ssx_phase_II(SSX *ssx)
   283 {     int ret;
   284       /* display initial progress of the search */
   285       show_progress(ssx, 2);
   286       /* main loop starts here */
   287       for (;;)
   288       {  /* display current progress of the search */
   289 #if 0
   290          if (utime() - ssx->tm_lag >= ssx->out_frq - 0.001)
   291 #else
   292          if (xdifftime(xtime(), ssx->tm_lag) >= ssx->out_frq - 0.001)
   293 #endif
   294             show_progress(ssx, 2);
   295          /* check if the iterations limit has been exhausted */
   296          if (ssx->it_lim == 0)
   297          {  ret = 2;
   298             break;
   299          }
   300          /* check if the time limit has been exhausted */
   301 #if 0
   302          if (ssx->tm_lim >= 0.0 && ssx->tm_lim <= utime() - ssx->tm_beg)
   303 #else
   304          if (ssx->tm_lim >= 0.0 &&
   305              ssx->tm_lim <= xdifftime(xtime(), ssx->tm_beg))
   306 #endif
   307          {  ret = 3;
   308             break;
   309          }
   310          /* choose non-basic variable xN[q] */
   311          ssx_chuzc(ssx);
   312          /* if xN[q] cannot be chosen, the current basic solution is
   313             dual feasible and therefore optimal */
   314          if (ssx->q == 0)
   315          {  ret = 0;
   316             break;
   317          }
   318          /* compute q-th column of the simplex table */
   319          ssx_eval_col(ssx);
   320          /* choose basic variable xB[p] */
   321          ssx_chuzr(ssx);
   322          /* if xB[p] cannot be chosen, the problem has no dual feasible
   323             solution (i.e. unbounded) */
   324          if (ssx->p == 0)
   325          {  ret = 1;
   326             break;
   327          }
   328          /* update values of basic variables */
   329          ssx_update_bbar(ssx);
   330          if (ssx->p > 0)
   331          {  /* compute p-th row of the inverse inv(B) */
   332             ssx_eval_rho(ssx);
   333             /* compute p-th row of the simplex table */
   334             ssx_eval_row(ssx);
   335             xassert(mpq_cmp(ssx->aq[ssx->p], ssx->ap[ssx->q]) == 0);
   336 #if 0
   337             /* update simplex multipliers */
   338             ssx_update_pi(ssx);
   339 #endif
   340             /* update reduced costs of non-basic variables */
   341             ssx_update_cbar(ssx);
   342          }
   343          /* jump to the adjacent vertex of the polyhedron */
   344          ssx_change_basis(ssx);
   345          /* one simplex iteration has been performed */
   346          if (ssx->it_lim > 0) ssx->it_lim--;
   347          ssx->it_cnt++;
   348       }
   349       /* display final progress of the search */
   350       show_progress(ssx, 2);
   351       /* return to the calling program */
   352       return ret;
   353 }
   354 
   355 /*----------------------------------------------------------------------
   356 // ssx_driver - base driver to exact simplex method.
   357 //
   358 // This routine is a base driver to a version of the primal simplex
   359 // method using exact (bignum) arithmetic.
   360 //
   361 // On exit the routine returns one of the following codes:
   362 //
   363 // 0 - optimal solution found;
   364 // 1 - problem has no feasible solution;
   365 // 2 - problem has unbounded solution;
   366 // 3 - iterations limit exceeded (phase I);
   367 // 4 - iterations limit exceeded (phase II);
   368 // 5 - time limit exceeded (phase I);
   369 // 6 - time limit exceeded (phase II);
   370 // 7 - initial basis matrix is exactly singular.
   371 ----------------------------------------------------------------------*/
   372 
   373 int ssx_driver(SSX *ssx)
   374 {     int m = ssx->m;
   375       int *type = ssx->type;
   376       mpq_t *lb = ssx->lb;
   377       mpq_t *ub = ssx->ub;
   378       int *Q_col = ssx->Q_col;
   379       mpq_t *bbar = ssx->bbar;
   380       int i, k, ret;
   381       ssx->tm_beg = xtime();
   382       /* factorize the initial basis matrix */
   383       if (ssx_factorize(ssx))
   384       {  xprintf("Initial basis matrix is singular\n");
   385          ret = 7;
   386          goto done;
   387       }
   388       /* compute values of basic variables */
   389       ssx_eval_bbar(ssx);
   390       /* check if the initial basic solution is primal feasible */
   391       for (i = 1; i <= m; i++)
   392       {  int t;
   393          k = Q_col[i]; /* x[k] = xB[i] */
   394          t = type[k];
   395          if (t == SSX_LO || t == SSX_DB || t == SSX_FX)
   396          {  /* x[k] has lower bound */
   397             if (mpq_cmp(bbar[i], lb[k]) < 0)
   398             {  /* which is violated */
   399                break;
   400             }
   401          }
   402          if (t == SSX_UP || t == SSX_DB || t == SSX_FX)
   403          {  /* x[k] has upper bound */
   404             if (mpq_cmp(bbar[i], ub[k]) > 0)
   405             {  /* which is violated */
   406                break;
   407             }
   408          }
   409       }
   410       if (i > m)
   411       {  /* no basic variable violates its bounds */
   412          ret = 0;
   413          goto skip;
   414       }
   415       /* phase I: find primal feasible solution */
   416       ret = ssx_phase_I(ssx);
   417       switch (ret)
   418       {  case 0:
   419             ret = 0;
   420             break;
   421          case 1:
   422             xprintf("PROBLEM HAS NO FEASIBLE SOLUTION\n");
   423             ret = 1;
   424             break;
   425          case 2:
   426             xprintf("ITERATIONS LIMIT EXCEEDED; SEARCH TERMINATED\n");
   427             ret = 3;
   428             break;
   429          case 3:
   430             xprintf("TIME LIMIT EXCEEDED; SEARCH TERMINATED\n");
   431             ret = 5;
   432             break;
   433          default:
   434             xassert(ret != ret);
   435       }
   436       /* compute values of basic variables (actually only the objective
   437          value needs to be computed) */
   438       ssx_eval_bbar(ssx);
   439 skip: /* compute simplex multipliers */
   440       ssx_eval_pi(ssx);
   441       /* compute reduced costs of non-basic variables */
   442       ssx_eval_cbar(ssx);
   443       /* if phase I failed, do not start phase II */
   444       if (ret != 0) goto done;
   445       /* phase II: find optimal solution */
   446       ret = ssx_phase_II(ssx);
   447       switch (ret)
   448       {  case 0:
   449             xprintf("OPTIMAL SOLUTION FOUND\n");
   450             ret = 0;
   451             break;
   452          case 1:
   453             xprintf("PROBLEM HAS UNBOUNDED SOLUTION\n");
   454             ret = 2;
   455             break;
   456          case 2:
   457             xprintf("ITERATIONS LIMIT EXCEEDED; SEARCH TERMINATED\n");
   458             ret = 4;
   459             break;
   460          case 3:
   461             xprintf("TIME LIMIT EXCEEDED; SEARCH TERMINATED\n");
   462             ret = 6;
   463             break;
   464          default:
   465             xassert(ret != ret);
   466       }
   467 done: /* decrease the time limit by the spent amount of time */
   468       if (ssx->tm_lim >= 0.0)
   469 #if 0
   470       {  ssx->tm_lim -= utime() - ssx->tm_beg;
   471 #else
   472       {  ssx->tm_lim -= xdifftime(xtime(), ssx->tm_beg);
   473 #endif
   474          if (ssx->tm_lim < 0.0) ssx->tm_lim = 0.0;
   475       }
   476       return ret;
   477 }
   478 
   479 /* eof */