Professional Documents
Culture Documents
Untitled
Untitled
ü Персонална информация
ü Условие на задачата
„ Начални данни
„ Брой стъпки
N = 40
„ Формула предиктор
H0L
I55 y'i − 59 yi−1 M
h ' ' '
yi+1 = yi + + 37 yi−2 − 9 yi−3 (3)
24
„ Формула коректор
ü Встъпителни думи
метод, а (4) е 3-стъпков интерполационен метод, то и двата метода имат локална грешка OIh4 M. Този факт за (4) е показан
Видно е, че формулите (3) и (4) са валидни формули на Адамс. При това, предвид че (3) е 4-стъпков екстраполационен
Hk1 + 2 k2 + 2 k3 + k4L
1
yi+1 = yi +
6
k1 = h f Hxi , yi L
h k1 (5)
k2 = h f xi + , yi +
2 2
h k2
k3 = h f xi + , yi +
k4 = h f Hxi + h, yi + k3 L
2 2
2 Предиктор-коректор
‚ ai ym+i − ‚ bi ym+i
1 k k
'
h i=0 i=0
След това около xm развиваме в ред на Тейлър y j и y'j , където j ∫ m. Както ще видим по-долу, от голямо значение е до кой
член ще развием, тъй като развитие, където броят на членовете е по-малък от реда на търсената грешка няма да даде
коректни резултати. Затова и важността на експериментите не е за пренебрегване.
Последно, групираме множителите по h (като същевременно някои от тях се унищожават) и виждаме коя е най-ниската
степен на h (след като сме изпосъкратили), т.е. от кое h нататък имаме разлика с оригинала.
Нека сметнем локалната грешка на (4), използвайки Mathematica. Тук ползваме постфиксен запис (//) – често стрещана
можем да запишем x êê G êê F. Чрез TraditionalForm получаваме резултатите в по-математически вид (например огражда
практика. За удобство, при записването на композиция от едноаргументни функции, вместо F@G@xDD, в Mathematica
За да продължим, трябва да запишем израза по-коректно – в досегашния запис y@iD отговаряше (само) логически на yi .
Сега ще го заместим с y@x@iDD. За тази цел се обръщаме към последния изход с % и ползваме ReplaceAll (/.), Rule (Ø) и
patterns.
% ê. 8y@w_D → y@x@wDD, y '@w_D → y '@x@wDD< êê Expand êê TraditionalForm
terms = 7;
Светлин Анков 3
Сега да заместим y@i + нещоD и y '@i + нещоD със съответните им представяния в редове на Тайлър.
HxHi - 1L - xHiLL y££ HxHiLL + HxHi - 1L - xHiLL2 yH3L HxHiLL + HxHi - 1L - xHiLL3 yH4L HxHiLL +
5 5 5
24 48 144
% ê. x@i_D → x0 + i h êê TraditionalForm
Не стана. Тъй като при работа с редове Mathematica има "едно наум", то нагледно неочудващият резултат от Series
всъщност не представлява обичаен израз, а символ от тип SeriesData. Използвайки Normal ще "култивираме" израза.
H%% êê NormalL ê. x@i_D → x0 + i h êê TraditionalForm
Разкриваме скобите.
% êê Expand êê TraditionalForm
За да покажем важността на броя членове в редовете на Тейлър, нека съберем горния алгоритъм в програмка с име
estimateError. Тук съм направил програмата да работи при всякакви производни yHkL . При това в последната стъпка
представям x0 + i h отново във вида xi . Необходимо е променливите да са y и i, при това символи (т.е. с незададени
числени стойности).
estimateError@expr_, terms_D :=
ModuleA
8exp = expr<,
exp = Iexp ê. 8y@w_D → y@x@wDD, Derivative@z_D@yD@w_D → Derivative@zD@yD@x@wDD<M;
exp = Iexp ê. 8Derivative@z_D@yD@x@i + k_DD → Series@Derivative@zD@yD@x@i + kDD,
8x@i + kD, x@iD, terms<D, y@x@i + k_DD −> Series@y@x@i + kDD, 8x@i + kD, x@iD, terms<D<M;
exp = IIHexp êê NormalL ê. x@i_D → x0 + i hM êê ExpandM;
exp = exp ê. Ix0 + i_ hM → x@iD; H∗ Връщаме пак в x@iD ∗L
exp êê TraditionalForm
E
h4 yH5L HxHiLL
5
-
144
При 3 члена обаче, грешката вече е OIh3 M, а не задължително нула, както някой биха очаквали.
h3 yH4L HxHiLL
1
-
24
- h2 yH3L HxHiLL
1
6
Това показва значението на броя членове за експерименталното пресмятане на локалната грешка на апроксимация.
Още да изтъкнем, че estimateError може да даде грешката и за друг диференчен метод. Наприм, на метода на Ойлер.
y@i + 1D − y@iD
estimateErrorB − y '@iD, 2F
h
h y££ HxHiLL
1
2
6 Предиктор-коректор
Последно, можем да доизпипаме програмата да връща резултата във вида OHhn L. Забележете, че в Mathematica коректния
начин на записване на остатъчния член е не O@hn D, а O@hDn . Въпреки това в TraditonalForm Mathematica ще ползва
познатото ни означение.
estimateErrorO@expr_, terms_D :=
Module@
8exp = HestimateError@expr, termsDL@@1DD<,
H∗ P1T защото имаме TraditionalForm@...D ∗L
exp = exp ê. 8h → h@1D, hx_ → h@xD<;
exp = Cases@exp, h@x_D, ∞D;
exp = Min @ exp@@All, 1DD;
If@exp ∞,
Print@"Грешката е по−голяма от OHhL!"D;
Return@D;
D;
O@hDexp êê TraditionalForm
D;
ü Реализация на програмата
Функцията rungekutta4 е пълнофункционален метод за намиране на приближено решение по формулите (5). По-нататък
ще я използваме за намирането на началните стойности, необходими, за да "тръгне" Адамс.
В реализацията използваме SetDelayed (:=), тъй като въвеждаме функция. Използваме долна черта (Blank: _ ) след
имената на аргументите, за да укажем, че не става дума за конкретни x и u, а за първи и втори аргумент на функция (т.е.
използваме patterns). Още използваме Module, за да ограничим променливите да имат локална природа (нещо обичайно в
смисъла на функция, но неавтоматизирано при писането на Mathematica. Този факт не е недостатък, а по-скоро резултат
на обобщения характер на езика). Също така ползваме и NestList, който е и един от начините във функционалното
програмиране за реализиране на итерация.
rungekutta4@f_, x0_, X_, u0_, n_D :=
ModuleB8h, rg4it<,
H∗ Забележка: Естесвено y0 === u0 ∗L
H∗ смятаме h ∗L
X − x0
h= ;
H∗
n
rg4it@8xold_, yold_<D :=
ModuleB8k1, k2, k3, k4<,
k1 = h f@xold, yoldD;
F;
h k1
k2 = h fBxold + , yold +
2 2
F;
h k2
k3 = h fBxold + , yold +
2 2
k4 = h f@xold + h, yold + k3D;
H∗ Итерираме n пъти ∗L
NestList@rg4it, 8x0, u0<, nD
F
Нека пробваме функцията с произволни данни. Сравнявайки например с резултати от ODE, ще се убедим, че работи
правилно. В долния пример ползвам анонимна функция, която може да се чете като u + 1 (т.е. втория параметър за f
(който е u) плюс единица).
rungekutta4@H 2 + 1L &, 0, 1, 1, 10D êê N êê Transpose êê Grid
Използваме N, за да получим числен отговор (в противен случай Mathematica връща едни страшни дроби). Последно
ползваме Transpose, за да завъртим таблицата от числа и Grid, за да получим по четлив резултат (иначе ще получим
списъци, заградени във фугирни скоби – не много удобно за четене).
8 Предиктор-коректор
Вече сме готови да напишем основния метод за проекта – predcorr. Още в сигнатурата на функцията чрез оператора за
условие, задаваме тя да е валидна само за целочислени n ¥ 0, а също задаваме и стойности по подразбиране за x и maxit.
predcorr@f_, x0_, X_, u0_, n_Integer ê; 0 ≤ n < ∞, ξ_: 0.00001, maxit_Integer: 3D :=
ModuleB
8x, y, iterations, g, h, predcorrit<,
H∗ списък с локалните променливи ∗L
H∗
Забележка
Естесвено y0 = u00
Също така y'i = fHxi ,yi L
∗L
If @ξ ≤ 0, ξ = 0.00001D;
If@maxit ≤ 0, maxit = 3D;
H∗ Смятаме h ∗L
X − x0
h= ;
n
H∗ За да се реализира цикъл,
разбира се можем да ползваме For, но функционалният начин е чрез Table ∗L
Table@
predcorrit@iD, 8i, 4, n<
H∗ Присвояването на новите стойности на y и iterations,
става директно в predcorrit от съображения за ефективност,
тъй като пак по същите съображения predcorrit има директен достъп до тях ∗L
D;
8x, y, iterations< H∗ връщаме резултата ∗L
F
10 Предиктор-коректор
ü Output функция
ü Резултати
u2 − x + 0.5
f@x_, u_D :=
x2 + u + 1
Сега, използвайки нашите данни, да извикаме метода за принтене. Сигнатурата беше: f , x0 , X , u0 , N, x, iterations
, x ∈ H0, 1D
u2 − x + 0.5
u'HxL =
u + x2 + 1
uH0L = 0
Параметри
ξ HточностL N HинтервалиL максимум
итерации
0.00001 40 3
x y it
0.00000000 0.00000000 0.00000000
0.02500000 0.01211290 0.00000000
0.05000000 0.02346525 0.00000000
0.07500000 0.03407665 0.00000000
0.10000000 0.04396569 1.00000000
0.12500000 0.05315009 1.00000000
0.15000000 0.06164688 1.00000000
0.17500000 0.06947249 1.00000000
0.20000000 0.07664292 1.00000000
0.22500000 0.08317380 1.00000000
0.25000000 0.08908045 1.00000000
0.27500000 0.09437800 1.00000000
0.30000000 0.09908143 1.00000000
0.32500000 0.10320560 1.00000000
0.35000000 0.10676533 1.00000000
0.37500000 0.10977538 1.00000000
0.40000000 0.11225052 1.00000000
0.42500000 0.11420555 1.00000000
0.45000000 0.11565525 1.00000000
0.47500000 0.11661447 1.00000000
0.50000000 0.11709806 1.00000000
0.52500000 0.11712093 1.00000000
0.55000000 0.11669798 1.00000000
0.57500000 0.11584414 1.00000000
0.60000000 0.11457432 1.00000000
0.62500000 0.11290341 1.00000000
0.65000000 0.11084628 1.00000000
0.67500000 0.10841772 1.00000000
0.70000000 0.10563246 1.00000000
0.72500000 0.10250512 1.00000000
0.75000000 0.09905019 1.00000000
0.77500000 0.09528201 1.00000000
0.80000000 0.09121479 1.00000000
0.82500000 0.08686251 1.00000000
0.85000000 0.08223895 1.00000000
0.87500000 0.07735766 1.00000000
0.90000000 0.07223196 1.00000000
0.92500000 0.06687488 1.00000000
0.95000000 0.06129916 1.00000000
0.97500000 0.05551726 1.00000000
1.00000000 0.04954133 1.00000000