【问题标题】:C++ - MATLAB : updating a Sparse Matrix blockwiseC++ - MATLAB:逐块更新稀疏矩阵
【发布时间】:2017-07-21 21:26:36
【问题描述】:

这里是matlab代码

 N = 4096;
 x       =   linspace(-1,1,N);     
 A = sparse(100000,100000); 
 index = 1:32;

 A(index,index)    =   kernel(x(index),x(index));
  //kernel here outputs a 32 x 32 matrix 

我必须将 MATLAB 代码转换为 C++,但我被困在 sparse 函数中,我尝试使用:

 N=4096;
 Eigen::VectorXd x = Eigen::VectorXd::LinSpaced(N,-1,1); 
 Eigen::SparseMatrix<double> A(Asize,Asize);
 A.block(1,1,index.size(), index.size()) = Kernel();

但是 SparseMatrix 具有 block 作为只读函数,因此不能用于更新矩阵。

另一点:

我浏览了 Eigen 文档并检查了另一种形式的 SparseMatrix 声明:

 typedef Eigen::Triplet<double> T;
 std::vector<T>tripleList;
 tripleList.reserve(nnz);

 for(...)
 {
  // ...
  tripletList.push_back(T(i,j,v_ij));   //?? what are these values?
  }
 A.setFromTriplets(tripleList.begin(), tripleList.end());

但我不明白 nnz 的值应该是什么,它应该是我从 Matlab 代码中获得的值吗?我应该通过 for 循环推动什么值?它们会是随机的吗,鉴于矩阵大小如此之大,我如何选择“推送值”。

还有最后一个问题,声明后的稀疏矩阵如何逐块更新?

【问题讨论】:

  • nnz 表示“非零的数量”。我假设这是用于 Eigen 中的内存分配。此外,`A(index,index) = kernel(x(index),x(index));` 这可以通过 C++ 中的简单双嵌套循环来完成,您不需要单行
  • 根据documentaion 出于性能原因,写入子稀疏矩阵是有限的。并且只有您可以更新连续的列集。子矩阵的大小应该在编译时知道
  • @AnderBiguri 如何在双嵌套循环中完成?您是否建议使用“插入”功能?但是如果同一行重复多次,我必须每次都先存储 Kernel() 的结果,然后将其插入稀疏矩阵。

标签: c++ matlab sparse-matrix eigen


【解决方案1】:

一般来说,Eigen 稀疏矩阵块是 const。该规则的例外是例如m.col(i) 在列主矩阵中或.row(i) 在行主矩阵中。

至于您的第二点,nnz 是非零的数量。通过指定矩阵在开始时需要保留多少个非零,您可以最大限度地减少构造稀疏矩阵时所需的重新分配/复制的数量。请参阅documentation。另外请注意,如果您知道每列需要多少个元素,other overload 会很有用。 关于 for 循环,假设您有三个数组:columnIndicesrowIndicesvalues,长度均为 nnz。您的 for 循环如下所示:

for(int i = 0; i < nnz; i++)
{
    tripletList.push_back(T(columnIndices[i], rowIndices[i], values[i]));
}

或者,您可以计算 for 循环中每个三元组的值。

【讨论】:

  • 当值为零时,此方法是否有效?因为我浏览了文档,它说:“用非零元素填充”。如果我想将已经存在的稀疏矩阵更新为一些包含零的小矩阵怎么办?
猜你喜欢
  • 2018-01-19
  • 2013-04-11
  • 1970-01-01
  • 2016-01-25
  • 2017-07-02
  • 2012-06-20
  • 2014-05-12
  • 1970-01-01
  • 2022-08-18
相关资源
最近更新 更多