本篇为稀疏矩阵求解算法经典论著<Direct Methods for Sparse Linear System>的<读书笔记 3>
Chapter 2 Basic algorithms
2.1 Sparse matrix data structures
稀疏矩阵的数据结构,常用的是三元组表示法,包括了COO,CSR,CSC等。其中每种表示法,也分为了基0(
- C code:全部基0;
- MATLAB:全部基1;
- 伪代码:基于0;
- 书中的图graph示例以及矩阵示例:基于1。
此处举例:
- COO的基0的表达为:
int i[] = {2, 1, 3, 0, 1, 3, 3, 1, 0, 2}; // entry 的行index
int j[] = {2, 0, 3, 2, 1, 0, 1, 3, 0, 1}; // entry 的列index
double x[] = {3.0, 3.1, 1.0, 3.2, 2.9, 3.5, 0.4, 0.9, 4.5, 1.7}; // entry 的值
COO比较容易创建,但是比较难用于实际的算法中。
2. CSC的基0的表达为:
int ptr[] = {0, 3, 6, 8, 10}; // 每列首非零entry的索引
int idx[] = {0, 1, 3, 1, 2, 3, 0, 2, 1, 3}; // 非零entry的行索引
double x[] = {4.5, 3.1, 3.5, 2.9, 1.7, 0.4, 3.2, 3.0, 0.9, 1.0}; // entry 的值
CSC格式更加有用,在CSparse中被广泛采用。如果想要取出第j列的全部的值,则对应的x数组的索引为ptr[j]->ptr[j+1]-1,即x[ptr[j]]->x[ptr[j+1]-1],这些值所对应的行号i为i[p[j]]到i[ptr[j+1]-1]。所以在实际算法中,采用CSC格式,利于对列元素组成的向量进行运算。
3. CSR的基0的表达为:
int ptr[] = {0, 2, 5, 7, 10}; // 每行首非零entry的索引
int idx[] = {0, 2, 0, 1, 3, 1, 2, 0, 1, 3}; // 非零entry的列索引
double x[] = {4.5, 3.2, 3.1, 2.9, 0.9, 1.7, 3.0, 3.5, 0.4, 1.0}; // entry 的值
同CSC格式类似,采用CSR格式,有利于对行元素组成的向量进行运算。所以在实际算法中,有可能需要对同一个稀疏矩阵,同时采用CSC和CSR进行表达。
在CSparse中,采用的数据结构为:
typedef struct cs_sparse
{
/* matrix in compressed-column or triplet form */
int nzmax; /* maximum number of entries */
int m ; /* number of rows */
int n ; /* number of columns */
int *p ; /* column pointers (size n+l) or col indices (size nzmax) */
int *i ; /* row indices, size nzmax */
double *x; /* numerical values, size nzmax */
int nz; /* # of entries in triplet matrix, -1 for compressed-col */
} cs;
对于COO以及CSC格式都是利用上述结构体,利用nz区别所采用的格式。在CSparse中,大部分函数仅支持一种数据格式,除了cs_print, cs_spalloc,cs_spfree, cs_sprealloc,这些格式都支持。
mexFunction in C or Fortran:
- mxGetJc:return A->p
- mxGetlr: return A->i
- mxGetPr:return A->x
- mxGetM:return A->m
- mxGetN: return A->n
- mxGetNzmax:return A->nzmax
上述的数据格式,是同样也可以用来表示矩阵A中的特定位置的零元素。是由于在后续的算法中,会对矩阵进行符号分析,会预估矩阵中的非零元素位置,但是这些元素在未被计算出来之前,是由0进行赋值的。
由于在已经确定的数据结构中增加或者删减一个entry,需要耗时