一.Eigen库模块和头文件

Eigen库被分为一个Core模块和其他一些模块,每个模块有一些相应的头文件。 为了便于引用,Dense模块整合了一系列模块;Eigen模块整合了所有模块。一般情况下,include<Eigen/Dense> 就够了。

R语言求特征值与特征矩阵 r语言eigen函数的特征向量_开发语言

二、矩阵和向量定义与初始化

1.模板

  在Eigen,所有的矩阵和向量都是Matrix模板类的对象,Vector只是一种特殊的矩阵(一行或者一列)。Matrix有6个模板参数,主要使用前三个参数,剩下的有默认值。

Matrix<typename Scalar,
       int RowsAtCompileTime,
       int ColsAtCompileTime,
       int Options = 0,
       int MaxRowsAtCompileTime = RowsAtCompileTime,
       int MaxColsAtCompileTime = ColsAtCompileTime>

Scalar是表示元素的类型,RowsAtCompileTime为矩阵的行,ColsAtCompileTime为矩阵的列。 

Options是一个比特标志位,这里,我们只介绍一种RowMajor,它表明matrix使用按行存储,默认是按列存储。

MaxRowsAtCompileTime和MaxColsAtCompileTime表示在编译阶段矩阵的上限。主要是避免动态内存分配,使用数组。

2.矩阵创建与初始化

Ⅰ.创建:Eigen定义了一些通用类型

  • MatrixNt = Matrix<type, N, N> 特殊地有 MatrxXi = Matrix<int, Dynamic, Dynamic>
  • VectorNt = Matrix<type, N, 1> 比如 Vector2f = Matrix<float, 2, 1>
  • RowVectorNt = Matrix<type, 1, N> 比如 RowVector3d = Matrix<double, 1, 3>

N可以是2,3,4或X(Dynamic),t可以是i(int)、f(float)、d(double)、cf(complex)、cd(complex)等。

常用如下: 

typedef Matrix<float, 4, 4> Matrix4f; //矩阵


typedef Matrix<float, 3, 1> Vector3f; //向量
typedef Matrix<int, 1, 2> RowVector2i;

typedef Matrix<double, Dynamic, Dynamic> MatrixXd; //动态矩阵
typedef Matrix<int, Dynamic, 1> VectorXi;

Ⅱ.初始化:

        默认构造函数不执行任何空间分配,也不初始化矩阵的元素。

Matrix3f a; //a是一个3*3的矩阵,分配了float[9]的空间,但未初始化内部元素
MatrixXf b; //b是一个动态大小的矩阵,定义是未分配空间(0*0)
Matrix3f a(3,3); //对指定大小的Matrix传递sizes也是合法的(传递被忽略)

 使用构造函数提供4以内尺寸的vector的初始化:

Vector2d a(5.0, 6.0);
Vector3d b(5.0, 6.0, 7.0);

 逗号初始化:

Matrix3f m;
m << 1, 2, 3,
     4, 5, 6,
     7, 8, 9;
std::cout << m;

        使用块结构初始化(块操作在下面矩阵操作详细介绍):

MatrixXf matA(2, 2);
matA << 1, 2, 3, 4;
MatrixXf matB(4, 4);
matB << matA, matA/10, matA/10, matA;
std::cout << matB << std::endl;

       使用功能函数:setZero(), MatrixBase::setIdentity()和 DenseBase::setLinSpaced()

const size = 6;
MatrixXd mat2(size, size);
mat2.topLeftCorner(size/2, size/2).setZero();
mat2.topRightCorner(size/2, size/2).setIdentity();
mat2.bottomLeftCorner(size/2, size/2).setIdentity();
mat2.bottomRightCorner(size/2, size/2).setZero();
std::cout << mat2 << std::endl << std::endl;

Ⅲ 特殊的矩阵和向量的创建

        零阵:类的静态成员函数Zero(),有三种定义形式

        类似的有常量矩阵:Constant([rows],[cols],value),Random()随机矩阵

        单位阵Identity()方法只能使用与Matrix不使用Array

