All Downloads are FREE. Search and download functionalities are using the official Maven repository.

gov.sandia.cognition.math.matrix.Matrix Maven / Gradle / Ivy

/*
 * File:                Matrix.java
 * Authors:             Kevin R. Dixon
 * Company:             Sandia National Laboratories
 * Project:             Cognitive Foundry
 *
 * Copyright April 12, 2006, Sandia Corporation.  Under the terms of Contract
 * DE-AC04-94AL85000, there is a non-exclusive license for use of this work by
 * or on behalf of the U.S. Government. Export of this program may require a
 * license from the United States Government. See CopyrightHistory.txt for
 * complete details.
 * 
 */

package gov.sandia.cognition.math.matrix;

import gov.sandia.cognition.annotation.CodeReview;
import gov.sandia.cognition.annotation.CodeReviews;
import gov.sandia.cognition.math.ComplexNumber;
import gov.sandia.cognition.math.Ring;
import java.text.NumberFormat;
import java.util.List;

/**
 * Defines the base functionality for all implementations of a Matrix
 *
 * @author Kevin R. Dixon
 * @since 1.0
 */
@CodeReviews(
    reviews={
        @CodeReview(
            reviewer="Kevin R. Dixon",
            date="2008-02-26",
            changesNeeded=false,
            comments={
                "Minor changes to the formatting",
                "Otherwise, looks good."
            }
        ),
        @CodeReview(
            reviewer="Jonathan McClain",
            date="2006-05-16",
            changesNeeded=false,
            comments="Interface looks ok. Made a few minor changes."
        )
    }
)
public interface Matrix
    extends java.lang.Iterable, Ring, Vectorizable
{

    @Override
    public Matrix clone();

    /**
     * Returns the number of rows in the Matrix 
     *
     * @return Number of rows in the Matrix
     */
    public int getNumRows();

    /**
     * Returns the number of columns in the Matrix 
     *
     * @return Number of columns in the Matrix
     */
    public int getNumColumns();
    
    /**
     * Gets the value of the element of the matrix at the zero-based row and
     * column indices. It throws an ArrayIndexOutOfBoundsException if either
     * index is out of range.
     * It is a convenience method for {@code getElement}.
     * 
     * @param   rowIndex
     *      The zero-based row index. Must be between 0 (inclusive) and the
     *      number of rows (exclusive).
     * @param   columnIndex
     *      The zero-based column index. Must be between 0 (inclusive) and the
     *      number of columns (exclusive).
     * @return 
     *      The value at the given row and column in the matrix.
     * @since   3.4.0
     */
    public double get(
        final int rowIndex,
        final int columnIndex);
    
    /**
     * Sets the value of the element of the matrix at the zero-based row and
     * column indices. It throws an ArrayIndexOutOfBoundsException if either
     * index is out of range.
     * It is a convenience method for {@code setElement}.
     * 
     * @param   rowIndex
     *      The zero-based row index. Must be between 0 (inclusive) and the
     *      number of rows (exclusive).
     * @param   columnIndex
     *      The zero-based column index. Must be between 0 (inclusive) and the
     *      number of columns (exclusive).
     * @param   value 
     *      The value to set at the given row and column in the matrix.
     * @since   3.4.0
     */
    public void set(
        final int rowIndex,
        final int columnIndex,
        final double value);

    /**
     * Gets the Matrix element at the specified zero-based indices
     * throws ArrayIndexOutOfBoundsException if either rowIndex or columnIndex
     * are less than 0, or greater than the number of rows (columns) minus one
     * (0 <= index <= num-1) 
     * 
     * @param rowIndex Zero-based index into the Matrix
     * @param columnIndex Zero-based index into the Matrix
     * @return The value at rowIndex, columnIndex
     */
    public double getElement(
        int rowIndex,
        int columnIndex );

    /**
     * Sets the Matrix element at the specified zero-based indices
     * throws ArrayIndexOutOfBoundsException if either rowIndex or columnIndex
     * are less than 0, or greater than the number of rows (columns) minus one
     * (0 <= index <= num-1)
     * 
     * @param rowIndex Zero-based index into the rows of the Matrix
     * @param columnIndex Zero-based index into the columns of the Matrix
     * @param value Value to set at the specified index
     */
    public void setElement(
        int rowIndex,
        int columnIndex,
        double value );

    /**
     * Gets the embedded submatrix inside of the Matrix, specified by the
     * inclusive, zero-based indices such that the result matrix will have size
     * (maxRow-minRow+1) x (maxColum-minCcolumn+1)
     * 
     * 
     * @param  minRow Zero-based index into the rows of the Matrix, must be less 
     *        than or equal to maxRow
     * @param  maxRow Zero-based index into the rows of the Matrix, must be 
     *         greater than or equal to minRow
     * @param  minColumn Zero-based index into the rows of the Matrix, must be 
     *         less than or equal to maxColumn
     * @param  maxColumn Zero-based index into the rows of the Matrix, must be 
     *         greater than or equal to minColumn
     * @return the Matrix of dimension (maxRow-minRow+1)x(maxColumn-minColumn+1)
     */
    public Matrix getSubMatrix(
        int minRow,
        int maxRow,
        int minColumn,
        int maxColumn );

    /**
     * Sets the submatrix inside of the Matrix, specified by the zero-based 
     * indices.
     *
     * @param  minRow Zero-based index into the rows of the Matrix, must be less 
     *         than or equal to maxRow
     * @param  minColumn Zero-based index into the rows of the Matrix, must be 
     *         less than or equal to maxColumn
     * @param  submatrix Matrix containing the values to set at the specified 
     *         indices
     */
    public void setSubMatrix(
        int minRow,
        int minColumn,
        Matrix submatrix );

    /**
     * Determines if the matrix is symmetric.
     *
     * @return true if the matrix is symmetric, false otherwise
     */
    public boolean isSymmetric();

    /**
     * Determines if the matrix is effectively symmetric 
     *
     * @param effectiveZero
     *          tolerance to determine symmetry
     * @return true if effectively symmetric, false otherwise
     */
    public boolean isSymmetric(
        double effectiveZero );

    /**
     * Checks to see if the dimensions are the same between this 
     * and otherMatrix
     *
     * @param otherMatrix 
     *          matrix against which to check
     * @return true if 
     *         this.getNumRows() == otherMatrix.getNumRows() and 
     *         this.getNumColumns() == otherMatrix.getNumColumns()
     */
    public boolean checkSameDimensions(
        Matrix otherMatrix );

    /**
     * Throws a DimensionalityMismatchException if dimensions between this
     * and otherMatrix aren't the same 
     *
     * @param otherMatrix
     *          Matrix dimensions to compare to this
     */
    public void assertSameDimensions(
        Matrix otherMatrix );

    /**
     * Checks to see if the dimensions are appropriate for:
     * this.times( postMultiplicationMatrix )
     *
     * @param postMultiplicationMatrix
     *          matrix by which this is to be multiplied
     * @return true if this.getNumColumns() ==
     *          postMultlicationMatrix.getNumColumns(), false otherwise
     */
    public boolean checkMultiplicationDimensions(
        Matrix postMultiplicationMatrix );
    
    /**
     * Checks to see if the dimensions are appropriate for:
     * this.times(postMultiplicationMatrix).
     *
     * @param postMultiplicationMatrix
     *          Matrix by which this is to be multiplied.
     */
    public void assertMultiplicationDimensions(
        final Matrix postMultiplicationMatrix);

    /**
     * Matrix multiplication of this and matrix,
     * operates like the "*" operator in Matlab
     * 
     * @param matrix this.getNumColumns()==matrix.getNumRows()
     * @return Matrix multiplication of this and
     *         matrix, will this.getNumRows() rows and
     *         matrix.getNumColumns() columns
     */
    public Matrix times(
        final Matrix matrix );

    /**
     * Returns the transpose of this 
     *
     * @return Matrix whose elements are equivalent to:
     *         this.getElement(i, j) == this.transpose().getElement(j, i)
     *          for any valid i, j.
     */
    public Matrix transpose();

    /**
     * Computes the full-blown inverse of this, which must be a
     * square matrix
     * 
     * @return Inverse of this, such that
     *         this.times(this.inverse()) == this.inverse().times(this)
     *         == identity matrix
     */
    public Matrix inverse();

    /**
     * Computes the effective pseudo-inverse of this, using a
     * rather expensive procedure (SVD)
     *
     * @return full singular-value pseudo-inverse of this
     */
    public Matrix pseudoInverse();

    /**
     * Computes the effective pseudo-inverse of this, using a
     * rather expensive procedure (SVD)
     *
     * @param effectiveZero
     *          effective zero to pass along to the SVD
     *
     * @return effective pseudo-inverse of this
     */
    public Matrix pseudoInverse(
        double effectiveZero );

    /**
     * Element-wise division of {@code this} by {@code other}. Note that if
     * {@code other} has zero elements the result will contain {@code NaN}
     * values.
     *
     * @param   other
     *      The other ring whose elements will divide into this one.
     * @return
     *      A new ring of equal size whose elements are equal to the
     *      corresponding element in {@code this} divided by the element in
     *      {@code other}.
     */
    public Matrix dotDivide(
        final Matrix other);

    /**
     * Inline element-wise division of {@code this} by {@code other}. Note
     * that if {@code other} has zero elements this will contain {@code NaN}
     * values.
     *
     * @param   other
     *      The other vector whose elements will divide into this one.
     */
    public void dotDivideEquals(
        final Matrix other);

    /**
     * Computes the natural logarithm of the determinant of this.
     * Very computationally intensive.  Please THINK LONG AND HARD before
     * invoking this method on sparse matrices, as they have to be converted
     * to a DenseMatrix first.
     * 
     * @return natural logarithm of the determinant of this
     */
    public ComplexNumber logDeterminant();

    /**
     * Computes the trace of this, which is the sum of the diagonal
     * elements. It is equivalent to the sum of the eigenvalues (which
     * is probably the most interesting result in all of algebra!).
     * 
     * @return trace of this
     */
    public double trace();

    /**
     * Computes the rank of this, which is the number of
     * linearly independent rows and columns in this.  Rank is
     * typically based on the SVD, which is a fairly computationally expensive
     * procedure and should be used carefully
     *
     * @return rank of this, equivalent to the number of linearly
     *         independent rows and columns in this
     */
    public int rank();

    /**
     * Computes the effective rank of this, which is the number of
     * linearly independent rows and columns in this.  Rank is
     * typically based on the SVD, which is a fairly computationally expensive
     * procedure and should be used carefully
     *
     * @param effectiveZero
     *          parameter to pass along to SVD to determine linear dependence
     *
     * @return rank of this, equivalent to the number of linearly
     *         indepenedent rows and columns in this
     */
    public int rank(
        double effectiveZero );

    /**
     * Compute the Frobenius norm of this, which is just a fancy
     * way of saying that I will square each element, add those up, and square
     * root the result.  This is probably the most intuitive of the matrix norms
     *
     * @return Frobenius norm of this
     */
    public double normFrobenius();
    
    /**
     * Compute the squared Frobenius norm of this, which is just a 
     * fancy way of saying that I will square each element and add those up.
     *
     * @return Frobenius norm of this
     */
    public double normFrobeniusSquared();

    /**
     * Determines if the matrix is square (numRows == numColumns) 
     *
     * @return true if square, false if nonsquare
     */
    public boolean isSquare();

    /**
     * Solves for "X" in the equation: this*X = B
     *
     * @param B Must satisfy this.getNumColumns() == B.getNumRows();
     * @return X Matrix with dimensions (this.getNumColumns() x B.getNumColumns())
     */
    public Matrix solve(
        final Matrix B );

    /**
     * Solves for "x" in the equation: this*x = b
     *
     * @param b must satisfy this.getNumColumns() == b.getDimensionality()
     * @return x Vector with dimensions (this.getNumColumns())
     */
    public Vector solve(
        final Vector b );

    /**
     * Formats the matrix as an identity matrix.  This does not have to be
     * square.
     */
    public void identity();

    /**
     * Returns the column vector from the equation
     * return = this * vector 
     *
     * @param vector
     *          Vector by which to post-multiply this, must have the
     *          same number of rows as this
     * @return Vector with the same dimensionality as the number of rows as
     *         this and vector
     */
    public Vector times(
        final Vector vector );

    /**
     * Returns true if this matrix has a potentially sparse underlying
     * structure. This can indicate that it is faster to only process the
     * non-zero elements rather than to do dense operations on it. Of course,
     * even with a sparse structure, there may be no zero elements or
     * conversely even with a non-sparse (dense) structure there may be many
     * zero elements.
     *
     * @return
     *      True if the matrix has a potentially sparse structure. Otherwise,
     *      false.
     */
    public boolean isSparse();
    
    /**
     * Gets the number of active entries in the matrix. Must be between 0
     * and the number of rows times the number of columns.
     * 
     * @return 
     *      The number of active entries in the matrix.
     */
    public int getEntryCount();

    /**
     * Gets the specified column from the zero-based index and returns a
     * vector that corresponds to that column.
     *
     * @param columnIndex
     *          zero-based index into the matrix
     * @return Vector with elements equal to the number of rows in this
     */
    public Vector getColumn(
        int columnIndex );

    /**
     * Gets the specified row from the zero-based index and returns a vector
     * that corresponds to that column 
     *
     * @param rowIndex
     *          zero-based index into the matrix
     * @return Vector with elements equal to the number of columns in this
     */
    public Vector getRow(
        int rowIndex );

    /**
     * Sets the specified column from the given columnVector 
     *
     * @param columnIndex
     *          zero-based index into the matrix
     * @param columnVector
     *          vector to replace in this, must have same number of elements
     *          as this has rows
     */
    public void setColumn(
        int columnIndex,
        Vector columnVector );

    /**
     * Sets the specified row from the given rowVector
     *
     * @param rowIndex
     *          zero-based index into the matrix
     * @param rowVector 
     *          vector to replace in this, must have the same number of elements
     *          as this has columns
     */
    public void setRow(
        int rowIndex,
        Vector rowVector );

    /**
     * Returns a new vector containing the sum across the rows.
     *
     * @return
     *      A new vector containing the sum of the rows. Its dimensionality is
     *      equal to the number of columns.
     * @since   3.0
     */
    public Vector sumOfRows();

    /**
     * Returns a new vector containing the sum across the columns.
     *
     * @return
     *      A new vector containing the sum of the columns. Its dimensionality
     *      is equal to the number of rows.
     * @since   3.0
     */
    public Vector sumOfColumns();
    
    /**
     * Increments the value at the given position by 1.
     * 
     * @param   row
     *      The zero-based row index.
     * @param   column 
     *      The zero-based column index.
     */
    public void increment(
        final int row,
        final int column);
    
    /**
     * Increments the value at the given position by the given value.
     * 
     * @param   row
     *      The zero-based row index.
     * @param   column 
     *      The zero-based column index.
     * @param   value
     *      The value to add.
     */    
    public void increment(
        final int row,
        final int column,
        final double value);
    
    /**
     * Decrements the value at the given position by 1.
     * 
     * @param   row
     *      The zero-based row index.
     * @param   column 
     *      The zero-based column index.
     */
    public void decrement(
        final int row,
        final int column);
    
    /**
     * Decrements the value at the given position by the given value.
     * 
     * @param   row
     *      The zero-based row index.
     * @param   column 
     *      The zero-based column index.
     * @param   value
     *      The value to subtract.
     */    
    public void decrement(
        final int row,
        final int column,
        final double value);
    
    /**
     * uploads a matrix from a column-stacked vector of parameters, so that
     * v(k) = A(i,j) = A( k%M, k/M )
     *
     * @param parameters column-stacked version of this
     */
    @Override
    public void convertFromVector(
        Vector parameters );

    /**
     * Creates a column-stacked version of this, so that
     * v(k) = A(i,j) = v(j*M+i)
     *
     * @return column-stacked Vector representing this
     */
    @Override
    public Vector convertToVector();

    /**
     * Converts this matrix to a new array of array of doubles, in the same
     * order as they are in the matrix. The returned will be safe in that no
     * references are maintained by this class.
     *
     * @return
     *      This matrix as a dense array. The length of the first layer of
     *      the array will be equal to the number of rows and the second
     *      layer will be equal to the number of columns.
     */
    public double[][] toArray();
    
    /**
     * Returns a column-stacked view of this matrix as a list. This means that
     * v(k) = A(i,j) = v(j*M+i).
     * 
     * @return 
     *      The values in this matrix as a column-stacked list.
     */
    public List valuesAsList();

    @Override
    public String toString();

    /**
     * Converts the vector to a {@code String}, using the given formatter.
     *
     * @param   format The number format to use.
     * @return  The String representation of the Matrix.
     */
    public String toString(
        final NumberFormat format);
    
    /**
     * Gets a matrix factory, typically one associated with this type of matrix.
     * 
     * @return 
     *      A matrix factory.
     */
    public MatrixFactory getMatrixFactory();

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy