src/glplux.h
author Alpar Juttner <alpar@cs.elte.hu>
Mon, 06 Dec 2010 13:09:21 +0100
changeset 1 c445c931472f
permissions -rw-r--r--
Import glpk-4.45

- Generated files and doc/notes are removed
alpar@1
     1
/* glplux.h (LU-factorization, bignum arithmetic) */
alpar@1
     2
alpar@1
     3
/***********************************************************************
alpar@1
     4
*  This code is part of GLPK (GNU Linear Programming Kit).
alpar@1
     5
*
alpar@1
     6
*  Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
alpar@1
     7
*  2009, 2010 Andrew Makhorin, Department for Applied Informatics,
alpar@1
     8
*  Moscow Aviation Institute, Moscow, Russia. All rights reserved.
alpar@1
     9
*  E-mail: <mao@gnu.org>.
alpar@1
    10
*
alpar@1
    11
*  GLPK is free software: you can redistribute it and/or modify it
alpar@1
    12
*  under the terms of the GNU General Public License as published by
alpar@1
    13
*  the Free Software Foundation, either version 3 of the License, or
alpar@1
    14
*  (at your option) any later version.
alpar@1
    15
*
alpar@1
    16
*  GLPK is distributed in the hope that it will be useful, but WITHOUT
alpar@1
    17
*  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
alpar@1
    18
*  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
alpar@1
    19
*  License for more details.
alpar@1
    20
*
alpar@1
    21
*  You should have received a copy of the GNU General Public License
alpar@1
    22
*  along with GLPK. If not, see <http://www.gnu.org/licenses/>.
alpar@1
    23
***********************************************************************/
alpar@1
    24
alpar@1
    25
#ifndef GLPLUX_H
alpar@1
    26
#define GLPLUX_H
alpar@1
    27
alpar@1
    28
#include "glpdmp.h"
alpar@1
    29
#include "glpgmp.h"
alpar@1
    30
alpar@1
    31
/*----------------------------------------------------------------------
alpar@1
    32
// The structure LUX defines LU-factorization of a square matrix A,
alpar@1
    33
// which is the following quartet:
alpar@1
    34
//
alpar@1
    35
//    [A] = (F, V, P, Q),                                            (1)
alpar@1
    36
//
alpar@1
    37
// where F and V are such matrices that
alpar@1
    38
//
alpar@1
    39
//    A = F * V,                                                     (2)
alpar@1
    40
//
alpar@1
    41
// and P and Q are such permutation matrices that the matrix
alpar@1
    42
//
alpar@1
    43
//    L = P * F * inv(P)                                             (3)
alpar@1
    44
//
alpar@1
    45
// is lower triangular with unity diagonal, and the matrix
alpar@1
    46
//
alpar@1
    47
//    U = P * V * Q                                                  (4)
alpar@1
    48
//
alpar@1
    49
// is upper triangular. All the matrices have the order n.
alpar@1
    50
//
alpar@1
    51
// The matrices F and V are stored in row/column-wise sparse format as
alpar@1
    52
// row and column linked lists of non-zero elements. Unity elements on
alpar@1
    53
// the main diagonal of the matrix F are not stored. Pivot elements of
alpar@1
    54
// the matrix V (that correspond to diagonal elements of the matrix U)
alpar@1
    55
// are also missing from the row and column lists and stored separately
alpar@1
    56
// in an ordinary array.
alpar@1
    57
//
alpar@1
    58
// The permutation matrices P and Q are stored as ordinary arrays using
alpar@1
    59
// both row- and column-like formats.
alpar@1
    60
//
alpar@1
    61
// The matrices L and U being completely defined by the matrices F, V,
alpar@1
    62
// P, and Q are not stored explicitly.
alpar@1
    63
//
alpar@1
    64
// It is easy to show that the factorization (1)-(3) is some version of
alpar@1
    65
// LU-factorization. Indeed, from (3) and (4) it follows that:
alpar@1
    66
//
alpar@1
    67
//    F = inv(P) * L * P,
alpar@1
    68
//
alpar@1
    69
//    V = inv(P) * U * inv(Q),
alpar@1
    70
//
alpar@1
    71
// and substitution into (2) gives:
alpar@1
    72
//
alpar@1
    73
//    A = F * V = inv(P) * L * U * inv(Q).
alpar@1
    74
//
alpar@1
    75
// For more details see the program documentation. */
alpar@1
    76
alpar@1
    77
typedef struct LUX LUX;
alpar@1
    78
typedef struct LUXELM LUXELM;
alpar@1
    79
typedef struct LUXWKA LUXWKA;
alpar@1
    80
alpar@1
    81
