0% found this document useful (0 votes)
54 views10 pages

Matrix: Remark: The Created Matrices Are Square Matrices. (Indicated by The Number: 2, 3, 4)

The document summarizes key concepts about matrices and vectors in Eigen, a C++ library for linear algebra. It covers basic syntax, initialization, arithmetic operations, transposition, solving linear systems, least squares solutions, and LU decomposition. Functions like matrix(), vector(), row(), col(), transpose(), inverse(), and decomposition methods like QR, SVD, Cholesky are demonstrated.

Uploaded by

Tsang MY
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
54 views10 pages

Matrix: Remark: The Created Matrices Are Square Matrices. (Indicated by The Number: 2, 3, 4)

The document summarizes key concepts about matrices and vectors in Eigen, a C++ library for linear algebra. It covers basic syntax, initialization, arithmetic operations, transposition, solving linear systems, least squares solutions, and LU decomposition. Functions like matrix(), vector(), row(), col(), transpose(), inverse(), and decomposition methods like QR, SVD, Cholesky are demonstrated.

Uploaded by

Tsang MY
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 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';

You might also like