Linearalgebra
a linear algebra package in Java
Install / Use
/learn @danhales/LinearalgebraREADME
linearalgebra
A linear algebra package in Java.
For flexibility, most methods are overloaded to include both static versions (which require the object as the first parameter) and instance methods. The static method does the heavy lifting, and the instance method is a wrapper for the static method using this as an argument (e.g. Matrix.transpose(this)).
No operations are carried out in-place––all operations that modify the object return a copy of the object with the modifications.
Current classes and capabilities (as of November 1, 2020)
Vector class
Because linear algebra (as it applies to machine learning) largely revolves around lists of numbers, the Vector class is a fancy wrapper for an array of doubles, and provides common functionality for working with both that array, in addition to operations involving other Vector objects.
Fields
entries- array of doubles
Constructors
-
Vector(double...)- accepts either a list of doubles (e.g.Vector(1,2,3)), or an array ofdoubles (e.g.Vector(new double[] {1,2,3})) -
Vector(Vector)- copies the entries in the passedVectorobject's private field into a new Vector object
Setters / Getters / Special calls to constructor
-
getEntries()- returns a copy of (not a reference to)entries -
get(int)- returns the value in the specified position of theVector, e.g.u.get(3)returns the entry in position 3 -
identityVector(int)- returns the additive identityVectorwith the specified length, which is just a list of zeros -
set(int, double)- sets the value at the specified index to be equal to the passed value -
setV(double[])- sets the values in thevfield -
toString()- returns a Python-style representation of theVector, e.g."[1, 2, 3]"
Unary Operations (operations on a single Vector)
-
inverseVector(Vector)/inverse()- returns the additive inverse of theVector, which is the same vector, with the signs flipped (e.g. {1, -2, 3} becomes {-1, 2, -3}) -
isCanonicalBasisVector(Vector)- checks to see ifVectoris all zeros, except for a single 1 -
isZero(Vector)- checks to see if theVectoris essentially zero, which I've defined as smaller than Double.MIN_VALUE * 10. -
length(Vector)- returns the number of entries in theVector, which is the length ofv -
magnitude(Vector)- returns the <a href="https://en.wikipedia.org/wiki/Euclidean_space#Euclidean_norm">Euclidean norm</a> of theVector -
normalize()- scales aVectorvwith the factor(1/v.magnitude()). Throws anIllegalArgumentExceptionifv.isZero()returnstrue -
pnorm(double)- computes the Lp norm with the given value ofp
Binary Operations (operations on two Vectors)
-
add(Vector)/add(Vector, Vector)- adds corresponding entries in twoVectorobjects, provided they have the same length. -
angleDegrees(Vector, Vector)/angleRadians(Vector, Vector)- returns the angle between the twoVectors (arccos(u1.dot(u2) / (u1.magnitude() * u2.magnitude()))) in either degrees or radians -
checkLengths(Vector, Vector)checks to make sure the twoVector- objects have compatible lengths and throws anIllegalArgumentExceptionif they have different lengths -
cross(Vector)/cross(Vector, Vector)- computes the cross product for two three-dimensionalVectors. The cross product is only defined for three-dimensional vectors, so anIllegalArgumentExceptionwill be thrown if aVectorany other dimension is passed. -
dot(Vector)/dot(Vector, Vector)- computes the dot product for twoVectors of the same length, which is the sum of products of corresponding entries, e.g. {1, 2, 3} dot {4, 5, 6} = (1)(4) + (2)(5) + (3)(6). -
subtract(Vector)/subtract(Vector,Vector)- subtracts the passedVectorfrom the callingVector, or the secondVectorfrom the first
Other Operations
-
linearCombination(Vector[], double[])- returns a weighted sum by multiplying theVectorobjects in theVectorarray by the weights in thedoublearray. -
multiply(Vector, double)/multiply(double)- computes the scalar product by multiplying each entry in theVectorby the specifieddouble -
scalarTripleProduct(Vector, Vector, Vector)- computes the scalar triple product of the three vectors, e.g. a.dot(b.cros(c)). This operation is NOT commutative.
Matrix class
The Matrix class takes advantage of many of the properties of the Vector class in order to work with a 2D array of doubles. Although there are many use cases possible for a Matrix class, I am focusing functionality in two primary areas before diving into more specific uses: machine learning and linear algebra operations. For machine learning purposes, we'll mostly be needing to multiply a Vector object by a Matrix object, pass the output through an activation function of some kind, and update the entries in the Matrix according to some kind of loss function. To accomplish this, we need a variety of linear algebra tricks, such as grabbing a row or column as a Vector, updating a single row or column, adding, subtracting, or multiplying Matrix objects, multiplying Matrix objects, and performing elementary operations such as adding a multiple of one row onto another row.
Fields
entries- a 2Ddoublearray. It is assumed that the array is rectangular.
Constructors
-
Matrix(double[][])- accepts the 2D array directly and copies its entries into the private fieldentries -
Matrix(Matrix)- copy constructor
Setters / Getters / Special calls to constructor
I'm using the terms "setters" and "getters" very loosely here in order to organize this README, because methods like getColumn do not return the value in a private field––they return a subset of entries in entries as a Vector object.
-
minorMatrix(Matrix, int, int)- returns a copy of theMatrixobject with the indicated row and column dropped. -
fromColumnVectors(Vector...)- accepts either an array ofVectorobjects, or a list ofVectorobjects as parameters, and returns aMatrixwhere thoseVectorobjects make up the columns.Vectorobjects must all have the same length, or anIllegalArgumentExceptionwill be thrown. Implemented by returning thetransposeof the value returned byfromRowVectors -
fromRowVectors(Vector...)- accepts an array ofVectorobjects, or a list ofVectorobjects as parameters, and returns aMatrixwhere theVectorobjects make up the rows.Vectorobjects must all have the same length, or anIllegalArgumentExceptionwill be thrown. -
dropColumn(Matrix, int)/dropRow(Matrix, int)- returns a copy of theMatrixobject with the specified row/column removed. Note that this operation does change the index of the entries after the dropped column/row. -
getColumn(Matrix,m int)/getRow(Matrix, int)- accepts anintfor the index of the desired column/row, and returns the entries in that column as aVectorobject. If the column/row index is out of range, anIllegalArgumentExceptionis thrown -
getEntry(int, int)- accepts anintfor the row index and anintfor the column index, and returns the entry atentries[row][col]. If either of the values are out of range, anIllegalArgumentExceptionis thrown. -
getNumColumns(Matrix)/getNumRows(Matrix)- returns the length of the first row inentries(columns), i.e.entries[0].length, or the length ofentries, i.e.entries.length. We assume the array is rectangular, and not ragged. -
identityMatrix(int)returns an n-by-n Matrix (wherenis specified as a parameter) which has ones on the diagonal, and zeros elsewhere. -
minorMatrix(Matrix, int, int)- returns a copy of the matrix with the specified row (first int) and specified column (second int) dropped -
setColumn(Matrix, int, double[])/setColumn(int, Vector)/setRow(Matrix, int, double[])/setRow(Matrix, int, Vector)- accepts an int for the index of the column/row we want to set and either an array of new entries or aVectorof new entries, and replaces the entries in that column/row with the new entries. If the length of the new entries is not equal to the length of the column/row being set, or if the column/row index specified is out of range, anIllegalArgumentExceptionwill be thrown. -
toColumnVectors(Matrix)- returns the columns of theMatrixas an array ofVectorobjects -
toRowVectors(Matrix)- returns the rows of theMatrixas an array ofVectorobjects -
toString()- represents entries Python-style as a stack of row vectors, e.g.
[[1, 2, 3], [4, -5, 6], [-7, 8, 9]]
Unary Operations (operations on a single Matrix)
-
determinant(Matrix)- recursively computes the determinant of a square matrix using the Laplace expansion, O(n!). Not recommended for use. -
isDiagonal(Matrix)- returnstrueif theMatrixis square and all nonzero entries (threshold-checked) are located on the diagonal -
isLowerTriangular(Matrix)- returnstrueif all values below the diagonal are zero -
isPermutationMatrix(Matrix)- returnstrueif the Matrix is all zeros, except for a single 1 in each row and each column -
isSparse(Matrix)/isSparse(Matrix, double)- counts the number of (threshold-checked) zero entries. No-arg version returnstrueif there are no more nonzero entries than max{number of rows, number of columns}. Version that accepts adoubleallows user to specify the proportion explicitly. As of now, this is simply a check, and no optimizations for sparse matrices are carried out. -
isSquare(Matrix)- checks to see if the number of rows equals the number of columns. All methods that operate only on square matrices call this method immediately and throw anIllegalArgumentExceptionif it returnsfalse. -
isUpperTriangular(Matrix)- che
