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

gov.sandia.cognition.math.matrix.decomposition.AbstractSingularValueDecomposition Maven / Gradle / Ivy

There is a newer version: 4.0.1
Show newest version
/*
 * File:                AbstractSingularValueDecomposition.java
 * Authors:             Kevin R. Dixon
 * Company:             Sandia National Laboratories
 * Project:             Cognitive Foundry
 *
 * Copyright February 21, 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.decomposition;

import gov.sandia.cognition.annotation.CodeReview;
import gov.sandia.cognition.math.matrix.Matrix;

/**
 * Abstract container class that stores the matrices for a Singular Value
 * Decomposition (SVD) and related operations but does not actually perform
 * a singular value decomposition
 *
 * @author Kevin R. Dixon
 * @since  1.0
 *
 */
@CodeReview(
    reviewer="Jonathan McClain",
    date="2006-05-16",
    changesNeeded=false,
    comments={
        "Made very minor changes.",
        "Otherwise, looks fine."
    }
)
public abstract class AbstractSingularValueDecomposition
    extends java.lang.Object
    implements SingularValueDecomposition
{

    /** Matrix that has the left singular vectors */
    private Matrix U;

    /** Diagonal matrix of singular values */
    private Matrix S;

    /** Transpose of the matrix containing the right singular vectors */
    private Matrix Vtranspose;

    /**
     * Default constructor that nulls out all matrices
     */
    public AbstractSingularValueDecomposition()
    {
        this( null, null, null );
    }

    /**
     * Creates a new instance of AbstractSingularValueDecomposition where
     * U*S*Vtranspose = original_matrix
     * 
     * @param U
     *      orthonormal matrix of left singular vectors
     * @param S
     *      PSD diagonal matrix of singular values, sorted in descending order
     * @param Vtranspose
     *      transpose of the orthonormal matrix of the right singular vectors
     */
    public AbstractSingularValueDecomposition(
        Matrix U,
        Matrix S,
        Matrix Vtranspose )
    {
        this.setU( U );
        this.setS( S );
        this.setVtranspose( Vtranspose );
    }

    public Matrix getU()
    {
        return this.U;
    }

    /**
     * setter for left singular vectors
     * @param U left singular vectors
     */
    protected void setU( Matrix U )
    {
        this.U = U;
    }

    public Matrix getS()
    {
        return this.S;
    }

    /**
     * setter for the singular values matrix
     * @param S singular values matrix
     */
    protected void setS(
        Matrix S )
    {
        this.S = S;
    }

    public Matrix getVtranspose()
    {
        return this.Vtranspose;
    }

    /**
     * sets the transpose of the right singular vectors matrix
     * @param Vtranspose transpose of the right singular vectors matrix
     */
    protected void setVtranspose(
        Matrix Vtranspose )
    {
        this.Vtranspose = Vtranspose;
    }

    public double norm2()
    {
        double maxSV = this.getS().getElement( 0, 0 );
        return maxSV;
    }

    public double conditionNumber()
    {
        int N = this.getS().getNumRows();

        double maxSV = this.getS().getElement( 0, 0 );
        double minSV = this.getS().getElement( N - 1, N - 1 );

        double conditionNumber;

        if (minSV > 0.0)
        {
            conditionNumber = maxSV / minSV;
        }
        else
        {
            conditionNumber = Double.POSITIVE_INFINITY;
        }

        return conditionNumber;
    }

    public int rank()
    {
        return this.effectiveRank( 0.0 );
    }

    public int effectiveRank(
        double effectiveZero )
    {
        int n, N = Math.min(this.getS().getNumRows(), this.getS().getNumColumns());
        for (n = 0; n < N; n++)
        {
            if (this.getS().getElement( n, n ) <= effectiveZero)
            {
                break;
            }
        }

        return n;
    }

    public Matrix pseudoInverse()
    {
        return this.pseudoInverse( 0.0 );
    }

    public Matrix pseudoInverse(
        double effectiveZero )
    {

        Matrix V = this.getVtranspose().transpose();
        Matrix Utranspose = this.getU().transpose();
        Matrix Spinv = this.getS().transpose();

        int N = Math.min( Spinv.getNumRows(), Spinv.getNumColumns() );
        for (int i = 0; i < N; i++)
        {
            double singularValue = Spinv.getElement( i, i );
            double svinv;
            if (singularValue <= effectiveZero)
            {
                svinv = 0.0;
            }
            else
            {
                svinv = 1.0 / singularValue;
            }
            Spinv.setElement( i, i, svinv );
        }

        return V.times( Spinv ).times( Utranspose );
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy