org.ujmp.core.doublematrix.calculation.general.decomposition
Class Ginv

java.lang.Object
  extended by org.ujmp.core.calculation.AbstractCalculation
      extended by org.ujmp.core.doublematrix.calculation.AbstractDoubleCalculation
          extended by org.ujmp.core.doublematrix.calculation.general.decomposition.Ginv
All Implemented Interfaces:
Serializable, Calculation, DoubleCalculation

public class Ginv
extends AbstractDoubleCalculation

This class implements some matrix operations that I need for other things I'm doing. Why not use existing packages? Well, I've tried, but they seem to not have simple linear algebra things like inverting singular or non-square inverses. Maybe I've just been looking in the wrong places.

Anyway I wrote this algorithm in 1989 using Ada and Fortran77. In 1992 I converted it to C++, and in 2003 I made it a C++ template to be used for absolutely anything that you'd want.

I attempted to convert this to a Java template, but I need to make objects of the parameter type, and without doing some inspection or copy tricks, I can't get there from here. I only use this for doubles anyway, so here's the version that I use. The C++ version is still available.

The matrix inversion was in from the start, as the only really useful part of the Class. I added the bandwidth reduction routine in 1991 - I was stuck in SOS (USAF school) at the time and was thinking about optimizing the bandwidth of a matrix made from a finite-element grid by renumbering the nodes of the grid.

Changes by Holger Arndt: The original code has been adapted for the Universal Java Matrix Package. Methods for different matrix implementations have been added.

Author:
Rand Huso, Holger Arndt
See Also:
Serialized Form

Nested Class Summary
 
Nested classes/interfaces inherited from interface org.ujmp.core.calculation.Calculation
Calculation.Ret
 
Field Summary
 
Fields inherited from interface org.ujmp.core.calculation.Calculation
ALL, COLUMN, LINK, NEW, NONE, ORIG, ROW
 
Constructor Summary
Ginv(Matrix source)
           
 
Method Summary
static void addColTimes(DenseDoubleMatrix2D matrix, long diag, long fromRow, long col, double factor)
          Add a factor times one column to another column
static void addColTimes(double[][] matrix, int diag, int fromRow, int col, double factor)
          Add a factor times one column to another column
static void addColTimes(Matrix matrix, long diag, long fromRow, long col, double factor)
          Add a factor times one column to another column
static void addRowTimes(DenseDoubleMatrix2D matrix, long diag, long fromCol, long row, double factor)
          Add a factor times one row to another row
static void addRowTimes(double[][] matrix, int diag, int fromCol, int row, double factor)
          Add a factor times one row to another row
static void addRowTimes(Matrix matrix, long diag, long fromCol, long row, double factor)
          Add a factor times one row to another row
static Matrix arbitrariness(Matrix source, Matrix inverse)
          Calculate the arbitrariness of the solution.
 DenseDoubleMatrix2D calcLink()
           
 DenseDoubleMatrix2D calcNew()
           
 DenseDoubleMatrix2D calcOrig()
           
static boolean canSwapCols(Matrix matrix, int col1, int col2, int row1)
          Check to see if columns can be swapped - part of the bandwidth reduction algorithm.
static boolean canSwapRows(Matrix matrix, int row1, int row2, int col1)
          Check to see if a non-zero and a zero value in the rows leading up to this column can be swapped.
static void divideRowBy(DenseDoubleMatrix2D matrix, long aRow, long fromCol, double value)
          Divide the row from this column position by this value
static void divideRowBy(double[][] matrix, int aRow, int fromCol, double value)
          Divide the row from this column position by this value
static void divideRowBy(Matrix matrix, long aRow, long fromCol, double value)
          Divide the row from this column position by this value
 double getDouble(long... coordinates)
           
static DenseDoubleMatrix2D inverse(DenseDoubleMatrix2D matrix)
          Same as inverse(Matrix) but optimized for 2D dense double matrices
static DenseDoubleMatrix2D inverse(double[][] matrix)
          Same as inverse(Matrix) but optimized for 2D double arrays
static DenseDoubleMatrix2D inverse(Matrix matrix)
           Matrix inversion is the reason this Class exists - this method creates a generalized matrix inverse of the current matrix.
static Matrix reduce(Matrix source)
          Mathematical operator to reduce the bandwidth of a HusoMatrix.
static Matrix reduce(Matrix source, Matrix response)
           
static void swapCols(DenseDoubleMatrix2D matrix, long col1, long col2)
          Swap components in the two columns.
static void swapCols(double[][] matrix, int col1, int col2)
          Swap components in the two columns.
