src/glplpf.c
changeset 2 4c8956a7bdf4
equal deleted inserted replaced
-1:000000000000 0:b4e9ceeb6190
       
     1 /* glplpf.c (LP basis factorization, Schur complement version) */
       
     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 "glplpf.h"
       
    26 #include "glpenv.h"
       
    27 #define xfault xerror
       
    28 
       
    29 #define _GLPLPF_DEBUG 0
       
    30 
       
    31 /* CAUTION: DO NOT CHANGE THE LIMIT BELOW */
       
    32 
       
    33 #define M_MAX 100000000 /* = 100*10^6 */
       
    34 /* maximal order of the basis matrix */
       
    35 
       
    36 /***********************************************************************
       
    37 *  NAME
       
    38 *
       
    39 *  lpf_create_it - create LP basis factorization
       
    40 *
       
    41 *  SYNOPSIS
       
    42 *
       
    43 *  #include "glplpf.h"
       
    44 *  LPF *lpf_create_it(void);
       
    45 *
       
    46 *  DESCRIPTION
       
    47 *
       
    48 *  The routine lpf_create_it creates a program object, which represents
       
    49 *  a factorization of LP basis.
       
    50 *
       
    51 *  RETURNS
       
    52 *
       
    53 *  The routine lpf_create_it returns a pointer to the object created. */
       
    54 
       
    55 LPF *lpf_create_it(void)
       
    56 {     LPF *lpf;
       
    57 #if _GLPLPF_DEBUG
       
    58       xprintf("lpf_create_it: warning: debug mode enabled\n");
       
    59 #endif
       
    60       lpf = xmalloc(sizeof(LPF));
       
    61       lpf->valid = 0;
       
    62       lpf->m0_max = lpf->m0 = 0;
       
    63       lpf->luf = luf_create_it();
       
    64       lpf->m = 0;
       
    65       lpf->B = NULL;
       
    66       lpf->n_max = 50;
       
    67       lpf->n = 0;
       
    68       lpf->R_ptr = lpf->R_len = NULL;
       
    69       lpf->S_ptr = lpf->S_len = NULL;
       
    70       lpf->scf = NULL;
       
    71       lpf->P_row = lpf->P_col = NULL;
       
    72       lpf->Q_row = lpf->Q_col = NULL;
       
    73       lpf->v_size = 1000;
       
    74       lpf->v_ptr = 0;
       
    75       lpf->v_ind = NULL;
       
    76       lpf->v_val = NULL;
       
    77       lpf->work1 = lpf->work2 = NULL;
       
    78       return lpf;
       
    79 }
       
    80 
       
    81 /***********************************************************************
       
    82 *  NAME
       
    83 *
       
    84 *  lpf_factorize - compute LP basis factorization
       
    85 *
       
    86 *  SYNOPSIS
       
    87 *
       
    88 *  #include "glplpf.h"
       
    89 *  int lpf_factorize(LPF *lpf, int m, const int bh[], int (*col)
       
    90 *     (void *info, int j, int ind[], double val[]), void *info);
       
    91 *
       
    92 *  DESCRIPTION
       
    93 *
       
    94 *  The routine lpf_factorize computes the factorization of the basis
       
    95 *  matrix B specified by the routine col.
       
    96 *
       
    97 *  The parameter lpf specified the basis factorization data structure
       
    98 *  created with the routine lpf_create_it.
       
    99 *
       
   100 *  The parameter m specifies the order of B, m > 0.
       
   101 *
       
   102 *  The array bh specifies the basis header: bh[j], 1 <= j <= m, is the
       
   103 *  number of j-th column of B in some original matrix. The array bh is
       
   104 *  optional and can be specified as NULL.
       
   105 *
       
   106 *  The formal routine col specifies the matrix B to be factorized. To
       
   107 *  obtain j-th column of A the routine lpf_factorize calls the routine
       
   108 *  col with the parameter j (1 <= j <= n). In response the routine col
       
   109 *  should store row indices and numerical values of non-zero elements
       
   110 *  of j-th column of B to locations ind[1,...,len] and val[1,...,len],
       
   111 *  respectively, where len is the number of non-zeros in j-th column
       
   112 *  returned on exit. Neither zero nor duplicate elements are allowed.
       
   113 *
       
   114 *  The parameter info is a transit pointer passed to the routine col.
       
   115 *
       
   116 *  RETURNS
       
   117 *
       
   118 *  0  The factorization has been successfully computed.
       
   119 *
       
   120 *  LPF_ESING
       
   121 *     The specified matrix is singular within the working precision.
       
   122 *
       
   123 *  LPF_ECOND
       
   124 *     The specified matrix is ill-conditioned.
       
   125 *
       
   126 *  For more details see comments to the routine luf_factorize. */
       
   127 
       
   128 int lpf_factorize(LPF *lpf, int m, const int bh[], int (*col)
       
   129       (void *info, int j, int ind[], double val[]), void *info)
       
   130 {     int k, ret;
       
   131 #if _GLPLPF_DEBUG
       
   132       int i, j, len, *ind;
       
   133       double *B, *val;
       
   134 #endif
       
   135       xassert(bh == bh);
       
   136       if (m < 1)
       
   137          xfault("lpf_factorize: m = %d; invalid parameter\n", m);
       
   138       if (m > M_MAX)
       
   139          xfault("lpf_factorize: m = %d; matrix too big\n", m);
       
   140       lpf->m0 = lpf->m = m;
       
   141       /* invalidate the factorization */
       
   142       lpf->valid = 0;
       
   143       /* allocate/reallocate arrays, if necessary */
       
   144       if (lpf->R_ptr == NULL)
       
   145          lpf->R_ptr = xcalloc(1+lpf->n_max, sizeof(int));
       
   146       if (lpf->R_len == NULL)
       
   147          lpf->R_len = xcalloc(1+lpf->n_max, sizeof(int));
       
   148       if (lpf->S_ptr == NULL)
       
   149          lpf->S_ptr = xcalloc(1+lpf->n_max, sizeof(int));
       
   150       if (lpf->S_len == NULL)
       
   151          lpf->S_len = xcalloc(1+lpf->n_max, sizeof(int));
       
   152       if (lpf->scf == NULL)
       
   153          lpf->scf = scf_create_it(lpf->n_max);
       
   154       if (lpf->v_ind == NULL)
       
   155          lpf->v_ind = xcalloc(1+lpf->v_size, sizeof(int));
       
   156       if (lpf->v_val == NULL)
       
   157          lpf->v_val = xcalloc(1+lpf->v_size, sizeof(double));
       
   158       if (lpf->m0_max < m)
       
   159       {  if (lpf->P_row != NULL) xfree(lpf->P_row);
       
   160          if (lpf->P_col != NULL) xfree(lpf->P_col);
       
   161          if (lpf->Q_row != NULL) xfree(lpf->Q_row);
       
   162          if (lpf->Q_col != NULL) xfree(lpf->Q_col);
       
   163          if (lpf->work1 != NULL) xfree(lpf->work1);
       
   164          if (lpf->work2 != NULL) xfree(lpf->work2);
       
   165          lpf->m0_max = m + 100;
       
   166          lpf->P_row = xcalloc(1+lpf->m0_max+lpf->n_max, sizeof(int));
       
   167          lpf->P_col = xcalloc(1+lpf->m0_max+lpf->n_max, sizeof(int));
       
   168          lpf->Q_row = xcalloc(1+lpf->m0_max+lpf->n_max, sizeof(int));
       
   169          lpf->Q_col = xcalloc(1+lpf->m0_max+lpf->n_max, sizeof(int));
       
   170          lpf->work1 = xcalloc(1+lpf->m0_max+lpf->n_max, sizeof(double));
       
   171          lpf->work2 = xcalloc(1+lpf->m0_max+lpf->n_max, sizeof(double));
       
   172       }
       
   173       /* try to factorize the basis matrix */
       
   174       switch (luf_factorize(lpf->luf, m, col, info))
       
   175       {  case 0:
       
   176             break;
       
   177          case LUF_ESING:
       
   178             ret = LPF_ESING;
       
   179             goto done;
       
   180          case LUF_ECOND:
       
   181             ret = LPF_ECOND;
       
   182             goto done;
       
   183          default:
       
   184             xassert(lpf != lpf);
       
   185       }
       
   186       /* the basis matrix has been successfully factorized */
       
   187       lpf->valid = 1;
       
   188 #if _GLPLPF_DEBUG
       
   189       /* store the basis matrix for debugging */
       
   190       if (lpf->B != NULL) xfree(lpf->B);
       
   191       xassert(m <= 32767);
       
   192       lpf->B = B = xcalloc(1+m*m, sizeof(double));
       
   193       ind = xcalloc(1+m, sizeof(int));
       
   194       val = xcalloc(1+m, sizeof(double));
       
   195       for (k = 1; k <= m * m; k++)
       
   196          B[k] = 0.0;
       
   197       for (j = 1; j <= m; j++)
       
   198       {  len = col(info, j, ind, val);
       
   199          xassert(0 <= len && len <= m);
       
   200          for (k = 1; k <= len; k++)
       
   201          {  i = ind[k];
       
   202             xassert(1 <= i && i <= m);
       
   203             xassert(B[(i - 1) * m + j] == 0.0);
       
   204             xassert(val[k] != 0.0);
       
   205             B[(i - 1) * m + j] = val[k];
       
   206          }
       
   207       }
       
   208       xfree(ind);
       
   209       xfree(val);
       
   210 #endif
       
   211       /* B = B0, so there are no additional rows/columns */
       
   212       lpf->n = 0;
       
   213       /* reset the Schur complement factorization */
       
   214       scf_reset_it(lpf->scf);
       
   215       /* P := Q := I */
       
   216       for (k = 1; k <= m; k++)
       
   217       {  lpf->P_row[k] = lpf->P_col[k] = k;
       
   218          lpf->Q_row[k] = lpf->Q_col[k] = k;
       
   219       }
       
   220       /* make all SVA locations free */
       
   221       lpf->v_ptr = 1;
       
   222       ret = 0;
       
   223 done: /* return to the calling program */
       
   224       return ret;
       
   225 }
       
   226 
       
   227 /***********************************************************************
       
   228 *  The routine r_prod computes the product y := y + alpha * R * x,
       
   229 *  where x is a n-vector, alpha is a scalar, y is a m0-vector.
       
   230 *
       
   231 *  Since matrix R is available by columns, the product is computed as
       
   232 *  a linear combination:
       
   233 *
       
   234 *     y := y + alpha * (R[1] * x[1] + ... + R[n] * x[n]),
       
   235 *
       
   236 *  where R[j] is j-th column of R. */
       
   237 
       
   238 static void r_prod(LPF *lpf, double y[], double a, const double x[])
       
   239 {     int n = lpf->n;
       
   240       int *R_ptr = lpf->R_ptr;
       
   241       int *R_len = lpf->R_len;
       
   242       int *v_ind = lpf->v_ind;
       
   243       double *v_val = lpf->v_val;
       
   244       int j, beg, end, ptr;
       
   245       double t;
       
   246       for (j = 1; j <= n; j++)
       
   247       {  if (x[j] == 0.0) continue;
       
   248          /* y := y + alpha * R[j] * x[j] */
       
   249          t = a * x[j];
       
   250          beg = R_ptr[j];
       
   251          end = beg + R_len[j];
       
   252          for (ptr = beg; ptr < end; ptr++)
       
   253             y[v_ind[ptr]] += t * v_val[ptr];
       
   254       }
       
   255       return;
       
   256 }
       
   257 
       
   258 /***********************************************************************
       
   259 *  The routine rt_prod computes the product y := y + alpha * R' * x,
       
   260 *  where R' is a matrix transposed to R, x is a m0-vector, alpha is a
       
   261 *  scalar, y is a n-vector.
       
   262 *
       
   263 *  Since matrix R is available by columns, the product components are
       
   264 *  computed as inner products:
       
   265 *
       
   266 *     y[j] := y[j] + alpha * (j-th column of R) * x
       
   267 *
       
   268 *  for j = 1, 2, ..., n. */
       
   269 
       
   270 static void rt_prod(LPF *lpf, double y[], double a, const double x[])
       
   271 {     int n = lpf->n;
       
   272       int *R_ptr = lpf->R_ptr;
       
   273       int *R_len = lpf->R_len;
       
   274       int *v_ind = lpf->v_ind;
       
   275       double *v_val = lpf->v_val;
       
   276       int j, beg, end, ptr;
       
   277       double t;
       
   278       for (j = 1; j <= n; j++)
       
   279       {  /* t := (j-th column of R) * x */
       
   280          t = 0.0;
       
   281          beg = R_ptr[j];
       
   282          end = beg + R_len[j];
       
   283          for (ptr = beg; ptr < end; ptr++)
       
   284             t += v_val[ptr] * x[v_ind[ptr]];
       
   285          /* y[j] := y[j] + alpha * t */
       
   286          y[j] += a * t;
       
   287       }
       
   288       return;
       
   289 }
       
   290 
       
   291 /***********************************************************************
       
   292 *  The routine s_prod computes the product y := y + alpha * S * x,
       
   293 *  where x is a m0-vector, alpha is a scalar, y is a n-vector.
       
   294 *
       
   295 *  Since matrix S is available by rows, the product components are
       
   296 *  computed as inner products:
       
   297 *
       
   298 *     y[i] = y[i] + alpha * (i-th row of S) * x
       
   299 *
       
   300 *  for i = 1, 2, ..., n. */
       
   301 
       
   302 static void s_prod(LPF *lpf, double y[], double a, const double x[])
       
   303 {     int n = lpf->n;
       
   304       int *S_ptr = lpf->S_ptr;
       
   305       int *S_len = lpf->S_len;
       
   306       int *v_ind = lpf->v_ind;
       
   307       double *v_val = lpf->v_val;
       
   308       int i, beg, end, ptr;
       
   309       double t;
       
   310       for (i = 1; i <= n; i++)
       
   311       {  /* t := (i-th row of S) * x */
       
   312          t = 0.0;
       
   313          beg = S_ptr[i];
       
   314          end = beg + S_len[i];
       
   315          for (ptr = beg; ptr < end; ptr++)
       
   316             t += v_val[ptr] * x[v_ind[ptr]];
       
   317          /* y[i] := y[i] + alpha * t */
       
   318          y[i] += a * t;
       
   319       }
       
   320       return;
       
   321 }
       
   322 
       
   323 /***********************************************************************
       
   324 *  The routine st_prod computes the product y := y + alpha * S' * x,
       
   325 *  where S' is a matrix transposed to S, x is a n-vector, alpha is a
       
   326 *  scalar, y is m0-vector.
       
   327 *
       
   328 *  Since matrix R is available by rows, the product is computed as a
       
   329 *  linear combination:
       
   330 *
       
   331 *     y := y + alpha * (S'[1] * x[1] + ... + S'[n] * x[n]),
       
   332 *
       
   333 *  where S'[i] is i-th row of S. */
       
   334 
       
   335 static void st_prod(LPF *lpf, double y[], double a, const double x[])
       
   336 {     int n = lpf->n;
       
   337       int *S_ptr = lpf->S_ptr;
       
   338       int *S_len = lpf->S_len;
       
   339       int *v_ind = lpf->v_ind;
       
   340       double *v_val = lpf->v_val;
       
   341       int i, beg, end, ptr;
       
   342       double t;
       
   343       for (i = 1; i <= n; i++)
       
   344       {  if (x[i] == 0.0) continue;
       
   345          /* y := y + alpha * S'[i] * x[i] */
       
   346          t = a * x[i];
       
   347          beg = S_ptr[i];
       
   348          end = beg + S_len[i];
       
   349          for (ptr = beg; ptr < end; ptr++)
       
   350             y[v_ind[ptr]] += t * v_val[ptr];
       
   351       }
       
   352       return;
       
   353 }
       
   354 
       
   355 #if _GLPLPF_DEBUG
       
   356 /***********************************************************************
       
   357 *  The routine check_error computes the maximal relative error between
       
   358 *  left- and right-hand sides for the system B * x = b (if tr is zero)
       
   359 *  or B' * x = b (if tr is non-zero), where B' is a matrix transposed
       
   360 *  to B. (This routine is intended for debugging only.) */
       
   361 
       
   362 static void check_error(LPF *lpf, int tr, const double x[],
       
   363       const double b[])
       
   364 {     int m = lpf->m;
       
   365       double *B = lpf->B;
       
   366       int i, j;
       
   367       double  d, dmax = 0.0, s, t, tmax;
       
   368       for (i = 1; i <= m; i++)
       
   369       {  s = 0.0;
       
   370          tmax = 1.0;
       
   371          for (j = 1; j <= m; j++)
       
   372          {  if (!tr)
       
   373                t = B[m * (i - 1) + j] * x[j];
       
   374             else
       
   375                t = B[m * (j - 1) + i] * x[j];
       
   376             if (tmax < fabs(t)) tmax = fabs(t);
       
   377             s += t;
       
   378          }
       
   379          d = fabs(s - b[i]) / tmax;
       
   380          if (dmax < d) dmax = d;
       
   381       }
       
   382       if (dmax > 1e-8)
       
   383          xprintf("%s: dmax = %g; relative error too large\n",
       
   384             !tr ? "lpf_ftran" : "lpf_btran", dmax);
       
   385       return;
       
   386 }
       
   387 #endif
       
   388 
       
   389 /***********************************************************************
       
   390 *  NAME
       
   391 *
       
   392 *  lpf_ftran - perform forward transformation (solve system B*x = b)
       
   393 *
       
   394 *  SYNOPSIS
       
   395 *
       
   396 *  #include "glplpf.h"
       
   397 *  void lpf_ftran(LPF *lpf, double x[]);
       
   398 *
       
   399 *  DESCRIPTION
       
   400 *
       
   401 *  The routine lpf_ftran performs forward transformation, i.e. solves
       
   402 *  the system B*x = b, where B is the basis matrix, x is the vector of
       
   403 *  unknowns to be computed, b is the vector of right-hand sides.
       
   404 *
       
   405 *  On entry elements of the vector b should be stored in dense format
       
   406 *  in locations x[1], ..., x[m], where m is the number of rows. On exit
       
   407 *  the routine stores elements of the vector x in the same locations.
       
   408 *
       
   409 *  BACKGROUND
       
   410 *
       
   411 *  Solution of the system B * x = b can be obtained by solving the
       
   412 *  following augmented system:
       
   413 *
       
   414 *     ( B  F^) ( x )   ( b )
       
   415 *     (      ) (   ) = (   )
       
   416 *     ( G^ H^) ( y )   ( 0 )
       
   417 *
       
   418 *  which, using the main equality, can be written as follows:
       
   419 *
       
   420 *       ( L0 0 ) ( U0 R )   ( x )   ( b )
       
   421 *     P (      ) (      ) Q (   ) = (   )
       
   422 *       ( S  I ) ( 0  C )   ( y )   ( 0 )
       
   423 *
       
   424 *  therefore,
       
   425 *
       
   426 *     ( x )      ( U0 R )-1 ( L0 0 )-1    ( b )
       
   427 *     (   ) = Q' (      )   (      )   P' (   )
       
   428 *     ( y )      ( 0  C )   ( S  I )      ( 0 )
       
   429 *
       
   430 *  Thus, computing the solution includes the following steps:
       
   431 *
       
   432 *  1. Compute
       
   433 *
       
   434 *     ( f )      ( b )
       
   435 *     (   ) = P' (   )
       
   436 *     ( g )      ( 0 )
       
   437 *
       
   438 *  2. Solve the system
       
   439 *
       
   440 *     ( f1 )   ( L0 0 )-1 ( f )      ( L0 0 ) ( f1 )   ( f )
       
   441 *     (    ) = (      )   (   )  =>  (      ) (    ) = (   )
       
   442 *     ( g1 )   ( S  I )   ( g )      ( S  I ) ( g1 )   ( g )
       
   443 *
       
   444 *     from which it follows that:
       
   445 *
       
   446 *     { L0 * f1      = f      f1 = inv(L0) * f
       
   447 *     {                   =>
       
   448 *     {  S * f1 + g1 = g      g1 = g - S * f1
       
   449 *
       
   450 *  3. Solve the system
       
   451 *
       
   452 *     ( f2 )   ( U0 R )-1 ( f1 )      ( U0 R ) ( f2 )   ( f1 )
       
   453 *     (    ) = (      )   (    )  =>  (      ) (    ) = (    )
       
   454 *     ( g2 )   ( 0  C )   ( g1 )      ( 0  C ) ( g2 )   ( g1 )
       
   455 *
       
   456 *     from which it follows that:
       
   457 *
       
   458 *     { U0 * f2 + R * g2 = f1      f2 = inv(U0) * (f1 - R * g2)
       
   459 *     {                        =>
       
   460 *     {           C * g2 = g1      g2 = inv(C) * g1
       
   461 *
       
   462 *  4. Compute
       
   463 *
       
   464 *     ( x )      ( f2 )
       
   465 *     (   ) = Q' (    )
       
   466 *     ( y )      ( g2 )                                               */
       
   467 
       
   468 void lpf_ftran(LPF *lpf, double x[])
       
   469 {     int m0 = lpf->m0;
       
   470       int m = lpf->m;
       
   471       int n  = lpf->n;
       
   472       int *P_col = lpf->P_col;
       
   473       int *Q_col = lpf->Q_col;
       
   474       double *fg = lpf->work1;
       
   475       double *f = fg;
       
   476       double *g = fg + m0;
       
   477       int i, ii;
       
   478 #if _GLPLPF_DEBUG
       
   479       double *b;
       
   480 #endif
       
   481       if (!lpf->valid)
       
   482          xfault("lpf_ftran: the factorization is not valid\n");
       
   483       xassert(0 <= m && m <= m0 + n);
       
   484 #if _GLPLPF_DEBUG
       
   485       /* save the right-hand side vector */
       
   486       b = xcalloc(1+m, sizeof(double));
       
   487       for (i = 1; i <= m; i++) b[i] = x[i];
       
   488 #endif
       
   489       /* (f g) := inv(P) * (b 0) */
       
   490       for (i = 1; i <= m0 + n; i++)
       
   491          fg[i] = ((ii = P_col[i]) <= m ? x[ii] : 0.0);
       
   492       /* f1 := inv(L0) * f */
       
   493       luf_f_solve(lpf->luf, 0, f);
       
   494       /* g1 := g - S * f1 */
       
   495       s_prod(lpf, g, -1.0, f);
       
   496       /* g2 := inv(C) * g1 */
       
   497       scf_solve_it(lpf->scf, 0, g);
       
   498       /* f2 := inv(U0) * (f1 - R * g2) */
       
   499       r_prod(lpf, f, -1.0, g);
       
   500       luf_v_solve(lpf->luf, 0, f);
       
   501       /* (x y) := inv(Q) * (f2 g2) */
       
   502       for (i = 1; i <= m; i++)
       
   503          x[i] = fg[Q_col[i]];
       
   504 #if _GLPLPF_DEBUG
       
   505       /* check relative error in solution */
       
   506       check_error(lpf, 0, x, b);
       
   507       xfree(b);
       
   508 #endif
       
   509       return;
       
   510 }
       
   511 
       
   512 /***********************************************************************
       
   513 *  NAME
       
   514 *
       
   515 *  lpf_btran - perform backward transformation (solve system B'*x = b)
       
   516 *
       
   517 *  SYNOPSIS
       
   518 *
       
   519 *  #include "glplpf.h"
       
   520 *  void lpf_btran(LPF *lpf, double x[]);
       
   521 *
       
   522 *  DESCRIPTION
       
   523 *
       
   524 *  The routine lpf_btran performs backward transformation, i.e. solves
       
   525 *  the system B'*x = b, where B' is a matrix transposed to the basis
       
   526 *  matrix B, x is the vector of unknowns to be computed, b is the vector
       
   527 *  of right-hand sides.
       
   528 *
       
   529 *  On entry elements of the vector b should be stored in dense format
       
   530 *  in locations x[1], ..., x[m], where m is the number of rows. On exit
       
   531 *  the routine stores elements of the vector x in the same locations.
       
   532 *
       
   533 *  BACKGROUND
       
   534 *
       
   535 *  Solution of the system B' * x = b, where B' is a matrix transposed
       
   536 *  to B, can be obtained by solving the following augmented system:
       
   537 *
       
   538 *     ( B  F^)T ( x )   ( b )
       
   539 *     (      )  (   ) = (   )
       
   540 *     ( G^ H^)  ( y )   ( 0 )
       
   541 *
       
   542 *  which, using the main equality, can be written as follows:
       
   543 *
       
   544 *      T ( U0 R )T ( L0 0 )T  T ( x )   ( b )
       
   545 *     Q  (      )  (      )  P  (   ) = (   )
       
   546 *        ( 0  C )  ( S  I )     ( y )   ( 0 )
       
   547 *
       
   548 *  or, equivalently, as follows:
       
   549 *
       
   550 *        ( U'0 0 ) ( L'0 S')    ( x )   ( b )
       
   551 *     Q' (       ) (       ) P' (   ) = (   )
       
   552 *        ( R'  C') ( 0   I )    ( y )   ( 0 )
       
   553 *
       
   554 *  therefore,
       
   555 *
       
   556 *     ( x )     ( L'0 S')-1 ( U'0 0 )-1   ( b )
       
   557 *     (   ) = P (       )   (       )   Q (   )
       
   558 *     ( y )     ( 0   I )   ( R'  C')     ( 0 )
       
   559 *
       
   560 *  Thus, computing the solution includes the following steps:
       
   561 *
       
   562 *  1. Compute
       
   563 *
       
   564 *     ( f )     ( b )
       
   565 *     (   ) = Q (   )
       
   566 *     ( g )     ( 0 )
       
   567 *
       
   568 *  2. Solve the system
       
   569 *
       
   570 *     ( f1 )   ( U'0 0 )-1 ( f )      ( U'0 0 ) ( f1 )   ( f )
       
   571 *     (    ) = (       )   (   )  =>  (       ) (    ) = (   )
       
   572 *     ( g1 )   ( R'  C')   ( g )      ( R'  C') ( g1 )   ( g )
       
   573 *
       
   574 *     from which it follows that:
       
   575 *
       
   576 *     { U'0 * f1           = f      f1 = inv(U'0) * f
       
   577 *     {                         =>
       
   578 *     { R'  * f1 + C' * g1 = g      g1 = inv(C') * (g - R' * f1)
       
   579 *
       
   580 *  3. Solve the system
       
   581 *
       
   582 *     ( f2 )   ( L'0 S')-1 ( f1 )      ( L'0 S') ( f2 )   ( f1 )
       
   583 *     (    ) = (       )   (    )  =>  (       ) (    ) = (    )
       
   584 *     ( g2 )   ( 0   I )   ( g1 )      ( 0   I ) ( g2 )   ( g1 )
       
   585 *
       
   586 *     from which it follows that:
       
   587 *
       
   588 *     { L'0 * f2 + S' * g2 = f1
       
   589 *     {                          =>  f2 = inv(L'0) * ( f1 - S' * g2)
       
   590 *     {                 g2 = g1
       
   591 *
       
   592 *  4. Compute
       
   593 *
       
   594 *     ( x )     ( f2 )
       
   595 *     (   ) = P (    )
       
   596 *     ( y )     ( g2 )                                                */
       
   597 
       
   598 void lpf_btran(LPF *lpf, double x[])
       
   599 {     int m0 = lpf->m0;
       
   600       int m = lpf->m;
       
   601       int n = lpf->n;
       
   602       int *P_row = lpf->P_row;
       
   603       int *Q_row = lpf->Q_row;
       
   604       double *fg = lpf->work1;
       
   605       double *f = fg;
       
   606       double *g = fg + m0;
       
   607       int i, ii;
       
   608 #if _GLPLPF_DEBUG
       
   609       double *b;
       
   610 #endif
       
   611       if (!lpf->valid)
       
   612          xfault("lpf_btran: the factorization is not valid\n");
       
   613       xassert(0 <= m && m <= m0 + n);
       
   614 #if _GLPLPF_DEBUG
       
   615       /* save the right-hand side vector */
       
   616       b = xcalloc(1+m, sizeof(double));
       
   617       for (i = 1; i <= m; i++) b[i] = x[i];
       
   618 #endif
       
   619       /* (f g) := Q * (b 0) */
       
   620       for (i = 1; i <= m0 + n; i++)
       
   621          fg[i] = ((ii = Q_row[i]) <= m ? x[ii] : 0.0);
       
   622       /* f1 := inv(U'0) * f */
       
   623       luf_v_solve(lpf->luf, 1, f);
       
   624       /* g1 := inv(C') * (g - R' * f1) */
       
   625       rt_prod(lpf, g, -1.0, f);
       
   626       scf_solve_it(lpf->scf, 1, g);
       
   627       /* g2 := g1 */
       
   628       g = g;
       
   629       /* f2 := inv(L'0) * (f1 - S' * g2) */
       
   630       st_prod(lpf, f, -1.0, g);
       
   631       luf_f_solve(lpf->luf, 1, f);
       
   632       /* (x y) := P * (f2 g2) */
       
   633       for (i = 1; i <= m; i++)
       
   634          x[i] = fg[P_row[i]];
       
   635 #if _GLPLPF_DEBUG
       
   636       /* check relative error in solution */
       
   637       check_error(lpf, 1, x, b);
       
   638       xfree(b);
       
   639 #endif
       
   640       return;
       
   641 }
       
   642 
       
   643 /***********************************************************************
       
   644 *  The routine enlarge_sva enlarges the Sparse Vector Area to new_size
       
   645 *  locations by reallocating the arrays v_ind and v_val. */
       
   646 
       
   647 static void enlarge_sva(LPF *lpf, int new_size)
       
   648 {     int v_size = lpf->v_size;
       
   649       int used = lpf->v_ptr - 1;
       
   650       int *v_ind = lpf->v_ind;
       
   651       double *v_val = lpf->v_val;
       
   652       xassert(v_size < new_size);
       
   653       while (v_size < new_size) v_size += v_size;
       
   654       lpf->v_size = v_size;
       
   655       lpf->v_ind = xcalloc(1+v_size, sizeof(int));
       
   656       lpf->v_val = xcalloc(1+v_size, sizeof(double));
       
   657       xassert(used >= 0);
       
   658       memcpy(&lpf->v_ind[1], &v_ind[1], used * sizeof(int));
       
   659       memcpy(&lpf->v_val[1], &v_val[1], used * sizeof(double));
       
   660       xfree(v_ind);
       
   661       xfree(v_val);
       
   662       return;
       
   663 }
       
   664 
       
   665 /***********************************************************************
       
   666 *  NAME
       
   667 *
       
   668 *  lpf_update_it - update LP basis factorization
       
   669 *
       
   670 *  SYNOPSIS
       
   671 *
       
   672 *  #include "glplpf.h"
       
   673 *  int lpf_update_it(LPF *lpf, int j, int bh, int len, const int ind[],
       
   674 *     const double val[]);
       
   675 *
       
   676 *  DESCRIPTION
       
   677 *
       
   678 *  The routine lpf_update_it updates the factorization of the basis
       
   679 *  matrix B after replacing its j-th column by a new vector.
       
   680 *
       
   681 *  The parameter j specifies the number of column of B, which has been
       
   682 *  replaced, 1 <= j <= m, where m is the order of B.
       
   683 *
       
   684 *  The parameter bh specifies the basis header entry for the new column
       
   685 *  of B, which is the number of the new column in some original matrix.
       
   686 *  This parameter is optional and can be specified as 0.
       
   687 *
       
   688 *  Row indices and numerical values of non-zero elements of the new
       
   689 *  column of B should be placed in locations ind[1], ..., ind[len] and
       
   690 *  val[1], ..., val[len], resp., where len is the number of non-zeros
       
   691 *  in the column. Neither zero nor duplicate elements are allowed.
       
   692 *
       
   693 *  RETURNS
       
   694 *
       
   695 *  0  The factorization has been successfully updated.
       
   696 *
       
   697 *  LPF_ESING
       
   698 *     New basis B is singular within the working precision.
       
   699 *
       
   700 *  LPF_ELIMIT
       
   701 *     Maximal number of additional rows and columns has been reached.
       
   702 *
       
   703 *  BACKGROUND
       
   704 *
       
   705 *  Let j-th column of the current basis matrix B have to be replaced by
       
   706 *  a new column a. This replacement is equivalent to removing the old
       
   707 *  j-th column by fixing it at zero and introducing the new column as
       
   708 *  follows:
       
   709 *
       
   710 *                   ( B   F^| a )
       
   711 *     ( B  F^)      (       |   )
       
   712 *     (      ) ---> ( G^  H^| 0 )
       
   713 *     ( G^ H^)      (-------+---)
       
   714 *                   ( e'j 0 | 0 )
       
   715 *
       
   716 *  where ej is a unit vector with 1 in j-th position which used to fix
       
   717 *  the old j-th column of B (at zero). Then using the main equality we
       
   718 *  have:
       
   719 *
       
   720 *     ( B   F^| a )            ( B0  F | f )
       
   721 *     (       |   )   ( P  0 ) (       |   ) ( Q  0 )
       
   722 *     ( G^  H^| 0 ) = (      ) ( G   H | g ) (      ) =
       
   723 *     (-------+---)   ( 0  1 ) (-------+---) ( 0  1 )
       
   724 *     ( e'j 0 | 0 )            ( v'  w'| 0 )
       
   725 *
       
   726 *       [   ( B0  F )|   ( f ) ]            [   ( B0 F )  |   ( f ) ]
       
   727 *       [ P (       )| P (   ) ] ( Q  0 )   [ P (      ) Q| P (   ) ]
       
   728 *     = [   ( G   H )|   ( g ) ] (      ) = [   ( G  H )  |   ( g ) ]
       
   729 *       [------------+-------- ] ( 0  1 )   [-------------+---------]
       
   730 *       [   ( v'  w')|     0   ]            [   ( v' w') Q|    0    ]
       
   731 *
       
   732 *  where:
       
   733 *
       
   734 *     ( a )     ( f )      ( f )        ( a )
       
   735 *     (   ) = P (   )  =>  (   ) = P' * (   )
       
   736 *     ( 0 )     ( g )      ( g )        ( 0 )
       
   737 *
       
   738 *                                 ( ej )      ( v )    ( v )     ( ej )
       
   739 *     ( e'j  0 ) = ( v' w' ) Q => (    ) = Q' (   ) => (   ) = Q (    )
       
   740 *                                 ( 0  )      ( w )    ( w )     ( 0  )
       
   741 *
       
   742 *  On the other hand:
       
   743 *
       
   744 *              ( B0| F  f )
       
   745 *     ( P  0 ) (---+------) ( Q  0 )         ( B0    new F )
       
   746 *     (      ) ( G | H  g ) (      ) = new P (             ) new Q
       
   747 *     ( 0  1 ) (   |      ) ( 0  1 )         ( new G new H )
       
   748 *              ( v'| w' 0 )
       
   749 *
       
   750 *  where:
       
   751 *                               ( G )           ( H  g )
       
   752 *     new F = ( F  f ), new G = (   ),  new H = (      ),
       
   753 *                               ( v')           ( w' 0 )
       
   754 *
       
   755 *             ( P  0 )           ( Q  0 )
       
   756 *     new P = (      ) , new Q = (      ) .
       
   757 *             ( 0  1 )           ( 0  1 )
       
   758 *
       
   759 *  The factorization structure for the new augmented matrix remains the
       
   760 *  same, therefore:
       
   761 *
       
   762 *           ( B0    new F )         ( L0     0 ) ( U0 new R )
       
   763 *     new P (             ) new Q = (          ) (          )
       
   764 *           ( new G new H )         ( new S  I ) ( 0  new C )
       
   765 *
       
   766 *  where:
       
   767 *
       
   768 *     new F = L0 * new R  =>
       
   769 *
       
   770 *     new R = inv(L0) * new F = inv(L0) * (F  f) = ( R  inv(L0)*f )
       
   771 *
       
   772 *     new G = new S * U0  =>
       
   773 *
       
   774 *                               ( G )             (     S      )
       
   775 *     new S = new G * inv(U0) = (   ) * inv(U0) = (            )
       
   776 *                               ( v')             ( v'*inv(U0) )
       
   777 *
       
   778 *     new H = new S * new R + new C  =>
       
   779 *
       
   780 *     new C = new H - new S * new R =
       
   781 *
       
   782 *             ( H  g )   (     S      )
       
   783 *           = (      ) - (            ) * ( R  inv(L0)*f ) =
       
   784 *             ( w' 0 )   ( v'*inv(U0) )
       
   785 *
       
   786 *             ( H - S*R           g - S*inv(L0)*f      )   ( C  x )
       
   787 *           = (                                        ) = (      )
       
   788 *             ( w'- v'*inv(U0)*R  -v'*inv(U0)*inv(L0)*f)   ( y' z )
       
   789 *
       
   790 *  Note that new C is resulted by expanding old C with new column x,
       
   791 *  row y', and diagonal element z, where:
       
   792 *
       
   793 *     x = g - S * inv(L0) * f = g - S * (new column of R)
       
   794 *
       
   795 *     y = w - R'* inv(U'0)* v = w - R'* (new row of S)
       
   796 *
       
   797 *     z = - (new row of S) * (new column of R)
       
   798 *
       
   799 *  Finally, to replace old B by new B we have to permute j-th and last
       
   800 *  (just added) columns of the matrix
       
   801 *
       
   802 *     ( B   F^| a )
       
   803 *     (       |   )
       
   804 *     ( G^  H^| 0 )
       
   805 *     (-------+---)
       
   806 *     ( e'j 0 | 0 )
       
   807 *
       
   808 *  and to keep the main equality do the same for matrix Q. */
       
   809 
       
   810 int lpf_update_it(LPF *lpf, int j, int bh, int len, const int ind[],
       
   811       const double val[])
       
   812 {     int m0 = lpf->m0;
       
   813       int m = lpf->m;
       
   814 #if _GLPLPF_DEBUG
       
   815       double *B = lpf->B;
       
   816 #endif
       
   817       int n = lpf->n;
       
   818       int *R_ptr = lpf->R_ptr;
       
   819       int *R_len = lpf->R_len;
       
   820       int *S_ptr = lpf->S_ptr;
       
   821       int *S_len = lpf->S_len;
       
   822       int *P_row = lpf->P_row;
       
   823       int *P_col = lpf->P_col;
       
   824       int *Q_row = lpf->Q_row;
       
   825       int *Q_col = lpf->Q_col;
       
   826       int v_ptr = lpf->v_ptr;
       
   827       int *v_ind = lpf->v_ind;
       
   828       double *v_val = lpf->v_val;
       
   829       double *a = lpf->work2; /* new column */
       
   830       double *fg = lpf->work1, *f = fg, *g = fg + m0;
       
   831       double *vw = lpf->work2, *v = vw, *w = vw + m0;
       
   832       double *x = g, *y = w, z;
       
   833       int i, ii, k, ret;
       
   834       xassert(bh == bh);
       
   835       if (!lpf->valid)
       
   836          xfault("lpf_update_it: the factorization is not valid\n");
       
   837       if (!(1 <= j && j <= m))
       
   838          xfault("lpf_update_it: j = %d; column number out of range\n",
       
   839             j);
       
   840       xassert(0 <= m && m <= m0 + n);
       
   841       /* check if the basis factorization can be expanded */
       
   842       if (n == lpf->n_max)
       
   843       {  lpf->valid = 0;
       
   844          ret = LPF_ELIMIT;
       
   845          goto done;
       
   846       }
       
   847       /* convert new j-th column of B to dense format */
       
   848       for (i = 1; i <= m; i++)
       
   849          a[i] = 0.0;
       
   850       for (k = 1; k <= len; k++)
       
   851       {  i = ind[k];
       
   852          if (!(1 <= i && i <= m))
       
   853             xfault("lpf_update_it: ind[%d] = %d; row number out of rang"
       
   854                "e\n", k, i);
       
   855          if (a[i] != 0.0)
       
   856             xfault("lpf_update_it: ind[%d] = %d; duplicate row index no"
       
   857                "t allowed\n", k, i);
       
   858          if (val[k] == 0.0)
       
   859             xfault("lpf_update_it: val[%d] = %g; zero element not allow"
       
   860                "ed\n", k, val[k]);
       
   861          a[i] = val[k];
       
   862       }
       
   863 #if _GLPLPF_DEBUG
       
   864       /* change column in the basis matrix for debugging */
       
   865       for (i = 1; i <= m; i++)
       
   866          B[(i - 1) * m + j] = a[i];
       
   867 #endif
       
   868       /* (f g) := inv(P) * (a 0) */
       
   869       for (i = 1; i <= m0+n; i++)
       
   870          fg[i] = ((ii = P_col[i]) <= m ? a[ii] : 0.0);
       
   871       /* (v w) := Q * (ej 0) */
       
   872       for (i = 1; i <= m0+n; i++) vw[i] = 0.0;
       
   873       vw[Q_col[j]] = 1.0;
       
   874       /* f1 := inv(L0) * f (new column of R) */
       
   875       luf_f_solve(lpf->luf, 0, f);
       
   876       /* v1 := inv(U'0) * v (new row of S) */
       
   877       luf_v_solve(lpf->luf, 1, v);
       
   878       /* we need at most 2 * m0 available locations in the SVA to store
       
   879          new column of matrix R and new row of matrix S */
       
   880       if (lpf->v_size < v_ptr + m0 + m0)
       
   881       {  enlarge_sva(lpf, v_ptr + m0 + m0);
       
   882          v_ind = lpf->v_ind;
       
   883          v_val = lpf->v_val;
       
   884       }
       
   885       /* store new column of R */
       
   886       R_ptr[n+1] = v_ptr;
       
   887       for (i = 1; i <= m0; i++)
       
   888       {  if (f[i] != 0.0)
       
   889             v_ind[v_ptr] = i, v_val[v_ptr] = f[i], v_ptr++;
       
   890       }
       
   891       R_len[n+1] = v_ptr - lpf->v_ptr;
       
   892       lpf->v_ptr = v_ptr;
       
   893       /* store new row of S */
       
   894       S_ptr[n+1] = v_ptr;
       
   895       for (i = 1; i <= m0; i++)
       
   896       {  if (v[i] != 0.0)
       
   897             v_ind[v_ptr] = i, v_val[v_ptr] = v[i], v_ptr++;
       
   898       }
       
   899       S_len[n+1] = v_ptr - lpf->v_ptr;
       
   900       lpf->v_ptr = v_ptr;
       
   901       /* x := g - S * f1 (new column of C) */
       
   902       s_prod(lpf, x, -1.0, f);
       
   903       /* y := w - R' * v1 (new row of C) */
       
   904       rt_prod(lpf, y, -1.0, v);
       
   905       /* z := - v1 * f1 (new diagonal element of C) */
       
   906       z = 0.0;
       
   907       for (i = 1; i <= m0; i++) z -= v[i] * f[i];
       
   908       /* update factorization of new matrix C */
       
   909       switch (scf_update_exp(lpf->scf, x, y, z))
       
   910       {  case 0:
       
   911             break;
       
   912          case SCF_ESING:
       
   913             lpf->valid = 0;
       
   914             ret = LPF_ESING;
       
   915             goto done;
       
   916          case SCF_ELIMIT:
       
   917             xassert(lpf != lpf);
       
   918          default:
       
   919             xassert(lpf != lpf);
       
   920       }
       
   921       /* expand matrix P */
       
   922       P_row[m0+n+1] = P_col[m0+n+1] = m0+n+1;
       
   923       /* expand matrix Q */
       
   924       Q_row[m0+n+1] = Q_col[m0+n+1] = m0+n+1;
       
   925       /* permute j-th and last (just added) column of matrix Q */
       
   926       i = Q_col[j], ii = Q_col[m0+n+1];
       
   927       Q_row[i] = m0+n+1, Q_col[m0+n+1] = i;
       
   928       Q_row[ii] = j, Q_col[j] = ii;
       
   929       /* increase the number of additional rows and columns */
       
   930       lpf->n++;
       
   931       xassert(lpf->n <= lpf->n_max);
       
   932       /* the factorization has been successfully updated */
       
   933       ret = 0;
       
   934 done: /* return to the calling program */
       
   935       return ret;
       
   936 }
       
   937 
       
   938 /***********************************************************************
       
   939 *  NAME
       
   940 *
       
   941 *  lpf_delete_it - delete LP basis factorization
       
   942 *
       
   943 *  SYNOPSIS
       
   944 *
       
   945 *  #include "glplpf.h"
       
   946 *  void lpf_delete_it(LPF *lpf)
       
   947 *
       
   948 *  DESCRIPTION
       
   949 *
       
   950 *  The routine lpf_delete_it deletes LP basis factorization specified
       
   951 *  by the parameter lpf and frees all memory allocated to this program
       
   952 *  object. */
       
   953 
       
   954 void lpf_delete_it(LPF *lpf)
       
   955 {     luf_delete_it(lpf->luf);
       
   956 #if _GLPLPF_DEBUG
       
   957       if (lpf->B != NULL) xfree(lpf->B);
       
   958 #else
       
   959       xassert(lpf->B == NULL);
       
   960 #endif
       
   961       if (lpf->R_ptr != NULL) xfree(lpf->R_ptr);
       
   962       if (lpf->R_len != NULL) xfree(lpf->R_len);
       
   963       if (lpf->S_ptr != NULL) xfree(lpf->S_ptr);
       
   964       if (lpf->S_len != NULL) xfree(lpf->S_len);
       
   965       if (lpf->scf != NULL) scf_delete_it(lpf->scf);
       
   966       if (lpf->P_row != NULL) xfree(lpf->P_row);
       
   967       if (lpf->P_col != NULL) xfree(lpf->P_col);
       
   968       if (lpf->Q_row != NULL) xfree(lpf->Q_row);
       
   969       if (lpf->Q_col != NULL) xfree(lpf->Q_col);
       
   970       if (lpf->v_ind != NULL) xfree(lpf->v_ind);
       
   971       if (lpf->v_val != NULL) xfree(lpf->v_val);
       
   972       if (lpf->work1 != NULL) xfree(lpf->work1);
       
   973       if (lpf->work2 != NULL) xfree(lpf->work2);
       
   974       xfree(lpf);
       
   975       return;
       
   976 }
       
   977 
       
   978 /* eof */