public void QR_Dec_Givens(Matrix A) { R = new UpperTriangularMatrix(A.M, A.N); Q = new LowerTriangularMatrix(A.M, A.N); double help1, help2; bool Flag_Diag = false; // заполним Q как единичную матрицу for (int i = 0; i < Q.M; i++) { Q.Elem[i][i] = 1; } // введем синус\косинус\тангенс double c = 1, s = 0, t = 0; for (int j = 0; j < A.N - 1; j++) { // если элемент нулевой if (Math.Abs(A.Elem[j][j]) < CONST.EPS) { Flag_Diag = true; c = 1; s = 0; t = 0; } // для каждой строки ниже диагонали for (int i = j + 1; i < A.M; i++) { // если ненулевой элемент if (Math.Abs(A.Elem[i][j]) > CONST.EPS) { if (!Flag_Diag) { t = A.Elem[i][j] / A.Elem[j][j]; c = 1.0 / (Math.Sqrt(1 + t * t)); s = t * c; } for (int k = j; k < A.N; k++) { help1 = c * A.Elem[j][k] + s * A.Elem[i][k]; help2 = c * A.Elem[i][k] - s * A.Elem[j][k]; R.Elem[j][k] = help1; R.Elem[i][k] = help2; // и в А A.Elem[j][k] = help1; A.Elem[i][k] = help2; } for (int k = 0; k < Q.M; k++) { help1 = c * Q.Elem[k][j] + s * Q.Elem[k][i]; help2 = c * Q.Elem[k][i] - s * Q.Elem[k][j]; Q.Elem[k][j] = help1; Q.Elem[k][i] = help2; } } } } }
//классический метод QR-разложения public void QR_Decomposition_Classic_Gram_Schmidt_Process(Matrix A) { R = new UpperTriangularMatrix(A.N, A.N); Q = new LowerTriangularMatrix(A.M, A.M); var q_ = new Vector(A.M); for (int j = 0; j < A.N; j++) { //формирование верхнетреугольной матрицы R for (int i = 0; i < j; i++) { for (int k = 0; k < A.M; k++) { R.Elem[i][j] += A.Elem[k][j] * Q.Elem[k][i]; } } //копирование j-ой строки матрицы A в вектор q_ q_.Copy_Column(A, j); for (int i = 0; i < j; i++) { for (int k = 0; k < q_.N; k++) { q_.Elem[k] -= Q.Elem[k][i] * R.Elem[i][j]; } } //запись значения нормы вектора q_ в Rj,j элемент матрицы R R.Elem[j][j] = q_.Norma(); if (R.Elem[j][j] < CONST.EPS) { return; } //формирование унитарной матрицы Q for (int i = 0; i < A.M; i++) { Q.Elem[i][j] = q_.Elem[i] / R.Elem[j][j]; } } }