如何在上节点L L^T分解中乘以cholmod_factor
L ?我不喜欢转换为simplicial,因为超节点表示导致更快的回算,而且我不喜欢复制因子,因为两个副本可能不适合RAM。
我从t_cholmod_change_factor.c
中的上节点到简单辅助函数中的一个很好的注释中理解了上节点表示。我转述了这条评论,并在下面添加了一些细节:
上节点Cholesky分解被表示为上节点块的集合。超级节点块的条目按照列主顺序排列,如下所示:
t - - - (row s[pi[snode+0]])
t t - - (row s[pi[snode+1]])
t t t - (row s[pi[snode+2]])
t t t t (row s[pi[snode+3]])
r r r r (row s[pi[snode+4]])
r r r r (row s[pi[snode+5]])
- 有未使用的条目(由连字符表示),以使矩阵矩形
- 列索引连续
- 第一个
ncols
行索引是那些相同的连续列索引。之后的行索引可以指t
三角形以下的任何行。 -
super
成员每个超级节点有一个条目; 表示超级节点所代表的第一列。 -
pi
成员每个超级节点有一个表项;它指的是s
成员中的第一个索引,您可以在其中查找行号。 -
px
成员每个超级节点有一个表项;它引用x
成员中存储条目的第一个索引。同样,这不是打包存储。
下面的cholmod_factor *L
乘法代码似乎可以工作(我只关心int
索引和双精度实数项):
cholmod_dense *mul_L(cholmod_factor *L, cholmod_dense *d) {
int rows = d->nrow, cols = d->ncol;
cholmod_dense *ans = cholmod_allocate_dense(rows, cols, rows,
CHOLMOD_REAL, &comm);
memset(ans->x, 0, 8 * rows * cols);
FOR(i, L->nsuper) {
int *sup = (int *)L->super;
int *pi = (int *)L->pi;
int *px = (int *)L->px;
double *x = (double *)L->x;
int *ss = (int *)L->s;
int r0 = pi[i], r1 = pi[i+1], nrow = r1 - r0;
int c0 = sup[i], c1 = sup[i+1], ncol = c1 - c0;
int px0 = px[i];
/* TODO: Use BLAS instead. */
for (int j = 0; j < ncol; j++) {
for (int k = j; k < nrow; k++) {
for (int l = 0; l < cols; l++) {
((double *)ans->x)[l * rows + ss[r0 + k]] +=
x[px0 + k + j * nrow] * ((double *)d->x)[l*rows+c0 + j];
}
}
}
}
return ans;
}