lemon-project-template-glpk

view deps/glpk/src/glplpf.c @ 9:33de93886c88

Import GLPK 4.47
author Alpar Juttner <alpar@cs.elte.hu>
date Sun, 06 Nov 2011 20:59:10 +0100
parents
children
line source
1 /* glplpf.c (LP basis factorization, Schur complement version) */
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, 2011 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 ***********************************************************************/
25 #include "glplpf.h"
26 #include "glpenv.h"
27 #define xfault xerror
29 #define _GLPLPF_DEBUG 0
31 /* CAUTION: DO NOT CHANGE THE LIMIT BELOW */
33 #define M_MAX 100000000 /* = 100*10^6 */
34 /* maximal order of the basis matrix */
36 /***********************************************************************
37 * NAME
38 *
39 * lpf_create_it - create LP basis factorization
40 *
41 * SYNOPSIS
42 *
43 * #include "glplpf.h"
44 * LPF *lpf_create_it(void);
45 *
46 * DESCRIPTION
47 *
48 * The routine lpf_create_it creates a program object, which represents
49 * a factorization of LP basis.
50 *
51 * RETURNS
52 *
53 * The routine lpf_create_it returns a pointer to the object created. */
55 LPF *lpf_create_it(void)
56 { LPF *lpf;
57 #if _GLPLPF_DEBUG
58 xprintf("lpf_create_it: warning: debug mode enabled\n");
59 #endif
60 lpf = xmalloc(sizeof(LPF));
61 lpf->valid = 0;
62 lpf->m0_max = lpf->m0 = 0;
63 lpf->luf = luf_create_it();
64 lpf->m = 0;
65 lpf->B = NULL;
66 lpf->n_max = 50;
67 lpf->n = 0;
68 lpf->R_ptr = lpf->R_len = NULL;
69 lpf->S_ptr = lpf->S_len = NULL;
70 lpf->scf = NULL;
71 lpf->P_row = lpf->P_col = NULL;
72 lpf->Q_row = lpf->Q_col = NULL;
73 lpf->v_size = 1000;
74 lpf->v_ptr = 0;
75 lpf->v_ind = NULL;
76 lpf->v_val = NULL;
77 lpf->work1 = lpf->work2 = NULL;
78 return lpf;
79 }
81 /***********************************************************************
82 * NAME
83 *
84 * lpf_factorize - compute LP basis factorization
85 *
86 * SYNOPSIS
87 *
88 * #include "glplpf.h"
89 * int lpf_factorize(LPF *lpf, int m, const int bh[], int (*col)
90 * (void *info, int j, int ind[], double val[]), void *info);
91 *
92 * DESCRIPTION
93 *
94 * The routine lpf_factorize computes the factorization of the basis
95 * matrix B specified by the routine col.
96 *
97 * The parameter lpf specified the basis factorization data structure
98 * created with the routine lpf_create_it.
99 *
100 * The parameter m specifies the order of B, m > 0.
101 *
102 * The array bh specifies the basis header: bh[j], 1 <= j <= m, is the
103 * number of j-th column of B in some original matrix. The array bh is
104 * optional and can be specified as NULL.
105 *
106 * The formal routine col specifies the matrix B to be factorized. To
107 * obtain j-th column of A the routine lpf_factorize calls the routine
108 * col with the parameter j (1 <= j <= n). In response the routine col
109 * should store row indices and numerical values of non-zero elements
110 * of j-th column of B to locations ind[1,...,len] and val[1,...,len],
111 * respectively, where len is the number of non-zeros in j-th column
112 * returned on exit. Neither zero nor duplicate elements are allowed.
113 *
114 * The parameter info is a transit pointer passed to the routine col.
115 *
116 * RETURNS
117 *
118 * 0 The factorization has been successfully computed.
119 *
120 * LPF_ESING
121 * The specified matrix is singular within the working precision.
122 *
123 * LPF_ECOND
124 * The specified matrix is ill-conditioned.
125 *
126 * For more details see comments to the routine luf_factorize. */
128 int lpf_factorize(LPF *lpf, int m, const int bh[], int (*col)
129 (void *info, int j, int ind[], double val[]), void *info)
130 { int k, ret;
131 #if _GLPLPF_DEBUG
132 int i, j, len, *ind;
133 double *B, *val;
134 #endif
135 xassert(bh == bh);
136 if (m < 1)
137 xfault("lpf_factorize: m = %d; invalid parameter\n", m);
138 if (m > M_MAX)
139 xfault("lpf_factorize: m = %d; matrix too big\n", m);
140 lpf->m0 = lpf->m = m;
141 /* invalidate the factorization */
142 lpf->valid = 0;
143 /* allocate/reallocate arrays, if necessary */
144 if (lpf->R_ptr == NULL)
145 lpf->R_ptr = xcalloc(1+lpf->n_max, sizeof(int));
146 if (lpf->R_len == NULL)
147 lpf->R_len = xcalloc(1+lpf->n_max, sizeof(int));
148 if (lpf->S_ptr == NULL)
149 lpf->S_ptr = xcalloc(1+lpf->n_max, sizeof(int));
150 if (lpf->S_len == NULL)
151 lpf->S_len = xcalloc(1+lpf->n_max, sizeof(int));
152 if (lpf->scf == NULL)
153 lpf->scf = scf_create_it(lpf->n_max);
154 if (lpf->v_ind == NULL)
155 lpf->v_ind = xcalloc(1+lpf->v_size, sizeof(int));
156 if (lpf->v_val == NULL)
157 lpf->v_val = xcalloc(1+lpf->v_size, sizeof(double));
158 if (lpf->m0_max < m)
159 { if (lpf->P_row != NULL) xfree(lpf->P_row);
160 if (lpf->P_col != NULL) xfree(lpf->P_col);
161 if (lpf->Q_row != NULL) xfree(lpf->Q_row);
162 if (lpf->Q_col != NULL) xfree(lpf->Q_col);
163 if (lpf->work1 != NULL) xfree(lpf->work1);
164 if (lpf->work2 != NULL) xfree(lpf->work2);
165 lpf->m0_max = m + 100;
166 lpf->P_row = xcalloc(1+lpf->m0_max+lpf->n_max, sizeof(int));
167 lpf->P_col = xcalloc(1+lpf->m0_max+lpf->n_max, sizeof(int));
168 lpf->Q_row = xcalloc(1+lpf->m0_max+lpf->n_max, sizeof(int));
169 lpf->Q_col = xcalloc(1+lpf->m0_max+lpf->n_max, sizeof(int));
170 lpf->work1 = xcalloc(1+lpf->m0_max+lpf->n_max, sizeof(double));
171 lpf->work2 = xcalloc(1+lpf->m0_max+lpf->n_max, sizeof(double));
172 }
173 /* try to factorize the basis matrix */
174 switch (luf_factorize(lpf->luf, m, col, info))
175 { case 0:
176 break;
177 case LUF_ESING:
178 ret = LPF_ESING;
179 goto done;
180 case LUF_ECOND:
181 ret = LPF_ECOND;
182 goto done;
183 default:
184 xassert(lpf != lpf);
185 }
186 /* the basis matrix has been successfully factorized */
187 lpf->valid = 1;
188 #if _GLPLPF_DEBUG
189 /* store the basis matrix for debugging */
190 if (lpf->B != NULL) xfree(lpf->B);
191 xassert(m <= 32767);
192 lpf->B = B = xcalloc(1+m*m, sizeof(double));
193 ind = xcalloc(1+m, sizeof(int));
194 val = xcalloc(1+m, sizeof(double));
195 for (k = 1; k <= m * m; k++)
196 B[k] = 0.0;
197 for (j = 1; j <= m; j++)
198 { len = col(info, j, ind, val);
199 xassert(0 <= len && len <= m);
200 for (k = 1; k <= len; k++)
201 { i = ind[k];
202 xassert(1 <= i && i <= m);
203 xassert(B[(i - 1) * m + j] == 0.0);
204 xassert(val[k] != 0.0);
205 B[(i - 1) * m + j] = val[k];
206 }
207 }
208 xfree(ind);
209 xfree(val);
210 #endif
211 /* B = B0, so there are no additional rows/columns */
212 lpf->n = 0;
213 /* reset the Schur complement factorization */
214 scf_reset_it(lpf->scf);
215 /* P := Q := I */
216 for (k = 1; k <= m; k++)
217 { lpf->P_row[k] = lpf->P_col[k] = k;
218 lpf->Q_row[k] = lpf->Q_col[k] = k;
219 }
220 /* make all SVA locations free */
221 lpf->v_ptr = 1;
222 ret = 0;
223 done: /* return to the calling program */
224 return ret;
225 }
227 /***********************************************************************
228 * The routine r_prod computes the product y := y + alpha * R * x,
229 * where x is a n-vector, alpha is a scalar, y is a m0-vector.
230 *
231 * Since matrix R is available by columns, the product is computed as
232 * a linear combination:
233 *
234 * y := y + alpha * (R[1] * x[1] + ... + R[n] * x[n]),
235 *
236 * where R[j] is j-th column of R. */
238 static void r_prod(LPF *lpf, double y[], double a, const double x[])
239 { int n = lpf->n;
240 int *R_ptr = lpf->R_ptr;
241 int *R_len = lpf->R_len;
242 int *v_ind = lpf->v_ind;
243 double *v_val = lpf->v_val;
244 int j, beg, end, ptr;
245 double t;
246 for (j = 1; j <= n; j++)
247 { if (x[j] == 0.0) continue;
248 /* y := y + alpha * R[j] * x[j] */
249 t = a * x[j];
250 beg = R_ptr[j];
251 end = beg + R_len[j];
252 for (ptr = beg; ptr < end; ptr++)
253 y[v_ind[ptr]] += t * v_val[ptr];
254 }
255 return;
256 }
258 /***********************************************************************
259 * The routine rt_prod computes the product y := y + alpha * R' * x,
260 * where R' is a matrix transposed to R, x is a m0-vector, alpha is a
261 * scalar, y is a n-vector.
262 *
263 * Since matrix R is available by columns, the product components are
264 * computed as inner products:
265 *
266 * y[j] := y[j] + alpha * (j-th column of R) * x
267 *
268 * for j = 1, 2, ..., n. */
270 static void rt_prod(LPF *lpf, double y[], double a, const double x[])
271 { int n = lpf->n;
272 int *R_ptr = lpf->R_ptr;
273 int *R_len = lpf->R_len;
274 int *v_ind = lpf->v_ind;
275 double *v_val = lpf->v_val;
276 int j, beg, end, ptr;
277 double t;
278 for (j = 1; j <= n; j++)
279 { /* t := (j-th column of R) * x */
280 t = 0.0;
281 beg = R_ptr[j];
282 end = beg + R_len[j];
283 for (ptr = beg; ptr < end; ptr++)
284 t += v_val[ptr] * x[v_ind[ptr]];
285 /* y[j] := y[j] + alpha * t */
286 y[j] += a * t;
287 }
288 return;
289 }
291 /***********************************************************************
292 * The routine s_prod computes the product y := y + alpha * S * x,
293 * where x is a m0-vector, alpha is a scalar, y is a n-vector.
294 *
295 * Since matrix S is available by rows, the product components are
296 * computed as inner products:
297 *
298 * y[i] = y[i] + alpha * (i-th row of S) * x
299 *
300 * for i = 1, 2, ..., n. */
302 static void s_prod(LPF *lpf, double y[], double a, const double x[])
303 { int n = lpf->n;
304 int *S_ptr = lpf->S_ptr;
305 int *S_len = lpf->S_len;
306 int *v_ind = lpf->v_ind;
307 double *v_val = lpf->v_val;
308 int i, beg, end, ptr;
309 double t;
310 for (i = 1; i <= n; i++)
311 { /* t := (i-th row of S) * x */
312 t = 0.0;
313 beg = S_ptr[i];
314 end = beg + S_len[i];
315 for (ptr = beg; ptr < end; ptr++)
316 t += v_val[ptr] * x[v_ind[ptr]];
317 /* y[i] := y[i] + alpha * t */
318 y[i] += a * t;
319 }
320 return;
321 }
323 /***********************************************************************
324 * The routine st_prod computes the product y := y + alpha * S' * x,
325 * where S' is a matrix transposed to S, x is a n-vector, alpha is a
326 * scalar, y is m0-vector.
327 *
328 * Since matrix R is available by rows, the product is computed as a
329 * linear combination:
330 *
331 * y := y + alpha * (S'[1] * x[1] + ... + S'[n] * x[n]),
332 *
333 * where S'[i] is i-th row of S. */
335 static void st_prod(LPF *lpf, double y[], double a, const double x[])
336 { int n = lpf->n;
337 int *S_ptr = lpf->S_ptr;
338 int *S_len = lpf->S_len;
339 int *v_ind = lpf->v_ind;
340 double *v_val = lpf->v_val;
341 int i, beg, end, ptr;
342 double t;
343 for (i = 1; i <= n; i++)
344 { if (x[i] == 0.0) continue;
345 /* y := y + alpha * S'[i] * x[i] */
346 t = a * x[i];
347 beg = S_ptr[i];
348 end = beg + S_len[i];
349 for (ptr = beg; ptr < end; ptr++)
350 y[v_ind[ptr]] += t * v_val[ptr];
351 }
352 return;
353 }
355 #if _GLPLPF_DEBUG
356 /***********************************************************************
357 * The routine check_error computes the maximal relative error between
358 * left- and right-hand sides for the system B * x = b (if tr is zero)
359 * or B' * x = b (if tr is non-zero), where B' is a matrix transposed
360 * to B. (This routine is intended for debugging only.) */
362 static void check_error(LPF *lpf, int tr, const double x[],
363 const double b[])
364 { int m = lpf->m;
365 double *B = lpf->B;
366 int i, j;
367 double d, dmax = 0.0, s, t, tmax;
368 for (i = 1; i <= m; i++)
369 { s = 0.0;
370 tmax = 1.0;
371 for (j = 1; j <= m; j++)
372 { if (!tr)
373 t = B[m * (i - 1) + j] * x[j];
374 else
375 t = B[m * (j - 1) + i] * x[j];
376 if (tmax < fabs(t)) tmax = fabs(t);
377 s += t;
378 }
379 d = fabs(s - b[i]) / tmax;
380 if (dmax < d) dmax = d;
381 }
382 if (dmax > 1e-8)
383 xprintf("%s: dmax = %g; relative error too large\n",
384 !tr ? "lpf_ftran" : "lpf_btran", dmax);
385 return;
386 }
387 #endif
389 /***********************************************************************
390 * NAME
391 *
392 * lpf_ftran - perform forward transformation (solve system B*x = b)
393 *
394 * SYNOPSIS
395 *
396 * #include "glplpf.h"
397 * void lpf_ftran(LPF *lpf, double x[]);
398 *
399 * DESCRIPTION
400 *
401 * The routine lpf_ftran performs forward transformation, i.e. solves
402 * the system B*x = b, where B is the basis matrix, x is the vector of
403 * unknowns to be computed, b is the vector of right-hand sides.
404 *
405 * On entry elements of the vector b should be stored in dense format
406 * in locations x[1], ..., x[m], where m is the number of rows. On exit
407 * the routine stores elements of the vector x in the same locations.
408 *
409 * BACKGROUND
410 *
411 * Solution of the system B * x = b can be obtained by solving the
412 * following augmented system:
413 *
414 * ( B F^) ( x ) ( b )
415 * ( ) ( ) = ( )
416 * ( G^ H^) ( y ) ( 0 )
417 *
418 * which, using the main equality, can be written as follows:
419 *
420 * ( L0 0 ) ( U0 R ) ( x ) ( b )
421 * P ( ) ( ) Q ( ) = ( )
422 * ( S I ) ( 0 C ) ( y ) ( 0 )
423 *
424 * therefore,
425 *
426 * ( x ) ( U0 R )-1 ( L0 0 )-1 ( b )
427 * ( ) = Q' ( ) ( ) P' ( )
428 * ( y ) ( 0 C ) ( S I ) ( 0 )
429 *
430 * Thus, computing the solution includes the following steps:
431 *
432 * 1. Compute
433 *
434 * ( f ) ( b )
435 * ( ) = P' ( )
436 * ( g ) ( 0 )
437 *
438 * 2. Solve the system
439 *
440 * ( f1 ) ( L0 0 )-1 ( f ) ( L0 0 ) ( f1 ) ( f )
441 * ( ) = ( ) ( ) => ( ) ( ) = ( )
442 * ( g1 ) ( S I ) ( g ) ( S I ) ( g1 ) ( g )
443 *
444 * from which it follows that:
445 *
446 * { L0 * f1 = f f1 = inv(L0) * f
447 * { =>
448 * { S * f1 + g1 = g g1 = g - S * f1
449 *
450 * 3. Solve the system
451 *
452 * ( f2 ) ( U0 R )-1 ( f1 ) ( U0 R ) ( f2 ) ( f1 )
453 * ( ) = ( ) ( ) => ( ) ( ) = ( )
454 * ( g2 ) ( 0 C ) ( g1 ) ( 0 C ) ( g2 ) ( g1 )
455 *
456 * from which it follows that:
457 *
458 * { U0 * f2 + R * g2 = f1 f2 = inv(U0) * (f1 - R * g2)
459 * { =>
460 * { C * g2 = g1 g2 = inv(C) * g1
461 *
462 * 4. Compute
463 *
464 * ( x ) ( f2 )
465 * ( ) = Q' ( )
466 * ( y ) ( g2 ) */
468 void lpf_ftran(LPF *lpf, double x[])
469 { int m0 = lpf->m0;
470 int m = lpf->m;
471 int n = lpf->n;
472 int *P_col = lpf->P_col;
473 int *Q_col = lpf->Q_col;
474 double *fg = lpf->work1;
475 double *f = fg;
476 double *g = fg + m0;
477 int i, ii;
478 #if _GLPLPF_DEBUG
479 double *b;
480 #endif
481 if (!lpf->valid)
482 xfault("lpf_ftran: the factorization is not valid\n");
483 xassert(0 <= m && m <= m0 + n);
484 #if _GLPLPF_DEBUG
485 /* save the right-hand side vector */
486 b = xcalloc(1+m, sizeof(double));
487 for (i = 1; i <= m; i++) b[i] = x[i];
488 #endif
489 /* (f g) := inv(P) * (b 0) */
490 for (i = 1; i <= m0 + n; i++)
491 fg[i] = ((ii = P_col[i]) <= m ? x[ii] : 0.0);
492 /* f1 := inv(L0) * f */
493 luf_f_solve(lpf->luf, 0, f);
494 /* g1 := g - S * f1 */
495 s_prod(lpf, g, -1.0, f);
496 /* g2 := inv(C) * g1 */
497 scf_solve_it(lpf->scf, 0, g);
498 /* f2 := inv(U0) * (f1 - R * g2) */
499 r_prod(lpf, f, -1.0, g);
500 luf_v_solve(lpf->luf, 0, f);
501 /* (x y) := inv(Q) * (f2 g2) */
502 for (i = 1; i <= m; i++)
503 x[i] = fg[Q_col[i]];
504 #if _GLPLPF_DEBUG
505 /* check relative error in solution */
506 check_error(lpf, 0, x, b);
507 xfree(b);
508 #endif
509 return;
510 }
512 /***********************************************************************
513 * NAME
514 *
515 * lpf_btran - perform backward transformation (solve system B'*x = b)
516 *
517 * SYNOPSIS
518 *
519 * #include "glplpf.h"
520 * void lpf_btran(LPF *lpf, double x[]);
521 *
522 * DESCRIPTION
523 *
524 * The routine lpf_btran performs backward transformation, i.e. solves
525 * the system B'*x = b, where B' is a matrix transposed to the basis
526 * matrix B, x is the vector of unknowns to be computed, b is the vector
527 * of right-hand sides.
528 *
529 * On entry elements of the vector b should be stored in dense format
530 * in locations x[1], ..., x[m], where m is the number of rows. On exit
531 * the routine stores elements of the vector x in the same locations.
532 *
533 * BACKGROUND
534 *
535 * Solution of the system B' * x = b, where B' is a matrix transposed
536 * to B, can be obtained by solving the following augmented system:
537 *
538 * ( B F^)T ( x ) ( b )
539 * ( ) ( ) = ( )
540 * ( G^ H^) ( y ) ( 0 )
541 *
542 * which, using the main equality, can be written as follows:
543 *
544 * T ( U0 R )T ( L0 0 )T T ( x ) ( b )
545 * Q ( ) ( ) P ( ) = ( )
546 * ( 0 C ) ( S I ) ( y ) ( 0 )
547 *
548 * or, equivalently, as follows:
549 *
550 * ( U'0 0 ) ( L'0 S') ( x ) ( b )
551 * Q' ( ) ( ) P' ( ) = ( )
552 * ( R' C') ( 0 I ) ( y ) ( 0 )
553 *
554 * therefore,
555 *
556 * ( x ) ( L'0 S')-1 ( U'0 0 )-1 ( b )
557 * ( ) = P ( ) ( ) Q ( )
558 * ( y ) ( 0 I ) ( R' C') ( 0 )
559 *
560 * Thus, computing the solution includes the following steps:
561 *
562 * 1. Compute
563 *
564 * ( f ) ( b )
565 * ( ) = Q ( )
566 * ( g ) ( 0 )
567 *
568 * 2. Solve the system
569 *
570 * ( f1 ) ( U'0 0 )-1 ( f ) ( U'0 0 ) ( f1 ) ( f )
571 * ( ) = ( ) ( ) => ( ) ( ) = ( )
572 * ( g1 ) ( R' C') ( g ) ( R' C') ( g1 ) ( g )
573 *
574 * from which it follows that:
575 *
576 * { U'0 * f1 = f f1 = inv(U'0) * f
577 * { =>
578 * { R' * f1 + C' * g1 = g g1 = inv(C') * (g - R' * f1)
579 *
580 * 3. Solve the system
581 *
582 * ( f2 ) ( L'0 S')-1 ( f1 ) ( L'0 S') ( f2 ) ( f1 )
583 * ( ) = ( ) ( ) => ( ) ( ) = ( )
584 * ( g2 ) ( 0 I ) ( g1 ) ( 0 I ) ( g2 ) ( g1 )
585 *
586 * from which it follows that:
587 *
588 * { L'0 * f2 + S' * g2 = f1
589 * { => f2 = inv(L'0) * ( f1 - S' * g2)
590 * { g2 = g1
591 *
592 * 4. Compute
593 *
594 * ( x ) ( f2 )
595 * ( ) = P ( )
596 * ( y ) ( g2 ) */
598 void lpf_btran(LPF *lpf, double x[])
599 { int m0 = lpf->m0;
600 int m = lpf->m;
601 int n = lpf->n;
602 int *P_row = lpf->P_row;
603 int *Q_row = lpf->Q_row;
604 double *fg = lpf->work1;
605 double *f = fg;
606 double *g = fg + m0;
607 int i, ii;
608 #if _GLPLPF_DEBUG
609 double *b;
610 #endif
611 if (!lpf->valid)
612 xfault("lpf_btran: the factorization is not valid\n");
613 xassert(0 <= m && m <= m0 + n);
614 #if _GLPLPF_DEBUG
615 /* save the right-hand side vector */
616 b = xcalloc(1+m, sizeof(double));
617 for (i = 1; i <= m; i++) b[i] = x[i];
618 #endif
619 /* (f g) := Q * (b 0) */
620 for (i = 1; i <= m0 + n; i++)
621 fg[i] = ((ii = Q_row[i]) <= m ? x[ii] : 0.0);
622 /* f1 := inv(U'0) * f */
623 luf_v_solve(lpf->luf, 1, f);
624 /* g1 := inv(C') * (g - R' * f1) */
625 rt_prod(lpf, g, -1.0, f);
626 scf_solve_it(lpf->scf, 1, g);
627 /* g2 := g1 */
628 g = g;
629 /* f2 := inv(L'0) * (f1 - S' * g2) */
630 st_prod(lpf, f, -1.0, g);
631 luf_f_solve(lpf->luf, 1, f);
632 /* (x y) := P * (f2 g2) */
633 for (i = 1; i <= m; i++)
634 x[i] = fg[P_row[i]];
635 #if _GLPLPF_DEBUG
636 /* check relative error in solution */
637 check_error(lpf, 1, x, b);
638 xfree(b);
639 #endif
640 return;
641 }
643 /***********************************************************************
644 * The routine enlarge_sva enlarges the Sparse Vector Area to new_size
645 * locations by reallocating the arrays v_ind and v_val. */
647 static void enlarge_sva(LPF *lpf, int new_size)
648 { int v_size = lpf->v_size;
649 int used = lpf->v_ptr - 1;
650 int *v_ind = lpf->v_ind;
651 double *v_val = lpf->v_val;
652 xassert(v_size < new_size);
653 while (v_size < new_size) v_size += v_size;
654 lpf->v_size = v_size;
655 lpf->v_ind = xcalloc(1+v_size, sizeof(int));
656 lpf->v_val = xcalloc(1+v_size, sizeof(double));
657 xassert(used >= 0);
658 memcpy(&lpf->v_ind[1], &v_ind[1], used * sizeof(int));
659 memcpy(&lpf->v_val[1], &v_val[1], used * sizeof(double));
660 xfree(v_ind);
661 xfree(v_val);
662 return;
663 }
665 /***********************************************************************
666 * NAME
667 *
668 * lpf_update_it - update LP basis factorization
669 *
670 * SYNOPSIS
671 *
672 * #include "glplpf.h"
673 * int lpf_update_it(LPF *lpf, int j, int bh, int len, const int ind[],
674 * const double val[]);
675 *
676 * DESCRIPTION
677 *
678 * The routine lpf_update_it updates the factorization of the basis
679 * matrix B after replacing its j-th column by a new vector.
680 *
681 * The parameter j specifies the number of column of B, which has been
682 * replaced, 1 <= j <= m, where m is the order of B.
683 *
684 * The parameter bh specifies the basis header entry for the new column
685 * of B, which is the number of the new column in some original matrix.
686 * This parameter is optional and can be specified as 0.
687 *
688 * Row indices and numerical values of non-zero elements of the new
689 * column of B should be placed in locations ind[1], ..., ind[len] and
690 * val[1], ..., val[len], resp., where len is the number of non-zeros
691 * in the column. Neither zero nor duplicate elements are allowed.
692 *
693 * RETURNS
694 *
695 * 0 The factorization has been successfully updated.
696 *
697 * LPF_ESING
698 * New basis B is singular within the working precision.
699 *
700 * LPF_ELIMIT
701 * Maximal number of additional rows and columns has been reached.
702 *
703 * BACKGROUND
704 *
705 * Let j-th column of the current basis matrix B have to be replaced by
706 * a new column a. This replacement is equivalent to removing the old
707 * j-th column by fixing it at zero and introducing the new column as
708 * follows:
709 *
710 * ( B F^| a )
711 * ( B F^) ( | )
712 * ( ) ---> ( G^ H^| 0 )
713 * ( G^ H^) (-------+---)
714 * ( e'j 0 | 0 )
715 *
716 * where ej is a unit vector with 1 in j-th position which used to fix
717 * the old j-th column of B (at zero). Then using the main equality we
718 * have:
719 *
720 * ( B F^| a ) ( B0 F | f )
721 * ( | ) ( P 0 ) ( | ) ( Q 0 )
722 * ( G^ H^| 0 ) = ( ) ( G H | g ) ( ) =
723 * (-------+---) ( 0 1 ) (-------+---) ( 0 1 )
724 * ( e'j 0 | 0 ) ( v' w'| 0 )
725 *
726 * [ ( B0 F )| ( f ) ] [ ( B0 F ) | ( f ) ]
727 * [ P ( )| P ( ) ] ( Q 0 ) [ P ( ) Q| P ( ) ]
728 * = [ ( G H )| ( g ) ] ( ) = [ ( G H ) | ( g ) ]
729 * [------------+-------- ] ( 0 1 ) [-------------+---------]
730 * [ ( v' w')| 0 ] [ ( v' w') Q| 0 ]
731 *
732 * where:
733 *
734 * ( a ) ( f ) ( f ) ( a )
735 * ( ) = P ( ) => ( ) = P' * ( )
736 * ( 0 ) ( g ) ( g ) ( 0 )
737 *
738 * ( ej ) ( v ) ( v ) ( ej )
739 * ( e'j 0 ) = ( v' w' ) Q => ( ) = Q' ( ) => ( ) = Q ( )
740 * ( 0 ) ( w ) ( w ) ( 0 )
741 *
742 * On the other hand:
743 *
744 * ( B0| F f )
745 * ( P 0 ) (---+------) ( Q 0 ) ( B0 new F )
746 * ( ) ( G | H g ) ( ) = new P ( ) new Q
747 * ( 0 1 ) ( | ) ( 0 1 ) ( new G new H )
748 * ( v'| w' 0 )
749 *
750 * where:
751 * ( G ) ( H g )
752 * new F = ( F f ), new G = ( ), new H = ( ),
753 * ( v') ( w' 0 )
754 *
755 * ( P 0 ) ( Q 0 )
756 * new P = ( ) , new Q = ( ) .
757 * ( 0 1 ) ( 0 1 )
758 *
759 * The factorization structure for the new augmented matrix remains the
760 * same, therefore:
761 *
762 * ( B0 new F ) ( L0 0 ) ( U0 new R )
763 * new P ( ) new Q = ( ) ( )
764 * ( new G new H ) ( new S I ) ( 0 new C )
765 *
766 * where:
767 *
768 * new F = L0 * new R =>
769 *
770 * new R = inv(L0) * new F = inv(L0) * (F f) = ( R inv(L0)*f )
771 *
772 * new G = new S * U0 =>
773 *
774 * ( G ) ( S )
775 * new S = new G * inv(U0) = ( ) * inv(U0) = ( )
776 * ( v') ( v'*inv(U0) )
777 *
778 * new H = new S * new R + new C =>
779 *
780 * new C = new H - new S * new R =
781 *
782 * ( H g ) ( S )
783 * = ( ) - ( ) * ( R inv(L0)*f ) =
784 * ( w' 0 ) ( v'*inv(U0) )
785 *
786 * ( H - S*R g - S*inv(L0)*f ) ( C x )
787 * = ( ) = ( )
788 * ( w'- v'*inv(U0)*R -v'*inv(U0)*inv(L0)*f) ( y' z )
789 *
790 * Note that new C is resulted by expanding old C with new column x,
791 * row y', and diagonal element z, where:
792 *
793 * x = g - S * inv(L0) * f = g - S * (new column of R)
794 *
795 * y = w - R'* inv(U'0)* v = w - R'* (new row of S)
796 *
797 * z = - (new row of S) * (new column of R)
798 *
799 * Finally, to replace old B by new B we have to permute j-th and last
800 * (just added) columns of the matrix
801 *
802 * ( B F^| a )
803 * ( | )
804 * ( G^ H^| 0 )
805 * (-------+---)
806 * ( e'j 0 | 0 )
807 *
808 * and to keep the main equality do the same for matrix Q. */
810 int lpf_update_it(LPF *lpf, int j, int bh, int len, const int ind[],
811 const double val[])
812 { int m0 = lpf->m0;
813 int m = lpf->m;
814 #if _GLPLPF_DEBUG
815 double *B = lpf->B;
816 #endif
817 int n = lpf->n;
818 int *R_ptr = lpf->R_ptr;
819 int *R_len = lpf->R_len;
820 int *S_ptr = lpf->S_ptr;
821 int *S_len = lpf->S_len;
822 int *P_row = lpf->P_row;
823 int *P_col = lpf->P_col;
824 int *Q_row = lpf->Q_row;
825 int *Q_col = lpf->Q_col;
826 int v_ptr = lpf->v_ptr;
827 int *v_ind = lpf->v_ind;
828 double *v_val = lpf->v_val;
829 double *a = lpf->work2; /* new column */
830 double *fg = lpf->work1, *f = fg, *g = fg + m0;
831 double *vw = lpf->work2, *v = vw, *w = vw + m0;
832 double *x = g, *y = w, z;
833 int i, ii, k, ret;
834 xassert(bh == bh);
835 if (!lpf->valid)
836 xfault("lpf_update_it: the factorization is not valid\n");
837 if (!(1 <= j && j <= m))
838 xfault("lpf_update_it: j = %d; column number out of range\n",
839 j);
840 xassert(0 <= m && m <= m0 + n);
841 /* check if the basis factorization can be expanded */
842 if (n == lpf->n_max)
843 { lpf->valid = 0;
844 ret = LPF_ELIMIT;
845 goto done;
846 }
847 /* convert new j-th column of B to dense format */
848 for (i = 1; i <= m; i++)
849 a[i] = 0.0;
850 for (k = 1; k <= len; k++)
851 { i = ind[k];
852 if (!(1 <= i && i <= m))
853 xfault("lpf_update_it: ind[%d] = %d; row number out of rang"
854 "e\n", k, i);
855 if (a[i] != 0.0)
856 xfault("lpf_update_it: ind[%d] = %d; duplicate row index no"
857 "t allowed\n", k, i);
858 if (val[k] == 0.0)
859 xfault("lpf_update_it: val[%d] = %g; zero element not allow"
860 "ed\n", k, val[k]);
861 a[i] = val[k];
862 }
863 #if _GLPLPF_DEBUG
864 /* change column in the basis matrix for debugging */
865 for (i = 1; i <= m; i++)
866 B[(i - 1) * m + j] = a[i];
867 #endif
868 /* (f g) := inv(P) * (a 0) */
869 for (i = 1; i <= m0+n; i++)
870 fg[i] = ((ii = P_col[i]) <= m ? a[ii] : 0.0);
871 /* (v w) := Q * (ej 0) */
872 for (i = 1; i <= m0+n; i++) vw[i] = 0.0;
873 vw[Q_col[j]] = 1.0;
874 /* f1 := inv(L0) * f (new column of R) */
875 luf_f_solve(lpf->luf, 0, f);
876 /* v1 := inv(U'0) * v (new row of S) */
877 luf_v_solve(lpf->luf, 1, v);
878 /* we need at most 2 * m0 available locations in the SVA to store
879 new column of matrix R and new row of matrix S */
880 if (lpf->v_size < v_ptr + m0 + m0)
881 { enlarge_sva(lpf, v_ptr + m0 + m0);
882 v_ind = lpf->v_ind;
883 v_val = lpf->v_val;
884 }
885 /* store new column of R */
886 R_ptr[n+1] = v_ptr;
887 for (i = 1; i <= m0; i++)
888 { if (f[i] != 0.0)
889 v_ind[v_ptr] = i, v_val[v_ptr] = f[i], v_ptr++;
890 }
891 R_len[n+1] = v_ptr - lpf->v_ptr;
892 lpf->v_ptr = v_ptr;
893 /* store new row of S */
894 S_ptr[n+1] = v_ptr;
895 for (i = 1; i <= m0; i++)
896 { if (v[i] != 0.0)
897 v_ind[v_ptr] = i, v_val[v_ptr] = v[i], v_ptr++;
898 }
899 S_len[n+1] = v_ptr - lpf->v_ptr;
900 lpf->v_ptr = v_ptr;
901 /* x := g - S * f1 (new column of C) */
902 s_prod(lpf, x, -1.0, f);
903 /* y := w - R' * v1 (new row of C) */
904 rt_prod(lpf, y, -1.0, v);
905 /* z := - v1 * f1 (new diagonal element of C) */
906 z = 0.0;
907 for (i = 1; i <= m0; i++) z -= v[i] * f[i];
908 /* update factorization of new matrix C */
909 switch (scf_update_exp(lpf->scf, x, y, z))
910 { case 0:
911 break;
912 case SCF_ESING:
913 lpf->valid = 0;
914 ret = LPF_ESING;
915 goto done;
916 case SCF_ELIMIT:
917 xassert(lpf != lpf);
918 default:
919 xassert(lpf != lpf);
920 }
921 /* expand matrix P */
922 P_row[m0+n+1] = P_col[m0+n+1] = m0+n+1;
923 /* expand matrix Q */
924 Q_row[m0+n+1] = Q_col[m0+n+1] = m0+n+1;
925 /* permute j-th and last (just added) column of matrix Q */
926 i = Q_col[j], ii = Q_col[m0+n+1];
927 Q_row[i] = m0+n+1, Q_col[m0+n+1] = i;
928 Q_row[ii] = j, Q_col[j] = ii;
929 /* increase the number of additional rows and columns */
930 lpf->n++;
931 xassert(lpf->n <= lpf->n_max);
932 /* the factorization has been successfully updated */
933 ret = 0;
934 done: /* return to the calling program */
935 return ret;
936 }
938 /***********************************************************************
939 * NAME
940 *
941 * lpf_delete_it - delete LP basis factorization
942 *
943 * SYNOPSIS
944 *
945 * #include "glplpf.h"
946 * void lpf_delete_it(LPF *lpf)
947 *
948 * DESCRIPTION
949 *
950 * The routine lpf_delete_it deletes LP basis factorization specified
951 * by the parameter lpf and frees all memory allocated to this program
952 * object. */
954 void lpf_delete_it(LPF *lpf)
955 { luf_delete_it(lpf->luf);
956 #if _GLPLPF_DEBUG
957 if (lpf->B != NULL) xfree(lpf->B);
958 #else
959 xassert(lpf->B == NULL);
960 #endif
961 if (lpf->R_ptr != NULL) xfree(lpf->R_ptr);
962 if (lpf->R_len != NULL) xfree(lpf->R_len);
963 if (lpf->S_ptr != NULL) xfree(lpf->S_ptr);
964 if (lpf->S_len != NULL) xfree(lpf->S_len);
965 if (lpf->scf != NULL) scf_delete_it(lpf->scf);
966 if (lpf->P_row != NULL) xfree(lpf->P_row);
967 if (lpf->P_col != NULL) xfree(lpf->P_col);
968 if (lpf->Q_row != NULL) xfree(lpf->Q_row);
969 if (lpf->Q_col != NULL) xfree(lpf->Q_col);
970 if (lpf->v_ind != NULL) xfree(lpf->v_ind);
971 if (lpf->v_val != NULL) xfree(lpf->v_val);
972 if (lpf->work1 != NULL) xfree(lpf->work1);
973 if (lpf->work2 != NULL) xfree(lpf->work2);
974 xfree(lpf);
975 return;
976 }
978 /* eof */