//реализация алгоритма поиска собственных знаечний: QR - итерации public List <double> Find_Eigenvalues_QR_Iterations(Matrix A, QR_Decomposition.QR_Algorithm Method) { //список собственных значений var EigenValues = new List <double>(); int iter = 0; //итерационный процесс while (A.M != 1) { //обновление спсика собственных значений for (int i = A.M - 1; i > 0; i--) { //если элемент A[i][i-1] == 0, A[i][i] - собственное значение if (Math.Abs(A.Elem[i][i - 1]) < 1e-6) { EigenValues.Add(A.Elem[i][i - 1]); //исключаем i-ые строку и столбец Delete_Row_Column(A, i); i = A.M; } } if (A.M == 1) { break; } //прямой сдвиг double shift = Rayleigh_Shift(A); Shift(A, -shift); //QR-разложение var QR = new QR_Decomposition(A, Method); //новая матрица А A = QR.R * QR.Q; //обратный сдвиг Shift(A, shift); } //дополняем список последним оставшимся собственным значением //EigenValues.Add(A.Elem[0][0]); //сортируем по возрастанию и формируем результат EigenValues.Sort((double X, double Y) => { if (X > Y) { return(0); } else { return(1); } }); return(EigenValues); }
//число обусловленности в матричной норме "бесконечность" public double Cond_Norm1() { //проверка на "квадратность" матрицы if (M != N) { throw new Exception("Cond(A): M != N ..."); } //решатель СЛАУ: A^t = QR и решаем системы A^t * A^(-t) = E var QR_Solver = new QR_Decomposition(this, QR_Decomposition.QR_Algorithm.Householder); //проверка на невырожденность if (Math.Abs(QR_Solver.R.Elem[M - 1][M - 1]) < CONST.EPS) { throw new Exception("Cond(A): detA = 0 ..."); } //число потоков int Number_Threads = Environment.ProcessorCount; //семафоры для потоков (по умолчанию false): сигнализируют, что i-ый поток завершился var Semaphores = new bool[Number_Threads]; //максимальные нормы столбцов (вычисляются на каждом i-ом потоке) var Norm_Column_A = new double[Number_Threads]; var Norm_Column_A1 = new double[Number_Threads]; //безымянная функция для решения СЛАУ -> столбцы обратной матрицы //Number - номер потока var Start_Solver = new Thread_Solver((Number) => { //столбец обратной матрицы var A1 = new Vector(M); double S1, S2; //первый и последний обрабатываемый столбец для потока int Begin = N / Number_Threads * Number; int End = Begin + N / Number_Threads; //в последний поток добавим остаток if (Number + 1 == Number_Threads) { End += N % Number_Threads; } //решаем системы A * A^(-1) = E for (int i = Begin; i < End; i++) { A1.Elem[i] = 1.0; A1 = QR_Solver.Start_Solver(A1); S1 = 0; S2 = 0; for (int j = 0; j < M; j++) { S1 += Math.Abs(Elem[i][j]); S2 += Math.Abs(A1.Elem[j]); A1.Elem[j] = 0.0; } if (Norm_Column_A [Number] < S1) { Norm_Column_A [Number] = S1; } if (Norm_Column_A1[Number] < S2) { Norm_Column_A1[Number] = S2; } } //сигнал о завершении потока Semaphores[Number] = true; }); //отцовский поток запускает дочерние for (int I = 0; I < Number_Threads - 1; I++) { int Number = Number_Threads - I - 1; ThreadPool.QueueUserWorkItem((Par) => Start_Solver(Number)); } //отцовский поток забирает первую порцию столбцов Start_Solver(0); //ожидание отцовским потоком завершения работы дочерних while (Array.IndexOf <bool>(Semaphores, false) != -1) { ; } //поиск наибольшей нормы for (int i = 1; i < Number_Threads; i++) { if (Norm_Column_A [0] < Norm_Column_A [i]) { Norm_Column_A [0] = Norm_Column_A [i]; } if (Norm_Column_A1[0] < Norm_Column_A1[i]) { Norm_Column_A1[0] = Norm_Column_A1[i]; } } return(Norm_Column_A[0] * Norm_Column_A1[0]); }
public List <double> Eigenvalues(QR_Decomposition.QR_Algorithm Method) { if (N != M) { throw new Exception("Eigenvalues: invalid size of matrix..."); } //создадим копию данной матрицы, чтобы не изменять её Matrix T = new Matrix(N, N); T.Copy(this); List <double> RES = new List <double>(); //приведём матрицу к верхней форме Хессенберга T.Hessenberg_Matrix(); int t = 1; //QR-итерации while (T.M != 1) { Console.WriteLine("Iteration {0} ", t); T.Console_Write_Matrix(); Console.WriteLine(" "); for (int i = T.M - 1; i > 0; i--) { //если элемент А[i][i-1] == 0, то A[i][i] - собственное значение if (Math.Abs(T.Elem[i][i - 1]) < 1e-6) { RES.Add(T.Elem[i][i]); //исключаем i-ые строку и столбец T.Delete_Row_Column(i); i = T.M; } } if (T.M == 1) { break; } //прямой сдвиг double shift = Eigenvalue_Problem.Rayleigh_Shift(T); Eigenvalue_Problem.Shift(T, -shift); var QR = new QR_Decomposition(T, Method); T = QR.R * QR.Q; Eigenvalue_Problem.Shift(T, shift); //аварийное завершение цикла t++; if (t == 100) { break; } } //дополняем список последним оставшимся собственным значением RES.Add(T.Elem[0][0]); //сортируем по возрастанию и формируем результат RES.Sort((double X, double Y) => { if (X > Y) { return(0); } return(1); }); return(RES); }