Eigen库学习(三)Matrix和vector算术运算

本节来讲Matrix和Vector的一些算术运算。

一、简介

Eigen提供对C++常见的运算符进行了重载运算,如加减乘除;除此还有一些特殊的方法如dot corss等。需要注意Matlab不一样地方,这里支持的只是常规的线性代数运算,如matrix1*matrix2是支持的,matrix+scalar不支持(matlab支持,表示所有的元素都加上一个常数,但是乘上一个常数支持)。如果你想支持所有的数组元素,请看下一节。

二、加法、乘法

  • 二元运算符 a+b
  • 二元运算符 a-b
  • 一元运算符 -a
  • 复合运算符 += -=
#include <iostream>
#include <Eigen/Dense>
 
using namespace Eigen;
 
int main()
{
  Matrix2d a;
  a << 1, 2,
       3, 4;
  MatrixXd b(2,2);
  b << 2, 3,
       1, 4;
  std::cout << "a + b =\n" << a + b << std::endl;
  std::cout << "a - b =\n" << a - b << std::endl;
  std::cout << "Doing a += b;" << std::endl;
  a += b;
  std::cout << "Now a =\n" << a << std::endl;
  Vector3d v(1,2,3);
  Vector3d w(1,0,0);
  std::cout << "-v + w - v =\n" << -v + w - v << std::endl;
}

三、标量乘和除法

  • 二元运算符 矩阵*scalar
  • 二元运算符 scalar*矩阵
  • 二元运算符 矩阵/scalar
  • 复合运算符 matrix*=scalar
  • 复合运算符 matrix=scalar
#include <iostream>
#include <Eigen/Dense>
 
using namespace Eigen;
 
int main()
{
  Matrix2d a;
  a << 1, 2,
       3, 4;
  Vector3d v(1,2,3);
  std::cout << "a * 2.5 =\n" << a * 2.5 << std::endl;
  std::cout << "0.1 * v =\n" << 0.1 * v << std::endl;
  std::cout << "Doing v *= 2;" << std::endl;
  v *= 2;
  std::cout << "Now v =\n" << v << std::endl;
}

三、不要害怕维度大的矩阵运算

VectorXf a(50), b(50), c(50), d(50);
...
a = 3*b + 4*c + 5*d;

这种运算将会被Eigen优化成:

for(int i = 0; i < 50; ++i)
  a[i] = 3*b[i] + 4*c[i] + 5*d[i];

大的运算将会基于Eigen更多的优化空间。

四、转置和共轭

转置 a T a^T aT(transpose)、共轭 a ˉ \bar a aˉ(conjugation)和伴随矩(adjoint) a ∗ a^* a

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;

注意,在使用transpose的时候,不要赋值给同一个值a = a.transpose();,如果你要对本身进行转置并存于本身,那么请用transposeInPlace

五、矩阵和矩阵 矩阵和向量乘法

#include <iostream>
#include <Eigen/Dense>
 
using namespace Eigen;
int main()
{
  Matrix2d mat;
  mat << 1, 2,
         3, 4;
  Vector2d u(-1,1), v(2,0);
  std::cout << "Here is mat*mat:\n" << mat*mat << std::endl;
  std::cout << "Here is mat*u:\n" << mat*u << std::endl;
  std::cout << "Here is u^T*mat:\n" << u.transpose()*mat << std::endl;
  std::cout << "Here is u^T*v:\n" << u.transpose()*v << std::endl;
  std::cout << "Here is u*v^T:\n" << u*v.transpose() << std::endl;
  std::cout << "Let's multiply mat by itself" << std::endl;
  mat = mat*mat;
  std::cout << "Now mat is mat:\n" << mat << std::endl;
}

Effective C++条款11,自我赋值的问题这里也会出现,如果不确定是否有这样的行为,那么请使用c.noalias()+=a*b;

六、点积和叉积

点积的结果是一个数字,叉积则是一个向量。

#include <iostream>
#include <Eigen/Dense>
 
using namespace Eigen;
using namespace std;
int main()
{
  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;
}

七、其他运算

累加值,累积值,平均值,最小值,最大值和迹。

#include <iostream>
#include <Eigen/Dense>
 
using namespace std;
int main()
{
  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;
}