Прежде всего, 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";
}
Если вы хотите сравнить шаблоны разреженности, вы можете проверить данные, начиная с внутреннего и внешнего указателей индекса (используя карту для обоих). Следующее работает, если обе матрицы имеют одинаковый тип и сжаты:
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;
}