//реализация алгоритма поиска собственных знаечний: 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);
        }
示例#2
0
        //число обусловленности в матричной норме "бесконечность"
        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]);
        }
示例#3
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);
        }