struct LUX
alpar@1
    82
{     /* LU-factorization of a square matrix */
alpar@1
    83
      int n;
alpar@1
    84
      /* the order of matrices A, F, V, P, Q */
alpar@1
    85
      DMP *pool;
alpar@1
    86
      /* memory pool for elements of matrices F and V */
alpar@1
    87
      LUXELM **F_row; /* LUXELM *F_row[1+n]; */
alpar@1
    88
      /* F_row[0] is not used;
alpar@1
    89
         F_row[i], 1 <= i <= n, is a pointer to the list of elements in
alpar@1
    90
         i-th row of matrix F (diagonal elements are not stored) */
alpar@1
    91
      LUXELM **F_col; /* LUXELM *F_col[1+n]; */
alpar@1
    92
      /* F_col[0] is not used;
alpar@1
    93
         F_col[j], 1 <= j <= n, is a pointer to the list of elements in
alpar@1
    94
         j-th column of matrix F (diagonal elements are not stored) */
alpar@1
    95
      mpq_t *V_piv; /* mpq_t V_piv[1+n]; */
alpar@1
    96
      /* V_piv[0] is not used;
alpar@1
    97
         V_piv[p], 1 <= p <= n, is a pivot element v[p,q] corresponding
alpar@1
    98
         to a diagonal element u[k,k] of matrix U = P*V*Q (used on k-th
alpar@1
    99
         elimination step, k = 1, 2, ..., n) */
alpar@1
   100
      LUXELM **V_row; /* LUXELM *V_row[1+n]; */
alpar@1
   101
      /* V_row[0] is not used;
alpar@1
   102
         V_row[i], 1 <= i <= n, is a pointer to the list of elements in
alpar@1
   103
         i-th row of matrix V (except pivot elements) */
alpar@1
   104
      LUXELM **V_col; /* LUXELM *V_col[1+n]; */
alpar@1
   105
      /* V_col[0] is not used;
alpar@1
   106
         V_col[j], 1 <= j <= n, is a pointer to the list of elements in
alpar@1
   107
         j-th column of matrix V (except pivot elements) */
alpar@1
   108
      int *P_row; /* int P_row[1+n]; */
alpar@1
   109
      /* P_row[0] is not used;
alpar@1
   110
         P_row[i] = j means that p[i,j] = 1, where p[i,j] is an element
alpar@1
   111
         of permutation matrix P */
alpar@1
   112
      int *P_col; /* int P_col[1+n]; */
alpar@1
   113
      /* P_col[0] is not used;
alpar@1
   114
         P_col[j] = i means that p[i,j] = 1, where p[i,j] is an element
alpar@1
   115
         of permutation matrix P */
alpar@1
   116
      /* if i-th row or column of matrix F is i'-th row or column of
alpar@1
   117
         matrix L = P*F*inv(P), or if i-th row of matrix V is i'-th row
alpar@1
   118
         of matrix U = P*V*Q, then P_row[i'] = i and P_col[i] = i' */
alpar@1
   119
      int *Q_row; /* int Q_row[1+n]; */
alpar@1
   120
      /* Q_row[0] is not used;
alpar@1
   121
         Q_row[i] = j means that q[i,j] = 1, where q[i,j] is an element
alpar@1
   122
         of permutation matrix Q */
alpar@1
   123
      int *Q_col; /* int Q_col[1+n]; */
alpar@1
   124
      /* Q_col[0] is not used;
alpar@1
   125
         Q_col[j] = i means that q[i,j] = 1, where q[i,j] is an element
alpar@1
   126
         of permutation matrix Q */
alpar@1
   127
      /* if j-th column of matrix V is j'-th column of matrix U = P*V*Q,
alpar@1
   128
         then Q_row[j] = j' and Q_col[j'] = j */
alpar@1
   129
      int rank;
alpar@1
   130
      /* the (exact) rank of matrices A and V */
alpar@1
   131
};
alpar@1
   132
alpar@1
   133
struct LUXELM
alpar@1
   134
{     /* element of matrix F or V */
alpar@1
   135
      int i;
alpar@1
   136
      /* row index, 1 <= i <= m */
alpar@1
   137
      int j;
alpar@1
   138
      /* column index, 1 <= j <= n */
alpar@1
   139
      mpq_t val;
alpar@1
   140
      /* numeric (non-zero) element value */
alpar@1
   141
      LUXELM *r_prev;
alpar@1
   142
      /* pointer to previous element in the same row */
alpar@1
   143
      LUXELM *r_next;
alpar@1
   144
      /* pointer to next element in the same row */
alpar@1
   145
      LUXELM *c_prev;
alpar@1
   146
      /* pointer to previous element in the same column */
alpar@1
   147
      LUXELM *c_next;
alpar@1
   148
      /* pointer to next element in the same column */
alpar@1
   149
};
alpar@1
   150
