c++ - Eigen :比较两个可能具有不同稀疏模式的稀疏矩阵

标签 c++ sparse-matrix eigen eigen3

我想比较两个 Eigen::SparseMatrix

据我所知,存在 res.isApprox(ans) 方法,但不幸的是,在不同稀疏模式的情况下,它会因断言而失败

AffineInvariantDeformerTest01: Eigen/src/SparseCore/SparseMatrix.h:934: void Eigen::internal::set_from_triplets(const InputIterator&, const InputIterator&, SparseMatrixType&, DupFunctor) [with InputIterator = __gnu_cxx::__normal_iterator<Eigen::Triplet<double, int>*, std::vector<Eigen::Triplet<double, int>, std::allocator<Eigen::Triplet<double, int> > > >; SparseMatrixType = Eigen::SparseMatrix<double, 0, int>; DupFunctor = Eigen::internal::scalar_sum_op<double, double>]: Assertion `it->row()>=0 && it->row()<mat.rows() && it->col()>=0 && it->col()<mat.cols()' failed.

我想要它用于单元测试,所以如果它不会那么快也没关系。也许我可以将我的稀疏矩阵转换为密集矩阵,但我希望存在更优雅的解决方案

编辑: 只需一种可以比较两个矩阵的稀疏模式的方法对我来说也可以

最佳答案

首先,即使使用不同的稀疏模式,isApprox() 也能正常工作。看起来你的错误在别处(当你使用 setFromTriplets() 设置矩阵时可能已经)

当给定两个具有不同稀疏模式的矩阵时,如果不同的条目(几乎)为零,则它们将被视为近似相等。以下应计算 true 两次(增加 1e-19 以查看差异):

#include <Eigen/SparseCore>
#include <iostream>
#include <array>

int main() {
    Eigen::SparseMatrix<double> Mat1(2,2), Mat2(2,2);

    std::array<Eigen::Triplet<double,int>, 2> data1  {{{0,0,1.0}, {1,1, 1e-19}}};
    std::array<Eigen::Triplet<double,int>, 2> data2  {{{0,0,1.0}, {1,0, 1e-19}}};

    Mat1.setFromTriplets(data1.begin(), data1.end());
    Mat2.setFromTriplets(data2.begin(), data2.end());

    std::cout << "Mat1.isApprox(Mat1) == " << Mat1.isApprox(Mat1) << "\nMat1.isApprox(Mat2) == " << Mat1.isApprox(Mat2) << "\n";
}

如果要比较稀疏模式,可以检查从内部和外部索引指针开始的数据(对两者都使用 Map)。如果两个矩阵具有相同的类型并且被压缩,则以下工作:

template<class Derived>
bool hasSamePattern(Eigen::SparseCompressedBase<Derived> const& A, Eigen::SparseCompressedBase<Derived> const& B)
{
    assert(A.isCompressed() && B.isCompressed());
    if(A.rows() != B.rows() || A.cols() != B.cols() || A.nonZeros() != B.nonZeros())
        return false;
    typedef Eigen::Matrix<typename Derived::StorageIndex, Eigen::Dynamic, 1> IndexVector;
    Eigen::Index outerSize = A.outerSize(), nnz = A.nonZeros();
    if(IndexVector::Map(A.outerIndexPtr(), outerSize) != IndexVector::Map(B.outerIndexPtr(), outerSize))
        return false;
    if(IndexVector::Map(A.innerIndexPtr(), nnz) != IndexVector::Map(B.innerIndexPtr(), nnz))
        return false;

    return true;
}

关于c++ - Eigen :比较两个可能具有不同稀疏模式的稀疏矩阵,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56545544/

相关文章:

R - 更新非常大的稀疏矩阵中的列

c++ - 在 Clion CMake 中包含 Eigen 库时出现问题

c++ - 这个浮点平方根近似是如何工作的?

c++ - 在堆栈上分配一个小对象比在堆上创建它(一次)更有效吗?

c++ - '$OutDir'在Visual Studio的脚本文件中定义在哪里?

python - SciPy稀疏矩阵(COO,CSR): Clear row

python - 对称稀疏矩阵的高效切片

c++ - Arpack++ 稀疏特征求解器比等效的 Matlab eigs() 慢很多倍

c++ - 通过引用传递的特征参数

c++ - 在 Windows 中将用户输入隐藏为星号?