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 */ |
---|