You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

211 lines
7.8 KiB

/* scf.h (sparse updatable Schur-complement-based factorization) */
/***********************************************************************
* This code is part of GLPK (GNU Linear Programming Kit).
*
* Copyright (C) 2013-2014 Andrew Makhorin, Department for Applied
* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
* reserved. E-mail: <mao@gnu.org>.
*
* GLPK is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GLPK is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
* License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
***********************************************************************/
#ifndef SCF_H
#define SCF_H
#include "btf.h"
#include "ifu.h"
#include "luf.h"
/***********************************************************************
* The structure SCF describes sparse updatable factorization based on
* Schur complement.
*
* The SCF-factorization has the following format:
*
* ( A A1~ ) ( A0 A1 ) ( R0 ) ( S0 S )
* ( ) = P ( ) Q = P ( ) ( ) Q, (1)
* ( A2~ A3~ ) ( A2 A3 ) ( R I ) ( C )
*
* where:
*
* A is current (unsymmetric) square matrix (not stored);
*
* A1~, A2~, A3~ are some additional matrices (not stored);
*
* A0 is initial (unsymmetric) square matrix (not stored);
*
* A1, A2, A3 are some additional matrices (not stored);
*
* R0 and S0 are matrices that define factorization of the initial
* matrix A0 = R0 * S0 (stored in an invertable form);
*
* R is a matrix defined from R * S0 = A2, so R = A2 * inv(S0) (stored
* in row-wise sparse format);
*
* S is a matrix defined from R0 * S = A1, so S = inv(R0) * A1 (stored
* in column-wise sparse format);
*
* C is Schur complement (to matrix A0) defined from R * S + C = A3,
* so C = A3 - R * S = A3 - A2 * inv(A0) * A1 (stored in an invertable
* form).
*
* P, Q are permutation matrices (stored in both row- and column-like
* formats). */
typedef struct SCF SCF;
struct SCF
{ /* Schur-complement-based factorization */
int n;
/* order of current matrix A */
/*--------------------------------------------------------------*/
/* initial matrix A0 = R0 * S0 of order n0 in invertable form */
int n0;
/* order of matrix A0 */
int type;
/* type of factorization used:
* 1 - LU-factorization (R0 = F0, S0 = V0)
* 2 - BT-factorization (R0 = I, S0 = A0) */
union
{ LUF *luf; /* type = 1 */
BTF *btf; /* type = 2 */
} a0;
/* factorization of matrix A0 */
/*--------------------------------------------------------------*/
/* augmented matrix (A0, A1; A2, A3) of order n0+nn */
int nn_max;
/* maximal number of additional rows and columns in the augmented
* matrix (this limits the number of updates) */
int nn;
/* current number of additional rows and columns in the augmented
* matrix, 0 <= nn <= nn_max */
SVA *sva;
/* associated sparse vector area (SVA) used to store rows of
* matrix R and columns of matrix S */
/*--------------------------------------------------------------*/
/* nn*n0-matrix R in row-wise format */
int rr_ref;
/* reference number of sparse vector in SVA, which is the first
* row of matrix R */
#if 0 + 0
int *rr_ptr = &sva->ptr[rr_ref-1];
/* rr_ptr[0] is not used;
* rr_ptr[i], 1 <= i <= nn, is pointer to i-th row in SVA;
* rr_ptr[nn+1,...,nn_max] are reserved locations */
int *rr_len = &sva->len[rr_ref-1];
/* rr_len[0] is not used;
* rr_len[i], 1 <= i <= nn, is length of i-th row;
* rr_len[nn+1,...,nn_max] are reserved locations */
#endif
/*--------------------------------------------------------------*/
/* n0*nn-matrix S in column-wise format */
int ss_ref;
/* reference number of sparse vector in SVA, which is the first
* column of matrix S */
#if 0 + 0
int *ss_ptr = &sva->ptr[ss_ref-1];
/* ss_ptr[0] is not used;
* ss_ptr[j], 1 <= j <= nn, is pointer to j-th column in SVA;
* ss_ptr[nn+1,...,nn_max] are reserved locations */
int *ss_len = &sva->len[ss_ref-1];
/* ss_len[0] is not used;
* ss_len[j], 1 <= j <= nn, is length of j-th column;
* ss_len[nn+1,...,nn_max] are reserved locations */
#endif
/*--------------------------------------------------------------*/
/* Schur complement C of order nn in invertable form */
IFU ifu;
/* IFU-factorization of matrix C */
/*--------------------------------------------------------------*/
/* permutation matrix P of order n0+nn */
int *pp_ind; /* int pp_ind[1+n0+nn_max]; */
/* pp_ind[i] = j means that P[i,j] = 1 */
int *pp_inv; /* int pp_inv[1+n0+nn_max]; */
/* pp_inv[j] = i means that P[i,j] = 1 */
/*--------------------------------------------------------------*/
/* permutation matrix Q of order n0+nn */
int *qq_ind; /* int qq_ind[1+n0+nn_max]; */
/* qq_ind[i] = j means that Q[i,j] = 1 */
int *qq_inv; /* int qq_inv[1+n0+nn_max]; */
/* qq_inv[j] = i means that Q[i,j] = 1 */
};
#define scf_swap_q_cols(j1, j2) \
do \
{ int i1, i2; \
i1 = qq_inv[j1], i2 = qq_inv[j2]; \
qq_ind[i1] = j2, qq_inv[j2] = i1; \
qq_ind[i2] = j1, qq_inv[j1] = i2; \
} while (0)
/* swap columns j1 and j2 of permutation matrix Q */
#define scf_r0_solve _glp_scf_r0_solve
void scf_r0_solve(SCF *scf, int tr, double x[/*1+n0*/]);
/* solve system R0 * x = b or R0'* x = b */
#define scf_s0_solve _glp_scf_s0_solve
void scf_s0_solve(SCF *scf, int tr, double x[/*1+n0*/],
double w1[/*1+n0*/], double w2[/*1+n0*/], double w3[/*1+n0*/]);
/* solve system S0 * x = b or S0'* x = b */
#define scf_r_prod _glp_scf_r_prod
void scf_r_prod(SCF *scf, double y[/*1+nn*/], double a, const double
x[/*1+n0*/]);
/* compute product y := y + alpha * R * x */
#define scf_rt_prod _glp_scf_rt_prod
void scf_rt_prod(SCF *scf, double y[/*1+n0*/], double a, const double
x[/*1+nn*/]);
/* compute product y := y + alpha * R'* x */
#define scf_s_prod _glp_scf_s_prod
void scf_s_prod(SCF *scf, double y[/*1+n0*/], double a, const double
x[/*1+nn*/]);
/* compute product y := y + alpha * S * x */
#define scf_st_prod _glp_scf_st_prod
void scf_st_prod(SCF *scf, double y[/*1+nn*/], double a, const double
x[/*1+n0*/]);
/* compute product y := y + alpha * S'* x */
#define scf_a_solve _glp_scf_a_solve
void scf_a_solve(SCF *scf, double x[/*1+n*/],
double w[/*1+n0+nn*/], double work1[/*1+max(n0,nn)*/],
double work2[/*1+n*/], double work3[/*1+n*/]);
/* solve system A * x = b */
#define scf_at_solve _glp_scf_at_solve
void scf_at_solve(SCF *scf, double x[/*1+n*/],
double w[/*1+n0+nn*/], double work1[/*1+max(n0,nn)*/],
double work2[/*1+n*/], double work3[/*1+n*/]);
/* solve system A'* x = b */
#define scf_add_r_row _glp_scf_add_r_row
void scf_add_r_row(SCF *scf, const double w[/*1+n0*/]);
/* add new row to matrix R */
#define scf_add_s_col _glp_scf_add_s_col
void scf_add_s_col(SCF *scf, const double v[/*1+n0*/]);
/* add new column to matrix S */
#define scf_update_aug _glp_scf_update_aug
int scf_update_aug(SCF *scf, double b[/*1+n0*/], double d[/*1+n0*/],
double f[/*1+nn*/], double g[/*1+nn*/], double h, int upd,
double w1[/*1+n0*/], double w2[/*1+n0*/], double w3[/*1+n0*/]);
/* update factorization of augmented matrix */
#endif
/* eof */