Eigen库学习 ---- 2.矩阵\向量的算数运算

Eigen库学习 ---- 2.矩阵\向量的算数运算

上篇:Eigen库学习 ---- 1.矩阵类
本篇为这个链接的学习总结。

  Eigen库提供了矩阵\向量的算数运算,如‘+ - * /’,或者特殊运算,如’dot(),cross()’。

一、加法和减法运算

  加减运算必须保证两边的矩阵\向量的维度相同,即有相同的rows和cols,元素的类型也必须相同,因为Eigen不会自动提升数据类型。加减运算有如下:
√ 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 (混合运算符
例如:

Matrix2d a;
	a << 1,2,3,4;
	MatrixXd b(2,2);
	b << 2, 3, 1, 4;
	cout << "a+b=\n" << a + b << endl;
	cout << "a-b=\n" << a - b << endl;
	a += b;
	cout << "Now a=\n" << a << endl;
	Vector3d v(1, 2, 3);
	Vector3d w(1, 0, 0);
	cout << "-v+w-v=\n" << -v + w - v << endl;

输出结果如下:

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

二、标量 与 矩阵\向量 的 乘\除法 运算

标量的乘法和除法很简单,运算符如下:
√ binary operator * as in ‘matrix * scalar’( 二元运算符
√ binary operator * as in ‘scalar * matrix’( 二元运算符
√ unary operator / as in ‘matrix/scalar’( 一元运算符
√ compound operator * = as in ‘matrix*=scalar’( 混合运算符
√ compound operator /= as in ‘matrix/=scalar’( 混合运算符
例如:

	Matrix2d a;
	a << 1, 2, 3, 4;
	Vector3d v(1,2,3);
	cout << "a*2.5=\n" << a*2.5 << endl;
	cout << "0.1*v=\n" << 0.1*v << endl;
	v *= 2;
	cout << "v*=2,v=\n" << v << endl;

输出结果如下:

a*2.5=
2.5   5
7.5  10
0.1*v=
0.1
0.2
0.3
v*=2,v=
2
4
6

三、Eigen乘法运算的简洁表达

  Eigen对代码做了许多优化,可以不用写一些很冗余的代码,如下面的表达式:

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

  在Eigen库中,可以这样简洁的写:

a = 3 * b + 4 * c + 5 * d;

四、矩阵的转置、伴随、共轭

             A T A^T AT   A ∗ A^* A   A ˉ \bar{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 matrix a^*:\n" << a.adjoint() << endl;
cout << "Here is the conjugate of matrix a:\n" << a.conjugate() << endl;

输出结果如下:

Here is the matrix a:
 (0.127171,-0.997497) (-0.0402539,0.170019)
 (0.617481,-0.613392)  (0.791925,-0.299417)
Here is the matrix a^T:
 (0.127171,-0.997497)  (0.617481,-0.613392)
(-0.0402539,0.170019)  (0.791925,-0.299417)
Here is the matrix a^*:
   (0.127171,0.997497)    (0.617481,0.613392)
(-0.0402539,-0.170019)    (0.791925,0.299417)
Here is the conjugate of matrix a:
   (0.127171,0.997497) (-0.0402539,-0.170019)
   (0.617481,0.613392)    (0.791925,0.299417)

  对于基本的算数运算符,transpose()和adjuint()只返回一个代理对象,而不执行实际的转置。如果执行b=transpose(),则将结果写入b的同时计算转置。如果执行a=a.transpose(),则在转置求完值之前,Eigen开始将结果写入a。因此,a=a.transpose()不会像预期的那样转置替换a。如下:

Matrix2i a;
a << 1, 2, 3, 4;
cout << "Here is the matrix a:\n" << a << endl;
//a = a.transpose();//这一句如果运行,会报错,报错类型是:别名问题。
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
3 4

  如果要执行原地转置,例如在a=a.transpose()中,只需使用transposeInPlace ()函数即可。例如:

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

输出结果如下:

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

五、矩阵乘矩阵/矩阵乘向量

  矩阵与矩阵相乘用的是操作符*。因为向量是一种特殊的矩阵,所以矩阵与向量的积实际上只是矩阵与矩阵的积的一种特殊情况,向量外积也是。所以操作符只有两个:
√ binary operator * as in a * b( 二元运算符
√ compound operator * = as in a * =b( 混合运算符
例如:

Matrix2d mat;
	mat << 1, 2,
		   3, 4;
	Vector2d u(-1, 1), v(2, 0);
	cout << "Here is mat*mat:\n" << mat * mat << endl << endl;
	cout << "Here is mat*u:\n" << mat * u << endl << endl;
	cout << "Here is mat*v:\n" << mat * v << endl << endl;
	cout << "Here is u^T*mat:\n" << u.transpose() * mat << endl << endl;
	cout << "Here is u^T*v:\n" << u.transpose() * v << endl << endl;
	cout << "Here is u*v^T:\n" << u * v.transpose() << endl << endl;
	cout << "Let's multiply mat by itself." <<  endl;
	mat = mat * mat;
	cout << "Now mat is:" << endl;
	cout << mat << endl;

输出结果如下:

Here is mat*mat:
 7 10
15 22

Here is mat*u:
1
1

Here is mat*v:
2
6

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:
 7 10
15 22

六、点乘和叉乘

  点乘和叉乘是用的dot()和cross()方法。点乘可以理解为1x1的矩阵,如u.adjoint()*v
例如:

Vector3d v(1,2,3);
Vector3d w(0,1,2);
cout << "点乘:" << v.dot(w) << endl;
double dp = v.adjoint()*w;
cout << "通过矩阵乘法的点乘:" << dp << endl;
cout << "叉乘:\n" << v.cross(w) << endl;

输出结果为:

点乘:8
通过矩阵乘法的点乘:8
叉乘:
 1

七、基本算数运算简化计算

  Eigen提供了一些基本运算来简化矩阵和向量的运算。如sum()求和,prod()求积,maxCoeff()求元素的最大值,minCoeff()求元素最小值。
例如:

Matrix2d mat;
	mat << 1,2,
		   3,4;
	cout << "Here is mat.sum():     " << mat.sum() << endl;
	cout << "Here is mat.prob():    " << 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.prob():    24
Here is mat.mean():    2.5
Here is mat.minCoeff():1
Here is mat.maxCoeff():4
Here is mat.trace():   5

  函数trance()返回的是矩阵的对角线之和,也可以用diagonal().sum()来高效地计算。minCoeff和maxCoeff也存在变体,可以通过给定参数来返回相应元素的坐标。
例如:

Matrix3f m = Matrix3f::Random();
	ptrdiff_t i, j;
	float minOfM = m.minCoeff(&i, &j);
	cout << "Here is the matrix m:\n" <<m<< endl;
	cout << "Its minimum cofficient (" << 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.997497   0.617481  -0.299417
  0.127171   0.170019   0.791925
 -0.613392 -0.0402539    0.64568
Its minimum cofficient (-0.997497) is at position (0,0)

Here is the vector v:  8080 -10679  11761   6897
Its maximum coefficient (11761) is at position 2

下篇:Eigen库学习 ---- 3.数组类和系数运算

Guess you like

Origin blog.csdn.net/qq_39400324/article/details/115921747