示例#1
0
        /// <summary>
        /// Initializes eigenvalue decomposition.
        /// </summary>
        /// <param name="A">Square matrix</param>
        /// <param name="eps">Epsilon [0, 1]</param>
        public EVD(float[,] A, float eps = 1e-16f)
        {
            if (!Matrice.IsSquare(A))
            {
                throw new Exception("The matrix must be square");
            }

            this.n   = A.GetLength(0);
            this.Re  = new float[n];
            this.Im  = new float[n];
            this.eps = Maths.Float(eps);

            // for symmetric matrices eigen-value decomposition
            // without Hessenberg form.
            if (Matrice.IsSymmetric(A))
            {
                hessenberg = Jagged.Zero(n, n);
                matrices   = Jagged.ToJagged(A);

                tred2(); // Tridiagonalize.
                tql2();  // Diagonalize.
            }
            // with Hessenberg form.
            else
            {
                matrices   = Jagged.Zero(n, n);
                hessenberg = Jagged.ToJagged(A);
                orthogonal = new float[n];

                orthes(); // Reduce to Hessenberg form.
                hqr2();   // Reduce Hessenberg to real Schur form.
            }
        }
示例#2
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="m">Matrix</param>
 private void Data(float[,] m)
 {
     this.l0      = m.GetLength(0);
     this.l1      = m.GetLength(1);
     this.radius0 = l0 >> 1;
     this.radius1 = l1 >> 1;
     this.kernel  = Jagged.ToJagged(m);
 }
示例#3
0
        /// <summary>
        /// Initializes LU decomposition.
        /// </summary>
        /// <param name="A">Square matrix</param>
        public LU(float[,] A)
        {
            if (!Matrice.IsSquare(A))
            {
                throw new Exception("The matrix must be square");
            }

            // LU-decomposition:
            ludecomp(Jagged.ToJagged(A));
        }
示例#4
0
        /// <summary>
        /// Initializes Cholesky decomposition.
        /// </summary>
        /// <param name="A">Square symmetric positive definite matrix</param>
        public Cholesky(float[,] A)
        {
            if (!Matrice.IsSquare(A))
            {
                throw new Exception("The matrix must be square");
            }

            // Cholesky decomposition:
            chol(Jagged.ToJagged(A));
        }
示例#5
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="A"></param>
        private void qrdecomp(float[,] A)
        {
            // params
            this.m    = A.GetLength(0);
            this.n    = A.GetLength(1);
            this.diag = new float[n];
            this.qr   = Jagged.ToJagged(A);
            float nrm, s;
            int   k, i, j;

            // Main loop.
            for (k = 0; k < n; k++)
            {
                // Compute 2-norm of k-th column without under/overflow.
                nrm = 0;

                for (i = k; i < m; i++)
                {
                    nrm = Maths.Hypotenuse(nrm, qr[i][k]);
                }

                if (nrm != 0.0)
                {
                    // Form k-th Householder vector.
                    if (qr[k][k] < 0)
                    {
                        nrm = -nrm;
                    }
                    for (i = k; i < m; i++)
                    {
                        qr[i][k] /= nrm; // Make v a unit vector
                    }
                    qr[k][k] += 1.0f;    // + the (e)kth vector

                    // Apply transformation to remaining columns.
                    for (j = k + 1; j < n; j++) // For each column
                    {
                        s = 0.0f;
                        for (i = k; i < m; i++) // For each row
                        {
                            s += qr[i][k] * qr[i][j];
                        }

                        s = (-s) / qr[k][k];    // Unit vector product

                        for (i = k; i < m; i++) // For each row
                        {
                            qr[i][j] += s * qr[i][k];
                        }
                    }
                }

                diag[k] = -nrm;
            }
        }
