我正在构建一个具有多个(软)约束的稀疏线性系统。我正在将一些使用boost::ublas构建矩阵的代码转换为Eigen。boost:ublas有一种方便的方式可以创建具有已知(或估计)非零数的稀疏矩阵,并且具有相当快的operator(int row, int col)操作符来更新其元素。
问题如下:
- 使用SparseMatrix::setFromTriplets: 我的系统有许多约束条件。作为一个天真的、略微夸张的例子,假设我有一个100x100的稀疏矩阵,其中有500个非零元素,但有10亿个冗余约束(即,非零系数被修改了10亿次)。setFromTriplets要求我存储10亿个系数,其中大部分将被加起来形成我的500个非零系数集。这不是很高效也不友好。 当然,我可以用std::map替换我的std::vector,并手动执行约束的累积,但这在某种程度上忽略了拥有稀疏矩阵类的重点,而且这也不是很高效。
- 使用SparseMatrix::insert(i,j,val): 如果该元素已经存在,则无法使用。我的问题是能够累加已经存在的系数。 - 使用SparseMatrix::coeffRef(i, j): 这样做是可行的,也是我正在寻找的函数。然而,它比boost::ublas慢几个数量级。我很惊讶没有看到更好的函数。 我认为这是因为非零元素的数量事先不知道,强制进行多次重新分配(实际上就是这样发生的)。然而,使用SparseMatrix::reserve()没有效果,因为它是一个仅适用于压缩矩阵的函数(源代码中的注释说"此函数在非压缩模式下没有意义",在断言之前)。...而且,正如文档所说的"向SparseMatrix插入新元素会将其转换为未压缩模式"。
在Eigen中构建稀疏矩阵的最有效方法是什么,同时还能够多次更新其系数?
谢谢
问题如下:
- 使用SparseMatrix::setFromTriplets: 我的系统有许多约束条件。作为一个天真的、略微夸张的例子,假设我有一个100x100的稀疏矩阵,其中有500个非零元素,但有10亿个冗余约束(即,非零系数被修改了10亿次)。setFromTriplets要求我存储10亿个系数,其中大部分将被加起来形成我的500个非零系数集。这不是很高效也不友好。 当然,我可以用std::map替换我的std::vector,并手动执行约束的累积,但这在某种程度上忽略了拥有稀疏矩阵类的重点,而且这也不是很高效。
- 使用SparseMatrix::insert(i,j,val): 如果该元素已经存在,则无法使用。我的问题是能够累加已经存在的系数。 - 使用SparseMatrix::coeffRef(i, j): 这样做是可行的,也是我正在寻找的函数。然而,它比boost::ublas慢几个数量级。我很惊讶没有看到更好的函数。 我认为这是因为非零元素的数量事先不知道,强制进行多次重新分配(实际上就是这样发生的)。然而,使用SparseMatrix::reserve()没有效果,因为它是一个仅适用于压缩矩阵的函数(源代码中的注释说"此函数在非压缩模式下没有意义",在断言之前)。...而且,正如文档所说的"向SparseMatrix插入新元素会将其转换为未压缩模式"。
在Eigen中构建稀疏矩阵的最有效方法是什么,同时还能够多次更新其系数?
谢谢
SparseMatrix<double> mat(10, 10);
for (int i=0; i<10; i++) {
for (int j=0; j<1000000; j++) {
mat.coeffRef(i, i) += rand()%10;
}
}
=>的功能是可以实现的,但当处理更大的矩阵和更现实的情况时,速度要慢得多,与ublas operator()相比。
std::vector<Eigen::Triplet<double> > triplets(10000000);
int k=0;
for (int i=0; i<10; i++) {
for (int j=0; j<1000000; j++) {
triplets[k++] = Eigen::Triplet<double>(i,i,rand()%10);
}
}
SparseMatrix<double> mat(10, 10);
mat.setFromTriplets(triplets.begin(), triplets.end());
=> 不友好的内存...
mat.coeffRef(i,j) += v_ij;
吗?(参见 http://eigen.tuxfamily.org/dox-devel/group__TutorialSparse.html#TutorialSparseFilling) - Escualo