Exemple de programe MATLAB
Metoda eliminării a lui Gauss
Constă în două faze
- Transformarea sistemului într-un sistem triunghiular echivalent
- Rezolvarea sistemului triunghiular prin substituție inversă
Vom implementa o funcție declarată în următorul mod:
Este mai practic să se lucreze cu matricea extinsă A=[A,b]
Etapa 1: triunghiularizare
La pasul i se elimină necunoscuta
din ecuația j, facând zerouri sub diagonala principală: se înmulțește ecuația (linia) i cu multiplicatorul
și se scade din ecuația (linia i). Deoarece sub diagonala principală elementele vor fi nule, ele se lasa netransformate. Aceasta se poate scrie compact cu codul MATLAB: Pentru ca eliminarea să fie posibilă, trebuie ca
. Dacă
este zero sau este mic linia i se permută cu linia p astfel ca Operația se numește pivotare parțială și a fost introdusă sistematic și studiată de von Neumann și Goldstine în 1947.
După
pași, matricea a fost transformată într-o matrice triunghiulară. Etapa 2: substituția inversă
Din ultima ecuație se obține
În general,
se obține din ecuatia i,
, cu Suma se poate scrie compact cu ajutorul produsului scalar A(i,i+1:n)*x(i+1:n).
La final, am obținut următoarea sursă:
Să testam pe următorul exemplu
, unde Metoda lui Newton
Prezentarea metodei
Dorim să rezolvăm ecuația
. Metoda: se pornește cu un
dat și se execută pasul iterativ până când
, ε precizie dată. Vom implementa o variantă a metodei care să functioneze și pentru sisteme de ecuații neliniare. Pentru un sistem metoda lui Newton are forma
În acest caz derivata
este matricea jacobiană în
. Inversarea de matrice este o operație costisitoare și generatoare de erori și de aceea trebuie evitată. Iterația se poate scrie sub forma
Corecția
se poate obține ca soluție a sistemului Rezolvarea se poate realiza în MATLAB cu operatorul \.
O condiție suficientă de convergență este
. Exemplu: o ecuație scalară
Polinomul
a fost utilizat de Wallis pentru a prezenta metoda lui Newton în fața Academiei framceze. Să definim polinomul și derivata sa. Reprezentăm grafic polinomul:
El are o rădăcină reală între
și
și o pereche de rădăcini complexe conjugate, cum se poate verifica Determinam rădăcina reală cu metoda lui Newton. Alegem valoarea de pornire
și precizia 
[z1,ni1] = Newton(f,fd,x0, 1e-8)
Precizia dorită a fost obținută după 6 iterații. Pentru determinarea rădăcinilor complexe vom utiliza valori de pornire complexe.
[z2,ni2] = Newton(f,fd,x0, 1e-8)
z2 =
-1.047275740771163 + 1.135939889088928i
Verificăm soluțiile
f([z1,z2,conj(z2)])
10-15 ×
-0.888178419700125 + 0.000000000000000i 0.000000000000000 - 0.888178419700125i 0.000000000000000 + 0.888178419700125i
Exemplu: un sistem neliniar
Vom exemplifica acum metoda lui Newton pentru un sistem
. Geometric, prima ecuație reprezintă cercul unitate, iar a doua o parabolă cubică.
fimplicit(@(x,y) x.^2+y.^2-1,[-1,1]); hold on
fimplicit(@(x,y) x.^3-y,[-1,1])
Definim funcția și jacobianul
F = @(x) [x(1)^2+x(2)^2-1; x(1)^3-x(2)];
dF = @(x) [2*x(1), 2*x(2); 3*x(1)^2, -1];
Rădăcinile sunt simetrice față de origine. O valoarea de pornire va fi
. Cu metoda lui Newton, obținem soluțiile [z1,ni1]=Newton(F,dF,x0,1e-8,1e-8,20)
0.826031357654187
0.563624162161259
[z2,ni2]=Newton(F,dF,-x0,1e-8,1e-8,20)
-0.826031357654187
-0.563624162161259
Aplicație la calculul radicalului
Vom folosi metoda lui Newton pentru a calcula
,
. Pornim de la ecuația
. Iterația Newton devine Ținând cont că feste convexă, putem alege ca valoare de pornire orice
pentru care
, adică
. O alegere potrivită este sugerată de inegalitatea mediilor
,deci, vom lua
. Șirul astfel obținut este descrescător și mărginit inferior de
, deci convergent. Vom obține un algoritm independent de mașină, care exploatează aritmetica finită. Ținând cont că într-un interval mărginit avem un număr finit de numere în virgulă flotantă, vom termina iterațiile când
. Dăm codul pentru această funcție De menționat că în aritmetica exactă acest algoritm ciclează la infinit.
Să dăm două exemple de utilizare:
Recursivitate
Curba lui Koch
Curba lui Koch pornește de la un segment de dreaptă, pe care îl imparte în trei și înlocuiește segmentul din mijloc cu două segmente congruente care formează laturile unui triunghi echilateral. După aceea, transformarea se aplică recursiv fiecărui segment, până la atingerea unui nivel dorit de recursivitate.
Funcţia koch are trei argumente de intrare. Primele două, pl şi pr dau coordonatele (x,y) ale capetelor segmentului curent şi al treilea, level, indică nivelul de recursivitate cerut. Dacă level = 0 se desenează un segment; altfel koch se autoapelează de patru ori cu level decrementat cu 1 şi cu puncte care definesc capetele celor patru segmente mai scurte.
Vom testa funcția pentru un segment orizontal de lungime 1 și niveluri de recursivitate de la 1 la 4
pr=[1;0]; %right endpoint
title(['Koch curve: level = ',num2str(k)],'FontSize',16)
Apelând koch cu perechi de puncte echidistante situate pe cercul unitate (varfurile unui poligon regulat) se obţine o curbă numită fulgul de zăpadă al lui Koch (Koch’s snowflake). Funcţia snowflake acceptă la intrare numărul de laturi edges şi nivelul de recursivitate level. Valorile implicite ale acestor parametrii sunt 7 şi respectiv 4.
Dăm două exemple de utilizare
Cuadraturi adaptive
Fie
. Formula elementară a lui Simpson este Pentru două subintervale se obține
unde
și
. Cantitatea
se obține combinând cele două aproximante anterioare (extrapolare): Putem să dăm acum un algoritm recursiv pentru aproximarea integralei. Funcția adquad evaluează integrandul aplicând regula lui Simpson. Ea apelează recursiv quadstep și aplică extrapolarea.
function [Q,fcount] = adquad(F,a,b,tol,varargin)
%ADQUAD adaptive quadrature
%call [Q,fcount] = adquad(F,a,b,tol,varargin)
% F - integrand
% a,b - interval endpoints
% tol - tolerance, default 1.e-6.
% the aditional arguments are passed to the integrand, F(x,p1,p2,..).
% make F callable by feval.
if ischar(F) & exist(F)~=2
F = inline(F);
elseif isa(F,'sym')
F = inline(char(F));
end
if nargin < 4 | isempty(tol), tol = 1.e-6; end
% Initialization
c = (a + b)/2;
fa = F(a,varargin{:}); fc = F(c,varargin{:});
fb = F(b,varargin{:});
% Recursive call
[Q,k] = quadstep(F, a, b, tol, fa, fc, fb, varargin{:});
fcount = k + 3;
% ---------------------------------------------------------
function [Q,fcount] = quadstep(F,a,b,tol,fa,fc,fb,varargin)
% Recursive subfunction called by adquad
h = b - a;
c = (a + b)/2;
fd = F((a+c)/2,varargin{:});
fe = F((c+b)/2,varargin{:});
Q1 = h/6 * (fa + 4*fc + fb);
Q2 = h/12 * (fa + 4*fd + 2*fc + 4*fe + fb);
if abs(Q2 - Q1) <= tol
Q = Q2 + (Q2 - Q1)/15;
fcount = 2;
else
[Qa,ka] = quadstep(F, a, c, tol, fa, fd, fc, varargin{:});
[Qb,kb] = quadstep(F, c, b, tol, fc, fe, fb, varargin{:});
Q = Qa + Qb;
fcount = ka + kb + 2;
end
Vom calcula aproximativ integralele cu valoarea exactă cunoscută
[vI1,nfe1]=adquad(@sin, 0, pi, 1e-8)
[vi2,nfe2]=adquad(g,-1,1,1e-8)
vi2 =
-1.973729821555834e-17