Методом парабол

Если в методе Ньютона (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 г. по ал­го­рит­­му Дек­ке­ра в вер­сии Брен­та. Здесь же пре­д­ла­га­ется ре­а­ли­зация ал­го­ритма на языкеPAS­­CAL, вы­­пол­нен­ная ав­то­рами по­со­бия.

Подрограмма оформлена как процедура-функ­ция ze­ro­­in.Все названия переменных по срав­не­нию с форт­­ран­ной версией сохранены. Об­ра­ще­ние к проце­ду­ре-функ­ции имеет простой вид:

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.

Соседние файлы в папке glava1