static void swapCols(Matrix matrix, long col1, long col2)
          Swap components in the two columns.
static void swapPivot(DenseDoubleMatrix2D source, long diag, DenseDoubleMatrix2D s, DenseDoubleMatrix2D t)
          Swap the matrices so that the largest value is on the pivot
static void swapPivot(double[][] source, int diag, double[][] s, double[][] t)
          Swap the matrices so that the largest value is on the pivot
static void swapPivot(Matrix source, long diag, Matrix s, Matrix t)
          Swap the matrices so that the largest value is on the pivot
static void swapRows(DenseDoubleMatrix2D matrix, long row1, long row2)
          Swap components in the two rows.
static void swapRows(double[][] matrix, int row1, int row2)
          Swap components in the two rows.
static void swapRows(Matrix matrix, long row1, long row2)
          Swap components in the two rows.
static DenseDoubleMatrix2D times(DenseDoubleMatrix2D matrix1, DenseDoubleMatrix2D matrix2, long timesInner)
          This routine performs the matrix multiplication.
static double[][] times(double[][] matrix1, double[][] matrix2, int timesInner)
          This routine performs the matrix multiplication.
 
Methods inherited from class org.ujmp.core.doublematrix.calculation.AbstractDoubleCalculation
getValueType, setDouble
 
Methods inherited from class org.ujmp.core.calculation.AbstractCalculation
allCoordinates, availableCoordinates, calc, calcMulti, contains, getAnnotation, getDimension, getSize, getSource, getSources, getStorageType, getValueCount, isSparse, setAnnotation, setDimension, setSources
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 
Methods inherited from interface org.ujmp.core.calculation.Calculation
allCoordinates, availableCoordinates, calc, calcMulti, contains, getAnnotation, getDimension, getSize, getSource, getSources, getStorageType, getValueCount, isSparse, setAnnotation, setDimension, setSources
 

Constructor Detail

Ginv

public Ginv(Matrix source)
Method Detail

times

public static DenseDoubleMatrix2D times(DenseDoubleMatrix2D matrix1,
                                        DenseDoubleMatrix2D matrix2,
                                        long timesInner)
This routine performs the matrix multiplication. The final matrix size is taken from the rows of the left matrix and the columns of the right matrix. The timesInner is the minimum of the left columns and the right rows.

Parameters:
matrix1 - the first matrix
matrix2 - the second matrix
timesInner - number of rows/columns to process
Returns:
product of the two matrices

times

public static double[][] times(double[][] matrix1,
                               double[][] matrix2,
                               int timesInner)
This routine performs the matrix multiplication. The final matrix size is taken from the rows of the left matrix and the columns of the right matrix. The timesInner is the minimum of the left columns and the right rows.

Parameters:
matrix1 - the first matrix
matrix2 - the second matrix
timesInner - number of rows/columns to process
Returns:
product of the two matrices

swapCols

public static void swapCols(Matrix matrix,
                            long col1,
                            long col2)
Swap components in the two columns.

Parameters:
matrix - the matrix to modify
col1 - the first row
col2 - the second row

swapCols

public static void swapCols(DenseDoubleMatrix2D matrix,
                            long col1,
                            long col2)
Swap components in the two columns.

Parameters:
matrix - the matrix to modify
col1 - the first row
col2 - the second row

swapCols

public static void swapCols(double[][] matrix,
                            int col1,
                            int col2)
Swap components in the two columns.

Parameters:
matrix - the matrix to modify
col1 - the first row
col2 - the second row

swapRows

public static void swapRows(Matrix matrix,
                            long row1,
                            long row2)
Swap components in the two rows.

Parameters:
matrix - the matrix to modify
row1 - the first row
row2 - the second row

swapRows

public static void swapRows(DenseDoubleMatrix2D matrix,
                            long row1,
                            long row2)
Swap components in the two rows.

Parameters:
matrix - the matrix to modify
row1 - the first row
row2 - the second row

swapRows

public static void swapRows(double[][] matrix,
                            int row1,
                            int row2)
Swap components in the two rows.

Parameters:
matrix - the matrix to modify
row1 - the first row
row2 - the second row

inverse

public static DenseDoubleMatrix2D inverse(Matrix matrix)

Matrix inversion is the reason this Class exists - this method creates a generalized matrix inverse of the current matrix. The result is returned in a new matrix.

Matrices may be square, non-square, or singular. The operations will be identical. If the matrix has a single possible inverse, there will be no arbitrariness to the solution. The method here was suggested to me by John Jones Jr. at AFIT in the 1980s, and this algorithm is an original creation of mine to implement his method.

