src/glpluf.h
changeset 2 4c8956a7bdf4
equal deleted inserted replaced
-1:000000000000 0:8710055d5f28
       
     1 /* glpluf.h (LU-factorization) */
       
     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 #ifndef GLPLUF_H
       
    26 #define GLPLUF_H
       
    27 
       
    28 /***********************************************************************
       
    29 *  The structure LUF defines LU-factorization of a square matrix A and
       
    30 *  is the following quartet:
       
    31 *
       
    32 *     [A] = (F, V, P, Q),                                            (1)
       
    33 *
       
    34 *  where F and V are such matrices that
       
    35 *
       
    36 *     A = F * V,                                                     (2)
       
    37 *
       
    38 *  and P and Q are such permutation matrices that the matrix
       
    39 *
       
    40 *     L = P * F * inv(P)                                             (3)
       
    41 *
       
    42 *  is lower triangular with unity diagonal, and the matrix
       
    43 *
       
    44 *     U = P * V * Q                                                  (4)
       
    45 *
       
    46 *  is upper triangular. All the matrices have the order n.
       
    47 *
       
    48 *  Matrices F and V are stored in row- and column-wise sparse format
       
    49 *  as row and column linked lists of non-zero elements. Unity elements
       
    50 *  on the main diagonal of matrix F are not stored. Pivot elements of
       
    51 *  matrix V (which correspond to diagonal elements of matrix U) are
       
    52 *  stored separately in an ordinary array.
       
    53 *
       
    54 *  Permutation matrices P and Q are stored in ordinary arrays in both
       
    55 *  row- and column-like formats.
       
    56 *
       
    57 *  Matrices L and U are completely defined by matrices F, V, P, and Q
       
    58 *  and therefore not stored explicitly.
       
    59 *
       
    60 *  The factorization (1)-(4) is a version of LU-factorization. Indeed,
       
    61 *  from (3) and (4) it follows that:
       
    62 *
       
    63 *     F = inv(P) * L * P,
       
    64 *
       
    65 *     U = inv(P) * U * inv(Q),
       
    66 *
       
    67 *  and substitution into (2) leads to:
       
    68 *
       
    69 *     A = F * V = inv(P) * L * U * inv(Q).
       
    70 *
       
    71 *  For more details see the program documentation. */
       
    72 
       
    73 typedef struct LUF LUF;
       
    74 
       
    75 struct LUF
       
    76 {     /* LU-factorization of a square matrix */
       
    77       int n_max;
       
    78       /* maximal value of n (increased automatically, if necessary) */
       
    79       int n;
       
    80       /* the order of matrices A, F, V, P, Q */
       
    81       int valid;
       
    82       /* the factorization is valid only if this flag is set */
       
    83       /*--------------------------------------------------------------*/
       
    84       /* matrix F in row-wise format */
       
    85       int *fr_ptr; /* int fr_ptr[1+n_max]; */
       
    86       /* fr_ptr[i], i = 1,...,n, is a pointer to the first element of
       
    87          i-th row in SVA */
       
    88       int *fr_len; /* int fr_len[1+n_max]; */
       
    89       /* fr_len[i], i = 1,...,n, is the number of elements in i-th row
       
    90          (except unity diagonal element) */
       
    91       /*--------------------------------------------------------------*/
       
    92       /* matrix F in column-wise format */
       
    93       int *fc_ptr; /* int fc_ptr[1+n_max]; */
       
    94       /* fc_ptr[j], j = 1,...,n, is a pointer to the first element of
       
    95          j-th column in SVA */
       
    96       int *fc_len; /* int fc_len[1+n_max]; */
       
    97       /* fc_len[j], j = 1,...,n, is the number of elements in j-th
       
    98          column (except unity diagonal element) */
       
    99       /*--------------------------------------------------------------*/
       
   100       /* matrix V in row-wise format */
       
   101       int *vr_ptr; /* int vr_ptr[1+n_max]; */
       
   102       /* vr_ptr[i], i = 1,...,n, is a pointer to the first element of
       
   103          i-th row in SVA */
       
   104       int *vr_len; /* int vr_len[1+n_max]; */
       
   105       /* vr_len[i], i = 1,...,n, is the number of elements in i-th row
       
   106          (except pivot element) */
       
   107       int *vr_cap; /* int vr_cap[1+n_max]; */
       
   108       /* vr_cap[i], i = 1,...,n, is the capacity of i-th row, i.e.
       
   109          maximal number of elements which can be stored in the row
       
   110          without relocating it, vr_cap[i] >= vr_len[i] */
       
   111       double *vr_piv; /* double vr_piv[1+n_max]; */
       
   112       /* vr_piv[p], p = 1,...,n, is the pivot element v[p,q] which
       
   113          corresponds to a diagonal element of matrix U = P*V*Q */
       
   114       /*--------------------------------------------------------------*/
       
   115       /* matrix V in column-wise format */
       
   116       int *vc_ptr; /* int vc_ptr[1+n_max]; */
       
   117       /* vc_ptr[j], j = 1,...,n, is a pointer to the first element of
       
   118          j-th column in SVA */
       
   119       int *vc_len; /* int vc_len[1+n_max]; */
       
   120       /* vc_len[j], j = 1,...,n, is the number of elements in j-th
       
   121          column (except pivot element) */
       
   122       int *vc_cap; /* int vc_cap[1+n_max]; */
       
   123       /* vc_cap[j], j = 1,...,n, is the capacity of j-th column, i.e.
       
   124          maximal number of elements which can be stored in the column
       
   125          without relocating it, vc_cap[j] >= vc_len[j] */
       
   126       /*--------------------------------------------------------------*/
       
   127       /* matrix P */
       
   128       int *pp_row; /* int pp_row[1+n_max]; */
       
   129       /* pp_row[i] = j means that P[i,j] = 1 */
       
   130       int *pp_col; /* int pp_col[1+n_max]; */
       
   131       /* pp_col[j] = i means that P[i,j] = 1 */
       
   132       /* if i-th row or column of matrix F is i'-th row or column of
       
   133          matrix L, or if i-th row of matrix V is i'-th row of matrix U,
       
   134          then pp_row[i'] = i and pp_col[i] = i' */
       
   135       /*--------------------------------------------------------------*/
       
   136       /* matrix Q */
       
   137       int *qq_row; /* int qq_row[1+n_max]; */
       
   138       /* qq_row[i] = j means that Q[i,j] = 1 */
       
   139       int *qq_col; /* int qq_col[1+n_max]; */
       
   140       /* qq_col[j] = i means that Q[i,j] = 1 */
       
   141       /* if j-th column of matrix V is j'-th column of matrix U, then
       
   142          qq_row[j] = j' and qq_col[j'] = j */
       
   143       /*--------------------------------------------------------------*/
       
   144       /* the Sparse Vector Area (SVA) is a set of locations used to
       
   145          store sparse vectors representing rows and columns of matrices
       
   146          F and V; each location is a doublet (ind, val), where ind is
       
   147          an index, and val is a numerical value of a sparse vector
       
   148          element; in the whole each sparse vector is a set of adjacent
       
   149          locations defined by a pointer to the first element and the
       
   150          number of elements; these pointer and number are stored in the
       
   151          corresponding matrix data structure (see above); the left part
       
   152          of SVA is used to store rows and columns of matrix V, and its
       
   153          right part is used to store rows and columns of matrix F; the
       
   154          middle part of SVA contains free (unused) locations */
       
   155       int sv_size;
       
   156       /* the size of SVA, in locations; all locations are numbered by
       
   157          integers 1, ..., n, and location 0 is not used; if necessary,
       
   158          the SVA size is automatically increased */
       
   159       int sv_beg, sv_end;
       
   160       /* SVA partitioning pointers:
       
   161          locations from 1 to sv_beg-1 belong to the left part
       
   162          locations from sv_beg to sv_end-1 belong to the middle part
       
   163          locations from sv_end to sv_size belong to the right part
       
   164          the size of the middle part is (sv_end - sv_beg) */
       
   165       int *sv_ind; /* sv_ind[1+sv_size]; */
       
   166       /* sv_ind[k], 1 <= k <= sv_size, is the index field of k-th
       
   167          location */
       
   168       double *sv_val; /* sv_val[1+sv_size]; */
       
   169       /* sv_val[k], 1 <= k <= sv_size, is the value field of k-th
       
   170          location */
       
   171       /*--------------------------------------------------------------*/
       
   172       /* in order to efficiently defragment the left part of SVA there
       
   173          is a doubly linked list of rows and columns of matrix V, where
       
   174          rows are numbered by 1, ..., n, while columns are numbered by
       
   175          n+1, ..., n+n, that allows uniquely identifying each row and
       
   176          column of V by only one integer; in this list rows and columns
       
   177          are ordered by ascending their pointers vr_ptr and vc_ptr */
       
   178       int sv_head;
       
   179       /* the number of leftmost row/column */
       
   180       int sv_tail;
       
   181       /* the number of rightmost row/column */
       
   182       int *sv_prev; /* int sv_prev[1+n_max+n_max]; */
       
   183       /* sv_prev[k], k = 1,...,n+n, is the number of a row/column which
       
   184          precedes k-th row/column */
       
   185       int *sv_next; /* int sv_next[1+n_max+n_max]; */
       
   186       /* sv_next[k], k = 1,...,n+n, is the number of a row/column which
       
   187          succedes k-th row/column */
       
   188       /*--------------------------------------------------------------*/
       
   189       /* working segment (used only during factorization) */
       
   190       double *vr_max; /* int vr_max[1+n_max]; */
       
   191       /* vr_max[i], 1 <= i <= n, is used only if i-th row of matrix V
       
   192          is active (i.e. belongs to the active submatrix), and is the
       
   193          largest magnitude of elements in i-th row; if vr_max[i] < 0,
       
   194          the largest magnitude is not known yet and should be computed
       
   195          by the pivoting routine */
       
   196       /*--------------------------------------------------------------*/
       
   197       /* in order to efficiently implement Markowitz strategy and Duff
       
   198          search technique there are two families {R[0], R[1], ..., R[n]}
       
   199          and {C[0], C[1], ..., C[n]}; member R[k] is the set of active
       
   200          rows of matrix V, which have k non-zeros, and member C[k] is
       
   201          the set of active columns of V, which have k non-zeros in the
       
   202          active submatrix (i.e. in the active rows); each set R[k] and
       
   203          C[k] is implemented as a separate doubly linked list */
       
   204       int *rs_head; /* int rs_head[1+n_max]; */
       
   205       /* rs_head[k], 0 <= k <= n, is the number of first active row,
       
   206          which has k non-zeros */
       
   207       int *rs_prev; /* int rs_prev[1+n_max]; */
       
   208       /* rs_prev[i], 1 <= i <= n, is the number of previous row, which
       
   209          has the same number of non-zeros as i-th row */
       
   210       int *rs_next; /* int rs_next[1+n_max]; */
       
   211       /* rs_next[i], 1 <= i <= n, is the number of next row, which has
       
   212          the same number of non-zeros as i-th row */
       
   213       int *cs_head; /* int cs_head[1+n_max]; */
       
   214       /* cs_head[k], 0 <= k <= n, is the number of first active column,
       
   215          which has k non-zeros (in the active rows) */
       
   216       int *cs_prev; /* int cs_prev[1+n_max]; */
       
   217       /* cs_prev[j], 1 <= j <= n, is the number of previous column,
       
   218          which has the same number of non-zeros (in the active rows) as
       
   219          j-th column */
       
   220       int *cs_next; /* int cs_next[1+n_max]; */
       
   221       /* cs_next[j], 1 <= j <= n, is the number of next column, which
       
   222          has the same number of non-zeros (in the active rows) as j-th
       
   223          column */
       
   224       /* (end of working segment) */
       
   225       /*--------------------------------------------------------------*/
       
   226       /* working arrays */
       
   227       int *flag; /* int flag[1+n_max]; */
       
   228       /* integer working array */
       
   229       double *work; /* double work[1+n_max]; */
       
   230       /* floating-point working array */
       
   231       /*--------------------------------------------------------------*/
       
   232       /* control parameters */
       
   233       int new_sva;
       
   234       /* new required size of the sparse vector area, in locations; set
       
   235          automatically by the factorizing routine */
       
   236       double piv_tol;
       
   237       /* threshold pivoting tolerance, 0 < piv_tol < 1; element v[i,j]
       
   238          of the active submatrix fits to be pivot if it satisfies to the
       
   239          stability criterion |v[i,j]| >= piv_tol * max |v[i,*]|, i.e. if
       
   240          it is not very small in the magnitude among other elements in
       
   241          the same row; decreasing this parameter gives better sparsity
       
   242          at the expense of numerical accuracy and vice versa */
       
   243       int piv_lim;
       
   244       /* maximal allowable number of pivot candidates to be considered;
       
   245          if piv_lim pivot candidates have been considered, the pivoting
       
   246          routine terminates the search with the best candidate found */
       
   247       int suhl;
       
   248       /* if this flag is set, the pivoting routine applies a heuristic
       
   249          proposed by Uwe Suhl: if a column of the active submatrix has
       
   250          no eligible pivot candidates (i.e. all its elements do not
       
   251          satisfy to the stability criterion), the routine excludes it
       
   252          from futher consideration until it becomes column singleton;
       
   253          in many cases this allows reducing the time needed for pivot
       
   254          searching */
       
   255       double eps_tol;
       
   256       /* epsilon tolerance; each element of the active submatrix, whose
       
   257          magnitude is less than eps_tol, is replaced by exact zero */
       
   258       double max_gro;
       
   259       /* maximal allowable growth of elements of matrix V during all
       
   260          the factorization process; if on some eliminaion step the ratio
       
   261          big_v / max_a (see below) becomes greater than max_gro, matrix
       
   262          A is considered as ill-conditioned (assuming that the pivoting
       
   263          tolerance piv_tol has an appropriate value) */
       
   264       /*--------------------------------------------------------------*/
       
   265       /* some statistics */
       
   266       int nnz_a;
       
   267       /* the number of non-zeros in matrix A */
       
   268       int nnz_f;
       
   269       /* the number of non-zeros in matrix F (except diagonal elements,
       
   270          which are not stored) */
       
   271       int nnz_v;
       
   272       /* the number of non-zeros in matrix V (except its pivot elements,
       
   273          which are stored in a separate array) */
       
   274       double max_a;
       
   275       /* the largest magnitude of elements of matrix A */
       
   276       double big_v;
       
   277       /* the largest magnitude of elements of matrix V appeared in the
       
   278          active submatrix during all the factorization process */
       
   279       int rank;
       
   280       /* estimated rank of matrix A */
       
   281 };
       
   282 
       
   283 /* return codes: */
       
   284 #define LUF_ESING    1  /* singular matrix */
       
   285 #define LUF_ECOND    2  /* ill-conditioned matrix */
       
   286 
       
   287 #define luf_create_it _glp_luf_create_it
       
   288 LUF *luf_create_it(void);
       
   289 /* create LU-factorization */
       
   290 
       
   291 #define luf_defrag_sva _glp_luf_defrag_sva
       
   292 void luf_defrag_sva(LUF *luf);
       
   293 /* defragment the sparse vector area */
       
   294 
       
   295 #define luf_enlarge_row _glp_luf_enlarge_row
       
   296 int luf_enlarge_row(LUF *luf, int i, int cap);
       
   297 /* enlarge row capacity */
       
   298 
       
   299 #define luf_enlarge_col _glp_luf_enlarge_col
       
   300 int luf_enlarge_col(LUF *luf, int j, int cap);
       
   301 /* enlarge column capacity */
       
   302 
       
   303 #define luf_factorize _glp_luf_factorize
       
   304 int luf_factorize(LUF *luf, int n, int (*col)(void *info, int j,
       
   305       int ind[], double val[]), void *info);
       
   306 /* compute LU-factorization */
       
   307 
       
   308 #define luf_f_solve _glp_luf_f_solve
       
   309 void luf_f_solve(LUF *luf, int tr, double x[]);
       
   310 /* solve system F*x = b or F'*x = b */
       
   311 
       
   312 #define luf_v_solve _glp_luf_v_solve
       
   313 void luf_v_solve(LUF *luf, int tr, double x[]);
       
   314 /* solve system V*x = b or V'*x = b */
       
   315 
       
   316 #define luf_a_solve _glp_luf_a_solve
       
   317 void luf_a_solve(LUF *luf, int tr, double x[]);
       
   318 /* solve system A*x = b or A'*x = b */
       
   319 
       
   320 #define luf_delete_it _glp_luf_delete_it
       
   321 void luf_delete_it(LUF *luf);
       
   322 /* delete LU-factorization */
       
   323 
       
   324 #endif
       
   325 
       
   326 /* eof */