稀疏矩阵(Eigen)中寻找最大值的有效方法

5
我在想是否有一种有效的方法来查找稀疏矩阵中的最大/最小系数。
似乎sparse矩阵没有实现minCoeff()/maxCoeff()函数,这有点奇怪。
我在这里找到了答案,但我无法理解。
 using Tmp = typename remove_cv_ref<decltype(matrix)>::type;
 if constexpr(std::is_base_of<Eigen::SparseMatrixBase<Tmp>, Tmp>::value)
 max = Eigen::Map<const Vector>(matrix.valuePtr(), matrix.size()).maxCoeff();
 else
    max = matrix.maxCoeff();

编辑: 这是我的尝试,我不确定效率如何。

typedef Eigen::SparseMatrix<int, Eigen::RowMajor> SRI;
int maxCoeff(const SparseMatrix<int, RowMajor> &A)
{
    size_t row = A.rows();
    size_t col = A.cols();
    int max_value = -10000000;
    for (size_t k = 0; k < row; k++)
    {
        for (SRI::InnerIterator it(A, k); it; ++it)
        {
            if (it.value() > max_value)
                max_value = it.value();
        }
    }
    return max_value;
}
2个回答

9

这些函数并不是readily available(易于使用)的,因为可能存在歧义,即是否应该考虑隐式的0。例如,如果所有的非零值都是负数,maxCoeff应该返回0吗?

如果您只想考虑显式存储的元素,并且您的稀疏矩阵处于压缩模式,则可以编写以下代码:

auto max = matrix.coeffs().maxCoeff();

coeff方法等同于RHertel的答案。


3

尝试使用此模板函数获取 Eigen::SparseMatrix 的最大非零值:

template <class T>
T sparseMax (SparseMatrix<T>& mat) { 
  return Map<Matrix<T, Dynamic, 1> >(mat.valuePtr(), mat.nonZeros()).maxCoeff();
}

这里的原理是将稀疏矩阵的非零元素映射到向量(一维 Eigen::Matrix)中,然后用 .maxCoeff() 提取最大值。这应该是确定矩阵最大值的非常有效的方法。请注意,必须压缩矩阵 才能使用此方法。
在代码中,可以像这样调用函数 sparseMax()
if (!mat.isCompressed()) mat.makeCompressed();
auto max = sparseMax(mat);

这里的mat是一个 Eigen::SparseMatrix

链接中给出的答案几乎正确,但应该将.size()替换为.nonZeros(),并且未确保矩阵被压缩。如果您知道正在处理SparseMatrix,则不需要链接答案中提到的if/else结构。


编辑

上述解决方案适用于使用默认列主存储顺序的SparseMatrix。对于RowMajor存储的情况,可以更改模板:

template <class T>
 T sparseMax_RM (SparseMatrix<T,RowMajor>& mat) { 
 return Map<Matrix<T, Dynamic, 1> >(mat.valuePtr(), mat.nonZeros()).maxCoeff();
}

更健壮的方法是使用成员函数.coeffs(),正如@ggael所指出的那样。.coeffs()函数适用于压缩的SparseMatrix类的两种类型,即行主序和列主序存储。

仍然在想为什么他们没有实现这个功能。 - Abolfazl
关于“为什么”,请看我的回答。 - ggael
error: no matching function for call to ‘sparseMax(Eigen::SparseMatrix<int, 1>&)’ auto max = sparseMax(mat); template argument ‘1’ does not match ‘0’ auto max = sparseMax(mat); - Abolfazl
1
@Abolfazl 出现错误是因为您正在使用具有“RowMajor”存储而不是默认的“ColMajor”顺序的SparseMatrix。要处理这种特殊情况,可以将模板更改为T sparseMax(SparseMatrix <T,RowMajor>&mat)。为了拥有一个接受“RowMajor”和“ColMajor”存储的函数而概括答案是不必要的,因为成员函数.coeff()似乎正好做到了这一点。 - RHertel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接