alpar@1
   151
struct LUXWKA
alpar@1
   152
{     /* working area (used only during factorization) */
alpar@1
   153
      /* in order to efficiently implement Markowitz strategy and Duff
alpar@1
   154
         search technique there are two families {R[0], R[1], ..., R[n]}
alpar@1
   155
         and {C[0], C[1], ..., C[n]}; member R[k] is a set of active
alpar@1
   156
         rows of matrix V having k non-zeros, and member C[k] is a set
alpar@1
   157
         of active columns of matrix V having k non-zeros (in the active
alpar@1
   158
         submatrix); each set R[k] and C[k] is implemented as a separate
alpar@1
   159
         doubly linked list */
alpar@1
   160
      int *R_len; /* int R_len[1+n]; */
alpar@1
   161
      /* R_len[0] is not used;
alpar@1
   162
         R_len[i], 1 <= i <= n, is the number of non-zero elements in
alpar@1
   163
         i-th row of matrix V (that is the length of i-th row) */
alpar@1
   164
      int *R_head; /* int R_head[1+n]; */
alpar@1
   165
      /* R_head[k], 0 <= k <= n, is the number of a first row, which is
alpar@1
   166
         active and whose length is k */
alpar@1
   167
      int *R_prev; /* int R_prev[1+n]; */
alpar@1
   168
      /* R_prev[0] is not used;
alpar@1
   169
         R_prev[i], 1 <= i <= n, is the number of a previous row, which
alpar@1
   170
         is active and has the same length as i-th row */
alpar@1
   171
      int *R_next; /* int R_next[1+n]; */
alpar@1
   172
      /* R_prev[0] is not used;
alpar@1
   173
         R_prev[i], 1 <= i <= n, is the number of a next row, which is
alpar@1
   174
         active and has the same length as i-th row */
alpar@1
   175
      int *C_len; /* int C_len[1+n]; */
alpar@1
   176
      /* C_len[0] is not used;
alpar@1
   177
         C_len[j], 1 <= j <= n, is the number of non-zero elements in
alpar@1
   178
         j-th column of the active submatrix of matrix V (that is the
alpar@1
   179
         length of j-th column in the active submatrix) */
alpar@1
   180
      int *C_head; /* int C_head[1+n]; */
alpar@1
   181
      /* C_head[k], 0 <= k <= n, is the number of a first column, which
alpar@1
   182
         is active and whose length is k */
alpar@1
   183
      int *C_prev; /* int C_prev[1+n]; */
alpar@1
   184
      /* C_prev[0] is not used;
alpar@1
   185
         C_prev[j], 1 <= j <= n, is the number of a previous column,
alpar@1
   186
         which is active and has the same length as j-th column */
alpar@1
   187
      int *C_next; /* int C_next[1+n]; */
alpar@1
   188
      /* C_next[0] is not used;
alpar@1
   189
         C_next[j], 1 <= j <= n, is the number of a next column, which
alpar@1
   190
         is active and has the same length as j-th column */
alpar@1
   191
};
alpar@1
   192
alpar@1
   193
#define lux_create            _glp_lux_create
alpar@1
   194
#define lux_decomp            _glp_lux_decomp
alpar@1
   195
#define lux_f_solve           _glp_lux_f_solve
alpar@1
   196
#define lux_v_solve           _glp_lux_v_solve
alpar@1
   197
#define lux_solve             _glp_lux_solve
alpar@1
   198
#define lux_delete            _glp_lux_delete
alpar@1
   199
alpar@1
   200
LUX *lux_create(int n);
alpar@1
   201
/* create LU-factorization */
alpar@1
   202
alpar@1
   203
int lux_decomp(LUX *lux, int (*col)(void *info, int j, int ind[],
alpar@1
   204
      mpq_t val[]), void *info);
alpar@1
   205
/* compute LU-factorization */
alpar@1
   206
alpar@1
   207
void lux_f_solve(LUX *lux, int tr, mpq_t x[]);
alpar@1
   208
/* solve system F*x = b or F'*x = b */
alpar@1
   209
alpar@1
   210
void lux_v_solve(LUX *lux, int tr, mpq_t x[]);
alpar@1
   211
/* solve system V*x = b or V'*x = b */
alpar@1
   212
alpar@1
   213
void lux_solve(LUX *lux, int tr, mpq_t x[]);
alpar@1
   214
/* solve system A*x = b or A'*x = b */
alpar@1
   215
alpar@1
   216
void lux_delete(LUX *lux);
alpar@1
   217
/* delete LU-factorization */
alpar@1
   218
alpar@1
   219
#endif
alpar@1
   220
alpar@1
   221
/* eof */