本文主要是Eigen中矩阵和向量的算术运算,在Eigen中的这些算术运算重载了C++的+,-,*,所以使用起来非常方便。
1.矩阵的运算
Eigen通过常见的C ++算术运算符(例如+,-,*)的重载,或通过诸如dot(),cross()等特殊方法的方式提供矩阵/矢量算术运算。对于Matrix类(矩阵和向量),运算符仅重载以支持线性代数运算。例如,matrix1 * matrix2表示矩阵矩阵乘积,并且vector + scalar是不允许的
Eigen提供+、-、一元操作符“-”、+=、-=
加减
左侧和右侧必须具有相同数量的行和列。它们还必须具有相同的类型
支持的操作有:
二进制运算符+如 a+b
二进制运算符-如 a-b
一元运算符-如 -a
复合运算符+ =如 a+=b
复合运算符-=如 a-=b
#include <iostream>
#include <eigen3/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;
}
输出:
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
与标量(scalar)乘除
二进制运算符如 matrixscalar
二进制运算符如 scalarmatrix
二元运算符/如 matrix/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;
}
输出:
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
注意:
关于表达式模板:
在Eigen中,算术操作例如 “操作符+”并不会自己执行计算操作,他们只是返回一个“算术表达式对象”,而实际的计算则会延迟到后面的赋值时才进行。这些不影响你的使用,它只是为了方便Eigen的优化。
矩阵的转置、共轭矩阵、伴随矩阵(共轭转置)
可以通过 成员函数transpose(), conjugate(),和 adjoint()来完成,注意这些函数返回操作后的结果,而不会对原矩阵的元素进行直接操作,如果要让原矩阵的进行转换,则需要使用响应的InPlace函数,例如:transposeInPlace() 、 adjointInPlace() 之类。
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()
矩阵相乘、矩阵向量相乘
矩阵的相乘,矩阵与向量的相乘也是使用操作符*,共有和=两种操作符,其用法可以参考如下代码:
#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;
}
输出:
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
向量内积(点积)、求共轭向量(叉积)
#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;
}
输出:
Dot product: 8
Dot product via a matrix product: 8
Cross product:
1
-2
1
点积也可以通过 1x1 matrix as u.adjoint()*v 获得
叉积仅适用于大小为3的向量。点积适用于任何大小的向量。当使用复数时,Eigen的点积在第一个变量中是共轭线性的,而在第二个变量中是线性的。
矩阵内一些性质:平均值、和、迹
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
注:迹 通过trace()获得,是对角系数之和,也可以通过a.diagonal().sum()获得
矩阵极大小值元素及其位置
int main(int argc, char const *argv[])
{
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;
return 0;
}
output:
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
操作的有效性
Eigen 检查操作的有效性,在可能的情况下,它在编译阶段检查,输出编译错误,这些错误可能何尝也很难看,但Eigen将这些信息输出到UPPERCASE_LETTERS_SO_IT_STANDS_OUT.例如:
Matrix3f m;
Vector4f v;
v = m*v; // Compile-time error: YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES
当然在很多情况下,在编译阶段无法检查出错误,Eigen使用运行时断言,这意味着在调试模式下程序将会在运行至非法操作时终止并抛出错误信息,如果关闭断言,程序会漰溃
MatrixXf m(3,3);
VectorXf v(4);
v = m * v; // Run-time assertion failure here: "invalid matrix product"