/// <summary>
        /// реализаци¤ QR-декомпозиции
        /// </summary>
        /// <param name="A - исходна¤ матрица"></param>
        /// <param name="Method - метод QR-декомпозиции"></param>
        public QR_Decomposition(Matrix A, QR_Algorithm Method)
        {
            R = new Matrix(A.M, A.N);
            Q = new Matrix(A.M, A.M);

            switch (Method)
            {
            case QR_Algorithm.Classic_Gram_Schmidt:
            {
                Gram_Schmidt_Procedure.Classic_Gram_Schmidt_Procedure(A, Q, R);
                break;
            }

            case QR_Algorithm.Modified_Gram_Schmidt:
            {
                Gram_Schmidt_Procedure.Modified_Gram_Schmidt_Procedure(A, Q, R);
                break;
            }

            case QR_Algorithm.Givens:
            {
                //начальна¤ инициализаци¤ матрицы ортогональных преобразований
                for (int i = 0; i < A.M; i++)
                {
                    Q.Elem[i][i] = 1.0;
                }
                Givens_Transformation.Givens_Orthogonalization(A, Q, R);
                break;
            }

            case QR_Algorithm.Householder:
            {
                //начальна¤ инициализаци¤ матрицы ортогональных преобразований
                for (int i = 0; i < A.M; i++)
                {
                    Q.Elem[i][i] = 1.0;
                }
                Householder_Transformation.Householder_Orthogonalization(A, Q, R);
                break;
            }
            }
        }
Esempio n. 2
0
        //---------------------------------------------------------------------------------------------

        /// <summary>
        /// двухэтапный SVD-алгоритм
        /// </summary>
        /// <param name="A - матрица для SVD"></param>
        public void Start_SVD(Matrix A)
        {
            //наименьшее измерение
            int Min_Size = Math.Min(A.M, A.N);

            //размеры нижней и верхней внешних диагоналей
            int Up_Size = Min_Size - 1, Down_Size = Min_Size - 1;

            //инициализация матрицы левых сингулярных векторов 
            U = new Matrix(A.M, A.M);
            
            //матрица сингулярных чисел
            Sigma = new Matrix(A.M, A.N);

            //инициализация матрицы правых сингулярных векторов 
            V = new Matrix(A.N, A.N);

            //инициализация матриц для SVD
            for (int i = 0; i < A.M; i++)
            {
                U.Elem[i][i] = 1.0;
                for (int j = 0; j < A.N; j++) Sigma.Elem[i][j] = A.Elem[i][j];
            }
            for (int i = 0; i < A.N; i++) V.Elem[i][i] = 1.0;

            //**************** этап I: бидиагонализация *************************
            
            for (int i = 0; i < Min_Size - 1; i++)
            {
                Householder_Transformation.Column_Transformation(Sigma, U, i, i);
                Householder_Transformation.Row_Transformation(Sigma, V, i, i + 1);
            }

            //ситуация M > N - строк больше => дополнительное умножение слева 
            if (A.M > A.N)
            {
                Householder_Transformation.Column_Transformation(Sigma, U, A.N - 1, A.N - 1);
                //нижняя побочная диагональ длиннее на 1
                Down_Size += 1;
            }

            //ситуация M < N - столбцов больше => дополнительное умножение справа
            if (A.M < A.N)
            {
                Householder_Transformation.Row_Transformation(Sigma, V, A.M - 1, A.M);
                //верхняя побочная диагональ длиннее на 1
                Up_Size += 1;
            }

            Sigma.Console_Write_Matrix();

            //**************** этап II: преследование ************
            //********* приведение к диагональному виду **********

            //для хранения изменяющихся элементов верхней диагонали
            var Up = new double[Up_Size];
            var Down = new double[Down_Size];
            //число неизменившихся элементов над главной диагональю
            int CountUpElements;

            //процедура преследования
            do
            {
                CountUpElements = 0;

                //обнуление верхней диагонали
                for (int i = 0; i < Up_Size; i++)
                {
                    if (Math.Abs(Up[i] - Sigma.Elem[i][i + 1]) > CONST.EPS)
                    {
                        Up[i] = Sigma.Elem[i][i + 1];
                        Givens_Transformation.Row_Transformation(Sigma, V, i, i);
                    }
                    else
                        CountUpElements++;
                }

                //обнуление нижней диагонали
                for (int i = 0; i < Down_Size; i++)
                {
                    if (Math.Abs(Down[i] - Sigma.Elem[i + 1][i]) > CONST.EPS)
                    {
                        Down[i] = Sigma.Elem[i + 1][i];
                        Givens_Transformation.Column_Transformation(Sigma, U, i, i);
                    }
                }
            }
            while (CountUpElements != Up_Size);

            //убираем отрицательные сингулярные числа
            Check_Singular_Values();
            //сортируем по возрастанию сингулярные числа
            Sort_Singular_Values();

            RES = new Matrix(U.M, V.M);
            RES = U * Sigma * V.Transpose_Matrix();

        }