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