std::cout << "A fixed-size array:\n";
Array33f a1 = Array33f::Zero();
std::cout << a1 << "\n\n";
std::cout << "A one-dimensional dynamic-size array:\n";
ArrayXf a2 = ArrayXf::Zero(3);
std::cout << a2 << "\n\n";
std::cout << "A two-dimensional dynamic-size array:\n";
ArrayXXf a3 = ArrayXXf::Zero(3, 4);
std::cout << a3 << "\n";


输出:
A fixed-size array:
0 0 0
0 0 0
0 0 0

A one-dimensional dynamic-size array:
0
0
0

A two-dimensional dynamic-size array:
0 0 0 0
0 0 0 0
0 0 0 0

         LinSpaced(size, low, high),生成一个从low到high等间距取值的矩阵,间距为size

ArrayXXf table(10, 4);
table.col(0) = ArrayXf::LinSpaced(10, 0, 90);
std::cout << table.col(0) << std::endl;

3.矩阵基础操作与元素访问

  Ⅰ 元素访问:通过中括号获取元素,对于矩阵是:(行,列);对于向量,只是传递它的索引,以0为起始。

MatrixXd m(2,2);
  m(0,0) = 3;
  m(1,0) = 2.5;

m(index)也可以用于获取矩阵元素,但取决于matrix的存储顺序,默认是按列存储的,当然也可以改为按行。[ ]操作符可以用于向量元素的获取,但是不能用于matrix,因为C++中[]不能传递超过一个参数。

        Ⅱ 矩阵操作

  resize:重新调整动态matrix的大小

MatrixXd m(2,5);
  m.resize(4,3);  //m大小变为4x3

块操作:函数.block(),有两种形式

operation

构建一个动态尺寸的block

构建一个固定尺寸的block

起点(i,j)块大小(p,q)

.block(i,j,p,q)

.block< p,q >(i,j)

Eigen::MatrixXf m(4,4);
  m <<  1, 2, 3, 4,
        5, 6, 7, 8,
        9,10,11,12,
       13,14,15,16;
  cout << "Block in the middle" << endl;
  cout << m.block<2,2>(1,1) << endl << endl;

  角相关操作 

operation

dynamic-size block

fixed-size block

左上角p\*q

matrix.topLeftCorner(p,q);

matrix.topLeftCorner< p,q >();

左下角p\*q

matrix.bottomLeftCorner(p,q);

matrix.bottomLeftCorner< p,q >();

右上角p\*q

matrix.topRightCorner(p,q);

matrix.topRightCorner< p,q >();

右下角p\*q

matrix.bottomRightCorner(p,q);

matrix.bottomRightCorner< p,q >();

前q行

matrix.topRows(q);

matrix.topRows< q >();

后q行

matrix.bottomRows(q);

matrix.bottomRows< q >();

左p列

matrix.leftCols(p);

matrix.leftCols< p >();

右p列

matrix.rightCols(p);

matrix.rightCols< p >();

Eigen::Matrix4f m;
  m << 1, 2, 3, 4,
       5, 6, 7, 8,
       9, 10,11,12,
       13,14,15,16;
  cout << "m.leftCols(2) =" << endl << m.leftCols(2) << endl << endl;

  vectors的块操作:

operation

dynamic-size block

fixed-size block

前n个

vector.head(n);

vector.head< n >();

后n个

vector.tail(n);

vector.tail< n >();

i起始的n个元素

vector.segment(i,n);

vector.segment< n >(i);

 assignment:复制一个矩阵到另外一个,操作符=。Eigen会自动resize左变量大小等于右变量大小,当左边矩阵大小固定时不允许这样操作。

MatrixXf a(2,2);
MatrixXf b(3,3);
a = b;  //a变成了3x3

   +,- 运算:左右两侧变量具有相同的尺寸(行和列),并且元素类型相同(Eigen不自动转化类型),包括a+b、a-b、-a、a+=b、a-=b

