LTP GCOV extension - code coverage report
Current view: directory - tpl/glpk/glpk/src - glpfhv.c
Test: Acro
Date: 2008-08-19 Instrumented lines: 307
Code covered: 87.3 % Executed lines: 268

       1                 : /* glpfhv.c (LP basis factorization, FHV eta file version) */
       2                 : 
       3                 : /***********************************************************************
       4                 : *  This code is part of GLPK (GNU Linear Programming Kit).
       5                 : *
       6                 : *  Copyright (C) 2000, 01, 02, 03, 04, 05, 06, 07 Andrew Makhorin,
       7                 : *  Department for Applied Informatics, Moscow Aviation Institute,
       8                 : *  Moscow, Russia. All rights reserved. E-mail: <mao@mai2.rcnet.ru>.
       9                 : *
      10                 : *  GLPK is free software: you can redistribute it and/or modify it
      11                 : *  under the terms of the GNU General Public License as published by
      12                 : *  the Free Software Foundation, either version 3 of the License, or
      13                 : *  (at your option) any later version.
      14                 : *
      15                 : *  GLPK is distributed in the hope that it will be useful, but WITHOUT
      16                 : *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
      17                 : *  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
      18                 : *  License for more details.
      19                 : *
      20                 : *  You should have received a copy of the GNU General Public License
      21                 : *  along with GLPK. If not, see <http://www.gnu.org/licenses/>.
      22                 : ***********************************************************************/
      23                 : 
      24                 : #include "glpfhv.h"
      25                 : #include "glplib.h"
      26                 : 
      27                 : /* CAUTION: DO NOT CHANGE THE LIMIT BELOW */
      28                 : 
      29                 : #define M_MAX 100000000 /* = 100*10^6 */
      30                 : /* maximal order of the basis matrix */
      31                 : 
      32                 : /***********************************************************************
      33                 : *  NAME
      34                 : *
      35                 : *  fhv_create_it - create LP basis factorization
      36                 : *
      37                 : *  SYNOPSIS
      38                 : *
      39                 : *  #include "glpfhv.h"
      40                 : *  FHV *fhv_create_it(void);
      41                 : *
      42                 : *  DESCRIPTION
      43                 : *
      44                 : *  The routine fhv_create_it creates a program object, which represents
      45                 : *  a factorization of LP basis.
      46                 : *
      47                 : *  RETURNS
      48                 : *
      49                 : *  The routine fhv_create_it returns a pointer to the object created. */
      50                 : 
      51                 : FHV *fhv_create_it(void)
      52               5 : {     FHV *fhv;
      53               5 :       fhv = xmalloc(sizeof(FHV));
      54               5 :       fhv->m_max = fhv->m = 0;
      55               5 :       fhv->valid = 0;
      56               5 :       fhv->luf = luf_create_it();
      57               5 :       fhv->hh_max = 50;
      58               5 :       fhv->hh_nfs = 0;
      59               5 :       fhv->hh_ind = fhv->hh_ptr = fhv->hh_len = NULL;
      60               5 :       fhv->p0_row = fhv->p0_col = NULL;
      61               5 :       fhv->cc_ind = NULL;
      62               5 :       fhv->cc_val = NULL;
      63               5 :       fhv->upd_tol = 1e-6;
      64               5 :       fhv->nnz_h = 0;
      65               5 :       return fhv;
      66                 : }
      67                 : 
      68                 : /***********************************************************************
      69                 : *  NAME
      70                 : *
      71                 : *  fhv_factorize - compute LP basis factorization
      72                 : *
      73                 : *  SYNOPSIS
      74                 : *
      75                 : *  #include "glpfhv.h"
      76                 : *  int fhv_factorize(FHV *fhv, int m, int (*col)(void *info, int j,
      77                 : *     int ind[], double val[]), void *info);
      78                 : *
      79                 : *  DESCRIPTION
      80                 : *
      81                 : *  The routine fhv_factorize computes the factorization of the basis
      82                 : *  matrix B specified by the routine col.
      83                 : *
      84                 : *  The parameter fhv specified the basis factorization data structure
      85                 : *  created by the routine fhv_create_it.
      86                 : *
      87                 : *  The parameter m specifies the order of B, m > 0.
      88                 : *
      89                 : *  The formal routine col specifies the matrix B to be factorized. To
      90                 : *  obtain j-th column of A the routine fhv_factorize calls the routine
      91                 : *  col with the parameter j (1 <= j <= n). In response the routine col
      92                 : *  should store row indices and numerical values of non-zero elements
      93                 : *  of j-th column of B to locations ind[1,...,len] and val[1,...,len],
      94                 : *  respectively, where len is the number of non-zeros in j-th column
      95                 : *  returned on exit. Neither zero nor duplicate elements are allowed.
      96                 : *
      97                 : *  The parameter info is a transit pointer passed to the routine col.
      98                 : *
      99                 : *  RETURNS
     100                 : *
     101                 : *  0  The factorization has been successfully computed.
     102                 : *
     103                 : *  FHV_ESING
     104                 : *     The specified matrix is singular within the working precision.
     105                 : *
     106                 : *  FHV_ECOND
     107                 : *     The specified matrix is ill-conditioned.
     108                 : *
     109                 : *  For more details see comments to the routine luf_factorize.
     110                 : *
     111                 : *  ALGORITHM
     112                 : *
     113                 : *  The routine fhv_factorize calls the routine luf_factorize (see the
     114                 : *  module GLPLUF), which actually computes LU-factorization of the basis
     115                 : *  matrix B in the form
     116                 : *
     117                 : *     [B] = (F, V, P, Q),
     118                 : *
     119                 : *  where F and V are such matrices that
     120                 : *
     121                 : *     B = F * V,
     122                 : *
     123                 : *  and P and Q are such permutation matrices that the matrix
     124                 : *
     125                 : *     L = P * F * inv(P)
     126                 : *
     127                 : *  is lower triangular with unity diagonal, and the matrix
     128                 : *
     129                 : *     U = P * V * Q
     130                 : *
     131                 : *  is upper triangular.
     132                 : *
     133                 : *  In order to build the complete representation of the factorization
     134                 : *  (see formula (1) in the file glpfhv.h) the routine fhv_factorize just
     135                 : *  additionally sets H = I and P0 = P. */
     136                 : 
     137                 : int fhv_factorize(FHV *fhv, int m, int (*col)(void *info, int j,
     138                 :       int ind[], double val[]), void *info)
     139               8 : {     int ret;
     140               8 :       if (m < 1)
     141               0 :          xfault("fhv_factorize: m = %d; invalid parameter\n", m);
     142               8 :       if (m > M_MAX)
     143               0 :          xfault("fhv_factorize: m = %d; matrix too big\n", m);
     144               8 :       fhv->m = m;
     145                 :       /* invalidate the factorization */
     146               8 :       fhv->valid = 0;
     147                 :       /* allocate/reallocate arrays, if necessary */
     148               8 :       if (fhv->hh_ind == NULL)
     149               5 :          fhv->hh_ind = xcalloc(1+fhv->hh_max, sizeof(int));
     150               8 :       if (fhv->hh_ptr == NULL)
     151               5 :          fhv->hh_ptr = xcalloc(1+fhv->hh_max, sizeof(int));
     152               8 :       if (fhv->hh_len == NULL)
     153               5 :          fhv->hh_len = xcalloc(1+fhv->hh_max, sizeof(int));
     154               8 :       if (fhv->m_max < m)
     155               5 :       {  if (fhv->p0_row != NULL) xfree(fhv->p0_row);
     156               5 :          if (fhv->p0_col != NULL) xfree(fhv->p0_col);
     157               5 :          if (fhv->cc_ind != NULL) xfree(fhv->cc_ind);
     158               5 :          if (fhv->cc_val != NULL) xfree(fhv->cc_val);
     159               5 :          fhv->m_max = m + 100;
     160               5 :          fhv->p0_row = xcalloc(1+fhv->m_max, sizeof(int));
     161               5 :          fhv->p0_col = xcalloc(1+fhv->m_max, sizeof(int));
     162               5 :          fhv->cc_ind = xcalloc(1+fhv->m_max, sizeof(int));
     163               5 :          fhv->cc_val = xcalloc(1+fhv->m_max, sizeof(double));
     164                 :       }
     165                 :       /* try to factorize the basis matrix */
     166               8 :       switch (luf_factorize(fhv->luf, m, col, info))
     167                 :       {  case 0:
     168               8 :             break;
     169                 :          case LUF_ESING:
     170               0 :             ret = FHV_ESING;
     171               0 :             goto done;
     172                 :          case LUF_ECOND:
     173               0 :             ret = FHV_ECOND;
     174               0 :             goto done;
     175                 :          default:
     176               0 :             xassert(fhv != fhv);
     177                 :       }
     178                 :       /* the basis matrix has been successfully factorized */
     179               8 :       fhv->valid = 1;
     180                 :       /* H := I */
     181               8 :       fhv->hh_nfs = 0;
     182                 :       /* P0 := P */
     183               8 :       memcpy(&fhv->p0_row[1], &fhv->luf->pp_row[1], sizeof(int) * m);
     184               8 :       memcpy(&fhv->p0_col[1], &fhv->luf->pp_col[1], sizeof(int) * m);
     185                 :       /* currently H has no factors */
     186               8 :       fhv->nnz_h = 0;
     187               8 :       ret = 0;
     188               8 : done: /* return to the calling program */
     189               8 :       return ret;
     190                 : }
     191                 : 
     192                 : /***********************************************************************
     193                 : *  NAME
     194                 : *
     195                 : *  fhv_h_solve - solve system H*x = b or H'*x = b
     196                 : *
     197                 : *  SYNOPSIS
     198                 : *
     199                 : *  #include "glpfhv.h"
     200                 : *  void fhv_h_solve(FHV *fhv, int tr, double x[]);
     201                 : *
     202                 : *  DESCRIPTION
     203                 : *
     204                 : *  The routine fhv_h_solve solves either the system H*x = b (if the
     205                 : *  flag tr is zero) or the system H'*x = b (if the flag tr is non-zero),
     206                 : *  where the matrix H is a component of the factorization specified by
     207                 : *  the parameter fhv, H' is a matrix transposed to H.
     208                 : *
     209                 : *  On entry the array x should contain elements of the right-hand side
     210                 : *  vector b in locations x[1], ..., x[m], where m is the order of the
     211                 : *  matrix H. On exit this array will contain elements of the solution
     212                 : *  vector x in the same locations. */
     213                 : 
     214                 : void fhv_h_solve(FHV *fhv, int tr, double x[])
     215             426 : {     int nfs = fhv->hh_nfs;
     216             426 :       int *hh_ind = fhv->hh_ind;
     217             426 :       int *hh_ptr = fhv->hh_ptr;
     218             426 :       int *hh_len = fhv->hh_len;
     219             426 :       int *sv_ind = fhv->luf->sv_ind;
     220             426 :       double *sv_val = fhv->luf->sv_val;
     221                 :       int i, k, beg, end, ptr;
     222                 :       double temp;
     223             426 :       if (!fhv->valid)
     224               0 :          xfault("fhv_h_solve: the factorization is not valid\n");
     225             426 :       if (!tr)
     226                 :       {  /* solve the system H*x = b */
     227            4606 :          for (k = 1; k <= nfs; k++)
     228            4298 :          {  i = hh_ind[k];
     229            4298 :             temp = x[i];
     230            4298 :             beg = hh_ptr[k];
     231            4298 :             end = beg + hh_len[k] - 1;
     232           12703 :             for (ptr = beg; ptr <= end; ptr++)
     233            8405 :                temp -= sv_val[ptr] * x[sv_ind[ptr]];
     234            4298 :             x[i] = temp;
     235                 :          }
     236                 :       }
     237                 :       else
     238                 :       {  /* solve the system H'*x = b */
     239            1564 :          for (k = nfs; k >= 1; k--)
     240            1446 :          {  i = hh_ind[k];
     241            1446 :             temp = x[i];
     242            1446 :             if (temp == 0.0) continue;
     243             790 :             beg = hh_ptr[k];
     244             790 :             end = beg + hh_len[k] - 1;
     245            2443 :             for (ptr = beg; ptr <= end; ptr++)
     246            1653 :                x[sv_ind[ptr]] -= sv_val[ptr] * temp;
     247                 :          }
     248                 :       }
     249                 :       return;
     250                 : }
     251                 : 
     252                 : /***********************************************************************
     253                 : *  NAME
     254                 : *
     255                 : *  fhv_ftran - perform forward transformation (solve system B*x = b)
     256                 : *
     257                 : *  SYNOPSIS
     258                 : *
     259                 : *  #include "glpfhv.h"
     260                 : *  void fhv_ftran(FHV *fhv, double x[]);
     261                 : *
     262                 : *  DESCRIPTION
     263                 : *
     264                 : *  The routine fhv_ftran performs forward transformation, i.e. solves
     265                 : *  the system B*x = b, where B is the basis matrix, x is the vector of
     266                 : *  unknowns to be computed, b is the vector of right-hand sides.
     267                 : *
     268                 : *  On entry elements of the vector b should be stored in dense format
     269                 : *  in locations x[1], ..., x[m], where m is the number of rows. On exit
     270                 : *  the routine stores elements of the vector x in the same locations. */
     271                 : 
     272                 : void fhv_ftran(FHV *fhv, double x[])
     273             210 : {     int *pp_row = fhv->luf->pp_row;
     274             210 :       int *pp_col = fhv->luf->pp_col;
     275             210 :       int *p0_row = fhv->p0_row;
     276             210 :       int *p0_col = fhv->p0_col;
     277             210 :       if (!fhv->valid)
     278               0 :          xfault("fhv_ftran: the factorization is not valid\n");
     279                 :       /* B = F*H*V, therefore inv(B) = inv(V)*inv(H)*inv(F) */
     280             210 :       fhv->luf->pp_row = p0_row;
     281             210 :       fhv->luf->pp_col = p0_col;
     282             210 :       luf_f_solve(fhv->luf, 0, x);
     283             210 :       fhv->luf->pp_row = pp_row;
     284             210 :       fhv->luf->pp_col = pp_col;
     285             210 :       fhv_h_solve(fhv, 0, x);
     286             210 :       luf_v_solve(fhv->luf, 0, x);
     287                 :       return;
     288                 : }
     289                 : 
     290                 : /***********************************************************************
     291                 : *  NAME
     292                 : *
     293                 : *  fhv_btran - perform backward transformation (solve system B'*x = b)
     294                 : *
     295                 : *  SYNOPSIS
     296                 : *
     297                 : *  #include "glpfhv.h"
     298                 : *  void fhv_btran(FHV *fhv, double x[]);
     299                 : *
     300                 : *  DESCRIPTION
     301                 : *
     302                 : *  The routine fhv_btran performs backward transformation, i.e. solves
     303                 : *  the system B'*x = b, where B' is a matrix transposed to the basis
     304                 : *  matrix B, x is the vector of unknowns to be computed, b is the vector
     305                 : *  of right-hand sides.
     306                 : *
     307                 : *  On entry elements of the vector b should be stored in dense format
     308                 : *  in locations x[1], ..., x[m], where m is the number of rows. On exit
     309                 : *  the routine stores elements of the vector x in the same locations. */
     310                 : 
     311                 : void fhv_btran(FHV *fhv, double x[])
     312             118 : {     int *pp_row = fhv->luf->pp_row;
     313             118 :       int *pp_col = fhv->luf->pp_col;
     314             118 :       int *p0_row = fhv->p0_row;
     315             118 :       int *p0_col = fhv->p0_col;
     316             118 :       if (!fhv->valid)
     317               0 :          xfault("fhv_btran: the factorization is not valid\n");
     318                 :       /* B = F*H*V, therefore inv(B') = inv(F')*inv(H')*inv(V') */
     319             118 :       luf_v_solve(fhv->luf, 1, x);
     320             118 :       fhv_h_solve(fhv, 1, x);
     321             118 :       fhv->luf->pp_row = p0_row;
     322             118 :       fhv->luf->pp_col = p0_col;
     323             118 :       luf_f_solve(fhv->luf, 1, x);
     324             118 :       fhv->luf->pp_row = pp_row;
     325             118 :       fhv->luf->pp_col = pp_col;
     326                 :       return;
     327                 : }
     328                 : 
     329                 : /***********************************************************************
     330                 : *  NAME
     331                 : *
     332                 : *  fhv_update_it - update LP basis factorization
     333                 : *
     334                 : *  SYNOPSIS
     335                 : *
     336                 : *  #include "glpfhv.h"
     337                 : *  int fhv_update_it(FHV *fhv, int j, int len, const int ind[],
     338                 : *     const double val[]);
     339                 : *
     340                 : *  DESCRIPTION
     341                 : *
     342                 : *  The routine fhv_update_it updates the factorization of the basis
     343                 : *  matrix B after replacing its j-th column by a new vector.
     344                 : *
     345                 : *  The parameter j specifies the number of column of B, which has been
     346                 : *  replaced, 1 <= j <= m, where m is the order of B.
     347                 : *
     348                 : *  Row indices and numerical values of non-zero elements of the new
     349                 : *  column of B should be placed in locations ind[1], ..., ind[len] and
     350                 : *  val[1], ..., val[len], resp., where len is the number of non-zeros
     351                 : *  in the column. Neither zero nor duplicate elements are allowed.
     352                 : *
     353                 : *  RETURNS
     354                 : *
     355                 : *  0  The factorization has been successfully updated.
     356                 : *
     357                 : *  FHV_ESING
     358                 : *     The adjacent basis matrix is structurally singular, since after
     359                 : *     changing j-th column of matrix V by the new column (see algorithm
     360                 : *     below) the case k1 > k2 occured.
     361                 : *
     362                 : *  FHV_ECHECK
     363                 : *     The factorization is inaccurate, since after transforming k2-th
     364                 : *     row of matrix U = P*V*Q, its diagonal element u[k2,k2] is zero or
     365                 : *     close to zero,
     366                 : *
     367                 : *  FHV_ELIMIT
     368                 : *     Maximal number of H factors has been reached.
     369                 : *
     370                 : *  FHV_EROOM
     371                 : *     Overflow of the sparse vector area.
     372                 : *
     373                 : *  In case of non-zero return code the factorization becomes invalid.
     374                 : *  It should not be used until it has been recomputed with the routine
     375                 : *  fhv_factorize.
     376                 : *
     377                 : *  ALGORITHM
     378                 : *
     379                 : *  The routine fhv_update_it is based on the transformation proposed by
     380                 : *  Forrest and Tomlin.
     381                 : *
     382                 : *  Let j-th column of the basis matrix B have been replaced by new
     383                 : *  column B[j]. In order to keep the equality B = F*H*V j-th column of
     384                 : *  matrix V should be replaced by the column inv(F*H)*B[j].
     385                 : *
     386                 : *  From the standpoint of matrix U = P*V*Q, replacement of j-th column
     387                 : *  of matrix V is equivalent to replacement of k1-th column of matrix U,
     388                 : *  where k1 is determined by permutation matrix Q. Thus, matrix U loses
     389                 : *  its upper triangular form and becomes the following:
     390                 : *
     391                 : *         1   k1       k2   m
     392                 : *     1   x x * x x x x x x x
     393                 : *         . x * x x x x x x x
     394                 : *     k1  . . * x x x x x x x
     395                 : *         . . * x x x x x x x
     396                 : *         . . * . x x x x x x
     397                 : *         . . * . . x x x x x
     398                 : *         . . * . . . x x x x
     399                 : *     k2  . . * . . . . x x x
     400                 : *         . . . . . . . . x x
     401                 : *     m   . . . . . . . . . x
     402                 : *
     403                 : *  where row index k2 corresponds to the lowest non-zero element of
     404                 : *  k1-th column.
     405                 : *
     406                 : *  The routine moves rows and columns k1+1, k1+2, ..., k2 of matrix U
     407                 : *  by one position to the left and upwards and moves k1-th row and k1-th
     408                 : *  column to position k2. As the result of such symmetric permutations
     409                 : *  matrix U becomes the following:
     410                 : *
     411                 : *         1   k1       k2   m
     412                 : *     1   x x x x x x x * x x
     413                 : *         . x x x x x x * x x
     414                 : *     k1  . . x x x x x * x x
     415                 : *         . . . x x x x * x x
     416                 : *         . . . . x x x * x x
     417                 : *         . . . . . x x * x x
     418                 : *         . . . . . . x * x x
     419                 : *     k2  . . x x x x x * x x
     420                 : *         . . . . . . . . x x
     421                 : *     m   . . . . . . . . . x
     422                 : *
     423                 : *  Then the routine performs gaussian elimination to eliminate elements
     424                 : *  u[k2,k1], u[k2,k1+1], ..., u[k2,k2-1] using diagonal elements
     425                 : *  u[k1,k1], u[k1+1,k1+1], ..., u[k2-1,k2-1] as pivots in the same way
     426                 : *  as described in comments to the routine luf_factorize (see the module
     427                 : *  GLPLUF). Note that actually all operations are performed on matrix V,
     428                 : *  not on matrix U. During the elimination process the routine permutes
     429                 : *  neither rows nor columns, so only k2-th row of matrix U is changed.
     430                 : *
     431                 : *  To keep the main equality B = F*H*V, each time when the routine
     432                 : *  applies elementary gaussian transformation to the transformed row of
     433                 : *  matrix V (which corresponds to k2-th row of matrix U), it also adds
     434                 : *  a new element (gaussian multiplier) to the current row-like factor
     435                 : *  of matrix H, which corresponds to the transformed row of matrix V. */
     436                 : 
     437                 : int fhv_update_it(FHV *fhv, int j, int len, const int ind[],
     438                 :       const double val[])
     439              98 : {     int m = fhv->m;
     440              98 :       LUF *luf = fhv->luf;
     441              98 :       int *vr_ptr = luf->vr_ptr;
     442              98 :       int *vr_len = luf->vr_len;
     443              98 :       int *vr_cap = luf->vr_cap;
     444              98 :       double *vr_piv = luf->vr_piv;
     445              98 :       int *vc_ptr = luf->vc_ptr;
     446              98 :       int *vc_len = luf->vc_len;
     447              98 :       int *vc_cap = luf->vc_cap;
     448              98 :       int *pp_row = luf->pp_row;
     449              98 :       int *pp_col = luf->pp_col;
     450              98 :       int *qq_row = luf->qq_row;
     451              98 :       int *qq_col = luf->qq_col;
     452              98 :       int *sv_ind = luf->sv_ind;
     453              98 :       double *sv_val = luf->sv_val;
     454              98 :       double *work = luf->work;
     455              98 :       double eps_tol = luf->eps_tol;
     456              98 :       int *hh_ind = fhv->hh_ind;
     457              98 :       int *hh_ptr = fhv->hh_ptr;
     458              98 :       int *hh_len = fhv->hh_len;
     459              98 :       int *p0_row = fhv->p0_row;
     460              98 :       int *p0_col = fhv->p0_col;
     461              98 :       int *cc_ind = fhv->cc_ind;
     462              98 :       double *cc_val = fhv->cc_val;
     463              98 :       double upd_tol = fhv->upd_tol;
     464                 :       int i, i_beg, i_end, i_ptr, j_beg, j_end, j_ptr, k, k1, k2, p, q,
     465                 :          p_beg, p_end, p_ptr, ptr, ret;
     466                 :       double f, temp;
     467              98 :       if (!fhv->valid)
     468               0 :          xfault("fhv_update_it: the factorization is not valid\n");
     469              98 :       if (!(1 <= j && j <= m))
     470               0 :          xfault("fhv_update_it: j = %d; column number out of range\n",
     471                 :             j);
     472                 :       /* check if the new factor of matrix H can be created */
     473              98 :       if (fhv->hh_nfs == fhv->hh_max)
     474                 :       {  /* maximal number of updates has been reached */
     475               0 :          fhv->valid = 0;
     476               0 :          ret = FHV_ELIMIT;
     477               0 :          goto done;
     478                 :       }
     479                 :       /* convert new j-th column of B to dense format */
     480            7154 :       for (i = 1; i <= m; i++)
     481            7056 :          cc_val[i] = 0.0;
     482             589 :       for (k = 1; k <= len; k++)
     483             491 :       {  i = ind[k];
     484             491 :          if (!(1 <= i && i <= m))
     485               0 :             xfault("fhv_update_it: ind[%d] = %d; row number out of rang"
     486                 :                "e\n", k, i);
     487             491 :          if (cc_val[i] != 0.0)
     488               0 :             xfault("fhv_update_it: ind[%d] = %d; duplicate row index no"
     489                 :                "t allowed\n", k, i);
     490             491 :          if (val[k] == 0.0)
     491               0 :             xfault("fhv_update_it: val[%d] = %g; zero element not allow"
     492                 :                "ed\n", k, val[k]);
     493             491 :          cc_val[i] = val[k];
     494                 :       }
     495                 :       /* new j-th column of V := inv(F * H) * (new B[j]) */
     496              98 :       fhv->luf->pp_row = p0_row;
     497              98 :       fhv->luf->pp_col = p0_col;
     498              98 :       luf_f_solve(fhv->luf, 0, cc_val);
     499              98 :       fhv->luf->pp_row = pp_row;
     500              98 :       fhv->luf->pp_col = pp_col;
     501              98 :       fhv_h_solve(fhv, 0, cc_val);
     502                 :       /* convert new j-th column of V to sparse format */
     503              98 :       len = 0;
     504            7154 :       for (i = 1; i <= m; i++)
     505            7056 :       {  temp = cc_val[i];
     506            7056 :          if (temp == 0.0 || fabs(temp) < eps_tol) continue;
     507             659 :          len++, cc_ind[len] = i, cc_val[len] = temp;
     508                 :       }
     509                 :       /* clear old content of j-th column of matrix V */
     510              98 :       j_beg = vc_ptr[j];
     511              98 :       j_end = j_beg + vc_len[j] - 1;
     512             219 :       for (j_ptr = j_beg; j_ptr <= j_end; j_ptr++)
     513                 :       {  /* get row index of v[i,j] */
     514             121 :          i = sv_ind[j_ptr];
     515                 :          /* find v[i,j] in the i-th row */
     516             121 :          i_beg = vr_ptr[i];
     517             121 :          i_end = i_beg + vr_len[i] - 1;
     518             121 :          for (i_ptr = i_beg; sv_ind[i_ptr] != j; i_ptr++) /* nop */;
     519             121 :          xassert(i_ptr <= i_end);
     520                 :          /* remove v[i,j] from the i-th row */
     521             121 :          sv_ind[i_ptr] = sv_ind[i_end];
     522             121 :          sv_val[i_ptr] = sv_val[i_end];
     523             121 :          vr_len[i]--;
     524                 :       }
     525                 :       /* now j-th column of matrix V is empty */
     526              98 :       luf->nnz_v -= vc_len[j];
     527              98 :       vc_len[j] = 0;
     528                 :       /* add new elements of j-th column of matrix V to corresponding
     529                 :          row lists; determine indices k1 and k2 */
     530              98 :       k1 = qq_row[j], k2 = 0;
     531             751 :       for (ptr = 1; ptr <= len; ptr++)
     532                 :       {  /* get row index of v[i,j] */
     533             654 :          i = cc_ind[ptr];
     534                 :          /* at least one unused location is needed in i-th row */
     535             654 :          if (vr_len[i] + 1 > vr_cap[i])
     536             444 :          {  if (luf_enlarge_row(luf, i, vr_len[i] + 10))
     537                 :             {  /* overflow of the sparse vector area */
     538               1 :                fhv->valid = 0;
     539               1 :                luf->new_sva = luf->sv_size + luf->sv_size;
     540               1 :                xassert(luf->new_sva > luf->sv_size);
     541               1 :                ret = FHV_EROOM;
     542               1 :                goto done;
     543                 :             }
     544                 :          }
     545                 :          /* add v[i,j] to i-th row */
     546             653 :          i_ptr = vr_ptr[i] + vr_len[i];
     547             653 :          sv_ind[i_ptr] = j;
     548             653 :          sv_val[i_ptr] = cc_val[ptr];
     549             653 :          vr_len[i]++;
     550                 :          /* adjust index k2 */
     551             653 :          if (k2 < pp_col[i]) k2 = pp_col[i];
     552                 :       }
     553                 :       /* capacity of j-th column (which is currently empty) should be
     554                 :          not less than len locations */
     555              97 :       if (vc_cap[j] < len)
     556              94 :       {  if (luf_enlarge_col(luf, j, len))
     557                 :          {  /* overflow of the sparse vector area */
     558               0 :             fhv->valid = 0;
     559               0 :             luf->new_sva = luf->sv_size + luf->sv_size;
     560               0 :             xassert(luf->new_sva > luf->sv_size);
     561               0 :             ret = FHV_EROOM;
     562               0 :             goto done;
     563                 :          }
     564                 :       }
     565                 :       /* add new elements of matrix V to j-th column list */
     566              97 :       j_ptr = vc_ptr[j];
     567              97 :       memmove(&sv_ind[j_ptr], &cc_ind[1], len * sizeof(int));
     568              97 :       memmove(&sv_val[j_ptr], &cc_val[1], len * sizeof(double));
     569              97 :       vc_len[j] = len;
     570              97 :       luf->nnz_v += len;
     571                 :       /* if k1 > k2, diagonal element u[k2,k2] of matrix U is zero and
     572                 :          therefore the adjacent basis matrix is structurally singular */
     573              97 :       if (k1 > k2)
     574               0 :       {  fhv->valid = 0;
     575               0 :          ret = FHV_ESING;
     576               0 :          goto done;
     577                 :       }
     578                 :       /* perform implicit symmetric permutations of rows and columns of
     579                 :          matrix U */
     580              97 :       i = pp_row[k1], j = qq_col[k1];
     581            1843 :       for (k = k1; k < k2; k++)
     582            1746 :       {  pp_row[k] = pp_row[k+1], pp_col[pp_row[k]] = k;
     583            1746 :          qq_col[k] = qq_col[k+1], qq_row[qq_col[k]] = k;
     584                 :       }
     585              97 :       pp_row[k2] = i, pp_col[i] = k2;
     586              97 :       qq_col[k2] = j, qq_row[j] = k2;
     587                 :       /* now i-th row of the matrix V is k2-th row of matrix U; since
     588                 :          no pivoting is used, only this row will be transformed */
     589                 :       /* copy elements of i-th row of matrix V to the working array and
     590                 :          remove these elements from matrix V */
     591              97 :       for (j = 1; j <= m; j++) work[j] = 0.0;
     592              97 :       i_beg = vr_ptr[i];
     593              97 :       i_end = i_beg + vr_len[i] - 1;
     594             299 :       for (i_ptr = i_beg; i_ptr <= i_end; i_ptr++)
     595                 :       {  /* get column index of v[i,j] */
     596             202 :          j = sv_ind[i_ptr];
     597                 :          /* store v[i,j] to the working array */
     598             202 :          work[j] = sv_val[i_ptr];
     599                 :          /* find v[i,j] in the j-th column */
     600             202 :          j_beg = vc_ptr[j];
     601             202 :          j_end = j_beg + vc_len[j] - 1;
     602             202 :          for (j_ptr = j_beg; sv_ind[j_ptr] != i; j_ptr++) /* nop */;
     603             202 :          xassert(j_ptr <= j_end);
     604                 :          /* remove v[i,j] from the j-th column */
     605             202 :          sv_ind[j_ptr] = sv_ind[j_end];
     606             202 :          sv_val[j_ptr] = sv_val[j_end];
     607             202 :          vc_len[j]--;
     608                 :       }
     609                 :       /* now i-th row of matrix V is empty */
     610              97 :       luf->nnz_v -= vr_len[i];
     611              97 :       vr_len[i] = 0;
     612                 :       /* create the next row-like factor of the matrix H; this factor
     613                 :          corresponds to i-th (transformed) row */
     614              97 :       fhv->hh_nfs++;
     615              97 :       hh_ind[fhv->hh_nfs] = i;
     616                 :       /* hh_ptr[] will be set later */
     617              97 :       hh_len[fhv->hh_nfs] = 0;
     618                 :       /* up to (k2 - k1) free locations are needed to add new elements
     619                 :          to the non-trivial row of the row-like factor */
     620              97 :       if (luf->sv_end - luf->sv_beg < k2 - k1)
     621              10 :       {  luf_defrag_sva(luf);
     622              10 :          if (luf->sv_end - luf->sv_beg < k2 - k1)
     623                 :          {  /* overflow of the sparse vector area */
     624               2 :             fhv->valid = luf->valid = 0;
     625               2 :             luf->new_sva = luf->sv_size + luf->sv_size;
     626               2 :             xassert(luf->new_sva > luf->sv_size);
     627               2 :             ret = FHV_EROOM;
     628               2 :             goto done;
     629                 :          }
     630                 :       }
     631                 :       /* eliminate subdiagonal elements of matrix U */
     632            1782 :       for (k = k1; k < k2; k++)
     633                 :       {  /* v[p,q] = u[k,k] */
     634            1687 :          p = pp_row[k], q = qq_col[k];
     635                 :          /* this is the crucial point, where even tiny non-zeros should
     636                 :             not be dropped */
     637            1687 :          if (work[q] == 0.0) continue;
     638                 :          /* compute gaussian multiplier f = v[i,q] / v[p,q] */
     639             173 :          f = work[q] / vr_piv[p];
     640                 :          /* perform gaussian transformation:
     641                 :             (i-th row) := (i-th row) - f * (p-th row)
     642                 :             in order to eliminate v[i,q] = u[k2,k] */
     643             173 :          p_beg = vr_ptr[p];
     644             173 :          p_end = p_beg + vr_len[p] - 1;
     645             462 :          for (p_ptr = p_beg; p_ptr <= p_end; p_ptr++)
     646             289 :             work[sv_ind[p_ptr]] -= f * sv_val[p_ptr];
     647                 :          /* store new element (gaussian multiplier that corresponds to
     648                 :             p-th row) in the current row-like factor */
     649             173 :          luf->sv_end--;
     650             173 :          sv_ind[luf->sv_end] = p;
     651             173 :          sv_val[luf->sv_end] = f;
     652             173 :          hh_len[fhv->hh_nfs]++;
     653                 :       }
     654                 :       /* set pointer to the current row-like factor of the matrix H
     655                 :          (if no elements were added to this factor, it is unity matrix
     656                 :          and therefore can be discarded) */
     657              95 :       if (hh_len[fhv->hh_nfs] == 0)
     658              23 :          fhv->hh_nfs--;
     659                 :       else
     660              72 :       {  hh_ptr[fhv->hh_nfs] = luf->sv_end;
     661              72 :          fhv->nnz_h += hh_len[fhv->hh_nfs];
     662                 :       }
     663                 :       /* store new pivot which corresponds to u[k2,k2] */
     664              95 :       vr_piv[i] = work[qq_col[k2]];
     665                 :       /* new elements of i-th row of matrix V (which are non-diagonal
     666                 :          elements u[k2,k2+1], ..., u[k2,m] of matrix U = P*V*Q) now are
     667                 :          contained in the working array; add them to matrix V */
     668              95 :       len = 0;
     669            2349 :       for (k = k2+1; k <= m; k++)
     670                 :       {  /* get column index and value of v[i,j] = u[k2,k] */
     671            2254 :          j = qq_col[k];
     672            2254 :          temp = work[j];
     673                 :          /* if v[i,j] is close to zero, skip it */
     674            2254 :          if (fabs(temp) < eps_tol) continue;
     675                 :          /* at least one unused location is needed in j-th column */
     676              21 :          if (vc_len[j] + 1 > vc_cap[j])
     677               7 :          {  if (luf_enlarge_col(luf, j, vc_len[j] + 10))
     678                 :             {  /* overflow of the sparse vector area */
     679               0 :                fhv->valid = 0;
     680               0 :                luf->new_sva = luf->sv_size + luf->sv_size;
     681               0 :                xassert(luf->new_sva > luf->sv_size);
     682               0 :                ret = FHV_EROOM;
     683               0 :                goto done;
     684                 :             }
     685                 :          }
     686                 :          /* add v[i,j] to j-th column */
     687              21 :          j_ptr = vc_ptr[j] + vc_len[j];
     688              21 :          sv_ind[j_ptr] = i;
     689              21 :          sv_val[j_ptr] = temp;
     690              21 :          vc_len[j]++;
     691                 :          /* also store v[i,j] to the auxiliary array */
     692              21 :          len++, cc_ind[len] = j, cc_val[len] = temp;
     693                 :       }
     694                 :       /* capacity of i-th row (which is currently empty) should be not
     695                 :          less than len locations */
     696              95 :       if (vr_cap[i] < len)
     697               4 :       {  if (luf_enlarge_row(luf, i, len))
     698                 :          {  /* overflow of the sparse vector area */
     699               0 :             fhv->valid = 0;
     700               0 :             luf->new_sva = luf->sv_size + luf->sv_size;
     701               0 :             xassert(luf->new_sva > luf->sv_size);
     702               0 :             ret = FHV_EROOM;
     703               0 :             goto done;
     704                 :          }
     705                 :       }
     706                 :       /* add new elements to i-th row list */
     707              95 :       i_ptr = vr_ptr[i];
     708              95 :       memmove(&sv_ind[i_ptr], &cc_ind[1], len * sizeof(int));
     709              95 :       memmove(&sv_val[i_ptr], &cc_val[1], len * sizeof(double));
     710              95 :       vr_len[i] = len;
     711              95 :       luf->nnz_v += len;
     712                 :       /* updating is finished; check that diagonal element u[k2,k2] is
     713                 :          not very small in absolute value among other elements in k2-th
     714                 :          row and k2-th column of matrix U = P*V*Q */
     715                 :       /* temp = max(|u[k2,*]|, |u[*,k2]|) */
     716              95 :       temp = 0.0;
     717                 :       /* walk through k2-th row of U which is i-th row of V */
     718              95 :       i = pp_row[k2];
     719              95 :       i_beg = vr_ptr[i];
     720              95 :       i_end = i_beg + vr_len[i] - 1;
     721             116 :       for (i_ptr = i_beg; i_ptr <= i_end; i_ptr++)
     722              21 :          if (temp < fabs(sv_val[i_ptr])) temp = fabs(sv_val[i_ptr]);
     723                 :       /* walk through k2-th column of U which is j-th column of V */
     724              95 :       j = qq_col[k2];
     725              95 :       j_beg = vc_ptr[j];
     726              95 :       j_end = j_beg + vc_len[j] - 1;
     727             663 :       for (j_ptr = j_beg; j_ptr <= j_end; j_ptr++)
     728             568 :          if (temp < fabs(sv_val[j_ptr])) temp = fabs(sv_val[j_ptr]);
     729                 :       /* check that u[k2,k2] is not very small */
     730              95 :       if (fabs(vr_piv[i]) < upd_tol * temp)
     731                 :       {  /* the factorization seems to be inaccurate and therefore must
     732                 :             be recomputed */
     733               0 :          fhv->valid = 0;
     734               0 :          ret = FHV_ECHECK;
     735               0 :          goto done;
     736                 :       }
     737                 :       /* the factorization has been successfully updated */
     738              95 :       ret = 0;
     739              98 : done: /* return to the calling program */
     740              98 :       return ret;
     741                 : }
     742                 : 
     743                 : /***********************************************************************
     744                 : *  NAME
     745                 : *
     746                 : *  fhv_delete_it - delete LP basis factorization
     747                 : *
     748                 : *  SYNOPSIS
     749                 : *
     750                 : *  #include "glpfhv.h"
     751                 : *  void fhv_delete_it(FHV *fhv);
     752                 : *
     753                 : *  DESCRIPTION
     754                 : *
     755                 : *  The routine fhv_delete_it deletes LP basis factorization specified
     756                 : *  by the parameter fhv and frees all memory allocated to this program
     757                 : *  object. */
     758                 : 
     759                 : void fhv_delete_it(FHV *fhv)
     760               5 : {     luf_delete_it(fhv->luf);
     761               5 :       if (fhv->hh_ind != NULL) xfree(fhv->hh_ind);
     762               5 :       if (fhv->hh_ptr != NULL) xfree(fhv->hh_ptr);
     763               5 :       if (fhv->hh_len != NULL) xfree(fhv->hh_len);
     764               5 :       if (fhv->p0_row != NULL) xfree(fhv->p0_row);
     765               5 :       if (fhv->p0_col != NULL) xfree(fhv->p0_col);
     766               5 :       if (fhv->cc_ind != NULL) xfree(fhv->cc_ind);
     767               5 :       if (fhv->cc_val != NULL) xfree(fhv->cc_val);
     768               5 :       xfree(fhv);
     769                 :       return;
     770                 : }
     771                 : 
     772                 : /* eof */

Generated by: LTP GCOV extension version 1.4