src/glpssx01.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
     1 /* glpssx01.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 #define xfault xerror
    28 
    29 /*----------------------------------------------------------------------
    30 // ssx_create - create simplex solver workspace.
    31 //
    32 // This routine creates the workspace used by simplex solver routines,
    33 // and returns a pointer to it.
    34 //
    35 // Parameters m, n, and nnz specify, respectively, the number of rows,
    36 // columns, and non-zero constraint coefficients.
    37 //
    38 // This routine only allocates the memory for the workspace components,
    39 // so the workspace needs to be saturated by data. */
    40 
    41 SSX *ssx_create(int m, int n, int nnz)
    42 {     SSX *ssx;
    43       int i, j, k;
    44       if (m < 1)
    45          xfault("ssx_create: m = %d; invalid number of rows\n", m);
    46       if (n < 1)
    47          xfault("ssx_create: n = %d; invalid number of columns\n", n);
    48       if (nnz < 0)
    49          xfault("ssx_create: nnz = %d; invalid number of non-zero const"
    50             "raint coefficients\n", nnz);
    51       ssx = xmalloc(sizeof(SSX));
    52       ssx->m = m;
    53       ssx->n = n;
    54       ssx->type = xcalloc(1+m+n, sizeof(int));
    55       ssx->lb = xcalloc(1+m+n, sizeof(mpq_t));
    56       for (k = 1; k <= m+n; k++) mpq_init(ssx->lb[k]);
    57       ssx->ub = xcalloc(1+m+n, sizeof(mpq_t));
    58       for (k = 1; k <= m+n; k++) mpq_init(ssx->ub[k]);
    59       ssx->coef = xcalloc(1+m+n, sizeof(mpq_t));
    60       for (k = 0; k <= m+n; k++) mpq_init(ssx->coef[k]);
    61       ssx->A_ptr = xcalloc(1+n+1, sizeof(int));
    62       ssx->A_ptr[n+1] = nnz+1;
    63       ssx->A_ind = xcalloc(1+nnz, sizeof(int));
    64       ssx->A_val = xcalloc(1+nnz, sizeof(mpq_t));
    65       for (k = 1; k <= nnz; k++) mpq_init(ssx->A_val[k]);
    66       ssx->stat = xcalloc(1+m+n, sizeof(int));
    67       ssx->Q_row = xcalloc(1+m+n, sizeof(int));
    68       ssx->Q_col = xcalloc(1+m+n, sizeof(int));
    69       ssx->binv = bfx_create_binv();
    70       ssx->bbar = xcalloc(1+m, sizeof(mpq_t));
    71       for (i = 0; i <= m; i++) mpq_init(ssx->bbar[i]);
    72       ssx->pi = xcalloc(1+m, sizeof(mpq_t));
    73       for (i = 1; i <= m; i++) mpq_init(ssx->pi[i]);
    74       ssx->cbar = xcalloc(1+n, sizeof(mpq_t));
    75       for (j = 1; j <= n; j++) mpq_init(ssx->cbar[j]);
    76       ssx->rho = xcalloc(1+m, sizeof(mpq_t));
    77       for (i = 1; i <= m; i++) mpq_init(ssx->rho[i]);
    78       ssx->ap = xcalloc(1+n, sizeof(mpq_t));
    79       for (j = 1; j <= n; j++) mpq_init(ssx->ap[j]);
    80       ssx->aq = xcalloc(1+m, sizeof(mpq_t));
    81       for (i = 1; i <= m; i++) mpq_init(ssx->aq[i]);
    82       mpq_init(ssx->delta);
    83       return ssx;
    84 }
    85 
    86 /*----------------------------------------------------------------------
    87 // ssx_factorize - factorize the current basis matrix.
    88 //
    89 // This routine computes factorization of the current basis matrix B
    90 // and returns the singularity flag. If the matrix B is non-singular,
    91 // the flag is zero, otherwise non-zero. */
    92 
    93 static int basis_col(void *info, int j, int ind[], mpq_t val[])
    94 {     /* this auxiliary routine provides row indices and numeric values
    95          of non-zero elements in j-th column of the matrix B */
    96       SSX *ssx = info;
    97       int m = ssx->m;
    98       int n = ssx->n;
    99       int *A_ptr = ssx->A_ptr;
   100       int *A_ind = ssx->A_ind;
   101       mpq_t *A_val = ssx->A_val;
   102       int *Q_col = ssx->Q_col;
   103       int k, len, ptr;
   104       xassert(1 <= j && j <= m);
   105       k = Q_col[j]; /* x[k] = xB[j] */
   106       xassert(1 <= k && k <= m+n);
   107       /* j-th column of the matrix B is k-th column of the augmented
   108          constraint matrix (I | -A) */
   109       if (k <= m)
   110       {  /* it is a column of the unity matrix I */
   111          len = 1, ind[1] = k, mpq_set_si(val[1], 1, 1);
   112       }
   113       else
   114       {  /* it is a column of the original constraint matrix -A */
   115          len = 0;
   116          for (ptr = A_ptr[k-m]; ptr < A_ptr[k-m+1]; ptr++)
   117          {  len++;
   118             ind[len] = A_ind[ptr];
   119             mpq_neg(val[len], A_val[ptr]);
   120          }
   121       }
   122       return len;
   123 }
   124 
   125 int ssx_factorize(SSX *ssx)
   126 {     int ret;
   127       ret = bfx_factorize(ssx->binv, ssx->m, basis_col, ssx);
   128       return ret;
   129 }
   130 
   131 /*----------------------------------------------------------------------
   132 // ssx_get_xNj - determine value of non-basic variable.
   133 //
   134 // This routine determines the value of non-basic variable xN[j] in the
   135 // current basic solution defined as follows:
   136 //
   137 //    0,             if xN[j] is free variable
   138 //    lN[j],         if xN[j] is on its lower bound
   139 //    uN[j],         if xN[j] is on its upper bound
   140 //    lN[j] = uN[j], if xN[j] is fixed variable
   141 //
   142 // where lN[j] and uN[j] are lower and upper bounds of xN[j]. */
   143 
   144 void ssx_get_xNj(SSX *ssx, int j, mpq_t x)
   145 {     int m = ssx->m;
   146       int n = ssx->n;
   147       mpq_t *lb = ssx->lb;
   148       mpq_t *ub = ssx->ub;
   149       int *stat = ssx->stat;
   150       int *Q_col = ssx->Q_col;
   151       int k;
   152       xassert(1 <= j && j <= n);
   153       k = Q_col[m+j]; /* x[k] = xN[j] */
   154       xassert(1 <= k && k <= m+n);
   155       switch (stat[k])
   156       {  case SSX_NL:
   157             /* xN[j] is on its lower bound */
   158             mpq_set(x, lb[k]); break;
   159          case SSX_NU:
   160             /* xN[j] is on its upper bound */
   161             mpq_set(x, ub[k]); break;
   162          case SSX_NF:
   163             /* xN[j] is free variable */
   164             mpq_set_si(x, 0, 1); break;
   165          case SSX_NS:
   166             /* xN[j] is fixed variable */
   167             mpq_set(x, lb[k]); break;
   168          default:
   169             xassert(stat != stat);
   170       }
   171       return;
   172 }
   173 
   174 /*----------------------------------------------------------------------
   175 // ssx_eval_bbar - compute values of basic variables.
   176 //
   177 // This routine computes values of basic variables xB in the current
   178 // basic solution as follows:
   179 //
   180 //    beta = - inv(B) * N * xN,
   181 //
   182 // where B is the basis matrix, N is the matrix of non-basic columns,
   183 // xN is a vector of current values of non-basic variables. */
   184 
   185 void ssx_eval_bbar(SSX *ssx)
   186 {     int m = ssx->m;
   187       int n = ssx->n;
   188       mpq_t *coef = ssx->coef;
   189       int *A_ptr = ssx->A_ptr;
   190       int *A_ind = ssx->A_ind;
   191       mpq_t *A_val = ssx->A_val;
   192       int *Q_col = ssx->Q_col;
   193       mpq_t *bbar = ssx->bbar;
   194       int i, j, k, ptr;
   195       mpq_t x, temp;
   196       mpq_init(x);
   197       mpq_init(temp);
   198       /* bbar := 0 */
   199       for (i = 1; i <= m; i++)
   200          mpq_set_si(bbar[i], 0, 1);
   201       /* bbar := - N * xN = - N[1] * xN[1] - ... - N[n] * xN[n] */
   202       for (j = 1; j <= n; j++)
   203       {  ssx_get_xNj(ssx, j, x);
   204          if (mpq_sgn(x) == 0) continue;
   205          k = Q_col[m+j]; /* x[k] = xN[j] */
   206          if (k <= m)
   207          {  /* N[j] is a column of the unity matrix I */
   208             mpq_sub(bbar[k], bbar[k], x);
   209          }
   210          else
   211          {  /* N[j] is a column of the original constraint matrix -A */
   212             for (ptr = A_ptr[k-m]; ptr < A_ptr[k-m+1]; ptr++)
   213             {  mpq_mul(temp, A_val[ptr], x);
   214                mpq_add(bbar[A_ind[ptr]], bbar[A_ind[ptr]], temp);
   215             }
   216          }
   217       }
   218       /* bbar := inv(B) * bbar */
   219       bfx_ftran(ssx->binv, bbar, 0);
   220 #if 1
   221       /* compute value of the objective function */
   222       /* bbar[0] := c[0] */
   223       mpq_set(bbar[0], coef[0]);
   224       /* bbar[0] := bbar[0] + sum{i in B} cB[i] * xB[i] */
   225       for (i = 1; i <= m; i++)
   226       {  k = Q_col[i]; /* x[k] = xB[i] */
   227          if (mpq_sgn(coef[k]) == 0) continue;
   228          mpq_mul(temp, coef[k], bbar[i]);
   229          mpq_add(bbar[0], bbar[0], temp);
   230       }
   231       /* bbar[0] := bbar[0] + sum{j in N} cN[j] * xN[j] */
   232       for (j = 1; j <= n; j++)
   233       {  k = Q_col[m+j]; /* x[k] = xN[j] */
   234          if (mpq_sgn(coef[k]) == 0) continue;
   235          ssx_get_xNj(ssx, j, x);
   236          mpq_mul(temp, coef[k], x);
   237          mpq_add(bbar[0], bbar[0], temp);
   238       }
   239 #endif
   240       mpq_clear(x);
   241       mpq_clear(temp);
   242       return;
   243 }
   244 
   245 /*----------------------------------------------------------------------
   246 // ssx_eval_pi - compute values of simplex multipliers.
   247 //
   248 // This routine computes values of simplex multipliers (shadow prices)
   249 // pi in the current basic solution as follows:
   250 //
   251 //    pi = inv(B') * cB,
   252 //
   253 // where B' is a matrix transposed to the basis matrix B, cB is a vector
   254 // of objective coefficients at basic variables xB. */
   255 
   256 void ssx_eval_pi(SSX *ssx)
   257 {     int m = ssx->m;
   258       mpq_t *coef = ssx->coef;
   259       int *Q_col = ssx->Q_col;
   260       mpq_t *pi = ssx->pi;
   261       int i;
   262       /* pi := cB */
   263       for (i = 1; i <= m; i++) mpq_set(pi[i], coef[Q_col[i]]);
   264       /* pi := inv(B') * cB */
   265       bfx_btran(ssx->binv, pi);
   266       return;
   267 }
   268 
   269 /*----------------------------------------------------------------------
   270 // ssx_eval_dj - compute reduced cost of non-basic variable.
   271 //
   272 // This routine computes reduced cost d[j] of non-basic variable xN[j]
   273 // in the current basic solution as follows:
   274 //
   275 //    d[j] = cN[j] - N[j] * pi,
   276 //
   277 // where cN[j] is an objective coefficient at xN[j], N[j] is a column
   278 // of the augmented constraint matrix (I | -A) corresponding to xN[j],
   279 // pi is the vector of simplex multipliers (shadow prices). */
   280 
   281 void ssx_eval_dj(SSX *ssx, int j, mpq_t dj)
   282 {     int m = ssx->m;
   283       int n = ssx->n;
   284       mpq_t *coef = ssx->coef;
   285       int *A_ptr = ssx->A_ptr;
   286       int *A_ind = ssx->A_ind;
   287       mpq_t *A_val = ssx->A_val;
   288       int *Q_col = ssx->Q_col;
   289       mpq_t *pi = ssx->pi;
   290       int k, ptr, end;
   291       mpq_t temp;
   292       mpq_init(temp);
   293       xassert(1 <= j && j <= n);
   294       k = Q_col[m+j]; /* x[k] = xN[j] */
   295       xassert(1 <= k && k <= m+n);
   296       /* j-th column of the matrix N is k-th column of the augmented
   297          constraint matrix (I | -A) */
   298       if (k <= m)
   299       {  /* it is a column of the unity matrix I */
   300          mpq_sub(dj, coef[k], pi[k]);
   301       }
   302       else
   303       {  /* it is a column of the original constraint matrix -A */
   304          mpq_set(dj, coef[k]);
   305          for (ptr = A_ptr[k-m], end = A_ptr[k-m+1]; ptr < end; ptr++)
   306          {  mpq_mul(temp, A_val[ptr], pi[A_ind[ptr]]);
   307             mpq_add(dj, dj, temp);
   308          }
   309       }
   310       mpq_clear(temp);
   311       return;
   312 }
   313 
   314 /*----------------------------------------------------------------------
   315 // ssx_eval_cbar - compute reduced costs of all non-basic variables.
   316 //
   317 // This routine computes the vector of reduced costs pi in the current
   318 // basic solution for all non-basic variables, including fixed ones. */
   319 
   320 void ssx_eval_cbar(SSX *ssx)
   321 {     int n = ssx->n;
   322       mpq_t *cbar = ssx->cbar;
   323       int j;
   324       for (j = 1; j <= n; j++)
   325          ssx_eval_dj(ssx, j, cbar[j]);
   326       return;
   327 }
   328 
   329 /*----------------------------------------------------------------------
   330 // ssx_eval_rho - compute p-th row of the inverse.
   331 //
   332 // This routine computes p-th row of the matrix inv(B), where B is the
   333 // current basis matrix.
   334 //
   335 // p-th row of the inverse is computed using the following formula:
   336 //
   337 //    rho = inv(B') * e[p],
   338 //
   339 // where B' is a matrix transposed to B, e[p] is a unity vector, which
   340 // contains one in p-th position. */
   341 
   342 void ssx_eval_rho(SSX *ssx)
   343 {     int m = ssx->m;
   344       int p = ssx->p;
   345       mpq_t *rho = ssx->rho;
   346       int i;
   347       xassert(1 <= p && p <= m);
   348       /* rho := 0 */
   349       for (i = 1; i <= m; i++) mpq_set_si(rho[i], 0, 1);
   350       /* rho := e[p] */
   351       mpq_set_si(rho[p], 1, 1);
   352       /* rho := inv(B') * rho */
   353       bfx_btran(ssx->binv, rho);
   354       return;
   355 }
   356 
   357 /*----------------------------------------------------------------------
   358 // ssx_eval_row - compute pivot row of the simplex table.
   359 //
   360 // This routine computes p-th (pivot) row of the current simplex table
   361 // A~ = - inv(B) * N using the following formula:
   362 //
   363 //    A~[p] = - N' * inv(B') * e[p] = - N' * rho[p],
   364 //
   365 // where N' is a matrix transposed to the matrix N, rho[p] is p-th row
   366 // of the inverse inv(B). */
   367 
   368 void ssx_eval_row(SSX *ssx)
   369 {     int m = ssx->m;
   370       int n = ssx->n;
   371       int *A_ptr = ssx->A_ptr;
   372       int *A_ind = ssx->A_ind;
   373       mpq_t *A_val = ssx->A_val;
   374       int *Q_col = ssx->Q_col;
   375       mpq_t *rho = ssx->rho;
   376       mpq_t *ap = ssx->ap;
   377       int j, k, ptr;
   378       mpq_t temp;
   379       mpq_init(temp);
   380       for (j = 1; j <= n; j++)
   381       {  /* ap[j] := - N'[j] * rho (inner product) */
   382          k = Q_col[m+j]; /* x[k] = xN[j] */
   383          if (k <= m)
   384             mpq_neg(ap[j], rho[k]);
   385          else
   386          {  mpq_set_si(ap[j], 0, 1);
   387             for (ptr = A_ptr[k-m]; ptr < A_ptr[k-m+1]; ptr++)
   388             {  mpq_mul(temp, A_val[ptr], rho[A_ind[ptr]]);
   389                mpq_add(ap[j], ap[j], temp);
   390             }
   391          }
   392       }
   393       mpq_clear(temp);
   394       return;
   395 }
   396 
   397 /*----------------------------------------------------------------------
   398 // ssx_eval_col - compute pivot column of the simplex table.
   399 //
   400 // This routine computes q-th (pivot) column of the current simplex
   401 // table A~ = - inv(B) * N using the following formula:
   402 //
   403 //    A~[q] = - inv(B) * N[q],
   404 //
   405 // where N[q] is q-th column of the matrix N corresponding to chosen
   406 // non-basic variable xN[q]. */
   407 
   408 void ssx_eval_col(SSX *ssx)
   409 {     int m = ssx->m;
   410       int n = ssx->n;
   411       int *A_ptr = ssx->A_ptr;
   412       int *A_ind = ssx->A_ind;
   413       mpq_t *A_val = ssx->A_val;
   414       int *Q_col = ssx->Q_col;
   415       int q = ssx->q;
   416       mpq_t *aq = ssx->aq;
   417       int i, k, ptr;
   418       xassert(1 <= q && q <= n);
   419       /* aq := 0 */
   420       for (i = 1; i <= m; i++) mpq_set_si(aq[i], 0, 1);
   421       /* aq := N[q] */
   422       k = Q_col[m+q]; /* x[k] = xN[q] */
   423       if (k <= m)
   424       {  /* N[q] is a column of the unity matrix I */
   425          mpq_set_si(aq[k], 1, 1);
   426       }
   427       else
   428       {  /* N[q] is a column of the original constraint matrix -A */
   429          for (ptr = A_ptr[k-m]; ptr < A_ptr[k-m+1]; ptr++)
   430             mpq_neg(aq[A_ind[ptr]], A_val[ptr]);
   431       }
   432       /* aq := inv(B) * aq */
   433       bfx_ftran(ssx->binv, aq, 1);
   434       /* aq := - aq */
   435       for (i = 1; i <= m; i++) mpq_neg(aq[i], aq[i]);
   436       return;
   437 }
   438 
   439 /*----------------------------------------------------------------------
   440 // ssx_chuzc - choose pivot column.
   441 //
   442 // This routine chooses non-basic variable xN[q] whose reduced cost
   443 // indicates possible improving of the objective function to enter it
   444 // in the basis.
   445 //
   446 // Currently the standard (textbook) pricing is used, i.e. that
   447 // non-basic variable is preferred which has greatest reduced cost (in
   448 // magnitude).
   449 //
   450 // If xN[q] has been chosen, the routine stores its number q and also
   451 // sets the flag q_dir that indicates direction in which xN[q] has to
   452 // change (+1 means increasing, -1 means decreasing).
   453 //
   454 // If the choice cannot be made, because the current basic solution is
   455 // dual feasible, the routine sets the number q to 0. */
   456 
   457 void ssx_chuzc(SSX *ssx)
   458 {     int m = ssx->m;
   459       int n = ssx->n;
   460       int dir = (ssx->dir == SSX_MIN ? +1 : -1);
   461       int *Q_col = ssx->Q_col;
   462       int *stat = ssx->stat;
   463       mpq_t *cbar = ssx->cbar;
   464       int j, k, s, q, q_dir;
   465       double best, temp;
   466       /* nothing is chosen so far */
   467       q = 0, q_dir = 0, best = 0.0;
   468       /* look through the list of non-basic variables */
   469       for (j = 1; j <= n; j++)
   470       {  k = Q_col[m+j]; /* x[k] = xN[j] */
   471          s = dir * mpq_sgn(cbar[j]);
   472          if ((stat[k] == SSX_NF || stat[k] == SSX_NL) && s < 0 ||
   473              (stat[k] == SSX_NF || stat[k] == SSX_NU) && s > 0)
   474          {  /* reduced cost of xN[j] indicates possible improving of
   475                the objective function */
   476             temp = fabs(mpq_get_d(cbar[j]));
   477             xassert(temp != 0.0);
   478             if (q == 0 || best < temp)
   479                q = j, q_dir = - s, best = temp;
   480          }
   481       }
   482       ssx->q = q, ssx->q_dir = q_dir;
   483       return;
   484 }
   485 
   486 /*----------------------------------------------------------------------
   487 // ssx_chuzr - choose pivot row.
   488 //
   489 // This routine looks through elements of q-th column of the simplex
   490 // table and chooses basic variable xB[p] which should leave the basis.
   491 //
   492 // The choice is based on the standard (textbook) ratio test.
   493 //
   494 // If xB[p] has been chosen, the routine stores its number p and also
   495 // sets its non-basic status p_stat which should be assigned to xB[p]
   496 // when it has left the basis and become xN[q].
   497 //
   498 // Special case p < 0 means that xN[q] is double-bounded variable and
   499 // it reaches its opposite bound before any basic variable does that,
   500 // so the current basis remains unchanged.
   501 //
   502 // If the choice cannot be made, because xN[q] can infinitely change in
   503 // the feasible direction, the routine sets the number p to 0. */
   504 
   505 void ssx_chuzr(SSX *ssx)
   506 {     int m = ssx->m;
   507       int n = ssx->n;
   508       int *type = ssx->type;
   509       mpq_t *lb = ssx->lb;
   510       mpq_t *ub = ssx->ub;
   511       int *Q_col = ssx->Q_col;
   512       mpq_t *bbar = ssx->bbar;
   513       int q = ssx->q;
   514       mpq_t *aq = ssx->aq;
   515       int q_dir = ssx->q_dir;
   516       int i, k, s, t, p, p_stat;
   517       mpq_t teta, temp;
   518       mpq_init(teta);
   519       mpq_init(temp);
   520       xassert(1 <= q && q <= n);
   521       xassert(q_dir == +1 || q_dir == -1);
   522       /* nothing is chosen so far */
   523       p = 0, p_stat = 0;
   524       /* look through the list of basic variables */
   525       for (i = 1; i <= m; i++)
   526       {  s = q_dir * mpq_sgn(aq[i]);
   527          if (s < 0)
   528          {  /* xB[i] decreases */
   529             k = Q_col[i]; /* x[k] = xB[i] */
   530             t = type[k];
   531             if (t == SSX_LO || t == SSX_DB || t == SSX_FX)
   532             {  /* xB[i] has finite lower bound */
   533                mpq_sub(temp, bbar[i], lb[k]);
   534                mpq_div(temp, temp, aq[i]);
   535                mpq_abs(temp, temp);
   536                if (p == 0 || mpq_cmp(teta, temp) > 0)
   537                {  p = i;
   538                   p_stat = (t == SSX_FX ? SSX_NS : SSX_NL);
   539                   mpq_set(teta, temp);
   540                }
   541             }
   542          }
   543          else if (s > 0)
   544          {  /* xB[i] increases */
   545             k = Q_col[i]; /* x[k] = xB[i] */
   546             t = type[k];
   547             if (t == SSX_UP || t == SSX_DB || t == SSX_FX)
   548             {  /* xB[i] has finite upper bound */
   549                mpq_sub(temp, bbar[i], ub[k]);
   550                mpq_div(temp, temp, aq[i]);
   551                mpq_abs(temp, temp);
   552                if (p == 0 || mpq_cmp(teta, temp) > 0)
   553                {  p = i;
   554                   p_stat = (t == SSX_FX ? SSX_NS : SSX_NU);
   555                   mpq_set(teta, temp);
   556                }
   557             }
   558          }
   559          /* if something has been chosen and the ratio test indicates
   560             exact degeneracy, the search can be finished */
   561          if (p != 0 && mpq_sgn(teta) == 0) break;
   562       }
   563       /* if xN[q] is double-bounded, check if it can reach its opposite
   564          bound before any basic variable */
   565       k = Q_col[m+q]; /* x[k] = xN[q] */
   566       if (type[k] == SSX_DB)
   567       {  mpq_sub(temp, ub[k], lb[k]);
   568          if (p == 0 || mpq_cmp(teta, temp) > 0)
   569          {  p = -1;
   570             p_stat = -1;
   571             mpq_set(teta, temp);
   572          }
   573       }
   574       ssx->p = p;
   575       ssx->p_stat = p_stat;
   576       /* if xB[p] has been chosen, determine its actual change in the
   577          adjacent basis (it has the same sign as q_dir) */
   578       if (p != 0)
   579       {  xassert(mpq_sgn(teta) >= 0);
   580          if (q_dir > 0)
   581             mpq_set(ssx->delta, teta);
   582          else
   583             mpq_neg(ssx->delta, teta);
   584       }
   585       mpq_clear(teta);
   586       mpq_clear(temp);
   587       return;
   588 }
   589 
   590 /*----------------------------------------------------------------------
   591 // ssx_update_bbar - update values of basic variables.
   592 //
   593 // This routine recomputes the current values of basic variables for
   594 // the adjacent basis.
   595 //
   596 // The simplex table for the current basis is the following:
   597 //
   598 //    xB[i] = sum{j in 1..n} alfa[i,j] * xN[q],  i = 1,...,m
   599 //
   600 // therefore
   601 //
   602 //    delta xB[i] = alfa[i,q] * delta xN[q],  i = 1,...,m
   603 //
   604 // where delta xN[q] = xN.new[q] - xN[q] is the change of xN[q] in the
   605 // adjacent basis, and delta xB[i] = xB.new[i] - xB[i] is the change of
   606 // xB[i]. This gives formulae for recomputing values of xB[i]:
   607 //
   608 //    xB.new[p] = xN[q] + delta xN[q]
   609 //
   610 // (because xN[q] becomes xB[p] in the adjacent basis), and
   611 //
   612 //    xB.new[i] = xB[i] + alfa[i,q] * delta xN[q],  i != p
   613 //
   614 // for other basic variables. */
   615 
   616 void ssx_update_bbar(SSX *ssx)
   617 {     int m = ssx->m;
   618       int n = ssx->n;
   619       mpq_t *bbar = ssx->bbar;
   620       mpq_t *cbar = ssx->cbar;
   621       int p = ssx->p;
   622       int q = ssx->q;
   623       mpq_t *aq = ssx->aq;
   624       int i;
   625       mpq_t temp;
   626       mpq_init(temp);
   627       xassert(1 <= q && q <= n);
   628       if (p < 0)
   629       {  /* xN[q] is double-bounded and goes to its opposite bound */
   630          /* nop */;
   631       }
   632       else
   633       {  /* xN[q] becomes xB[p] in the adjacent basis */
   634          /* xB.new[p] = xN[q] + delta xN[q] */
   635          xassert(1 <= p && p <= m);
   636          ssx_get_xNj(ssx, q, temp);
   637          mpq_add(bbar[p], temp, ssx->delta);
   638       }
   639       /* update values of other basic variables depending on xN[q] */
   640       for (i = 1; i <= m; i++)
   641       {  if (i == p) continue;
   642          /* xB.new[i] = xB[i] + alfa[i,q] * delta xN[q] */
   643          if (mpq_sgn(aq[i]) == 0) continue;
   644          mpq_mul(temp, aq[i], ssx->delta);
   645          mpq_add(bbar[i], bbar[i], temp);
   646       }
   647 #if 1
   648       /* update value of the objective function */
   649       /* z.new = z + d[q] * delta xN[q] */
   650       mpq_mul(temp, cbar[q], ssx->delta);
   651       mpq_add(bbar[0], bbar[0], temp);
   652 #endif
   653       mpq_clear(temp);
   654       return;
   655 }
   656 
   657 /*----------------------------------------------------------------------
   658 -- ssx_update_pi - update simplex multipliers.
   659 --
   660 -- This routine recomputes the vector of simplex multipliers for the
   661 -- adjacent basis. */
   662 
   663 void ssx_update_pi(SSX *ssx)
   664 {     int m = ssx->m;
   665       int n = ssx->n;
   666       mpq_t *pi = ssx->pi;
   667       mpq_t *cbar = ssx->cbar;
   668       int p = ssx->p;
   669       int q = ssx->q;
   670       mpq_t *aq = ssx->aq;
   671       mpq_t *rho = ssx->rho;
   672       int i;
   673       mpq_t new_dq, temp;
   674       mpq_init(new_dq);
   675       mpq_init(temp);
   676       xassert(1 <= p && p <= m);
   677       xassert(1 <= q && q <= n);
   678       /* compute d[q] in the adjacent basis */
   679       mpq_div(new_dq, cbar[q], aq[p]);
   680       /* update the vector of simplex multipliers */
   681       for (i = 1; i <= m; i++)
   682       {  if (mpq_sgn(rho[i]) == 0) continue;
   683          mpq_mul(temp, new_dq, rho[i]);
   684          mpq_sub(pi[i], pi[i], temp);
   685       }
   686       mpq_clear(new_dq);
   687       mpq_clear(temp);
   688       return;
   689 }
   690 
   691 /*----------------------------------------------------------------------
   692 // ssx_update_cbar - update reduced costs of non-basic variables.
   693 //
   694 // This routine recomputes the vector of reduced costs of non-basic
   695 // variables for the adjacent basis. */
   696 
   697 void ssx_update_cbar(SSX *ssx)
   698 {     int m = ssx->m;
   699       int n = ssx->n;
   700       mpq_t *cbar = ssx->cbar;
   701       int p = ssx->p;
   702       int q = ssx->q;
   703       mpq_t *ap = ssx->ap;
   704       int j;
   705       mpq_t temp;
   706       mpq_init(temp);
   707       xassert(1 <= p && p <= m);
   708       xassert(1 <= q && q <= n);
   709       /* compute d[q] in the adjacent basis */
   710       /* d.new[q] = d[q] / alfa[p,q] */
   711       mpq_div(cbar[q], cbar[q], ap[q]);
   712       /* update reduced costs of other non-basic variables */
   713       for (j = 1; j <= n; j++)
   714       {  if (j == q) continue;
   715          /* d.new[j] = d[j] - (alfa[p,j] / alfa[p,q]) * d[q] */
   716          if (mpq_sgn(ap[j]) == 0) continue;
   717          mpq_mul(temp, ap[j], cbar[q]);
   718          mpq_sub(cbar[j], cbar[j], temp);
   719       }
   720       mpq_clear(temp);
   721       return;
   722 }
   723 
   724 /*----------------------------------------------------------------------
   725 // ssx_change_basis - change current basis to adjacent one.
   726 //
   727 // This routine changes the current basis to the adjacent one swapping
   728 // basic variable xB[p] and non-basic variable xN[q]. */
   729 
   730 void ssx_change_basis(SSX *ssx)
   731 {     int m = ssx->m;
   732       int n = ssx->n;
   733       int *type = ssx->type;
   734       int *stat = ssx->stat;
   735       int *Q_row = ssx->Q_row;
   736       int *Q_col = ssx->Q_col;
   737       int p = ssx->p;
   738       int q = ssx->q;
   739       int p_stat = ssx->p_stat;
   740       int k, kp, kq;
   741       if (p < 0)
   742       {  /* special case: xN[q] goes to its opposite bound */
   743          xassert(1 <= q && q <= n);
   744          k = Q_col[m+q]; /* x[k] = xN[q] */
   745          xassert(type[k] == SSX_DB);
   746          switch (stat[k])
   747          {  case SSX_NL:
   748                stat[k] = SSX_NU;
   749                break;
   750             case SSX_NU:
   751                stat[k] = SSX_NL;
   752                break;
   753             default:
   754                xassert(stat != stat);
   755          }
   756       }
   757       else
   758       {  /* xB[p] leaves the basis, xN[q] enters the basis */
   759          xassert(1 <= p && p <= m);
   760          xassert(1 <= q && q <= n);
   761          kp = Q_col[p];   /* x[kp] = xB[p] */
   762          kq = Q_col[m+q]; /* x[kq] = xN[q] */
   763          /* check non-basic status of xB[p] which becomes xN[q] */
   764          switch (type[kp])
   765          {  case SSX_FR:
   766                xassert(p_stat == SSX_NF);
   767                break;
   768             case SSX_LO:
   769                xassert(p_stat == SSX_NL);
   770                break;
   771             case SSX_UP:
   772                xassert(p_stat == SSX_NU);
   773                break;
   774             case SSX_DB:
   775                xassert(p_stat == SSX_NL || p_stat == SSX_NU);
   776                break;
   777             case SSX_FX:
   778                xassert(p_stat == SSX_NS);
   779                break;
   780             default:
   781                xassert(type != type);
   782          }
   783          /* swap xB[p] and xN[q] */
   784          stat[kp] = (char)p_stat, stat[kq] = SSX_BS;
   785          Q_row[kp] = m+q, Q_row[kq] = p;
   786          Q_col[p] = kq, Q_col[m+q] = kp;
   787          /* update factorization of the basis matrix */
   788          if (bfx_update(ssx->binv, p))
   789          {  if (ssx_factorize(ssx))
   790                xassert(("Internal error: basis matrix is singular", 0));
   791          }
   792       }
   793       return;
   794 }
   795 
   796 /*----------------------------------------------------------------------
   797 // ssx_delete - delete simplex solver workspace.
   798 //
   799 // This routine deletes the simplex solver workspace freeing all the
   800 // memory allocated to this object. */
   801 
   802 void ssx_delete(SSX *ssx)
   803 {     int m = ssx->m;
   804       int n = ssx->n;
   805       int nnz = ssx->A_ptr[n+1]-1;
   806       int i, j, k;
   807       xfree(ssx->type);
   808       for (k = 1; k <= m+n; k++) mpq_clear(ssx->lb[k]);
   809       xfree(ssx->lb);
   810       for (k = 1; k <= m+n; k++) mpq_clear(ssx->ub[k]);
   811       xfree(ssx->ub);
   812       for (k = 0; k <= m+n; k++) mpq_clear(ssx->coef[k]);
   813       xfree(ssx->coef);
   814       xfree(ssx->A_ptr);
   815       xfree(ssx->A_ind);
   816       for (k = 1; k <= nnz; k++) mpq_clear(ssx->A_val[k]);
   817       xfree(ssx->A_val);
   818       xfree(ssx->stat);
   819       xfree(ssx->Q_row);
   820       xfree(ssx->Q_col);
   821       bfx_delete_binv(ssx->binv);
   822       for (i = 0; i <= m; i++) mpq_clear(ssx->bbar[i]);
   823       xfree(ssx->bbar);
   824       for (i = 1; i <= m; i++) mpq_clear(ssx->pi[i]);
   825       xfree(ssx->pi);
   826       for (j = 1; j <= n; j++) mpq_clear(ssx->cbar[j]);
   827       xfree(ssx->cbar);
   828       for (i = 1; i <= m; i++) mpq_clear(ssx->rho[i]);
   829       xfree(ssx->rho);
   830       for (j = 1; j <= n; j++) mpq_clear(ssx->ap[j]);
   831       xfree(ssx->ap);
   832       for (i = 1; i <= m; i++) mpq_clear(ssx->aq[i]);
   833       xfree(ssx->aq);
   834       mpq_clear(ssx->delta);
   835       xfree(ssx);
   836       return;
   837 }
   838 
   839 /* eof */