You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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";

}

代码说明

  1. 生成索引向量:创建包含当前行索引的向量,后续基于该向量排序,避免直接操作矩阵行。
  2. 排序索引:根据指定列的元素值对索引排序,排序逻辑和原需求一致。
  3. 应用排列:用排序后的索引构造PermutationMatrix,通过矩阵乘法将原矩阵的行按排序后的索引重新排列,直接修改传入的矩阵块。

这种方法既保证了对固定/动态矩阵的兼容性,也避免了表达式模板带来的迭代器操作问题,能稳定实现按列排序行的需求。

内容的提问来源于stack exchange,提问作者Ernest

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 11:45:35