示例#6
0
文件: GEVD.cs 项目: asiryan/UMapx
        /// <summary>
        /// Initializes generalized eigenvalue decomposition.
        /// </summary>
        /// <param name="a">Matrix A</param>
        /// <param name="b">Matrix B</param>
        /// <param name="eps">Epsilon [0, 1]</param>
        public GEVD(float[,] a, float[,] b, float eps = 1e-16f)
        {
            if (a.GetLength(0) != a.GetLength(1))
            {
                throw new ArgumentException("The matrix must be square");
            }

            if (b.GetLength(0) != b.GetLength(1))
            {
                throw new ArgumentException("The matrix must be square");
            }

            if (a.GetLength(0) != b.GetLength(0) || a.GetLength(1) != b.GetLength(1))
            {
                throw new ArgumentException("Matrices should be the same size");
            }

            // params
            this.n    = a.GetLength(0);
            this.ar   = new float[n];
            this.ai   = new float[n];
            this.beta = new float[n];
            this.Z    = Jagged.Zero(n, n);
            var  A    = Jagged.ToJagged(a);
            var  B    = Jagged.ToJagged(b);
            bool matz = true;
            int  ierr = 0;


            // reduces A to upper Hessenberg form and B to upper
            // triangular form using orthogonal transformations
            qzhes(n, A, B, matz, Z);

            // reduces the Hessenberg matrix A to quasi-triangular form
            // using orthogonal transformations while maintaining the
            // triangular form of the B matrix.
            qzit(n, A, B, Maths.Float(eps), matz, Z, ref ierr);

            // reduces the quasi-triangular matrix further, so that any
            // remaining 2-by-2 blocks correspond to pairs of complex
            // eigenvalues, and returns quantities whose ratios give the
            // generalized eigenvalues.
            qzval(n, A, B, ar, ai, beta, matz, Z);

            // computes the eigenvectors of the triangular problem and
            // transforms the results back to the original coordinate system.
            qzvec(n, A, B, ar, ai, beta, Z);
        }
示例#7
0
文件: UDL.cs 项目: asiryan/UMapx
        /// <summary>
        ///
        /// </summary>
        /// <param name="a"></param>
        private void udldecomp(float[,] a)
        {
            int i, j, k;
            int n = a.GetLength(0);

            this.upper = new float[n, n];
            this.diag  = new float[n];
            float[][] p = Jagged.ToJagged(a);
            float     alpha, beta, gamma;

            // Mathematics in science and engineering, v.128,
            // Factorization methods for discrete sequential estimation, Gerald J. Bierman.
            // UDU* factorization aglorithm.
            //
            for (j = n - 1; j >= 1; j--)
            {
                gamma   = p[j][j];
                diag[j] = gamma;
                alpha   = 1.0f / gamma;

                for (k = 0; k < j; k++)
                {
                    beta        = p[k][j];
                    upper[k, j] = alpha * beta;

                    for (i = 0; i <= k; i++)
                    {
                        p[i][k] -= beta * upper[i, j];
                    }
                }
            }
            diag[0] = p[0][0];

            // diagonal eyes:
            for (i = 0; i < n; i++)
            {
                upper[i, i] = 1.0f;
            }
            return;
        }
