Текст подпрограммы и версий aes4r_c.zip , aes4d_c.zip |
Тексты тестовых примеров taes4r_c.zip , taes4d_c.zip |
Вычисление нескольких крайних собственных значений и соответствующих собственных векторов вещественной симметричной разреженной или имеющей регулярную структуру матрицы методом Ланцоша с выборочной ортогонализацией.
Метод Ланцоша для заданной симметричной матрицы А порядка N и начального вектора v ∈ EN, v ≠ 0, строит последовательность векторов v1, v2,..., vj и последовательность трехдиагональных матриц T1, T2,..., Tj по следующим формулам
(1) v1 = v / (vTv)1/2 , β1 = 0 , ui = Avi - βivi -1 , αi = uiTvi , T1 = α1 , i = 1 , | | 0 | | | . | Ti = | Ti-1 | 0 | , i > 1 , | ______ | βi | | 0 ... 0 βi αi | wi +1 = ui - αivi , βi +1 = (wTi +1wi +1)1/2 , vi +1 = wi +1 / βi +1 , i = 1,..., j
Метод Ланцоша может быть рассмотрен как реализация для спектральной задачи Az = λz метода проекций Ритца - Галеркина на последовательность подпространств Крылова
K( j ) = span { v1, Av1,... , Aj -1 v1 } , j = 1,... , N ,
при этом числа Ритца (собственные значения сужения оператора PjA на K ( j ), где Pj - ортогональный проект на K ( j ) ) совпадают с собственными значениями θi ( j ), i = 1,..., j, матрицы Tj, получаемой на j - ом шаге метода Ланцоша, а векторы Ритца равны Vjsi ( j ), где si ( j ) - соответствующие θi ( j ) собственные векторы Tj, а Vj - матрица, столбцами которой являются векторы Ланцоша v1, v2,..., vj.
Полезной особенностью метода Ланцоша является то, что часто уже при j ~ 2√N крайние пары Ритца ( θi ( j ), Vj sj ( j ) ) оказываются хорошими приближениями к искомым крайним собственным парам матрицы А.
Метод Ланцоша использует исходную матрицу только в операциях умножения матрицы на вектор, поэтому информацию о матрице удобно задавать в виде подпрограммы умножения матрицы на вектор, в которой пользователь может максимально учесть специфику матрицы.
В подпрограмме aes4r_c используется метод Ланцоша с выборочной ортогонализацией - устойчивая к влиянию ошибок округления модификация простого метода Ланцоша, отличающаяся от него тем, что на некоторых шагах процесса (1) проводится ортогонализация wj + 1 относительно некоторых векторов Ритца.
В подпрограмме aes4r_c предполагается, что || A || 2 ~ 1, где || A || 2 - спектральная норма матрицы. Гарантированной точностью по невязке для вычисляемых собственных векторов является величина k || A ||2√ε, где ε - относительная машинная точность, k ~ 1, но часто возможно получение лучшей точности.
Выход из подпрограммы происходит, когда все требуемые собственные векторы будут вычислены с заданной точностью по невязке или если продолжение процесса (1) окажется невозможным или бесполезным.
Б.Парлетт. Симметричная проблема собственных значений. Численные методы. М.: Мир, 1983.
int aes4r_c (integer *n, integer *kl, integer *kr, real *ff, real *eps, integer *m, real *vj, integer *k, integer *l, real *r, real *r1, real *r2, real *ev, real *er, real *v, real *y, integer *ip)
Параметры
n - | порядок исходной матрицы, (тип: целый); |
kl, kr - | задаваемые соответственно число наименьших и число наибольших собственных значений и соответствующих собственных векторов, которые требуется вычислить (тип: целый); |
ff - |
имя подпрограммы вычисления
w : = ( A - sI ) v - w;
первый оператор подпрограммы должен иметь вид: int ff (float *v, float *w, int *n, float *s) Здесь: |
v - | заданный вещественный вектор длины n; |
w - | вещественный вектор длины n, содержащий на входе в подпрограмму заданный вектор, а на выходе из программы - вычисленный вектор ( A - sI ) v - w; |
n - | порядок матрицы a (тип: целый); |
s - | простая переменная (тип: вещественный); |
eps - | заданная требуемая точность по невязке для вычисляемых собственных значений и соответствующих собственных векторов (тип: вещественный); |
m - | целая переменная, содержащая на входе в подпрограмму задаваемое максимальное число шагов алгоритма, а на выходе из подпрограммы - число выполненных шагов; |
vj - | вещественный вектор длины n, содержащий на входе в подпрограмму заданный начальный вектор; если vj = 0, то в качестве начального будет взят вектор v1 = (1., 1., ... , 1.) t; |
k - | заданное максимальное число вычисляемых собственых значений и соответствующих собственных векторов матриц tj, k ≥ kl + kr + 2 (тип: целый); |
l - | длина рабочего вектора r (тип: целый), l ≥ m (k + 9) + 8k; |
r - | вещественный рабочий вектор длины l, использемый как рабочий; |
r1, r2 - | вещественные рабочие вектора длины n, используемые как рабочие; |
ev - | вещественный вектор длины (kl + kr), в первых kl компонентах которого на выходе из подпрограммы содержатся в порядке неубывания вычисленные kl наименьших собственных значений, а в последних kr компонентах в порядке невозрастания - kr наибольших собственных значений; |
er - | вещественный вектор длины (kl + kr), содержащий невязки er ( i ) = || Ayi - er ( i ) yi ||, где yi = yi - вычисленный нормированный собственный вектор матрицы A соответствующий собственному значению er ( i ), 1 ≤ i ≤ kl + kr; |
v - | вещественный двумерный массив размерности n * mmax, в столбцах которого в ходе работы подпрограммы располагаются вычисленные векторы Ланцоша v1, v2, ..., vmmax; |
y - | вещественный двумерный массив размерности n * k, в i - ом, 1 ≤ i ≤ kl + kr, столбце которого на выходе из подпрограммы содержится вычисленный нормированный собственный вектор, соответствующий выходному значению ev ( i ); |
ip - | простая целочисленная переменная, содержащая на входе в подпрограмму признак рещаемой задачи, при этом: |
ip = 1 - | если требуется выполнить ровно m шагов алгоритма; |
ip = 0 - | если допустим выход из программы при j < m, j - число выполненных шагов; в этом случае вычисления будут прекращены после того, как на некотором шаге j будет получено заданное число приближений к собственным парам матрицы A с заданной точностью; |
на выходе из подпрограммы ip содержит признак выхода, причем: |
ip = -1 - | если заданное значение параметра l не удовлетворяет неравенству l ≥ m * (9 + k) + 8k; |
ip = -2 - | если заданное значение параметра k не удовлетворяет неравенству k ≥ kl + kr + 2; |
ip = -3 - | если обе описанные выше ошибки имели место; |
ip = 0 - | если требуемые собственные значения и соответствующие собственные векторы вычислены с заданной точностью; |
ip = 1 - | если выполнено заданное число m шагов алгоритма, а заданная точность еще не достигнута; |
ip = 2 - | если на некотором шаге j, j < m, алгоритма потребовалось вычислить более k собственных пар матрицы Tj; в этом случае для продолжения процесса не хватает памяти; |
ip = 3 - | если заданная точность не может быть достигнута; |
ip = 4 - | если получено слишком малое значение βj + 1; |
ip = 5 - | если резко возрастает объем работ по проведению выборочной ортогонализации. |
Версии
aes4d_c - | вычисление нескольких крайних собственных значений и соответствующих собственных векторов вещественной симметричной разреженной или имеющей регулярную структуру матрицы, заданной с двойной точностью, методом Ланцоша с выборочной ортогонализацией. |
Вызываемые подпрограммы
avz6r_c - | упорядочивание вектора по возрастанию его компонент с запоминанием произведенных перестановок; |
avz2r_c - | нахождение максимальной по модулю компоненты и ее индекса из всего вектора или из заданного подмножества компонент этого вектора; |
av02r_c - | вычисление евклидовой нормы вектора; |
av04a_c - | вычисление скалярного произведения в режиме накопления; |
am05r_c - | вычисление произведения матрицы на вектор. |
Замечания по использованию
1. | Наименование подпрограммы, соответствующей формальному параметру ff, должно быть указано в операторе extern в программе пользователя, вызывающей aes4r_c; | |
2. | Подпpогpамма ff должна сохранять вектор v; | |
3. | Если начальный вектор был выбран неудачно (имел нулевые составляющие вдоль направлений некоторых из искомых собственных векторов), то возможно, что вычисленные векторы не обязательно будут приближениями именно к тем собственным векторам, которые соответствуют первым kl и последним kr собственным значениям. Поэтому, вообще говоря, для проверки необходимо обратиться к aes4r_c с начальными векторами. Особенно это необходимо, если на выходе из программы ip = 4 или мало выходное значение параметра m; | |
4. | Неудачный выбор начального вектора может привести к выходу из подпрограммы на шаге с номером j < kl + kr по признаку ip = 4. В этом случае будут вычислены все j собственных пар, причем все j вычисленных собственных значений будут расположены в массиве ev в порядке неубывания. Понятно, что в этом случае повторное обращение к подпрограмме совершенно необходимо; | |
5. | Если на выходе из подпрограммы ip < 0, то никакой информации об искомых собственных парах получено не будет; если же ip > 0, то на выходе из подпрограммы будут получены kl первых и kr последних пар Ритца, вычисленных на шаге прерывания (номер этого шага - выходное значение m), т.е. будут получены приближения к искомым собственным парам, хотя их точность и не является удовлетворительной. Эти приближения могут быть использованы для построения нового начального вектора и повторного обращения к aes4r_c; | |
6. | Если на выходе из подпрограммы ip = 2, то необходимо увеличить значение параметра k и соответственно l. Рекомендации для выбора значения k, которые были бы удовлетворительными для любых матриц, не могут быть даны, т.к. требуемое значение k зависит от спектра исходной матрицы и равно числу пар Ритца, невязки которых станут величинами ~ || A || √ε к тому моменту, когда невязки для заданного числа крайних пар Ритца станут меньше eps; | |
7. | В подпpогpамме aes4d_c паpаметpы eps, vj, r, r1, r2, ev, er, v, y имеют тип double; | |
8. | Подпpогpаммы aes4r1_c (aes4d1_c), aes0r0_c (aes0d0_c), av04r1_c (av04d1_c) используются в качестве рабочих; | |
9. | В подпpогpамме ff паpаметpы v, w, s должны иметь тип double. |
int main(void) { /* Initialized data */ static float vj[6] = { 1.f,1.f,1.f,1.f,1.f,1.f }; /* Local variables */ extern int aes4r_c(int *, int *, int *, U_fp, float *, int *, float *, int *, int *, float *, float *, float *, float *, float *, float *, float *, int *); static int i__, m; static float r__[97], v[30] /* was [6][5] */, y[12] /* was [6][2] */; extern int f0_c(); static float r1[6], r2[6], er[2]; static int ip; static float ev[2]; #define y_ref(a_1,a_2) y[(a_2)*6 + a_1 - 7] m = 5; ip = 0; aes4r_c(&c__6, &c__0, &c__2, (U_fp)f0_c, &c_b4, &m, vj, &c__4, &c__97, r__, r1, r2, ev, er, v, y, &ip); printf("\n %5i %5i \n", ip, m); if (ip < 0) { goto l55; } printf("\n %17.7e %17.7e \n", ev[0], ev[1]); for (i__ = 1; i__ <= 6; ++i__) { printf("\n %17.7e %17.7e \n", y_ref(i__,1), y_ref(i__,2)); } printf("\n %17.7e %17.7e \n", er[0], er[1]); l55: return 0; } /* main */ int f0_c(float *x, float *z__, int *n, float *s) { /* Initialized data */ static float rab[6] = { 0.f,1e-5f,2e-5f,3e-5f,.1f,1.f }; /* System generated locals */ int i__1; /* Local variables */ static int i__; /* Parameter adjustments */ --z__; --x; /* Function Body */ i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { z__[i__] = (rab[i__ - 1] - *s) * x[i__] - z__[i__]; /* l10: */ } return 0; } /* f0_c */ Результаты: ip = 0 , m = 3 coбcтвeнныe значения: ev(1) = 1. , ev(2) = 0.1 coбcтвeнныe векторы: | 5.e - 7 2.e - 4 | | - 6.e - 7 5.e - 5 | | - 2.e - 6 - 6.e - 5 | y_ref = | - 3.e - 6 - 2.e - 4 | | 1.e - 6 - 1. | | 1. 3.e - 6 | нeвязkи: er(1) = 4.e - 6 , er(2) = 2.e - 5