gov.sandia.cognition.math.matrix.mtj.AbstractSparseMatrix Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cognitive-foundry Show documentation
Show all versions of cognitive-foundry Show documentation
A single jar with all the Cognitive Foundry components.
/*
* File: AbstractSparseMatrix.java
* Authors: Kevin R. Dixon
* Company: Sandia National Laboratories
* Project: Cognitive Foundry
*
* Copyright April 11, 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.mtj;
import gov.sandia.cognition.annotation.CodeReview;
import gov.sandia.cognition.math.OperationNotConvergedException;
import gov.sandia.cognition.math.matrix.MatrixEntry;
import java.text.NumberFormat;
import no.uib.cipr.matrix.sparse.QMR;
/**
* Implements some generic operations that any sparse-matrix representation
* must do.
*
* @author Kevin R. Dixon
* @since 1.0
*
*/
@CodeReview(
reviewer="Jonathan McClain",
date="2006-05-19",
changesNeeded=false,
comments="Looks fine."
)
public abstract class AbstractSparseMatrix
extends AbstractMTJMatrix
{
/**
* Creates a new instance of AbstractSparseMatrix using the given MTJ matrix
* @param internalMatrix
* internal MTJ matrix to base this on
*/
protected AbstractSparseMatrix(
no.uib.cipr.matrix.Matrix internalMatrix )
{
super( internalMatrix );
}
/**
* Compact the memory used by the matrix, getting rid of any zero elements
*/
public abstract void compact();
public SparseVector times(
final AbstractMTJVector vector )
{
SparseVector answer = new SparseVector( this.getNumRows() );
this.timesInto( vector, answer );
return answer;
}
@Override
public void setElement(
int rowIndex,
int columnIndex,
double value )
{
// Only set a value in a SparseVector if it's different than what's
// in there already!
// (This is to prevent us from adding zeros into the SparseVector
// unnecessarily)
double existing = this.getElement( rowIndex, columnIndex );
if (existing != value)
{
super.setElement( rowIndex, columnIndex, value );
}
}
/**
* This sparse-vector solver performs iterative solving for "x" in the
* equation: this*x = b, and the AbstractSparseMatrix "this" can be
* unstructured (e.g., asymmetric, indefinite, etc.)
* @param b {@inheritDoc}
* @return {@inheritDoc}
*/
@Override
public SparseVector solve(
final AbstractMTJVector b )
{
int M = this.getNumRows();
int N = this.getNumColumns();
AbstractSparseMatrix Asquare;
int S = Math.max( M, N );
if (M != N)
{
Asquare = new SparseMatrix( S, S );
Asquare.setSubMatrix( 0, 0, this );
}
else
{
Asquare = this;
}
AbstractMTJVector bsquare;
if (S != M)
{
bsquare = new SparseVector( S );
for (int i = 0; i < M; i++)
{
bsquare.setElement( i, b.getElement( i ) );
}
}
else
{
bsquare = b;
}
SparseVector xsquare = new SparseVector( Asquare.getNumColumns() );
QMR sparseSolver = new QMR( xsquare.getInternalVector() );
try
{
sparseSolver.solve( Asquare.getInternalMatrix(), bsquare.getInternalVector(), xsquare.getInternalVector() );
}
catch (Exception ex)
{
throw new OperationNotConvergedException(ex);
}
SparseVector x;
if (S != N)
{
x = new SparseVector( N );
for (int i = 0; i < N; i++)
{
x.setElement( i, xsquare.getElement( i ) );
}
}
else
{
x = xsquare;
}
return x;
}
public DenseMatrix pseudoInverse(
double effectiveZero )
{
DenseMatrix Ainternal = new DenseMatrix( this );
return Ainternal.pseudoInverse( effectiveZero );
}
/**
* Creates a string in the "(Row,Column): value" for the nonzero elements
* @return String representing the sparse matrix
*/
@Override
public String toString()
{
final StringBuilder result = new StringBuilder(100);
for (MatrixEntry e : this)
{
result.append("(");
result.append(e.getRowIndex());
result.append(",");
result.append(e.getColumnIndex());
result.append("): ");
result.append(e.getValue());
result.append("\n");
}
if (result.length() == 0)
{
result.append("No nonzero entries");
}
return result.toString();
}
public String toString(
final NumberFormat format)
{
final StringBuilder result = new StringBuilder();
for (MatrixEntry e : this)
{
result.append("(");
result.append(e.getRowIndex());
result.append(",");
result.append(e.getColumnIndex());
result.append("): ");
result.append(format.format(e.getValue()));
result.append("\n");
}
if (result.length() == 0)
{
result.append("No nonzero entries");
}
return result.toString();
}
public SparseVector getColumn(
int columnIndex )
{
int M = this.getNumRows();
SparseVector columnVector = new SparseVector( M );
for (int i = 0; i < M; i++)
{
double value = this.getElement( i, columnIndex );
if (value != 0.0)
{
columnVector.setElement( i, value );
}
}
return columnVector;
}
public SparseVector getRow(
int rowIndex )
{
int N = this.getNumColumns();
SparseVector rowVector = new SparseVector( N );
for (int j = 0; j < N; j++)
{
double value = this.getElement( rowIndex, j );
if (value != 0.0)
{
rowVector.setElement( j, value );
}
}
return rowVector;
}
@Override
public boolean isSparse()
{
return true;
}
}