簡介
Eigen內的Matrix和Vector提供了類似C++的運算符,如+,-,*
;也提供了編程的函數方法,如點乘和叉乘的dot(), cross()
,如此等等。
在Eigen的Matrix類,代表矩陣matrics和向量vector,重載的運算符僅用於支持線性代數的運算,而不支持標量計算。比如matrix1 * matrix2
,表示矩陣matrix 乘以 matrix2,而matrix1 + 10
則不允許。
加法和減法
如大家所知,如果2個矩陣運行運算,對2個矩陣的行數和列數是有條件要求的。另外,在Eigen內,用於計算時,矩陣的係數類型必須統一,並不會內部進行類型轉換。
二元運算符 + : ma + mb;
二元運算符 - : ma - mb;
一元運算符 - : - ma;
組合運算符 +=: ma+=mb;
組合運算符 -=: ma-=mb;
示例:
// matrix_cal1.cpp
#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
int main()
{
Matrix2d a;
a << 1, 2,
3, 4;
MatrixXd b(2,2);
b << 5, 6,
7, 8;
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;
std::cout << endl;
Vector3d v(1,2,3);
Vector3d w(1,0,0);
std::cout << "-v + w - v =\n" << -v + w - v << std::endl;
}
執行後輸出:
$ ./matrix_cal1
a + b =
6 8
10 12
a - b =
-4 -4
-4 -4
Doing a += b;
Now a =
6 8
10 12
-v + w - v =
-1
-4
-6
與標量的乘、除
與標量的乘法和除法計算是支持的,重載的操作符如下:
二元運算符 * : matrix * scalar;
二元運算符 * : scalar * matrix;
二元運算符 / : matrix / scalar;
組合運算符 *=: matrix *= scalar;
組合運算符 /=: matrix /= scalar;
示例:
// matrix_cal2.cpp
#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
int main()
{
Matrix2d a;
a << 1, 2,
3, 4;
std::cout << "a * 2.5 =\n" << a * 2.5 << std::endl;
Vector3d v(1,2,3);
std::cout << "calculating v *= 2;" << std::endl;
v *= 2;
std::cout << "2.0 * v =\n" << 2.0 * v << std::endl;
std::cout << "Now v =\n" << v << std::endl;
}
執行結果:
$ ./matrix_cal2
a * 2.5 =
2.5 5
7.5 10
calculating v *= 2;
2.0 * v =
4
8
12
Now v =
2
4
6
轉置和共軛
在線性代數中,矩陣有轉置操作,共軛計算,共軛轉置計算: , , , Matrix提供了對應的函數:transpose(), conjugate(), and adjoint()
。
說明一下: 共軛是針對複數而言的,共軛矩陣也是複數矩陣的對應的共軛矩陣。
示例程序:
// matrix_cal3.cpp
#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
using namespace std;
int main()
{
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;
}
執行:
$ g++ matrix_cal3.cpp -o matrix_cal3 -I /usr/local/include/eigen3
$ ./matrix_cal3
Here is the matrix a
(-0.999984,-0.736924) (0.0655345,-0.562082)
(0.511211,-0.0826997) (-0.905911,0.357729)
Here is the matrix a^T
(-0.999984,-0.736924) (0.511211,-0.0826997)
(0.0655345,-0.562082) (-0.905911,0.357729)
Here is the conjugate of a
(-0.999984,0.736924) (0.0655345,0.562082)
(0.511211,0.0826997) (-0.905911,-0.357729)
Here is the matrix a^*
(-0.999984,0.736924) (0.511211,0.0826997)
(0.0655345,0.562082) (-0.905911,-0.357729)
對實數矩陣,並沒有對應的共軛矩陣,其共軛轉置矩陣就是其轉置矩陣。
matrix-matrix與matrix-vector的乘法
矩陣的matrix-matrix乘法,及矩陣*矩陣,是由操作符operator *
完成的。而在Eigen內,向量vector也是一種特殊的矩陣,所以,matrix-vector和vector-vector的乘法也是由operator *
來完成。
這裏有2種運算:
- 二元運算符 * : a * b;
- 複合運算符 *=: a *= b;
示例:
// matrix_cal4.cpp
#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;
}
執行
$ g++ matrix_cal4.cpp -o matrix_cal4 -I /usr/local/include/eigen3
$
$ ./matrix_cal4
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
aliasing issues與運算模板
矩陣的點乘與叉乘
使用matrix類的dot(), cross()
函數,來執行矩陣的點乘和叉乘。
點乘的結果可以看出是1X1的矩陣,u * v
還可以使用u.adjoint()*v
進行計算.
示例:
#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
基礎算數操作–arithmetic reduction
對矩陣matrix或向量vector,提供了一些算數分解操作,比如獲取矩陣的係數之和,最大值,最小值,平均值、及對角線的相關算數。
- sum() : 係數之和
- prod() : 係數乘積
- maxCoeff() : 最大系數
- minCoeff() : 最小系數
- trace() : 對角線係數和。
#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; // 10
cout << "Here is mat.prod(): " << mat.prod() << endl; // 24
cout << "Here is mat.mean(): " << mat.mean() << endl; // 2.5
cout << "Here is mat.minCoeff(): " << mat.minCoeff() << endl; // 1
cout << "Here is mat.maxCoeff(): " << mat.maxCoeff() << endl; // 4
cout << "Here is mat.trace(): " << mat.trace() << endl; // 5
}
注意這些函數的重載,還可以同時獲取該係數的位置。
// matrix_cal5.cpp
#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
using namespace std;
int main()
{
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;
}
執行結果如下:
$ g++ matrix_cal5.cpp -o matrix_cal5 -I /usr/local/include/eigen3
$ ./matrix_cal5
Here is the matrix m:
-0.999984 -0.0826997 -0.905911
-0.736924 0.0655345 0.357729
0.511211 -0.562082 0.358593
Its minimum coefficient (-0.999984) is at position (0,0)
Here is the vector v: 933495885 -250177384 41696341 710742668
Its maximum coefficient (933495885) is at position 0