src/glplpf.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 /* 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 */