sym-ildl  1.2
Incomplete LDL' factorizations of indefinite symmetric and skew-symmetric matrices.
lilc_matrix_declarations.h
1 // -*- mode: c++ -*-
2 #ifndef _LILC_MATRIX_DECLARATIONS_H_
3 #define _LILC_MATRIX_DECLARATIONS_H_
4 
5 #include <algorithm>
6 #include <cmath>
7 #include <cassert>
8 #include <iostream>
9 #include <iterator>
10 #include <set>
11 
12 #include "swap_struct.h"
13 
21 template<class el_type>
22 class lilc_matrix : public lil_sparse_matrix<el_type>
23 {
24 public:
25 
26  //-------------- typedefs and inherited variables --------------//
36 
37 
38  typedef typename lil_sparse_matrix<el_type>::idx_vector_type idx_vector_type;
39  typedef typename lil_sparse_matrix<el_type>::elt_vector_type elt_vector_type;
40 
41  typedef typename idx_vector_type::iterator idx_it;
42  typedef typename elt_vector_type::iterator elt_it;
43 
44  std::vector< std::vector< int > > list;
45 
46  std::vector<int> row_first;
47  std::vector<int> col_first;
48 
50 
51  //-------------- types of pivoting procedures ----------------//
54  struct pivot_type {
55  enum {
56  BKP,
57  ROOK
58  };
59  };
60 
61 public:
62 
65  lilc_matrix (int n_rows = 0, int n_cols = 0):
66  lil_sparse_matrix<el_type> (n_rows, n_cols)
67  {
68  m_x.reserve(n_cols);
69  m_idx.reserve(n_cols);
70  }
71 
72  //----Matrix referencing/filling----//
73 
80  inline virtual el_type coeff(const int& i, const int& j, int offset = 0) const
81  {
82  //invariant: first elem in each col of a is the diagonal elem if it exists.
83  if (i == j) {
84  if (m_idx[j].size() == 0) return 0;
85  return (m_idx[j][0] == i ? m_x[j][0] : 0);
86  }
87 
88  for (int k = offset, end = m_idx[j].size(); k < end; k++) {
89  if (m_idx[j][k] == i) return m_x[j][k];
90  }
91 
92  return 0;
93  }
94 
102  inline bool coeffRef(const int& i, const int& j, std::pair<idx_it, elt_it>& its)
103  {
104  for (unsigned int k = 0; k < m_idx[j].size(); k++) {
105  if (m_idx[j][k] == i) {
106  its = make_pair(m_idx[j].begin() + k, m_x[j].begin() + k);
107  return true;
108  }
109  }
110 
111  its = make_pair(m_idx[j].end(), m_x[j].end());
112  return false;
113  }
114 
119  void resize(int n_rows, int n_cols)
120  {
121  m_n_rows = n_rows;
122  m_n_cols = n_cols;
123 
124  m_x.clear();
125  m_idx.clear();
126  row_first.clear();
127  col_first.clear();
128  list.clear();
129 
130  m_x.resize(n_cols);
131  m_idx.resize(n_cols);
132 
133  row_first.resize(n_cols, 1);
134  col_first.resize(n_cols, 1);
135  list.resize(n_cols);
136 
137  S.resize(n_cols, 1);
138  for (int i = 0; i < n_cols; i++) {
139  m_x[i].clear();
140  m_idx[i].clear();
141  list[i].clear();
142  }
143  }
144 
145  //-----Reorderings/Rescalings------//
150  void find_root(int& s);
151 
157  inline bool find_level_set(vector<int>& lvl_set, vector<bool>& visited);
158 
164  void sym_rcm(vector<int>& perm);
165 
171  inline void sym_amd(vector<int>& perm);
172 
176  void sym_perm(vector<int>& perm);
177 
182  void sym_equil();
183 
184  //----Factorizations----//
197  void ildl(lilc_matrix<el_type>& L, block_diag_matrix<el_type>& D, idx_vector_type& perm, const double& fill_factor, const double& tol, const double& pp_tol, int piv_type = pivot_type::BKP);
198 
209  void ildl_inplace(block_diag_matrix<el_type>& D, idx_vector_type& perm, const double& fill_factor, const double& tol, const double& pp_tol, int piv_type = pivot_type::BKP);
210 
211  //------Helpers------//
217  void backsolve(const elt_vector_type& b, elt_vector_type& x) {
218  assert(b.size() == x.size());
219  x = b;
220  // simple forward substitution
221  for (int i = 0; i < m_n_cols; i++) {
222  x[i] /= m_x[i][0];
223  for (int k = 1; k < m_idx[i].size(); k++) {
224  x[m_idx[i][k]] -= x[i]*m_x[i][k];
225  }
226  }
227  }
228 
234  void forwardsolve(const elt_vector_type& b, elt_vector_type& x) {
235  assert(b.size() == x.size());
236  // simple back substitution
237  for (int i = m_n_cols-1; i >= 0; i--) {
238  x[i] = b[i]/m_x[i][0];
239  for (int k = 1; k < m_idx[i].size(); k++) {
240  x[i] -= x[m_idx[i][k]]*m_x[i][k]/m_x[i][0];
241  }
242  }
243  }
244 
251  void multiply(const elt_vector_type& x, elt_vector_type& y, bool full_mult = true) {
252  y.clear(); y.resize(x.size(), 0);
253  for (int i = 0; i < m_n_cols; i++) {
254  for (int k = 0; k < m_idx[i].size(); k++) {
255  y[m_idx[i][k]] += x[i]*m_x[i][k];
256  if (full_mult && i != m_idx[i][k]) {
257  y[i] += x[m_idx[i][k]]*m_x[i][k];
258  }
259  }
260  }
261  }
262 
271  inline void pivot(swap_struct<el_type>& s, vector<bool>& in_set, lilc_matrix<el_type>& L, const int& k, const int& r);
272 
280  inline void pivotA(swap_struct<el_type>& s, vector<bool>& in_set, const int& k, const int& r);
281 
299  template <class Container>
300  inline void ensure_invariant(const int& j, const int& k, Container& con, bool update_list = false) {
301  int offset;
302  if (update_list) offset = row_first[j];
303  else offset = col_first[j];
304 
305  if ((offset >= (int) con.size()) || con.empty() || con[offset] == k) return;
306 
307  int i, min(offset);
308  for (i = offset; i < (int) con.size(); i++) {
309  if (con[i] == k) {
310  min = i;
311  break;
312  } else if ( con[i] < con[min] ) {
313  min = i;
314  }
315  }
316 
317  if (update_list)
318  std::swap(con[offset], con[min]);
319  else {
320  std::swap(con[offset], con[min]);
321  std::swap(m_x[j][offset], m_x[j][min]);
322  }
323  }
324 
328  inline void advance_first(const int& k) {
329  for (idx_it it = list[k].begin(); it != list[k].end(); it++) {
330  ensure_invariant(*it, k, m_idx[*it]); //make sure next element is good before we increment.
331  col_first[*it]++; //should have ensured invariant now
332  }
333  }
334 
338  inline void advance_list(const int& k) {
339  for (idx_it it = m_idx[k].begin(); it != m_idx[k].end(); it++) {
340  if (*it == k) continue;
341  ensure_invariant(*it, k, list[*it], true); //make sure next element is good.
342  row_first[*it]++; //invariant ensured.
343  }
344  }
345 
346  //----IO Functions----//
347 
352  std::string to_string () const;
353 
357  bool load(std::string filename);
358 
364  bool load(const std::vector<int>& ptr, const std::vector<int>& row, const std::vector<el_type>& val);
365 
372  bool load(const int* ptr, const int* row, const el_type* val, int dim);
373 
378  bool save(std::string filename, bool sym = false);
379 
380 };
381 
382 //------------------ include files for class functions -------------------//
383 
384 #include "lilc_matrix_find_level_set.h"
385 #include "lilc_matrix_find_root.h"
386 #include "lilc_matrix_sym_rcm.h"
387 #include "lilc_matrix_sym_amd.h"
388 #include "lilc_matrix_sym_perm.h"
389 #include "lilc_matrix_sym_equil.h"
390 #include "lilc_matrix_ildl_helpers.h"
391 #include "lilc_matrix_ildl.h"
392 #include "lilc_matrix_ildl_inplace.h"
393 #include "lilc_matrix_pivot.h"
394 #include "lilc_matrix_load.h"
395 #include "lilc_matrix_save.h"
396 #include "lilc_matrix_to_string.h"
397 
398 #endif
void advance_list(const int &k)
Updates A.list for iteration k.
Definition: lilc_matrix_declarations.h:338
void sym_amd(vector< int > &perm)
Returns a Approximate Minimum Degree ordering of the matrix A (stored in perm).
Definition: lilc_matrix_sym_amd.h:56
void forwardsolve(const elt_vector_type &b, elt_vector_type &x)
Performs a forward solve of this matrix, assuming that it is upper triangular (stored row major)...
Definition: lilc_matrix_declarations.h:234
bool load(std::string filename)
Loads a matrix in matrix market format.
Definition: lilc_matrix_load.h:24
Definition: lilc_matrix_declarations.h:54
void ildl_inplace(block_diag_matrix< el_type > &D, idx_vector_type &perm, const double &fill_factor, const double &tol, const double &pp_tol, int piv_type=pivot_type::BKP)
Performs an inplace LDL&#39; factorization of this matrix.
Definition: lilc_matrix_ildl_inplace.h:10
void sym_perm(vector< int > &perm)
Given a permutation vector perm, A is permuted to P&#39;AP, where P is the permutation matrix associated ...
Definition: lilc_matrix_sym_perm.h:6
vector< elt_vector_type > m_x
The values of the nonzeros in the matrix.
Definition: lil_sparse_matrix.h:36
block_diag_matrix< el_type > S
A diagonal scaling matrix S such that SAS will be equilibriated in the max-norm (i.e. every row/column has norm 1). S is constructed after running the sym_equil() function, after which SAS will be stored in place of A.
Definition: lilc_matrix_declarations.h:49
vector< idx_vector_type > m_idx
The row/col indices. The way m_idx is used depends on whether the matrix is in LIL-C or LIL-R...
Definition: lil_sparse_matrix.h:35
int m_n_cols
Number of cols in the matrix.
Definition: lil_sparse_matrix.h:31
std::vector< int > row_first
On iteration k, first[i] gives the number of non-zero elements on row i of A before A(i...
Definition: lilc_matrix_declarations.h:46
void sym_equil()
The symmetric matrix A is equilibrated and the symmetric equilibrated matrix SAS is stored in A...
Definition: lilc_matrix_sym_equil.h:8
lilc_matrix(int n_rows=0, int n_cols=0)
Constructor for a column oriented list-of-lists (LIL) matrix. Space for both the values list and the ...
Definition: lilc_matrix_declarations.h:65
void resize(int n, el_type default_value)
Resizes this matrix to an n*n matrix with default_value on the main diagonal.
Definition: block_diag_matrix.h:70
bool coeffRef(const int &i, const int &j, std::pair< idx_it, elt_it > &its)
Finds the index/value pointers to (i,j)th coefficient of the matrix.
Definition: lilc_matrix_declarations.h:102
void advance_first(const int &k)
Updates A.first for iteration k.
Definition: lilc_matrix_declarations.h:328
int n_rows() const
Definition: lil_sparse_matrix.h:46
void pivotA(swap_struct< el_type > &s, vector< bool > &in_set, const int &k, const int &r)
The inplace version of the function above.
Definition: lilc_matrix_pivot.h:68
A list-of-lists (LIL) matrix in column oriented format.
Definition: lilc_matrix.h:9
A quick implementation of a diagonal matrix with 1x1 and 2x2 blocks.
Definition: block_diag_matrix.h:39
A structure containing variables used in pivoting a LIL-C matrix.
Definition: swap_struct.h:6
void sym_rcm(vector< int > &perm)
Returns a Reverse Cuthill-McKee ordering of the matrix A (stored in perm).
Definition: lilc_matrix_sym_rcm.h:27
int m_n_rows
Number of rows in the matrix.
Definition: lil_sparse_matrix.h:28
void multiply(const elt_vector_type &x, elt_vector_type &y, bool full_mult=true)
Performs a matrix-vector product with this matrix.
Definition: lilc_matrix_declarations.h:251
virtual el_type coeff(const int &i, const int &j, int offset=0) const
Finds the (i,j)th coefficient of the matrix.
Definition: lilc_matrix_declarations.h:80
void find_root(int &s)
Returns a pseudo-peripheral root of A. This is essentially many chained breadth-first searchs across ...
Definition: lilc_matrix_find_root.h:6
void resize(int n_rows, int n_cols)
Resizes the matrix. For use in preallocating space before factorization begins.
Definition: lilc_matrix_declarations.h:119
std::vector< int > col_first
On iteration k, first[i] gives the number of non-zero elements on col i of A before A(i...
Definition: lilc_matrix_declarations.h:47
void ensure_invariant(const int &j, const int &k, Container &con, bool update_list=false)
Ensures two the invariants observed by A.first and A.list are held.
Definition: lilc_matrix_declarations.h:300
void pivot(swap_struct< el_type > &s, vector< bool > &in_set, lilc_matrix< el_type > &L, const int &k, const int &r)
Performs a symmetric permutation between row/col k & r of A.
Definition: lilc_matrix_pivot.h:14
std::vector< std::vector< int > > list
A list of linked lists that gives the non-zero elements in each row of A. Since at any time we may sw...
Definition: lilc_matrix_declarations.h:44
The abstract parent of all sparse matrices.
Definition: lil_sparse_matrix.h:15
void ildl(lilc_matrix< el_type > &L, block_diag_matrix< el_type > &D, idx_vector_type &perm, const double &fill_factor, const double &tol, const double &pp_tol, int piv_type=pivot_type::BKP)
Performs an LDL&#39; factorization of this matrix.
Definition: lilc_matrix_ildl.h:10
void backsolve(const elt_vector_type &b, elt_vector_type &x)
Performs a back solve of this matrix, assuming that it is lower triangular (stored column major)...
Definition: lilc_matrix_declarations.h:217
bool find_level_set(vector< int > &lvl_set, vector< bool > &visited)
Returns the next level set given the current level set of A. This is essentially all neighbours of th...
Definition: lilc_matrix_find_level_set.h:6
int n_cols() const
Definition: lil_sparse_matrix.h:52
std::string to_string() const
Returns a string representation of A, with each column and its corresponding indices & non-zero value...
Definition: lilc_matrix_to_string.h:9
bool save(std::string filename, bool sym=false)
Saves a matrix in matrix market format.
Definition: lilc_matrix_save.h:15