Algebra lineare
G. Puppo
Algebra lineare
Numero di condizionamento
Sistemi triangolari
Fattorizzazione LU
Soluzione di sistemi lineari in Matlab
Effetto del numero di condizionamento
Numero di condizionamento
Per calcolare il numero di
condizionamento, Matlab usa l’istruzione
cond(a,p), dove:
p = 1 è per la norma 1
p = 2 è per la norma 2 (default)
p = inf è per la norma infinito
Andamento del numero di
condizionamento
Costruiamo un programma che calcoli il numero di
condizionamento al variare di N per matrici N per N assegnate.
In particolare il programma deve:
avere un ciclo su N
calcolare le matrici richieste per ogni N
calcolare il numero di condizionamento
corrispondente per ogni matrice, in ognuna
delle norme 1, 2 e inf
stampare un grafico con i risultati
function plot_con(nmax)
%Calcola il numero di condizionamento per le matrici
%RAND(N), con N=1:NMAX, confrontando su un grafico
%i risultati ottenuti in norma 1, norma 2, e norma inf
for n=1:nmax
a=rand(n);
con1(n) = cond(a,1);
con2(n) = cond(a,2);
coninf(n) = cond(a,inf);
end
plot(log10(con2))
hold on
plot(log10(con1),'g')
plot(log10(coninf),'m')(log10(
Proviamo altre matrici ...
Cambiamo le matrici calcolate nella
function plot_con
Sostituiamo a rand(n) le matrici
tridiagonali, fornite dalla function
tridiag(n)
Sostituiamo le matrici di Hilbert, hilb(n),
che hanno un condizionamento ~exp(n).
Matrice tridiagonale
tridiag(n)
Matrici di Hilbert
La scala verticale è logaritmica
Sistemi triangolari inferiori
Scrivo una function che calcola la soluzione del sistema Ax=b,
nel caso in cui A è triangolare inferiore.
In una function che deve essere utilizzata da diversi utenti è
bene controllare che i dati forniti siano coerenti.
In questo caso controllo che:
- A sia quadrata
- A sia triangolare inferiore
- A sia non singolare
- Il vettore b abbia le dimensioni giuste
Controllo che la matrice A sia ben impostata
function x=tri_inf(a,b)
%TRI_INF(A,B) Risolve il sistema triangolare inferiore AX=B.
%
Se A non e' quadrata, o A non e' triangolare inferiore,
%
stampa un messaggio di errore
% Controlla le dimensioni di A:
[n,m] = size(a);
if m ~= n
display('A non e'' quadrata')
return
end
for i=1:n
for j=(i+1):n
if a(i,j) ~=0
display('A non e'' triangolare inf')
return
end
end
end
Termino il controllo dei dati
% Controlla le dimensioni di B
if length(b) ~= n
display('B non e'' compatibile')
return
end
% Controlla se A e' singolare:
for i=1:n
if abs( a(i,i)) < eps*norm(b)
display('A e'' quasi singolare')
return
end
end
Finalmente, risolvo il sistema:
La formula ricorsiva è:
L’algoritmo corrispondente è:
%Risolve il sistema
x(1) = b(1)/a(1,1);
for i=2:n
sum=b(i);
for j=1:(i-1)
sum = sum - a(i,j)*x(j);
end
x(i) = sum/a(i,i);
end
Risolvo un sistema triangolare superiore.
Controllo che A sia ben impostata:
function x=tri_sup(a,b)
%TRI_SUP(A,B) Risolve il sistema triangolare superiore AX=B.
%
Se A non e' quadrata, o A non e' triangolare superiore,
%
stampa un messaggio di errore
% Controlla le dimensioni di A:
[n,m] = size(a);
if m ~= n
display('A non e'' quadrata')
return
end
for i=1:n
for j=1:i-1
if a(i,j) ~=0
display('A non e'' triangolare sup')
return
end
end
end
Controllo che B sia compatibile e che A non sia singolare
% Controlla le dimensioni di B
if length(b) ~= n
display('B non e'' compatibile')
return
end
% Controlla se A e' singolare:
for i=1:n
if abs( a(i,i)) < eps*norm(b)
display('A e'' quasi singolare')
return
end
end
Risolvo il sistema:
La formula ricorsiva è:
E l’algoritmo corrispondente è:
%Risolve il sistema
x(n) = b(n)/a(n,n);
for i=n-1:-1:1
sum=b(i);
for j=i+1:n
sum = sum - a(i,j)*x(j);
end
x(i) = sum/a(i,i);
end
Calcola la fattorizzazione LU di una matrice
function [l,u] = elleu(a)
%ELLEU(A) Calcola la fattorizzazione LU di A, senza pivoting
%Sintassi: [L,U]=ELLEU(A)
%
esce con un messaggio di errore, se trova un pivot <
%
EPS*NORM(A)
nor=norm(a);
% Controlla le dimensioni di A:
[n,m] = size(a);
if m ~= n
display('A non e'' quadrata')
return
end
Calcola la fattorizzazione LU,
riscrivendo su A:
l=-eye(n);
for k=1:n-1
if abs(a(k,k)) < eps*nor
display('Pivot troppo piccolo')
return
end
m(k+1:n,k) = -a(k+1:n,k)/a(k,k);
a(k+1:n,k+1:n) = a(k+1:n,k+1:n)+m(k+1:n,k)*a(k,k+1:n);
end
…infine, immagazzina i risultati nelle matrici L e U:
% Immagazzina i risultati nelle matrici l e u:
l = -m;
u = zeros(n);
for i=1:n
for j=i:n
u(i,j) = a(i,j);
end
end
Risoluzione di un sistema
lineare
Con le tre functions appena costruite, posso risolvere un
sistema lineare.
Devo impostare una matrice quadrata A e un vettore B di
termini noti. Per risolvere il sistema Ax=B, devo:
Calcolare la fattorizzazione LU;
Risolvere il sistema triangolare inferiore Ly=b;
Risolvere il sistema triangolare superiore Ux=y;
>> [l,u]=elleu(a);
>> y=tri_inf(l,b);
>> x=tri_sup(u,y)
Esempio
Risolvo il sistema Ax=b, per:
>> a=[2 -1 0; -1 2 -1; 0 -1 2];
>> a
a=
2 -1 0
-1 2 -1
0 -1 2
>> b=ones(3,1);
Calcola la fattorizzazione LU:
>> [l,u]=elleu(a)
l=
1.0000
0
0
-0.5000 1.0000
0
0 -0.6667 1.0000
u=
2.0000 -1.0000
0
0 1.5000 -1.0000
0
0 1.3333
Osservo che:
>> l*u
ans =
2 -1
-1 2
0 -1
0
-1
2
Risolvo i due sistemi triangolari
>> y=tri_inf(l,b)
y=
1.0000 1.5000 2.0000
>> x=tri_sup(u,y)
x=
1.5000 2.0000 1.5000
Osservo che
>> a*x'-b
ans =
1.0e-015 *
0
0.2220
-0.4441
Quindi, il residuo è piccolo, anche
se non è zero. La soluzione è
accettabile
Provo un altro esempio con a=hilb(5), b=ones(5,1).
Ottengo:
>> a=hilb(5);
>> b=ones(5,1);
>> [l,u]=elleu(a);
>> y=tri_inf(l,b);
>> x=tri_sup(u,y);
>> norm(a*x'-b)
ans =
3.1776e-014
Quindi il residuo è aumentato, infatti:
>> cond(a)
ans =
4.7661e+005
L’effetto del numero di condizionamento si vede meglio con questo
esempio:
Scelgo b, in modo da conoscere la soluzione esatta, x.
Calcolo la soluzione x1 risolvendo il sistema lineare.
In aritmetica esatta, avrei x-x1=0. In aritmetica floating point:
>> a=hilb(5);
>> x=ones(5,1);
>> b=a*x;
>> [l,u]=elleu(a);
>> y=tri_inf(l,b);
>> x1=tri_sup(u,y);
>> norm(x-x1')/norm(x)
ans =
1.5531e-012
La differenza ||x-x1|| è molto più
grande del residuo
Risoluzione di sistemi lineari con
Matlab
Matlab risolve il sistema lineare Ax=b con il comando:
x=A\b.
Se A è quadrata, questo comando implica i seguenti passi:
- Calcola la fattorizzazione LU con pivoting sulle colonne
- Risolvi i due sistemi triangolari
Se A è rettangolare (sistemi sovradeterminati), Matlab calcola la
soluzione nel senso dei minimi quadrati, cioè:
- Calcola la fattorizzazione QR con pivoting sulle colonne
- Risolve il sistema triangolare superiore
Se il condizionamento di A è elevato, stampa un messaggio di
warning, ma calcola ugualmente la soluzione.
Risoluzione di sistemi lineari con
Matlab 2
Nella versione 7, è stata inserita una nuova function per risolvere
sistemi lineari con struttura particolare
x=linsolve(a,b)
Esempio
>> a=[2 -1 0; -1 2 -1; 0 -1 2];
>> b=ones(3,1);
>> x=a\b
x=
1.5000
2.0000
1.5000
Attenzione!
Matlab usa sia / che \ ma i due operatori hanno un effetto diverso.
Provare per credere!
Attenzione! Matlab calcola una soluzione anche quando il
sistema non ammette soluzione.
Nell’esempio seguente, a è singolare:
>> a=[1 2 3; 4 5 6; 7 8 9];
>> b=[1; 1; 0];
>> x=a\b;
Warning: Matrix is close to singular or badly scaled.
Results may be inaccurate. RCOND = 1.541976e-018.
>> norm(a*x-b)
ans =
5.0990
RCOND è il reciproco del numero di condizionamento: se RCOND
è piccolo, la matrice è mal condizionata.
Fattorizzazione LU
Matlab calcola la fattorizzazione LU di una matrice con
il comando:
[l,u] = lu(a)
In questo caso, l contiene anche gli scambi di riga effettuati.
Se la fattorizzazione è PA = LU, allora l=P-1 L.
Oppure posso usare tre argomenti in output::
[l,u,p]=lu(a)
In questo caso, l=L, u=U, p=P.
Esempio
>> a=[1 2 3; 4 5 6; 7 8 9];
>> [l,u]=lu(a)
l=
0.1429 1.0000
0
0.5714 0.5000 1.0000
1.0000
0
0
u=
7.0000 8.0000 9.0000
0 0.8571 1.7143
0
0 0.0000
Notare che l contiene la
matrice triangolare L
con le righe scambiate,
cioè l=P-1 L
Per forzare la soluzione di un sistema tramite
fattorizzazione LU, devo quindi dare i comandi:
>> [l,u]=lu(a);
>> y=l\b;
>> x=u\y;
Fattorizzazione QR
Matlab esegue la fattorizzazione A=QR mediante il
comando:
>>[q,r] = qr(a)
Per forzare la soluzione di un sistema lineare mediante
fattorizzazione QR devo quindi dare i comandi:
>> [q,r]=qr(a);
>> x=r\q'*b;
Esercizio
Effetto del numero di
condizionamento
Variazione del residuo per matrici mal
condizionate
Effetto del condizionamento sulla
precisione della soluzione numerica
Stima del rango
Variazione del residuo per
matrici mal condizionate
Scrivo un programma che calcoli, per n da 1 a 100:
-Vorrei
a=hilb(n)
studiare come varia il residuo
-r b=rand(n,1)
= ||Ax-b||, in funzione del condizionamento
- risolve il sistema a*x=b
della matrice A. Scelgo come matrice mal
- calcola la norma del residuo a*x-b
condizionata
la
matrice
di
Hilbert,
mentre
per
- calcola il condizionamento di a
b- stampa
assegno
vettore
numeri casualied il residuo
un un
grafico
con ildicondizionamento
in funzione di n
Script res_hilb.m
%Esegue un grafico del residuo, in funzione di n,
%per sistemi lineari del tipo Hilb(n)*x=rand(n,1)
nmax=100;
for n=1:nmax
a=hilb(n);
b=rand(n,1);
x=a\b;
c(n)=cond(a);
r(n)=norm(a*x-b)
end
plot(log10(c))
hold on
plot(log10(r+eps),'m')
Ottengo questi risultati
Effetto del condizionamento
sulla precisione della
soluzione
Scrivo un programma che calcoli, per n da 1 a 100:
- a=hilb(n)
Imposto
un problema Ax=b di cui conosco la
- xexa=ones(n,1) (xexa=soluzione esatta)
soluzione
esatta.
numericamente
il
- b=a*xexa
(b =Risolvo
termine noto
corrispondente a xexa)
- risolve il calcolando
sistema a*x=b la
(x=soluzione
approssimata)
problema,
soluzione
stimata y.
- calcola
l’errore l’errore
relativo fra||x-y||.
x e xexa
Quindi
calcolo
- calcola il condizionamento di a
Mi -aspetto
se uso per eAl’errore
una
stampa unerrori
grafico grandi
con il condizionamento
relativo
matrice
mal condizionata, come, di nuovo, la
matrice di Hilbert.
Script hilb_exa.m
% Calcola la differenza fra soluzione esatta e soluzione
% approssimata, per i sistemi lineari hilb(n)*x=b
% e ne stampa il grafico, confrontando con il condizionamento
nmax=100;
for n=1:nmax
a=hilb(n);
xexa=ones(n,1);
b=a*xexa;
x=a\b;
c(n)=cond(a);
err(n)=norm(x-xexa)/norm(xexa);
end
plot(log10(c))
hold on
plot(log10(err+eps),'m')
Ottengo questi risultati
Stima del rango di una
matrice
Per stimare il rango di una matrice posso:
 Calcolare la fattorizzazione LU e contare gli elementi
U(i,i) che hanno modulo maggiore di una tolleranza
assegnata
 Calcolare la fattorizzazione QR e contare gli elementi
R(i,i) che hanno modulo maggiore di una tolleranza
assegnata
Per matrici mal condizionate il secondo metodo è più
affidabile.
La tolleranza assegnata ha un ruolo fondamentale
Listato della function rango.m
function r=rango(a,tol)
% Calcola il rango della matrice A, usando
% il metodo QR
% Sintassi: R=RANGO(A) Calcola il rango di A. Usa EPS
%
se |r(i,i)| <EPS*norm(a,1) => r(i,i)=0
%
R=RANGO(A,TOL) Calcola il rango di A,
%
se |r(i,i)| <TOL => r(i,i)=0
Questa function può essere chiamata in due modi:
rango(a) usa una tolleranza di default: TOL=EPS*NORM(a,1)
rango(a,tol) usa la tolleranza TOL fissata in input
Questa possibilità di scelta è implementata con la function
NARGIN, che conta il numero di argomenti in input:
if nargin < 2
tol=eps*norm(a,1);
end
Quindi, se NARGIN ritorna il valore 1, la function RANGO
calcola la tolleranza,
TOL=EPS*NORM(A,1)
altrimenti TOL non viene calcolata, ma viene usato il valore
assegnato in input
function r=rango(a,tol)
% Calcola il rango della matrice A, usando
% il metodo QR
% Sintassi: R=RANGO(A) Calcola il rango di A. Usa EPS
%
se |r(i,i)| <EPS*norm(a,1) => r(i,i)=0
%
R=RANGO(A,TOL) Calcola il rango di A,
%
se |r(i,i)| <TOL => r(i,i)=0
if nargin < 2
tol=eps*norm(a,1);
end
[q,rr]=qr(a);
r=0; [m,n]=size(a);
for i=1:n
if abs(rr(i,i))>tol
r=r+1;
end
end
Provo ora a calcolare il rango delle matrici di Hilbert.
Uso le seguenti istruzioni:
for i=1:100
r(i)=rango(hilb(i));
end
>> plot(r)
Notare che tutte le matrici di Hilbert sono non singolari,
quindi dovrei avere r(i)=i
Rango delle matrici di Hilbert, con TOL=EPS*NORM(A,1)
Rango delle matrici di Hilbert, con TOL=1e-40
Ora tutte le matrici hanno rango pieno
Apparentemente, i risultati ottenuti con TOL=1e-40 sono
più corretti di quelli ottenuti con TOL=EPS*NORM(A,1).
Calcoliamo però qual è l’accuratezza della fattorizzazione QR
che stiamo calcolando, per esempio per HILB(50):
>> a=hilb(50);
>> [q,r]=qr(a);
>> norm(q*r-a)
ans =
5.7905e-016
Quindi non ha senso usare un valore di TOL più basso di
circa 1e-16, perché la matrice R non è abbastanza accurata
Scarica

Algebra lineare