Eigen库动态大小矩阵行排序失效,固定大小矩阵正常求助
动态大小Eigen矩阵按列排序行失效,固定大小矩阵正常
问题描述
尝试按列值对Eigen矩阵(或矩阵块)的行进行排序,发现固定大小矩阵上可正常运行,但动态大小矩阵上无法生效。注释掉第一行#define FIXED_SIZE_MMM后,以下代码无法正常工作:
#define FIXED_SIZE_MMM #include <Eigen/Core> #include <iostream> namespace Eigen { template<class T> void swap(T&& a, T&& b){ a.swap(b); } } void sortRowsByColumn(Eigen::Ref<Eigen::MatrixXi> mat, int col) { std::sort( mat.rowwise().begin(), mat.rowwise().end(), [col](auto const& r1, auto const& r2) { return r1(col) < r2(col); } ); } int main(){ #ifdef FIXED_SIZE_MMM Eigen::Matrix4i A; A.Random(); #else Eigen::MatrixXi A; A.resize(4,4); A.Random(); #endif std::cout << "before sorting:\n" << A << "\n"; sortRowsByColumn(A.topRows(3),3); std::cout << "sorted:\n" << A << "\n"; }
问题根源
直接使用std::sort操作Eigen的RowwiseView迭代器时,在动态矩阵场景下,由于Eigen的表达式模板特性,迭代器指向的是临时行表达式而非直接的内存引用,排序过程中的交换操作无法正确映射到原矩阵的实际数据,导致排序失效。固定大小矩阵能生效是因为其行的内存布局连续且固定,迭代器可直接操作内存。
解决方法
改用Eigen的PermutationMatrix实现行排序,这种方法兼容固定和动态大小的矩阵,且更符合Eigen的设计范式:
#include <Eigen/Core> #include <iostream> #include <algorithm> void sortRowsByColumn(Eigen::Ref<Eigen::MatrixXi> mat, int col) { // 生成行索引向量 Eigen::VectorXi indices(mat.rows()); for (int i = 0; i < mat.rows(); ++i) { indices(i) = i; } // 根据指定列的值对索引排序 std::sort(indices.data(), indices.data() + indices.size(), [&mat, col](int i1, int i2) { return mat(i1, col) < mat(i2, col); }); // 构造排列矩阵并重新排列行 Eigen::PermutationMatrix<Eigen::Dynamic, Eigen::Dynamic> perm(indices.size()); perm.indices() = indices; mat = perm * mat; } int main(){ // 注释掉下面一行切换到动态矩阵测试 // #define FIXED_SIZE_MMM #ifdef FIXED_SIZE_MMM Eigen::Matrix4i A; A.Random(); #else Eigen::MatrixXi A; A.resize(4,4); A.Random(); #endif std::cout << "before sorting:\n" << A << "\n"; sortRowsByColumn(A.topRows(3),3); std::cout << "sorted:\n" << A << "\n"; }
代码说明
- 生成索引向量:创建包含当前行索引的向量,后续基于该向量排序,避免直接操作矩阵行。
- 排序索引:根据指定列的元素值对索引排序,排序逻辑和原需求一致。
- 应用排列:用排序后的索引构造
PermutationMatrix,通过矩阵乘法将原矩阵的行按排序后的索引重新排列,直接修改传入的矩阵块。
这种方法既保证了对固定/动态矩阵的兼容性,也避免了表达式模板带来的迭代器操作问题,能稳定实现按列排序行的需求。
内容的提问来源于stack exchange,提问作者Ernest
相关产品推荐
相关产品推荐

