zoukankan      html  css  js  c++  java
  • Eigen 3.3.7 入门教程

    Eigen 3.3.7 入门教程

    原文地址:http://eigen.tuxfamily.org/dox/GettingStarted.html
    学完当前教程后可以参考 The Matrix class 进行进一步学习。

    如何安装 Eigen

    因为 Eigen 是 header-only 的,所以直接下载 Eigen 头文件即可使用。

    一个简单的示例

    #include <iostream>
    #include <Eigen/Dense>
    using Eigen::MatrixXd;
    int main()
    {
      MatrixXd m(2,2);
      m(0,0) = 3;
      m(1,0) = 2.5;
      m(0,1) = -1;
      m(1,1) = m(1,0) + m(0,1);
      std::cout << m << std::endl;
    }
    

    下面先介绍编译方式再解释代码

    编译并执行

    Eigen 不依赖其他三方库,只要把 Eigen 库放到编译器可以发现的路径即可。使用GCC你可以使用-I指明Eigen头文件的路径,你可以使用下面的指令编译上面的代码:
    g++ -I /path/to/eigen/ my_program.cpp -o my_program
    在linux或者Mac OS X中,你可以将 Eigen 头文件复制到 usr/local/include 目录下,这样你就可以使用下面的指令编译上面的代码:
    g++ my_program.cpp -o my_program
    编译并执行上面的代码,你将获得如下输出:

    3 -1 2.5 1.5

    解释第一个程序

    Eigen 头文件定义了很多类型,对于简单的使用来说只使用 MatrixXd 类就可以了。MatrixXd 可以表示任意维度的矩阵(MatrixXd中的X表示任意),而且矩阵的元素都是 double 类型的(MatrixXd中的d表示double)。quick reference guide 中简要介绍了 Eigen 提供的用于描述矩阵的类。

    Eigen/Dense头文件定义了MatrixXd类中可用的所有方法和相关类型,所有方法均定义在Eigen名字空间中。

    main 函数中的第一行定义了一个2行2列的MatrixXd矩阵,表达式m(0,0) = 3将矩阵左上角的元素置为3。在 Eigen 中你可以使用小括号来获得对应元素的引用。在计算机科学中第一个元素的下标为 0,然而在传统的数学表达方法中第一个元素的下标是 1。

    示例2,:矩阵和向量

    下面的例子包含了矩阵和向量,我们先讲第二段代码

    // 代码片段1:运行时设置矩阵的维度
    #include <iostream>
    #include <Eigen/Dense>
    using namespace Eigen;
    using namespace std;
    int main()
    {
      MatrixXd m = MatrixXd::Random(3,3);
      m = (m + MatrixXd::Constant(3,3,1.2)) * 50;
      cout << "m =" << endl << m << endl;
      VectorXd v(3);
      v << 1, 2, 3;
      cout << "m * v =" << endl << m * v << endl;
    }
    
    // 代码片段2:编译时确定矩阵的维度
    #include <iostream>
    #include <Eigen/Dense>
    using namespace Eigen;
    using namespace std;
    int main()
    {
      Matrix3d m = Matrix3d::Random();
      m = (m + Matrix3d::Constant(1.2)) * 50;
      cout << "m =" << endl << m << endl;
      Vector3d v(1,2,3);
      
      cout << "m * v =" << endl << m * v << endl;
    }
    

    第二段代码编译后执行的输出为(因为矩阵是随机初始化的故输出可能不同):

    m =                    
    10.1251 90.8741 45.0291
    66.3585 68.5009 99.5962
    29.3304 57.9873  92.284
    m * v =                
    326.961                
    502.149                
    422.157                               
    

    第二个示例的解释

    第二段代码main中声明了一个3×3的矩阵并使用 Random() 进行了随机初始化(初始值在-1和1之间)。第二行代码将m中所有元素的值映射到10和110之间。Constant(3,3,1.2)生成了一个所有元素值为1.2的3×3的矩阵。第三行引入了一个新的类型:VectorXd,这个类表示了一个任意维度列向量。第四行代码使用逗号初始化生成了一个3×1的向量。

    最后一行代码执行矩阵和向量的点乘。

    上面示例中的两段代码,其功能是相同的。第一段代码使用的向量和矩阵其维度是在运行时决定的,第二段代码中矩阵和向量的形状在编译时就已知了,第二段代码中矩阵和向量的维度是固定的。

    使用固定尺寸的矩阵有一定的优势,例如编译器可以生成更高效的可执行文件。使用固定尺寸的类型可以进行更加严格的编译时检查,例如编译器可以检查两个向量是否可以相乘。一个比较好的经验是在矩阵维度小于或等于 4×4 时使用固定尺寸的矩阵(例如:Matrix3f、Matrix2i、Matrix4d等内置类型)。

    进一步的学习

    阅读long turorial是比较好的选择。

    其他教程

    下面内容源自CSCI2240

    使用模板创建固定维度的矩阵

    Matrix<short, 5, 5> m1;
    Matrix<float, 20, 75> m2;
    

    使用模板创建未知维度的矩阵

    // MatrixXf, MatrixXd
    

    迭代矩阵

    Eigen 在内存中按列顺序保存矩阵,所以在迭代矩阵的时候按列的顺序进行迭代,效率会比按行进行迭代要快(逗号初始化的时候按行),如下伪代码:

    for i = 1:4 {
    	for j = 1:4 {
    		B(j , i ) = 0.0;
    	}
    }
    

    内置矩阵辅助函数

    // Set each coefficient to a uniform random value in the range [ -1 , 1]
    A = Matrix3f :: Random () ;
    // Set B to the identity matrix
    B = Matrix4d :: Identity () ;
    // Set all elements to zero
    A = Matrix3f :: Zero () ;
    // Set all elements to ones
    A = Matrix3f :: Ones () ;
    // Set all elements to a constant value
    B = Matrix4d :: Constant (4.5) ;
    // Scalar multiplication , and subtraction
    // What do you expect the output to be?
    cout << M2 - Matrix4f :: Ones () * 2.2 << endl ;
    
    

    将矩阵看做数组

    一些对矩阵的运算需要操作每一个矩阵元素,使用 array() 方法可以让 Eigen 将矩阵看做数组,随后的操作都将是 element-wise(以元素为单位进行处理)。array()不是in-place操作,即 array() 将返回一个和原矩阵完全相同的新矩阵对象。为了效率,Eigen 没有为Matrix类提供element-wise操作,做这些操作需要先将矩阵转化为Array对象,所以自己写代码时要先确定需要哪种对象来完成操作。

    // Square each element of the matrix
    cout << M1 . array () . square () << endl ;
    // Multiply two matrices element - wise
    cout << M1 . array () * Matrix4f :: Identity () . array () << endl ;
    // All relational operators can be applied element - wise
    cout << M1 . array () <= M2 . array () << endl << endl ;
    cout << M1 . array () > M2 . array () << endl ;
    

    向量

    // Utility functions
    Vector3f v1 = Vector3f :: Ones () ;
    Vector3f v2 = Vector3f :: Zero () ;
    Vector4d v3 = Vector4d :: Random () ;
    Vector4d v4 = Vector4d :: Constant (1.8) ;
    cout << v1 * v2 . transpose () << endl ;
    cout << v1 . dot ( v2 ) << endl << endl ;
    cout << v1 . normalized () << endl << endl ;
    cout << v1 . cross ( v2 ) << endl ;
    cout << v1 . array () * v2 . array () << endl << endl ;
    cout << v1 . array () . sin () << endl ;
    
  • 相关阅读:
    7.Flask-上传文件和访问上传的文件
    Python 数字模块
    Django之模板语法
    decimal模块
    python中的计时器:timeit模块
    6.Flask-WTForms
    Django之ORM跨表操作
    公司 邮件 翻译 培训 长难句 16
    公司 邮件 翻译 培训 长难句 15
    公司 邮件 翻译 培训 长难句 14
  • 原文地址:https://www.cnblogs.com/jiahu-Blog/p/11334249.html
Copyright © 2011-2022 走看看