Matrix2d a;
  a << 1, 2,
       3, 4;
  MatrixXd b(2,2);
  b << 2, 3,
       1, 4;
a + b;
a += b;

  x、÷(标量): matrix*scalar、scalar*matrix、matrix/scalar、matrix*=scalar、matrix/=scalar

Matrix2d a;
  a << 1, 2,
       3, 4;
  Vector3d v(1,2,3);
  v *= 2;

        ×(矩阵): a*b、a*=b

Matrix2d mat;
  mat << 1, 2,
         3, 4;
  mat = mat*mat;

 向量点积和叉运算:dot()执行点积,cross()执行叉积

Vector3d v(1,2,3);
  Vector3d w(0,1,2);
  cout << "Dot product: " << v.dot(w) << endl;
  double dp = v.adjoint()*w; // automatic conversion of the inner product to a scalar
  cout << "Dot product via a matrix product: " << dp << endl;
  cout << "Cross product:\n" << v.cross(w) << endl;

转置和共轭:transpose转置、conjugate共轭、adjoint(共轭转置) 伴随矩阵

MatrixXcf a = MatrixXcf::Random(2,2);
cout << "Here is the matrix a\n" << a << endl;
cout << "Here is the matrix a^T\n" << a.transpose() << endl;
cout << "Here is the conjugate of a\n" << a.conjugate() << endl;
cout << "Here is the matrix a^*\n" << a.adjoint() << endl;

归约:sum()、prod()、maxCoeff()和minCoeff(),他们对所有元素进行操作

Eigen::Matrix2d mat;
  mat << 1, 2,
         3, 4;
  cout << "Here is mat.sum():       " << mat.sum()       << endl; //加
  cout << "Here is mat.prod():      " << mat.prod()      << endl; //乘
  cout << "Here is mat.mean():      " << mat.mean()      << endl; //平均
  cout << "Here is mat.minCoeff():  " << mat.minCoeff()  << endl; //最小值
  cout << "Here is mat.maxCoeff():  " << mat.maxCoeff()  << endl; //最大值
  cout << "Here is mat.trace():     " << mat.trace()     << endl; //迹(对角线元素和)

   4.Array类和元素级操作      

        相对于Matrix提供的线性代数运算,Array类提供了更为一般的数组功能。Array类为元素级的操作提供了有效途径,比如点加(每个元素加值)或两个数据相应元素的点乘。

Array是个类模板(类似于Matrx),前三个参数是必须指定的,后三个是可选的

Array<typename Scalar, int RowsAtCompileTime, int ColsAtCompileTime>

Type

Tyoedef

Array<float,Dynamic,1>

ArrayXf

Array<float,3,1>

Array3f

Array<double,Dynamic,Dynamic>

ArrayXXd

Array<double,3,3>

Array33d

        2.初始化和获取元素都类似于矩阵

        3.加减乘也类似于矩阵,但要求大小相同,而且乘法执行的是相应元素相乘

        4.其他元素级操作

Function

function

abs

绝对值

sqrt

平方根

min(.)

两个array相应元素的最小值

         5.array和matrix之间的转换

        当需要线性代数类操作时,请使用Matrix;但需要元素级操作时,需要使用Array。这样就需要提供两者的转化方法。

        Matrix提供了.array()函数将它们转化为Array对象。

        Array提供了.matrix()函数将它们转化为Matrix对象。

        另外,Matrix提供了cwiseProduct函数也实现了点乘。

MatrixXf m(2,2);
  MatrixXf n(2,2);
  MatrixXf result(2,2);
  m << 1,2,
       3,4;
  n << 5,6,
       7,8;
  result = m * n;
  cout << "-- Matrix m*n: --" << endl << result << endl << endl;
  result = m.array() * n.array();
  cout << "-- Array m*n: --" << endl << result << endl << endl;
  result = m.cwiseProduct(n);
  cout << "-- With cwiseProduct: --" << endl << result << endl << endl;
  result = m.array() + 4;
  cout << "-- Array m + 4: --" << endl << result << endl << endl;