Exemplo n.º 1
0
    public static void svd_truncated_u(int m, int n, double[] a, ref double[] un, ref double[] sn,
                                       ref double[] v)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    SVD_TRUNCATED_U gets the truncated SVD when N <= M
    //
    //  Discussion:
    //
    //    A(mxn) = U(mxm)  * S(mxn)  * V(nxn)'
    //           = Un(mxn) * Sn(nxn) * V(nxn)'
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    14 September 2006
    //
    //  Author:
    //
    //    John Burkardt
    //
    //  Parameters:
    //
    //    Input, int M, N, the number of rows and columns in the matrix A.
    //
    //    Input, double A[M*N], the matrix whose singular value
    //    decomposition we are investigating.
    //
    //    Output, double UN[M*N], SN[N*N], V[N*N], the factors
    //    that form the singular value decomposition of A.
    //
    {
        int i;
        int j;

        //
        //  The correct size of E and SDIAG is min ( m+1, n).
        //
        double[] a_copy = new double[m * n];
        double[] e      = new double[m + n];
        double[] sdiag  = new double[m + n];
        double[] work   = new double[m];
        //
        //  Compute the eigenvalues and eigenvectors.
        //
        const int job = 21;

        //
        //  The input matrix is destroyed by the routine.  Since we need to keep
        //  it around, we only pass a copy to the routine.
        //
        for (j = 0; j < n; j++)
        {
            for (i = 0; i < m; i++)
            {
                a_copy[i + j * m] = a[i + j * m];
            }
        }

        int info = DSVDC.dsvdc(ref a_copy, m, m, n, ref sdiag, ref e, ref un, m, ref v, n, work, job);

        if (info != 0)
        {
            Console.WriteLine("");
            Console.WriteLine("SVD_TRUNCATED_U - Failure!");
            Console.WriteLine("  The SVD could not be calculated.");
            Console.WriteLine("  LINPACK routine DSVDC returned a nonzero");
            Console.WriteLine("  value of the error flag, INFO = " + info + "");
            return;
        }

        //
        //  Make the NxN matrix S from the diagonal values in SDIAG.
        //
        for (j = 0; j < n; j++)
        {
            for (i = 0; i < n; i++)
            {
                if (i == j)
                {
                    sn[i + j * n] = sdiag[i];
                }
                else
                {
                    sn[i + j * n] = 0.0;
                }
            }
        }
    }
Exemplo n.º 2
0
    public static void r8mat_svd_linpack(int m, int n, double[] a, ref double[] u, ref double[] s,
                                         ref double[] v)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    R8MAT_SVD_LINPACK gets the SVD of a matrix using a call to LINPACK.
    //
    //  Discussion:
    //
    //    The singular value decomposition of a real MxN matrix A has the form:
    //
    //      A = U * S * V'
    //
    //    where
    //
    //      U is MxM orthogonal,
    //      S is MxN, and entirely zero except for the diagonal;
    //      V is NxN orthogonal.
    //
    //    Moreover, the nonzero entries of S are positive, and appear
    //    in order, from largest magnitude to smallest.
    //
    //    This routine calls the LINPACK routine DSVDC to compute the
    //    factorization.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    14 September 2006
    //
    //  Author:
    //
    //    John Burkardt
    //
    //  Parameters:
    //
    //    Input, int M, N, the number of rows and columns in the matrix A.
    //
    //    Input, double A[M*N], the matrix whose singular value
    //    decomposition we are investigating.
    //
    //    Output, double U[M*M], S[M*N], V[N*N], the factors
    //    that form the singular value decomposition of A.
    //
    {
        int i;
        int j;

        //
        //  The correct size of E and SDIAG is min ( m+1, n).
        //
        double[] a_copy = new double[m * n];
        double[] e      = new double[m + n];
        double[] sdiag  = new double[m + n];
        double[] work   = new double[m];
        //
        //  Compute the eigenvalues and eigenvectors.
        //
        const int job = 11;

        //
        //  The input matrix is destroyed by the routine.  Since we need to keep
        //  it around, we only pass a copy to the routine.
        //
        for (j = 0; j < n; j++)
        {
            for (i = 0; i < m; i++)
            {
                a_copy[i + j * m] = a[i + j * m];
            }
        }

        int info = DSVDC.dsvdc(ref a_copy, m, m, n, ref sdiag, ref e, ref u, m, ref v, n, work, job);

        if (info != 0)
        {
            Console.WriteLine("");
            Console.WriteLine("R8MAT_SVD_LINPACK - Failure!");
            Console.WriteLine("  The SVD could not be calculated.");
            Console.WriteLine("  LINPACK routine DSVDC returned a nonzero");
            Console.WriteLine("  value of the error flag, INFO = " + info + "");
            return;
        }

        //
        //  Make the MxN matrix S from the diagonal values in SDIAG.
        //
        for (j = 0; j < n; j++)
        {
            for (i = 0; i < m; i++)
            {
                if (i == j)
                {
                    s[i + j * m] = sdiag[i];
                }
                else
                {
                    s[i + j * m] = 0.0;
                }
            }
        }
        //
        //  Note that we do NOT need to transpose the V that comes out of LINPACK!
        //
    }