A matrix inverse has some properties described here. Let A be the original matrix. Let the inverse, as calculated here be A12 (an inverse with properties 1 and 2 - being left side inverse and right side inverse). An inverse times the original matrix should yield an identity matrix. A x = b is the usual equation where A is the matrix, x is a vector of the unknowns and b is a vector of the constant values:

Given these equations: C x + D y + E z = b1 F x + G y + H z = b1

(The usual programs available don't handle more unknowns than equations, and will stop at this point)

The A matrix is: | C D E | | F G H |

The x vector is: | x | | y | | z |

The b vector is: | b1 | | b2 |

A * x = b

The generalized inverse A12 in this case will be of size (3,2): | J K | | L M | | N P |

The left-hand inverse is defined such that the product of the (generalized) inverse times the original matrix times the (generalized) inverse will yield the (generalized) inverse again: A12 * (A * A12) = A12

The right-hand inverse is defined similarly: (A * A12) * A = A

If a matrix (A12) meets these criteria, it's considered to be a generalized inverse of the A matrix, even though it may not be square, or the product of A * A12 or A12 * A may not be the identity matrix! (Won't be if the input A matrix is non-square or singular)

In the case of (A * A12) being the identity matrix, the product of (A12 * A) will also be the identity matrix, and the solution will be unique: A12 will be the exact and only solution to the equation.

Refer to http://mjollnir.com/matrix/ for the best description.

Parameters:
matrix - matrix to invert
Returns:
a generalized matrix inverse (possibly not unique)

inverse

public static DenseDoubleMatrix2D inverse(DenseDoubleMatrix2D matrix)
Same as inverse(Matrix) but optimized for 2D dense double matrices

Parameters:
matrix - the matrix to invert
Returns:
generalized matrix inverse

inverse

public static DenseDoubleMatrix2D inverse(double[][] matrix)
Same as inverse(Matrix) but optimized for 2D double arrays

Parameters:
matrix - the matrix to invert
Returns:
generalized matrix inverse

addColTimes

public static void addColTimes(Matrix matrix,
                               long diag,
                               long fromRow,
                               long col,
                               double factor)
Add a factor times one column to another column

Parameters:
matrix - the matrix to modify
diag - coordinate on the diagonal
fromRow - first row to process
col - column to process
factor - factor to multiply

addColTimes

public static void addColTimes(double[][] matrix,
                               int diag,
                               int fromRow,
                               int col,
                               double factor)
Add a factor times one column to another column

Parameters:
matrix - the matrix to modify
diag - coordinate on the diagonal
fromRow - first row to process
col - column to process
factor - factor to multiply

addColTimes

public static void addColTimes(DenseDoubleMatrix2D matrix,
                               long diag,
                               long fromRow,
                               long col,
                               double factor)
Add a factor times one column to another column

Parameters:
matrix - the matrix to modify
diag - coordinate on the diagonal
fromRow - first row to process
col - column to process
factor - factor to multiply

addRowTimes

public static void addRowTimes(DenseDoubleMatrix2D matrix,
                               long diag,
                               long fromCol,
                               long row,
                               double factor)
Add a factor times one row to another row

Parameters:
matrix - the matrix to modify
diag - coordinate on the diagonal
fromCol - first column to process
row - row to process
factor - factor to multiply

addRowTimes

public static void addRowTimes(double[][] matrix,
                               int diag,
                               int fromCol,
                               int row,
                               double factor)
Add a factor times one row to another row

Parameters:
matrix - the matrix to modify
diag - coordinate on the diagonal
fromCol - first column to process
row - row to process
factor - factor to multiply

addRowTimes

public static void addRowTimes(Matrix matrix,
                               long diag,
                               long fromCol,
                               long row,
                               double factor)
Add a factor times one row to another row

Parameters:
matrix - the matrix to modify
diag - coordinate on the diagonal
fromCol - first column to process
row - row to process
factor - factor to multiply

divideRowBy

public static void divideRowBy(Matrix matrix,
                               long aRow,
                               long fromCol,
                               double value)
Divide the row from this column position by this value

Parameters:
matrix - the matrix to modify
aRow - the row to process
fromCol - starting from column
value - the value to divide

divideRowBy

public static void divideRowBy(DenseDoubleMatrix2D matrix,
                               long aRow,
                               long fromCol,
                               double value)
Divide the row from this column position by this value

Parameters:
matrix - the matrix to modify
aRow - the row to process
fromCol - starting from column
value - the value to divide

divideRowBy

