
mikera.matrixx.Matrixx Maven / Gradle / Ivy
package mikera.matrixx;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import mikera.arrayz.INDArray;
import mikera.indexz.Index;
import mikera.matrixx.impl.ADiagonalMatrix;
import mikera.matrixx.impl.AStridedMatrix;
import mikera.matrixx.impl.ColumnMatrix;
import mikera.matrixx.impl.DenseColumnMatrix;
import mikera.matrixx.impl.DiagonalMatrix;
import mikera.matrixx.impl.IdentityMatrix;
import mikera.matrixx.impl.ScalarMatrix;
import mikera.matrixx.impl.SparseColumnMatrix;
import mikera.matrixx.impl.SparseRowMatrix;
import mikera.matrixx.impl.StridedMatrix;
import mikera.matrixx.impl.StridedRowMatrix;
import mikera.matrixx.impl.ZeroMatrix;
import mikera.vectorz.AVector;
import mikera.vectorz.Tools;
import mikera.vectorz.Vector3;
import mikera.vectorz.Vectorz;
import mikera.vectorz.impl.SparseIndexedVector;
import mikera.vectorz.util.ErrorMessages;
import mikera.vectorz.util.VectorzException;
import us.bpsm.edn.parser.Parseable;
import us.bpsm.edn.parser.Parser;
import us.bpsm.edn.parser.Parsers;
/**
* Static method class for matrices
*
* @author Mike
*/
public class Matrixx {
private static final long SPARSE_ELEMENT_THRESHOLD = 100000;
private final static Random rand=new Random();
/**
* Creates an identity matrix
*/
public static AMatrix createIdentityMatrix(int dimensions) {
return createImmutableIdentityMatrix(dimensions);
}
/**
* Creates a sparse, immutable identity matrix. This is the most efficient format for identity matrices
*/
public static IdentityMatrix createImmutableIdentityMatrix(int dimensions) {
return IdentityMatrix.create(dimensions);
}
/**
* Creates a fully mutable identity matrix
*/
public static AMatrix createMutableIdentityMatrix(int dimensions) {
AMatrix m = newMatrix(dimensions, dimensions);
for (int i = 0; i < dimensions; i++) {
m.unsafeSet(i, i, 1.0);
}
return m;
}
/**
* Coerce an object to a matrix format, on a best effort basis.
*
* Can handle:
* - Existing matrices
*/
@SuppressWarnings("unchecked")
public static AMatrix toMatrix(Object o) {
if (o instanceof AMatrix) {
return (AMatrix) o;
} else if (o instanceof AVector) {
return ColumnMatrix.wrap((AVector) o);
} else if (o instanceof Iterable>) {
List al = Tools.toList((Iterable) o);
return createFromVectors(al);
}
throw new UnsupportedOperationException("Can't convert to matrix: "
+ o.getClass());
}
/**
* Creates a sparse matrix from the given matrix, ignoring zeros
*/
public static AMatrix createSparse(AMatrix m) {
int rc=m.rowCount();
int cc=m.columnCount();
if ((rc==0)||(cc==0)) return ZeroMatrix.create(rc, cc);
return SparseRowMatrix.create(m);
}
/**
* Creates a sparse matrix of the given size, initially zero-filled. Uses row-based storage by default
*/
public static SparseRowMatrix createSparse(int rowCount, int columnCount) {
return SparseRowMatrix.create(rowCount,columnCount);
}
/**
* Creates a sparse matrix from the given matrix, ignoring zeros. Uses row-based storage by default
*/
public static SparseRowMatrix createSparseRows(Iterable rows) {
Iterator rowIterator=rows.iterator();
return createSparseRows(rowIterator);
}
/**
* Creates a sparse matrix from the given iterator. Each vector in the iterator will be copied to
* a row in the new sparse matrix
*/
public static ArrayList createSparseArray(Iterator vecIterator) {
AVector v0=vecIterator.next();
int len = v0.length();
ArrayList vecList = new ArrayList();
vecList.add(v0);
while (vecIterator.hasNext()) {
AVector v = vecIterator.next();
if ((v == null) || (v.isZero()))
v = Vectorz.createZeroVector(len);
else
v = v.sparseClone();
vecList.add(v.sparseClone());
}
return vecList;
}
public static SparseRowMatrix createSparseRows(Iterator rowIterator) {
return SparseRowMatrix.wrap(createSparseArray(rowIterator));
}
public static SparseColumnMatrix createSparseColumns(Iterator colIterator) {
return SparseColumnMatrix.wrap(createSparseArray(colIterator));
}
/**
* Create a sparse array, given an Index of column positions and AVector of corresponding values for each row in the sparse array
* Performs a defensive copy of underlying data.
*/
public static AMatrix createSparse(int columnCount, Index[] indexes,
AVector[] weights) {
int rowCount = indexes.length;
if (rowCount != weights.length)
throw new IllegalArgumentException("Length of indexes array must match length of weights array");
SparseRowMatrix sm=SparseRowMatrix.create(rowCount, columnCount);
for (int i = 0; i < rowCount; i++) {
sm.replaceRow(i, SparseIndexedVector.wrap(columnCount, indexes[i].clone(), weights[i].toDoubleArray()));
}
return sm;
}
/**
* Creates a SparseColumnMatrix from the given matrix, ignoring zeros
*/
public static SparseColumnMatrix createSparseColumns(AMatrix m) {
int cc = m.columnCount();
AVector[] cols = new AVector[cc];
for (int i = 0; i < cc; i++) {
cols[i] = Vectorz.createSparse(m.getColumn(i));
}
return SparseColumnMatrix.wrap(cols);
}
/**
* Creates a SparseRowMatrix matrix from the given matrix, ignoring zeros
*/
public static AMatrix createSparseRows(AMatrix m) {
if (m.rowCount()==0) return ZeroMatrix.create(0, m.columnCount());
return SparseRowMatrix.create(m);
}
/**
* Creates a SparseRowMatrix matrix from the given INDArray, ignoring zeros
*/
public static SparseRowMatrix createSparseRows(INDArray a) {
if (!(a.dimensionality()==2)) throw new IllegalArgumentException(ErrorMessages.incompatibleShape(a));
int rc=a.getShape(0);
int cc=a.getShape(1);
SparseRowMatrix m=SparseRowMatrix.create(rc,cc);
for (int i=0; iSPARSE_ELEMENT_THRESHOLD) return createSparse(rows,columns);
return Matrix.create(rows, columns);
}
/**
* Creates a new matrix using the elements in the specified vector.
* Truncates or zero-pads the data as required to fill the new matrix
* @param data
* @param rows
* @param columns
* @return
*/
public static Matrix createFromVector(AVector source, int rows, int columns) {
int length=source.length();
Matrix m = Matrix.create(rows, columns);
int n=Math.min(rows*columns, length);
source.copyTo(0, m.data, 0, n);
return m;
}
/**
* Computes the inverse of a matrix. Returns null if the matrix is singular.
*
* Throws an Exception is the matrix is not square
* @param m
* @return
*/
public AMatrix createInverse(AMatrix m) {
return m.inverse();
}
/**
* Creates a zero-filled matrix with the specified number of dimensions for both rows and columns
* @param dimensions
* @return
*/
private static Matrix createSquareMatrix(int dimensions) {
return Matrix.create(dimensions, dimensions);
}
/**
* Extracts a lower triangular matrix from a matrix
*/
public static AMatrix extractLowerTriangular(AMatrix a) {
int rc=a.rowCount();
if (rc>a.columnCount()) throw new IllegalArgumentException("Too few columns in matrix");
AMatrix r=Matrixx.newMatrix(rc,rc);
for (int i=0; ia.rowCount()) throw new IllegalArgumentException("Too few rows in matrix");
AMatrix r=Matrixx.newMatrix(cc,cc);
for (int i=0; i rows) {
int rc = rows.size();
AVector firstRow = Vectorz.create(rows.get(0));
int cc = firstRow.length();
Matrix m = Matrix.create(rc, cc);
m.setRow(0, firstRow);
for (int i = 1; i < rc; i++) {
m.setRow(i, Vectorz.create(rows.get(i)));
}
return m;
}
/**
* Creates a mutable copy of a matrix
*/
public static AMatrix create(IMatrix m) {
int rows = m.rowCount();
int columns = m.columnCount();
AMatrix result = newMatrix(rows, columns);
result.set(m);
return result;
}
/**
* Fills a matrix with uniform random numbers
* @param m
*/
public static void fillRandomValues(AMatrix m) {
int rows = m.rowCount();
int columns = m.columnCount();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
m.unsafeSet(i, j, rand.nextDouble());
}
}
}
/**
* Fills a matrix with uniform random numbers, using the specified Random instance
* @param m
*/
public static void fillRandomValues(AMatrix m, Random rand) {
int rows = m.rowCount();
int columns = m.columnCount();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
m.unsafeSet(i, j, rand.nextDouble());
}
}
}
/**
* Create a matrix using as array of vectors which represent the data for each row
* @param data
* @return
*/
public static AMatrix createFromVectors(INDArray... data) {
int rc = data.length;
int cc = (rc == 0) ? 0 : data[0].sliceCount();
AMatrix m = newMatrix(rc, cc);
for (int i = 0; i < rc; i++) {
m.setRow(i, data[i].asVector());
}
return m;
}
/**
* Create a matrix using a list of vectors as the data for each row
* @param data
* @return
*/
public static AMatrix createFromVectors(List data) {
int rc = data.size();
int cc = (rc == 0) ? 0 : data.get(0).sliceCount();
AMatrix m = newMatrix(rc, cc);
for (int i = 0; i < rc; i++) {
m.setRow(i,data.get(i).asVector());
}
return m;
}
// ====================================
// Edn formatting and parsing functions
private static Parser.Config getMatrixParserConfig() {
return Parsers.defaultConfiguration();
}
/**
* Parse a matrix in edn format
*
* @param ednString
* @return
*/
public static AMatrix parse(String ednString) {
Parser p = Parsers.newParser(getMatrixParserConfig());
Parseable ps = Parsers.newParseable(ednString);
@SuppressWarnings("unchecked")
List> data = (List>) p.nextValue(ps);
int rc = data.size();
int cc = (rc == 0) ? 0 : data.get(0).size();
AMatrix m = newMatrix(rc, cc);
for (int i = 0; i < rc; i++) {
List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy