2 #ifndef _LIL_MATRIX_SYM_AMD_H_ 3 #define _LIL_MATRIX_SYM_AMD_H_ 9 inline int amd_flip(
const int& i) {
return -i-2; }
12 inline int wclear (
int mark,
int lemax,
int *w,
int n)
15 if(mark < 2 || (mark + lemax < 0))
17 for(k = 0; k < n; k++)
26 inline int tdfs(
int j,
int k,
int *head,
const int *next,
int *post,
int *stack)
29 if(!head || !next || !post || !stack)
return (-1);
55 template<
class el_type>
61 int d, dk, dext, lemax = 0, e, elenk, eln, i, j, k, k1,
62 k2, k3, jlast, ln, dense, nzmax, mindeg = 0, nvi, nvj, nvk, mark, wnvi,
63 ok, nel = 0, p, p1, p2, p3, p4, pj, pk, pk1, pk2, pn, q, t;
66 int n = this->n_rows();
67 dense = max(16,
int(10 * sqrt(
double(n))));
68 dense = min(n-2, dense);
72 int* W =
new int[8*(n+1)];
75 int* next = W + 2*(n+1);
76 int* head = W + 3*(n+1);
77 int* elen = W + 4*(n+1);
78 int* degree = W + 5*(n+1);
80 int* hhead = W + 7*(n+1);
82 int* temp_perm =
new int[n+1];
83 int* last = temp_perm;
86 int cnz = this->nnz();
87 t = 3*cnz + 3*cnz/5 + 2*n;
88 int* Cp =
new int[n+1];
93 for (
int i = 0; i < n; i++) {
94 for (
int j = 0; j < (int) list[i].size(); j++) {
95 Ci[cnt++] = list[i][j];
97 for (
int j = 0; j < (int) m_idx[i].size(); j++) {
98 Ci[cnt++] = m_idx[i][j];
104 for(k = 0; k < n; k++)
105 len[k] = Cp[k+1] - Cp[k];
109 for(i = 0; i <= n; i++)
120 mark = amd::wclear(0, 0, w, n);
126 for(i = 0; i < n; i++)
141 Cp[i] = amd::amd_flip (n);
146 if(head[d] != -1) last[head[d]] = i;
155 for(k = -1; mindeg < n && (k = head[mindeg]) == -1; mindeg++) {}
156 if(next[k] != -1) last[next[k]] = -1;
157 head[mindeg] = next[k];
163 if(elenk > 0 && cnz + mindeg >= nzmax)
165 for(j = 0; j < n; j++)
170 Ci[p] = amd::amd_flip (j);
173 for(q = 0, p = 0; p < cnz; )
175 if((j = amd::amd_flip (Ci[p++])) >= 0)
179 for(k3 = 0; k3 < len[j]-1; k3++) Ci[q++] = Ci[p++];
189 pk1 = (elenk == 0) ? p : cnz;
192 for(k1 = 1; k1 <= elenk + 1; k1++)
206 for(k2 = 1; k2 <= ln; k2++)
209 if((nvi = nv[i]) <= 0)
continue;
213 if(next[i] != -1) last[next[i]] = last[i];
216 next[last[i]] = next[i];
220 head[degree[i]] = next[i];
225 Cp[e] = amd::amd_flip (k);
229 if(elenk != 0) cnz = pk2;
236 mark = amd::wclear(mark, lemax, w, n);
237 for(pk = pk1; pk < pk2; pk++)
240 if((eln = elen[i]) <= 0)
continue;
243 for(p = Cp[i]; p <= Cp[i] + eln - 1; p++)
252 w[e] = degree[e] + wnvi;
258 for(pk = pk1; pk < pk2; pk++)
262 p2 = p1 + elen[i] - 1;
264 for(h = 0, d = 0, p = p1; p <= p2; p++)
278 Cp[e] = amd::amd_flip (k);
283 elen[i] = pn - p1 + 1;
286 for(p = p2 + 1; p < p4; p++)
289 if((nvj = nv[j]) <= 0)
continue;
296 Cp[i] = amd::amd_flip (k);
306 degree[i] = std::min(degree[i], d);
310 len[i] = pn - p1 + 1;
318 lemax = std::max(lemax, dk);
319 mark = amd::wclear(mark+lemax, lemax, w, n);
322 for(pk = pk1; pk < pk2; pk++)
325 if(nv[i] >= 0)
continue;
329 for(; i != -1 && next[i] != -1; i = next[i], mark++)
333 for(p = Cp[i]+1; p <= Cp[i] + ln-1; p++) w[Ci[p]] = mark;
335 for(j = next[i]; j != -1; )
337 ok = (len[j] == ln) && (elen[j] == eln);
338 for(p = Cp[j] + 1; ok && p <= Cp[j] + ln - 1; p++)
340 if(w[Ci[p]] != mark) ok = 0;
344 Cp[j] = amd::amd_flip (i);
361 for(p = pk1, pk = pk1; pk < pk2; pk++)
364 if((nvi = -nv[i]) <= 0)
continue;
366 d = degree[i] + dk - nvi;
367 d = std::min(d, n - nel - nvi);
368 if(head[d] != -1) last[head[d]] = i;
372 mindeg = std::min(mindeg, d);
377 if((len[k] = p-pk1) == 0)
382 if(elenk != 0) cnz = p;
387 for(i = 0; i < n; i++) Cp[i] = amd::amd_flip (Cp[i]);
388 for(j = 0; j <= n; j++) head[j] = -1;
389 for(j = n; j >= 0; j--)
391 if(nv[j] > 0)
continue;
392 next[j] = head[Cp[j]];
395 for(e = n; e >= 0; e--)
397 if(nv[e] <= 0)
continue;
400 next[e] = head[Cp[e]];
405 for(k = 0, i = 0; i <= n; i++)
407 if(Cp[i] == -1) k = amd::tdfs(i, k, head, next, temp_perm, w);
410 for (
int i = 0; i < n; i++) {
411 perm[i] = temp_perm[i];
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
Definition: lilc_matrix_sym_amd.h:8