示例#8
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="A"></param>
        private void svdcmp(float[,] A)
        {
            this.Ur = Jagged.ToJagged(A);
            this.Sr = new float[m];
            this.Vr = Jagged.Zero(m, m);
            float[] rv1 = new float[m];

            int   flag, i, its, j, jj, k, l = 0, nm = 0;
            float anorm, c, f, g, h, e, scale, x, y, z;


            // householder reduction to bidiagonal form
            g = scale = anorm = 0.0f;

            for (i = 0; i < m; i++)
            {
                l      = i + 1;
                rv1[i] = scale * g;
                g      = e = scale = 0;

                if (i < n)
                {
                    for (k = i; k < n; k++)
                    {
                        scale += Math.Abs(Ur[k][i]);
                    }

                    if (scale != 0.0)
                    {
                        for (k = i; k < n; k++)
                        {
                            Ur[k][i] /= scale;
                            e        += Ur[k][i] * Ur[k][i];
                        }

                        f        = Ur[i][i];
                        g        = -Sign((float)Math.Sqrt(e), f);
                        h        = f * g - e;
                        Ur[i][i] = f - g;

                        if (i != m - 1)
                        {
                            for (j = l; j < m; j++)
                            {
                                for (e = 0.0f, k = i; k < n; k++)
                                {
                                    e += Ur[k][i] * Ur[k][j];
                                }

                                f = e / h;

                                for (k = i; k < n; k++)
                                {
                                    Ur[k][j] += f * Ur[k][i];
                                }
                            }
                        }

                        for (k = i; k < n; k++)
                        {
                            Ur[k][i] *= scale;
                        }
                    }
                }

                Sr[i] = scale * g;
                g     = e = scale = 0.0f;

                if ((i < n) && (i != m - 1))
                {
                    for (k = l; k < m; k++)
                    {
                        scale += Math.Abs(Ur[i][k]);
                    }

                    if (scale != 0.0)
                    {
                        for (k = l; k < m; k++)
                        {
                            Ur[i][k] /= scale;
                            e        += Ur[i][k] * Ur[i][k];
                        }

                        f        = Ur[i][l];
                        g        = -Sign((float)Math.Sqrt(e), f);
                        h        = f * g - e;
                        Ur[i][l] = f - g;

                        for (k = l; k < m; k++)
                        {
                            rv1[k] = Ur[i][k] / h;
                        }

                        if (i != n - 1)
                        {
                            for (j = l; j < n; j++)
                            {
                                for (e = 0.0f, k = l; k < m; k++)
                                {
                                    e += Ur[j][k] * Ur[i][k];
                                }
                                for (k = l; k < m; k++)
                                {
                                    Ur[j][k] += e * rv1[k];
                                }
                            }
                        }

                        for (k = l; k < m; k++)
                        {
                            Ur[i][k] *= scale;
                        }
                    }
                }
                anorm = Math.Max(anorm, (Math.Abs(Sr[i]) + Math.Abs(rv1[i])));
            }

            // accumulation of right-hand transformations
            for (i = m - 1; i >= 0; i--)
            {
                if (i < m - 1)
                {
                    if (g != 0.0)
                    {
                        for (j = l; j < m; j++)
                        {
                            Vr[j][i] = (Ur[i][j] / Ur[i][l]) / g;
                        }

                        for (j = l; j < m; j++)
                        {
                            for (e = 0, k = l; k < m; k++)
                            {
                                e += Ur[i][k] * Vr[k][j];
                            }
                            for (k = l; k < m; k++)
                            {
                                Vr[k][j] += e * Vr[k][i];
                            }
                        }
                    }
                    for (j = l; j < m; j++)
                    {
                        Vr[i][j] = Vr[j][i] = 0;
                    }
                }
                Vr[i][i] = 1;
                g        = rv1[i];
                l        = i;
            }

            // accumulation of left-hand transformations
            for (i = m - 1; i >= 0; i--)
            {
                l = i + 1;
                g = Sr[i];

                if (i < m - 1)
                {
                    for (j = l; j < m; j++)
                    {
                        Ur[i][j] = 0.0f;
                    }
                }

                if (g != 0)
                {
                    g = 1.0f / g;

                    if (i != m - 1)
                    {
                        for (j = l; j < m; j++)
                        {
                            for (e = 0, k = l; k < n; k++)
                            {
                                e += Ur[k][i] * Ur[k][j];
                            }

                            f = (e / Ur[i][i]) * g;

                            for (k = i; k < n; k++)
                            {
                                Ur[k][j] += f * Ur[k][i];
                            }
                        }
                    }

                    for (j = i; j < n; j++)
                    {
                        Ur[j][i] *= g;
                    }
                }
                else
                {
                    for (j = i; j < n; j++)
                    {
                        Ur[j][i] = 0;
                    }
                }
                ++Ur[i][i];
            }

            // diagonalization of the bidiagonal form: Loop over singular values
            // and over allowed iterations
            for (k = m - 1; k >= 0; k--)
            {
                for (its = 1; its <= iterations; its++)
                {
                    flag = 1;

                    for (l = k; l >= 0; l--)
                    {
                        // test for splitting
                        nm = l - 1;

                        if (Math.Abs(rv1[l]) + anorm == anorm)
                        {
                            flag = 0;
                            break;
                        }

                        if (Math.Abs(Sr[nm]) + anorm == anorm)
                        {
                            break;
                        }
                    }

                    if (flag != 0)
                    {
                        c = 0.0f;
                        e = 1.0f;
                        for (i = l; i <= k; i++)
                        {
                            f = e * rv1[i];

                            if (Math.Abs(f) + anorm != anorm)
                            {
                                g     = Sr[i];
                                h     = Maths.Hypotenuse(f, g);
                                Sr[i] = h;
                                h     = 1.0f / h;
                                c     = g * h;
                                e     = -f * h;

                                //for (j = 1; j <= m; j++)
                                for (j = 1; j < n; j++)
                                {
                                    y         = Ur[j][nm];
                                    z         = Ur[j][i];
                                    Ur[j][nm] = y * c + z * e;
                                    Ur[j][i]  = z * c - y * e;
                                }
                            }
                        }
                    }

                    z = Sr[k];

                    if (l == k)
                    {
                        // convergence
                        if (z < 0.0)
                        {
                            // singular value is made nonnegative
                            Sr[k] = -z;

                            for (j = 0; j < m; j++)
                            {
                                Vr[j][k] = -Vr[j][k];
                            }
                        }
                        break;
                    }

                    if (its == iterations)
                    {
                        throw new ApplicationException("No convergence in " + iterations.ToString() + " iterations of singular decomposition");
                    }

                    // shift from bottom 2-by-2 minor
                    x  = Sr[l];
                    nm = k - 1;
                    y  = Sr[nm];
                    g  = rv1[nm];
                    h  = rv1[k];
                    f  = ((y - z) * (y + z) + (g - h) * (g + h)) / (2.0f * h * y);
                    g  = Maths.Hypotenuse(f, 1.0f);
                    f  = ((x - z) * (x + z) + h * ((y / (f + Sign(g, f))) - h)) / x;

                    // next QR transformation
                    c = e = 1.0f;

                    for (j = l; j <= nm; j++)
                    {
                        i      = j + 1;
                        g      = rv1[i];
                        y      = Sr[i];
                        h      = e * g;
                        g      = c * g;
                        z      = Maths.Hypotenuse(f, h);
                        rv1[j] = z;
                        c      = f / z;
                        e      = h / z;
                        f      = x * c + g * e;
                        g      = g * c - x * e;
                        h      = y * e;
                        y     *= c;

                        for (jj = 0; jj < m; jj++)
                        {
                            x         = Vr[jj][j];
                            z         = Vr[jj][i];
                            Vr[jj][j] = x * c + z * e;
                            Vr[jj][i] = z * c - x * e;
                        }

                        z     = Maths.Hypotenuse(f, h);
                        Sr[j] = z;

                        if (z != 0)
                        {
                            z = 1.0f / z;
                            c = f * z;
                            e = h * z;
                        }

                        f = c * g + e * y;
                        x = c * y - e * g;

                        for (jj = 0; jj < n; jj++)
                        {
                            y         = Ur[jj][j];
                            z         = Ur[jj][i];
                            Ur[jj][j] = y * c + z * e;
                            Ur[jj][i] = z * c - y * e;
                        }
                    }

                    rv1[l] = 0.0f;
                    rv1[k] = f;
                    Sr[k]  = x;
                }
            }
        }
