Eigen之矩阵、向量、标量的操作运算

介绍

Eigen是通过中重载C++操作运算符如+、-、*或通过dot()、cross()等来实现矩阵/向量的操作运算

加法和减法

  • binary operator + as in a+b
  • binary operator - as in a-b
  • unary operator - as in -a
  • compound operator += as in a+=b
  • compound operator -= as in a-=b

例子:

#include 
#include 
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;
}

Output:

a + b =
3 5
4 8
a - b =
-1 -1
 2  0
Doing a += b;
Now a =
3 5
4 8
-v + w - v =
-1
-4
-6

标量的乘除

  • binary operator * as in matrix*scalar
  • binary operator * as in scalar*matrix
  • binary operator / as in matrix/scalar
  • compound operator = as in matrix=scalar
  • compound operator /= as in matrix/=scalar
    例子:
#include 
#include 
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;
}

Output:

a * 2.5 =
2.5   5
7.5  10
0.1 * v =
0.1
0.2
0.3
Doing v *= 2;
Now v =
2
4
6

A note about expression templates

这是我们在这个页面上解释的一个高级主题,但是现在只提到它是很有用的。在Eigen,算术运算符,比如运算符+不执行任何计算,他们只是返回一个描述计算的“表达式对象”。实际的计算发生在稍后,当整个表达式被求值时,通常在操作符=。虽然这听起来可能很重,但是任何现代的优化编译器都能够优化抽象,结果是完美的优化代码。例如,当你这样做的时候:

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

Eigen将其编译为一个for循环,这样数组就只遍历一次。简化(例如忽略SIMD优化),这个循环是这样的:

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

因此,你不应该害怕使用Eigen的相对大的算术表达式:这只给了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;

结果:

Here is the matrix a
 (-0.211,0.68) (-0.605,0.823)
 (0.597,0.566)  (0.536,-0.33)
Here is the matrix a^T
 (-0.211,0.68)  (0.597,0.566)
(-0.605,0.823)  (0.536,-0.33)
Here is the conjugate of a
 (-0.211,-0.68) (-0.605,-0.823)
 (0.597,-0.566)    (0.536,0.33)
Here is the matrix a^*
 (-0.211,-0.68)  (0.597,-0.566)
(-0.605,-0.823)    (0.536,0.33)

注:对于一个实数矩阵,conjugate()是没有进行什么操作的,因此adjoint() = transpose()。
对于基本运算操作,transpose()和adjoint() 都仅是返回一个中间变量而没有进行实际的值改变。如果运算时b = a.transpose(),则结果值会赋值给b,但是如果进行的运算为a = a.transpose(),则Eigen会在转置完成之前将值赋值给a,因此无法达到期望的值。
例:

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;

结果:

Here is the matrix a:
1 2
3 4
and the result of the aliasing effect:
1 2
2 4

这种现象被称为混叠问题(aliasing issue)
为解决该问题,可以使用transposeInPlace()函数来完成:

MatrixXf a(2,3); a << 1, 2, 3, 4, 5, 6;
cout << "Here is the initial matrix a:\n" << a << endl;
a.transposeInPlace();
cout << "and after being transposed:\n" << a << endl;

结果:

Here is the initial matrix a:
1 2 3
4 5 6
and after being transposed:
1 4
2 5
3 6

矩阵与矩阵、矩阵与向量间的乘法

  • binary operator * as in a*b
  • compound operator = as in a=b (this multiplies on the right: a*=b
    is equivalent to a = a*b)
    例:
#include 
#include 
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;
}

结果:

Here is mat*mat:
 7 10
15 22
Here is mat*u:
1
1
Here is u^T*mat:
2 2
Here is u^T*v:
-2
Here is u*v^T:
-2 -0
 2  0
Let's multiply mat by itself
Now mat is mat:
 7 10
15 22

提示:对于矩阵的乘法不会出现上述的混叠问题,因为Eigen将乘法作为一个特例

tmp = m*m;
m = tmp;

点乘和叉乘

Eigen中通过dot()和cross()来实现点乘和叉乘
例:

#include 
#include 
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;
}

结果:

Dot product: 8
Dot product via a matrix product: 8
Cross product:
 1
-2
 1

其他基础操作

Eigen还提供了一些函数实现一些其他基本操作,如sum()进行求和,prod()实现矩阵内值的积,maxCoeff()求矩阵内最大值等。
例:

#include 
#include 
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;   // 求对角和
}

结果:

Here is mat.sum():       10
Here is mat.prod():      24
Here is mat.mean():      2.5
Here is mat.minCoeff():  1
Here is mat.maxCoeff():  4
Here is mat.trace():     5

minCoeff()函数和maxCoeff()函数的变换使用:

 Matrix3f m = Matrix3f::Random();
  std::ptrdiff_t i, j;
  float minOfM = m.minCoeff(&i,&j);
  cout << "Here is the matrix m:\n" << m << endl;
  cout << "Its minimum coefficient (" << minOfM 
       << ") is at position (" << i << "," << j << ")\n\n";
  RowVector4i v = RowVector4i::Random();
  int maxOfV = v.maxCoeff(&i);
  cout << "Here is the vector v: " << v << endl;
  cout << "Its maximum coefficient (" << maxOfV 
       << ") is at position " << i << endl;

结果:

Here is the matrix m:
  0.68  0.597  -0.33
-0.211  0.823  0.536
 0.566 -0.605 -0.444
Its minimum coefficient (-0.605) is at position (2,1)

Here is the vector v:  1  0  3 -3
Its maximum coefficient (3) is at position 2

【参考】http://eigen.tuxfamily.org/dox/group__TutorialMatrixArithmetic.html

你可能感兴趣的:(Eigen)