• Eigen库中MatrixXd类型与VectorXd类型的相互映射与数据复制


       一、Eigen库的Map功能

       Eigen库的Map功能是一个强大的工具,用于将现有的数据(例如数组或其他线性代数库的数据结构)映射到Eigen矩阵或向量中,而无需复制数据。这种映射可以大大提高性能,因为它避免了不必要的数据复制,同时允许你使用Eigen库的功能来操作这些数据。以下是关于Eigen库的Map功能的详细介绍:

       1. 创建Map对象

       要使用Map功能,首先需要创建一个Map对象。通常,你会指定要映射的数据的类型和指针。例如:

    double data[] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0};
    Eigen::Map<Eigen::MatrixXd> matrix(data, 2, 3);
    
    • 1
    • 2

       在这个例子中,我们创建了一个Map对象matrix,将一个双精度浮点数数组data映射到一个2x3的Eigen矩阵中。数据指针是data,数据类型是Eigen::MatrixXd(通用的矩阵类型)。

       2. 使用映射数据

       一旦创建了Map对象,你可以像使用任何其他Eigen矩阵或向量一样使用它。你可以执行矩阵运算、访问元素等操作。例如:

    Eigen::MatrixXd result = matrix.transpose() * matrix;
    
    • 1

       这行代码计算了matrix的转置与自身的乘积,并将结果存储在result中。

       3. 避免数据复制

       一个关键的优势是,Map对象不会复制数据,而是直接引用现有数据。这意味着对Map对象的修改会影响到原始数据,反之亦然。这可以大大减少内存开销和提高性能。

       4. 数据格式与Eigen兼容性

       Map对象允许你将外部数据以与Eigen库兼容的方式映射到Eigen矩阵或向量中。这意味着你可以与其他库(如STL容器、C数组等)交互,并将它们与Eigen库的功能结合使用。

       总的来说,Eigen库的Map功能使我们能够有效地使用外部数据,并利用Eigen库的高性能线性代数功能,同时避免了数据的不必要复制。这对于需要与其他库或外部数据源进行交互的应用程序非常有用。

       二、MatrixXd类型到VectorXd类型的映射

       下面的给出中给出了一个将Eigen::MatrixXd 类型的2行3列的变量q,通过map功能映射到一个Eigen::VectorXd类型的列向量p中的例子

    #include 
    #include 
    
    int main() {
        int n = 3; // 举例,你可以设置合适的 n 值
        Eigen::MatrixXd q(2, n);
        
        // 假设将 q 填充为一些数据
        for (int i = 0; i < 2; ++i) {
            for (int j = 0; j < n; ++j) {
                q(i, j) = static_cast<double>(i * n + j);
            }
        }
        
        // 使用 Map 将 q 映射到 VectorXd
        Eigen::Map<Eigen::VectorXd> p(q.data(), 2 * n);
        
        // 输出 q 的内容
        std::cout << "q:\n" << q << "\n";
        
        // 输出 p 的内容
        std::cout << "p:\n" << p << "\n";
    
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

       其运行结果如下:

    q:
    0 1 2
    3 4 5
    p:
    0
    3
    1
    4
    2
    5
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

       通过第一部分的第3点内容介绍可知,Map对象不会复制数据,而是直接引用现有数据。这意味着对Map对象的修改会影响到原始数据,下面我们来对向量p中的元素进行修改,将p中第0个元素改为666,第3个元素改为999,然后再打印出q和p的元素

    #include 
    #include 
    
    int main() {
        int n = 3; // 举例,你可以设置合适的 n 值
        Eigen::MatrixXd q(2, n);
    
        // 假设将 q 填充为一些数据
        for (int i = 0; i < 2; ++i) {
            for (int j = 0; j < n; ++j) {
                q(i, j) = static_cast<double>(i * n + j);
            }
        }
    
        // 使用 Map 将 q 映射到 VectorXd
        Eigen::Map<Eigen::VectorXd> p(q.data(), 2 * n);
    
        // 输出 q 的内容
        std::cout << "原数据q:\n" << q << "\n";
    
        // 输出 p 的内容
        std::cout << "原数据p:\n" << p << "\n";
    
        // 对p中元素进行修改
        p[0] = 666;
        p[3] = 999;
    
        // 输出 q 的内容
        std::cout << "对p修改后q中的数据:\n" << q << "\n";
    
        // 输出 p 的内容
        std::cout << "对p修改后p中的数据:\n" << p << "\n";
    
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

       其运行结果如下:

    原数据q:
    0 1 2
    3 4 5
    原数据p:
    0
    3
    1
    4
    2
    5
    对p修改后q中的数据:
    666   1   2
      3 999   5
    对p修改后p中的数据:
    666
      3
      1
    999
      2
      5
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

       可以发现对p中的元素进行修该,q中对应的元素也会“自动修改”,因为它们本来就是同一个数据。


       三、VectorXd类型到MatrixXd类型的映射

       同理,我们可以进行VectorXd类型到MatrixXd类型的映射,Eigen::VectorXd是一个列向量(1列n行),而Eigen::MatrixXd是一个矩阵,通常是多行多列。要将一个Eigen::VectorXd对象映射到一个Eigen::MatrixXd对象,你需要确保维度匹配。具体来说,如果你的Eigen::VectorXd p包含2n个数据,你可以将其映射到一个2xn的Eigen::MatrixXd对象。

       下面的示例中,VectorXd类型变量p中含有2n个元素,将其映射到一个2xn的MatrixXd类型变量q中,同样,q中的数据与p共享,这意味着对q 的修改也会影响到 p,反之亦然。

    #include 
    #include 
    
    int main() {
        int n = 3; // 举例,你可以设置合适的n值
        Eigen::VectorXd p(2 * n);
    
        // 假设将p填充为一些数据
        for (int i = 0; i < 2 * n; ++i) {
            p(i) = static_cast<double>(i);
        }
    
        // 使用Map将p映射到MatrixXd
        Eigen::Map<Eigen::MatrixXd> q(p.data(), 2, n);
    
        // 输出 p 的内容
        std::cout << "p:\n" << p << "\n";
        
        // 现在,q是一个2x3的矩阵,数据与p共享
        std::cout << "q:\n" << q << "\n";
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

       其运行结果如下:

    p:
    0
    1
    2
    3
    4
    5
    q:
    0 2 4
    1 3 5
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

       四、MatrixXd类型到VectorXd类型的复制(不推荐)

       如果不想采用以上的map映射的方法,要将Eigen::MatrixXd类型的变量p中的每个数据存储到Eigen::VectorXd类型的变量q中,也可以使用Eigen库的一些内置函数和操作来完成这个任务。以下是一种方法:

    #include 
    #include 
    
    int main() {
        Eigen::MatrixXd p(3, 3); // 创建一个3x3的矩阵
        p << 1, 2, 3,
             4, 5, 6,
             7, 8, 9;
    
        Eigen::VectorXd q(p.rows() * p.cols()); // 创建一个大小足够存储p中所有数据的向量
    
        // 将p中的数据存储到q中
        for (int i = 0; i < p.rows(); ++i) {
            for (int j = 0; j < p.cols(); ++j) {
                q(i * p.cols() + j) = p(i, j);
            }
        }
    
        // 打印结果
        std::cout << "p:\n" << p << "\n";
        std::cout << "q:\n" << q << "\n";
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

       在这个示例中,首先创建了一个3x3的Eigen::MatrixXd矩阵p,并将一些示例数据赋给它。然后,创建了一个大小足够容纳所有p中数据的Eigen::VectorXd向量q。接下来,使用嵌套的循环遍历p的每个元素,并将其复制到q中。最后,打印了p和q的值。其运行结果如下:

    p:
    1 2 3
    4 5 6
    7 8 9
    q:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

       五、VectorXd类型到MatrixXd类型的复制(不推荐)

       如果不想采用以上的map映射的方法,要将Eigen::VectorXd类型的变量q中的每个数据(共2n个)存储到Eigen::MatrixXd类型的变量p中(p是2xn的矩阵),也可以使用Eigen库的一些内置函数和操作来完成这个任务。以下是一种方法:

    #include 
    
    int main() {
        int n = 3; // 假设n为3
        Eigen::VectorXd q(2 * n); // 创建一个包含2n个数据的向量q
    
        // 填充向量q的数据,这里假设有6个数据
        q << 1, 2, 3, 4, 5, 6;
    
        Eigen::MatrixXd p(2, n); // 创建一个2x3的矩阵p
    
        // 将q中的数据存储到p中
        for (int i = 0; i < 2; ++i) {
            for (int j = 0; j < n; ++j) {
                p(i, j) = q(i * n + j);
            }
        }
    
        // 打印结果
        std::cout << "q:\n" << q << "\n";
        std::cout << "p:\n" << p << "\n";
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

       在这个示例中,首先创建了一个2n维的Eigen::VectorXd向量q,并向其填充了示例数据。然后,创建了一个2x3的Eigen::MatrixXd矩阵p,用于存储q中的数据。接下来,使用嵌套的循环将q中的数据复制到p中。最后,打印q和p的值。可根据实际需求和数据尺寸来调整上述中的变量n以适应不同大小的问题。调整内外循环的顺序来调整转换后数据的存储顺序。其运行结果如下:

    q:
    1
    2
    3
    4
    5
    6
    p:
    1 2 3
    4 5 6
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

  • 相关阅读:
    【数据结构】图(邻接矩阵、邻接表、十字链表、邻接多重表)的数据结构(C++实现)
    Presto RBO之 Sort算子优化
    < Linux > 进程概念(1)
    开源简历生成器OpenResume
    201 -202.MySQL的数据类型
    部署:端口映射相关问题
    电影售票系统遇到的问题
    Spring XmlBeanFactory 容器的基本实现
    配置mysql8.0.27教程以及注意事项
    安卓活动连续跳转后虚拟机提示连续关闭
  • 原文地址:https://blog.csdn.net/qq_44339029/article/details/132799888