示例#9
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="a"></param>
        private void tred2(float[,] a)
        {
            int i, j, k;

            this.matrices = Jagged.ToJagged(a);

            // Symmetric Householder reduction to tridiagonal form.
            // This is derived from the Algol procedures tred2 by Bowdler, Martin, Reinsch, and Wilkinson,
            // Handbook for Auto. Comp., Vol.ii-Linear Algebra, and the corresponding Fortran subroutine in EISPACK.
            for (j = 0; j < n; j++)
            {
                Re[j] = matrices[n - 1][j];
            }

            float scale, h, f, g, hh;

            // Householder reduction to tridiagonal form.
            for (i = n - 1; i > 0; i--)
            {
                // Scale to avoid under/overflow.
                scale = 0;
                h     = 0;
                for (k = 0; k < i; k++)
                {
                    scale = scale + System.Math.Abs(Re[k]);
                }

                if (scale == 0)
                {
                    Im[i] = Re[i - 1];
                    for (j = 0; j < i; j++)
                    {
                        Re[j]          = matrices[i - 1][j];
                        matrices[i][j] = 0;
                        matrices[j][i] = 0;
                    }
                }
                else
                {
                    // Generate Householder Matrice.
                    for (k = 0; k < i; k++)
                    {
                        Re[k] /= scale;
                        h     += Re[k] * Re[k];
                    }

                    f = Re[i - 1];
                    g = (float)System.Math.Sqrt(h);
                    if (f > 0)
                    {
                        g = -g;
                    }

                    Im[i]     = scale * g;
                    h         = h - f * g;
                    Re[i - 1] = f - g;
                    for (j = 0; j < i; j++)
                    {
                        Im[j] = 0;
                    }

                    // Apply similarity transformation to remaining columns.
                    for (j = 0; j < i; j++)
                    {
                        f = Re[j];
                        matrices[j][i] = f;
                        g = Im[j] + matrices[j][j] * f;
                        for (k = j + 1; k <= i - 1; k++)
                        {
                            g     += matrices[k][j] * Re[k];
                            Im[k] += matrices[k][j] * f;
                        }
                        Im[j] = g;
                    }

                    f = 0;
                    for (j = 0; j < i; j++)
                    {
                        Im[j] /= h;
                        f     += Im[j] * Re[j];
                    }

                    hh = f / (h + h);
                    for (j = 0; j < i; j++)
                    {
                        Im[j] -= hh * Re[j];
                    }

                    for (j = 0; j < i; j++)
                    {
                        f = Re[j];
                        g = Im[j];
                        for (k = j; k <= i - 1; k++)
                        {
                            matrices[k][j] -= (f * Im[k] + g * Re[k]);
                        }

                        Re[j]          = matrices[i - 1][j];
                        matrices[i][j] = 0;
                    }
                }
                Re[i] = h;
            }

            // Accumulate transformations.
            for (i = 0; i < n - 1; i++)
            {
                matrices[n - 1][i] = matrices[i][i];
                matrices[i][i]     = 1;
                h = Re[i + 1];
                if (h != 0)
                {
                    for (k = 0; k <= i; k++)
                    {
                        Re[k] = matrices[k][i + 1] / h;
                    }

                    for (j = 0; j <= i; j++)
                    {
                        g = 0;
                        for (k = 0; k <= i; k++)
                        {
                            g += matrices[k][i + 1] * matrices[k][j];
                        }
                        for (k = 0; k <= i; k++)
                        {
                            matrices[k][j] -= g * Re[k];
                        }
                    }
                }

                for (k = 0; k <= i; k++)
                {
                    matrices[k][i + 1] = 0;
                }
            }

            for (j = 0; j < n; j++)
            {
                Re[j] = matrices[n - 1][j];
                matrices[n - 1][j] = 0;
            }

            matrices[n - 1][n - 1] = 1;
            Im[0] = 0;
            return;
        }
