Back to TIL list

Álgebra linear com Armadillo

Created at

Algebra linear com a biblioteca armadillo.

$$ A_{m,n} = \begin{pmatrix} a_{1,1} & a_{1,2} & \cdots & a_{1,n} \\ a_{2,1} & a_{2,2} & \cdots & a_{2,n} \\ \vdots & \vdots & \ddots & \vdots \\ a_{m,1} & a_{m,2} & \cdots & a_{m,n} \end{pmatrix} $$

Armadillo é uma biblioteca de álgebra linear para C++ rápida e fácil de usar, com sintaxe parecida com a do Matlab.

Provê suporte para:

  • vetores (tensores de primeira ordem)
  • matrizes (tensores de segunda ordem)
  • cubos (tensores de terceira ordem)
  • matrizes densas e esparsas
  • números inteiros, de ponto flutuante e complexos
  • decomposição (via LAPACK)
  • multi-thread (Intel MKL ou OpenBLAS)
  • avaliador de expressão baseado em meta-programação
  • paralelização (via OpenMP)

Principais usos:

  • machine learning
  • reconhecimento de padrões
  • visão computacional
  • processamento de sinais
  • bioinformática
  • estatística
  • finanças

Instalação no Debian

apt install libarmadillo-dev

Instalação no MacOS

brew install armadillo

Exemplos de uso

#include <armadillo>
#include <iostream>

using namespace std;
using namespace arma;

int main()
{
  // inicia o gerador de números aleatórios
  arma_rng::set_seed_random();

  // Cria uma matriz com dados aleatório com dimensão 2x3
  auto A = randu( 2, 3 );
  cout << A << endl;
  //    0.7038   0.6819   0.9555
  //    0.3804   0.9666   0.9270

  // Transposta
  cout << A.t() << endl;
  //    0.7526   0.5681
  //    0.5874   0.9469
  //    0.3562   0.9346

  // Multiplicação de matrizes
  cout << A.t() * A << endl;
  //    0.0536   0.2644   0.2534
  //    0.4731   0.3874   0.9599
  //    0.1739   0.3313   0.4768

  mat B( 3, 3, fill::randu );
  cout << B << endl;
  //    0.9563   0.8955   0.0919
  //    0.3291   0.3086   0.3452
  //    0.1894   0.9898   0.8642

  cout << "Determinante: " << det( B ) << endl;
  // Determinante: -0.243228

  auto C = randu( 3, 3 );
  cout << C << endl;
  //    0.5561   0.6219   0.2147
  //    0.3105   0.2813   0.9172
  //    0.3408   0.1925   0.4703
  cout << "Determinante: " << det( C ) << endl;
  // Determinante: -0.254525

  mat D = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
  cout << D << endl;
  //    1.0000   2.0000   3.0000
  //    4.0000   5.0000   6.0000
  //    7.0000   8.0000   9.0000
  cout << "Determinante: " << det( D ) << endl;
  // Determinante: 6.66134e-16

  D.row( 0 ) = D.row( 1 ) + D.row( 2 );
  cout << D << endl;
  // 11.0000   13.0000   15.0000
  //  4.0000    5.0000    6.0000
  //  7.0000    8.0000    9.0000

  D.row( 1 ) = D.row( 1 ) * 5;
  cout << D << endl;
  // 11.0000   13.0000   15.0000
  // 20.0000   25.0000   30.0000
  //  7.0000    8.0000    9.0000
  //

  D.row( 2 ).zeros();
  cout << D << endl;
  // 11.0000   13.0000   15.0000
  // 20.0000   25.0000   30.0000
  //       0         0         0

  D.col( 2 ) = D.col( 2 ) + 10;
  cout << D << endl;
  // 11.0000   13.0000   25.0000
  // 20.0000   25.0000   40.0000
  //       0         0   10.0000

  D = diagmat( D );
  cout << D << endl;
  // 11.0000         0         0
  //       0   25.0000         0
  //       0         0   10.0000

  D.save( "D.bin" );

  D.save( "D.txt", arma_ascii );
  // ARMA_MAT_TXT_FN008
  // 3 3
  //    1.10000000000000e+01   0.00000000000000e+00   0.00000000000000e+00
  //    0.00000000000000e+00   2.50000000000000e+01   0.00000000000000e+00
  //    0.00000000000000e+00   0.00000000000000e+00   1.00000000000000e+01

  auto O = ones( 2, 2 );
  cout << O << endl;
  // 1.0000   1.0000
  // 1.0000   1.0000

  auto Z = zeros( 3, 5 );
  cout << Z << endl;
  // 0        0        0        0        0
  // 0        0        0        0        0
  // 0        0        0        0        0

  mat F1, F2;
  F1.load( "D.bin" );
  F2.load( "D.txt" );
  cout << F1 << endl;
  // 11.0000         0         0
  //       0   25.0000         0
  //       0         0   10.000

  cout << F1 - F2 << endl;
  // 0        0        0
  // 0        0        0
  // 0        0        0

  mat F( 2, 3 );
  F.fill( 3.14 );
  cout << F << endl;
  // 3.1400   3.1400   3.1400
  // 3.1400   3.1400   3.1400

  F = F.ones();
  F.col( 0 ) *= datum::pi;
  F.col( 1 ) *= datum::inf;
  F.col( 2 ) *= datum::nan;
  cout << F << endl;
  // 3.1416      inf      nan
  // 3.1416      inf      nan

  return 0;
}

Referências