Sie sind auf Seite 1von 10

Remember to include using namespace Eigen;

Matrix

Basic syntax: Matrix3f A; Matrix4d B; Matrix3i C;


Remark: The created matrices are square matrices. [indicated by the number: 2, 3, 4]
Type is indicated by the alphabet. [f:floating; d:double; i:integer; …]

For particular cases, we have column and row vectors.


Vector3f a; RowVector2f b;

Remark: By default, a is a column vector.

Sometimes, we do not know the size during compile time, we may have dynamic size.
MatrixXd A; VectorXi a

Matrix Constructor

There are no initializations for the matrix, but just allocating the memories!
MatrixXf A(10, 15); VectorXf b(30);

A is a 10 x 15 matrix while b is a vector with 30 elements.

Initialization

For vectors, we can simply use parentheses!!


Vector4d c(5.0, 6.0, 7.0, 8.0);
For matrix we need the following:
Matrix3f m;
m << 1, 2, 3,
4, 5, 6,
7, 8, 9;
Or, we can directly input every element.
MatrixXd m(2, 2);
m(0, 0) = 3;
m(1, 0) = 2.5;
m(0, 1) = -1;
m(1, 1) = m(1, 0) + m(0, 1);
Remark: Be careful, we use parentheses, unlike the standard syntax in C++ std lib!!
Assignment and Resizing

We can make assignment for two matrices of different sizes.

MatrixXf A(2, 2);


MatrixXf B(4, 5);
A = B;
cout << A.rows() << 'x' << A.cols(); // 4x5

Remark: We can use X.rows() and X.cols() to assess the size of a matrix X.
Besides, we may use X.resize(r,c) to modify the size.
Remark: One may use X.conservativeResize(r,c) to maintain ALL the previous values.

Arithmetic

We can do addition, subtraction, multiplication as usual…

A + B =
MatrixXf A(2, 2);
0 -1
MatrixXf B(2, 2);
5 4
A << 1, 2,
3, 4; A * 2 =

B << -1, -3, 2 4

2, 0; 6 8

cout << "A + B = \n" << A + B << '\n'; A * B =


cout << "A * 2 = \n" << A * 2 << '\n'; 3 -3
cout << "A * B = \n" << A * B << '\n'; 5 -9

Note: The division operator / is used for scalar division only.

Transpose, conjugate, adjoint

We can define a complex-valued matrix using MatrixXcd. The operations can be computed as
follows.
a.transpose(); a.conjugate(); a.adjoint()

Danger: Transpose and assignment are performed together!!


A = A.transpose(); // Danger!
Remark: One may use X.transposeInPlace() to substitute above action.
Dot Product. Cross Product

See example.

Vector3d v(1, 2, 3);


Vector3d w(0, 1, 2);
cout << "Dot product: " << v.dot(w) << '\n'; //8
cout << "Cross product:\n" << v.cross(w) << '\n'; //1, -2, 1

Remark: Further operations consist of


a.sum(); a.prod(); a.mean(); a.minCoeff(); a.maxCoeff(); a.trace();

Array

Basic syntax: Array3f A; Array33d B; ArrayXXi C;


Remark: The created arrays are 1-D array. Two numbers mean 2-D array.
Type is indicated by the alphabet. [f:floating; d:double; i:integer; …]

Array Initialization

Similarly, we can initialize an array using <<.

ArrayXXd A(2, 2);


A << 1, 2,
3, 4;
cout << A;

Array Arithmetic

We can do addition, subtraction, … as usual. For multiplication, it is done component-wisely.


+,-,*,/…
Note that component-wisely operations can be done using array only. (e.g. A + 2, …)

MatrixXd A(2, 2);


A << 1, 2,
3, 4;
cout << A.array() + 2; // Similarly, for array, we have A.matrix().
Block, row, column of a Matrix/Vector/Array

One may want to extract a block from a matrix.

MatrixXd m(4, 4);


m << 1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,
13, 14, 15, 16;
cout << "Block in the middle" << endl;
cout << m.block<2, 2>(1, 1) << endl << endl;
cout << m.block(1,1,2,2) << endl << endl; // the same!!

Remark: m.block<size>(position) and m.block(position, size) are equivalent!!


(fixed size!!) (dynamic size!!)

cout << m.row(2) << "\n\n"; // 9,10,11,12


cout << m.col(0) << '\n'; // 1, 5, 9, 13

For arrays, we can obtain the first/last element or a part of vector!

ArrayXf v(6);
v << 1, 2, 3, 4, 5, 6;
cout << v.head(3) << endl << endl; // 1, 2, 3
cout << v.tail<3>() << endl << endl; // 4, 5, 6
v.segment(1, 4) *= 2;
cout << v << endl; // 1, 4, 6, 8, 10, 6

Remark: We can summarize it below.

Fixed Dynamic
First n elements v.head(n) v.head<n>()

Last n elements v.tail(n) v.tail<n>()

Middle n elements v.segment(i,n) v.segment<n>(i)


Joining vectors

VectorXd v(3);
v << 1, 2, 3;
VectorXd v2(2);
v2 << 4, 5;
VectorXd joint(5);
joint << v, v2; // Join two vectors
cout << joint;

𝒍𝒍𝒑𝒑 norm

See example.

VectorXf v(2);

v << -1,
2;

cout << v.squaredNorm() << '\n'; // 5


