Introduction to Armadillo#

Armadillo is an efficient linear algebra library for C++, that balances speed and ease of use. We recommend using this library for numerical linear algebra computations in this course.

We’ll cover some of the very basics of Armadillo here to get you started with the library. A complete overview of the available classes and functions, along with usage examples, can be found in the Armadillo code documentation.

Building code with Armadillo#

We must make sure to include the header file for Armadillo, which amounts to adding #include <armadillo> at the top of a header or source file.

Compiling code with Armadillo#

For macOS users specifically, you must specificy a version of C++ that is C++11 or later. This is done by adding the compiler flag -std=c++11 during compilation.

For Linux users, nothing special is typically required.

Linking code with Armadillo#

To link to Armadillo, we must add the compiler flag -larmadillo during linking.

Vectors#

Armadillo provides a useful vector class arma::vec that can be used to replace arrays in numerical computations. Assume n is a positive integer.

Declaring and filling vectors#

arma::vec x = arma::vec(n); //Initialize vector but don't fill it.
arma::vec y = arma::vec(n).fill(2.); //Declare and fill a vector with 2's.
arma::vec z = arma::vec(n).randu(); //Declare and fill a vector with random values from a uniform distribution.
arma::vec u = arma::vec("0.0 0.1 0.2"); //Declare and fill a vector with the values 0.1, 0.2 and 0.3.

Accessing and assigning elements in a vector#

We can access an element i from a vector x by

double x_i = x(i); //Extract element i of x and assign it to x_i.

We can assign a new value to element i in the vector x using

x(i) = some_new_value;

Matrices#

Assume that n and m are positive integers.

Declaring and filling matrices#

Creating matrices with Armadillo is easy. Here’s a couple examples:

arma::mat A = arma::mat(n, m); //Initialize matrix but don't fill.
arma::mat B = arma::mat(n, m).fill(0.); //Declare and fill a matrix with zeros.
arma::mat C = arma::mat(n, m).randn(); //Declare and fill a matrix with random values from the normal distribution.
arma::mat D = arma::mat("0.0 0.1 0.2 ; 1.0 1.1 1.2 ; 2.0 2.1 2.2"); //Declare and fill a 3x3 matrix with the listed values. (Note the semicolons.)

Accessing elements in a matrix#

Access of elements in an Armadillo matrix is done as follows:

double A_ij = A(i,j); //Assign element (i,j) of the matrix A to A_ij.

Extracting a column of a matrix#

Armadillo provides a simple way to extract entire columns of a matrix:

arma::vec col_vec = A.col(j); //Extract column j of A and assign it to col_vec.

Read matrix columns in a given order#

A particular task that may be useful in this course is to read the columns of a matrix in a specific order. Below is an example that uses arma::sort_index to find the index ordering that sorts a given vector (from low to high values), and then sorts both the vector and the columns of a matrix according to this ordering.

arma::mat A = arma::mat("0.0 0.1 0.2 ; 1.0 1.1 1.2 ; 2.0 2.1 2.2");
arma::vec x = arma::vec("20. 10. 30.");

arma::uvec x_sort_indices = arma::sort_index(x); // Get index ordering that sorts x.
  
x = x(x_sort_indices); // Sort x according to ordering in x_sort_indices.
A = A.cols(x_sort_indices); // Sort columns of A according to ordering in x_sort_indices.

Saving and loading vectors and matrices#

Armadillo provides built-in functionality for saving and loading arma::vec and arma::mat objects to binary files. Not only does this simplify storage of results with a predictable format, but it turns out that they provide a Python module pyarma that can me used to load in these objects directly into a Python program!

If A is an arma::mat object, you can save it using

A.save(filename);

The default storage format is binary. Your filename should end with .bin. Loading the object is as simple as

B = arma::mat() //Initialize an arma::mat variable
B.load(filename) //Load content of arma::mat A stored earlier into arma::mat B.

Reading a data table in text format#

The load functionality in Armadillo can also be used to load data from files not generated by Armadillo, as long as the data file has some standard format (see the Armadillo documentation for details). For instance, assume we have a text file mynumbers.dat looking like this:

0.0000e+00  0.0000e+00  0.0000e+00
0.0000e+00  1.9635e-01  3.8553e-02
0.0000e+00  3.9270e-01  1.5421e-01
0.0000e+00  5.8905e-01  3.4698e-01
0.0000e+00  7.8540e-01  6.1685e-01
1.9635e-01  0.0000e+00  1.9635e-01
1.9635e-01  1.9635e-01  2.4247e-01
1.9635e-01  3.9270e-01  3.6569e-01
1.9635e-01  5.8905e-01  5.6599e-01
1.9635e-01  7.8540e-01  8.4336e-01
3.9270e-01  0.0000e+00  3.9270e-01
3.9270e-01  1.9635e-01  4.6150e-01
3.9270e-01  3.9270e-01  6.0723e-01
3.9270e-01  5.8905e-01  8.2971e-01
3.9270e-01  7.8540e-01  1.1288e+00
5.8905e-01  0.0000e+00  5.8905e-01
5.8905e-01  1.9635e-01  6.9558e-01
5.8905e-01  3.9270e-01  8.7831e-01
5.8905e-01  5.8905e-01  1.1363e+00
5.8905e-01  7.8540e-01  1.4688e+00

To read these numbers into an Armadillo matrix, we simply do this:

arma::mat A;
A.load("mynumbers.dat", arma::raw_ascii)

The Python module#

You can install the Armadillo Python module pyarma using

pip install pyarma

The recommended way to import the library in Python is

import pyarma as pa

From there, you can easily load the arma::mat (or arma::vec) object you saved in C++ using

A = pa.mat() #Create pa.mat object (just as arma::mat in C++)
A.load(filename) #Load the content of the matrix you saved into your Python program.