分享

Eigen入门指导书2--矩阵和向量算数运算

 SLAM之路 2022-04-24

矩阵和向量的算数运算

主要针对矩阵间、向量间或前两者与标量间的算数运算;

01

加法和减法

运算符两侧矩阵必须具有相同行数和列数,也必须具有相同类型的元素,Eigen不支持自动类型转换

二元运算符 + , a+b

二元运算符 -  , a-b

一元运算符 -  , -a

复合运算符 += , a+=b

复合运算符 -=  , a-=b

  Eigen::Matrix2d a;  a << 1, 2,       3, 4;  Eigen::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;  Eigen::Vector3d v(1,2,3);  Eigen::Vector3d w(1,0,0);  std::cout << "-v + w - v =\n" << -v + w - v << std::endl;

02

标量乘法和除法

乘以或除以标量是一种简单的运算

二元运算符 * , matrix*scalar

二元运算符 * , scalar*matrix

二元运算符 / , matrix/scalar

复合运算符 *= , matrix*=scalar

复合运算符 /= , matrix/=scalar

Eigen::Matrix2d a;  a << 1, 2,        3, 4;  Eigen::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;

在Eigen中,算数运算符(如+)本身并不进行运算,它只是返回一个“表达式对象”描述如何计算;真实的计算是在后面进行,当评估完整个表达式(一般在=处)

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中应当警惕这种相对比较大的算数运算,这给与Eigen更多优化的机会;

03

转置和共轭

矩阵或向量的转置、共轭、共轭转置可分别通过成员函数:

transpose()、conjugate()、adjoint();

对实矩阵,共轭矩阵即是本身,共轭转置等同于转置;

Eigen::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;

注:如算数计算,转置和共轭转置仅仅返回代理对象,并实际并未转置:如果执行b=a.transpose(),那么在将结果写入b的同时进行转置;若是进行a=a.transpose(),在完成转置前结果已经写入a,因此并不会用a的转置替换a;

Eigen::Matrix2i a; a << 1, 2, 3, 4; cout << "Here is the matrix a:\n" << a << endl;a = a.transpose(); // !!! do NOT do this !!!cout << "and the result of the aliasing effect:\n" << a << endl;

以上就是所谓的化名混淆问题,为解决这种问题可以通过增加临时变量或使用函数a.transposeInPlace();

04

矩阵×矩阵 和 矩阵×向量

矩阵✖矩阵使用符号*,因为向量是矩阵的特列,所以矩阵✖向量仅仅是矩阵✖矩阵的特列;

二元运算符 * , a*b

复合运算符 *= , a*=b

  Eigen::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;

注:Eigen中矩阵乘法是一种特列,会引入临时变量以避免化名混淆现象;

05

点积和叉积

点积和叉积分别使用dot()和cross()方法;

 Eigen::Vector3d v(1,2,3);  Eigen::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;

06

算数归约操作

Eigen提供一些缩减操作,以减少给定的矩阵或向量为单一的值:

求和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;

注:本文参考自https://eigen./dox/group__TutorialMatrixArithmetic.html

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约