cout << v.norm() << '\n'; // sqrt(5)
cout << v.lpNorm<2>() << '\n'; // sqrt(5)
cout << v.lpNorm<1>() << '\n'; // 3
cout << v.lpNorm<Infinity>() << '\n'; // 2

Some useful Boolean expressions

Three useful Boolean expressions: expr.all();expr.any();expr.count()

ArrayXXf a(2, 2);

a << 1, 2,
3, 4;

cout << (a > 2).all() << '\n'; // 0


cout << (a > 2).any() << '\n'; // 1
cout << (a > 2).count() << '\n'; // 2
Visitors

One can find the location for some characteristics by the Index type.

MatrixXf m(2, 2);

m << 1, 2,
3, 4;

MatrixXf::Index maxRow, maxCol; // The location type is Index!!


float max = m.maxCoeff(&maxRow, &maxCol); // Use & to get the location

MatrixXf::Index minRow, minCol; // The location type is Index!!


float min = m.minCoeff(&minRow, &minCol); // Use & to get the location

cout << "Max: " << max << ", at: " << // Max 4 at (1,1)
maxRow << "," << maxCol << endl;
cout << "Min: " << min << ", at: " << // Min 1 at (0,0)
minRow << "," << minCol << endl;

Row-wise / Col-wise. Broadcasting

If one wants to perform operators in row-wise/ col-wise manner, we may use the code .colwise()
or .rowwise().

MatrixXf mat(2, 4);


mat << 1, 2, 6, 9,
3, 1, 7, 2;

cout << mat.colwise().maxCoeff() << '\n'; // 3 2 7 9


cout << mat.rowwise().maxCoeff() << '\n'; // 9 7

Another example is as follows.

Vector2d v;
v << 0,
1;
mat.colwise() += v; //add v to each column of m

cout << mat << '\n'; // 1 2 6 9


// 4 2 8 3

Mapping (Simple one)

We can turn an array into a matrix.

int array[8];
for (int i = 0; i < 8; ++i) array[i] = i;
cout << Map<Matrix<int, 2, 4> >(array) << '\n'; // Column major
cout << Map<Matrix<int, 2, 4, RowMajor> >(array) << '\n'; // Row major
cout << Map<Matrix<int, 2, 4>, Unaligned, Stride<1, 4> >(array) << '\n';

Remark: One can input a pointer instead of a matrix!

Aliasing problem

Aliasing problem occurs when the same matrix appears on both sides of an assignment.
Component-wise operations are probably alright.
Matrix multiplication allows aliasing problem by default.

MatrixXf matA(2, 2), matB(2, 2);


matA << 2, 0, 0, 2;

matA = matA * matA; // Okay!

matB = matA * matA; // Simple but not quite as efficient


cout << matB << '\n' << '\n';

matB.noalias() = matA * matA; // More complicated but also more efficient


cout << matB;

Other kinds of function should be aware of.


A = A.transpose(); // Danger!
System of Linear Equations

A fundamental way to solve the system is as follows.

Matrix3f A;
Vector3f b;
A << 1, 2, 3, 4, 5, 6, 7, 8, 10;
b << 3, 3, 4;

Vector3f x = A.colPivHouseholderQr().solve(b);

The table shows different numerical method to solve the system.

Remark: It is always advantageous to use Cholesky decomposition if A is SPD.

One can check the relative error of the computation in order to see if a solution exists.

MatrixXd A = MatrixXd::Random(100, 100);


MatrixXd b = MatrixXd::Random(100, 50);
MatrixXd x = A.fullPivLu().solve(b);
double relative_error = (A*x - b).norm() / b.norm(); // norm() is L2 norm
cout << "The relative error is:\n" << relative_error << endl;

Remark: To find a matrix determinant and its inverse, we may use the following.
A.determinant(); A.inverse();
Least-squared Solutions

Basically, we have 3 different numerical methods for it.

MatrixXf A = MatrixXf::Random(3, 2);


VectorXf b = VectorXf::Random(3);

// SUV
cout << A.jacobiSvd(ComputeThinU | ComputeThinV).solve(b) << '\n';
// QR
cout << A.colPivHouseholderQr().solve(b) << '\n';
// normal equation
cout << (A.transpose() * A).ldlt().solve(A.transpose() * b) << '\n';

LU decomposition

See one example.

MatrixXd A(2, 2);


A << 2, -1, 1, 3;
cout << "Here is the input matrix A before decomposition:\n" << A << '\n';

PartialPivLU<Ref<MatrixXd> > lu(A);


cout << "Here is the input matrix A after decomposition:\n" << A << '\n'; //
A is modified!
// If one need the original A, we have to save it first!

Remark: Diagonal entries of 𝐿𝐿 must be ‘1’!!!


Cholesky decomposition

See an example.

MatrixXd A(3, 3);


A << 4, -1, 2, -1, 6, 0, 2, 0, 5;
cout << "The matrix A is" << '\n' << A << '\n';
LLT<MatrixXd> chol(A); // compute the Cholesky decomposition of A
MatrixXd L = chol.matrixL(); // retrieve factor L in the decomposition
// The previous two lines can also be written as "L = A.llt().matrixL()"

cout << "The Cholesky factor L is" << '\n' << L << '\n';
cout << "To check this, let us compute L * L.transpose()" << '\n';
cout << L * L.transpose() << '\n';
cout << "This should equal the matrix A" << '\n';

Das könnte Ihnen auch gefallen