Fork me on GitHub

Linear Algebra for Java

Lightweight and 100% Java sparse/dense matrix library

I've read through parts of la4j library. It's very well designed - not too much object poetry (though there's a bit of a factory proliferation), some good defaults, and so far - I'm using the sparse matrix and vector classes - performance is good.

John Stewart, Amplify, Inc, New York, USA

I found la4j-0.4.0 has a lot of changes compared to the previous version. And I am glad that the AbstractMatrix has included a lot new functionalities like Kronecker product and slice operations. What a wonderful job!

Xiaorui Jiang, Zhejiang University of Technology, Zhejiang, China

Download la4j-0.4.9.zip


Download

The la4j might be simply downloaded by clicking big green button at the top of this page or by visiting it's GitHub releases page or by updating Maven's pom.xml.

<dependency>
  <groupId>org.la4j</groupId>
  <artifactId>la4j</artifactId>
  <version>0.4.9</version>
</dependency>


Overview

The la4j is open source and 100% Java library that provides Linear Algebra primitives (matrices and vectors) and algorithms. The la4j was initially designed to be lightweight and simple tool for passionate Java developers. It has been started as student project and turned into one of the most popular Java packages for matrices and vectors.

The key features of the la4j are listed bellow:



Use Cases

  Create new dense matrix from double array
// A simple 2D array matrix
Matrix a = new Basic2DMatrix(new double[][]{
  { 1.0, 2.0, 3.0 },
  { 4.0, 5.0, 6.0 },
  { 7.0, 8.0, 9.0 }
});

// This one uses 1D array as internal representation
Matrix b = new Basic1DMatrix(new double[][]{
  { 1.0, 2.0, 3.0 },
  { 4.0, 5.0, 6.0 },
  { 7.0, 8.0, 9.0 }
});

  Create new dense matrix from CSV file
/*** matrix.cvs

1.0, 2.0, 3.0
4.0, 5.0, 6.0
7.0, 8.0, 9.0

***/

// We will use a Symbol Separated source provider
Matrix a = new Basic2DMatrix(Matrices.asSymbolSeparatedSource(
                             new FileInputStream("matrix.csv")));

  Create new dense matrix from MatrixMarket file
/*** matrix.mm

%%MatrixMarket matrix array real general
% rows columns
3 3
% value
1.0
2.0
3.0
4.0
5.0
6.0
7.0
8.0
9.0

***/

// We will use a MatrixMarket source provider
Matrix a = new Basic1DMatrix(Matrices.asMatrixMarketSource(
                             new FileInputStream("matrix.mm")));

  Create new sparse matrix from double array
// A 'Compressed Row Storage' matrix
Matrix a = new CRSMatrix(new double[][]{
  { 1.0, 0.0, 3.0 },
  { 0.0, 5.0, 0.0 },
  { 7.0, 0.0, 9.0 }
});

// This one implements 'Compressed Column Storage' format
Matrix b = new CCSMatrix(new double[][]{
  { 0.0, 2.0, 0.0 },
  { 4.0, 5.0, 6.0 },
  { 0.0, 0.0, 9.0 }
});

  Create new sparse matrix from CSV file
/*** matrix.cvs

1.0, 0.0, 3.0
0.0, 5.0, 0.0
7.0, 0.0, 9.0

***/

// We will use a Symbol Separated source provider
Matrix a = new CRSMatrix(Matrices.asSymbolSeparatedSource(
                         new FileInputStream("matrix.csv")));

  Create new sparse matrix from MatrixMarket file
/*** matrix.mm

%%MatrixMarket matrix coordinate real general
% rows columns non-zero-values
3 3 5
% row column value
1 2 2.0
2 1 4.0
2 2 5.0
2 3 6.0
3 3 9.0

***/

// We will use a MatrixMarket source provider
Matrix a = new CCSMatrix(Matrices.asMatrixMarketSource(
                         new FileInputStream("matrix.mm")));

  Create new dense/sparse vector from double array
// A simple array-based vector
Vector a = new BasicVector(new double[]{ 1.0, 2.0, 3.0 });

// A compressed vector that uses double array as internal representation
Vector b = new CompressedVector(new double[] { 0.0, 2.0, 0.0 });

  Create new dense/sparse vector from CSV file
/*** vector.cvs

0.0, 2.0, 0.0

***/

// We will use a Symbol Separated source provider
Vector a = new BasicVector(Vectors.asSymbolSeparatedSource(
                           new FileInputStream("vector.csv")));

Vector b = new CompressedVector(Vectors.asSymbolSeparatedSource(
                                new FileInputStream("vector.csv")));

  Create new dense vector from MatrixMarket file
/*** vector.mm

%%MatrixMarket vector array real general
% length
3
% value
1.0
2.0
3.0

***/

// We will use a MatrixMarket source provider
Vector a = new BasicVector(Vectors.asMatrixMarketSource(
                           new FileInputStream("vector.mm")));

  Create new sparse vector from MatrixMarket file
/*** vector.mm

%%MatrixMarket vector coordinate real general
% length non-zero-values
3 1
% index value
2 2.0

***/

// We will use a MatrixMarket source provider
Vector a = new CompressedVector(Vectors.asMatrixMarketSource(
                                new FileInputStream("vector.mm")));

  Convert matrix to vector
// A 'Compressed Row Storage' matrix
Matrix a = new CRSMatrix(new double[][]{
  { 1.0, 0.0, 3.0 },
  { 0.0, 5.0, 0.0 },
  { 7.0, 0.0, 9.0 }
});

// We want to take first row of the matrix 'a' as sparse vector 'b'
Vector b = a.toRowVector();

// We want to take first column of the matrix 'a' as sparse vector 'c'
Vector c = a.toColumnVector();

  Convert vector to matrix
// A simple array-based vector
Vector a = new BasicVector(new double[]{ 1.0, 2.0, 3.0 });

// We want to take vector 'a' as first row of dense matrix 'b'
Matrix b = a.toRowMatrix();

// We want to take vector 'a' as first column of dense matrix 'c'
Matrix c = a.toColumnMatrix();

  Convert dense matrix to sparse matrix
// This matrix uses 1D array as internal representation
Matrix a = new Basic1DMatrix(new double[][]{
  { 1.0, 2.0, 3.0 },
  { 4.0, 5.0, 6.0 },
  { 7.0, 8.0, 9.0 }
});

// Convert Basic1DMatrix to CRSMatrix
Matrix b = a.copy(LinearAlgebra.CRS_FACTORY);

  Convert sparse matrix to dense matrix
// This matrix implements 'Compressed Column Storage' format
Matrix a = new CCSMatrix(new double[][]{
  { 0.0, 2.0, 0.0 },
  { 4.0, 5.0, 6.0 },
  { 0.0, 0.0, 9.0 }
});

// Convert CCSMatrix to Basic2DMatrix
Matrix b = a.copy(LinearAlgebra.BASIC2D_FACTORY);

  Convert vectors
// A simple array-based vector
Vector a = new BasicVector(new double[]{ 1.0, 2.0, 3.0 });

// Convert BasicVector to CompressedVector
Vector b = c.copy(LinearAlgebra.SPARSE_FACTORY);

// Convert CompressedVector to BasicVector
Vector c = b.copy(LinearAlgebra.DENSE_FACTORY);

  Transform matrix using predefined functors
// We want simple dense matrix that uses 2D array as internal representation
Matrix a = new Basic2DMatrix(new double[][] {
   { 1.0, 2.0, 3.0 },
   { 4.0, 5.0, 6.0 },
   { 7.0, 8.0. 9.0 }
});

// Multiply each element of matrix 'a' by 10.0
Matrix b = a.transform(Matrices.asMulFunction(10.0));

// Increase each element of matrix 'b' by 1 
Matrix c = b.transform(Matrices.INC_FUNCTION);

  Transform matrix using used-defined functors
// We want CRS matrix
Matrix a = new CRSMatrix(new double[][] {
   { 1.0, 0.0, 0.0 },
   { 4.0, 5.0, 6.0 },
   { 0.0, 0.0. 9.0 }
});

// We keep only diagonal elements of matrix 'a'
Matrix b = a.transform(new MatrixFunction() {
  @Override
  public double evaluate(int i, int j, double value) {
    return (i == j) ? value : 0.0;
  }
});

  Multiply matrix by matrix
// We want CCS matrix
Matrix a = new CCSMatrix(new double[][] {
   { 1.0, 2.0, 3.0 },
   { 4.0, 0.0, 6.0 },
   { 7.0, 0.0. 9.0 }
});

// We want 2D array matrix
Matrix b = new Basic2DMatrix(new double[][] {
   { 1.0, 2.0, 3.0 },
   { 4.0, 5.0, 6.0 },
   { 7.0, 8.0. 9.0 }
});

// Multiply 'a' by 'b'
Matrix c = a.multiply(b);

  Multiply matrix by vector
// We want CRS matrix
Matrix a = new CRSMatrix(new double[][] {
   { 1.0, 2.0, 3.0 },
   { 4.0, 0.0, 6.0 },
   { 7.0, 0.0. 9.0 }
});

// We want sparse vector
Vector b = new CompressedVector(new double[] { 1.0, 0.0, 3.0 });

// Multiply 'a' by 'b'
Vector c = a.multiply(b);

  Multiply vector by matrix
// We want dense vector
Vector a = new BasicVector(new double[] { 1.0, 0.0, 3.0 });

// We want CCS matrix
Matrix b = new CCSMatrix(new double[][] {
   { 1.0, 2.0, 3.0 },
   { 4.0, 0.0, 6.0 },
   { 7.0, 0.0. 9.0 }
});

// Multiply 'a' by 'b'
Vector c = a.multiply(b);

  Compute inner-product (dot-product) of two vectors
// We want dense vectors
Vector a = new BasicVector(new double[]{ 1.0, 2.0, 3.0 });
Vector b = new BasicVector(new double[]{ 4.0, 5.0, 6.0 });

double d = a.innerProduct(b); // 1.0*4.0 + 2.0*5.0 + 3.0*6.0 = 32

  Compute Hadamard product (element-wise product) of two vectors
// We want dense vectors
Vector a = new BasicVector(new double[]{ 1.0, 2.0, 3.0 });
Vector b = new BasicVector(new double[]{ 4.0, 5.0, 6.0 });

Vector c = a.hadamardProduct(b); // Vector { 4.0, 10.0, 18.0 }

  Compute Outer product of two vectors, which produces a matrix as result
// We want dense vectors
Vector a = new BasicVector(new double[]{ 1.0, 2.0, 3.0 });
Vector b = new BasicVector(new double[]{ 4.0, 5.0, 6.0 });

/* 
Matrix {
  4.0,  5.0,  6.0
  8.0, 10.0, 12.0
 12.0, 15.0, 18.0
}
*/
Matrix c = a.outerProduct(b);

  Matrix inversion
// We want simple dense matrix that uses 2D array as internal representation
Matrix a = new Basic2DMatrix(new double[][] {
   { 1.0, 2.0, 3.0 },
   { 4.0, 5.0, 6.0 },
   { 7.0, 8.0. 9.0 }
});

// We will use Gauss-Jordan method for inverting
MatrixInverter inverter = a.withInverter(LinearAlgebra.GAUSS_JORDAN);
// The 'b' matrix will be dense
Matrix b = inverter.invert(LinearAlgebra.DENSE_FACTORY);

  System of linear equations (m = n)
// The coefficient matrix 'a' is a CRS (Compressed Row Storage) matrix 
Matrix a = new CRSMatrix(new double[][] {
   { 1.0, 2.0, 3.0 },
   { 4.0, 5.0, 6.0 },
   { 7.0, 8.0. 9.0 }
});

// A right hand side vector, which is simple dense vector
Vector b = new BasicVector(new double[] {
   1.0, 2.0, 3.0
});

// We will use standard Forward-Back Substitution method,
// which is based on LU decomposition and can be used with square systems
LinearSystemSolver solver = a.withSolver(LinearAlgebra.FORWARD_BACK_SUBSTITUTION);
// The 'x' vector will be sparse
Vector x = solver.solve(b, LinearAlgebra.SPARSE_FACTORY);

  System of linear equations (m > n)
// The coefficient matrix 'a' is dense 1D matrix 
Matrix a = new Basic1DMatrix(new double[][] {
   {  1.0,  2.0,  3.0 },
   {  4.0,  5.0,  6.0 },
   {  7.0,  8.0.  9.0 },
   { 10.0, 11.0. 12.0 },
   { 13.0, 14.0. 15.0 }
});

// A right hand side vector, which is simple dense vector
Vector b = new BasicVector(new double[] {
   1.0, 2.0, 3.0, 4.0, 5.0
});

// We will use Least Squares method,
// which is based on QR decomposition and can be used with overdetermined systems
LinearSystemSolver solver = a.withSolver(LinearAlgebra.LEAST_SQUARES);
// The 'x' vector will be sparse
Vector x = solver.solve(b, LinearAlgebra.DENSE_FACTORY);

  Matrix decomposition (i.e. LU)
// We want simple dense matrix, which is based on 1D double's array 
Matrix a = new Basic1DMatrix(new double[][] {
   { 1.0, 2.0, 3.0 },
   { 4.0, 5.0, 6.0 },
   { 7.0, 8.0. 9.0 }
});

// We will use LU decompositor
MatrixDecompositor decompositor = a.withDecompositor(LinearAlgebra.LU);
// The result should be treated as: L = lup[0], U = lup[1], P = lup[2]
Matrix[] lup = decompositor.decompose(LinearAlgebra.DENSE_FACTORY);

Contributions

The la4j project is maintained at GitHub, where you can:

The last but not least way to contribute - drop a feedback to the author @vkostyukov.


References