sym-ildl  1.2
Incomplete LDL' factorizations of indefinite symmetric and skew-symmetric matrices.
lilc_matrix_pivot.h
1 using std::abs;
2 
13 template <class el_type>
14 inline void lilc_matrix<el_type> :: pivot(swap_struct<el_type>& s, vector<bool>& in_set, lilc_matrix<el_type>& L, const int& k, const int& r) {
15  //initialize temp variables
16  int i, j, idx, offset;
17 
18  //----------pivot A ----------//
19  this->pivotA(s, in_set, k, r);
20  //--------end pivot A---------//
21 
22  //----------pivot L ----------//
23  s.swap_clear();
24 
25  // -------------------- (1) for L ------------------------//
26  //push back pointers to L(k, i)
27  for (idx_it it = L.list[k].begin(); it != L.list[k].end(); it++)
28  {
29  for (i = L.col_first[*it]; i < (int) L.m_idx[*it].size(); i++) {
30  if (L.m_idx[*it][i] == k) {
31  s.swapr.push_back(L.m_idx[*it].begin() + i);
32  break;
33  }
34  }
35  }
36 
37  //push back pointers to L(r, i)
38  for (idx_it it = L.list[r].begin(); it != L.list[r].end(); it++) {
39  for (i = L.col_first[*it]; i < (int) L.m_idx[*it].size(); i++) {
40  if (L.m_idx[*it][i] == r) {
41  s.swapk.push_back(L.m_idx[*it].begin() + i);
42  break;
43  }
44  }
45  }
46 
47  //swap rows k and r
48  for (typename vector<idx_it>::iterator it = s.swapk.begin(); it != s.swapk.end(); it++) {
49  **it = k;
50  }
51  for (typename vector<idx_it>::iterator it = s.swapr.begin(); it != s.swapr.end(); it++) {
52  **it = r;
53  }
54 
55  //row swap on row non-zero indices stored in L.list
56  L.list[k].swap(L.list[r]);
57 
58  //--------end pivot L---------//
59 }
60 
67 template <class el_type>
68 inline void lilc_matrix<el_type> :: pivotA(swap_struct<el_type>& s, vector<bool>& in_set, const int& k, const int& r) {
69  assert(k < r); // this algorithm implicitly assumes k < r
70 
71  //initialize temp variables
72  std::pair<idx_it, elt_it> its_k, its_r;
73  int i, j, idx, offset;
74 
75  //----------- clear out old variables from last pivot -------------- //
76  //for vectors of primitive types, clear is always constant time regardless of how many elements are in the container.
77  s.col_clear();
78  s.row_clear();
79 
80  //----------pivot A ----------//
81  s.swap_clear();
82 
83  //------------- row-row swap (1) for A -------------//
84 
85  //pushes column indices (which contain non-zero elements) of A(k, 1:k) onto row_r
86  for (idx_it it = list[k].begin(); it != list[k].begin() + row_first[k]; ++it) {
87  s.row_r.push_back(*it);
88  }
89 
90  //pushes column indices (which contain non-zero elements) of A(r, 1:k) onto row_k
91  for (idx_it it = list[r].begin(); it != list[r].begin() + row_first[r]; ++it) {
92  s.row_k.push_back(*it);
93  }
94 
95  //merge these two sets of indices together
96  s.all_swaps.assign(list[k].begin(), list[k].begin() + row_first[k]);
97  unordered_inplace_union(s.all_swaps, list[r].begin(), list[r].begin() + row_first[r], in_set);
98 
99  //do row swaps in A (i.e. swap A(k, 1:k) with A(r, 1:k))
100  for (idx_it it = s.all_swaps.begin(), end = s.all_swaps.end(); it != end; ++it) {
101  safe_swap(m_idx[*it], k, r);
102  }
103  s.all_swaps.clear();
104 
105  //----------------------------------------------------//
106 
107 
108  //---------------------- (2) and (3) for A --------------------------//
109 
110  //after sym. perm, a_rr will be swapped to a_kk, so we put a_rr as first
111  //elem of col k if its non-zero. this also means that we ensure the first
112  //elem of col k is the diagonal element if it exists.
113  el_type elem = coeff(r, r);
114  if (abs(elem) > eps){
115  s.col_k_nnzs.push_back(k);
116  s.col_k.push_back(elem);
117  }
118 
119  //same as above, put a_kk in new col r if it exists.
120  elem = coeff(k, k);
121  if (abs(elem) > eps){
122  s.col_r_nnzs.push_back(r);
123  s.col_r.push_back(elem);
124  }
125 
126 
127  //first[r] should have # of nnz of A(r, 0:k-1)
128  for (i = row_first[r]; i < (int) list[r].size(); i++) {
129  j = list[r][i];
130  assert(j >= k);
131  if (coeffRef(r, j, its_k)) {
132  if (j == k) {
133  s.col_k_nnzs.push_back(r); //A(r, k) is fixed upon permutation so its index stays r
134  s.row_r.push_back(k);
135  } else {
136  s.col_k_nnzs.push_back(j); //place A(r, j) (where k < j < r) into A(j, k)
137  }
138  s.col_k.push_back(*its_k.second);
139 
140  //delete A(r,j) from A.
141  *its_k.first = m_idx[j].back();
142  *its_k.second = m_x[j].back();
143 
144  m_idx[j].pop_back();
145  m_x[j].pop_back();
146  }
147  }
148 
149  if (m_idx[r].size() > 0) {
150 
151  //place A(r:n, r) into A(r:n, k). since we already took care of A(r,r) above,
152  //we need to offset by 1 if necessary.
153  ensure_invariant(r, r, m_idx[r], false);
154  offset = (m_idx[r][0] == r ? 1 : 0);
155  std::copy(m_x[r].begin()+offset, m_x[r].end(), std::back_inserter(s.col_k));
156  std::copy(m_idx[r].begin()+offset, m_idx[r].end(), std::back_inserter(s.col_k_nnzs));
157 
158  for (idx_it it = m_idx[r].begin() + offset; it != m_idx[r].end(); it++) {
159 
160  //for each non-zero row index in the rth column, find a pointer to it in list
161  //these pointers will be used to perform column swaps on list
162  for (i = row_first[*it]; i < (int) list[*it].size(); i++) {
163  if (list[*it][i] == r) {
164  s.swapk.push_back(list[*it].begin() + i);
165  break;
166  }
167  }
168  }
169  }
170 
171  //swap A(k:r, k) with A(r, k:r)
172  if (m_idx[k].size() > 0) {
173 
174  //since we already took care of A(k,k), we need an offset of 1 if necessary
175  ensure_invariant(k, k, m_idx[k], false);
176  offset = (m_idx[k][0] == k ? 1 : 0);
177  for (i = offset; i < (int) m_idx[k].size(); i++) {
178  idx = m_idx[k][i];
179 
180  //if idx < r, we are in (2) (row-col swap) otherwise we are in (3) (col-col swap)
181  if (idx < r) {
182 
183  //swap A(i, k) with A(r, i) where k < i < r.
184  m_idx[idx].push_back(r);
185  m_x[idx].push_back(m_x[k][i]);
186 
187  //we also have to ensure that list is updated by popping off old entries
188  //that were meant for the A(i, k)'s before they were swapped.
189  ensure_invariant(idx, k, list[idx], true);
190  std::swap(list[idx][row_first[idx]], list[idx][list[idx].size() - 1]);
191  list[idx].pop_back();
192 
193  //push back new elements on row_r
194  s.row_r.push_back(idx);
195 
196  } else if (idx > r) {
197 
198  //swap A(i, k) with A(i, r) where r < i.
199  s.col_r.push_back(m_x[k][i]);
200  s.col_r_nnzs.push_back(idx);
201 
202  //for each non-zero row index in the kth column, find a pointer to it in list
203  //these pointers will be used to perform column swaps on list
204  for (j = row_first[idx]; j < (int) list[idx].size(); j++) {
205  if (list[idx][j] == k) {
206  s.swapr.push_back(list[idx].begin() + j);
207  break;
208  }
209  }
210  }
211  }
212  }
213 
214  //swap all A(i, k) with A(i, r) in list.
215  for (typename vector<idx_it>::iterator it = s.swapk.begin(); it != s.swapk.end(); it++) {
216  **it = k;
217  }
218  for (typename vector<idx_it>::iterator it = s.swapr.begin(); it != s.swapr.end(); it++) {
219  **it = r;
220  }
221 
222  //add new entries for new col k into list
223  for (idx_it it = s.col_k_nnzs.begin(); it != s.col_k_nnzs.end(); it++) {
224  if ((*it > k) && (*it < r)) {
225  list[*it].push_back(k);
226  }
227  }
228 
229  //set the kth col
230  m_idx[k].swap(s.col_k_nnzs);
231  m_x[k].swap(s.col_k);
232 
233  //set the rth col
234  m_idx[r].swap(s.col_r_nnzs);
235  m_x[r].swap(s.col_r);
236 
237  //set the kth row and rth row
238  list[k].swap(s.row_k);
239  list[r].swap(s.row_r);
240 
241  //row swaps for first
242  std::swap(row_first[k], row_first[r]);
243  //--------end pivot A---------//
244 }
void col_clear()
Clears all col vectors (col_k, col_r, col_k_nnzs, col_r_nnzs).
Definition: swap_struct.h:38
void swap_clear()
Clears all swap vectors (swapk, swapr, all_swaps).
Definition: swap_struct.h:30
vector< idx_it > swapk
List of indices from row r that will be swapped to row k.
Definition: swap_struct.h:15
idx_vector_type col_k_nnzs
Row indices of non-zeros in the new column k.
Definition: swap_struct.h:19
idx_vector_type all_swaps
Column indices of all swaps done in swapk and swapr.
Definition: swap_struct.h:18
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 row_clear()
Clears all row vectors (row_k, row_r).
Definition: swap_struct.h:47
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
vector< idx_it > swapr
List of indices from row k that will be swapped to row r.
Definition: swap_struct.h:16
A list-of-lists (LIL) matrix in column oriented format.
Definition: lilc_matrix.h:9
idx_vector_type col_r_nnzs
Row indices of non-zeros in the new column r.
Definition: swap_struct.h:20
A structure containing variables used in pivoting a LIL-C matrix.
Definition: swap_struct.h:6
elt_vector_type col_r
Non-zero values in the new column r (order dependent on col_r_nnzs).
Definition: swap_struct.h:23
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 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
idx_vector_type row_r
Column indices of non-zeros in the new row r.
Definition: swap_struct.h:26
idx_vector_type row_k
Column indices of non-zeros in the new row k.
Definition: swap_struct.h:25
elt_vector_type col_k
Non-zero values in the new column k (order dependent on col_k_nnzs).
Definition: swap_struct.h:22