1 #ifndef _LILC_MATRIX_ILDL_H_ 2 #define _LILC_MATRIX_ILDL_H_ 9 template <
class el_type>
14 const int ncols = n_cols();
17 if (fill_factor > 1e4) lfil = ncols;
18 else lfil = 2*fill_factor*nnz()/ncols;
20 const el_type alpha = (1.0+sqrt(17.0))/8.0;
21 el_type w1(-1), wr(-1), d1(-1), dr(-1);
22 el_type det_D, D_inv11, D_inv22, D_inv12;
25 vector<bool> in_set(ncols,
false);
28 elt_vector_type work(ncols, 0), temp(ncols, 0);
29 idx_vector_type curr_nnzs, temp_nnzs;
30 curr_nnzs.reserve(ncols);
33 int i, j, k, r, offset, col_size, col_size2(-1);
34 bool size_two_piv =
false;
41 for (k = 0; k < ncols; k++) {
45 curr_nnzs.assign (m_idx[k].begin(), m_idx[k].end());
48 for (j = 0; j < (int) curr_nnzs.size(); j++) {
49 work[curr_nnzs[j]] = m_x[k][j];
51 sort(curr_nnzs.begin(), curr_nnzs.end());
58 update(k, work, curr_nnzs, L, D, in_set);
66 w1 = max(work, curr_nnzs, r);
68 if (piv_type == pivot_type::BKP) {
74 for (i = 0; i < (int) curr_nnzs.size(); i++) {
75 if (abs(work[curr_nnzs[i]])-pp_tol*w1 > eps ) {
87 }
else if ( (alpha * w1 - abs(d1)) < eps ) {
96 offset = row_first[r];
99 for (j = offset; j < (int) list[r].size(); j++) {
100 temp_nnzs.push_back(list[r][j]);
101 temp[list[r][j]] = coeff(r, list[r][j]);
105 temp_nnzs.insert(temp_nnzs.end(), m_idx[r].begin(), m_idx[r].end());
108 for (j = 0; j < (int) m_idx[r].size(); j++) {
109 temp[m_idx[r][j]] = m_x[r][j];
114 update(r, temp, temp_nnzs, L, D, in_set);
120 wr = max(temp, temp_nnzs, j);
122 if ((alpha*w1*w1 - abs(d1)*wr) < eps) {
125 }
else if ( (alpha * wr - abs(dr)) < eps) {
131 pivot(s, in_set, L, k, r);
136 std::swap(perm[k], perm[r]);
139 std::swap(work[k], work[r]);
141 curr_nnzs.swap(temp_nnzs);
143 safe_swap(curr_nnzs, k, r);
165 pivot(s, in_set, L, k+1, r);
170 std::swap(perm[k+1], perm[r]);
173 std::swap(work[k+1], work[r]);
174 std::swap(temp[k+1], temp[r]);
177 safe_swap(curr_nnzs, k+1, r);
178 safe_swap(temp_nnzs, k+1, r);
186 }
else if (piv_type == pivot_type::ROOK) {
191 if (alpha * w1 <= abs(d1) + eps) {
196 for (idx_it it = temp_nnzs.begin(); it != temp_nnzs.end(); it++) {
201 offset = row_first[r];
204 for (j = offset; j < (int) list[r].size(); j++) {
205 temp_nnzs.push_back(list[r][j]);
206 temp[list[r][j]] = coeff(r, list[r][j]);
210 temp_nnzs.insert(temp_nnzs.end(), m_idx[r].begin(), m_idx[r].end());
213 for (j = 0; j < (int) m_idx[r].size(); j++) {
214 temp[m_idx[r][j]] = m_x[r][j];
219 update(r, temp, temp_nnzs, L, D, in_set);
225 wr = max(temp, temp_nnzs, j);
228 if (alpha * wr <= abs(dr) + eps) {
230 pivot(s, in_set, L, k, r);
232 std::swap(perm[k], perm[r]);
234 std::swap(temp[k], temp[r]);
237 safe_swap(temp_nnzs, k, r);
238 curr_nnzs.swap(temp_nnzs);
242 }
else if (abs(w1 - wr) < eps) {
247 pivot(s, in_set, L, k, i);
252 std::swap(perm[k], perm[i]);
255 std::swap(work[k], work[i]);
256 std::swap(temp[k], temp[i]);
259 safe_swap(curr_nnzs, k, i);
260 safe_swap(temp_nnzs, k, i);
270 pivot(s, in_set, L, k+1, r);
275 std::swap(perm[k+1], perm[r]);
278 std::swap(work[k+1], work[r]);
279 std::swap(temp[k+1], temp[r]);
282 safe_swap(curr_nnzs, k+1, r);
283 safe_swap(temp_nnzs, k+1, r);
293 curr_nnzs.swap(temp_nnzs);
301 curr_nnzs.erase(std::remove(curr_nnzs.begin(), curr_nnzs.end(), k), curr_nnzs.end());
306 drop_tol(work, curr_nnzs, lfil, tol);
310 temp_nnzs.erase(std::remove(temp_nnzs.begin(), temp_nnzs.end(), k), temp_nnzs.end());
311 curr_nnzs.erase(std::remove(curr_nnzs.begin(), curr_nnzs.end(), k+1), curr_nnzs.end());
312 temp_nnzs.erase(std::remove(temp_nnzs.begin(), temp_nnzs.end(), k+1), temp_nnzs.end());
315 det_D = d1*dr - work[k+1]*work[k+1];
316 if ( abs(det_D) < eps) det_D = 1e-6;
319 D_inv12 = -work[k+1]/det_D;
326 unordered_inplace_union(curr_nnzs, temp_nnzs.begin(), temp_nnzs.end(), in_set);
330 for (idx_it it = curr_nnzs.begin(); it != curr_nnzs.end(); it++) {
331 l_11 = work[*it]*D_inv11 + temp[*it]*D_inv12;
332 l_12 = work[*it]*D_inv12 + temp[*it]*D_inv22;
341 temp_nnzs.assign(curr_nnzs.begin(), curr_nnzs.end());
344 drop_tol(temp, temp_nnzs, lfil, tol);
345 drop_tol(work, curr_nnzs, lfil, tol);
351 L.
m_idx[k].resize(curr_nnzs.size()+1);
352 L.
m_x[k].resize(curr_nnzs.size()+1);
363 if ( abs(D[k]) < eps) D[k] = 1e-6;
365 for (idx_it it = curr_nnzs.begin(); it != curr_nnzs.end(); it++) {
366 if ( abs(work[*it]) > eps) {
368 L.
m_x[k][i] = work[*it]/D[k];
370 L.
list[*it].push_back(k);
383 L.
m_idx[k+1].resize(temp_nnzs.size()+1);
384 L.
m_x[k+1].resize(temp_nnzs.size()+1);
388 L.
m_idx[k+1][0] = k+1;
392 for (idx_it it = curr_nnzs.begin(); it != curr_nnzs.end(); it++) {
393 if ( abs(work[*it]) > eps) {
394 L.
m_x[k][i] = work[*it];
397 L.
list[*it].push_back(k);
405 for (idx_it it = temp_nnzs.begin(); it != temp_nnzs.end(); it++) {
406 if ( abs(temp[*it]) > eps) {
407 L.
m_x[k+1][j] = temp[*it];
408 L.
m_idx[k+1][j] = *it;
410 L.
list[*it].push_back(k+1);
435 for (idx_it it = curr_nnzs.begin(); it != curr_nnzs.end(); it++) {
440 for (idx_it it = temp_nnzs.begin(); it != temp_nnzs.end(); it++) {
448 L.
m_x[k].resize(col_size);
449 L.
m_idx[k].resize(col_size);
452 L.
m_x[k+1].resize(col_size2);
453 L.
m_idx[k+1].resize(col_size2);
456 size_two_piv =
false;
int nnz_count
Number of nonzeros in the matrix.
Definition: lil_sparse_matrix.h:32
el_type & off_diagonal(int i)
Definition: block_diag_matrix.h:114
vector< elt_vector_type > m_x
The values of the nonzeros in the matrix.
Definition: lil_sparse_matrix.h:36
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
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
void advance_first(const int &k)
Updates A.first for iteration k.
Definition: lilc_matrix_declarations.h:328
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 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< 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
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' factorization of this matrix.
Definition: lilc_matrix_ildl.h:10