找到稀疏矩阵(本征)最大值的有效方法
Efficient way to find maximum value of Sparse matrix (Eigen)
我想知道是否可以有效地在稀疏矩阵中找到 max/min 系数。
好像没有为稀疏矩阵实现minCoeff()/maxCoeff()函数,有点奇怪。
我找到了这个答案here,但我想不通。
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;
}
试试这个模板函数来获取 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
.
因此link中的答案几乎是正确的,但是.size()
应该替换为.nonZeros()
并且它不能确保矩阵被压缩。如果您知道您正在处理 SparseMatrix,则不需要 linked 答案中提到的 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 类,RowMajor 和 ColMajor 存储顺序。
这些函数不容易获得,因为是否应考虑隐式零可能不明确。例如,如果所有非零都是负数,应 maxCoeff
returns 0
?
如果您只想考虑显式存储的元素并且您的稀疏矩阵处于压缩模式,那么您可以这样写:
auto max = matrix.coeffs().maxCoeff();
coeff方法等同于RHertel的回答。
我想知道是否可以有效地在稀疏矩阵中找到 max/min 系数。
好像没有为稀疏矩阵实现minCoeff()/maxCoeff()函数,有点奇怪。
我找到了这个答案here,但我想不通。
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;
}
试试这个模板函数来获取 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
.
因此link中的答案几乎是正确的,但是.size()
应该替换为.nonZeros()
并且它不能确保矩阵被压缩。如果您知道您正在处理 SparseMatrix,则不需要 linked 答案中提到的 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 类,RowMajor 和 ColMajor 存储顺序。
这些函数不容易获得,因为是否应考虑隐式零可能不明确。例如,如果所有非零都是负数,应 maxCoeff
returns 0
?
如果您只想考虑显式存储的元素并且您的稀疏矩阵处于压缩模式,那么您可以这样写:
auto max = matrix.coeffs().maxCoeff();
coeff方法等同于RHertel的回答。