/// <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; } } }
//--------------------------------------------------------------------------------------------- /// <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(); }