求和特征中稀疏矩阵的三角视图
sum triangular views of sparse matrices in eigen
使用 Visual Studio 2010,我尝试使用稀疏矩阵在 eigen (from the repositories 3.3 branch) 中表达以下 matlab 代码:
m = [1 2 3 ;
4 5 6;
7 8 9];
r = triu(m,1) + tril(m)';
即计算不包含对角线的方阵的上三角与包含对角线的同一方阵的转置下三角之和
对于这个简单的例子,结果是
1 6 10
0 5 14
0 0 9
尝试使用稠密矩阵在本征中做到这一点,我主要想到了以下方法(唯一不那么直观的是使用成员方法 addTo 而不是 + 运算符)直接的方法:
Eigen::Matrix3d dm;
dm << 1,2,3, 4,5,6, 7,8,9;
std::cout << "dm" << std::endl << dm << std::endl;
auto dsut = dm.triangularView<Eigen::StrictlyUpper>();
auto dltt = dm.triangularView<Eigen::Lower>().transpose();
std::cout << "dsut" << std::endl << dsut.toDenseMatrix() << std::endl;
std::cout << "dltt" << std::endl << dltt.toDenseMatrix() << std::endl;
// doesn't compile --> Eigen::Matrix3d dj = dsut + dltt;
// (last) error:
// error C2676: binary '+' : 'Eigen::TriangularView<_MatrixType,_Mode>' does not define this operator or a conversion to a type acceptable to the predefined operator
// with
// [
// _MatrixType=Eigen::Matrix<double,3,3>,
// _Mode=10
// ]
Eigen::Matrix3d dj = dsut;
dltt.addTo(dj);
std::cout << "dj" << std::endl << dj << std::endl;
输出符合预期:
dm
1 2 3
4 5 6
7 8 9
dsut
0 2 3
0 0 6
0 0 0
dltt
1 4 7
0 5 8
0 0 9
dj
1 6 10
0 5 14
0 0 9
但我找不到对稀疏矩阵执行相同操作的方法。
这是我尝试过的:
std::vector<Eigen::Triplet<double> > triplets;
triplets.push_back(Eigen::Triplet<double>(0,0,1));
triplets.push_back(Eigen::Triplet<double>(0,1,2));
triplets.push_back(Eigen::Triplet<double>(0,2,3));
triplets.push_back(Eigen::Triplet<double>(1,0,4));
triplets.push_back(Eigen::Triplet<double>(1,1,5));
triplets.push_back(Eigen::Triplet<double>(1,2,6));
triplets.push_back(Eigen::Triplet<double>(2,0,7));
triplets.push_back(Eigen::Triplet<double>(2,1,8));
triplets.push_back(Eigen::Triplet<double>(2,2,9));
Eigen::SparseMatrix<double> sm(3, 3);
sm.setFromTriplets(triplets.begin(), triplets.end());
std::cout << "sm" << std::endl << sm << std::endl;
auto ssut = sm.triangularView<Eigen::StrictlyUpper>();
auto sltt = sm.triangularView<Eigen::Lower>().transpose();
std::cout << "ssut" << std::endl << ssut << std::endl;
std::cout << "sltt" << std::endl << sltt << std::endl;
// doesn't compile --> Eigen::SparseMatrix<double> j = ssut + sltt;
// (last) error:
// eigen\eigen\src/Core/CwiseBinaryOp.h(49): error C2752: 'Eigen::internal::cwise_promote_storage_order<LhsKind,RhsKind,LhsOrder,RhsOrder>' : more than one partial specialization matches the template argument list
// with
// [
// LhsKind=Eigen::internal::traits<Eigen::SparseMatrix<double>>::StorageKind,
// RhsKind=Eigen::internal::traits<Eigen::SparseMatrix<double>>::StorageKind,
// LhsOrder=0,
// RhsOrder=1
// ]
// eigen\src/Core/util/XprHelper.h(540): could be 'Eigen::internal::cwise_promote_storage_order<Eigen::Sparse,RhsKind,LhsOrder,RhsOrder>'
// eigen\src/Core/util/XprHelper.h(539): or 'Eigen::internal::cwise_promote_storage_order<LhsKind,Eigen::Sparse,LhsOrder,RhsOrder>'
// eigen\src/Core/EigenBase.h(41) : see reference to class template instantiation 'Eigen::internal::traits<T>' being compiled
Eigen::SparseMatrix<double> j = ssut;
// doesn't compile --> sltt.addTo(j);
// (last) error:
// eigen\src/Core/EigenBase.h(72): error C2248: 'Eigen::SparseMatrixBase<Derived>::evalTo' : cannot access private member declared in class 'Eigen::SparseMatrixBase<Derived>'
// with
// [
// Derived=Eigen::TriangularView<const Eigen::Transpose<const Eigen::SparseMatrix<double>>,2>
// ]
std::cout << "j" << std::endl << j.toDense() << std::endl;
我标记了非编译代码,所以这是可编译部分的输出:
sm
Nonzero entries:
(1,0) (4,1) (7,2) (2,0) (5,1) (8,2) (3,0) (6,1) (9,2)
Outer pointers:
0 3 6 $
1 2 3
4 5 6
7 8 9
ssut
0 2 3
0 0 6
0 0 0
sltt
1 4 7
0 5 8
0 0 9
j
0 2 3
0 0 6
0 0 0
似乎 + 运算符和 addTo 成员方法都不能在转置两个三角视图时使用。
转置 none 时,+ 运算符有效,但 addTo 方法无效。用伴随替换转置会导致相同的编译错误。
我有什么明显的遗漏吗?或者有没有办法重新制定这个?我的目标是使用 eigen 中的现有函数并避免将稀疏矩阵转换为密集矩阵。
主要问题是您将列优先稀疏矩阵添加到行优先稀疏矩阵,这是被禁止的,因为无法直接有效地执行此类操作。基本上以下更简单的代码片段也将无法编译:
SparseMatrix<double> A,B,C;
C = A + B.transpose();
你应该得到一个明确的静态断言来告诉你的错误。
解决方案是将一个操作数显式复制(求值)到具有适当存储顺序的显式稀疏矩阵:
C = A + SparseMatrix<double>(B.transpose());
所以在你的情况下,将 auto sltt
替换为 SparseMatrix<double> sltt
,你应该没问题。
最后,如果您尝试使某些矩阵对称,selfadjointView
可能是更好的选择,例如:
C = A.selfadjointView<Lower>();
使用 Visual Studio 2010,我尝试使用稀疏矩阵在 eigen (from the repositories 3.3 branch) 中表达以下 matlab 代码:
m = [1 2 3 ;
4 5 6;
7 8 9];
r = triu(m,1) + tril(m)';
即计算不包含对角线的方阵的上三角与包含对角线的同一方阵的转置下三角之和
对于这个简单的例子,结果是
1 6 10
0 5 14
0 0 9
尝试使用稠密矩阵在本征中做到这一点,我主要想到了以下方法(唯一不那么直观的是使用成员方法 addTo 而不是 + 运算符)直接的方法:
Eigen::Matrix3d dm;
dm << 1,2,3, 4,5,6, 7,8,9;
std::cout << "dm" << std::endl << dm << std::endl;
auto dsut = dm.triangularView<Eigen::StrictlyUpper>();
auto dltt = dm.triangularView<Eigen::Lower>().transpose();
std::cout << "dsut" << std::endl << dsut.toDenseMatrix() << std::endl;
std::cout << "dltt" << std::endl << dltt.toDenseMatrix() << std::endl;
// doesn't compile --> Eigen::Matrix3d dj = dsut + dltt;
// (last) error:
// error C2676: binary '+' : 'Eigen::TriangularView<_MatrixType,_Mode>' does not define this operator or a conversion to a type acceptable to the predefined operator
// with
// [
// _MatrixType=Eigen::Matrix<double,3,3>,
// _Mode=10
// ]
Eigen::Matrix3d dj = dsut;
dltt.addTo(dj);
std::cout << "dj" << std::endl << dj << std::endl;
输出符合预期:
dm
1 2 3
4 5 6
7 8 9
dsut
0 2 3
0 0 6
0 0 0
dltt
1 4 7
0 5 8
0 0 9
dj
1 6 10
0 5 14
0 0 9
但我找不到对稀疏矩阵执行相同操作的方法。 这是我尝试过的:
std::vector<Eigen::Triplet<double> > triplets;
triplets.push_back(Eigen::Triplet<double>(0,0,1));
triplets.push_back(Eigen::Triplet<double>(0,1,2));
triplets.push_back(Eigen::Triplet<double>(0,2,3));
triplets.push_back(Eigen::Triplet<double>(1,0,4));
triplets.push_back(Eigen::Triplet<double>(1,1,5));
triplets.push_back(Eigen::Triplet<double>(1,2,6));
triplets.push_back(Eigen::Triplet<double>(2,0,7));
triplets.push_back(Eigen::Triplet<double>(2,1,8));
triplets.push_back(Eigen::Triplet<double>(2,2,9));
Eigen::SparseMatrix<double> sm(3, 3);
sm.setFromTriplets(triplets.begin(), triplets.end());
std::cout << "sm" << std::endl << sm << std::endl;
auto ssut = sm.triangularView<Eigen::StrictlyUpper>();
auto sltt = sm.triangularView<Eigen::Lower>().transpose();
std::cout << "ssut" << std::endl << ssut << std::endl;
std::cout << "sltt" << std::endl << sltt << std::endl;
// doesn't compile --> Eigen::SparseMatrix<double> j = ssut + sltt;
// (last) error:
// eigen\eigen\src/Core/CwiseBinaryOp.h(49): error C2752: 'Eigen::internal::cwise_promote_storage_order<LhsKind,RhsKind,LhsOrder,RhsOrder>' : more than one partial specialization matches the template argument list
// with
// [
// LhsKind=Eigen::internal::traits<Eigen::SparseMatrix<double>>::StorageKind,
// RhsKind=Eigen::internal::traits<Eigen::SparseMatrix<double>>::StorageKind,
// LhsOrder=0,
// RhsOrder=1
// ]
// eigen\src/Core/util/XprHelper.h(540): could be 'Eigen::internal::cwise_promote_storage_order<Eigen::Sparse,RhsKind,LhsOrder,RhsOrder>'
// eigen\src/Core/util/XprHelper.h(539): or 'Eigen::internal::cwise_promote_storage_order<LhsKind,Eigen::Sparse,LhsOrder,RhsOrder>'
// eigen\src/Core/EigenBase.h(41) : see reference to class template instantiation 'Eigen::internal::traits<T>' being compiled
Eigen::SparseMatrix<double> j = ssut;
// doesn't compile --> sltt.addTo(j);
// (last) error:
// eigen\src/Core/EigenBase.h(72): error C2248: 'Eigen::SparseMatrixBase<Derived>::evalTo' : cannot access private member declared in class 'Eigen::SparseMatrixBase<Derived>'
// with
// [
// Derived=Eigen::TriangularView<const Eigen::Transpose<const Eigen::SparseMatrix<double>>,2>
// ]
std::cout << "j" << std::endl << j.toDense() << std::endl;
我标记了非编译代码,所以这是可编译部分的输出:
sm
Nonzero entries:
(1,0) (4,1) (7,2) (2,0) (5,1) (8,2) (3,0) (6,1) (9,2)
Outer pointers:
0 3 6 $
1 2 3
4 5 6
7 8 9
ssut
0 2 3
0 0 6
0 0 0
sltt
1 4 7
0 5 8
0 0 9
j
0 2 3
0 0 6
0 0 0
似乎 + 运算符和 addTo 成员方法都不能在转置两个三角视图时使用。
转置 none 时,+ 运算符有效,但 addTo 方法无效。用伴随替换转置会导致相同的编译错误。
我有什么明显的遗漏吗?或者有没有办法重新制定这个?我的目标是使用 eigen 中的现有函数并避免将稀疏矩阵转换为密集矩阵。
主要问题是您将列优先稀疏矩阵添加到行优先稀疏矩阵,这是被禁止的,因为无法直接有效地执行此类操作。基本上以下更简单的代码片段也将无法编译:
SparseMatrix<double> A,B,C;
C = A + B.transpose();
你应该得到一个明确的静态断言来告诉你的错误。
解决方案是将一个操作数显式复制(求值)到具有适当存储顺序的显式稀疏矩阵:
C = A + SparseMatrix<double>(B.transpose());
所以在你的情况下,将 auto sltt
替换为 SparseMatrix<double> sltt
,你应该没问题。
最后,如果您尝试使某些矩阵对称,selfadjointView
可能是更好的选择,例如:
C = A.selfadjointView<Lower>();