提问人:Cedric Martens 提问时间:11/10/2023 更新时间:11/10/2023 访问量:59
C++ 特征只读稀疏块子表达式?怎么写?
C++ Eigen read-only sparse block subexpression? How to write?
问:
我想使用 Eigen 的块表达式从四个不同的矩阵创建一个大矩阵。
但是,在左上角添加第一个矩阵会导致错误:
error: static assertion failed: THIS_SPARSE_BLOCK_SUBEXPRESSION_IS_READ_ONLY
451 | EIGEN_STATIC_ASSERT(sizeof(T)==0, THIS_SPARSE_BLOCK_SUBEXPRESSION_IS_READ_ONLY);
我无法找到导致此问题的确切原因。不要将矩阵转换为密集表示,这一点非常重要。这是我的代码:
Eigen::SparseMatrix<double> top_left = K + Eigen::SparseMatrix<double>(K.transpose());
Eigen::SparseMatrix<double> block_laplacian_sq;
block_laplacian_sq.resize(top_left.rows() + C.rows(), top_left.cols() + C.rows());
block_laplacian_sq.topLeftCorner(top_left.rows(), top_left.cols()) = top_left;
// error here^^^
答:
2赞
Homer512
11/10/2023
#1
正如教程所解释的:
关于读取访问,稀疏矩阵公开的 API 与密集矩阵相同的 API 来访问子矩阵,例如块、列和行。有关详细介绍,请参阅块操作。但是,出于性能原因,写入次稀疏矩阵要有限得多,并且目前只有列主矩阵(或行主矩阵)的连续列集(或行)是可写的。此外,此信息必须在编译时已知,省略了 和 等方法。
SparseMatrix
block(...)
corner*(...)
对于要初始化左上角的特定用例,可以使用以下事实:调整大小后,未初始化的矩阵条目隐式为零。所以这有效:
top_left.conservativeResize(block_laplacian_sq.rows(), top_left.cols());
block_laplacian_sq.leftCols(top_left.cols()) = top_left;
但是,当您想要初始化底行时,这对您没有帮助。假设你想用子矩阵初始化所有 4 个角,我建议构建一个大的三元组向量(请参阅将特征矩阵转换为三元组形式的 C++),然后一次性初始化最终矩阵。
一种可能的替代方法是用完整逐列子矩阵的条目填充行主矩阵。我看不出这会如何更快,但对于您的用例来说,它可能更优雅。
Eigen::SparseMatrix<double, Eigen::RowMajor> left(
block_laplacian_sq.rows(), top_left.cols());
left.topRows(top_left.rows()) = top_left;
left.bottomRows(bottom_left.rows()) = bottom_left;
block_laplacian_sq.leftCols(left.cols()) = left;
(显然,您会尝试重新排列表达式,以避免行优先<>列优先更改)
评论