- •§ 2. Решение нелинейных алгебраических уравнений с одной переменной
- •§2. Решение нелинейных алгебраических уравнений с одной переменной
- •2.1. Задача отделения корней. Уточнение корней методом половинного деления (метод дихотомии)
- •Методом хорд (секущих)
- •Методом касательных (Ньютона)
- •Методом итераций
- •Методом парабол
- •2.7. Методы ускорения сходимости
Методом парабол
Если в методе Ньютона (1.19) вместо производной вычислять разность первого порядка, то это можно рассматривать как замену функции F(х) интерполяционным многочленом первой степени, построенным по узламхn, хn-1. Но по трем последним итерациям можно построить интерполяционный многочлен второй степени, т.е. заменить график функцииF(х) параболой. Если воспользуемся вторым интерполяционным многочленом Ньютона, то приравняв его к нулю, получим квадратное уравнение:
аz2 + bz + с = 0,
где z = х - хn; а = F(хn, хn-1, хn-2); b = а(х - хn)+ F(хn, хn-1); с= F(х0).
Тогда, решив уравнение, выбирают меньший по модулю корень, который будет определять новое приближение: х n+1= хn + z.
Очевидно, что для начала расчетов надо определить первые три приближения х0 , х2 и х3. Обычнозадают любые три числа из отрезка, на котором ищется корень, но можно определить эти значения и иначе.
Метод парабол относится к трехшаговым методам. По сравнению с ранее изученными он сходится гораздо медленнее, но имеет следующее достоинство: даже если все предыдущие приближения действительны, этот метод может привести к комплексным числам. Во всех же остальных методах для сходимости к комплексному корню требуется задание комплексного начального приближения. Кроме того, метод парабол исключительно эффективен для нахождения всех корней многочлена высокой степени. Интересно заметить, что если F(х)- некоторый многочлен высокой степени, то, хотя сходимость метода не доказана [Касаткин, 1978] при произвольном начальном приближении, на практике итерациивсегдасходятся к какому-либо корню. По теореме Горнера для алгебраического многочлена частноеF(х)/(х - хn) будет тоже многочленом, но меньшейстепени. Поэтому, последовательно удаляянайденные корни, можно найти все корни многочлена.
Один из лучших имеющихся машинных алгоритмов для нахождения действительного нуля функции сочетает в себе безотказность метода бисекции с асимптотической скоростью метода парабол в случае гладких функций. Он называется zeroin и был изобретен в1960-х гг. в Математическом центре Амстердама Ван Вейнгарденом, Деккером и др. Описание алгоритма и его анализ даны в публикации Уилкинсона (1967, с. 8-12). Сам алгоритм впервые был опубликован в 1969 г. Деккером, а в 1973 г. улучшен Брентом. Реализация программы на языкеFORTRAN была предложена Форсайтом в 1980 г. по алгоритму Деккера в версии Брента. Здесь же предлагается реализация алгоритма на языкеPASCAL, выполненная авторами пособия.
Подрограмма оформлена как процедура-функция zeroin.Все названия переменных по сравнению с фортранной версией сохранены. Обращение к процедуре-функции имеет простой вид:
zz := zeroin (a, b, tol).
Здесь аиb(типreal) - точки интервала, на котором ищется нуль,tol(типreal) - граница погрешности вычисления результата. ПроцедураZeroin обращается также к процедуре-функцииfunc(x) (типreal),которая возвращает значение функции в заданной точке. Без проверки в Zeroinпредполагается, чтоfunc(a) иfunc(b) имеют разные знаки.
В процедуре Zeroinвыполняется итерационный процесс, в котором на каждом шаге присутствуют три абсциссыa, bиc.Обычно абcциссаa- предыдущее приближение (хn-1);b- последнее и наилучшее приближениехn;c- предыдущее, но еще более раннее приближение, причем sign(func(b) ) = sign(func(c) ). Таким образом,bисограничивают нуль. При этом |func(b)|< |func(c)|. Если |b - c| уменьшилось настолько, что выполняется условие
|b-c| <tol+ 4.0× eps × abs(b),
то bвыдается как найденное значение процедуры-функцииzeroin.Кроме параметраtоlв проверке сходимости участвует еще один параметр -ерs, "машинный нуль", чтобы подстраховаться на случай, еслиtol задано слишком маленьким, например равным нулю.
На каждой очередной итерации в zeroinвыбирается очередное приближение к корню из двух - один получен алгоритмом бисекции, а другой - интерполяцией. Еслиa, bиcразличны, то используется квадратичная интерполяция (метод парабол), если нет, то метод секущих (линейная интерполяция). Если полученноеxn+1находится в "разумных" пределах, то выбирают его, в противном случае выбирают точку бисекции. Определение "разумности" означает, чтоxn+1О [b, c], т.е. лежит внутри интервала и не совпадает с его концами. Таким образом, длина интервала гарантированно убывает с каждой итерацией, а если функция еще к тому же ведет себя хорошо, то и достаточно быстро. Более подробно об алгоритме, программе и описании метода можно посмотреть в книге Брента (1973).
Еще несколько важных замечаний по поводу алгоритма. Для того чтобы точка бисекции всегда лежала внутри расчетного интервала и желаемая величина получалась как малая поправка к найденному приближению, ее вычисляют по формуле xm :=b + 0.5*(c -b).
Большое вниманиев алгоритме уделяется проблеме машинных нулей.Это выражаетсяв необычнойпроверке знаковfunc(b) иfunc(c) (см. соответствующие подпрограммы).
Итоговая точка, получаемая алгоритмом, записывается в виде b + p/q,но деление не выполняется до тех пор, пока оно не станет безопасным и действительно необходимым, так как если будет выбрана точка по методу бисекций, то деление вообще не нужно.
Версия алгоритма Брента, во-первых, всегда сходится, даже при плавающей арифметике. Во-вторых, количество итераций не может стать больше числа
,
где tol1 := 0.5*tol + 2.0*eps*abs(B). В-третьих, нульr, получаемый алгоритмом, таков, чтоfuncгарантированно меняет знак в определенном интервале, приблизительно совпадающим с
[R - exp(tol*ln2),R + exp(tol*ln2)].
В-четвертых, сам Брент тщательно проверял свой алгоритм на самых разнообразных функциях и установил, что в типичном случае для гладкой функции требуется не более 10 итераций. В общем случае Брент ни разу не встретил функции, для которой количество итераций было больше трехзначного числа. Более подробно смотрите работу Брента (1973).
Формальные параметры процедуры.Входные:ax, bx(типreal) - определяют отрезок, на котором ищется корень уравнения;tol (типreal) - точность, с которой должен быть определен корень уравнения.Выходные:процедура-функция возвращает найденное с заданной точностью значение корня на отрезке [ax,bx].
Описанная процедура выглядит:
Function zeroin (ax, bx, tol : real) : real;
Label 20, 30;
var a,b,c,d,e,eps,fa,fb,fc,tol1,xm,p,q,r,s:real;
dn : boolean;
begin eps := 1.0;
dn := false;
repeat
eps := eps / 2.0;
tol1 := 1.0 + eps;
until tol1 <= 1.0;
a := ax;
b := bx;
fa := func (a);
fb := func (b);
20: c := a;
FC := FA;
d := b - a;
e := d;
repeat
if abs (FC) < abs (FB) then
begin a := b;
b := c; c := a;
fa := fb; fb := fc;
fc := fa;
end;
{*** ПРОВЕРКА СХОДИМОСТИ ***}
tol1 := 2.0*eps*abs(b) + 0.5*tol;
xm := 0.5 * (c-b);
if abs (xm) <= tol1 then dn := true
else
if fb=0.0 then dn := true
else
begin
{*** ВОПРОС О НЕОБХОДИМОСТИ БИСЕКЦИИ ***}
if (abs(e)>=tol1) and
(abs(fa)>abs(fb)) then
begin
{*** ПРОВЕРКА НА КВАДРАТИЧ. ИНТЕРПОЛЯЦИЮ ***}
if a<>c then
begin
q := fa / fc; r := fb / fc;
c := fb / fa;
p:= s*(2.0*xm*q*(q-r)- (b-a)*(r-1.0));
q := (q-1.0)*(r-1.0)*(s-1.0);
end
else
begin s := fb / fa;
p := 2.0*xm*s;
q := 1.0 - s;
end;
{*** ВЫБОР ЗНАКА ДЛЯ Q ***}
if p > 0.0 then q := -q;
p := abs (p);
{** ВОПРОС О ПРИМЕНИМОСТИ МЕТОДА ИНТЕРПОЛЯЦИИ **}
if ((2.0*p) < (3.0*xm*q-abs(Tol1*q)))
and (p < (abs(0.5*e*q))) then
begin e := d;
d := p/q; goto 30;
end;
end;
d := xm; e := d;
30: a := b;
fa := fb;
if abs(d) > tol1 then b := b + d;
if abs(d) <= Tol1 then
b := b + sign(Tol1)*xm;
fb := func (b);
if (fb*(fc / abs(fc))) > 0.0 then goto 20;
end;
until dn;
zeroin := b;
end.
Процедура-функция проверялась на примере решения уравнения из п. 2.5 (см. табл. 1.11 и 1.12). Результаты работы данной программы приводятся ниже:
на отрезке [0, 1]:
x = 0.150858;F(x) = -0.0000000000;i= 5.
на отрезке [-3,-2]:
x= -2.071157;F(x) = -0.0000000001;i= 7.
на отрезке [2, 3]:
x= 1.920299;F(x) = 0.0000000001;i= 7.