示例#10
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="A"></param>
        private void orthes(float[,] A)
        {
            // Properties
            int n = A.GetLength(0);

            this.matrices   = Jagged.Zero(n, n);
            this.hessenberg = Jagged.ToJagged(A);
            float[] orthogonal = new float[n];

            // Nonsymmetric reduction to Hessenberg form.
            // This is derived from the Algol procedures orthes and ortran, by Martin and Wilkinson,
            // Handbook for Auto. Comp., Vol.ii-Linear Algebra, and the corresponding Fortran subroutines in EISPACK.
            int   low = 0;
            int   high = n - 1;
            int   m, i, j;
            float scale, h, g, f;

            for (m = low + 1; m <= high - 1; m++)
            {
                // Scale column.

                scale = 0;
                for (i = m; i <= high; i++)
                {
                    scale = scale + System.Math.Abs(hessenberg[i][m - 1]);
                }

                if (scale != 0)
                {
                    // Compute Householder transformation.
                    h = 0;
                    for (i = high; i >= m; i--)
                    {
                        orthogonal[i] = hessenberg[i][m - 1] / scale;
                        h            += orthogonal[i] * orthogonal[i];
                    }

                    g = (float)System.Math.Sqrt(h);
                    if (orthogonal[m] > 0)
                    {
                        g = -g;
                    }

                    h             = h - orthogonal[m] * g;
                    orthogonal[m] = orthogonal[m] - g;

                    // Apply Householder similarity transformation
                    // H = (I - u * u' / h) * H * (I - u * u') / h)
                    for (j = m; j < n; j++)
                    {
                        f = 0;
                        for (i = high; i >= m; i--)
                        {
                            f += orthogonal[i] * hessenberg[i][j];
                        }

                        f = f / h;
                        for (i = m; i <= high; i++)
                        {
                            hessenberg[i][j] -= f * orthogonal[i];
                        }
                    }

                    for (i = 0; i <= high; i++)
                    {
                        f = 0;
                        for (j = high; j >= m; j--)
                        {
                            f += orthogonal[j] * hessenberg[i][j];
                        }

                        f = f / h;
                        for (j = m; j <= high; j++)
                        {
                            hessenberg[i][j] -= f * orthogonal[j];
                        }
                    }

                    orthogonal[m]        = scale * orthogonal[m];
                    hessenberg[m][m - 1] = scale * g;
                }
            }

            // Accumulate transformations (Algol's ortran).
            for (i = 0; i < n; i++)
            {
                for (j = 0; j < n; j++)
                {
                    matrices[i][j] = (i == j ? 1 : 0);
                }
            }

            for (m = high - 1; m >= low + 1; m--)
            {
                if (hessenberg[m][m - 1] != 0)
                {
                    for (i = m + 1; i <= high; i++)
                    {
                        orthogonal[i] = hessenberg[i][m - 1];
                    }

                    for (j = m; j <= high; j++)
                    {
                        g = 0;
                        for (i = m; i <= high; i++)
                        {
                            g += orthogonal[i] * matrices[i][j];
                        }

                        // float division avoids possible underflow.
                        g = (g / orthogonal[m]) / hessenberg[m][m - 1];
                        for (i = m; i <= high; i++)
                        {
                            matrices[i][j] += g * orthogonal[i];
                        }
                    }
                }
            }

            // final reduction:
            if (n > 2)
            {
                for (i = 0; i < n - 2; i++)
                {
                    for (j = i + 2; j < n; j++)
                    {
                        hessenberg[j][i] = 0;
                    }
                }
            }
        }