public static void divideRowBy(double[][] matrix,
                               int aRow,
                               int fromCol,
                               double value)
Divide the row from this column position by this value

Parameters:
matrix - the matrix to modify
aRow - the row to process
fromCol - starting from column
value - the value to divide

swapPivot

public static void swapPivot(Matrix source,
                             long diag,
                             Matrix s,
                             Matrix t)
Swap the matrices so that the largest value is on the pivot

Parameters:
source - the matrix to modify
diag - the position on the diagonal
s - the matrix s
t - the matrix t

swapPivot

public static void swapPivot(DenseDoubleMatrix2D source,
                             long diag,
                             DenseDoubleMatrix2D s,
                             DenseDoubleMatrix2D t)
Swap the matrices so that the largest value is on the pivot

Parameters:
source - the matrix to modify
diag - the position on the diagonal
s - the matrix s
t - the matrix t

swapPivot

public static void swapPivot(double[][] source,
                             int diag,
                             double[][] s,
                             double[][] t)
Swap the matrices so that the largest value is on the pivot

Parameters:
source - the matrix to modify
diag - the position on the diagonal
s - the matrix s
t - the matrix t

canSwapRows

public static boolean canSwapRows(Matrix matrix,
                                  int row1,
                                  int row2,
                                  int col1)
Check to see if a non-zero and a zero value in the rows leading up to this column can be swapped. This is part of the bandwidth reduction algorithm.

Parameters:
matrix - the matrix to check
row1 - the first row
row2 - the second row
col1 - the column
Returns:
true if the rows can be swapped

canSwapCols

public static boolean canSwapCols(Matrix matrix,
                                  int col1,
                                  int col2,
                                  int row1)
Check to see if columns can be swapped - part of the bandwidth reduction algorithm.

Parameters:
matrix - the matrix to check
col1 - the first column
col2 - the second column
row1 - the row
Returns:
true if the columns can be swapped

reduce

public static Matrix reduce(Matrix source,
                            Matrix response)

reduce

public static Matrix reduce(Matrix source)
Mathematical operator to reduce the bandwidth of a HusoMatrix. The HusoMatrix must be a square HusoMatrix or no operations are performed. This method reduces a sparse HusoMatrix and returns the numbering of nodes to achieve this banding. It may be advantageous to run this twice, though sample cases haven't shown the need. Rows are numbered beginning with 0. The return HusoMatrix is a vector with what should be used as the new numbering to achieve minimum banding. Each node in a typical finite-element grid is connected to surrounding nodes which are connected back to this node. This routine was designed with this requirement in mind. It may work where a node is connected to an adjacent node that is not connected back to this node... and this is quite possible when the grid is on a sphere and the connections are determined based on initial headings or bearings.

Returns:
the vector indicating the numbering required to achieve a minimum banding

arbitrariness

public static Matrix arbitrariness(Matrix source,
                                   Matrix inverse)
Calculate the arbitrariness of the solution. This is a way to find out how unique the existing inverse is. The equation is here: A * x = b And the solution is: x = A12 * b + an arbitrariness which could be infinite, but will follow a general pattern. For instance, if the solution is a line, it could be anchored in the Y at any arbitrary distance. If the solution is a plane it could be arbitrarily set to any place in perhaps two different dimensions. The arbitrariness is calculated by taking the difference between the complete inverse times the original and subtracting the generalized inverse times the original matrix. That's the idea, here's the formula: x = A12 * b + (I - (A12 * A)) * z The z is a completely arbitrary vector (you decide that one). The product (A12 * A) could be the Identity HusoMatrix, if the solution is unique, in which case the right side drops out: (I - I) * z Again, it's a lot easier to refer to the http://aktzin.com/ site for the description and a different way to get this information.

Returns:
the matrix (I - (A12 * A))

getDouble

public double getDouble(long... coordinates)
                 throws MatrixException
Throws:
MatrixException

calcLink

public DenseDoubleMatrix2D calcLink()
                             throws MatrixException
Specified by:
calcLink in interface Calculation
Overrides:
calcLink in class AbstractDoubleCalculation
Throws:
MatrixException

calcNew

public DenseDoubleMatrix2D calcNew()
                            throws MatrixException
Specified by:
calcNew in interface Calculation
Overrides:
calcNew in class AbstractDoubleCalculation
Throws:
MatrixException

calcOrig

public DenseDoubleMatrix2D calcOrig()
                             throws MatrixException
Specified by:
calcOrig in interface Calculation
Overrides:
calcOrig in class AbstractDoubleCalculation
Throws:
MatrixException


Copyright © 2010. All Rights Reserved.