Added a getCovariance method to singular value decomposition

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@788805 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Luc Maisonobe 2009-06-26 18:27:57 +00:00
parent c8a6ed4c40
commit 8e473959fd
5 changed files with 87 additions and 1 deletions

View File

@ -383,6 +383,10 @@ public class MessagesResources_fr
{ "matrix is singular",
"matrice singuli\u00e8re" },
// org.apache.commons.math.linear.decomposition.SingularValueDecompositionImpl
{ "cutoff singular value is {0}, should be at most {1}",
"la valeur singuli\u00e8re de coupure vaut {0}, elle ne devrait pas d\u00e9passer {1}" },
// org.apache.commons.math.linear.decomposition.CholeskyDecompositionImpl
// org.apache.commons.math.linear.decomposition.EigenDecompositionImpl
// org.apache.commons.math.linear.decomposition.LUDecompositionImpl

View File

@ -39,7 +39,8 @@ package org.apache.commons.math.linear;
* getRank},</li>
* <li>a {@link #getUT() getUT} method has been added,</li>
* <li>a {@link #getVT() getVT} method has been added,</li>
* <li>a {@link #getSolver() getSolver} method has been added.</li>
* <li>a {@link #getSolver() getSolver} method has been added,</li>
* <li>a {@link #getCovariance(double) getCovariance} method has been added.</li>
* </ul>
* @see <a href="http://mathworld.wolfram.com/SingularValueDecomposition.html">MathWorld</a>
* @see <a href="http://en.wikipedia.org/wiki/Singular_value_decomposition">Wikipedia</a>
@ -96,6 +97,19 @@ public interface SingularValueDecomposition {
*/
RealMatrix getVT();
/**
* Returns the n &times; n covariance matrix.
* <p>The covariance matrix is V &times; J &times; V<sup>T</sup>
* where J is the diagonal matrix of the inverse of the squares of
* the singular values.</p>
* @param minSingularValue value below which singular values are ignored
* (a 0 or negative value implies all singular value will be used)
* @return covariance matrix
* @exception IllegalArgumentException if minSingularValue is larger than
* the largest singular value, meaning all singular values are ignored
*/
RealMatrix getCovariance(double minSingularValue) throws IllegalArgumentException;
/**
* Returns the L<sub>2</sub> norm of the matrix.
* <p>The L<sub>2</sub> norm is max(|A &times; u|<sub>2</sub> /

View File

@ -256,6 +256,35 @@ public class SingularValueDecompositionImpl implements SingularValueDecompositio
}
/** {@inheritDoc} */
public RealMatrix getCovariance(final double minSingularValue) {
// get the number of singular values to consider
int dimension = 0;
while ((dimension < n) && (singularValues[dimension] >= minSingularValue)) {
++dimension;
}
if (dimension == 0) {
throw MathRuntimeException.createIllegalArgumentException(
"cutoff singular value is {0}, should be at most {1}",
minSingularValue, singularValues[0]);
}
final double[][] data = new double[dimension][n];
getVT().walkInOptimizedOrder(new DefaultRealMatrixPreservingVisitor() {
/** {@inheritDoc} */
@Override
public void visit(final int row, final int column, final double value) {
data[row][column] = value / singularValues[row];
}
}, 0, dimension - 1, 0, n - 1);
RealMatrix jv = new Array2DRowRealMatrix(data, false);
return jv.transpose().multiply(jv);
}
/** {@inheritDoc} */
public double getNorm()
throws InvalidMatrixException {

View File

@ -39,6 +39,9 @@ The <action> type attribute can be add,update,fix,remove.
</properties>
<body>
<release version="2.0" date="TBD" description="TBD">
<action dev="luc" type="add" due-to="Dimitri Pourbaix">
Added a getCovariance method to singular value decomposition
</action>
<action dev="luc" type="add" issue="MATH-278" due-to="Eugene Kirpichov">
Added robust locally weighted regression (Loess).
</action>

View File

@ -97,6 +97,42 @@ public class SingularValueDecompositionImplTest extends TestCase {
}
/** Test based on a dimension 4 Hadamard matrix. */
public void testHadamard() {
RealMatrix matrix = new Array2DRowRealMatrix(new double[][] {
{15.0 / 2.0, 5.0 / 2.0, 9.0 / 2.0, 3.0 / 2.0 },
{ 5.0 / 2.0, 15.0 / 2.0, 3.0 / 2.0, 9.0 / 2.0 },
{ 9.0 / 2.0, 3.0 / 2.0, 15.0 / 2.0, 5.0 / 2.0 },
{ 3.0 / 2.0, 9.0 / 2.0, 5.0 / 2.0, 15.0 / 2.0 }
}, false);
SingularValueDecomposition svd = new SingularValueDecompositionImpl(matrix);
assertEquals(16.0, svd.getSingularValues()[0], 1.0e-14);
assertEquals( 8.0, svd.getSingularValues()[1], 1.0e-14);
assertEquals( 4.0, svd.getSingularValues()[2], 1.0e-14);
assertEquals( 2.0, svd.getSingularValues()[3], 1.0e-14);
RealMatrix fullCovariance = new Array2DRowRealMatrix(new double[][] {
{ 85.0 / 1024, -51.0 / 1024, -75.0 / 1024, 45.0 / 1024 },
{ -51.0 / 1024, 85.0 / 1024, 45.0 / 1024, -75.0 / 1024 },
{ -75.0 / 1024, 45.0 / 1024, 85.0 / 1024, -51.0 / 1024 },
{ 45.0 / 1024, -75.0 / 1024, -51.0 / 1024, 85.0 / 1024 }
}, false);
assertEquals(0.0,
fullCovariance.subtract(svd.getCovariance(0.0)).getNorm(),
1.0e-14);
RealMatrix halfCovariance = new Array2DRowRealMatrix(new double[][] {
{ 5.0 / 1024, -3.0 / 1024, 5.0 / 1024, -3.0 / 1024 },
{ -3.0 / 1024, 5.0 / 1024, -3.0 / 1024, 5.0 / 1024 },
{ 5.0 / 1024, -3.0 / 1024, 5.0 / 1024, -3.0 / 1024 },
{ -3.0 / 1024, 5.0 / 1024, -3.0 / 1024, 5.0 / 1024 }
}, false);
assertEquals(0.0,
halfCovariance.subtract(svd.getCovariance(6.0)).getNorm(),
1.0e-14);
}
/** test A = USVt */
public void testAEqualUSVt() {
checkAEqualUSVt(MatrixUtils.createRealMatrix(testSquare));