Exemplo n.º 3
0
    public static double[] svd_solve(int m, int n, double[] a, double[] b)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    SVD_SOLVE solves a linear system in the least squares sense.
    //
    //  Discussion:
    //
    //    The vector X returned by this routine should always minimize the
    //    Euclidean norm of the residual ||A*x-b||.
    //
    //    If the matrix A does not have full column rank, then there are multiple
    //    vectors that attain the minimum residual.  In that case, the vector
    //    X returned by this routine is the unique such minimizer that has the
    //    the minimum possible Euclidean norm, that is, ||A*x-b|| and ||x||
    //    are both minimized.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    21 April 2012
    //
    //  Author:
    //
    //    John Burkardt
    //
    //  Reference:
    //
    //    David Kahaner, Cleve Moler, Steven Nash,
    //    Numerical Methods and Software,
    //    Prentice Hall, 1989,
    //    ISBN: 0-13-627258-4,
    //    LC: TA345.K34.
    //
    //  Parameters:
    //
    //    Input, int M, the number of rows of A.
    //
    //    Input, int N, the number of columns of A.
    //
    //    Input, double A[M*N], the matrix.
    //
    //    Input, double B[M], the right hand side.
    //
    //    Output, double SVD_SOLVE[N], the least squares solution.
    //
    {
        int i;

        //
        //  Get the SVD.
        //
        double[]  a_copy = typeMethods.r8mat_copy_new(m, n, a);
        double[]  sdiag  = new double[Math.Max(m + 1, n)];
        double[]  e      = new double[Math.Max(m + 1, n)];
        double[]  u      = new double[m * m];
        double[]  v      = new double[n * n];
        double[]  work   = new double[m];
        const int job    = 11;

        int info = DSVDC.dsvdc(ref a_copy, m, m, n, ref sdiag, ref e, ref u, m, ref v, n, work, job);

        if (info != 0)
        {
            Console.WriteLine("");
            Console.WriteLine("SVD_SOLVE - Failure!");
            Console.WriteLine("  The SVD could not be calculated.");
            Console.WriteLine("  LINPACK routine DSVDC returned a nonzero");
            Console.WriteLine("  value of the error flag, INFO = " + info + "");
            return(null);
        }

        double[] ub = typeMethods.r8mat_mtv_new(m, m, u, b);
        //
        //  For singular problems, there may be tiny but nonzero singular values
        //  that should be ignored.  This is a reasonable attempt to avoid such
        //  problems, although in general, the user might wish to control the tolerance.
        //
        double smax = typeMethods.r8vec_max(n, sdiag);

        if (smax <= typeMethods.r8_epsilon())
        {
            smax = 1.0;
        }

        double stol = typeMethods.r8_epsilon() * smax;

        double[] sub = new double[n];

        for (i = 0; i < n; i++)
        {
            sub[i] = 0.0;
            if (i >= m)
            {
                continue;
            }

            if (stol <= sdiag[i])
            {
                sub[i] = ub[i] / sdiag[i];
            }
        }

        double[] x = typeMethods.r8mat_mv_new(n, n, v, sub);

        return(x);
    }
