Library for tensor computations in Java.
The tensor library was developed with the following objectives in mind
- support for exact precision using integer fractions
- support for calculation with physical units
- suitable for use in safety-critical real-time systems
- API and string expressions inspired by
Mathematica
Diverse projects rely on the tensor library:
Mobility-on-Demand |
SwissTrolley+ |
Motion Planning |
Autonomous Gokart |
- multi-dimensional arrays: scalars, vectors, matrices, n-linear forms, Lie-algebra ad-tensor, ...
- unstructured, nested tensors, for instance
{{1+2*I[A], -3/4}, {{5.678}, 9[kg*s^-1], 2[m^3]}}
- scalars are real-, or complex numbers, from finite fields, or quantities with physical units
- values are encoded as exact integer fractions, in double precision, and as
java.math.BigDecimal
- probability distributions for random variate generation: Binomial-, Poisson-, Exponential-distribution, etc.
- linear solvers
GaussianElimination
,CholeskyDecomposition
,QRDecomposition
,SingularValueDecomposition
- matrix functions
MatrixExp
,MatrixLog
,MatrixSqrt
, ... - tensor functions
TensorProduct
,TensorWedge
,Trace
,HodgeDual
, ... - Lie theory:
BakerCampbellHausdorff
- parametric functions
LinearInterpolation
,BSplineFunction
- window functions: Gaussian, Hamming, Hann, Blackman, ...
- spectral analysis:
Fourier
,SpectrogramArray
- import from and export to
Mathematica
,CSV
, and image files
Gamma function |
Trigonometry |
Nylander's formula |
Newton's method |
Solving systems of linear equations
Tensor matrix = Tensors.matrixInt(new int[][] { { 2, -3, 2 }, { 4, 9, -3 }, { -1, 3, 2 } });
System.out.println(Pretty.of(Inverse.of(matrix)));
[
[ 9/37 4/37 -3/37 ]
[ -5/111 2/37 14/111 ]
[ 7/37 -1/37 10/37 ]
]
Linear programming
Tensor x = LinearOptimization.maxLessEquals( //
Tensors.vector(1, 1), // rewards
Tensors.fromString("{{4, -1}, {2, 1}, {-5, 2}}"), // matrix
Tensors.vector(8, 7, 2)); // rhs
System.out.println(x);
{4/3, 13/3}
Pseudoinverse, Moore-Penrose inverse
Tensor matrix = Tensors.fromString("{{-1 + I, 0}, {-I, 2}, {2 - I, 2 * I}}");
System.out.println(Pretty.of(PseudoInverse.of(matrix)));
[
[ -1/3-I/3 1/6-I/6 1/6+I/6 ]
[ 1/6-I/3 5/12+I/12 -1/12-I/12 ]
]
Nullspace
Tensor matrix = Tensors.fromString("{{-1/3, 0, I}}");
System.out.println(Pretty.of(NullSpace.of(matrix)));
[
[ 1 0 -I/3 ]
[ 0 1 0 ]
]
Statistics
Distribution distribution = HypergeometricDistribution.of(10, 50, 100);
System.out.println(RandomVariate.of(distribution, 20));
PDF pdf = PDF.of(distribution);
System.out.println("P(X=3)=" + pdf.at(RealScalar.of(3)));
{6, 5, 1, 4, 3, 4, 7, 5, 7, 4, 6, 3, 5, 4, 5, 4, 6, 2, 6, 7}
P(X=3)=84000/742729
The tensor library implements Quantity
, i.e. numbers with physical units.
Several algorithms are verified to work with scalars of type Quantity
.
Tensor matrix = Tensors.fromString( //
"{{60[m^2], 30[m*rad], 20[kg*m]}, {30[m*rad], 20[rad^2], 15[kg*rad]}, {20[kg*m], 15[kg*rad], 12[kg^2]}}");
CholeskyDecomposition cd = CholeskyDecomposition.of(matrix);
System.out.println(cd.diagonal());
System.out.println(Pretty.of(cd.getL()));
System.out.println(cd.det().divide(Quantity.of(20, "m^2*rad")));
{60[m^2], 5[rad^2], 1/3[kg^2]}
[
[ 1 0 0 ]
[ 1/2[m^-1*rad] 1 0 ]
[ 1/3[kg*m^-1] 1[kg*rad^-1] 1 ]
]
5[kg^2*rad]
The units of a quantity are chosen by the application layer.
For instance, Quantity.of(3, "Apples")
is valid syntax.
The tensor library contains the resource /unit/si.properties
that encodes the SI unit system in the familiar strings such as m
, kg
, s
, but the use of this convention is optional.
The example below makes use of these provided definitions
Scalar mass = Quantity.of(300, "g"); // in gram
Scalar a = Quantity.of(981, "cm*s^-2"); // in centi-meters per seconds square
Scalar force = mass.multiply(a);
System.out.println(force);
Scalar force_N = UnitConvert.SI().to(Unit.of("N")).apply(force);
System.out.println(force_N);
294300[cm*g*s^-2]
2943/1000[N]
The scalar type Quantity
was developed in collaboration with SwissTrolley+.
The tensor library implements DateTime
for calendar arithmetic and data sets with calendar entries.
The arithmetic and string expressions are identical to those of the java class LocalDateTime
.
Scalar mean = DateTime.of(2022, Month.FEBRUARY, 28, 12, 00);
Scalar sigma = Quantity.of(30, "h");
Distribution distribution = NormalDistribution.of(mean, sigma);
Scalar guess = RandomVariate.of(distribution);
System.out.println(mean.add(sigma));
System.out.println(guess);
2022-03-01T18:00
2022-03-02T10:12:06.641540174
The scalar type DateTime
was developed in collaboration with GRZ Technologies.
Tensors of rank 3
Tensor ad = LeviCivitaTensor.of(3).negate();
Tensor x = Tensors.vector(7, 2, -4);
Tensor y = Tensors.vector(-3, 5, 2);
System.out.println(ad);
System.out.println(ad.dot(x).dot(y)); // coincides with cross product of x and y
{{{0, 0, 0}, {0, 0, -1}, {0, 1, 0}}, {{0, 0, 1}, {0, 0, 0}, {-1, 0, 0}}, {{0, -1, 0}, {1, 0, 0}, {0, 0, 0}}}
{24, -2, 41}
Functions for complex numbers
System.out.println(Sqrt.of(RationalScalar.of(-9, 16)));
3/4*I
Several functions support evaluation to higher than machine precision for type DecimalScalar
.
System.out.println(Exp.of(DecimalScalar.of(10)));
System.out.println(Sqrt.of(DecimalScalar.of(2)));
220255.6579480671651695790064528423`34
1.414213562373095048801688724209698`34
The number after the prime indicates the precision of the decimal.
The string representation is compatible with Mathematica
.
Indices for the set
and get
functions start from zero like in C/Java:
Tensor matrix = Array.zeros(3, 4);
matrix.set(Tensors.vector(9, 8, 4, 5), 2);
matrix.set(Tensors.vector(6, 7, 8), Tensor.ALL, 1);
System.out.println(Pretty.of(matrix));
System.out.println(matrix.get(Tensor.ALL, 3)); // extraction of the 4th column
[
[ 0 6 0 0 ]
[ 0 7 0 0 ]
[ 9 8 4 5 ]
]
{0, 0, 5}
Distance-based queries for point sets in Euclidean space
k-nearest neighbors |
radius search |
Predefined color gradients
Predefined color lists
From time to time, a version is deployed and made available for maven integration. Specify repository
and dependency
of the library tensor
in the pom.xml
file of your maven project:
<dependencies>
<!-- other dependencies -->
<dependency>
<groupId>ch.alpine</groupId>
<artifactId>tensor</artifactId>
<version>1.0.6</version>
</dependency>
</dependencies>
<repositories>
<!-- other repositories -->
<repository>
<id>tensor-mvn-repo</id>
<url>https://raw.github.com/datahaki/tensor/mvn-repo/</url>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
</snapshots>
</repository>
</repositories>
For Java 17, for version
use 1.0.6
.
For Java 11, for version
use 1.1.1-jdk-11
.
The source code is attached to every release.
The branch master
always contains the latest features for Java 17, and does not correspond to the most recent deployed version generally.