Exemplo n.º 4
0
    public static void singular_vectors(int m, int n, int basis_num, ref double[] a, ref double[] sval)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    SINGULAR_VECTORS computes the desired singular values.
    //
    //  Discussion:
    //
    //    The LINPACK SVD routine DSVDC is used to compute the singular
    //    value decomposition:
    //
    //      A = U * S * V'
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    09 May 2005
    //
    //  Author:
    //
    //    John Burkardt
    //
    //  Parameters:
    //
    //    Input, int M, the number of spatial dimensions.
    //
    //    Input, int N, the number of data points.
    //
    //    Input, int BASIS_NUM, the number of basis vectors to be extracted.
    //
    //    Input/output, double A[M*N]; on input, the matrix whose
    //    singular values are to be computed.  On output, A(M,1:BASIS_NUM)
    //    contains the first BASIS_NUM left singular vectors.
    //
    //    Output, double SVAL[BASIS_NUM], the first BASIS_NUM
    //    singular values.
    //
    {
        int i;

        Console.WriteLine("");
        Console.WriteLine("SINGULAR_VECTORS");
        Console.WriteLine("  For an MxN matrix A in general storage,");
        Console.WriteLine("  The LINPACK routine DSVDC computes the");
        Console.WriteLine("  singular value decomposition:");
        Console.WriteLine("");
        Console.WriteLine("    A = U * S * V'");
        Console.WriteLine("");
        //
        //  Compute the eigenvalues and eigenvectors.
        //
        double[]  s    = new double[Math.Min(m + 1, n)];
        double[]  e    = new double[n];
        double[]  u    = a;
        double[]  v    = null;
        double[]  work = new double[m];
        const int job  = 20;

        int info = DSVDC.dsvdc(ref a, m, m, n, ref s, ref e, ref u, m, ref v, n, work, job);

        if (info != 0)
        {
            Console.WriteLine("");
            Console.WriteLine("SINGULAR_VECTORS - Warning:");
            Console.WriteLine("  DSVDC returned nonzero INFO = " + info + "");
            return;
        }

        for (i = 0; i < basis_num; i++)
        {
            sval[i] = s[i];
        }

        Console.WriteLine("");
        Console.WriteLine("  The leading singular values:");
        Console.WriteLine("");

        for (i = 0; i < basis_num; i++)
        {
            Console.WriteLine("  "
                              + (i + 1).ToString(CultureInfo.InvariantCulture).PadLeft(4) + "  "
                              + sval[i].ToString(CultureInfo.InvariantCulture).PadLeft(16) + "");
        }
    }
Exemplo n.º 5
0
    public static double[] r8mat_solve_svd(int m, int n, double[] a, double[] b)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    R8MAT_SOLVE_SVD solves a linear system A*x=b using the SVD.
    //
    //  Discussion:
    //
    //    When the system is determined, the solution is the solution in the
    //    ordinary sense, and A*x = b.
    //
    //    When the system is overdetermined, the solution minimizes the
    //    L2 norm of the residual ||A*x-b||.
    //
    //    When the system is underdetermined, ||A*x-b|| should be zero, and
    //    the solution is the solution of minimum L2 norm, ||x||.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    30 June 2012
    //
    //  Author:
    //
    //    John Burkardt
    //
    //  Parameters:
    //
    //    Input, int M, N, the number of rows and columns
    //    in the matrix A.
    //
    //    Input, double A[M,*N], the matrix.
    //
    //    Input, double B[M], the right hand side.
    //
    //    Output, double R8MAT_SOLVE_SVD[N], the solution.
    //
    {
        int i;
        int j;

        //
        //  Compute the SVD decomposition.
        //
        double[]  a_copy = r8mat_copy_new(m, n, a);
        double[]  sdiag  = new double[Math.Max(m + 1, n)];
        double[]  e      = new double[Math.Max(m + 1, n)];
        double[]  u      = new double[m * m];
        double[]  v      = new double[n * n];
        double[]  work   = new double[m];
        const int job    = 11;

        int info = DSVDC.dsvdc(ref a_copy, m, m, n, ref sdiag, ref e, ref u, m, ref v, n, work, job);

        if (info != 0)
        {
            Console.WriteLine("");
            Console.WriteLine("R8MAT_SOLVE_SVD - Fatal error!");
            Console.WriteLine("  The SVD could not be calculated.");
            Console.WriteLine("  LINPACK routine DSVDC returned a nonzero");
            Console.WriteLine("  value of the error flag, INFO = " + info + "");
            return(null);
        }

        double[] s = new double [m * n];

        for (j = 0; j < n; j++)
        {
            for (i = 0; i < m; i++)
            {
                s[i + j * m] = 0.0;
            }
        }

        for (i = 0; i < Math.Min(m, n); i++)
        {
            s[i + i * m] = sdiag[i];
        }

        //
        //  Compute the pseudo inverse.
        //
        double[] sp = new double [n * m];

        for (j = 0; j < m; j++)
        {
            for (i = 0; i < n; i++)
            {
                sp[i + j * m] = 0.0;
            }
        }

        for (i = 0; i < Math.Min(m, n); i++)
        {
            if (s[i + i * m] != 0.0)
            {
                sp[i + i * n] = 1.0 / s[i + i * m];
            }
        }

        double[] a_pseudo = new double[n * m];

        for (j = 0; j < m; j++)
        {
            for (i = 0; i < n; i++)
            {
                a_pseudo[i + j * n] = 0.0;
                int k;
                for (k = 0; k < n; k++)
                {
                    int l;
                    for (l = 0; l < m; l++)
                    {
                        a_pseudo[i + j * n] += v[i + k * n] * sp[k + l * n] * u[j + l * m];
                    }
                }
            }
        }

        //
        //  Compute x = A_pseudo * b.
        //
        double[] x = r8mat_mv_new(n, m, a_pseudo, b);

        return(x);
    }