You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
UNIVERSITÀ DEGLI STUDI DI FIRENZE<br />
FACOLTÀ DI SCIENZE MATEMATICHE, FISICHE E NATURALI<br />
Corso di Laurea in Informatica<br />
<strong>Calcolo</strong><br />
<strong>Numerico</strong><br />
Roberto Balducci<br />
Professore Luigi Brugnano<br />
ANNO ACCADEMICO 2006-2007
Indice<br />
1 Introduzione 3<br />
2 Errori ed aritmetica finita 4<br />
2.1 Errori di discretizzazione . . . . . . . . . . . . . . . . . . . . . . 5<br />
2.2 Errori di convergenza . . . . . . . . . . . . . . . . . . . . . . . . 6<br />
2.3 Errori di round-off . . . . . . . . . . . . . . . . . . . . . . . . . . 8<br />
2.3.1 Numeri interi . . . . . . . . . . . . . . . . . . . . . . . . . 8<br />
2.3.2 Numeri reali . . . . . . . . . . . . . . . . . . . . . . . . . 9<br />
2.3.3 Overflow e underflow . . . . . . . . . . . . . . . . . . . . 11<br />
2.3.4 Lo standard IEEE 754 . . . . . . . . . . . . . . . . . . . . 11<br />
2.3.5 Aritmetica finita . . . . . . . . . . . . . . . . . . . . . . . 13<br />
2.3.6 Condizionamento del problema . . . . . . . . . . . . . . . 15<br />
3 Radici di un equazione 19<br />
3.1 Il metodo di bisezione . . . . . . . . . . . . . . . . . . . . . . . . 19<br />
3.1.1 Criterio d’arresto . . . . . . . . . . . . . . . . . . . . . . . 20<br />
3.2 Metodo di Newton . . . . . . . . . . . . . . . . . . . . . . . . . . 27<br />
3.2.1 Convergenza locale . . . . . . . . . . . . . . . . . . . . . . 28<br />
3.2.2 Criterio d’arresto . . . . . . . . . . . . . . . . . . . . . . . 30<br />
3.2.3 Ancora sul criterio d’arresto . . . . . . . . . . . . . . . . . 35<br />
3.2.4 Radici multiple . . . . . . . . . . . . . . . . . . . . . . . . 36<br />
3.3 Metodi quasi-Newton . . . . . . . . . . . . . . . . . . . . . . . . . 39<br />
4 Sistemi lineari 46<br />
4.1 Casi elementari . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46<br />
4.1.1 Matrici diagonali . . . . . . . . . . . . . . . . . . . . . . . 46<br />
4.1.2 Matrici triangolari . . . . . . . . . . . . . . . . . . . . . . 48<br />
4.1.3 Matrici ortogonali . . . . . . . . . . . . . . . . . . . . . . 51<br />
4.2 Metodi di fattorizzazione . . . . . . . . . . . . . . . . . . . . . . . 52<br />
4.3 Fattorizzazione LU di una matrice . . . . . . . . . . . . . . . . . 52<br />
4.3.1 Costo computazionale . . . . . . . . . . . . . . . . . . . . 60<br />
4.4 Matrici a diagonale dominante . . . . . . . . . . . . . . . . . . . 60<br />
4.5 Matrici sdp: fattorizzazione LDL T . . . . . . . . . . . . . . . . . 61<br />
4.6 Fattorizzazione LU con pivoting . . . . . . . . . . . . . . . . . . 64<br />
4.7 Condizionamento del problema . . . . . . . . . . . . . . . . . . . 69<br />
4.8 Sistemi lineari sovradimensionati . . . . . . . . . . . . . . . . . . 72<br />
4.9 Esistenza della fattorizzazione QR . . . . . . . . . . . . . . . . . 73<br />
1
5 Approssimazione di funzioni 79<br />
5.1 Interpolazione polinomiale . . . . . . . . . . . . . . . . . . . . . . 79<br />
5.2 Forma di Lagrange e forma di Newton . . . . . . . . . . . . . . . 80<br />
5.3 Interpolazione di Hermite . . . . . . . . . . . . . . . . . . . . . . 90<br />
5.4 Errore nell’interpolazione . . . . . . . . . . . . . . . . . . . . . . 91<br />
5.5 Condizionamento del problema . . . . . . . . . . . . . . . . . . . 93<br />
5.6 Ascisse di Chebyshev . . . . . . . . . . . . . . . . . . . . . . . . . 95<br />
5.7 Interpolazione mediante funzioni spline . . . . . . . . . . . . . . . 96<br />
5.8 Spline cubiche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98<br />
5.9 <strong>Calcolo</strong> spline cubica . . . . . . . . . . . . . . . . . . . . . . . . . 98<br />
5.10 Approssimazione polinomiale ai minimi quadrati . . . . . . . . . 102<br />
6 Formule di quadratura 104<br />
6.1 Metodo di Newton-Cotes . . . . . . . . . . . . . . . . . . . . . . 104<br />
6.2 Errore . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106<br />
6.3 Formule composite . . . . . . . . . . . . . . . . . . . . . . . . . . 107<br />
6.4 Formule adattive . . . . . . . . . . . . . . . . . . . . . . . . . . . 109<br />
2
Capitolo 1<br />
Introduzione<br />
Il calcolo numerico è una disciplina che rientra nel campo della matematica<br />
applicata.L’obiettivo di questa scienza è dare una soluzione, il più possibile accurata<br />
ed efficiente, a tutti quei problemi di natura matematica. Nel calcolo<br />
numerico, a differenza del calcolo simbolico, importa andare a calcolare la soluzione<br />
con dei vincoli di tempo e precisione. Facciamo l’esempio della centralina<br />
dell’ABS che comanda il servofreno di un automobile. Quando la leva del freno<br />
viene premuta, la centralina deve elaborare i dati in ingresso in tempo e con<br />
una precisione appropriata, altrimenti rischieremmo il bloccaggio delle ruote<br />
con il rischio di provocare un incidente. Come si può facilmente intuire, sono<br />
innumerevoli gli esempi nei quali il calcolo numerico ricopre una fondamentale<br />
importanza. Questa scienza quindi presterà particolare attenzione agli errori che<br />
vengono commessi nelle varie fasi dello sviluppo degli algoritmi atti a ottenere<br />
la soluzione numerica del problema.<br />
3
Capitolo 2<br />
Errori ed aritmetica finita<br />
L’utilizzo di tecnologie digitali, indispensabili nell’analisi numerica, porta inevitabilmente<br />
a rappresentare un valore, sia esso x ∈ R, nell’ambito dell’aritmetica<br />
finita. Con questi valori digitalizzati, poi si svolgono operazioni che potrebero<br />
portare ad un valore nel campo dei reali. Ancora una volta dobbiamo rappresentare<br />
questo risultato con un’aritmetica finita. Vediamo allora come si può<br />
misurare l’errore.<br />
Chiamiamo errore assoluto, e la indichiamo con ∆x, la differenza tra ˜x, il dato<br />
approssimato, e x, il dato esatto.<br />
∆x ≡ ˜x − x (2.1)<br />
Esempio 1. Se x = Π e ˜x = 3.14 l’errore assoluto che commettiamo è pari a<br />
∆x ≈ −1.6 · 10 −3 .<br />
Notiamo subito che l’errore assoluto non fornisce un informazione di per sè<br />
attendibile. Infatti un errore di −1.6 · 10 −3 , risulterebbe essere macroscopico<br />
nel campo delle nanotecnologie, oppure assolutamente trascurabile se parliamo<br />
di distanze intergalattiche. Si ha la necessità quindi di definire l’errore relativo:<br />
ǫx ≡ ∆x<br />
x<br />
= ˜x − x<br />
x<br />
Dalla 2.2 con qualche passaggio algebrico arriviamo alla forma<br />
(2.2)<br />
˜x = x(1 + ǫx) ⇒ ˜x<br />
= 1 + ǫx<br />
x<br />
Pertanto l’errore relativo dobbiamo confrontarlo con l’unità.Un errore relativo ≈<br />
1, ci dice che l’errore commesso è troppo grande. Mentre un errore relativo<br />
dell’ordine di 10−6 , ci dice che abbiamo sbagliato di una parte su un milione,<br />
il che è trascurabile.<br />
Esempio 2. Consideriamo ˜π = 3.14 e π ≈ 3.1415926535.<br />
∆x = ˜π − π ≈ 1.5926535 · 10 −3 ǫx = ∆x<br />
π<br />
≈ 0, 506957354 · 10−3<br />
La cosa si fa interessante se consideriamo l’intero più piccolo del logaritmo in<br />
base 10 dell’errore relativo. Infatti − log 10 |ǫx| ≈ 3, 295028 ⇒ ⌊− log 10 |ǫx|⌋ = 3,<br />
che guarda caso sono il numero di cifre decimali uguali tra il valore approssimato<br />
e quello esatto.<br />
4
2.1 Errori di discretizzazione<br />
Nei problemi matematici molto spesso abbiamo a che fare con funzioni che<br />
operano nel continuo, e che devono essere discretizzate. Facciamo un esempio:<br />
data la funzione f(x) e ¯x ∈ R si chiede di calcolare f ′ (¯x), ma invece di calcolare<br />
la derivata, non sempre evidente, si cercano sue approssimazioni.<br />
Per il nostro scopo usiamo la definizione di rapporto incrementale:<br />
f ′ f(¯x + h) − f(¯x)<br />
(¯x) = limh→0<br />
h<br />
≈ f(¯x + ¯ h) − f(¯x)<br />
¯h<br />
¯h è piccolo e opportunamente scelto, percui l’approssimazione è una quantità<br />
discreta visto che ¯ h non può tendere a 0.<br />
Deduciamo dunque che l’errore corrispondente è appunto l’errore di discretizzazione,<br />
ma vediamo a quanto ammonta: Sviluppiamo quindi con taylor la<br />
funzione f(x)con punto iniziale ¯x con resto al secondo ordine<br />
f(¯x + h) = f(¯x) + h · f ′ (¯x) + h2<br />
2 · f ′′ (ξ) ξ ∈ (¯x, ¯x + h)<br />
f(¯x + h) − f(¯x)<br />
h<br />
h<br />
Possiamo scrivere in modo del tutto equivalente<br />
= f(¯x) + h · f ′ (¯x) + h2<br />
2 · f(2) (ξ) − f(¯x)<br />
= f ′ (¯x)+ h<br />
2 f(2) (ξ)<br />
f ′ f(¯x + h) − f(¯x)<br />
(¯x) = −<br />
h<br />
h<br />
2 f(2) (ξ)<br />
Questo significa che usando il rapporto incrementale per calcolare la derivata<br />
della funzione f(x) nel punto ¯x, si commette un errore pari a h<br />
2f(2) (ξ), che per<br />
h → 0 è un o(h)<br />
Per calcolare la derivata di una funzione, possiamo usare un altro metodo che<br />
risulta più accurato. Consideriamo ad esempio la seguente espressione<br />
f(¯x + h) − f(¯x − h)<br />
2h<br />
Sviluppiamo ancora i due addendi del numeratore<br />
f(¯x + h) = f(¯x) + h · f ′ (¯x) + h2<br />
2 · f(2) (¯x) + h(3)<br />
· f<br />
3!<br />
(3) (ψ)<br />
Dove ψ, ζ ∈ (¯x, ¯x + h)<br />
f(¯x − h) = f(¯x) − h · f ′ (¯x) + h2<br />
2 · f(2) (¯x) − h(3)<br />
· f<br />
3!<br />
(3) (ζ)<br />
f(¯x + h) − f(¯x − h)<br />
2h<br />
= f ′ (¯x) + h2<br />
3! · (f(3) (ψ) + f (3) (ζ))<br />
Con qualche semplificazione arriviamo al seguente risultato:<br />
f ′ (¯x) =<br />
f(¯x + h) − f(¯x − h)<br />
2h<br />
− h2<br />
3! · (f(3) (ψ) + f (3) (ζ))<br />
(2.3)<br />
Per h → 0 l’addendo h2<br />
3! ·(f(3) (ψ)+f (3) (ζ)) si comporta come un o(h 2 ). Questo<br />
sta a significare che approssimando la derivata f ′ (¯x) con la 2.3 si ha un errore<br />
che si comporta come h 2 . In questo modo trasformiamo dunque un problema<br />
continuo in uno discreto, introducendo un errore.<br />
5
2.2 Errori di convergenza<br />
Nell’universo dei metodi matematici, esistono degli algoritmi che forniscono un<br />
risultato tanto più approssimato quante più volte si reitera l’algoritmo stesso.<br />
Sia x ∗ il risultato esatto del problema. Definiamo quindi la funzione di iterazione<br />
come segue:<br />
xn+1 = Φ(xn), n = 0, 1, 2, · · · (2.4)<br />
Cerchiamo di capire come funziona generalmente una funzione di iterazione,<br />
e quali sono le condizioni per le quali questa funzione è consistente.<br />
Il valore iniziale di ingresso della funzione è x0, un approssimazione (a volte<br />
anche molto lasca) di x ∗ . Il metodo si dice convergente se:<br />
lim<br />
n→∞ xn = x ∗<br />
(2.5)<br />
La funzione 2.4 rispetta il teorema del punto fisso; sostanzialmente Φ(x ∗ ) = x ∗ .<br />
La soluzione del problema si ricava solamente iterando infinite volte la funzione<br />
2.4. Quindi affinchè si possa utilizzare la soluzione fornita da un metodo siffatto,<br />
dovremmo definire un opportuno criterio d’arresto. Se arrestiamo l’esecuzione<br />
a n = N − 1, calcoleremo xN. Definiamo quindi l’errore di convergenza come:<br />
xN − x ∗<br />
(2.6)<br />
Vediamo due metodi per calcolare √ 2 = 1, 4142135623730950488016887242097<br />
Esempio 3 (<strong>Calcolo</strong> di √ 2-prima versione).<br />
Consideriamo la funzione di iterazione seguente<br />
xn+1 = 1<br />
2 (xn + 2<br />
xn<br />
), n = 0, 1, 2, · · · x0 = 2<br />
È interessante notare come l’algoritmo sopra descritto rispetti il teorema del<br />
punto fisso. Infatti<br />
1<br />
2 ·<br />
√<br />
√2 2 2 1<br />
+ √2 = + √ =<br />
2 2 2<br />
√ =<br />
2 √ 2<br />
Vediamo come in Matlab può essere implementata e quali risultati possiamo<br />
ottenere.<br />
risultato=[];<br />
x=2;<br />
y=0;<br />
for i=1:10<br />
y=1/2*(x+2/x);<br />
risultato(i,:)=[i,y];<br />
x=y;<br />
end<br />
Il risultato dell’esecuzione di questo listato è di seguito, mostra sulla colonna<br />
di sinistra l’iterazione i-esima e sulla colonna di destra il valore di xi.Come si<br />
può vedere il metodo converge molto velocemente al valore √ 2<br />
6
1.00000000000000 1.50000000000000<br />
2.00000000000000 1.41666666666667<br />
3.00000000000000 1.41421568627451<br />
4.00000000000000 1.41421356237469<br />
5.00000000000000 1.41421356237309<br />
6.00000000000000 1.41421356237309<br />
7.00000000000000 1.41421356237309<br />
8.00000000000000 1.41421356237309<br />
9.00000000000000 1.41421356237309<br />
10.00000000000000 1.41421356237309<br />
Esempio 4 (<strong>Calcolo</strong> di √ 2-seconda versione).<br />
Questa è la seconda funzione per il calcolo di √ 2<br />
xn+1 = xn · xn−1 + 2<br />
xn + xn+1<br />
x0 = 2 , x1 = 1.5<br />
Anche questo algoritmo rispetta il teorema del punto fisso. Infatti ipotizzando<br />
che alla n + 1-esima iterazione siamo arrivati a calcolare √ 2 abbiamo che:<br />
√ 2 √ 2 + 2<br />
√ 2 + √ 2 =<br />
2 + 2<br />
2 · √ 2<br />
= 2<br />
√ 2 = √ 2<br />
risultato (1,:)=[0,2];<br />
risultato (2,:)=[1,1.5];<br />
y=0;<br />
for i=3:10<br />
y=(risultato(i-1,2)*risultato(i-2,2)+2)/(risultato(i-1,2)+risultato(i-2,2));<br />
risultato(i,:)=[i-1,y];<br />
end<br />
Come si può notare, a parità di iterazione, la prima verione dell’algoritmo è<br />
molto più efficiente della seconda.<br />
0 2.00000000000000<br />
1.00000000000000 1.50000000000000<br />
2.00000000000000 1.42857142857143<br />
3.00000000000000 1.41463414634146<br />
4.00000000000000 1.41421568627451<br />
5.00000000000000 1.41421356268887<br />
6.00000000000000 1.41421356237310<br />
7.00000000000000 1.41421356237310<br />
8.00000000000000 1.41421356237309<br />
9.00000000000000 1.41421356237310<br />
10.00000000000000 1.41421356237310<br />
11.00000000000000 1.41421356237309<br />
7
2.3 Errori di round-off<br />
Nell’ambito dell’analisi numerica una delle problematiche maggiori è l’analisi<br />
degli errori. In ogni fase di risoluzione di un problema reale si commettono<br />
degli errori. Nella scelta del modello matematico s’introducono gli errori dovuti<br />
all’aggiunta di ipotesi semplificative, ad una incompleta o inesatta deduzione<br />
del modello stesso; tali errori saranno tanto più piccoli quanto più le ipotesi saranno<br />
soddisfatte. Nella fase di discretizzazione del modello s’introduce l’errore<br />
di troncamento analitico, dovuto, ad esempio, alla sostituzione di insiemi continui<br />
con insiemi discreti o all’approssimazione di operazioni basate sul concetto<br />
di infinito con operazioni razionali in numero finito. Nell’ultima fase, infine,<br />
intervengono gli errori di round-off dovuti all’approssimazione di numeri reali<br />
con numeri macchina.<br />
Un calcolatore numerico, infatti, è in grado di rappresentare soltanto un<br />
numero finito di cifre; ne consegue la possibilità che un numero reale introdotto<br />
nel calcolatore sia approssimato. Inoltre le operazioni elementari eseguite su tali<br />
numeri possono e loro volta, produrre risultati non rappresentabili esattamente<br />
nel calcolatore. Pertanto, quando un algoritmo, costituito da una successione<br />
di operazioni elementari, è eseguito su un calcolatore, si ha in generale una<br />
creazione e successiva propagazione di errori. Tali errori sono appunto gli errori<br />
di arrotondamento o round-off.<br />
L’errore di troncamento è una discrepanza introdotta dal fatto che i metodi<br />
numerici utilizzano delle approssimazioni per eseguire calcoli matematici e<br />
rappresentare quantità esatte.<br />
Il risultato prodotto dall’algoritmo differisce, quindi in generale dal risultato<br />
esatto, cioè da quel risultato ideale che si otterrebbe operando con tutte le cifre<br />
richieste. Il risultato dipenderà da come le perturbazioni, cioè la successione<br />
di errori, si amplificheranno. Lo studio del comportamento degli errori nonché<br />
la progettazione di tecniche per contenerne la propagazione, stanno alla base<br />
di qualsiasi algoritmo per il calcolo numerico, in quanto, l’amplificazione di un<br />
errore anche piccolo può addirittura invalidare il risultato dell’algoritmo. In<br />
questo capitolo ci occuperemo di studiare come vengono rappresentati i numeri<br />
nel calcolatore; vedremo anche gli errori che vengono introdotti da questa<br />
operazione. Non andremo a considerare gli errori di propagazione, in quanto<br />
richiederebbe un analisi molto più approfondita.<br />
2.3.1 Numeri interi<br />
Un numero intero viene memorizzato, nel calcolatore, come una stringa di N +1<br />
cifre nel seguente modo:<br />
α0α1 · · · αN<br />
(2.7)<br />
dove b ∈ N è la base del numero e<br />
α0 ∈ {+, −}, αi ∈ {0, 1, · · · , b − 1} i = 1, · · · , N<br />
Con la stringa 2.7 si può rappresentare il numero<br />
N<br />
n = i=1 αibN−i , se α0 = +<br />
N i=1 αibN−i − bN , se α0 = −<br />
8<br />
(2.8)
Esempio 5. Consideriamo il caso di una variabile di tipo int.Nel linguaggio<br />
java questa variabile occupa 16 bit. Il suo intervallo di rappresentazione è<br />
[−32768, 32767]. È interessante notare che i numeri positivi hanno il bit α0 = 0;<br />
di contro i numeri negativi hanno il bit α0 = 1.<br />
2.3.2 Numeri reali<br />
Un numero reale viene memorizzato, nel calcolatore, mediante una stringa di<br />
m + 1 + s cifre nel seguente modo:<br />
dove b ∈ N è la base del numero e<br />
α0α1 · · · αmβ1 · · · βs<br />
(2.9)<br />
α0 ∈ {+, −}, αi, βj ∈ {0, 1, · · · , b − 1} i = 1, · · · , m, j = 1, · · · , s e α1 = 0<br />
Definiamo rispettivamente la mantissa e l’esponente<br />
ρ =<br />
m<br />
i=1<br />
αib 1−i = α1b 0 + α2b −1 + · · · + αnb 1−m<br />
<br />
α1,α2,··· ,αm<br />
(2.10)<br />
η = e − ν (2.11)<br />
La stringa 2.9 andrà a denotare il numero reale r definito di seguito:<br />
r = ± m <br />
i=1<br />
αib 1−i b e−ν , dove e =<br />
s<br />
βjb s−j<br />
j=1<br />
(2.12)<br />
Il numero ν ∈ N è fissato a priori, in modo tale da dividere circa a metà l’intervallo<br />
dei numeri che si possono formare con e bit. Questo viene fatto per evitare<br />
di sprecare un bit per il segno. Infatti il numero ν rappresenta uno shift. Allora<br />
il numero 2.11 risulterà sempre positivo.<br />
Teorema 1. ρ un numero tale che 1 ≤ ρ < b<br />
Vediamo che ρmin ≥ 1; Il minimo valore che può assumere ρ, sia esso ρmin, si<br />
ha quando αi = 0, i = 2, · · · , m e α1 = 1. Quindi<br />
ρmin = α1b 0 + α2b −1 + · · · + αmb 1−m<br />
= α1b<br />
<br />
0<br />
0 ≥ 1.<br />
Invece il massimo valore che può assumere ρ, sia esso ρmax, si ha quando αi =<br />
b − 1, i = 1, · · · , m. Quindi<br />
m<br />
ρmax = (b−1)·b 1−i m<br />
= (b−1)·b b −i 1 − b−m<br />
= (b−1)·b·<br />
b − 1 = b·(1−b−m ) ≤ b<br />
i=1<br />
i=1<br />
Teorema 2. e è un numero tale che −ν ≤ e ≤ b s − 1 − ν.<br />
La dimostrazione di questo teorema è del tutto analoga a quella del teorema 1.<br />
9
Teorema 3. Il più piccolo ed il più grande, in valore assoluto, tra i numeri di<br />
macchina diversi da zero, sono rispettivamente:<br />
r1 = ρmin · b −ν<br />
(2.13)<br />
r2 = ρmax · b emax (2.14)<br />
Definizione 1. Si definisce l’insieme dei numeri di macchina come:<br />
⎧<br />
⎨<br />
M =<br />
⎩ x ∈ R : x = ±ρbe m<br />
, ρ = αib 1−i s<br />
, e = βjb s−j<br />
⎫<br />
⎬<br />
∪ {∅} (2.15)<br />
⎭<br />
i=1<br />
Definizione 2. Definiamo allora l’insieme<br />
j=1<br />
I = [−r2, −r1] ∪ {0} ∪ [r1, r2] (2.16)<br />
Dobbiamo sottolineare che M ⊆ I, in quanto I un insieme definito nel<br />
continuo, mentre M è definito nel discreto.<br />
Si rende necessario quindi definire una funzione:<br />
fl : I → M (2.17)<br />
che prende in input un numero reale x ∈ R e restituisce in output fl(x) ∈ M.<br />
In generale nell’applicazione della funzione fl si genera un errore di rappresentazione<br />
dovuto al fatto che quasi sempre fl(x) = x. Dato un generico elemento<br />
positivo di I<br />
x = (α1α2 · · ·αmαm+1 · · · )b e−ν<br />
Elenchiamo di seguito le due possibili rappresentazioni:<br />
• Rappresentazione per troncamento<br />
fl(x) = (α1α2 · · · αm)b e−ν<br />
(2.18)<br />
Questo vuol dire che abbiamo troncato la mantissa di x alla sua m-esima<br />
cifa significativa.<br />
• Rappresentazione per arrotondamento<br />
con<br />
fl(x) = (α1α2 · · · αm−1˜αm)b e−ν<br />
˜αm =<br />
αm, se αm+1 < b/2<br />
αm + 1, se αm+1 ≥ b/2<br />
(2.19)<br />
(2.20)<br />
Nel caso in cui ˜αm ≥ b ci sarà evidentemente un riporto sulle cifre precedenti<br />
la m-esima.<br />
Definiamo quindi due casi particolari per la funzione fl(x):<br />
• fl(0) = 0<br />
• fl(x) = −fl(−x), se x ∈ I, x < 0<br />
Definizione 3. Il numero u viene definito precisione di macchina<br />
<br />
1−m b , in caso di troncamento<br />
u =<br />
1/2 · b1−m , in caso di arrotondamento<br />
Teorema 4. Se x ∈ I e x = 0 allora:<br />
fl(x) = x · (1 + ǫx)<br />
10
2.3.3 Overflow e underflow<br />
Quando si vuole rappresentare numeri non contenuti in I (vedi 2.16), si può<br />
incorrere in condizioni d’errore. Due casi particolari si hanno quando:<br />
• |x| > r2. In questo caso si verifica una condizione di overflow.<br />
• 0 < |x| < r1. In questo caso invece si verifica una condizione di underflow.<br />
Nella prossima sezione verranno illustrati i metodi di recovery secondo lo standard<br />
IEEE 754 delle situazioni sopracitate.<br />
2.3.4 Lo standard IEEE 754<br />
Circa 40 anni fa l’anarchia minacciava l’aritmetica in virgola mobile.Oltre una<br />
dozzina di aritmetiche proprietarie, vantavano diverse wordsize 1 , precisioni,<br />
procedure di arrotondamento, e diversi comportamenti in caso di owerflow e<br />
underflow. Sviluppare codice portabile divenne molto presto economicamente<br />
costoso, visto la diversità di aritmetica mobile nelle svariate architetture. Circa<br />
30 anni fa, quando lo standard divenne ufficiale, la maggior parte dei produttori<br />
di microprocessori adottò questa architettura, malgrado la sfida lanciata dagli<br />
implementatori.Con un altruismo inaspettato, gli hardware designers uscirono<br />
dalla competizione per la progettazione della miglior aritmetica, con la speranza<br />
di incoraggiare e facilitare un più massiccio sviluppo di software numerico.<br />
Appunto fu creato lo standard ANSI/IEEE Std 754-1985. Questo standard<br />
fu definito per fare in modo che lo stesso software, potesse essere eseguito su<br />
più piattaforme, solamente ricompilando il codice sorgente, e con il requisito<br />
di dare lo stesso risultato se eseguito su piattaforme differenti. Lo standard in<br />
questione definisce tre tipi di formati per i numeri in virgola mobile: single,<br />
double, double extended. Affinché una macchina possa vantare di rispettare lo<br />
standard, deve implementare correttamente i numeri in virgola mobile in singola<br />
e doppia precisione. La doppia precisione estesa, infatti, opzionale, e non tutte<br />
le piattaforme e linguaggi la implementano. La mantissa memorizzata in forma<br />
binaira (base 2):<br />
. 1.f se il numero normalizzato ovvero se la prima cifra 1.<br />
. 0.f se il numero denormalizzato.<br />
Siccome la cifra della parte intera è sempre nota a priori, è possibile ometterla,<br />
risparmiando così 1 bit per la sua memorizzazione esplicita.<br />
Di seguito vengono mostrate più in dettaglio le due forme per i numeri in<br />
virgola mobile.<br />
• Singola precisione<br />
1 8 23 lunghezza in bit<br />
+-+--------+-----------------------+<br />
|s| e | f |<br />
+-+--------+-----------------------+<br />
32 31 23 0 indice dei bit<br />
1 lunghezza di un istruzione<br />
11
Come si può vedere dalla rappresentazione ascii, la singola precisione memorizza<br />
un numero in virgola mobile usando 32 bit, dei quali uno usato<br />
per il segno (e), otto per l’esponente (s) e i restanti ventitre per la mantissa<br />
(f ). Con riferimento alla notazione usata in (2.9)-(2.12) sono da<br />
considerare i seguenti casi:<br />
. se 0 < e < 255, la mantissa è normalizzata e ν = 127;<br />
. se e = 0 e f = 0, la mantissa è denormalizzata e ν = 126;<br />
. se e = f = 0, si ha zero (negativo o positivo);<br />
. se e = 255, α0 = 0, f = 0, si ha +inf;<br />
. se e = 255, α0 = 1, f = 0, si ha -inf;<br />
. se e = 255, f = 0, si ha un Nan (Not a Number);<br />
IEEE 754 definisce che le seguenti operazioni diano come risultato Nan:<br />
– √ numero negativo, radice di un numero negativo;<br />
– 0 ∗ ∞ zero moltiplicato infinito;<br />
– 0.0/0.0 zero diviso zero;<br />
– ∞/∞ infinito diviso infinito;<br />
– numero%0.0 resto della divisione di un numero per zero (operazione<br />
modulo);<br />
– ∞%numero resto della divisione di infinito per un numero;<br />
– ∞ − ∞ infinito meno infinito (n.b. ∞ + ∞ = ∞);<br />
• Doppia precisione<br />
1 11 52 lunghezza in bit<br />
+-+-----------+----------------------------------------------------+<br />
|s| e | f |<br />
+-+-----------+----------------------------------------------------+<br />
64 63 52 0 indice dei bit<br />
. se 0 < e < 2047, la mantissa normalizzata e ν = 1023;<br />
. se e = 0 e f = 0, la mantissa denormalizzata e ν = 1022;<br />
. se e = f = 0, si ha zero (negativo o positivo);<br />
. se e = 2047, α0 = 0, f = 0, si ha +inf;<br />
. se e = 2047, α0 = 1, f = 0, si ha -inf;<br />
. se e = 2047, f = 0, si ha un Nan (Not a Number);<br />
Esempio 6. Calcoliamo con l’aiuto di matlab i seguenti numeri in doppia<br />
precisione:<br />
. il più grande numero di macchina<br />
12
help realmax<br />
REALMAX Largest positive floating point number.<br />
x = realmax is the largest double precision floating point number<br />
representable on this computer. Anything larger overflows.<br />
>> REALMAX(’double’)<br />
ans = 1.797693134862316e+308<br />
. il più piccolo numero di macchina normalizzato positivo<br />
>> help realmin<br />
REALMIN Smallest positive floating point number.<br />
x = realmin is the smallest positive normalized double precision floating<br />
point number on this computer. Anything smaller underflows or is an IEEE<br />
"denormal".<br />
>> REALMIN(’double’)<br />
ans = 2.225073858507201e-308<br />
. il più piccolo numero di macchina denormalizzato positivo.<br />
Per calcolare questo numero non vi è una funzione precisa. Però dalla definizione<br />
di numero denormalizzato (2.12), possiamo ricavarlo facilemte.<br />
Infatti il più piccolo numero denormalizzato è quello con mantissa composta<br />
da tutti zeri tranne il primo bit settato a 1, esponente settato a zero, e<br />
ν settato a 1022. Quindi basta calcolare la formula 2 1−53 2 − 1022, ottenuta<br />
dalla 2.12 sostituendo i valori di m, i, e ν. Ecco il risultato ottenuto:<br />
>> (2^-52)*(2^-1022)<br />
ans = 4.9407e-324<br />
. la precisione di macchina<br />
>> help eps<br />
eps returns the distance from 1.0 to the next largest double-precision number,<br />
that is eps = 2^(-52).<br />
>> eps<br />
ans = 2.220446049250313e-016<br />
2.3.5 Aritmetica finita<br />
Quando effettuiamo delle operazioni matematiche, sappiamo che valgono determinate<br />
proprietà. In particolare se condideriamo la somma, sappiamo che gode<br />
delle proprietà commutativa e associativa. Essa viene preservata nel caso di<br />
numeri interi. Ciò non accade con i numeri in virgola mobile. Infatti quando<br />
13
sommiamo due nuemri, x e y, in aritmetica finita, x ⊕ y, devono prima essere<br />
convertiti in numeri di macchina, dopodiché si esegue la somma e si rappresenta<br />
il risultato come numero di macchina; Con riferimento alla funzione 2.17,<br />
possiamo scrivere:<br />
x ⊕ y = fl(fl(x) + fl(y)), x, y ∈ R<br />
Mostriamo un semplice esempio tratto da [4]:<br />
Esempio 7. In aritmetica esatta, il valore di e è banale:<br />
a = 4/3<br />
b = a − 1<br />
c = b + b + b<br />
e = 1 − c<br />
Infatti esso è zero. Se in matlab eseguiamo queste righe di codice,<br />
a=4/3;<br />
b=a-1;<br />
c=b+b+b;<br />
e=1-c<br />
il risultato sarà:<br />
e =2.220446049250313e-016<br />
Ancora un altro esercizio sulla rappresentazione dei numeri in virgola mobile<br />
in aritmetica finita:<br />
Esempio 8. x=0;<br />
delta=0.1;<br />
while x ~= 1<br />
x = x+delta;<br />
end<br />
Il risultato è che il ciclo è infinito, perché la condizione non è mai vera.<br />
Cosideriamo questa istruzione t = 0.1. Il valore di t non è esattamente 0.1,<br />
perché la frazione 1<br />
10 ,per essere espressa in aritmetica finita , richiede una serie<br />
infinita. Infatti:<br />
1 1 1 0 0 1 1 0 0 1<br />
= + + + + + + + + + · · ·<br />
10 24 25 26 27 28 29 210 211 212 Dopo il primo termine, la sequenza di coefficienti 1,0,0,1, si ripete all’infinito.<br />
Il numero reale 0.1, ottenuto dal’arrotondamento della suddetta serie al 53◦ termine, incluso l’arrotondamento degli ultimi quattro coefficienti, in binario<br />
1010. Se raggruppiamo i termini della serie descritta a gruppi di 4, possiamo<br />
riscriverla in base 16, ovvero esadecimale, ne seguente modo:<br />
t = (1 + 9 9 9 9 9<br />
+ + + · · · + + ) ∗ 2−4<br />
16 162 163 1612 1613 Il comando Matlab, format hex, ci può far vedere il contenuto di t in fomra<br />
esadecimale che è 3fb999999999999a. I primi tre caratteri 3fb si riferiscono<br />
all’esponente polarizzato e + 1023, dove e = −4. Gli altri tredici caratteri sono<br />
la rappresentazione della frazione f. Concludendo, il valore memorizzato in t,<br />
si avvicina molto a 0.1, ma non è esattamente 0.1.<br />
14
2.3.6 Condizionamento del problema<br />
Dato un problema espresso tramite relazioni tra valori numerici, il condizionamento<br />
è un valore che quantifica di quanto viene amplificato l’errore in ogni computazione<br />
tra gli errori sui dati in ingresso e quelli sui dati in uscita. Possiamo<br />
formalizzare il problema come una funzione:<br />
dove<br />
x rappresenta i parametri di input<br />
f rappresenta la descrizione del problema<br />
y rappresenta i dati di output<br />
y = f(x) (2.21)<br />
Senza perdita di generalità possiamo assumere che x, y ∈ R e f : R → R con<br />
f ∈ C 2 Quindi possiamo formalizzare il problema matematico come<br />
dove<br />
˜x = ˜ f(˜x) (2.22)<br />
˜x rappresenta i dati di input perturbati, sia da errori di rappresentazione<br />
che da errori di misurazioni.<br />
˜f rappresenta il metodo numerico utilizzato per risolvere il problema, che<br />
può presentare errori di discretizzazione o convergenza oppure entrambi.<br />
˜y rappresenta i dati di output perturbati in quanto sia i dati di input che<br />
la funzione risultano perturbati.<br />
Risulta interessante quindi studiare come le perturbazioni sui dati in input<br />
affliggono i risultati, supponendo di usare un metodo numerico esatto.<br />
˜y = f(˜x) (2.23)<br />
Ovvero vogliamo valutare la differenza ˜y − y in funzione della differenza ˜x − x.<br />
Se consideriamo gli errori relativi possiamo riscrivere le due differenze in questo<br />
modo:<br />
˜x = x(1 + ǫx), ˜y = y(1 + ǫy) (2.24)<br />
Sviluppando il secondo membro in x delle 2.24, otteniamo<br />
y + yǫy = f(x) + f ′ (x)xǫx + O(ǫ 2 x ) (2.25)<br />
Tenendo conto della 2.21 possiamo sostituire ottenendo<br />
yǫy = f ′ (x)xǫx + O(ǫ 2 x )<br />
Se poi consideriamo uno studio al primo ordine si ottiene che:<br />
<br />
<br />
|ǫy| ≈ <br />
f ′ (x) x<br />
<br />
<br />
<br />
y ∗ |ǫx| ≡ k |ǫx| (2.26)<br />
K il fattore di amplificazione, che misura quanto gli errori sui dati in ingresso<br />
influiscano sui dati in uscita. Ci sono due casi interessanti:<br />
15
. K ≈ 1 gli errori sui dati in ingresso influiscono pochissimo sui dati in<br />
uscita. In questo caso il problema è ‘ben condizionato’<br />
. K >> 1 gli errori sui dati in uscita sono molto più grandi che sui dati in<br />
ingresso. Quindi anche un piccolissimo errore sui dati di input, dovuto sia<br />
all’imprecisione nella misurazione, che nella rappresentazione in aritmetica<br />
finita, causa un grande errore sui dati di output. In questo caso il problema<br />
si dice ‘mal condizionato’.<br />
Osserviamo il condizionamento delle operazioni aritmetiche fondamentali<br />
Somma<br />
Studiamo il condizionamento della somma di due variabili x1, x2 ∈ R tali che<br />
x1 + x2 = 0:<br />
y = x1 + x2<br />
(2.27)<br />
Considerando gli errori relativi per ognuna delle variabili in gioco, otteniamo:<br />
˜x1 = x1 ∗ (1 + ǫ1)<br />
˜x2 = x2 ∗ (1 + ǫ2)<br />
˜y = y ∗ (1 + ǫy)<br />
Combinando le tre equazioni otteniamo:<br />
y(1 + ǫy) = x1(1 + ǫ1) + x2(1 + ǫ2) = x1 + x2 + x1ǫ1 + x2ǫ2<br />
Considerando la 2.27, riusciamo a trovare la stima che stavamo cercando:<br />
(2.28)<br />
|ǫy| ≤ |x1| + |x2|<br />
|x1 + x2| ǫx ≡ kǫx, ǫx = max {|ǫ1| , |ǫ2|} (2.29)<br />
Ci sono anche in questo caso due casi interessanti:<br />
• x1x2 > 0:se le due variabili hanno segno concorde la somma è ben condizionata,<br />
infatti k = 1.<br />
• x1 ≈ −x2: in questo caso il numero di condizionamento può assumere valori<br />
arbitrariamente grandi. Infatti nella 2.29 il numeratore diventa ‘grande’,<br />
mentre il denominatore diventa ‘piccolo’. Questa situazione porta<br />
fenomeno della cancellazione numerica.<br />
Esempio 9. Vediamo adesso un esempio di cancellazione numerica, ipotizzando<br />
di utilizzare una rappresentazione decimale con arrotondamento<br />
alla quarta cifra significativa.<br />
y =<br />
<br />
0.12345678<br />
<br />
− 0.12341234<br />
<br />
= 0.00004444 = 4.4 ∗ 10 −5<br />
x1<br />
x2<br />
Calcoliamo adesso la rappresentazione in aritmetica finita con arrotondamento<br />
alla quarta cifra decimale:<br />
fl(x1) = 1.235 ∗ 10 −1<br />
fl(x2) = 1.234 ∗ 10 −1<br />
16
Vediamo l’errore relativo sui dati in ingresso:<br />
ǫx1 = fl(x1) − x1<br />
x1<br />
ǫx2 = fl(x2) − x2<br />
x2<br />
≈ 3.5 ∗ 10 −4<br />
≈ 1.0 ∗ 10 −4<br />
Il risultato afflitto da errori di rappresentazione :<br />
˜y = fl(fl(x1) − fl(x2)) = fl(0.001 ∗ 10 −1 ) = fl(1.0 ∗ 10 −4 ) = 1.000 ∗ 10 −4<br />
Calcoliamo adesso l’errore relativo sul risultato<br />
ǫy =<br />
˜y − y<br />
y = 1.000 ∗ 10−4 − 4.444 ∗ 10−5 4.444 ∗ 10−5 = 1.25<br />
Vediamo adesso la costante k del condizionamento del problema, con i<br />
valori ottenuti<br />
k = |x1| + |x2|<br />
|x1 − x2| = 1.2345678 ∗ 10−1 + 1.2341234 ∗ 10−1 4.444 ∗ 10−5 ≈ 5.5 ∗ 10 3<br />
Abbiamo visto in questo esempio come gli errori relativi sui dati in ingresso<br />
fossero nella norma, ma l’errore relativo sui dati in uscita era abbastanza<br />
alto. Tutto questo in accordo con la costante di condizionamento k che<br />
in questo caso aveva un valore molto elevato 5500. Tenendo conto della<br />
definizione 2.26 abbiamo che<br />
k ∗ min {ǫx1, ǫx2} < ǫy < k ∗ max {ǫx1, ǫx2}<br />
e sostituendo i valori otteniamo<br />
5.5 ∗ 10 3 ∗ 1.0 ∗ 10 −4 < 1.25 < 5.5 ∗ 10 3 ∗ 3.5 ∗ 10 −4 ⇒ 0.55 < 1.25 < 1.925<br />
Moltiplicazione<br />
Studiamo il condizionamento della moltiplicazione di due variabili x1, x2 ∈ R<br />
tali che x1x2 = 0:<br />
y = x1 ∗ x2<br />
(2.30)<br />
Considerando gli errori relativi, otteniammo la seguente espressione:<br />
y(1 + ǫy) = x1(1 + ǫ1)x2(1 + ǫ2) = x1x2(1 + ǫ1 + ǫ2 + ǫ1ǫ2) (2.31)<br />
Trascurando il membro quadratico ǫ1ǫ2, e considerando la 2.30, otteniamo,<br />
|ǫy| ≈ |ǫ1 + ǫ2| ≤ 2ǫx, doveǫx = max {|ǫ1|,|ǫ2|} (2.32)<br />
Perciò il numero di condizionamento k = 2. La moltiplicazione in ogni caso<br />
è un operazione sempre ben condizionata, perché l’errore sui dati in ingresso<br />
amplifica di un fattore 2 l’errore sui dati in uscita.<br />
17
Divisione<br />
Studiamo il condizionamento della divisione di due variabili x1, x2 ∈ R tali che<br />
x1x2 = 0:<br />
y = x1<br />
x2<br />
(2.33)<br />
Analogamente a come abbiamo fatto per lo studio del condizionamento della<br />
moltiplicazione, otteniamo,<br />
y(1 + ǫy) = x1(1 + ǫ1)<br />
x2(1 + ǫ2)<br />
≈ x1<br />
x2<br />
(1 + ǫ1)(1 − ǫ2) = x1<br />
(1 + ǫ1 − ǫ2 − ǫ1ǫ2) (2.34)<br />
Trascurando quindi il termine quadratico ǫ1ǫ2 e tenendo conto della 2.33, otteniamo,<br />
|ǫy| ≈ |ǫ1 − ǫ2| ≤ 2ǫx, dove ǫx = max {|ǫ1| , |ǫ2|} (2.35)<br />
Come per la moltiplicazione, il numero di condizionamento della divisione k = 2.<br />
Esempio 10. Dimostriamo che il numero di condizionamento del problema del<br />
calcolo di y = √ x è k = 1/2.<br />
In questo caso la nostra funzione y = √ x = x 1<br />
2 = f(x). Applicando la<br />
definizione del numero di condizionamento 2.26<br />
<br />
1 1<br />
2x− 2x<br />
<br />
1<br />
k = =<br />
2<br />
1<br />
x− 2<br />
dove la derivata di f(x) è f ′ (x) = 1 1<br />
2x− 2. Come possiamo vedere l’operazione di<br />
radice ammette un buon numero di condizionamento.<br />
18<br />
x2
Capitolo 3<br />
Radici di un equazione<br />
In questo capitolo ci occuperemo di trovare uno zero della funzione f(x). Sia<br />
data la funzione f(x) : [a, b] ∈ R → R, si cerca di trovare un valore di x ∈ R<br />
tale che f(x) = 0. Generalmente la funzione può ammettere:<br />
• un numero finito di soluzioni, per esempio f(x) = (x − 1)(x − 2) 2 ;<br />
• non ammettere alcuna soluzione, per esempio f(x) = x 2 + 5x + 1;<br />
• ammettere un numero infinito di soluzioni, per esempio f(x) = cos(x);<br />
Tuttavia per il nostro problema, prenderemo in considerazione solo il caso<br />
in cui f(x) ammetta almeno una radice reale. Consideriamo quindi nelle nostre<br />
ipotesi che f(a) · f(b) < 0. Essendo la funzione continua in tutto l’intervallo<br />
[a, b], avrà sicuramente uno zero in un punto sia esso x ∗ . Andiamo quindi a<br />
presentare nelle seguenti sezioni due metodi con diversi criteri di convergenza.<br />
3.1 Il metodo di bisezione<br />
Prima di mostrare questo metodo, dobbiamo fare alcune assunzioni sulle funzioni<br />
che andiamo a considerare per il nostro problema. In particolare la funzione<br />
f(x) deve soddisfare le seguenti ipotesi.<br />
• f(x) : [a, b] ∈ R → R<br />
• f continua ∀x ∈ [a, b]<br />
• f(a) · f(b) < 0<br />
Definizione 4. [a, b] si definisce un intervallo di confidenza della funzione f(x)<br />
per la radice se ∃x ∈ [a, b] tale che f(x) = 0.<br />
Di seguito descriviamo i passi che devono essere eseguiti per la corretta<br />
applicazione del metodo di bisezione:<br />
Calcoliamo una prima approssimazione della radice<br />
x ∗ ≈ x1 =<br />
19<br />
a + b<br />
2
• se f(x1) = 0 ⇒ x ∗ = x1<br />
• se f(a) · f(x1) < 0 ⇒ [a, x1]<br />
• se f(b) · f(x1) < 0 ⇒ [x1, b]<br />
Questo è il primo passo. Poi si riapplica il procedimento al nuovo intervallo di<br />
confidenza individuato. Il metodo converge alla soluzione. Si vede chiaramente<br />
infatti che ad ogni iterazione, l’intervallo di confidenza si dimezza, e che l’n −<br />
esimo intervallo di confidenza ha dimensione b−a<br />
2n . Per n → ∞ questo intervallo<br />
tende ad avere dimensione zero, e siccome è un intervallo di confidenza, esso<br />
sarà la radice della funzione. Vediamo una prima implementazione in Matlab<br />
dell’algoritmo di bisezione:<br />
Algoritmo 3.1 (Metodo di bisezione, implementazione basilare).<br />
fa=feval(f,a);<br />
fb=feval(f,b);<br />
x=(a+b)/2;<br />
fx=feval(f,x);<br />
while fx~=0<br />
if fa*fx
|x ∗ b − a<br />
− x1| ≤<br />
2<br />
Quindi il nostro errore nell’approssimare x ∗ con x1 è maggiorato da b−a<br />
2 ,<br />
ovvero la metà dell’intervallo di confidenza iniziale. Sia [ai, bi] l’intervallo di<br />
confidenza dell’i-esima iterazione dell’algoritmo di bisezione. Abbiamo allora<br />
che<br />
|x ∗ − xi| < bi − ai<br />
2<br />
= bi−1 − ai−1<br />
2 2<br />
Il nostro criterio d’arresto sarà<br />
= bi−2 − ai−2<br />
2 3<br />
= . . . = b1 − a1<br />
2 i<br />
b − a<br />
≤ tolx<br />
2i dove tolx rappresenta la tolleranza desiderata. Con qualche semplice passaggio<br />
abbiamo quindi che<br />
b − a<br />
≤ 2i<br />
tolx<br />
Quindi i sarà il numero massimo di iterazioni, per ottenere la tolleranza<br />
richiesta<br />
imax = ⌈log 2(b − a) − log 2(tolx)⌉<br />
Una volta introdotto il concetto di tolleranza, possiamo modificare l’algoritmo<br />
3.5 per ricavarne uno con un criterio d’arresto più efficace. Prima però<br />
dobbiamo risolvere il problema della condizione f(xi) = 0, che difficilmente si<br />
verifica in aritmetica finita. Siccome per ipotesi la funzione è continua nell’intervallo<br />
[a, b], abbiamo che in un intorno di x, sia esso [x − tolx, x + tolx], si<br />
verifica la condizione che |f(xi) − f(x ∗ )| ≤ tolf. Per definizione f(x ∗ ) = 0,<br />
quindi il nuovo criterio d’arresto diventa |f(xi)| ≤ tolf , ovvero<br />
abs(fx)
• f ′ (x ∗ ) ≈ 0 in questo caso, la situazione è favorevole, perché fissato tolf il<br />
criterio d’arresto sarà molto lasco.<br />
• |f ′ (x ∗ )| ≫ 1 in quest’altro caso invece fissato tolx, tolf risulterà molto<br />
più grande.<br />
Per arrivare all’algoritmo finale del il metodo di bisezione, ci serve uno strumento<br />
per calcolare la derivata di un punto. Ebbene ci serviamo della seguente<br />
formula:<br />
f ′ (x ∗ ) ≈ f(bi) − f(ai)<br />
bi − ai<br />
(3.2)<br />
Questa, evidentemente è solo un approssimazione, ma è molto facile da calcolare,<br />
ed è tanto più precisa, quanto più la funzione è regolare e l’intervallo di<br />
confidenza è piccolo. In più, questa formula, ha il vantaggio di costare poco, dal<br />
punto di vista computazionale, perché f(bi)e f(ai) li abbiamo già calcolati.<br />
22
Algoritmo 3.2 (Metodo di bisezione, implementazione definitva).<br />
function[x,i]=bisezione(f,a,b,tolx)<br />
%BISEZIONE implementa il metodo per la ricerca<br />
%della radice di una funzione<br />
%INPUT<br />
% f funzione che contiene uno zero<br />
% a,b estremi dell’intervallo di confidenza<br />
% tolx tolleranza sul valore x tale che<br />
% f(x)=0<br />
%OUTPUT<br />
% x ascissa per la quale si verifica f(x)=0<br />
% i numero di iterazioni dell’algoritmo<br />
if tolx
Dalla 3.1, ricaviamo facilmente il fattore di amplificazione per il metodo di<br />
bisezione. Infatti f(x) può essere inteso come la perturbazione sui dati in ingresso<br />
(tenendo conto che il dato esatto in ingresso è f(x ∗ ) = 0), e |x − x ∗ | come<br />
la perturbazione sui dati in uscita. Di conseguenza il fattore di amplificazione<br />
per la radice di una funzione è:<br />
k =<br />
1<br />
|f ′ (x ∗ )|<br />
Definizione 5. (Molteplicità di una radice)<br />
x ∗ è una radice di molteplicità esatta m (m ∈ R) se<br />
f (0) (x ∗ ) = f (1) (x ∗ ) = . . . = f (m−1) (x ∗ ) = 0 e f (m) (x ∗ ) = 0<br />
La radice viene chiamata semplice se m = 1, multipla se m > 1.<br />
Teorema 5. Se x ∗ è una radice di molteplicità esatta m per f(x), allora<br />
si può scrivere così:<br />
f(x) = (x − x ∗ ) m · g(x)<br />
(3.3)<br />
f(x) = f(x ∗ )+f ′ (x ∗ )(x−x ∗ )+. . .+ f(m−1)<br />
(m − 1)! (x∗ )(x−x∗) m−1 + f(m)<br />
m! (ζx)(x−x ∗ ) m<br />
se la radice ha molteplicità m allora tutte le derivate fino alla m−esima si<br />
annullano.<br />
Quando viene usato un metodo iterativo, risulta interessante e addirittura<br />
necessario sapere se, man mano che iteriamo l’algoritmo, l’approssimazione<br />
converge alla soluzione, e con quale velocità converge. Per questo definiamo l’<br />
errore dell’i-esima iterazione come:<br />
ei = xi − x ∗<br />
Diremo perciò che il metodo numerico converge se<br />
(3.4)<br />
lim<br />
i→∞ ei = 0 (3.5)<br />
Definizione 6. (Ordine di convergenza)<br />
Un metodo iterativo ha ordine di convergenza p con costante asintotica c, se si<br />
verifica che<br />
Quando i ≫ 1 abbiamo che<br />
|ei+1|<br />
lim<br />
i→∞ |ei| p = c < ∞<br />
|ei+1| ≈ c · |ei|<br />
|ei+2| ≈ c · |ei+1| ≈ c 2 · |ei|<br />
|ei+k| ≈ c k · |ei|<br />
dove c k · |ei| → 0 per k → ∞ se e solo se 0 ≤ c < 1<br />
24
Esempio 11 (Bisezione - radice di funzione lineare). Consideriamo in questo<br />
esempio una funzione lineare nell’intervallo [−5, 5]. Nello specifico la funzione<br />
è<br />
f(x) = x + 1<br />
Il grafico risultante è la figura 3.1 Sono stati eseguiti dei test per valutare la<br />
6<br />
5<br />
4<br />
3<br />
2<br />
1<br />
0<br />
−1<br />
−2<br />
−3<br />
X: −1.004<br />
Y: −0.003636<br />
−4<br />
−5 −4 −3 −2 −1 0 1 2 3 4 5<br />
Figura 3.1: Grafico della funzione lineare y=x+1.<br />
Il valore nel riquadro solamente un indicazione della radice<br />
radice di questa funzione. In particolare è stato interessante vedere il numero<br />
di iterazioni, che l’algoritmo impiegava per trovare la radice, al variare della<br />
tolleranza richiesta<br />
tolx iterazioni f(xi)<br />
10 −1 5 −0.93750000000000<br />
10 −5 19 −1.00000381469727<br />
10 −10 35 −1.00000000005821<br />
Esempio 12 (Bisezione - radice di polinomio di terzo grado). Un altro esempio<br />
dell’applicazione del metodo di bisezione sulla seguente funzione<br />
f(x) = 1<br />
10 x3 + 3x 2 − 100<br />
considerata nell’intervallo [−30, 15]. Il grafico risultante è la figura 3.2 Come<br />
nell’esempio precedente sono stati effettuati dei test con diverse tolleranze. Di<br />
seguito vi è la tabella con i risultati ottenuti<br />
tolx iterazioni f(xi)<br />
10 −1 8 28.76953125000000<br />
10 −5 21 −28.79384279251099<br />
10 −10 21 −28.79384279251099<br />
25
1000<br />
800<br />
600<br />
400<br />
200<br />
0<br />
X: −28.79<br />
Y: 0.06525<br />
−200<br />
−30 −25 −20 −15 −10 −5 0 5 10 15<br />
Figura 3.2: Grafico della funzione cubica y = 1<br />
10 x3 + 3x 2 − 100.<br />
Il valore nel riquadro è solamente un indicazione della radice<br />
È interessante notare come il valore f(xi) non cambi portando la tolleranza da<br />
10 −5 a 10 −10 . In accordo con l’analisi sul condizionamento della radice, si nota<br />
come la derivata del polinomio di terzo grado nella sua radice, sia relativamente<br />
alta. Questo fa in modo che il vincolo sulla tolleranza sia meno stringente.<br />
Esempio 13 (Bisezione - radice della funzione trigonometrica coseno). L’ultimo<br />
esempio che viene proposto riguarda la funzione<br />
f(x) = cos(x)<br />
considerata nell’intervallo [0, 6]. Il grafico risultante è la figura 3.3<br />
Come nell’esempio precedente sono stati effettuati dei test con diverse tolleranze.<br />
Di seguito vi è la tabella con i risultati ottenuti<br />
tolx iterazioni f(xi)<br />
10 −1 6 1.59375000000000<br />
10 −5 18 1.57079315185547<br />
10 −10 34 1.57079632685054<br />
26
1<br />
0.8<br />
0.6<br />
0.4<br />
0.2<br />
0<br />
−0.2<br />
−0.4<br />
−0.6<br />
−0.8<br />
X: 1.57<br />
Y: 0.0006128<br />
−1<br />
0 1 2 3 4 5 6<br />
Figura 3.3: Grafico della funzione cubica y = cos(x).<br />
Il valore nel riquadro è solamente un indicazione della radice<br />
3.2 Metodo di Newton<br />
Il metodo di Newton-Raphson, anche conosciuto come metodo delle tangenti,<br />
si occupa di trovare la radice della funzione data. Per il suo scopo utilizza, appunto,<br />
delle tangenti a partire da un’approssimazione iniziale, x0. Per calcolare<br />
la successiva approssimazione, si eseguono i seguenti passi:<br />
• prendiamo l’intersezione della funzione f(x) con la retta x = x0<br />
• individuiamo un nuovo punto, sia esso P, sulla curva della funzione f(x),<br />
con coordinate (x0, f(x0))<br />
• tracciamo la retta tangente alla funzione f(x) nel punto P appena individuato<br />
• l’intersezione della retta tangente con l’asse delle ascisse sarà la nuova<br />
approssimazione della radice della funzione.<br />
Consideriamo l’equazione di una retta passante per un punto specificato:<br />
y − f(x0) = m · (x − x0) (3.6)<br />
Il coefficiente angolare nel nostro caso sarà il valore della derivata della<br />
funzione nel punto x0. Sostituendolo al posto del parametro m, otteniamo<br />
y − f(x0) = f ′ (x0) · (x − x0)<br />
A questo punto è facile trovare la nuova approssimazione della radice, perché<br />
basterà porre y = 0 nella precedente equazione per ottenere, con un pò di<br />
passaggi algebrici la formula<br />
27
x = x0 − f(x0)<br />
f ′ (x0)<br />
Iterando il procedimento troviamo la formula generale<br />
xi+1 = xi − f(xi)<br />
f ′ (xi)<br />
(3.7)<br />
Il metodo di newton però richiede che il punto di innesco, x0 sia vicino<br />
alla radice x ∗ . Più precisamente si richiede che la derivata della funzione f(x)<br />
non cambi il segno nell’intervallo [x0, x ∗ ], se x0 ≤ x ∗ , [x ∗ , x0] altrimenti. A<br />
differenza del metodo di bisezione, il metodo delle tangenti, richiede il calcolo<br />
sia della funzione, che della sua derivata. Quindi la funzione in esame deve essere<br />
non solo continua nell’intervallo che stiamo considerando, ma anche derivabile.<br />
Teorema 6. Se f(x) è regolare, il metodo di Newton converge quadraticamente<br />
verso radici semplici.<br />
Dim.: Sia x ∗ la radice verso la quale il metodo converge. Per ipotesi la<br />
funzione f(x) ∈ C 2 , quindi esiste ξi compreso tra x ∗ e xi per il quale vale:<br />
0 = f(x ∗ ) = f(xi) + f ′ (xi)(x ∗ − xi) + 1<br />
2 f ′′ (ξi)(x ∗ − xi) 2<br />
= f ′ (xi)<br />
<br />
f(xi)<br />
f ′ (xi) − xi + x ∗<br />
<br />
+ 1<br />
2 f ′′ (ξi)(x ∗ − xi) 2<br />
Considerando la 3.7 e che xi − x ∗ = ei, otteniamo<br />
ei+1<br />
e 2 i<br />
= f ′′ (ξi)<br />
2f ′ (xi)<br />
(3.8)<br />
Sono semplici passaggi algebrici ma risultano più chiari se visti nel seguente<br />
modo<br />
f ′ (xi)( f(xi)<br />
f ′ − xi +x<br />
(xi)<br />
<br />
∗<br />
) + 1<br />
−xi+1<br />
<br />
−ei+1<br />
2 f ′′ (ξi)(x ∗ − xi) 2<br />
<br />
(−ei) 2<br />
La 3.8 è ben definita, perché per ipotesi f ′ (x) = 0 Quindi nel caso in cui il<br />
metodo è convergente risulta che<br />
e1+1<br />
lim<br />
i→∞ e2 =<br />
i<br />
f ′′ (x∗ )<br />
2f ′ (x∗ )<br />
Dalla definizione 6 risulta evidente che l’ordine di convergenza è p = 2.<br />
3.2.1 Convergenza locale<br />
Abbiamo visto che il metodo di bisezione, converge globalmente sotto alcune<br />
ipotesi. Al contrario, per il metodo di Newton, la convergenza è garantita solo<br />
localmente ad determinato intorno. Al fine di provare sotto quale ipotesi, il<br />
28
suddetto metodo converge, dobbiamo considerare la funzione di iterazione Φ,<br />
che è caratteristica del metodo numerico:<br />
Φ(xi) = xi − f(xi)<br />
f ′ (xi)<br />
(3.9)<br />
Questa funzione deve godere di una proprietà fondamentale affinché il metodo<br />
iterativo converga:<br />
Enunciamo e dimostriamo il seguente teorema:<br />
x ∗ = Φ(x ∗ ) (3.10)<br />
Teorema 7 (del punto fisso). Sia Φ(x), la funzione di iterazione. Se esistono<br />
δ > 0 e 0 ≤ L < 1, tali che per ogni x, y ∈ (x ∗ − δ, x ∗ + δ) ≡ I e tali che<br />
|Φ(x) − Φ(y)| ≤ L · |x − y|<br />
allora:<br />
1 x ∗ è l’unico punto fisso di Φ in I.<br />
2 se x0 ∈ I allora xi ∈ I ∀i ≥ 0<br />
3 limi→∞xi = x ∗<br />
Dim:<br />
1 (per assurdo): Supponiamo che esista un altro punto fisso ¯x = Φ(¯x) ∈ I.<br />
Otteniamo che<br />
ovvero<br />
|x ∗ − ¯x| = |Φ(x ∗ ) − Φ(¯x)| ≤ L · |x ∗ − ¯x| < |x ∗ − ¯x|<br />
|x ∗ − ¯x| < |x ∗ − ¯x|<br />
che è impossibile.<br />
2 (per induzione): Dalle ipotesi sappiamo che x0 ∈ I. Questo implica che<br />
|x ∗ − x0| < δ Ricordando che 0 ≤ L < 1, abbiamo che:<br />
|x ∗ − x1| = Φ(x ∗ ) − Φ(x0) ≤ L · |x ∗ − x0| < L · δ < δ<br />
3: xi → x ∗ per i → ∞. Abbiamo che<br />
|xi − x ∗ | = |Φ(xi−1) − Φ(x ∗ )| ≤ L · |xi−1 − x ∗ |<br />
= L · |Φ(xi−2 − Φ(x ∗ )| ≤ L 2 · |xi−1 − x ∗ |<br />
= . . .L i · |x0 − x ∗ |<br />
se i → ∞ allora L i → 0. La tesi segue banalmente.<br />
29
3.2.2 Criterio d’arresto<br />
Come per il metodo di bisezione, è necessario definire un criterio d’arresto. Per<br />
questo condiseriamo la seguente espressione:<br />
<br />
<br />
<br />
<br />
|xi+1 − xi| = xi+1<br />
− x<br />
<br />
<br />
∗<br />
+x<br />
<br />
∗ <br />
<br />
<br />
<br />
− xi<br />
= |ei − ei+1|<br />
<br />
<br />
−ei+1<br />
Quando il metodo di Newton converge quadraticamente, nelle vicinanze della<br />
radice, l’addendo ei+1, risulta essere poco significativo, quindi ha senso compiere<br />
questa approssimazione<br />
ei<br />
|ei − ei+1| ≈ |ei| ≤ tolx<br />
Quindi il controllo |ei| ≤ tolx lo implementeremo con |xi+1 − xi| ≤ tolx.<br />
Dall’espressione 3.7, ricaviamo che<br />
Allora il nuovo controllo diviene:<br />
|xi+1 − xi| = |f(xi)|<br />
|f ′ (xi)|<br />
|f(xi)| ≤ tolx · |f ′ (xi)| (3.11)<br />
Vediamo allora la prima implementazione dell’algoritmo del metodo di Newton<br />
30
Algoritmo 3.3 (Metodo di Newton).<br />
%NEWTON implementa il metodo delle tangenti<br />
%per la ricerca della radice di una funzione<br />
%INPUT<br />
% f funzione che contiene uno zero<br />
% df derivata della funzione f<br />
% x0 punto di partenza dell’algoritmo<br />
% toll tolleranza sul valore x tale che<br />
% f(x)=0<br />
%<br />
%OUTPUT<br />
% zero ascissa per la quale f(zero)=0<br />
% niter numero di iterazioni<br />
function [zero, niter]=newton(f,df,x0,toll,nmax)<br />
x = x0;<br />
fx = feval(f, x);<br />
fpx = feval(df, x);<br />
niter = 0;<br />
dif = toll+1;<br />
while dif > toll & niter
function f=dcubica2(x)<br />
f = (3/100).*x.^2;<br />
Ricordiamoci infatti che per applicare il metodo di newton serve anche specificare<br />
la derivata della funzione. Il grafico delle funzione cubica e della sua derivata<br />
è mostrato in figura 3.4<br />
Risulta interessante vedere come risponde il metodo di newton al variare del<br />
15<br />
10<br />
5<br />
0<br />
f(x)=x 3 /100 + 5<br />
D(f (x))=x 2 /100<br />
−5<br />
−10 −8 −6 −4 −2 0 2 4 6 8 10<br />
Figura 3.4: Grafico della funzione cubica e della sua derivata.<br />
punto di innesco e della tolleranza Ecco una tabella riassuntiva:<br />
radice iterazioni<br />
newton(’cubica2’,’dcubica2’,5,0.00001,100) -7.93700525984119 8<br />
newton(’cubica2’,’dcubica2’,-2,0.00001,100) -7.93700525984100 10<br />
newton(’cubica2’,’dcubica2’,-50,0.00001,100) -7.93700525984100 9<br />
newton(’cubica2’,’dcubica2’,-50,eps,100000) -7.93700525984100 100001<br />
newton(’cubica2’,’dcubica2’,-50,eps*10,100) -7.93700525984100 10<br />
È interessante notare come a parità di tolleranza (10 − 5) , ma con differente<br />
punto di innesco, le iterazioni varino di poco. Le ultime due righe della tabella<br />
invece, fanno notare come la radice −7.93700525984100 rientri sostanzialmente<br />
nella tolleranza della precisione di macchina.<br />
Esempio 15. Abbiamo visto che il metodo di newton converge alla radice della<br />
funzione solo sotto alcune ipotesi, una delle quali è che la derivata prima della<br />
funzione che ammette radice, non cambi di segno. Se la derivata prima cambia<br />
di segno infatti, si può avere un ciclo infinito. Questo comportamento viene<br />
evidenziato bene in figura 3.5<br />
Si vede benissimo infatti che l’intersezione delll’asse delle ascisse con la tangente<br />
alla funzione coseno nel punto x0, produce una nuova approssimazione<br />
x1. Ancora una volta vediamo che l’intersezione delll’asse delle ascisse con<br />
32
1<br />
0.8<br />
0.6<br />
0.4<br />
0.2<br />
0<br />
−0.2<br />
−0.4<br />
−0.6<br />
−0.8<br />
−1<br />
x 0<br />
( x 0 , f ( x 0 ) )<br />
( x 1 , f ( x 1 ) )<br />
3.5 4 4.5 5 5.5 6<br />
Figura 3.5: Grafico dell’applicazione del metodo di newton<br />
alla funzione coseno.<br />
la tangente alla funzione coseno nel punto x1, produce l’ approssimazione x0.<br />
Quindi in questo caso il metodo di newton non converge. Questo esempio è stato<br />
generato in matlab con il seguente listato dell’algoritmo 3.4.<br />
33<br />
x 1
Algoritmo 3.4.<br />
function[a]=esempio(tol,passo)<br />
%Esempio di come il metodo di newton non converga<br />
%in presenza di un cambio di segno della derivata<br />
%in due punti x0 e x1.<br />
format long e;<br />
ok=0;<br />
x0max=3.5468277953;<br />
for x0=3.546827795175:passo:x0max<br />
fx0=cos(x0);<br />
x1=x0-(fx0/-sin(x0));<br />
fx1=cos(x1);<br />
x01=x1-(fx1/-sin(x1));<br />
if abs(x0-x01)
y=[0:0.01:cos(x1)];<br />
plot(x1,y,’r--’);<br />
y=[0:-0.01:cos(x0)];<br />
plot(x0,y,’r--’);<br />
L’output invece è il seguente<br />
>> esempio(eps*10,eps)<br />
x0 3.5468277951774785000e+000<br />
x1 5.8779501655919013000e+000<br />
fx0 -9.1900972156043170000e-001<br />
fx1 9.1900972156043181000e-001<br />
f1x0 3.9423486867274654000e-001<br />
f1x1 3.9423486867274649000e-001<br />
ans =<br />
>><br />
3.546827795177479e+000<br />
3.2.3 Ancora sul criterio d’arresto<br />
Il criterio d’arresto 3.11, è un controllo sull’errore assoluto. Quando la radice<br />
della funzione ha un valore molto grande, risulta poco efficiente un controllo del<br />
genere. Per questo motivo vorremmo un controllo sull’errore assoluto quando la<br />
radice è vicino a zero, mentre vorremmo un controllo sull’errore relativo quando<br />
la radice è un numero molto grande<br />
<br />
∗ tolx, se x ≈ 0<br />
|xi+1 − xi| ≤<br />
rtolx · |xi+1| , se x∗ ≫ 1<br />
Quindi si preferisce utilizzare il seguente controllo:<br />
|ei|<br />
tolx + rtolx · |x∗ ≤ 1 (3.12)<br />
|<br />
Quando siamo molto vicini alla radice della funzione, ha senso approssimare<br />
x ∗ con xi+1 e |ei| con |xi+1 − xi|. Inoltre viene anche considerata l’uguaglianza<br />
rtolx = tolx. Per cui, sostituendo le varie approssimazioni e facendo qualche<br />
passaggio algebrico, otteniamo il nuovo criterio d’arresto:<br />
|xi+1 − xi|<br />
1 + |xi+1|<br />
≤ tolx (3.13)<br />
In questo modo quando x ∗ ≈ 0 si ha un controllo simile a |xi| ≤ tolx, mentre<br />
quando x ∗ ≫ 1, viene effettuato un controllo relativo.<br />
35
3.2.4 Radici multiple<br />
Se la funzione ammette più di una radice, il metodo di newton risulta malcondizionato,<br />
e il fattore p , detto ordine di convergenza (definizione 6), assume<br />
valore 1. È però possibile, attraverso alcune modifiche riportare la convergenza<br />
quadratica.<br />
• Molteplicità della radice nota Supponiamo, per semplicità, di avere<br />
una funzione siffatta:<br />
f(x) = (x − x ∗ ) m<br />
Se applichiamo il metodo di newton, abbiamo che<br />
x1 = x0 −<br />
(x0 − x ∗ ) m<br />
m · (x0 − x ∗ ) m−1 = x0 − 1<br />
m · (x0 − x ∗ )<br />
<br />
f(x 0 )<br />
f ′ (x 0 )<br />
Quindi, conoscendo la molteplicità esatta, é possibile ottenere la soluzione<br />
moltiplicando per il fattore m.<br />
xi+1 = xi − m · f(xi)<br />
f ′ , i = 0, 1, 2 . . .<br />
(xi)<br />
Con questa modifica si ripristina la convergenza quadratica verso una delle<br />
radici.<br />
• Molteplicità della radice non nota Siccome in questo caso, il metodo<br />
converge solo linearmente, abbiamo che ei ≈ c · ei−1 e ei+1 ≈ c · ei.<br />
dividendo membro a membro otteniamo che:<br />
e1<br />
ei+1<br />
≈ ei−1<br />
ei<br />
considerando l’equazione 3.4, con i seguenti passaggi arriviamo al risultato<br />
voluto:<br />
(xi−1 − x ∗ )(xi+1 − x ∗ ) ≈ (xi − x ∗ ) 2<br />
xi+1xi−1 − x ∗ (xi+1 + xi−1) + (x ∗ ) 2 ≈ x 2 i − 2xix ∗ + (x ∗ ) 2<br />
xi+1xi−1 − x 2 i ≈ x ∗ · (xi+1 + xi−1) − 2xix ∗<br />
xi+1xi−1 − x 2 i ≈ x∗ · (xi+1 + xi−1 − 2xi)<br />
x ∗ ≈ x ∗ i ≈<br />
xi+1xi−1 − x 2 i<br />
xi+1 + xi−1 − 2xi<br />
(3.14)<br />
A partire da un punto iniziale x0, si calcolano due approssimazioni, siano esse<br />
x (0)<br />
1 e x (0)<br />
2 . Con quest’ultime due approssimazioni, e x0, si può calcolare x (1)<br />
0 .<br />
È possibile reiterare il procedimento semplicemente ponendo x0 = x (1)<br />
0 .<br />
36
Algoritmo 3.5 (Metodo di Newton: accelerazione di Aitken).<br />
%AITKEN<br />
%function [x,passi]=Aitken(f,df,x0,epsilon,upper)<br />
%<br />
% Trova la radice della funzione f<br />
%INPUT<br />
% f funzione che contiene uno zero<br />
% df derivata della funzione f<br />
% x0 punto di partenza dell’algoritmo<br />
% toll tolleranza sul valore x tale che<br />
% f(x)==0<br />
% imax numero massimo di iterazioni<br />
%<br />
%OUTPUT<br />
% zero ascissa per la quale f(zero)=0<br />
% iterazioni numero di iterazioni<br />
function [x,iterazioni]=Aitken(f,df,x0,toll,imax)<br />
f0=feval(f,x0);<br />
d=feval(df,x0);<br />
x1=x0-(f0/d);<br />
f1=feval(f,x1);<br />
d=feval(df,x1);<br />
x2=x1-(f1/d);<br />
f2=feval(f,x2);<br />
i=0;<br />
while (iabs(toll*d)<br />
i=i+1;<br />
x0=(x1*x1-x0*x2)/(2*x1-x2-x0);<br />
f0=feval(f,x0);<br />
d=feval(df,x0);<br />
x1=x0-(f0/d);<br />
f1=feval(f,x1);<br />
d=feval(df,x1);<br />
x2=x1-(f1/d);<br />
f2=feval(f,x2);<br />
end<br />
x=x2;<br />
iterazioni=i+2;<br />
return<br />
Il metodo di accelerazione di aitken in sostanza ripristina la convergenza<br />
quadratica nel caso in cui la funzioni presenti radici multiple con molteplicità<br />
37
sconosciuta. Osserviamo che possiamo utilizzare lo stesso criterio d’arresto del<br />
metodo di newton 3.3 in quanto la convergenza non è più lineare ma quadratica<br />
Esempio 16. In questo esempio confrontiamo il metodo di Newton base, con<br />
quello dell’accelerazione di Aitken. La funzione in esame è la seguente:<br />
y = (x − 5) 5<br />
(3.15)<br />
I file pol5.m e dpol5.m, infatti rappresentano la precedente funzione e la sua<br />
derivata. Eccone il contenuto:<br />
function f = pol5(x)<br />
f=(x -5).^5;<br />
function f = dpol5(x)<br />
f=5.*(x-5).^4;<br />
Mostriamo il grafico delle due funzioni sopracitate: La cosa sorprendente è la<br />
5<br />
4<br />
3<br />
2<br />
1<br />
0<br />
−1<br />
4 4.2 4.4 4.6 4.8 5 5.2 5.4 5.6 5.8 6<br />
Figura 3.6: Grafico della funzione 3.15 e della sua derivata.<br />
differenza nel numero di iterazioni che i metodi, di Newton e Aitken, impiegano<br />
per trovare la radice con tolleranza 10 −14 . Di seguito mostriamo l’output delle<br />
prove effettuate:<br />
>> [radice,iterazioni]=newton(’pol5’,’dpol5’,6,10^-14,10000);<br />
>> radice<br />
radice =<br />
5.0000<br />
>> iterazioni<br />
38<br />
X: 5<br />
Y: 0<br />
(x−5) 5<br />
5⋅(x−5) 4
iterazioni =<br />
139<br />
>> [radice,iterazioni]=Aitken(’pol5’,’dpol5’,6,10^-14,10000);<br />
>> radice<br />
radice =<br />
5.0000<br />
>> iterazioni<br />
iterazioni =<br />
3<br />
3.3 Metodi quasi-Newton<br />
Ci sono alcune varianti del metodo di Newton, che risultano computazionalmente<br />
meno dispendiose, ma anche meno performanti. In generale lo schema<br />
da seguire è il seguente:<br />
xi+1 = xi − f(xi)<br />
, i = 0, 1, 2, . . ., ϕi ≈ f ′ (xi) (3.16)<br />
φi<br />
Con questa generalizzazione affrontiamo due metodi:<br />
• Metodo delle corde L’idea di base è quella di calcolare solo una volta<br />
la derivata della funzione. Infatti, localmente alla radice, la derivata<br />
prima della funzione, varierà di poco. Per questo la derivata convergerà<br />
alla radice della funzione con la stessa inclinazione. Si procede con<br />
l’approssimazione f ′ (xi) ≈ f ′ (x0) per definire il seguente metodo:<br />
xi+1 = xi − f(xi)<br />
f ′ , i = 0, 1, 2, . . . (3.17)<br />
(x0)<br />
Questo metodo valuta solo una volta la derivata prima e per questo richiede<br />
poche risorse. Ma se da un lato richiede poche risorse, dall’altro lato<br />
non offre grandi prestazioni. Infatti il metodo delle corde converge solo<br />
linearmente<br />
• Metodo delle secanti L’idea che è alla base di questo metodo, è di ottenere<br />
la successiva approssimazione della radice, a partire da una secante<br />
la curva. Praticamente i passi da seguire sono i seguenti:<br />
. Al primo passo si individuano due punti, x0 e x1.<br />
. Si valuta la secante della curva nei punti (f(x1), x1) e (f(x0), x0).<br />
39
. La prossima approssimazione è calcolata come l’intersezione della<br />
secante con l’asse delle ascisse.<br />
La funzione ϕ definita nello schema generale dei metodi quasi-newton<br />
nell’equazione 3.16, in questo caso risulta essere così fatta:<br />
f ′ (xi) ≈ f(xi) − f(xi−1)<br />
xi − xi−1<br />
Pertanto l’iterazione dell’algoritmo diviene<br />
≡ ϕi. (3.18)<br />
xi+1 = f(xi) · xi−1 − f(xi−1) · xi<br />
, i = 1, 2, . . . (3.19)<br />
f(xi) − f(xi−1)<br />
Come vedremo nell’algoritmo 3.7, per determinare il punto x1, viene usato<br />
un passo dell’algoritmo di Newton.<br />
40
Algoritmo 3.6 (Metodo delle corde).<br />
%CORDE<br />
%[x,passi]=corde(f,df,x0,toll,imax)<br />
% Trova la radice della funzione f<br />
%INPUT<br />
% f funzione che contiene uno zero<br />
% df derivata della funzione f<br />
% x0 punto di partenza dell’algoritmo<br />
% toll tolleranza sul valore x tale che<br />
% f(x)==0<br />
% imax numero massimo di iterazioni<br />
%<br />
%OUTPUT<br />
% zero ascissa per la quale f(zero)=0<br />
% iterazioni numero di iterazioni<br />
function [radice,iterazioni]=corde(f,df,x0,toll,imax)<br />
i=0;<br />
d=feval(df,x0);<br />
while(itoll)<br />
i=i+1;<br />
x0=x0-(feval(f,x0)/d);<br />
end<br />
radice=x0;<br />
iterazioni=i;<br />
return<br />
41
Algoritmo 3.7 (Metodo delle Secanti).<br />
%SECANTI<br />
%[x,passi]=secanti(f,df,x0,toll,imax)<br />
% Trova la radice della funzione f<br />
%INPUT<br />
% f funzione che contiene uno zero<br />
% df derivata della funzione f<br />
% x0 punto di partenza dell’algoritmo<br />
% toll tolleranza sul valore x tale che<br />
% f(x)==0<br />
% imax numero massimo di iterazioni<br />
%<br />
%OUTPUT<br />
% zero ascissa per la quale f(zero)=0<br />
% iterazioni numero di iterazioni<br />
function [radice,iterazioni]=secantiEsempio(f,df,x0,toll,imax)<br />
i=0;<br />
%<br />
while(itoll)<br />
i=i+1;<br />
x2=((fx1*x0)-(fx0*x1))/(fx1-fx0);<br />
fx2=feval(f,x2);<br />
fx1=feval(f,x1);<br />
x0=x1;<br />
fx0=fx1;<br />
x1=x2;<br />
fx1=fx2;<br />
end<br />
radice=x1;<br />
iterazioni=i;<br />
return<br />
Esempio 17 (Corde vs Secanti: due metodi quasi-Newton a confronto). Come<br />
si evince dal titolo, in questo esempio verranno messi a confronto il metodo delle<br />
secanti e quello delle corde. Il confronto sarà effettuato sulla medesima funzione<br />
e con lo stesso punto di innesco. la funione è la seguente:<br />
function f = iperbole(x)<br />
f=10./x -2;<br />
42
Di seguito mostriamo le chiamate dei due metodi, e il loro output<br />
>> [x,iterazioni]=cordeEsempio(’iperbole’,’diperbole’,1,10^-4,1000)<br />
x =<br />
4.9998<br />
iterazioni =<br />
>><br />
217<br />
>> [x,iterazioni]=secantiEsempio(’iperbole’,’diperbole’,1,10^-4,1000)<br />
x =<br />
5.0000<br />
iterazioni =<br />
>><br />
7<br />
Con un altro codice sono stati generati i rispettivi grafici, che ci fanno capire<br />
meglio come lavorano i due metodi.<br />
Dai due grafici 3.7 e 3.8, possiamo subito notare il modo in cui viene usata<br />
la retta per l’approssimazione della nuova radice. Infatti nel metodo delle corde,<br />
l’inclinazione della retta rimane la solita fino alla radice, mentre nel metodo<br />
delle secanti è adattiva. Dal punto di vista computazionale, osserviamo che il<br />
metodo delle corde impiega 217 iterazioni contro le 7 del metodo delle secanti.<br />
In realtà il confronto in questo caso è impari. Infatti se scegliessimo un punto<br />
d’innesco più vicino alla radice, potremmo vedere la differenza, tra i due metodi,<br />
assottigliarsi. Concludiamo facendo un analisi sulle operazioni impiegate:<br />
Corde: Vediamo nell’algoritmo 3.6, che c’è subito una valutazione di funzione,<br />
e poi per ogni iterazioni, l’algoritmo effettua due confronti, una moltiplicazione,<br />
due valutazioni di funzione, e due somme. Se utiliziamo la<br />
seguente legenda, C = confronti, M = moltiplicazione o divisione,<br />
V = valutazione i funzione, S = somma o sottrazione, possiamo esprimere<br />
il costo dell’algoritmo in forma parametrica. Alla luce di questa<br />
analisi l’algoritmo delle corde ha un costo di:<br />
Costo(i, C, M, V, S) = V + i · (2C + M + 2V + 2S) (3.20)<br />
Secanti: A differenza del metodo delle corde, ci sono più costi fissi, ovvero più<br />
operazioni che non dipendono dal numero di iterazioni. Abbiamo inoltre<br />
43
8<br />
7<br />
6<br />
5<br />
4<br />
3<br />
2<br />
1<br />
0<br />
−1<br />
0.5 1 1.5 2 2.5 3 3.5 4 4.5 5<br />
Figura 3.7: Grafico della funzione 18 e dell’applicazione del metodo delle corde.<br />
due moltiplicazioni e/o divisioni e una somma e/o sottrazione in più del<br />
metodo delle corde.<br />
Costo(i, C, M, V, S) = 3V + M + S + i · (2C + 3M + 2V + 3S) (3.21)<br />
Nel nostro caso, se sostituiamo i valori di i che sono le iterazioni compiute,<br />
troviamo quante operazioni sono state fatte.<br />
C M V S<br />
corde 534 217 535 534<br />
secanti 14 22 17 21<br />
Il vero vantaggio, nell’usare il metodo delle corde piuttosto che quello delle secanti,<br />
risiede nel fatto che il punto di innesco deve essere molto vicino alla radice.<br />
Tanto più il valore della derivata è costante nell’intervallo [x0, x ∗ ], tanto più<br />
risulterà conveniente il metodo delle corde.<br />
44
8<br />
7<br />
6<br />
5<br />
4<br />
3<br />
2<br />
1<br />
0<br />
−1<br />
0.5 1 1.5 2 2.5 3 3.5 4 4.5 5<br />
Figura 3.8: Grafico della funzione 18 e dell’applicazione del metodo delle secanti.<br />
45
Capitolo 4<br />
Sistemi lineari<br />
Un sistema lineare di m equazioni in n incognite è un insieme di relazioni<br />
algebriche nella forma<br />
n<br />
aijxj = bi, i = 1, . . .,m (4.1)<br />
j=1<br />
dove xj sono le incognite, aij i coefficienti del sistema e bi i termini noti. D’ora<br />
in poi faremo riferimento al sistema 4.1 con la seguente notazione in forma<br />
matriciale:<br />
Ax = b (4.2)<br />
dove A = (aij) ∈ R mxn la matrice dei coefficienti, b = (bi) ∈ R m il vettore dei<br />
termini noti, e con x = (xi) ∈ R n il vettore incognito. La soluzione del sistema<br />
4.2 è una qualsiasi n-pla di valori che soddisfa l’equazione 4.1.<br />
Prenderemo in considerazione i casi in cui m ≥ n e che la matrice abbia<br />
rango massimo, ovvero rank(A) = n. Una soluzione del sistema può essere<br />
ottenuta tramite la regola di Cramer<br />
xj = ∆j<br />
, j = 1, . . .,n (4.3)<br />
det(A)<br />
dove ∆j è il determinante della matrice ottenuta sostituendo la j-esima colonna<br />
di A con il termine noto b. Tuttavia questo metodo risulta essere assai inefficiente,<br />
ed è per questo che andremo a considerare metodi alternativi alla regola<br />
di Cramer.<br />
4.1 Casi elementari<br />
A seconda delle proprietà che alcuni tipi particolari di matrici posseggono, possiamo<br />
definire metodi numerici studiati ad hoc per la loro risoluzione. Studieremo<br />
il caso di matrici diagonali, triangolari e ortogonali.<br />
4.1.1 Matrici diagonali<br />
Una matrice diagonale presenta la caratteristica di avere gli elementi<br />
46
aij se i = j<br />
aij =<br />
0 altrimenti<br />
Possiamo rappresentarle con un sistema grafico nel seguente modo:<br />
⎛ ⎞<br />
A =<br />
⎜<br />
⎝<br />
a11<br />
. ..<br />
ann<br />
⎟<br />
⎠<br />
Di conseguenza il sistema lineare equivale alla forma<br />
aiixi = bi, per i = 1, . . .,n<br />
la soluzione di suddetto sistema si otterrà calcolando<br />
xi = bi<br />
aii<br />
per i = 1, . . .,n (4.4)<br />
Essendo la matrice A non singolare, il rapporto dell’equazione 4.4 è sempre ben<br />
definito. Il costo computazionale e in termini di occupazione di memoria, è<br />
lineare rispetto alla dimensione della matrice.<br />
47
Algoritmo 4.1 (Matrici diagonali).<br />
%function x=diagonale(A,B)<br />
%<br />
%Se A quadrata e B ha lo stesso numero<br />
%di righe delle colonne di B<br />
%allora questo algoritmo calcola la soluzione<br />
%dell’equazione Ax=B;<br />
%INPUT<br />
% A Matrice dei coefficienti<br />
% B Matrice dei termini noti<br />
%OUTPUT<br />
% x Matrice delle incognite<br />
function x=diagonale(A,B)<br />
[righeA,colonneA]=size(A);<br />
[righeB,colonneB]=size(B);<br />
if righeA==colonneA<br />
if colonneA==righeB<br />
for j = 1:n<br />
if A(i,i)==0<br />
error(’la matrice è singolare’)<br />
else<br />
x(i)=b(i)./A(i,i)<br />
end<br />
end<br />
else<br />
error(’Il numero di colonne della matrice A’)<br />
error(’non è uguale al numero di righe della matrice B’)<br />
end<br />
else<br />
error(’La matrice A non è quadrata’)<br />
end<br />
4.1.2 Matrici triangolari<br />
Con il termine triangolare si distinguono quelle matrici che godono di una delle<br />
seguenti proprietà:<br />
• Superiore: gli elementi aij con i > j sono tutti uguali a zero.<br />
⎛ ⎞<br />
a11 . . . a1n<br />
⎜<br />
A = ⎝<br />
. ..<br />
. ⎟<br />
. ⎠<br />
48<br />
ann
• Inferiore: gli elementi aij con i < j sono tutti uguali a zero<br />
A =<br />
⎛<br />
⎜<br />
⎝<br />
a11<br />
.<br />
. ..<br />
an1 . . . ann<br />
Analiziamo soltanto il caso in cui la matrice A risulti diagonale inferiore, in<br />
quanto l’altro caso è analogo. Otteniamo un sistema di equazioni nella seguente<br />
forma:<br />
a11x1 = b1<br />
⎞<br />
⎟<br />
⎠<br />
a21x1 +a22x2 = b2<br />
a31x3 +a32x3 +a33x3 = b3<br />
.<br />
. ..<br />
an1xn +an2xn + . . . +annxn = bn<br />
Questo sistema può essere risolto con sostituzioni successive nel seguente modo:<br />
x1 = b1<br />
a11<br />
x2 = (b2 − a21x1)<br />
a22<br />
x3 = b3 − a31x1 − a32x2)<br />
.<br />
xn =<br />
a33<br />
<br />
bn − n−1 j=1 anjxj<br />
<br />
ann<br />
.<br />
.<br />
(4.5)<br />
Come per il metodo per la risoluzione delle matrici diagonali, essendo la matrice<br />
A non singolare, necessariamente aii sarà diverso da zero per ogni i = 1, . . .,n,<br />
quindi le divisioni nelle equazioni 4.5 sono ben definite.<br />
49
Algoritmo 4.2 (Matrici triangolari inferiori).<br />
% slts acronimo di Solve Lower Triangolar System<br />
%INPUT<br />
% A matrice dei coefficienti (triangolare superiore)<br />
% B vettore dei termini noti<br />
% flag se settato a uno controlla la struttura della matrice A<br />
%OUTPUT<br />
% x vettore delle incognite<br />
function [x]=slts(A,b)<br />
[m,n]=size(A);<br />
if(m~=n)<br />
error(’L matrice A non quadrata’);<br />
end<br />
for i=1:n<br />
for j=(i+1):n<br />
if A(i,j) ~=0<br />
error(’A non triangolare inferiore’);<br />
end<br />
end<br />
end<br />
if length(b) ~= n<br />
error(’B non e’’ compatibile’);<br />
end<br />
for i=1:n<br />
for j=1:i-1<br />
b(i)=b(i)-A(i,j)*x(j);<br />
end<br />
if A(i,i)==0<br />
error(’Il sistema triangolare inferiore presenta infinite soluzioni’);<br />
else<br />
x(i)=b(i)/A(i,i);<br />
end<br />
end<br />
50
Algoritmo 4.3 (Matrici triangolari superiori).<br />
%suts acronimo di Solve Upper Triangolar System<br />
%A una matrice triangolare superiore<br />
%x il vettore dei termini noti<br />
%i parametri di ritorno sono:<br />
% x il vettore delle inconite<br />
% t il tempo che l’algoritmo impiega per effettuare tale operazione<br />
function [x]=suts(A,b)<br />
[m,n]=size(A);<br />
if(m~=n)<br />
error(’L matrice A non quadrata’);<br />
end<br />
for i=1:n<br />
for j=1:i-1<br />
if A(i,j) ~=0<br />
error(’A non e’’ triangolare sup’);<br />
end<br />
end<br />
end<br />
if length(b) ~= n<br />
error(’B non e’’ compatibile’);<br />
end<br />
for i=n:-1:1<br />
for j=i+1:n<br />
b(i)=b(i)-A(i,j)*x(j);<br />
end<br />
if (A(i,i)==0)<br />
if(x(i)~=0)<br />
error(’Il sistema presenta infinite soluzioni’);<br />
else<br />
x(i)=0;<br />
end<br />
else<br />
x(i)=b(i)/A(i,i);<br />
end<br />
end<br />
4.1.3 Matrici ortogonali<br />
Una matrice A si dice ortogonale, se A −1 = A T , ovvero se A · A T = IA. Quindi<br />
nel caso che A sia una matrice ortogonale, l’equazione x = A −1 · b, diventa<br />
x = A T · b, e la soluzione viene trovata semplicemente effettuando una moltiplicazione<br />
tra la matrice dei coefficienti A trasposta e il vettore dei termini noti.<br />
51
Il costo computazionale per effettuare un prodotto matrice-vettore è dell’ordine<br />
di 2n 2 flop, mentre la memoria viene occupata per n 2 posizioni.<br />
4.2 Metodi di fattorizzazione<br />
Abbiamo visto fin qui, come trattare la fattorizzazione di matrici semplici, ovvero<br />
con determinate caratteristiche, in quanto risulta molto semplice ed efficiente,<br />
trovare la soluzione dell’equazione 4.2. Vorremmo trovare dei metodi che<br />
riescano a fattorizzare qualunque tipo (o quasi) di matrice nel seguente modo:<br />
A = F1F2 . . . Fk, (4.6)<br />
dove le Fi, sono matrici semplici (triangolari superiori o inferiori oppure ortogonali,<br />
non singolari). La soluzione dell’equazione 4.6, può essere calcolata<br />
risolvendo i seguenti sistemi lineari:<br />
F1x1 = b<br />
F2x2 = x1<br />
.<br />
Fkxk = xk−1<br />
x ≡ xk<br />
Come detto in precedenza, questi sistemi lineari sono efficientemente risolvibili,<br />
in più l’occupazione di memoria non ne risente, in quanto una volta calcolato il<br />
vettore xi, non abbiamo più bisogno dei precedenti.<br />
4.3 Fattorizzazione LU di una matrice<br />
La fattorizzazione LU, consite nella trasformazione della matrice A nel prodotto<br />
di due fattori, L e U, dove L è una matrice triangolare inferiore con diagonale<br />
unitaria, e U è una matrice triangolare superiore (L ed U stanno per lower e<br />
upper).<br />
Teorema 8. La somma e il prodotto di matrici triangolari inferiori (superiori)<br />
è una matrice triangolare inferiore (superiore).<br />
Dim. Essendo triangolari inferiori si ha che:<br />
L1 = (aij) e L2 = (bij) =⇒ aij, bij = 0 per j > i<br />
Somma : è banale verificare che L2 + L1 = (aij + bij) e aij + bij = 0 per j > i<br />
Prodotto : dobbiamo dimostrare che se L1 · L2 = (cij) allora cij = 0 quando j > i.<br />
se j > i allora<br />
⎛ ⎞<br />
cij : e T i (L1·L2)e i = (e T i ·L1)·(L2·e i ) = (ai1, ai2, . . .,aii, 0, . . .,0<br />
52<br />
b1j<br />
⎜b2j⎟<br />
⎜ ⎟<br />
⎜ . ⎟<br />
⎜ . ⎟<br />
)· ⎜<br />
⎜bjj<br />
⎟ = 0<br />
⎜<br />
n−i ⎜ 0 ⎟ <br />
⎜ ⎟<br />
⎝ . ⎠ j − i<br />
0
Praticamente vuol dire che non c’è alcun intersezione tra gli elementi nulli<br />
bij e aij.<br />
Teorema 9. La somma e il prodotto di matrici triangolari inferiori (superiori)<br />
a diagonale unitaria, è una matrice triangolare inferiore (superiore) a diagonale<br />
unitaria. La dimostrazione analoga alla precedente.<br />
Teorema 10. Se L è non singolare triangolare inferiore (superiore), allora L −1<br />
è triangolare inferiore (superiore). Consegue che L ·L −1 = I. Essendo L = (aij<br />
e L −1 = (bij), allora bii · aii = 1 =⇒ bii = 1/aii<br />
Teorema 11 (Unicità della fattorizzazione LU). Se A è non singolare e fatorizzabile<br />
LU allora i fattori L ed U sono univocamente determinati.<br />
Dim.(per assurdo) Dimostriamo che se esistessero due fattorizzazioni, allora<br />
queste sarebbero uguali. Infatti se A = L1U1 = L2U2 fossero due fattorizzazioni<br />
si avrebbe che<br />
0 = det(A) = det(L2U2) = det(L2)det(U2) = det(U2)<br />
Ricordiamoci infatti, che essendo L una matrice triangolare inferiore a diagonale<br />
unitaria, il suo determinante sarà 1. Quindi U2 è non singolare.<br />
L −1<br />
1 L2 = U1U −1<br />
2 ≡ D<br />
Siccome L −1<br />
1 L2 è triangolare inferiore e U1U −1<br />
2 è triangolare superiore, allora<br />
questi due prodotti devono assolutamente essere una matrice diagonale.<br />
Essendo L −1<br />
1 L2 a diagonale unitaria, lo sarà anche D. Quindi se D è una<br />
matrice diagonale con elementi uguali a uno, questa corrisponde proprio alla<br />
matrice identità, cioè D = I. Allora abbiamo che:<br />
L −1<br />
1 L2 = D = I =⇒ L2 = L1I = L1 e U1U −1<br />
2 = D = I =⇒ U1 = U2I = U2<br />
Sappiamo dell’unicità della fattorizzazione, ma non dell’esistenza. Vediamo<br />
allora un metodo che ci consente, se possibile, di trovare la fattorizzazione di una<br />
matrice. In generale attraverso una procedura semi-iterativa, trasformeremo,<br />
tramite n − 1 moltiplicazioni a sinistra con L i , la matrice A nella matrice U.<br />
I fattori L i , moltiplicati tra loro, non sono altro che L −1 . Infatti abbiamo<br />
che L −1 · A = U, ovvero A = LU. Vediamo più in dettaglio il procedimento<br />
dell’algoritmo. Ricordiamoci che L deve essere una matrice triangolare inferiore<br />
a diagonale unitaria. Vogliamo azzerare tutte le componenti di un vettore v<br />
dalla k + 1 − esima in poi. Ci serviremo di una matrice L, tale che<br />
⎛ ⎞<br />
v1<br />
⎜ ⎟<br />
⎜ . ⎟<br />
⎜vk⎟<br />
Lv = ⎜ ⎟<br />
⎜ 0 ⎟<br />
⎜ ⎟<br />
⎝ . ⎠<br />
0<br />
Definiamo, per questo scopo, il vettore elementare di Gauss come<br />
g ≡ 1<br />
(0, . . .,0<br />
vk <br />
k<br />
, vk+1, . . .,vn) T<br />
53<br />
g ∈ R k+n×1<br />
(4.7)<br />
(4.8)
e la matrice elementare di Gauss<br />
L ≡ I − ge T k<br />
Graficamente la matrice 4.9 appare così:<br />
⎛<br />
1<br />
⎜<br />
L = ⎜<br />
⎝<br />
. ..<br />
1<br />
− vk+1<br />
vk<br />
.<br />
− vn<br />
vk<br />
Verifichiamo che l’equazione 4.7 è soddisfatta:<br />
⎛<br />
Lv = (I−ge T k )·v = v−g· (eT k v)<br />
<br />
è uno scalare<br />
. ..<br />
⎜<br />
= v−gvk = ⎜<br />
⎝<br />
v1<br />
.<br />
.<br />
vk<br />
. ..<br />
vk+1<br />
.<br />
vn<br />
⎞<br />
1<br />
⎞<br />
⎟<br />
⎠<br />
⎛<br />
⎟<br />
⎟−vk·<br />
⎟<br />
⎠<br />
1<br />
⎜<br />
vk<br />
⎜<br />
⎝<br />
0<br />
.<br />
.<br />
0<br />
vk+1<br />
.<br />
vn<br />
⎞<br />
(4.9)<br />
⎛<br />
v1<br />
⎞<br />
⎟ ⎜ . ⎟<br />
⎟ ⎜<br />
⎟ ⎜ . ⎟<br />
⎟ ⎜vk⎟<br />
⎟ = ⎜ ⎟<br />
⎜<br />
⎟ ⎜ 0 ⎟<br />
⎟ ⎜ ⎟<br />
⎠ ⎝ . ⎠<br />
0<br />
Vediamo ancora più in dettaglio le trasformazioni che la matrice A subisce per<br />
diventare la matrice U. Al primo passo la matrice si presenta così:<br />
A ≡ A (1) ⎛<br />
a<br />
⎜<br />
= ⎜<br />
⎝<br />
(1)<br />
11 . . . a (1)<br />
⎞<br />
1n<br />
⎟<br />
. . ⎠<br />
(4.10)<br />
a (1)<br />
n1 . . . a (1)<br />
nn<br />
L’indice tra parentesi indica l’ultima iterazione che ha modificato l’elemento.<br />
Come detto in precedenza, al primo passo, si deve moltiplicare a sinistra la<br />
matrice 4.10 per una matrice triangolare inferiore a diagonale unitaria, in modo<br />
tale che la matrice risultante abbia la prima colonna strutturalmente uguale<br />
alla prima colonna di un matrice triangolare superiore. Costruiamo per questo<br />
il primo vettore di Gauss<br />
g1 ≡ 1<br />
a (1)<br />
11<br />
e la corrispondente matrice di Gauss<br />
⎛<br />
L1 ≡ I − g1e T 1 =<br />
⎜<br />
⎝<br />
(0, a (1)<br />
21 , . . . , a(1) n1 )T<br />
1<br />
− a(1)<br />
21<br />
a (1)<br />
11<br />
.<br />
− a(1)<br />
n1<br />
a (1)<br />
11<br />
54<br />
1<br />
. ..<br />
⎞<br />
⎟<br />
⎠<br />
1<br />
(4.11)<br />
(4.12)
Moltiplicando la matrice 4.12 con la matrice 4.10 otteniamo:<br />
⎛<br />
a<br />
⎜<br />
L1A = ⎜<br />
⎝<br />
(1)<br />
11 . . . . . . a (1)<br />
0 a<br />
1n<br />
(2)<br />
22 . . . a (2)<br />
. .<br />
⎞<br />
⎟<br />
2n ⎟ ≡ A(2)<br />
. ⎠<br />
0 a (2)<br />
n2 . . . a (2)<br />
nn<br />
(4.13)<br />
Siccome L1 ha la prima riga formata da un 1 seguito da zeri, la prima riga<br />
di A (2) , risulterà inalterata.<br />
⎛<br />
a<br />
⎜<br />
Li−1 . . . L2L1A = ⎜<br />
⎝<br />
(1)<br />
11 . . . . . . . . . . . . a (1)<br />
1n<br />
.<br />
0 ..<br />
.<br />
.<br />
. .. (i−1)<br />
a i−1,i−1 . . . . . . a (i−1)<br />
i−1,n<br />
. 0 a (i)<br />
ii . . . a (i)<br />
⎞<br />
⎟ ≡ A<br />
⎟<br />
in ⎟<br />
. . . . . . ⎠<br />
(i)<br />
(4.14)<br />
0 . . . 0 a (i)<br />
ni . . . a (i)<br />
nn<br />
A questo punto segue l’i-esimo passo.Se a (i)<br />
ii = 0 si può calcolare l’i-esimo vettore<br />
di Gauss e la i-esima matrice di Gauss<br />
gi ≡ 1<br />
a (i)<br />
ii<br />
Li ≡ I − gie T ⎛<br />
1<br />
⎜<br />
i = ⎜<br />
⎝<br />
(0 . . . , 0,<br />
a<br />
<br />
i<br />
(i)<br />
. ..<br />
i+1,i<br />
, . . .,a(i)<br />
ni )T<br />
1<br />
− a(i)<br />
i+1,i<br />
a (i)<br />
ii<br />
.<br />
.<br />
− a(i)<br />
ni<br />
a (i)<br />
ii<br />
. ..<br />
⎞<br />
⎟<br />
⎠<br />
1<br />
Moltiplicando a sinistra A (i) con l’i-esima matrice di Gauss, otteniamo:<br />
LiA (i) ⎛<br />
a<br />
⎜<br />
= Li−1 . . . L2L1A = ⎜<br />
⎝<br />
(1)<br />
.<br />
0 ..<br />
.<br />
.<br />
. .<br />
. .. (i)<br />
a i,i . . . . . . a (i)<br />
in<br />
. 0 a (i+1)<br />
.<br />
.<br />
. . . .<br />
11 . . . . . . . . . . . . a (1)<br />
1n<br />
i+1,i+1 . . . a (i+1)<br />
i+1,n<br />
0 . . . 0 a (i+1)<br />
n,i+1 . . . a (i+1)<br />
nn<br />
⎞<br />
(4.15)<br />
(4.16)<br />
⎟ ≡ A<br />
⎟<br />
⎠<br />
(i+1)<br />
(4.17)<br />
Le prime i righe della matrice 4.17, restano invariate perchè le prime i righe<br />
della i-esima matrice di Gauss corrispondono alla matrice identità. Iterando il<br />
55
procedimanto fin qui descritto, al passo i = n − 1, otteniamo:<br />
⎛<br />
a<br />
⎜<br />
Ln−1 . . . L1A = ⎜<br />
⎝<br />
(1)<br />
11 . . . . . . a (1)<br />
0<br />
. ..<br />
a<br />
1n<br />
.<br />
(n−1)<br />
⎞<br />
⎟<br />
⎠ ≡ A(n) ≡ U (4.18)<br />
n−1,n−1 a(n−1) n−1,n<br />
a (n−1)<br />
nn<br />
I fattori Li meritano una considerazione. Come detto in precedenza, tali<br />
fattori sono matrici tringolari inferiori a diagonale unitaria, e per i teoremi 8<br />
e 9 il prodotto n−1 i=1 Li è ancora una matrice triangolare inferiore a diagonale<br />
unitaria. In particolare abbiamo che<br />
Ma allora<br />
Invertendo le matrici abbiamo che<br />
L −1 A = U =⇒ A = LU<br />
L −1 = Ln−1Ln−2 . . .L1<br />
L = L −1<br />
n−1L−1 n−2 . . . L−1 1<br />
Vediamo più in dettaglio cosa sono L e L −1<br />
L = I − ge T k<br />
L −1 = I + ge T k<br />
Dalla definizione di matrice inversa, sappiamo che L ·L −1 = I. Quindi abbiamo<br />
che:<br />
(I − ge T k ) · (I + ge T k ) = (I + ge T k − ge T k − ge T k ge T k ) = I − g(e T k g<br />
<br />
0<br />
)e T k = I<br />
È interessante vedere sotto quali condizioni è possibile effettuare la fattorizzazione<br />
LU.<br />
Definizione 7 (sottomatrice di ordine k). Data A ∈ Rn×n si dice sottomatrice<br />
principale di ordine k, la matrice<br />
⎛ ⎞<br />
a11 . . . a1k<br />
⎜<br />
Ak = ⎝ .<br />
.<br />
⎟<br />
. ⎠ ∈ R k×k<br />
ak1 . . . akk<br />
Teorema 12 (Esistenza della fattorizzazione LU). A è fattorizzabile LU se e<br />
solo se U è non singolare, se e solo se ∀K = 1, . . . , n Uk è non singolare.<br />
Dim. possiamo ottenere Ak a partire da A nel seguente modo:<br />
Ak = <br />
IK Ok,n−k · A ·<br />
IK<br />
On−k,k<br />
Sostituiamo nella precedente equazione la matrice A con LU opportunamente<br />
partizionate<br />
⎛<br />
⎞⎛<br />
⎞<br />
⎜<br />
Ak = ⎜<br />
⎝<br />
IK Ok,n−k<br />
<br />
UK UK1<br />
<br />
LK<br />
·<br />
LK1<br />
<br />
⎟⎜<br />
Ok,n−k ⎟⎜<br />
⎟⎜<br />
LK2 ⎠⎝<br />
<br />
<br />
UK2<br />
<br />
L<br />
U<br />
56<br />
IK<br />
On−k,k<br />
⎟<br />
⎠ =
= <br />
Uk<br />
Lk Ok,n−k · = LKUK = AK<br />
On−k,k<br />
Osserviamo che det(AK) = det(LKUK) = det(LK) · det(UK) = det(UK)<br />
Abbiamo ottenuto quindi che la sottomatrice di ordine k di U è non singolare<br />
se e solo se la sottomatrice di ordine k di A è non singolare.<br />
Algoritmo 4.4 (Fattorizzazione LU).<br />
function [A]=LU(A)<br />
%fattorizza la matrice A in due fattori:<br />
%una matrice triangolare inferiore a diagonale unitaria<br />
%una matrice triangolare superiore<br />
%INPUT<br />
% A matrice non singolare<br />
%OUTPUT<br />
% A matrice che contiene la fattorizzazioen LU<br />
[m,n]=size(A);<br />
if m==n<br />
for i=1:n-1<br />
if A(i,i)==0<br />
error(’la matrice non fattorizzabile LU’)<br />
end<br />
A(i+1:n,i)=A(i+1:n,i)/A(i,i);<br />
A(i+1:n,i+1:n)=A(i+1:n,i+1:n) - A(i+1:n,i)*A(i,i+1:n);<br />
end<br />
else<br />
error(’la matrice non quadrata’)<br />
end<br />
57
Algoritmo 4.5 (Matrici diagonali).<br />
function [x]=swlu(A,b)<br />
%swlu l’acronimo di Solve With LU<br />
%A la matrice quadrata da fattorizzare<br />
%b il vettore dei termini noti<br />
%x il parametro di ritorno x la soluzione<br />
A<br />
b<br />
lu=LU(A);<br />
%estraggo L e setto la diagonale a 1<br />
%visto che la diagonale unitaria non era<br />
%esplicitamente memorizzata<br />
L=tril(lu);<br />
L=L-diag(diag(L-1,0))<br />
%estraggo U<br />
U=triu(lu)<br />
%adesso risolvo il sistema<br />
%A=LU, quindi LUx=b<br />
%Lx1=b e Ux=x1<br />
x1=slts(L,b);<br />
x=suts(U,x1);<br />
x’<br />
58
Esempio 18 (Risoluzione sistema di equazioni). Mostriamo un esempio di<br />
risoluzione di un sistema di equazioni tramite la fattorizzazione LU.<br />
>> x=swlu(A,b);<br />
A =<br />
b =<br />
3 7 -2 -5 4<br />
-1 0 9 -4 3<br />
12 -1 -1 2 -5<br />
0 3 3 -6 -2<br />
1 1 -4 3 6<br />
14<br />
34<br />
-8<br />
9<br />
4<br />
L =<br />
1.0000 0 0 0 0<br />
-0.3333 1.0000 0 0 0<br />
4.0000 -12.4286 1.0000 0 0<br />
0 1.2857 -0.0698 1.0000 0<br />
0.3333 -0.5714 0.0129 -0.9815 1.0000<br />
U =<br />
x =<br />
3.0000 7.0000 -2.0000 -5.0000 4.0000<br />
0 2.3333 8.3333 -5.6667 4.3333<br />
0 0 110.5714 -48.4286 32.8571<br />
0 0 0 -2.0930 -5.2791<br />
0 0 0 0 1.5370<br />
1.0000 -1.0000 2.0000 -2.0000 3.0000<br />
ans =<br />
1.0000<br />
-1.0000<br />
2.0000<br />
-2.0000<br />
3.0000<br />
>><br />
59
4.3.1 Costo computazionale<br />
Data una matrice A ∈ R n×n il costo della sua fattorizzazione LU è dato da<br />
n−1 <br />
(n − i) + 2(n − i)(n − i) ≈ 2<br />
3 n3<br />
i=1<br />
Infatti ad ognuna delle n − 1 iterazioni, vengono eseguite n − i divisioni e 2<br />
operazioni per ognuno dei (n − i) 2 elementi. Svolgendo i calcoli, otteniamo:<br />
n−1 <br />
n−1 <br />
(n − i) + 2(n − i)(n − i) =<br />
i=1<br />
i=1<br />
n(n − 1)<br />
= n(n − 1) −<br />
2<br />
= n(n − 1)<br />
+<br />
2<br />
2n(n − 1)(2n − 1)<br />
6<br />
n − i + 2n 2 − 4ni + 2i 2<br />
+ 2n 2 (n − 1) − 2n 2 (n − 1) +<br />
= 3n2 = 3n + (2n2 − 2)(2n − 1)<br />
6<br />
= 3n2 − 3n + 4n3 − 4n2 − 4n + 2<br />
≈<br />
6<br />
4<br />
6 n3 = 2<br />
3 n3<br />
2n(n − 1)(2n − 1)<br />
6<br />
Per quanto riguarda l’occupazione di memoria, possiamo vedere che ad ogni<br />
iterazioni viene azzerata la parte della sottodiagonale principale. L’informazione<br />
riguardante il fattore U, ad ogni iterazione, viene scritta nella parte superiore<br />
della matrice, mentre l’informazione del fattore L, viene scritta nella nella parte<br />
inferiore. Siccome L è a diagonale unitaria, non richiede esplicita memorizzazione,<br />
rendendo così possibile scrivere sia il fattore L che il fattore U nella<br />
stessa matrice. In definitiva, per quanto riguarda l’occupazione di memoria,<br />
l’algoritmo di fattorizzazione LU ha un costo lineare.<br />
4.4 Matrici a diagonale dominante<br />
Vediamo in questa sezione una classe di matrici con determinate proprietà<br />
algebriche, che le rendono fattorizzabili LU.<br />
Definizione 8. A è diagonale dominante per righe se<br />
∀i = 1, . . .,n : |aii| ><br />
A è diagonale dominante per colonne se<br />
∀i = 1, . . .,n : |aii| ><br />
n<br />
j=1,j=i<br />
n<br />
j=1,j=i<br />
Lemma 1. A è diagonale dominante per righe se e solo se A è diagonale<br />
dominante per colonne.<br />
Lemma 2. A è diagonale dominante per righe (colonne) allora ∀i = 1, . . .,n,<br />
Ak è diagonale dominante per righe (colonne)<br />
60<br />
aij<br />
aji
Teorema 13. Se A è diagonale dominante allora A è non singolare. dim. (per<br />
assurdo) Supponiamo che A sia singolare; allora esiste x = 0 tale che Ax = 0.<br />
Supponiamo che xk sia la componente di massimo modulo e che sia uguale ad<br />
1.<br />
xk = max|xi| = 1 (4.19)<br />
Abbiamo quindi che | xi<br />
| ≤ 1. La k-esima equazione<br />
xk<br />
Quindi per la 4.19<br />
Allora<br />
akk = akkxk = −<br />
Ovvero<br />
n<br />
j=1,j=k<br />
n<br />
akjxj = 0<br />
j=1<br />
akkxk = akk<br />
akjxj ⇒ |akk| = |<br />
|akk| <<br />
n<br />
n<br />
akjxj| ≤ |akj xj<br />
<br />
j=1,j=k j=1,j=k<br />
xj 0(positività)<br />
⎛<br />
1<br />
⎜<br />
A = ⎜2<br />
⎝3<br />
2 3<br />
5 6<br />
6 8<br />
⎞<br />
4<br />
7 ⎟<br />
9⎠<br />
4 7 9 0<br />
La precedente matrice è simmetrica ma non positiva. Infatti x = e4 = 0 mentre<br />
e T 4 Ae4 = 0<br />
Teorema 15. Se A è sdp, allora per ogni i = 1, . . .,n, aii > 0<br />
61<br />
| <<br />
n<br />
j=1,j=k<br />
akj
Teorema 16. Se A è sdp, allora per ogni i = 1, . . .,n, Ak è sdp. dim. Sia<br />
y ∈ Rk , y = 0, tale che yT Aky > 0. Sia x ∈ Rn tale che<br />
<br />
y<br />
x = = 0<br />
0<br />
Abbiamo che:<br />
0 < x T Ax = y T 0 T Ak B T<br />
B D<br />
y<br />
0<br />
<br />
= y T Ak y T B T y<br />
0<br />
Teorema 17. Se A è sdp, allora A è non singolare. dim.(per assurdo) Se A<br />
è singolare allora esiste x = 0 tale che Ax = 0. Per la proprietà di positività<br />
x T Ax > 0. Se sostituiamo Ax = 0 nella precedente espressione otteniamo<br />
l’assurdo: x T 0 > 0.<br />
Teorema 18. A è sdp allora A = LU La dimostrazione discende direttamente<br />
dai due teoremi precedenti 16 e 17<br />
Teorema 19. A è sdp se e solo se A = LDL T con<br />
. L triangolare inferiore a diagonale unitaria<br />
. D diagonale con elementi diagonali positivi<br />
dim.: Se A è sdp allora A = LDLT . Per il teorema 18 se A è sdp allora è<br />
LU. Prendiamo la matrice U uguale a DÛ, con<br />
⎛<br />
u11<br />
⎜<br />
D = ⎝<br />
. ..<br />
⎞<br />
0<br />
⎟<br />
⎠<br />
0 u1n<br />
Quindi<br />
Û = D −1 ⎛<br />
1<br />
⎜<br />
U = ⎝<br />
. ..<br />
⎞<br />
∗<br />
⎟<br />
⎠<br />
0 1<br />
A = LU = L(DÛ )<br />
<br />
U<br />
Siccome A = A T allora A T = (LD Û)T = ÛT DL T . Essendo la fattorizzazione<br />
LU unica segue che<br />
L = ÛT<br />
Û = L T<br />
Adesso rimane solo da dimostrare che gli elementi diagonali di D sono positivi.<br />
Risulta che:<br />
∀x = 0 : x T Ax > 0<br />
Definisco<br />
L T x = ei dove x = 0<br />
0 < x T Ax = x T LDL T x = (L T x) T D(L T x) = e T i Dei = di<br />
62<br />
<br />
= y T Aky > 0
dim.: Se A = LDL T allora A è sdp. Se A = LDL T allora<br />
A T = (LDL T ) T = (L T ) T D T L T = LDL T = A(simmetria)<br />
Ora rimane da dimostrare che ∀x = 0, xTLDLT x > 0. Ponendo LTx = y si ha<br />
che:<br />
y T n<br />
Dy = diiy 2 i > 0<br />
Vediamo adesso come si ottiene la fattorizzazione A = LDLT :<br />
⎛<br />
1<br />
⎜<br />
⎜l21<br />
L = ⎜<br />
⎝ .<br />
. ..<br />
. .. . ..<br />
⎞<br />
⎟ j = 1, . . . , n<br />
⎠<br />
⎛<br />
d1<br />
⎜<br />
D = ⎝<br />
. ..<br />
ln1 . . . ln,n−1 1<br />
Quando i = j<br />
Quindi<br />
Quando i > j<br />
Quindi<br />
i=1<br />
aij = e T i Aej = e T i (LDL T )ej = (e T i L)D(e T j L) T =<br />
j−1<br />
=<br />
k=1<br />
<br />
j<br />
k=1<br />
j−1<br />
likljkdk + lijljjdj = likljkdk + lijdj<br />
j−1<br />
aij =<br />
k=1<br />
k=1<br />
<br />
l 2 jkdk + lijljjdj = l 2 jjdj j−1<br />
+<br />
k=1<br />
k=1<br />
ljkdk<br />
dn<br />
likljkdk<br />
⎞<br />
⎟<br />
⎠<br />
j−1<br />
dj = ajj − ljk(ljkdk) j = 1, . . . , n (4.20)<br />
aij =<br />
j<br />
k=1<br />
lij = aij −<br />
likljkdk = lijljjdj<br />
<br />
j−1<br />
lik(ljkdk)<br />
k=1<br />
dj<br />
j−1<br />
k=1<br />
likljkdk<br />
i = j + 1, . . .,n (4.21)<br />
Possiamo vedere come nell’equazioni 4.20 e 4.21 sia presente il fattore<br />
likljk. Utilizzeremo un vettore d’appoggio per calcolarlo, così da calcolarlo<br />
una sola volta e risparmiare un pò di operazioni.<br />
Il costo computazionale della fattorizzazione LDL T è approssimativamente di<br />
1<br />
3 n3 flop. Per quanto riguarda l’occupazione di memoria, questo algoritmo, come<br />
d’altronde il metodo LU, non richiede addizionale spazio per la memorizzazione,<br />
tranne per il vettore di appoggio. I fattori L e D dell’avvenuta fattorizzazione<br />
possono essere tranquillamente scritti nella matrice A di partenza.<br />
63
Algoritmo 4.6 (Fattorizzazione LDL T ).<br />
function A=LDLT(A)<br />
%<br />
[m,n]=size(A);<br />
if m==n<br />
if A(1,1)
Per come è definito a (i)<br />
<br />
<br />
kii = maxk≥i a (i)<br />
<br />
<br />
ki , è il massimo della colonna i-esima<br />
sotto la componente ai−1,i; se il massimo in valore assoluto è zero, significa che<br />
tutti i numeri considerati sono zero, e pertanto A (i−1) :<br />
⎛<br />
⎞<br />
A (i−1) ⎜<br />
= ⎜<br />
⎝<br />
a (1)<br />
11 a (1)<br />
12 . . . a (1)<br />
1i−1<br />
0 a (2)<br />
22 . . . a (2)<br />
2i−1<br />
.<br />
.<br />
. ..<br />
.<br />
a (1)<br />
1i<br />
a (2)<br />
2i<br />
.<br />
a (1)<br />
1i+1 . . . a (1)<br />
1n<br />
a (2)<br />
2i+1 . . . a (2)<br />
2n<br />
0 0 . . . a (i−1)<br />
i−1i−1 a (i−1)<br />
i−1i a (i−1)<br />
i−1i+1 . . . a (i−1)<br />
i−1n<br />
0 0 . . . 0 0 a (i−1)<br />
ii+1<br />
.<br />
.<br />
.<br />
0 0 . . . 0 0 a (i−1)<br />
ni+1<br />
.<br />
.<br />
.<br />
.<br />
. . . a (i−1)<br />
in<br />
.<br />
. . . a (i−1)<br />
nn<br />
I vettori che costituiscono le prime i − 1 colonne sono linearmente indipendenti<br />
e pertanto la i-esima colonna si può esprimere come combinazione lineare di<br />
queste. Pertanto si evince che la matrice A (i−1) è singolare. Inoltre ricordando<br />
che:<br />
A (i−1) = Li−2Li−3 . . .L1A<br />
si ha che:<br />
e quindi A è singolare.<br />
0 = det(A (i−1) ) = det(Li−2Li−3 . . . L1A) = det(A)<br />
A partire dalla matrice identità di ordine n, ovvero In, definiamo la prima<br />
matrice elementare di permutazione<br />
⎛<br />
0 . . . . . . 0 1 0<br />
⎞<br />
. . . 0<br />
⎜ .<br />
⎜<br />
. 1<br />
⎜<br />
.<br />
⎜ . ..<br />
⎜<br />
P1 ≡ ⎜ 0 1<br />
⎜ 1 0 . . . . . .<br />
⎜ 0 . . . . . . . . .<br />
⎜<br />
⎝<br />
.<br />
.<br />
0<br />
.<br />
. .<br />
. 0<br />
0<br />
0 1<br />
.<br />
.<br />
. ⎟<br />
. ⎟ ⎛<br />
. ⎟ 0<br />
⎟ ⎜<br />
. . . 0 ⎟ = ⎜ 0<br />
⎝<br />
⎟ 1<br />
⎟<br />
. ⎟<br />
.. ⎠<br />
0<br />
Ik1−2<br />
0<br />
1<br />
0<br />
0<br />
⎞<br />
⎟<br />
⎠<br />
In−k1<br />
0 . . . . . . . . . 0 1<br />
(4.24)<br />
La suddetta matrice, non è altro che la matrice identità con la prima e la k-esima<br />
riga (colonna) scambiate tra di loro. È da notare che la matrice P è ortogonale<br />
e simmetrica, quindi risulta che P1 = P T 1 = P −1<br />
1 .<br />
Se moltiplichiamo la matrice A per la matrice P il risultato è la matrice A<br />
con due righe invertite.<br />
65<br />
⎟<br />
⎠
⎛<br />
P1A (1) ⎜<br />
= ⎜<br />
⎝<br />
a (1)<br />
k11 . . . . . . . . . . . . . . . . . . a (1)<br />
k1n<br />
a (1)<br />
21 . . . . . . . . . . . . . . . . . . a (1)<br />
2n<br />
.<br />
a (1)<br />
k1−1,1 . . . . . . . . . . . . . . . . . . a (1)<br />
k1−1,n<br />
a (1)<br />
k11 . . . . . . . . . . . . . . . . . . a (1)<br />
k1n<br />
a (1)<br />
k1+1,1 . . . . . . . . . . . . . . . . . . a (1)<br />
k1+1,n<br />
.<br />
a (1)<br />
n1 . . . . . . . . . . . . . . . . . . a (1)<br />
nn<br />
.<br />
.<br />
⎞<br />
⎟<br />
⎠<br />
←− riga 1<br />
←− riga k1<br />
(4.25)<br />
La matrice così ottenuta ha l’elemento ak11 diverso da zero, in quanto è di<br />
modulo massimo. Allora possiamo applicare il primo passo di eliminazione di<br />
Gauss, costruendo il primo vettore elementare di Gauss:<br />
g1 = 1<br />
ak11<br />
(0, a (1)<br />
21<br />
k1<br />
<br />
, . . . ,<br />
a (1)<br />
11<br />
, . . . , a(1)<br />
n1 )T<br />
A questo punto, continuando come con il metodo LU, calcoliamo la prima<br />
matrice elementare di Gauss:<br />
L1 = I − g1e T 1<br />
con la quale possiamo calcolare<br />
⎛<br />
a<br />
⎜<br />
L1P1A1 = ⎜<br />
⎝<br />
(1)<br />
0 a (2)<br />
. .<br />
k11 . . . . . . a (1)<br />
k1n<br />
22 . . . a (1)<br />
2n<br />
0 a (2)<br />
n2 . . . a (2)<br />
nn<br />
.<br />
⎞<br />
⎟<br />
⎠<br />
≡ A(2)<br />
(4.26)<br />
La procedura è analoga alla fattorizzazione LU; differisce solo nella moltiplicazione<br />
per la matrice P. In generale al passo i-esimo potremmo ottenere<br />
⎛<br />
a<br />
⎜<br />
Li−1Pi−1 . . . L1P1A1 = ⎜<br />
⎝<br />
(1)<br />
.<br />
0 ..<br />
.<br />
. 0 a (i)<br />
. . .<br />
. . .<br />
k11 . . . . . . . . . . . . a (1)<br />
k1n<br />
. .. (i−1)<br />
a ki−1,i−1 . . . . . . a (i−1)<br />
ki−1,n<br />
.<br />
.<br />
ii . . . a (i)<br />
in<br />
0 . . . 0 a (i)<br />
ni . . . a (i)<br />
nn<br />
Definendo l’i-esimo elemento di modulo massimo<br />
.<br />
.<br />
⎞<br />
⎟ ≡ A<br />
⎟<br />
⎠<br />
(i)<br />
(4.27)<br />
|a (i)<br />
kii | ≡ max<br />
k≥i |a(i)<br />
ki | con ki > i (4.28)<br />
66
otteniamo la i-esima matrice di permutazione<br />
⎛<br />
pi ≡<br />
⎜<br />
⎝<br />
Ii−1<br />
0 0 1<br />
0 Iki−i−1 0<br />
1 0 0<br />
In−ki<br />
⎞<br />
⎟<br />
⎠<br />
(4.29)<br />
L’elemento in posizione (i, i) della matrice PiA (i) sarà diverso da zero, in<br />
quanto è l’elemento di modulo massimo della i-esima colonna della matrice A.<br />
Possiamo definire a questo punto l’i-esimo vettore di gauss<br />
gi ≡ 1<br />
a (i)<br />
(0. . . .,0,<br />
a<br />
<br />
kii<br />
i<br />
(i)<br />
i+1,i<br />
ki<br />
<br />
, . . . ,<br />
a (i)<br />
ii<br />
, . . . , a(i)<br />
ni )T<br />
con il quale otteniamo la i-esima matrice elementare di Gauss<br />
Li = I − gie T i<br />
Quindi con le matrici 4.27 , 4.29 e 4.31, otteniamo<br />
LiPiA (i) ⎛<br />
a<br />
⎜<br />
= ⎜<br />
⎝<br />
(1)<br />
0<br />
.<br />
.<br />
. ..<br />
0 a<br />
.<br />
(i+1)<br />
.<br />
.<br />
.<br />
.<br />
.<br />
.<br />
.<br />
.<br />
k11 . . . . . . . . . . . . a (1)<br />
k1n<br />
. .. a (i)<br />
kii . . . . . . a (i)<br />
kin<br />
i+1,i+1 . . . a (i+1)<br />
i+1,n<br />
0 . . . 0 a (i+1)<br />
n,i+1 . . . a (i+1)<br />
n,n<br />
⎞<br />
⎟ ≡ A<br />
⎟<br />
⎠<br />
(i+1)<br />
(4.30)<br />
(4.31)<br />
(4.32)<br />
Per il teorema 20, sappiamo che se A è non singolare, sarà sempre possibile<br />
scegliere l’elemento di modulo massimo diverso da zero, e quindi continuare<br />
l’algoritmo fino all’iterazione i = n − 1, ottenendo la fattorizzazione<br />
Ln−1Pn−1Ln−2Pn−2 . . . L1P1A = A (n) ≡ U<br />
Se PA = LU, allora L −1 PA = U. Cerchiamo di scoprire chi è il fattore L −1 ;<br />
Consideriamo la seguente equazione:<br />
Con<br />
ˆLn−1 ≡ Ln−1<br />
ˆLn−1 ˆ Ln−2 . . . ˆ L1PA = U<br />
ˆLi ≡ Pn−1 . . . Pi+1LiPi+1 . . .Pn−1 per i = 1, . . .,n − 2<br />
P ≡ Pn−1 . . . P1 (4.33)<br />
Di conseguenza la matrice<br />
ˆLn−1 . . . ˆ L1 ≡ L −1<br />
67
Infatti ˆ Li è una matrice triangolare inferiore a diagonale unitaria. Osserviamo<br />
che<br />
ˆLi = (Pn−1 . . . Pi+1)(I − gie T i )(Pi+1 . . . Pn−1) =<br />
= I − (Pn−1 . . .Pi+1gi)(e T i Pi+1 . . . Pn−1<br />
<br />
eT i Pj=eT i ∀j>i<br />
) = I − (Pn−1 . . . Pi+1gi<br />
<br />
dove ˆgi non è altro che l’i-esimo vetore elementare di Gauss con le prime i<br />
componenti permutate. Ne deduciamo che la struttra di ˆ Ln−1 . . . ˆ L1 è uguale a<br />
quella di una matrice triangolare inferiore a diagonale unitaria.<br />
Esempio 20. Facciamo un esempio teorico con n = 4. Applicando l’algoritmo<br />
fin qui descritto otterremo<br />
L3P3L2P2L1P1 ≡ A (4)<br />
Sostituendo le matrici Li con le corrispondenti ˆ Li otteniamo<br />
L3P3L2 P3P3 P2L1 P2 P3P3<br />
<br />
I<br />
I<br />
<br />
P2 P1 = A<br />
<br />
I<br />
(4)<br />
Notiamo che le sostituzioni non alterano la struttura della matrice.<br />
L3 (P3L2P3) (P3P2L1P2P3)<br />
<br />
ˆL2<br />
ˆL1<br />
68<br />
(P3P2P1)<br />
<br />
P=P −1 =P T<br />
ˆgi<br />
)e T i
Algoritmo 4.7 (Fattorizzazione PLU).<br />
function [A,P]=PLU(A)<br />
%Fattorizza la matrice in tre fattori<br />
%INPUT<br />
% A è una matrice non singolare<br />
%OUTPUT<br />
% A contiene i fattori L e U<br />
% P è la matrice di permutazione<br />
P=[1:n];<br />
for i=1:n-1<br />
[mi,ki]=max(abs(A(i:n,i)));<br />
if mi==0<br />
error(’La matrice è singolare’)<br />
end<br />
ki=ki+i-1;<br />
if ki>i<br />
A([i ki],:)=A([ki i],:);<br />
P([i ki])=P([ki i]);<br />
end<br />
A(i+1:n,i)=A(i+1:n,i)/A(i,i);<br />
A(i+1:n,i+1:n)=A(i+1:n,i+1:n)-A(i+1:n,i)*A(i,i+1:n);<br />
end<br />
4.7 Condizionamento del problema<br />
Accenniamo questo argomento per introdurre meglio un altro tipo di fattorizzazione.<br />
Più in dettaglio vogliamo capire come degli errori sui dati in ingresso si<br />
possono ripercuotere sui dati in uscita. In un sistema lineare Ax = b, andremo<br />
a introdurre al posto di A e di b rispettivamente (A + ∆A) e (b + ∆b). Il nostro<br />
sistema risulterà quindi perturbato.<br />
(A + ∆A)(x + ∆x) = (b + ∆b) (4.34)<br />
Poniamo ∆A = ǫ · F con F ∈ R n×n e ∆b = ǫ · f con f ∈ R n . Definiamo<br />
allora<br />
A(ǫ) = A + ǫF = A + ∆A =⇒ A(0) = A (4.35)<br />
b(ǫ) = b + ǫf = b + ∆b =⇒ b(0) = b (4.36)<br />
Possiamo quindi scrivere l’equazione funzionale ad ǫ.<br />
A(ǫ)x(ǫ) = b(ǫ) (4.37)<br />
69
Siamo interessati a sviluppare x(ǫ) per arrrivare poi all’equazione del condizionamento<br />
di un sistema lineare. Quindi sviluppando con Taylor otteniamo:<br />
x(ǫ) = x(0) + ǫ ˙x(0) + o(ǫ 2 ) ≈ x(0) + ǫ ˙x(0)<br />
Siccome x(0) = x e x(ǫ) = x + ∆x, otteniamo che<br />
∆x = (x+∆x)−x = (x+∆x)−x(0) = x(ǫ)−x(0) ≈ x(0)+ǫ ˙x(0)−x(0) = ǫ ˙x(0)<br />
Abbiamo quindi ricavato l’errore assoluto. Continuando nel nostro percorso<br />
per la scoperta del condizionamento di un sistema lineare proviamo a derivare<br />
membro a membro l’equazione 4.37<br />
d<br />
A(ǫ)x(ǫ)<br />
dǫ<br />
=<br />
d<br />
dǫ b(ǫ)<br />
d<br />
A(ǫ)x(ǫ)<br />
dǫ<br />
= f<br />
A(ǫ)x(ǫ) ˙ + A(ǫ) ˙x(ǫ) = f<br />
Fx(ǫ) + A(ǫ) ˙x(ǫ) = f<br />
Calcolando quest’ultima equazione nel punto ǫ = 0 otteniamo che<br />
Ovvero<br />
Fx + A ˙x(0) = f<br />
˙x(0) = A −1 (f − Fx)<br />
Moltiplicando ambo i membri per ǫ riusciamo a riottenere un espressione in<br />
funzione dell’errore assoluto<br />
ǫ ˙x(0) = A −1 (ǫf − ǫFx)<br />
∆x = A −1 (∆b − ∆Ax)<br />
Considerando il risultato ottenuto con le norme otteniamo che<br />
||∆x|| = ||A −1 · (∆b − ∆Ax)|| ≥ ||A −1 || · ||(∆b − ∆Ax)|| ≥ ||A −1 || · (||∆b|| + ||∆A|| · ||x||)<br />
Dividendo membro a membro per ||x||<br />
||∆x||<br />
||x|| ≤ ||A−1 <br />
||∆b||<br />
||<br />
||x||<br />
Moltiplicando e dividendo per ||A||<br />
||A −1 <br />
||∆b|| ||∆A||<br />
|| · ||A|| +<br />
||x|| ||A|| ||A||<br />
<br />
+ ||∆A||<br />
≤ ||A −1 <br />
||∆b|| ||∆A||<br />
|| · ||A|| +<br />
||b|| ||A||<br />
Abbiamo ricavato l’errore sui dati in uscita, il coefficiente k di condizionamento,<br />
in funzione dei dati in ingresso<br />
||∆x||<br />
||x|| ≥ ||A−1 <br />
||∆b|| ||∆A||<br />
|| · ||A|| + (4.38)<br />
||b|| ||A||<br />
70
Dove<br />
||∆x||<br />
||x||<br />
è l’errore in uscita (4.39)<br />
||A −1 || · ||A|| è il coefficiente di condizionamento (4.40)<br />
||∆b||<br />
||b||<br />
+ ||∆A||<br />
||A||<br />
chiamato anche k<br />
Definiamo allora la funzione di condizionamento<br />
Ovvero<br />
è l’errore sui dati in ingresso (4.41)<br />
k(x) : R n×n −→ R<br />
k(A) ≡ ||A|| · ||A −1 || (4.42)<br />
Notiamo che il numero di condizionamento k(A) non può mai essere inferiore<br />
ad uno. Infatti abbiamo che<br />
k(A) = ||A|| · ||A −1 || ≥ ||A · A −1 || = ||I|| = 1<br />
Quindi il numero di condizionamento di una matrice deve essere raffrontato<br />
all’unità.<br />
Esempio 21 (Condizionamento di una matrice). Con questo esempio si vuole<br />
far vedere che esistono alcune matrici che hanno un numero di condizionamento<br />
talmente alto, da non permetterci di fare alcuna operazione direttamente.<br />
Consideriamo quindi la seguente matrice<br />
⎛<br />
⎞<br />
1<br />
⎜<br />
.<br />
A = ⎜100<br />
..<br />
⎟<br />
⎜<br />
⎝<br />
. .. . ⎟<br />
.. ⎠<br />
100 1<br />
10×10<br />
È una matrice con la diagonale principale formata da dieci 1, mentre la sottodiagonale<br />
principale ha nove 100. In matlab si è possibile costruire la matrice<br />
sopracitata con i seguenti comandi.<br />
> diag0=ones(10,1);<br />
>> diag_1=100*ones(9,1);<br />
>> A=zeros(10,10)+diag(diag0,0)+diag(diag_1,-1);<br />
Poi calcoliamo la norma della matrice e della sua inversa.<br />
>> normA=norm(A,1)<br />
normA =<br />
101<br />
>> normInvA=norm(inv(A),1)<br />
Warning: Matrix is close to singular or badly scaled.<br />
71
normInvA =<br />
1.0101e+018<br />
Results may be inaccurate. RCOND = 9.801980e-021.<br />
Infine calcoliamo il numero di condizionamento<br />
>> normA*normInvA<br />
ans =<br />
1.0202e+020<br />
Sicuramente un numero di condizionamento troppo alto. Un errore sui dati in<br />
ingresso dell’ordine di 10 −10 , comporterebbe un errore sui dati in uscita di 10 10 .<br />
Sicuramente non è accettabile.<br />
4.8 Sistemi lineari sovradimensionati<br />
In questa sezione proporremo un metodo per cercare di risolvere sistemi Ax = b,<br />
in cui A è una matrice rettangolare (m×n) con m ≫ n e tale che A sia di rango<br />
massimo, ovvero n = rank(A) = dim(ran(A)). Sia<br />
A ∈ R m×n<br />
con A = (c1, c2, . . . cn), cj ∈ R m<br />
Sappiamo che il range di A è definito come<br />
⎧<br />
⎨<br />
ran(A) =<br />
⎩ y ∈ Rm : y =<br />
Il rango di una matrice invece è definito come<br />
Tenendo conto che<br />
Abbiamo che<br />
⎧<br />
⎪⎨<br />
dim(null(A)) = n − rank(A) =<br />
⎪⎩<br />
k<br />
n<br />
j=1<br />
rank(A) = dim(ran(A))<br />
αjcj<br />
null(A) = {x ∈ R n : Ax = 0}<br />
⎫<br />
⎬<br />
⎭<br />
0 se rank(A) = n<br />
se e solo se null(A) = 0<br />
> 0 esistono infiniti vettori in null(A)<br />
Consideriamo il primo caso, ovvero il caso in cui dim(null(A)) = 0, cioè quando<br />
la matrice A ha rango massimo. Il problema che dobbiamo affrontare con<br />
i sistemi lineari sovradimensionati, non è tanto l’unicità della soluzione, ma<br />
l’esistenza. Infatti<br />
Sia b ∈ R m ran(A) ⊂ R m<br />
Il range di A ha dimensione n che è minore di m.Il fatto che b appartenga<br />
al range di A è da scartare perchè probabilisticamente impossibile. Non ci<br />
possiamo quindi aspettare una soluzione classica Ax = b.<br />
72
Definizione 10 (Soluzione del sistema lineare sovradimensionato). Sia r =<br />
Ax − b il vettore residuo. La soluzione x è il vettore che minimizza la seguente<br />
quantità:<br />
||r|| 2<br />
2 =<br />
m<br />
i=1<br />
|ri| 2 = ||Ax − b|| 2<br />
2<br />
Tale soluzione viene definita anche come soluzione ai minimi quadrati.<br />
Teorema 21 (Fattorizzazione QR). Sia A ∈ R m×n con m > n tale che<br />
rank(A) = n. Allora esistono<br />
• Q ∈ R m×n , con Q T Q = Im<br />
• ˆ R ∈ R n×n triangolare superiore e non singolare<br />
tali che<br />
<br />
ˆR<br />
A = QR = Q<br />
0<br />
ˆR ∈ R m×n<br />
(4.43)<br />
È interessante notare che Q sia ortogonale. Consideriamo la norma euclidea<br />
del prodotto Qv, dove v è un vettore.<br />
||Qv|| 2<br />
<br />
I<br />
2 = (Qv)T QV = v T Q T Q<br />
V = v T v = ||v|| 2<br />
2<br />
Cerchiamo quindi di minimizzare la quantità della definizione 10.<br />
||Ax − b|| 2<br />
2 = ||QRx − b||2 2 = ||Q(Rx − QTb)|| 2<br />
2 = ||Rx − g||2 2<br />
dove g = Q T b. Sviluppiamo formalmente l’espressione Rx − g<br />
||Rx − g|| 2<br />
2 =<br />
<br />
<br />
<br />
ˆR<br />
<br />
<br />
x −<br />
0<br />
g1<br />
g2<br />
<br />
<br />
<br />
2<br />
2<br />
dove g1 ∈ R n , g2 ∈ R m−n×n<br />
<br />
2 <br />
ˆRx<br />
= <br />
− g1<br />
<br />
<br />
<br />
−g2<br />
= <br />
2<br />
ˆ <br />
<br />
Rx − g1<br />
2<br />
2<br />
+ ||g2|| 2<br />
2<br />
<br />
<br />
Quello che possiamo fare è minimizzare la quantità <br />
ˆ <br />
<br />
Rx − g1<br />
2<br />
. Quindi<br />
Se Rx ˆ = g1 allora ||Ax − b|| 2 2<br />
2 = ||g2|| 2 ≡ min<br />
4.9 Esistenza della fattorizzazione QR<br />
Al fine di determininare l’esistenza della fattorizzazione QR, dobbiamo conoscere<br />
qualche particolare. Supponiamo di avere<br />
• un vettore z ∈ R n<br />
• una matrice H ∈ R n×n ortogonale, ovvero tale che H T H = I<br />
73<br />
2
tali che<br />
⎛ ⎞<br />
α<br />
⎜<br />
⎜0<br />
⎟<br />
Hz = αe1 = ⎜ . ⎟<br />
⎝ . ⎠<br />
0<br />
(4.44)<br />
La matrice H è chiamata matrice di HouseHolder. Consideriamo la norma<br />
euclidea dei due membri dell’equazione 4.44<br />
Queste due equazioni implicano che<br />
||Hz|| 2<br />
2 = zT H T Hz = z t z = ||z|| 2<br />
2<br />
||αe1|| 2<br />
2 = |α|2 · ||e1|| 2<br />
2 = |α|2<br />
α = ± ||z|| 2<br />
Definiamo la matrice H nel seguente modo:<br />
H = I − 2<br />
v T v vvT<br />
Verifichiamo che H è ortogonale ovvero che HH T = I:<br />
H T H = H 2 <br />
= I − 2<br />
vT v vvT<br />
<br />
I − 2<br />
vT v vvT<br />
<br />
(4.45)<br />
con v ∈ R n v = 0 (4.46)<br />
= I− 4<br />
v T v vvT + 4<br />
(v T v) 2 v(vT v)v T = I<br />
Affinché la matrice di Householder sia consistente con l’equazione 4.44, dobbiamo<br />
scegliere il vettore v in modo particolare. Scegliamo allora<br />
v = z − αe1<br />
Dimostriamo che l’equazione appena scritta soddisfa la 4.44.<br />
Hz =<br />
<br />
I − 2<br />
vT v vvT<br />
<br />
z = z− 2<br />
vTv vvT z = z− 2<br />
vTv (zT z−αz1)v =<br />
(4.47)<br />
= z− 2<br />
vT v (zT <br />
z−αz1)(z−αe1) = 1 − 2<br />
vT v (zT <br />
z − αz1) z+α 2<br />
vT v (zT z−αz1)e1<br />
Se la quantità<br />
2<br />
vT v (zT z − αz1) (4.48)<br />
è uguale a uno, allora il primo addendo si annulla e il secondo addendo è uguale<br />
a αe1. Dimostriamo allora che l’espressione 4.48 è uguale a uno.<br />
Se<br />
2<br />
v T v (zT z −αz1) = 1 allora 2z T z −2αz1 = v T v = (z −αe1) T (z −αe1) =<br />
= z T z+α 2 −2α e T 1 z<br />
<br />
z1<br />
= 2z T z−2αz1<br />
74<br />
Nota:<br />
v T z = (z − αe1) T z =<br />
= z T z − αe T 1 z<br />
Nota:<br />
α = ||z|| 2<br />
Quindi<br />
α 2 = ||z|| 2<br />
2 = zT z
Guardiamo in dettaglio il vettore v:<br />
Se<br />
⎛ ⎞<br />
z1<br />
⎜z2⎟<br />
⎜ ⎟<br />
z = ⎜ ⎟<br />
⎝ . ⎠ allora v = z − αe1<br />
⎛ ⎞<br />
z1 − α<br />
⎜ z2 ⎟<br />
⎜ ⎟<br />
= ⎜ ⎟<br />
⎝ . ⎠<br />
zn<br />
Se in aritmetica esatta le operazioni di addizione e sottrazione sono esatte, in<br />
aritmetica finita non è così. Siccome per l’equazione 4.45, è possibile scegliere<br />
il segno di α, lo sceglieremo in modo da rendere ben condizionata la somma<br />
algebrica. Quindi<br />
α = −sign(z1) · ||z|| 2 dove sign(z1) =<br />
zn<br />
1 se z1 ≥ 0<br />
−1 se z1 < 0<br />
Inoltre se z è non banale, abbiamo che |v1| = 0. Allora posso riscrivere il vettore<br />
v in questo modo:<br />
⎛ ⎞<br />
1<br />
v2 ⎜ ⎟<br />
⎜ v1 ⎟<br />
v = v1 · ⎜ ⎟<br />
⎝ ⎠ = v1 · ˆv<br />
Abbiamo ottenuto ˆv in funzione di v.<br />
.<br />
vn<br />
v1<br />
ˆv = 1<br />
v<br />
Vediamo adesso la matrice di householder in funzione del vettore ˆv<br />
v1<br />
H = I − 2<br />
ˆv t ˆv ˆvˆvT = I − 2<br />
v T v<br />
v 2 1<br />
1<br />
v 2 1<br />
vv T = I − 2<br />
v T v vvT<br />
Come si può notare, la matrice espressa con v oppure ˆv rimane la stessa. Questa<br />
proprietà di invarianza risulterà utile per rendere più efficiente l’algoritmo per<br />
la risoluzione di sistemi lineari con metodo di fattorizzazione QR. Dimostriamo<br />
come avviene la fattorizzazione in modo iterativo della matrice A di partenza<br />
nelle matrici Q ed R. Sia A la seguente matrice:<br />
⎛<br />
a<br />
⎜<br />
A = ⎜<br />
(0)<br />
11 . . . . . . a (0)<br />
⎞<br />
1n<br />
⎟<br />
.<br />
. ⎟ ≡ A (0)<br />
(4.49)<br />
⎜<br />
⎝<br />
.<br />
.<br />
.<br />
.<br />
.<br />
.<br />
a (0)<br />
m1 . . . . . . a (0)<br />
mn<br />
con le notazioni usate solitamente. Definiamo la matrice elementare di Householder<br />
H1 ∈ Rm×m , tale che<br />
H (1)<br />
⎛<br />
a<br />
⎜<br />
⎝<br />
(0)<br />
11<br />
.<br />
.<br />
a (0)<br />
⎞<br />
⎟<br />
⎠<br />
m1<br />
≡<br />
⎛<br />
a<br />
⎜<br />
⎝<br />
(1) ⎞<br />
11<br />
0 ⎟<br />
(4.50)<br />
. ⎠<br />
0<br />
75<br />
⎟<br />
⎠
Questo v1, il vettore Householder andrà associato alla prima colonna della<br />
matrice A. Moltiplicandolo avremo<br />
H1A (0) ⎛<br />
a<br />
⎜<br />
= ⎜<br />
⎝<br />
(1)<br />
11 a (1)<br />
12 . . . a (1)<br />
1n<br />
0 a (1)<br />
22 . . . a (1)<br />
⎞<br />
⎟<br />
2n ⎟<br />
.<br />
.<br />
. ⎟ ≡ A(1) (4.51)<br />
. ⎠<br />
0 a (1)<br />
m2 . . . a (1)<br />
mn<br />
Il secondo passo inizia considerando la porzione della seconda colonna e definisce<br />
la seconda matrice di Householder<br />
H (2)<br />
⎛<br />
a<br />
⎜<br />
⎝<br />
(1)<br />
22<br />
.<br />
a (1)<br />
⎞<br />
⎟<br />
⎠<br />
m2<br />
≡<br />
⎛<br />
a<br />
⎜<br />
⎝<br />
(2) ⎞<br />
22<br />
0 ⎟<br />
⎟.<br />
(4.52)<br />
. ⎠<br />
0<br />
quindi considerando A2 come<br />
⎛<br />
A (1) ⎜<br />
= ⎜<br />
⎝<br />
con A1 non singolare. Definendo H2 come<br />
<br />
1<br />
H2 =<br />
a (1)<br />
11 a (1)<br />
12 . . . a (1)<br />
0<br />
1n<br />
.<br />
.<br />
0<br />
A1<br />
H (2)<br />
<br />
∈ R m×m<br />
⎞<br />
⎟<br />
⎠<br />
(4.53)<br />
(4.54)<br />
possiamo premoltiplicarla per A (1) ed eseguire il nostro passo di fattorizzazione.<br />
H2A (1) ⎛<br />
a<br />
⎜<br />
= H2H1A = ⎜<br />
⎝<br />
(1)<br />
11 a (1)<br />
12 a (1)<br />
0 a (2)<br />
22 a (2)<br />
0 0 a (2)<br />
.<br />
.<br />
.<br />
13 . . . a (1)<br />
1n<br />
23 . . . a (2)<br />
2n<br />
33 . . . a (2)<br />
3n<br />
.<br />
0 0 a (2)<br />
m3 . . . a (2)<br />
mn<br />
⎞<br />
⎟ ≡ A<br />
⎟<br />
⎠<br />
(2)<br />
Induttivamente possiamo definire la generica matrice al passo i-esimo<br />
A (i) ⎛<br />
a<br />
⎜<br />
≡ HiHi−1 . . .H1A = ⎜<br />
⎝<br />
(1)<br />
11 . . . . . . . . . . . . a (1)<br />
0<br />
.<br />
. ..<br />
. .. (i)<br />
a ii . . .<br />
1n<br />
.<br />
. . . a (i)<br />
.<br />
. 0 a<br />
1n<br />
(i)<br />
i+1,i+1 . . . a (i)<br />
. . .<br />
⎞<br />
⎟<br />
i+1,n ⎟<br />
. ⎠<br />
0 . . . 0 a (i)<br />
m,i+1 . . . a (i)<br />
mn<br />
76<br />
dove a (j)<br />
jj<br />
= 0, j = 1, . . . , i.
A questo punto l’i-esimo passo consiste nel costruire l’i-esima matrice di Householder<br />
H (i+1)<br />
⎛<br />
a<br />
⎜<br />
⎝<br />
(i)<br />
i+1,i+1<br />
.<br />
a (i)<br />
⎞<br />
⎟<br />
⎠<br />
m,1+1<br />
≡<br />
⎛<br />
a<br />
⎜<br />
⎝<br />
(i+1) ⎞<br />
i+1,i+1<br />
0 ⎟ .<br />
. ⎠<br />
0<br />
(4.55)<br />
al fine di definire la seguente matrice<br />
Hi+1 =<br />
Ii<br />
H (i+1)<br />
<br />
∈ R m×m<br />
Premoltiplicando la matrice Hi+1 per A (i) , otteniamo<br />
A (i) ⎛<br />
a<br />
⎜<br />
≡ HiHi−1 . . .H1A = ⎜<br />
⎝<br />
(1)<br />
.<br />
0 ..<br />
. .<br />
. .. (i+1)<br />
a<br />
. 0 a (i+1)<br />
.<br />
.<br />
.<br />
11 . . . . . . . . . . . . a (1)<br />
1n<br />
1+1;i+1 . . . . . . a (1+1)<br />
1+1,n<br />
i+2,i+2 . . . a (i+1)<br />
i+2,n<br />
0 . . . 0 a (i)<br />
m,i+1 . . . a (i)<br />
mn<br />
.<br />
.<br />
⎞<br />
⎟<br />
⎠<br />
(4.56)<br />
Eseguendo i vari passi si finisce su sottomatrici sempre più piccole e non singolari<br />
e otterremo<br />
A (n) ⎛<br />
a<br />
⎜<br />
≡ Hn . . . H1A = ⎜<br />
⎝<br />
(1)<br />
11 . . . a (1)<br />
0<br />
.<br />
.<br />
.<br />
.<br />
. ..<br />
. ..<br />
⎞<br />
in<br />
⎟<br />
. ⎟<br />
(n)<br />
a ⎟<br />
nn ⎟ ≡ R<br />
0<br />
⎟<br />
. ⎟<br />
.<br />
⎠<br />
0 . . . 0<br />
Infine ponendo Q T = Hn · · · H1 otterremo la 4.43.<br />
77<br />
dove a (i+1)<br />
i+1,i+1 = 0.
Algoritmo 4.8 (Fattorizzazione QR).<br />
function [A] = QR(A)<br />
% [A] = QR(A)<br />
%<br />
% Calcola e restituisce la fattorizzazione QR della matrice in input.<br />
% La matrice in uscita contiene i vettori di Householder normalizzati<br />
% secondo la prima componente uno per colonna nella parte strettamente<br />
% triangolare inferiore. Mentre nella parte triangolare superiore<br />
% contenuta la R^.<br />
%<br />
%<br />
% See also RISOLVI_QR<br />
[m,n] = size(A);<br />
if m>=n<br />
for i=1:n<br />
alpha = norm(A(i:m,i));<br />
if alpha == 0<br />
error(’La matrice non ha rango massimo.’);<br />
end<br />
if A(i,i) >= 0<br />
alpha = -alpha;<br />
end<br />
v1 = A(i,i) - alpha;<br />
A(i,i) = alpha;<br />
A(i+1:m,i) = A(i+1:m,i)/v1;<br />
beta = -v1/alpha;<br />
A(i:m,i+1:n)=A(i:m,i+1:n)-(beta*[1;A(i+1:m,i)])*([1 A(i+1:m,i)’]*A(i:m,i+1:n));<br />
end<br />
else<br />
error(’La matrice non fattorizzabile QR.’);<br />
end<br />
78
Capitolo 5<br />
Approssimazione di funzioni<br />
Una funzione f(x), può essere a volte anche molto complicata. In certe applicazioni,<br />
che richiedono una certa velocità di esecuzione, è preferibile utilizzare<br />
un’approssimazione di tale funzione, che sia molto più semplice e quindi più<br />
facile da calcolare. Inoltre non sempre si conosce direttamente la funzione, ma<br />
solo alcuni suoi punti. Vediamo che cos’è un approssimazione e come possiamo<br />
fare per calcolare la funzione approssimata. Chiameremo f(x) la funzione<br />
originaria, e p(x) il polinomio approssimato.<br />
5.1 Interpolazione polinomiale<br />
Sia f(x) f : [a, b] −→ R [a, b] ∈ R<br />
Consideriamo un ordine in [a, b] così fatto:<br />
a ≤ x0 < x1 < x2 < . . . < xn ≤ b<br />
Avremo quindi n+1 ascisse all’interno dell’intervallo [a, b].Per ogni i = 0, . . . , n<br />
conosciamo<br />
fi ≡ f(xi) (5.1)<br />
Quindi a partire da n + 1 coppie (xi, fi) il problema è quello di riuscire a<br />
determinare un polinomio p(x) tale che<br />
Sia<br />
p(xi) = fi i = 0, . . .,n (5.2)<br />
Πn = {p(x) : p è il polinomio di grado al più n}<br />
Teorema 22. Esiste ed è unico il polinomio interpolante pn ∈ Πn tale che<br />
dim.<br />
pn(xi) = fi i = 0, . . .,n<br />
pn ∈ Πn ⇐⇒ pn(x) =<br />
n<br />
k=0<br />
n<br />
akx k<br />
k=0<br />
akx k i = fi i = 0, . . .,n (5.3)<br />
79
La condizione di interpolazione si traduce nel seguente sistema lineare, nelle<br />
incognite a0, a1, . . . an:<br />
a0 + a1x0 + . . . anx n 0<br />
a0 + a1x1 + . . . anx n 1<br />
. . .<br />
a0 + a1xn + . . . anx n n<br />
Questo sistema di equazioni può essere rappresentato così:<br />
Dove<br />
⎛<br />
ao<br />
an<br />
⎞<br />
⎜a1⎟<br />
⎜ ⎟<br />
a = ⎜ . ⎟<br />
⎝ . ⎠<br />
⎛<br />
f0<br />
fn<br />
⎞<br />
⎜f1⎟<br />
⎜ ⎟<br />
f = ⎜ . ⎟<br />
⎝ . ⎠<br />
V a = f (5.4)<br />
⎛<br />
⎜<br />
V = ⎜ .<br />
⎝ .<br />
x0 0 x1 0 . . . xn 0<br />
x0 1 x1 1 . . . xn 1<br />
.<br />
.<br />
. ..<br />
.<br />
.<br />
x 0 n x1 n . . . x n n<br />
⎞<br />
⎟ ∈ Rn+1×n+1<br />
⎠<br />
V è la matrice di Van Der Monde traposta. Di tale matrice si conoscono alcune<br />
sue proprietà, ed in particolare sappiamo calcolare il suo determinante. Infatti<br />
det(V ) = <br />
(xi − xj) = 0<br />
i>j<br />
Il suo determinante è diverso da zero, quindi esiste ed è unica la soluzione del<br />
sistema 5.4, e quindi esiste ed è unico il polinomio interpolante.<br />
La matrice di Van Der Monde inoltre presenta un numero di condizionamento<br />
molto alto.<br />
Esempio 22. Supponiamo che nell’intervallo [0, 1) vi siano le ascisse così de-<br />
terminate : xi = 1<br />
n i = 1, . . .,n Mostriamo il numero di condizionamento<br />
della relativa matrice di Van Der Monde in funzione di n.<br />
n k<br />
1 15<br />
2 99<br />
. .<br />
20 1017 Come si evince da questo semplice esempio, risulta impraticabile trovare il<br />
polinomio interpolante la funzione f con il metodo sopra descritto. Dobbiamo<br />
quindi considerare metodi alternativi.<br />
5.2 Forma di Lagrange e forma di Newton<br />
In questa sezione prenderemo in considerazione una base differente per il calcolo<br />
del polinomio interpolante. Invece della canonica base 5.3, esaminiamo i<br />
polinomi nella forma di Lagrange.<br />
80
Risulta che:<br />
Lkn(x) =<br />
n<br />
x − xj<br />
xk − xj<br />
j=0,j=k<br />
Lkn(xi) =<br />
, k = 0, 1, . . .,n (5.5)<br />
1 i = k<br />
0 i = k<br />
Essi hanno grado esatto n e il loro coefficiente principale è :<br />
n<br />
j=0,j=n<br />
1<br />
(xk − xj)<br />
Infatti sviluppando il polinomio di Lagrange, otteniamo<br />
n<br />
x − xj<br />
xk − xj<br />
j=0,j=k<br />
=<br />
n<br />
j=0,j=n<br />
1<br />
(xk − xj)<br />
(5.6)<br />
, k = 0, 1, . . .,n (5.7)<br />
(x − x0) · . . . · (x − xk−1 (x − xk+1) · . . . · (x − xn)<br />
<br />
<br />
k<br />
n−k<br />
(5.8)<br />
Inoltre essendo i polinomi di Lagrange linearmente indipendenti tra di loro,<br />
costituiscono una base per Πn.<br />
Teorema 23 (Forma del polinomio di Lagrange).<br />
pn(x) =<br />
n<br />
fkLkn(x) (5.9)<br />
k=0<br />
Il polinomio 5.9 appartiene a Πn e soddisfa i criteri del polinomio interpolante<br />
definiti nell’equazione 5.2.<br />
dim.<br />
Per ogni i = 0, 1, . . .,n si ha che<br />
⎛<br />
⎞<br />
n<br />
n<br />
p(xi) = fkLkn(xi) = ⎝ fkLkn(xi) ⎠ + fiLin(xi) = fiLin(xi) = fi<br />
k=0<br />
k=0,k=i<br />
Infatti per la 5.6, la sommatoria<br />
n<br />
k=0,k=i<br />
i = k, mentre essendo i = k, Lin(xi) vale 1.<br />
fkLkn(xi), vale sempre zero perché<br />
Esempio 23. Come al solito un esempio ci può chiarire alcuni dubbi che<br />
avevamo. Prendiamo ad esempio il seguente polinomio:<br />
p(x) = − 1<br />
50 x5 + 1<br />
5 x4 − 1<br />
20 x3 + 3x 2 − 20x. (5.10)<br />
Calcoleremo i polinomi interpolanti dal primo grado, fino al quinto grado. Le<br />
coppie (xi, fi) con i = 2, 3, 4, 5, 6, sono state scelte in modo tale che i punti xi<br />
fossero equidistanti. Questo non inficia in alun modo la validità dell’esempio.<br />
Mostriamo quidi i codici matlab che ci sono serviti:<br />
81
Algoritmo 5.1 (Interpolazione con base di lagrange).<br />
function p=lagrange1(xi,fi)<br />
n=length(xi);<br />
L=1;<br />
p=0;<br />
for k=1:n<br />
L=1;<br />
for j=1:n<br />
if k~=j<br />
L=conv(L,[1,-xi(j)])/(xi(k)-xi(j));<br />
end<br />
end<br />
L<br />
p=addVecR(p,(fi(k)*L));<br />
end<br />
return;<br />
Riportiamo anche il codice della funzione addV ecR, che somma i vettori<br />
che rappresentano i polinomi, in modo consistente. Infatti in matlab si possono<br />
sommare solo polinomi di ugual grado con l’operatore +.<br />
Algoritmo 5.2 (Somma di polinomi).<br />
function x=addVecR(A,B)<br />
if length(A)>length(B)<br />
long=A;<br />
short=B;<br />
end<br />
if length(B)>length(A)<br />
long=B;<br />
short=A;<br />
end<br />
if length(B)== length(A)<br />
%non si fa niente perch si possono sommare tranquillamente<br />
x=A+B;<br />
else<br />
short=[zeros(1,length(long)-length(short)),short];<br />
x=long+short;<br />
end<br />
82
Il seguente codice invece è quello che realizza il grafico 5.1.<br />
Algoritmo 5.3 (Esempio di interpolazione con base di Lagrange).<br />
function esempioLagrange(i,a,b)<br />
poly=[-1/50,1/5,-1/20,3,-20,0]<br />
x=[a:0.2:b];<br />
y=polyval(poly,x);<br />
plot(x,y,’k’,’LineWidth’,2);<br />
hold on<br />
color=[’r’,’g’,’b’,’y’,’m’,’c’];<br />
for k=1:i-2<br />
xi=[a:(b-a)/k:b];<br />
fi=polyval(poly,xi);<br />
pol=lagrange1(xi,fi)<br />
y=polyval(pol,x);<br />
plot(x,y,color(k),’LineWidth’,1);<br />
end<br />
In particolare si creano i vari polinomi interpolanti di grado n = 1, 2, . . ., 4.<br />
Per farlo dobbiamo prima prima creare le coppie di valori (xi, fi). Queste potrebbero<br />
essere un dato già conosciuto, ma nel nostro caso le ricaviamo dal polinomio.<br />
I valori xi vengono ricavati semplicemente dividendo l’intervallo [a, b]<br />
in k + 1 parti, per ottenere k + 2 ascisse. Le corrispondenti yi invece vengono<br />
ricavate valutando il polinomio per ogni elemento in xi. Questi due vettori rappresentano<br />
i punti che vanno in input alla funzione 5.1, che una volta eseguita<br />
ritorna il polinomio interpolante. A questo punto per disegnare il polinomio<br />
interpolante, basta valutarlo sulle ascisse x, proprio come abbiamo fatto per il<br />
polinomio di partenza. N.B. sappiamo che il polinomio interpolante esiste ed è<br />
unico. Siccome è unico se provassimo a interpolare un polinomio di grado n con<br />
un altro di pari grado oppure maggiore, otterremo lo stesso identico polinomio!<br />
Nella figura 5.1 possiamo notare i vari polinomi. Distinguendoli per colore<br />
troviamo:<br />
rosso è il polinomio interpolante di grado 1.I suoi punti di interpolazione sono:<br />
xi 0 10<br />
fi 0 −723.84<br />
Il polinomio interpolante è: p(x) = −60.32x<br />
verde è il polinomio interpolante di grado 2.I suoi punti di interpolazione sono:<br />
xi 0 6 12<br />
fi 0 80.88 −723.84<br />
Il polinomio interpolante è: p(x) = −12.3x 2 + 87.28x<br />
83
lu è il polinomio interpolante di grado 3.I suoi punti di interpolazione sono:<br />
xi 0 4 8 12<br />
fi 0 −4.48 170.24 −723.84<br />
Il polinomio interpolante è: p(x) = −3.25x 3 + 44.6x 2 − 127.52x<br />
giallo è il polinomio interpolante di grado 4.I suoi punti di interpolazione sono:<br />
xi 0 3 6 9 12<br />
fi 0 −23.01 80.88 157.77 −723.84<br />
Il polinomio interpolante è: p(x) = −0.4x 4 − 6.25x 3 − 24x 2 − 18.8x<br />
200<br />
100<br />
0<br />
−100<br />
−200<br />
−300<br />
−400<br />
−500<br />
−600<br />
−700<br />
−0.02 x 5 + 0.2x 4 −0.05x 3 +3x 2 −20x<br />
−60.32x<br />
−12.3x 2 +87.28x<br />
−3.25x 3 +44.6x 2 −127.52x<br />
−0.4x 4 +6.25x 3 −24x 2 +18.88x<br />
−800<br />
0 2 4 6 8 10 12<br />
Figura 5.1: Grafico dei polinomi interpolanti la funzione 5.10<br />
Con la forma di Lagrange, se volessimo aggiungere un ascissa di interpolazione,<br />
dovremmo rieseguire di nuovo l’algoritmo con i nuovi punti (xi, fi),<br />
ricostruendo tutte le informazioni necessarie. La forma di Newton, risolve questo<br />
problema, rendendo possibile una costruzione incrementale del polinomio,<br />
cioè a partire dal polinomio di grado n, pn(x), possiamo ottenere pn+1(x). Per<br />
farlo prendiamo in considerazione una diversa base per rappresentare i polinomi.<br />
Definizione 11 (Base di Newton).<br />
Quindi:<br />
ω0(x) ≡ 1 (5.11)<br />
ωk+1 ≡ (x − xk) · ωk(x) k = 0, 1, . . . (5.12)<br />
ωk+1 =<br />
k<br />
(x − xj) (5.13)<br />
j=0<br />
I polinomi di newton godono delle seguenti proprietà:<br />
• ωk(x) ∈ Π ′ k dove Π ′ k<br />
rappresentano i polinomi monici di grado k.<br />
84
dim. Possiamo dimostrare questa proprietà per induzione sul grado del<br />
polinomio. La base dell’induzione risulta vera; infatti ω0(x) = 1 per definizione<br />
risulta appartenere a Π ′ 0. Per ipotesi induttiva, ωk ∈ Π ′ k . Dalla<br />
definizione 5.12, ωk+1 = (x − xj) · ωk(x).Moltiplicando un polinomio di<br />
grado 1 con un altro di grado k, il risultato è un polinomio di grado k +1.<br />
• ωk+1(x) =<br />
k<br />
x − xj<br />
j=0<br />
• ωk+1(xi) = 0, per i ≤ k<br />
dim.<br />
ωk+1(xi) =<br />
k<br />
(xi − xj) = (xi − x0) · . . . · (xi − xi) · . . . · (xi − xk) = 0<br />
j=0<br />
• ω0(x), . . . , ωk(x), costituiscono una base per Πk.<br />
Enunciamo allora il teorema per la definizione del polinomio interpolante con<br />
base di Newton:<br />
Teorema 24. I polinomi interpolanti che soddisfano i seguenti criteri di interpolazione,<br />
pr(x) ∈ Πr<br />
pr(xi) = fi , i = 0, . . . , r<br />
si possono generare in modo ricorsivo nel seguente modo:<br />
p0(x) = f0ω0(x) (5.14)<br />
pr(x) = pr−1 + f[x0, x1, . . . , xr]ωr(x), r = 1, . . .,n (5.15)<br />
f[x0, x1, . . . , xr] è la differenza divisa , ed è definita così:<br />
f[x0, x1, . . . , xr] =<br />
r<br />
k=0<br />
r<br />
j=0,j=k<br />
fk<br />
(xk − xj)<br />
(5.16)<br />
dim.(per induzione) La base della dimostrazione è verificata, perché quando<br />
r = 0, per definizione (vedi 5.11), abbiamo che<br />
p0(x) = f0ω0(x) = f0<br />
Per ipotesi supponiamo che la tesi sia dimostrata per r − 1. Dimostriamo che<br />
pr(x) ∈ Πr. ωr(x) ∈ Π ′ r, inoltre per ipotesi induttiva, pr−1(x) ∈ Πr−1;Risulta<br />
evidente che sommando pr−1(x) e f[x0, . . .,xr]ωr(x) si ottiene che pr(x) ∈ Πr.<br />
Si distinguono due casi<br />
• i < r<br />
pr(xi) = pr−1(xi) + f[x0, . . . , xr]ωr(xi) = pr−1(xi) = fi<br />
ωr(xi) = 0 e pr−1(xi) = fi risulta vero per ipotesi induttiva.<br />
85
• i = r<br />
pr(xr) = pr−1(xr) + f[x0, . . . , xr]ωr(xi) = pr−1(xr) = fr<br />
L’ultima uguaglianza, è stata imposta.Esprimiamo la differenza divisa in<br />
funzione di fr.<br />
f[x0. . . . xr] = fr − pr−1(xr)<br />
(5.17)<br />
ωr(xr)<br />
Dobbiamo dimostrare che la 5.16 e la 5.17 hanno la stessa forma.<br />
f[x0. . . . xr] = fr − pr−1(xr)<br />
ωr(xr)<br />
= fr pr−1(xr)<br />
−<br />
ωr(xr) ωr(xr)<br />
Esprimiamo il polinomio di grado r nella forma di Lagrange (vedi 5.9):<br />
fr 1<br />
−<br />
r−1 <br />
r−1 <br />
(xr − xj) (xr − xj)<br />
j=0<br />
fr<br />
j=0<br />
=<br />
−<br />
r−1 <br />
(xr − xj)<br />
j=0<br />
fr<br />
=<br />
r−1 <br />
(xr − xj)<br />
j=0<br />
fr<br />
=<br />
r−1 <br />
(xr − xj)<br />
j=0<br />
=<br />
fr<br />
1<br />
xr − xk<br />
r−1<br />
−<br />
<br />
r−1<br />
· fk ·<br />
fk<br />
k=0<br />
r−1<br />
·<br />
k=0<br />
xr − xk<br />
k=0<br />
r−1<br />
+<br />
=<br />
r−1 <br />
(xr − xj)<br />
j=0<br />
r<br />
j=0,j=r<br />
fr<br />
(xr − xj)<br />
=<br />
xk − xr<br />
k=0<br />
r<br />
k=0<br />
fk<br />
r−1<br />
+<br />
k=0<br />
r−1<br />
+<br />
r<br />
k=0<br />
j=0,j=k<br />
·<br />
·<br />
r<br />
j=0,j=k<br />
fk<br />
r−1 <br />
j=0,j=k<br />
r−1 <br />
j=0,j=k<br />
r−1 <br />
j=0,j=k<br />
r−1 <br />
j=0,j=k<br />
r−1 <br />
j=0,j=k<br />
r<br />
fk<br />
j=0,j=k<br />
(xk − xj)<br />
fk<br />
(xr − xj)<br />
(xk − xj)<br />
(xk − xj)<br />
1<br />
(xk − xj)<br />
1<br />
(xk − xj)<br />
fk<br />
(xk − xj)<br />
=<br />
(xk − xj)<br />
Teorema 25. Mostriamo le proprietà delle quali gode la differenza divisa:<br />
86<br />
=<br />
=<br />
=<br />
=<br />
=
• Se<br />
Allora<br />
f , g : [a, b] → R α, β ∈ R<br />
(α · f + β · g)[x0, . . . , xr] = α · f[x0, . . . , xr] + β · g[x0, . . . , xr] (5.18)<br />
• Per ogni {i0, i1, . . .,ir} permutazione dell’insieme {0, 1, . . ., r} risulta che<br />
f[xi0, xi1, . . .,xir] = f[x0, x1, . . . , xr] (5.19)<br />
In definitiva questa proprietà dice che cambiando l’ordine delle ascisse la<br />
differenza divisa non cambia.<br />
• Sia f ∈ Πl con l ≤ r, allora<br />
dim.<br />
pr(x) =<br />
f[x0, x1, . . .,xr] =<br />
ak se l = r<br />
0 se l < r<br />
(5.20)<br />
n<br />
akx k = f[x0]+f[x0, x1]ω1(x)+. . .+f[x0, x1, . . . , xr]ωr(x) ≡ f(x)<br />
k=0<br />
• Se f ∈ C (r) ([a, b]), insieme di funzioni derivabili r volte, allora<br />
•<br />
f[x0, x1, . . . , xr] = f(r) (ξ)<br />
r!<br />
ξ ∈ [min<br />
i xi, max<br />
k xk] (5.21)<br />
⎧<br />
⎨ f0 ≡ f(x0) se r = 0<br />
f[x0, x1, . . .,xr] =<br />
⎩ f[x1,...,xr]−f[x0,...,xr−1]<br />
altrimenti<br />
xr−x0<br />
(5.22)<br />
dim.(per induzione) Verifichiamo che la base k = 1 è soddisfatta. Per<br />
definizione abbiamo che<br />
f[x0, x1] =<br />
1<br />
i=0<br />
1<br />
j=0,j=i<br />
fi<br />
(xi − xj)<br />
=<br />
f0<br />
x0 − x1<br />
+ f1<br />
x1 − x0<br />
= f1 − f0<br />
x1 − x0<br />
La base quindi è soddisfatta. Per ipotesi induttiva risulta vero fino a k-<br />
1. Partendo dalla definizione otteniamo la differenza di ordine k da due<br />
differenze divise di ordine k − 1.<br />
f[x1, . . . , xk]−f[x0, . . .,xk−1] =<br />
k<br />
i=1<br />
87<br />
k<br />
j=1,j=i<br />
fi<br />
(xi − xj)<br />
k−1 <br />
−<br />
i=0<br />
k−1 <br />
j=1,j=i<br />
fi<br />
(xi − xj)<br />
=
Moltiplichiamo il numeratore e il denominatore del primo addendo per<br />
(xi − x0) e del secondo addendo per (xi − xk), in modo tale da rendere i<br />
denominatori e le sommatorie uguali<br />
=<br />
k<br />
i=0<br />
k<br />
j=0,j=i<br />
=<br />
fi<br />
k<br />
i=0<br />
(xi − xj)<br />
fi(xi − x0)<br />
k<br />
−<br />
(xi − xj)<br />
j=0,j=i<br />
k<br />
i=0<br />
fi(xi − xk)<br />
k<br />
(xi − xj)<br />
j=0,j=i<br />
·(xi−x0−xi+xk) = (xk −x0)·<br />
k<br />
i=0<br />
k<br />
j=0,j=i<br />
fi<br />
(xi − xj)<br />
Presentiamo adesso un algoritmo per il calcolo di un punto x in un polinomio.<br />
Algoritmo 5.4 (Agoritmo di Horner).<br />
function p=horner(a,x)<br />
%INPUT<br />
% a il vettore dei coefficienti<br />
% del polionomio p e del quale si vuole calcolare<br />
% p(x)<br />
% x il punto per il quale si calcola p(x)<br />
n=length(a);<br />
p=Coefficienti(n);<br />
for i=n-1:-1:1<br />
p=x*p +a(i);<br />
end<br />
Il funzionamento del precedente algoritmo è molto semplice. Come abbiamo<br />
già visto, la forma canonica del polinomio è:<br />
p(x) =<br />
Sviluppando la sommatoria otteniamo:<br />
n<br />
akx k<br />
k=0<br />
p(x) = a0 + a1x + a2x 2 + . . . + anx n<br />
manipoliamo questa espressione per avere una forma ricorsiva<br />
p(x) = a0 + x(a1 + x(a2 + x(. . . + x(an))))<br />
Presentiamo l’algoritmo per il calcolo della differenza divisa di ordine n<br />
Algoritmo 5.5 (Algoritmo per il calcolo della differenza divisa).<br />
88
function f=differenzaDivisa(x,f,n)<br />
%Questa function calcola le differenze divise<br />
%fino all’ordine n.<br />
%<br />
%INPUT<br />
% x il vettore delle ascisse<br />
% f il vettore delle ordinate ottenute da f(x)<br />
% n l’ordine della differenza divisa<br />
if(n>length(x)-1)<br />
message1=(’La differenza divisa non pu avere un ordine ’);<br />
message2=(’maggiore del numero delle ascisse pi uno’);<br />
error([message1,message2]);<br />
end<br />
for i=1:n<br />
for j=n+1:-1:i+1<br />
f(j)=(f(j)-f(j-1))/(x(j)-x(j-i));<br />
end<br />
end<br />
Algoritmo 5.6 (Algoritmo di Hornerper la valutazione del polinomio interpolante<br />
di Newton).<br />
function p=hornerNewton(xx,x,f,n)<br />
%<br />
%hornerNewton, calcola il valore del polinomio<br />
%interpolante nei punti dati dal vettore xx<br />
%<br />
%INPUT<br />
% xx punti da valutare<br />
% x ascisse del polinomio<br />
% f vettore delle differenze divise<br />
P=zeros(1,length(f));<br />
n=length(f)-1;<br />
l=length(xx);<br />
for i=1:l<br />
p(i)=f(n+1)<br />
for k=n:-1:1<br />
p(i)=f(k)+(p(i)*(xx(i)-x(k)));<br />
end<br />
end<br />
Come è stato fatto per l’algoritmo 5.4, dimostriamone la correttezza. Il<br />
89
polinomio con interpolante con la base di Newton, ha la seguente forma:<br />
pn(x) =<br />
n<br />
f[x0, . . .,xi]ωi(x)<br />
i=0<br />
Sviluppando la sommatoria e rinominando per semplicità la differenza divisa<br />
f[x0, . . . , xi] con Ai, otteniamo<br />
pn(x) = A0ω0(x) + A1ω1(x) + . . . + Anωn(x)<br />
Sostituaimo il simbolo di omega con la parte destra dell’equazione della definizione<br />
5.13 della base di Newton.<br />
pn(x) = A0 ·1+A1 ·(x−x1)+A2 ·(x−x1)(x−x2)+. . .+An ·(x−x1)...(x−xn)<br />
Mettiamo in evidenza i fattori (x − xi)<br />
A0 + (x − x1) · (A1 + (x − x2) · (A2 + (x − x3) · (. . . An−1 + (x − xn) · (An))))<br />
5.3 Interpolazione di Hermite<br />
L’idea che sta alla base dell’interpolazione di Hermite, è quella di interpolare in<br />
un punto sia la funzione sia la sua derivata. Questo è possibile grazie a qualche<br />
accorgimento. Le ascisse quindi saranno un numero dispari:<br />
n = 2m + 1, m = 0, 1, . . . (5.23)<br />
Supponiamo queste ascisse tutte distinte. Se facciamo tendere le ascisse di indice<br />
dispari, all’ascissa di indice pari minore<br />
x2i+1 −→ x2i i = 0, 1, . . ., m<br />
e supponendo che la funzione da interpolare f(x) ∈ C (1) , possiamo scrivere<br />
f(x2i+1) − f(x2i)<br />
x2i+1 − x2i<br />
= f[x2i, x2i+1] −→ f ′ (x2i) i = 0, 1, . . .,m (5.24)<br />
Come possiamo notare dall’equazione precedente, il rapporto incrementale è<br />
proprio la differenza divisa, e se x2i+1 −→ x2i, questo tende alla derivata della<br />
funzione nel punto x2i. Risulta quindi che<br />
p(x2i) = f(x2i), p ′ (x2i) = f ′ (x2i), i = 0, 1, . . ., m<br />
Rinumerando le ascisse nel seguente modo<br />
x0 = x0 < x1 = x1 < . . . < xm = xm<br />
possiamo esprimere il polinomio di Hermite:<br />
(5.25)<br />
p(x) = f[x0] + f[x0, x0](x − x0)+<br />
+f[x0, x0, x1](x − x0) 2 +<br />
+f[x0, x0, x1, x1](x − x0) 2 (x − x1)+<br />
+f[x0, x0, x1, x1, x2](x − x0) 2 (x − x1) 2 + . . .+<br />
+ . . . + f[x0, x0, x1, x1, . . .,...,xm, xm](x − x0) 2 . . . (x − xm−1) 2 (x − xm)<br />
90
5.4 Errore nell’interpolazione<br />
In questa sezione vogliamo valutare l’errore di interpolazione come una differenza:<br />
en(x) = f(x) − pn(x) (5.26)<br />
Evidentemente, en(xi) = 0 per ogni i = 0, . . .,n, in quanto deve soddisfare le<br />
condizioni di interpolazione (vedi 5.1 e 5.2). Se prendiamo un punto generico<br />
ˆx = xi per i = 0, 1, . . ., n risulta che:<br />
<br />
ˆpn(xi) = fi i = 0, . . .,n<br />
ˆpn+1(x) ∈ Πn+1<br />
ˆpn(ˆx) = f(ˆx)<br />
Quindi<br />
Risulta inoltre che<br />
In più se f ∈ C n+1 allora<br />
ˆpn+1(ˆx) = pn(ˆx) + f[x0, . . . , xn, ˆx] · ωn+1(ˆx) = f(ˆx)<br />
e(ˆx) = f(ˆx) − pn(ˆx) = f[x0, . . . , xn, ˆx] · ωn+1(ˆx)<br />
en(x) = fn+1 (ξ)<br />
(n + 1)! ωn+1(x) ξ ∈ (min<br />
i xi, max<br />
i xi) (5.27)<br />
Riguardo a questa ultima espressione di e(x), possiamo fare alcune considerazioni:<br />
• Se x ∈ {xi} con i = 0, . . .n, allora ωn+1(x) si annulla e di conseguenza<br />
anche l’errore<br />
• Se x ∈ [x0, xn] e x = xi con i = 0, . . .n, allora l’errore oscilla intorno alla<br />
funzione in un range limitato.<br />
• Se non si verifica nessuna condizione delle precedenti, ovvero se x /∈<br />
[x0, xn], allora |ωn+1(x)| ha l’andamento della funzione |x n+1 |.<br />
In definitiva, l’interpolazione a partire da un set di coppie (xi, fi), ha senso solo<br />
se si sceglie un x ∈ [x0, xn].<br />
Esempio 24 (Stima errore di interpolazione). Siamo interessati a stimare quante<br />
ascisse equidistanti di interpolazione sono necessarie per approssimare la<br />
funzione sin(x) sull’intervallo [0, 2π], con un errore di interpolazione inferiore<br />
a 10 −6 . Prendendo in esame l’espressione 5.27 dell’errore di interpolazione,<br />
possiamo fare qualche analisi. Analiziamola fattore per fattore:<br />
• f (n+1) (ξx): la funzione sin in questo caso ci viene in aiuto e non ci complica<br />
le cose.Le derivate di questa funzione sono ±sin(x) e ±cos(x), a<br />
seconda dell’ordine della derivata.In ogni caso sappiamo che<br />
f (n+1) (ξx) ≤ 1 per ξx ∈ [0, 2π]<br />
• ωn+1(x): Nell’intervallo [0, 2π] possiamo dire che<br />
|x − xj| < 2π<br />
Quindi se consideriamo che l’intera produttoria della base di Newton è<br />
costituita da n + 1 fattori possiamo fare la seguente stima:<br />
|ωn+1(x)| < (2π) n+1<br />
91
Quindi stimiamo il nostro errore come<br />
en(x) = (2π)n+1<br />
(n + 1)!<br />
(5.28)<br />
Procediamo alla stima del valore di n, tale che la 5.28 sia minore di 10 6 , in<br />
modo non nalitico. La soluzione quindi è stata ottenuta col seguente script di<br />
matlab<br />
Algoritmo 5.7.<br />
f=inline(’((2*pi).^(x+1))./(factorial(x+1))’);<br />
n=0;<br />
tol=10^-6;<br />
while(f(n)>= tol)<br />
n=n+1;<br />
end<br />
printf(’L errore e’ inferiore a %d per n=%d’,tol,n);<br />
x=[0:1:40];<br />
y=f(x);<br />
plot(x,y,’k’);<br />
Questo script restituisce in output il seguente risultato e il grafico dell’andamento<br />
dell’errore al crescere del numero di ascisse di interpolazione equidistanti.<br />
L errore e’ inferiore a 1.0000e-06 per n=26<br />
90<br />
80<br />
70<br />
60<br />
50<br />
40<br />
30<br />
20<br />
10<br />
(2 ⋅ π) (n+1) /(n+1)!<br />
0<br />
0 5 10 15 20 25 30 35 40<br />
Come si può vedere dal grafico, per valori di n < 5, il fattore ωn+1(x) domina<br />
sul fattoriale, facendo innalzare molto l’errore. Invece per valori di n > 6, il<br />
fattoriale prende il sopravvento, riducendo a zero l’errore per n → ∞. Come<br />
vedremo nella prossima sezione, risulta controproducente innalzare il numero di<br />
ascisse in modo indiscriminato. Infatti all’aumentare del numero delle ascisse<br />
il problema diventa mal condizionato.<br />
92
5.5 Condizionamento del problema<br />
Consideriamo il polinomio interpolante di grado n, pn(x), ottenuto dai dati<br />
in ingresso, ovvero le coordinate (xi, fi). Assumiamo che l’errore sui dati in<br />
ingresso sia solo sulla funzione e non sulle ascisse. Quindi i dati in ingresso<br />
risultano essere le coppie di valori (xi, ˜ fi), dove ˜ fi = ˜ f(xi). siamo interessati a<br />
valutare quindi<br />
|pn(x) − ˜pn(x)| (5.29)<br />
Il polinomio che usiamo per questo caso, è quello di Lagrange<br />
i=0<br />
p(x) =<br />
˜pn(x) =<br />
n<br />
fiLin(x)<br />
i=0<br />
n<br />
˜fiLin(x)<br />
i=0<br />
Quindi la 5.29 diventa<br />
<br />
n<br />
n<br />
<br />
<br />
<br />
|pn(x) − ˜pn(x)| = fiLin(x) − ˜fiLin(x)<br />
<br />
<br />
<br />
=<br />
<br />
n <br />
(fi −<br />
<br />
˜ <br />
<br />
<br />
fi) · Lin(x) <br />
<<br />
i=0<br />
i<br />
i=0<br />
n <br />
<br />
< (fi − ˜ <br />
<br />
fi) · Lin(x) ≤ max f(xi) − ˜ n<br />
<br />
<br />
<br />
f(xi) · |Lin(x)| ≡ max fi −<br />
i<br />
˜ <br />
<br />
fi·Λn<br />
Λn(x) è la funzione di Lebesgue, che dipende solo dalle ascisse di interpolazione.<br />
Consideriamo allora un intervallo [a, b]. Definiamo la norma di una funzione<br />
come<br />
||f|| = max<br />
a≤x≤b |f(x)|<br />
Da questa definizione otteniamo che<br />
i=0<br />
i=0<br />
||pn − ˜pn|| ≤ maxi|fi − ˜ fi| · ||Λn|| ≤ ||f − ˜ f|| · Λn<br />
(5.30)<br />
Λn in questo caso diventa la costante di Lebesgue. ||pn−˜pn|| rappresenta i dati in<br />
uscita, ||f − ˜ f|| rappresenta i dati in ingresso. Risulta evidente che Λn è il numero<br />
di condizionamento del problema. Ma come sono correlati l’approssimazione e<br />
l’errore?<br />
Teorema 26 (Polinomio di miglior approssimazione). Se f ∈ C (0) continua<br />
nell’intervallo [a, b], allora per ogni n ∈ N esiste p ∗ (x) ∈ Πn tale che<br />
||f − p ∗ || = min ||f − p||<br />
p∈Πn<br />
p ∗ (x) ∈ Πn è il polinomio che meglio approssima f(x) di grado al più n.<br />
Teorema 27.<br />
dim.<br />
||e|| ≤ (1 + Λn) · ||f − p ∗ ||<br />
||e|| = ||f − p|| = ||f − p ∗ + p ∗ − p|| ≤ ||f − p ∗ ||+||p − p ∗ ||<br />
<br />
Λn||f−p ∗ ≤ (1+Λn)·||f − p<br />
||<br />
∗ ||<br />
93
Definizione 12. Si definisce modulo di continuità di una funzione il valore<br />
ω(f; h), dove<br />
ω(f; h) ≡ max {|f(x) − f(y)| : |x − y| ≤ h} (5.31)<br />
Proprietà:<br />
• Se f è continua, allora lim<br />
h→0 ω(f; h) = 0<br />
• Se f è Lipschitziana con costante L, allora ω(f; h) ≤ L·h f è Lipschitziana<br />
con costante L se<br />
|f(x) − f(y)| ≤ L · |x − y|<br />
Quindi se f ∈ C (1) allora L = ||f ′ ||. dim.<br />
Quindi L = f ′ .<br />
|f(x) − f(y)| = |f(x) − f(x) − f ′ (x)(x − y)| ≤ L · |x − y|<br />
Teorema 28 (Jackson). Se f ∈ C (0) allora esiste α indipendente da n tale che:<br />
Lemma 3.<br />
||f − p ∗ || ≤ α · ω(f;<br />
||e|| ≤ α · (1 + Λn) · ω(f;<br />
b − a<br />
) (5.32)<br />
n<br />
b − a<br />
n )<br />
Al crescere di n, Λn cresce, mentre ω(f; b−a<br />
n ) decresce.<br />
Passando alle norme, l’equazione 5.27, diventa<br />
<br />
<br />
||e|| ≤<br />
f (n+1) <br />
(n + 1)!<br />
||wn+1||<br />
Per riuscire a minimizzare l’errore, dobbiamo agire sulla scelta delle ascisse di<br />
interpolazione. Notiamo però che il primo fattore del secondo membro non<br />
dipende da questa scelta. Per questo il problema di minimizzare l’errore si<br />
riduce a minimizzare la quantità ||ωn+1||. In definitiva il nuovo problema da<br />
risolvere è:<br />
min<br />
a≤x0
Delle proprorzioni sappiamo che il prodotto degli estremi è uguale al prodotto<br />
dei medi. Quindi abbiamo che<br />
˜x =<br />
b − a<br />
2<br />
Questo appunto rappresenta l’offset dal centro dell’intervallo.<br />
Teorema 30. Per ogni a, b, se ˜x ∈ [a, b], allora x ∈ [−1, 1], dove<br />
x =<br />
· x<br />
2˜x − a − b<br />
b − a<br />
Come prima l’offset è individuato, ricavando la x dalla proporzione 5.34 ottendendo:<br />
x = 2˜x<br />
b − a<br />
Affinché al x ∈ [−1, 1] dobbiamo sottrarre la quantità b+a<br />
b−a .<br />
Teorema 31. È sempre possibile trasformare un problema di interpolazione definito<br />
sulle ascisse nell’intervallo [a, b], in uno definito sulle ascisse dell’intervallo<br />
[−1, 1] e viceversa. La dimostrazione discende immediatamente dai teroremi<br />
29 e 30<br />
5.6 Ascisse di Chebyshev<br />
Definizione 13 (Polinomi di Chebishev di prima specie). Si definiscono in<br />
modo ricorsivo:<br />
Proprietà:<br />
T0(x) ≡ 1 (5.35)<br />
T1(x) = x (5.36)<br />
Tk+1(x) = 2xTk(x) − Tk−1(x), k = 1, 2, . . . (5.37)<br />
• Tk(x) è un polinomio di grado esatto K.<br />
• Il coefficiente principale di Tk(x) è 2 k−1 per k ≥ 1.<br />
• Le famiglie di polinomi ˆ Tk(x) = 2 1−k Tk(x) è una famiglia di polinomi<br />
monici di grado k.<br />
• Sia x = cosθ con θ ∈ [0, π], allora possiamo parametrizzare i punti<br />
dell’intervallo [−1, 1] rispetto a θ, ottenendo:<br />
dim.(per induzione)<br />
Per k = 0 è ovvio.<br />
Tk(x) ≡ Tk(cosθ) = coskθ<br />
T0(x) ≡ 1 Per definizione ma cos0 ≡ 1<br />
95
Per k + 1 abbiamo che<br />
Tk+1(cosθ) = 2 cosθTk(cosθ)−Tk−1(cos θ) = 2 cosθ coskθ−cos(k − 1)θ =<br />
= 2 cosθ coskθ − (coskθ cosθ + sin kθ sin θ) =<br />
2 cosθ coskθ − cosθ coskθ − sin θ sin kθ = cos(k + 1)θ<br />
• Le radici di Tk(x) sono date da<br />
x (k)<br />
<br />
2i + 1 π<br />
i = cos<br />
k 2<br />
• ||Tk|| = 1<br />
<br />
<br />
• <br />
ˆ <br />
<br />
Tk<br />
= <br />
1−k 2 Tk<br />
1−k = 2<br />
•<br />
<br />
<br />
<br />
ˆ <br />
<br />
Tk<br />
= min<br />
p∈Π ′ n+1<br />
||p|| = 2 1−k<br />
i = 0, . . .,k − 1<br />
Scegliendo le seguenti ascisse di interpolazione per l’intervallo [−1, 1]<br />
<br />
(2i + 1)π<br />
xi = cos<br />
(5.38)<br />
2(n + 1)<br />
si ottiene<br />
ωn+1(x) =<br />
n<br />
(x − xi) ≡ ˆ Tn+1(x) (5.39)<br />
i=0<br />
che risulta essere la soluzione per il problema di minmassimo 5.33 Con la scelta<br />
dei nodi 5.38, otteniamo il seguente errore<br />
<br />
<br />
||e|| =<br />
f (n+1) <br />
(n + 1)!2n (5.40)<br />
Di conseguenza, la costante di Lebesgue diventa<br />
Λn ≈ 2<br />
log n (5.41)<br />
π<br />
Questa costante risulta avere un buon andamento per n → ∞. Se volessimo<br />
generalizzare le ascisse 5.38 per un generico intervallo [a, b], la definizione delle<br />
ascisse cambierebbe in<br />
xn−i =<br />
<br />
a + b b − a (2i + 1)π<br />
cos<br />
2 2 2(n + 1)<br />
5.7 Interpolazione mediante funzioni spline<br />
(5.42)<br />
Vediamo adesso un altro apporccio per approssimare una funzione e minimizzare<br />
l’errore:<br />
b − a<br />
||e|| ≤ α · (1 + Λn) · ω(f;<br />
n )<br />
96
Abbiamo visto che al crescere di n, la costante Λn cresce. Se invece n assume<br />
valori bassi, l’ultimo fattore, non può avere valori bassi. Consideriamo allora la<br />
partizione ∆ = {a = x0, < x1 < . . . < xn = b}, per la quale si abbia<br />
h = max<br />
i=1,...,n (xi − xi−1) → 0 per n → ∞ (5.43)<br />
Su ogni sottointervallo [xi, xi−1], prendiamo il polinomio di grado m (fissato a<br />
priori), che interpola la funzione nei punti estremi all’ntervallo, ovvero<br />
pm(xi) = f(xi)<br />
pm(xi−1) = f(xi−1)<br />
(5.44)<br />
Così facendo, il condizionamento del problema rimane sotto controllo, essendo<br />
m fissato. In più se f ∈ C (0) , il fattore ω(f; h) → 0 per n → ∞<br />
Definiamo spline di grado m sulla partizione ∆ la funzione che ha i seguenti<br />
requisiti:<br />
• sm(x) ∈ C (m−1) nell’intervallo [a, b]<br />
<br />
<br />
[xi−1,xi](x) ∈ Πm per i = 1, . . .,n<br />
• sm<br />
Inoltre se vale la seguente condizione<br />
sm(xi) = fi per i = 0, 1, . . ., n (5.45)<br />
la spline interpola la funzione nei nodi della partizione. Sappiamo che sono<br />
necessarie m + n condizioni indipendenti per determinare in modo univoco la<br />
spline interpolante nella partizione ∆. Noi però abbiamo n + 1 condizioni di<br />
interpolazione, e questo ci consente di di individuare univocamente solo le spline<br />
di grado 1, ovvero le spline lineari. La spline lineare viene individuata dalla<br />
seguente equazione<br />
<br />
s1 <br />
[xi−1,xi](x) = (x − xi−1)fi + (xi − x)fi−1<br />
(xi − xi−1)<br />
i = 1, . . .,n (5.46)<br />
Esempio 25 (spline lineare). Matlab, mette a disposizione la funzione interpol.<br />
Il codice per l’esempio è il seguente:<br />
xx=[0:0.02:10];<br />
x=[0:1:10];<br />
y=sin(x);<br />
yy=interp1(x,y,xx,’linear’);<br />
plot(xx,yy,’k’);<br />
La funzione da interpolare è sin(x) nelle ascisse della partizione ∆ = [0, 1, . . .,10].<br />
I parametri di input sono i vettori delle ascisse e delle ordinate dei nodi<br />
di interpolazione (x e y), il vettore delle ascisse di valutazione del polinomio<br />
interpolante, e il tipo di interpolazione. Se xx è un vettore, allora yy = s1(xx);<br />
La figura 5.2, mostra la spline interpolante la funzione sin(x) sui nodi (xi, yi).<br />
97
1<br />
0.8<br />
0.6<br />
0.4<br />
0.2<br />
0<br />
−0.2<br />
−0.4<br />
−0.6<br />
−0.8<br />
−1<br />
0 1 2 3 4 5 6 7 8 9 10<br />
5.8 Spline cubiche<br />
Figura 5.2: Grafico della spline lineare.<br />
La spline cubica prende il suo nome dal grado del polinomio interpolante che<br />
è 3. Ci sono vari tipi di spline cubiche, a seconda delle condizioni imposte per<br />
l’unicità.<br />
• Spline naturale<br />
La condizione aggiuntiva da imporre è<br />
s ′′<br />
3(a) = 0 s ′′<br />
3(b) = 0 (5.47)<br />
• not-a-knot<br />
Le condizioni per definire una spline not-a-knot, sono le seguenti<br />
s ′′<br />
3(x1) − s ′′<br />
3(x0)<br />
x1 − x0<br />
s ′′<br />
3(xn) − s ′′<br />
3(xn − 1)<br />
xn − xn−1<br />
= s′′ 3(x2) − s ′′<br />
3(x1)<br />
= s′′<br />
x2 − x1<br />
3(xn−1) − s ′′<br />
3(xn−2)<br />
xn−1 − xn−2<br />
(5.48)<br />
(5.49)<br />
Teorema 32. s ′′′<br />
<br />
<br />
<br />
3 [xi,xi−1](x) ∈ Π0. Infatti se sm <br />
[xi,xi−1](x) ∈ Πm la sua<br />
derivata prima sarà un polinomio di grado m − 1. Procedendo per induzione<br />
si vede facilmente che la sua derivata m-esima è un polinomio appartentente a<br />
Π0.<br />
5.9 <strong>Calcolo</strong> spline cubica<br />
Per semplicità ridefiniamo le seguenti variabili<br />
mi = s ′′<br />
3(xi) i = 0, 1, . . .,n (5.50)<br />
hi = xi − xi−1 i = 0, 1, . . .,n (5.51)<br />
98
Con queste definizioni, le condizioni 5.48 e 5.49 diventano:<br />
(h1 + h2)m1 = h2m0 + h1m2 (5.52)<br />
(hn−1 + hn)mn−1 = hnmn−2 + hn−1mn (5.53)<br />
Infatti sostituendo la parte destra con la parte sinistra delle equazioni 5.50 e<br />
5.51, abbiamo che<br />
m1<br />
h1<br />
m1<br />
h1<br />
− m0<br />
h1<br />
+ m1<br />
h2<br />
h2m1 + h1m1<br />
h1h2<br />
= m2<br />
h2<br />
= m0<br />
h1<br />
− m1<br />
h2<br />
+ m2<br />
h2<br />
= h2m0 + h1m2<br />
h1h2<br />
m1(h2 + h1) = h2m0 + h1m2<br />
(5.54)<br />
Analogamente si può fare per la seconda condizione not-a-knot 5.49, che diventa<br />
mn−1(hn + hn−1) = hnmn−2 + hn−1mn<br />
(5.55)<br />
Dal teorema 32, se s3(x) è una spline cubica allora s ′ 3 (x) è una spline di secondo<br />
grado e s ′′<br />
3(x) è una spline lineare. Quindi possiamo scrivere che<br />
s ′′<br />
<br />
<br />
3 [xi,xi−1](x) = (xi − xi−1)mi + (xi − x)mi−1<br />
hi<br />
Integrando la precedente equazione otteniamo<br />
<br />
s ′′<br />
<br />
<br />
3 [xi,xi−1](x) = s ′ 3(x) = (x − xi−1) 2mi + (xi − x) 2mi−1 + qi<br />
2hi<br />
(5.56)<br />
(5.57)<br />
dove qi è la costante di integrazione.Reintegrando ulteriormente otteniamo<br />
<br />
s ′ <br />
<br />
3 [xi,xi−1](x) = s3(x) = (x − xi−1) 3mi + (xi − x) 3mi−1 + qi(x − xi−1) + ri<br />
6hi<br />
(5.58)<br />
dove ri è un altra costante di integrazione. Calcoliamo adesso le due costanti<br />
di integrazione qi e ri. Dobbiamo imporre la condizione di interpolazione 5.45.<br />
Così sostituendo in x il valore xi−1, otteniamo<br />
<br />
s3 <br />
[xi−1,xi](xi−1) = h2i 6 mi−1 + ri = fi−1<br />
Ricaviamo ri dll’espressione precedente:<br />
ri = fi−1 − h2 i<br />
6 mi−1<br />
(5.59)<br />
(5.60)<br />
Analogamente imponiamo la condizione di interpolazione al fine di ricavare la<br />
costante di integrazione qi<br />
<br />
s3 <br />
[xi−1,xi](xi) = h2i 6 mi + qihi + fi−1 − h2i 6 mi−1<br />
<br />
99<br />
ri<br />
= fi<br />
(5.61)
qi = fi − fi−1<br />
hi<br />
− mi − mi−1<br />
hi = f[xi−1, xi] −<br />
6<br />
hi<br />
6 (mi − mi−1) (5.62)<br />
Quindi l’equazione della derivata prima della spline cubica diventa<br />
s ′ <br />
<br />
3 [xi−1,xi](x) = (x − xi−1) 2mi + (xi − x) 2mi−1 + f[xi−1, xi] −<br />
2hi<br />
hi<br />
6 (mi − mi−1)<br />
(5.63)<br />
Ancora i valori mi sono incogniti.Per calcolarli dobbiamo imporre la condizione<br />
s ′ <br />
<br />
3 [xi−1−xi](xi) = s ′ <br />
<br />
3 [xi−xi+1](xi) (5.64)<br />
Dalla 5.64 e 5.63, otteniamo<br />
hi<br />
2 mi+f[xi−1, xi]− hi<br />
6 (mi−mi−1) = − hi + 1<br />
2 mi+f[xi, xi+1]− hi+1<br />
6 (mi+1−mi)<br />
(5.65)<br />
Moltiplicando per 6 e portando a primo membro le incognite mi, otteniamo:<br />
himi−1 + mi(2hi + 2hi+1) + hi+1mi+1 = 6(f[xi, xi+1] − f[xi−1, xi]) (5.66)<br />
Per accorpare le due differenze divise in una, utiliziamo la proprietà 5.22. Per<br />
poter sfruttare tale proprietà dobbiamo dividere entrambi i membri per<br />
Siano<br />
allora la 5.66, diventa<br />
ϕi =<br />
ξi =<br />
xi+1 − xi−1 = hi + hi+1<br />
hi<br />
hi + hi+1<br />
hi+1<br />
hi + hi+1<br />
i = 1, . . .,n (5.67)<br />
i = 1, . . .,n (5.68)<br />
ϕimi−1 + 2mi + ξimi+1 = 6f[xi−1, xi, xi+1] (5.69)<br />
Dobbiamo quindi risolvere il seguente sistema<br />
⎛<br />
2<br />
⎜ϕ2<br />
⎜<br />
⎝<br />
ξ1<br />
2<br />
. ..<br />
ξ2<br />
. ..<br />
ϕn−2<br />
. ..<br />
2<br />
⎞⎛<br />
⎞ ⎛<br />
m1<br />
⎟⎜<br />
m2 ⎟ ⎜<br />
⎟⎜<br />
⎟ ⎜<br />
⎟⎜<br />
⎟ ⎜<br />
⎟⎜<br />
⎟⎜<br />
. ⎟ = 6 ⎜<br />
ξn−2⎠<br />
⎜ ⎟ ⎜<br />
⎝ . ⎠ ⎝<br />
f[x0, x1, x2]<br />
f[x1, x2, x3]<br />
.<br />
.<br />
⎞<br />
⎟<br />
⎠<br />
ϕn−1 2<br />
f[xn−2, xn−1, xn]<br />
mn−1<br />
(5.70)<br />
Osserviamo che per ogni i = 1, . . . , n, ξi +ϕi = 1 < 2. La matrice quindi risulta<br />
diagonale dominante per righe, e di conseguenza fattorizzabile LU, dove L ed<br />
U sono così definiti: ⎛<br />
1<br />
⎞<br />
⎜<br />
⎜l2<br />
L = ⎜<br />
⎝<br />
. ..<br />
. .. . ..<br />
⎟<br />
⎠<br />
(5.71)<br />
100<br />
ln−1 1
dove<br />
⎛<br />
⎜<br />
U = ⎜<br />
⎝<br />
u1 = 2 , li+1 = ϕi+1<br />
ui<br />
u1 ξ1<br />
. ..<br />
. ..<br />
⎟<br />
. ⎟<br />
.. ξn−2<br />
⎠<br />
un−1<br />
⎞<br />
, ui+1 = 2 − li+1ξi per i = 1, . . .,n − 2<br />
Il sistema 5.70 si risolve quindi ponendo<br />
Ly = b con<br />
<br />
y1 = b1<br />
yi = bi − liyi−1 i = 2, . . .,n − 1<br />
Um = y con<br />
mn−1 = yn−1<br />
un−1<br />
mi = (yi−ξimi+1)<br />
un<br />
i = n − 2, . . .,1<br />
(5.72)<br />
La prova della consistenza dei fattori L ed U, può essere verificata tramite la<br />
loro moltiplicazione. Chiamiamo A la matrice dei coefficienti del sistema lineare<br />
5.70. La prima riga ha in prima e seconda posizione i seguenti elementi:<br />
A1,1 = 1 · u1 = u1 = 2<br />
A1,2 = 1 · ξ1 + 0 · u2 = ξ1<br />
La prima riga della matrice A infatti corrisponde alla matrice dei coefficienti del<br />
sistema 5.70. Per una i-esima riga si verifica che<br />
Ai,i−1 = ξi−2 · 0 + l1 · ui−1 + 1 · 0 = ϕi<br />
Ai,i = li · ξi−1 + 1 · ui =<br />
Ai,i+1 = 1 · ξi = ξi<br />
ui−1<br />
<br />
ϕi<br />
ξi−1<br />
uu−1<br />
· ui−1 = ϕi<br />
<br />
+ 2 −<br />
<br />
ϕi<br />
ξi−1<br />
uu−1<br />
<br />
= 2<br />
Analogamente alla prima riga si può procedere per l’ultima riga. I risultati di<br />
tale fattorizzazione, i coefficienti mi, dovranno poi essere sostituiti nell’equazione<br />
5.58, tenendo conto delle definizioni delle costanti di integrazione. Questo<br />
procedimento che abbiamo seguito è valido per la spline cubica naturale. Per il<br />
calcolo della spline cubica con condizione not-a-knot, dobbiamo imporre le condizioni<br />
5.54 e 5.55. Rispettando queste imposizioni e considerando l’equazione<br />
5.69, otteniamo il sistema lineare<br />
⎛<br />
⎜<br />
⎝<br />
ξ1 −1 ϕ1<br />
ϕ1 2 ξ1<br />
. ..<br />
. ..<br />
. ..<br />
ϕn−1 2 ξn−1<br />
ξn−1 −1 ϕn−1<br />
⎞⎛<br />
⎟⎜<br />
⎟⎜<br />
⎟⎜<br />
⎟⎜<br />
⎟⎜<br />
⎠⎝<br />
m0<br />
m1<br />
.<br />
.<br />
mn−1<br />
mn<br />
⎞ ⎛<br />
⎞<br />
0<br />
⎟ ⎜<br />
⎟ ⎜ f[x0, x1, x2] ⎟<br />
⎟ ⎜<br />
⎟ = 6<br />
. ⎟<br />
⎜<br />
⎟ ⎜ . ⎟<br />
⎠ ⎝f[xn−2,<br />
xn−1, xn] ⎠<br />
0<br />
(5.73)<br />
Se nella matrice sostituisco la prima riga con la somma della prima e della<br />
seconda riga, e sostituisco l’ultima, con la somma dell’ultima e della penultima<br />
101
iga, ottengo:<br />
⎛<br />
1 1 1<br />
⎜ϕ1<br />
⎜ 2 ξ1<br />
⎜<br />
. .. . ..<br />
⎜<br />
⎝<br />
. ..<br />
ϕn−1 2 ξn−1<br />
1 1 1<br />
⎞⎛<br />
⎟⎜<br />
⎟⎜<br />
⎟⎜<br />
⎟⎜<br />
⎟⎜<br />
⎠⎝<br />
m0<br />
m1<br />
.<br />
mn−1<br />
mn<br />
⎞ ⎛<br />
⎞<br />
f[x0, x1, x2]<br />
⎟ ⎜<br />
⎟ ⎜ f[x0, x1, x2] ⎟<br />
⎟ ⎜<br />
⎟<br />
⎟ = 6 ⎜<br />
⎟ ⎜ . ⎟<br />
⎠ ⎝f[xn−2,<br />
xn−1, xn] ⎠<br />
f[xn−2, xn−1, xn]<br />
(5.74)<br />
Adesso si sottrae alla seconda e terza colonna la prima, alla n − 2esima e n −<br />
1esima la n-esima. Ottenendo quindi<br />
⎛<br />
1<br />
⎜ϕ1<br />
⎜ (2 − ϕ1) (ξ1 − ϕ1)<br />
⎜ ϕ2 ⎜<br />
2 ξ2<br />
⎜<br />
. .. . ..<br />
⎜<br />
ϕn−2 2<br />
⎝<br />
(ξn−1 − ϕn−1)<br />
. ..<br />
ξn−2<br />
(2 − ϕn−1)<br />
⎞ ⎛<br />
⎟ ⎜<br />
⎟ ⎜<br />
⎟ ⎜<br />
⎟ ⎜<br />
⎟ ⎜<br />
⎟ ⎜<br />
⎟ ⎜<br />
⎟ ⎜<br />
ϕn−1⎠<br />
⎝<br />
1<br />
m0<br />
.<br />
.<br />
⎛<br />
⎞<br />
f[x0, x1, x2]<br />
⎜<br />
f[x0, x1, x2] ⎟<br />
⎜<br />
⎟<br />
⎜<br />
= 6 ⎜ . ⎟<br />
⎜<br />
⎟<br />
⎜ . ⎟<br />
⎝f[xn−2,<br />
xn−1, xn] ⎠<br />
f[xn−2, xn−1, xn]<br />
(5.75)<br />
m0 + m1 + m2<br />
mn−1<br />
mn + mn−1 + mn−2<br />
Considerando che la matrice ha tutti i minori principali non nulli, la matrice<br />
stessa risulta fattorizzabile LU.<br />
5.10 Approssimazione polinomiale ai minimi quadrati<br />
Spesso ci si trova a dover approssimare una funzione di tipo polinomiale, dove<br />
i dati di ingresso sono ottenuti sperimentalmente o con modelli matematici che<br />
simulano un comportamento fisico. Tali dati non sono esatti. Si avrà quindi<br />
il vettore dei dati osservati f = (f0, . . . , fn) T ∈ R n+1 , e per ognuno di questi<br />
valori, si avrà il valore atteso y = (y0, . . . , yn) T ∈ R n+1 . Cosa vuol dire che<br />
pm(xi) ≈ fi? Si chiama soluzione ai minimi quadrati, il minimo della norma<br />
euclidea di f − y, ovvero<br />
L’equazione del polinomio esatto è<br />
min ||f − y||<br />
pm∈Πn<br />
2<br />
2<br />
yi = pm(xi) = (x 0 i , x 1 i,...,x m i ) · (a0, a1, . . .,an) T<br />
Posso scegliere allora y = V a, dove V è la matrice di Van der Monde<br />
⎛<br />
⎞<br />
⎜<br />
V = ⎜ .<br />
⎜<br />
⎝ .<br />
x 0 0 x 1 0 . . . x m 0<br />
.<br />
.<br />
x 0 n x 1 n . . . x m n<br />
102<br />
.<br />
.<br />
⎟<br />
⎠<br />
(5.76)<br />
(5.77)<br />
⎞<br />
⎟ =<br />
⎟<br />
⎠
Il problema dei minimi quadrati diventa<br />
min ||f − y||<br />
pm∈Πn<br />
2<br />
2 = min<br />
a∈Rn+1 ||V a − f|| 2<br />
2<br />
Siccome il rango di V è m + 1, ovvero massimo, V risulta fattorizzabile QR.<br />
<br />
ˆR<br />
V = QR ≡ Q<br />
0<br />
dove QTQ = In+1, e ˆ R, R ∈ Rn+1×m+1 Quindi l’equazione 5.76, la possiamo<br />
riscrivere come<br />
||QRa − f|| 2<br />
2 = Q(Ra − Q T f) 2 2 =<br />
<br />
2<br />
<br />
ˆR <br />
<br />
<br />
a − g<br />
0 <br />
(5.78)<br />
dove g = QTf.Partizioniamo g nel seguente modo<br />
<br />
g1<br />
g = dove g1 ∈ R m+1 , g2 ∈ R n−m<br />
g2<br />
Allora possiamo continuare la trasformazione dell’equazione 5.78<br />
<br />
<br />
<br />
ˆ <br />
<br />
Ra − g1<br />
2<br />
2 + ||g2|| = ||g2|| 2<br />
2<br />
2<br />
(5.79)<br />
(5.80)<br />
L’equazione vista sopra è vera se e solo se ˆ Ra = g1. Scegliamo allora a = ˆ R −1 g1.<br />
Si osserva che se m = n allora anche g2 = 0, e quindi i dati vengono interpolati<br />
esattamente e non approssimati.<br />
103
Capitolo 6<br />
Formule di quadratura<br />
In questo capitolo siamo interessati a capire come una perturbazione sulla funzione<br />
integrata su ripercuote sull’integrale. Vedremo poi qualche metodo per<br />
approssimare integrali definiti.<br />
6.1 Metodo di Newton-Cotes<br />
L’integrale, espresso come funzione di f, è così definito:<br />
I(f) =<br />
b<br />
a<br />
f(x)dx (6.1)<br />
Senza perdita di generalità, considereremo che a < b e che f(x) sia continua in<br />
[a, b]. Se chiamiamo ˜ f, la funzione perturbata da integrare, il condizionamento<br />
dell’approssimazione di un integrale definito dato da<br />
<br />
<br />
I(f) − I( ˜ <br />
<br />
f) =<br />
<br />
<br />
<br />
<br />
<br />
b<br />
a<br />
x∈[a,b]<br />
f(x)dx<br />
b<br />
a<br />
<br />
<br />
˜f(x)dx<br />
<br />
<br />
=<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
≤ max f(x) − ˜ <br />
<br />
f(x) ·<br />
b<br />
a<br />
b<br />
a<br />
f(x) − ˜ <br />
<br />
<br />
f(x)dx<br />
≤<br />
Risulta quindi chiaro che<br />
<br />
<br />
I(f) − I( ˜ <br />
<br />
f) = (b − a) · f<br />
−<br />
<br />
K<br />
errore in output<br />
˜ <br />
<br />
f<br />
<br />
errore in input<br />
b<br />
a<br />
<br />
<br />
f(x) − ˜ <br />
<br />
f(x)dx<br />
≤<br />
<br />
<br />
dx = (b − a) · f<br />
− ˜ <br />
<br />
f<br />
(6.2)<br />
In definitiva il numero di condizionamento per l’approssimazione di un integrale<br />
definito, è proprio l’ampiezza dell’intervallo di integrazione. L’idea per approssimare<br />
l’integrale di una funzione, è di calcolare l’integrale dell’approssimazione<br />
di una funzione più facilmente integrabile. Ovvero<br />
I(f) =<br />
b<br />
a<br />
f(x)dx ≈<br />
b<br />
a<br />
pn(x)dx ≡ In(f)<br />
Consideriamo allora una partizione dell’intervallo [a, b] così definita:<br />
xi = a + i · h i = 0, . . .,n dove h =<br />
104<br />
b − a<br />
n<br />
(6.3)
Se il polinomio interpolante la funzione lo sostituiamo con quello di Lagrange,<br />
otteniamo:<br />
In(f) =<br />
b<br />
a<br />
pn(x)dx =<br />
b<br />
a<br />
n<br />
Lin(x)fidx =<br />
i=0<br />
Ponendo i = t nell’equazione 6.3 otteniamo<br />
n<br />
i=0<br />
x = a + th dove 0 ≤ t ≤ n<br />
Con tale sostituzione i polinomi di Lagrange diventano<br />
Lin(x) =<br />
n<br />
x − xj<br />
xi − xj<br />
j=0,j=i<br />
=<br />
n<br />
j=0,j=i<br />
a + th − (a + jh)<br />
a + ih − (a + jh) =<br />
fi<br />
b<br />
n<br />
a<br />
j=0,j=i<br />
Lin(x)dx<br />
(t − j)h<br />
(i − j)h =<br />
Pertanto l’approssimazione dell’integrale con i polinomi di Lagrange, risulta<br />
Ovvero<br />
Dove<br />
Distinguiamo alcuni casi:<br />
n=1<br />
n=2<br />
Siccome<br />
si ha che<br />
Quindi<br />
b − a<br />
n<br />
n<br />
i=0<br />
fi<br />
In(f) =<br />
c (n)<br />
i =<br />
n<br />
0<br />
n<br />
0<br />
b − a<br />
n<br />
c (1)<br />
0<br />
c (1)<br />
0<br />
n<br />
j=0,j=i<br />
n<br />
n<br />
i=0<br />
j=0,j=i<br />
+ c(1)<br />
1<br />
t − j<br />
i − j dt<br />
n<br />
j=0,j=i<br />
c (n)<br />
i fi (6.4)<br />
t − j<br />
i − j dt<br />
= 1<br />
= 1 − c(1)<br />
1<br />
c (1)<br />
1 =<br />
1<br />
t 1<br />
dt =<br />
0 1 − 0 2<br />
I1(f) =<br />
c (2)<br />
0<br />
c (1)<br />
0<br />
b − a<br />
2<br />
= 1<br />
2<br />
(f(a) + f(b)) (6.5)<br />
+ c(2) 1 + c(2) 2 = 2<br />
c (2)<br />
2 =<br />
2<br />
t · (t − 1) 1<br />
dt =<br />
0 2 · (1 − 0) 2 ·<br />
<br />
3 2<br />
t t2 <br />
− =<br />
3 2 0<br />
1<br />
3<br />
c (2)<br />
0 =<br />
2<br />
2<br />
(t − 1) · (t − 2) 1<br />
1<br />
dt = · (t(t − 1) − 2(t − 1))dt =<br />
0 2 · 1 0 2 3<br />
105<br />
t − j<br />
i − j
I2(f) =<br />
b − a<br />
6<br />
c (2) 4<br />
1 =<br />
3<br />
<br />
f(a) + 4f(<br />
<br />
a + b<br />
) + f(b)<br />
2<br />
Una proprietà che caratterizza la formula di Newton-Cotes, è la seguente:<br />
i=0<br />
Per ogni n < 6<br />
Per n > 7<br />
i=0<br />
1<br />
n<br />
1<br />
n<br />
n <br />
<br />
c<br />
i=0<br />
(k)<br />
i<br />
n <br />
<br />
c<br />
i=0<br />
(k)<br />
i<br />
<br />
<br />
= 1<br />
<br />
<br />
> 1<br />
Studiamo il condizionamento perturbando la f.<br />
<br />
<br />
In(f) − In( ˜ <br />
<br />
<br />
f) = <br />
h<br />
n<br />
fic (n)<br />
n<br />
i − h ˜fic (n)<br />
<br />
n<br />
<br />
i = h (fi −<br />
<br />
˜ fi) · c (n)<br />
<br />
n <br />
<br />
i ≤ h· fi −<br />
˜ <br />
<br />
fi<br />
·<br />
Considerando che <br />
fi<br />
− ˜ <br />
<br />
fi<br />
≤ f<br />
− ˜ <br />
<br />
f<br />
otteniamo che<br />
h ·<br />
n <br />
<br />
fi − ˜ <br />
<br />
fi<br />
·<br />
i=0<br />
c (n)<br />
i<br />
i=0<br />
<br />
<br />
≤ (b − a) · f<br />
− ˜ <br />
<br />
f<br />
· 1<br />
n<br />
n <br />
<br />
c<br />
i=0<br />
(n)<br />
i<br />
<br />
<br />
f<br />
− ˜ <br />
<br />
f<br />
rappresentano i dati in ingresso, quidni i restanti due fattori della<br />
precedente equazione concorrono in qualche modo a modificare la perturbazione.<br />
Analiziamo i due casi:<br />
• Se n ≤ 6 allora<br />
• Se n ≥ 7 allora<br />
<br />
<br />
(b − a) f<br />
− ˜ <br />
<br />
fi<br />
<br />
<br />
(b − a) · f<br />
− ˜ <br />
<br />
f<br />
· 1<br />
n<br />
n <br />
<br />
c<br />
i=0<br />
(n)<br />
i<br />
Considerando che per n ≥ 7, il fattore 1 n n<br />
questo algoritmo non conveniete in questo caso.<br />
6.2 Errore<br />
<br />
<br />
<br />
<br />
<br />
i=0 c (n)<br />
i<br />
Definiamo l’errore commesso nell’approssimazione (vedi 5.26) come<br />
En(f) = I(f) − In(f) =<br />
b<br />
a<br />
f(x) − pn(x)dx =<br />
106<br />
b<br />
a<br />
<br />
<br />
<br />
i=0<br />
<br />
<br />
≫ 1, si considera<br />
f[x0, . . .,xn, x]ωn+1(x)dx<br />
(6.6)<br />
c (n)<br />
i
Teorema 33 (Errore quadratura). Se f ∈ C (n+k) ([a, b]) con k = 1 se n è pari,<br />
k = 2 altrimenti, allora<br />
n+k+1<br />
En(f) = νn · f(n+1) <br />
(ξ) b − a<br />
·<br />
n + k n<br />
con ξ ∈ [a, b] (6.7)<br />
⎧ n n<br />
⎪⎨<br />
(t − j)dt n dispari<br />
0 j=0<br />
ν = n n<br />
⎪⎩<br />
t · (t − j)dt n pari<br />
(6.8)<br />
0<br />
Con questa nuova formula l’errore per la formula dei trapezi è:<br />
E1(f) = − 1<br />
12 f(2) (ξ)(b − a) 3<br />
j=0<br />
mentre l’errore per la formula di Simpson risulta:<br />
E2(f) = − 1<br />
90 f(4) (ξ)(b − a) 5<br />
(6.9)<br />
(6.10)<br />
Il nostro intento è quello di ridurre l’errore, senza aumentare il valore di n più di<br />
6. Usiamo un approccio del tutto simile a quello utilizzato per ridurre l’errore<br />
nel calcolo del polinomio interpolante. Infatti le spline sono state introdotte<br />
proprio per questo. Si tratta quindi di applicare il metodo Newton-Cotes con<br />
lo stesso valore di n, a pi sottointervalli di [a, b], con un ampiezza minore.<br />
6.3 Formule composite<br />
Presentiamo di seguito la formula composita dei trapezi:<br />
b<br />
a<br />
f(x)dx =<br />
n<br />
i=1<br />
xi<br />
xi−1<br />
f(x)dx =<br />
b − a<br />
n<br />
n<br />
i=1<br />
f(xi−1 + f(xi)<br />
2<br />
= b − a<br />
2n · (f0 + f1 + f1 + f2 + f2 + . . . + . . . + fn−1 + fn−1 + fn) =<br />
= b − a<br />
<br />
<br />
n−1 <br />
f0 + 2 · fi + fn =<br />
2n<br />
b − a<br />
<br />
f0<br />
n 2 +<br />
n−1 <br />
fi + fn<br />
<br />
2<br />
i=1<br />
Da notare che adesso n rappresenta il numero degli intervalli in cui è suddiviso<br />
[a, b]. Dal terorema 33, possiamo ricavare l’errore per la relativa formula<br />
composita.<br />
E (n)<br />
1 (f) = − 1<br />
12<br />
= − 1<br />
12 n·<br />
<br />
b − a<br />
n<br />
n<br />
i=1<br />
3 n<br />
i=1<br />
f (2) (ξ)(xi − xi−1) 3 = − 1<br />
12<br />
i=1<br />
=<br />
n<br />
f (2) <br />
b − a<br />
(ξ)<br />
n<br />
i=1<br />
f (2) (b − a)3<br />
(ξi) = −<br />
12n2 f(2) ( ˆ ξi) ≈ o<br />
107<br />
3<br />
=<br />
3 (b − a)<br />
n2 <br />
→ 0 per n → ∞
Per la formula di Simpson invece risulta:<br />
b<br />
a<br />
f(x)dx =<br />
= b − a<br />
n<br />
i=1<br />
3n<br />
x2i<br />
x2i−2<br />
m−1<br />
<br />
i=0<br />
f(x)dx =<br />
b − a<br />
3n<br />
<br />
m−1<br />
f2i+1 + 2<br />
i=1<br />
m<br />
i=1<br />
f2i−2 + 4f2i−1 + f2i =<br />
f2i + f0 + fn<br />
Analogamente alla formula di trapezi si dimostra che l’errore per la relativa<br />
formula compostia di Simpson è:<br />
E (n)<br />
2 (f) = − n<br />
180 f(n) (ξ)<br />
b − a<br />
n<br />
5<br />
<br />
=<br />
→ 0 per n → ∞ (6.11)<br />
In definitiva, l’errore, sia per la formula dei trapezi, che per quella di Simpson,<br />
si riduce notevolemtne man mano che il numero di intervalli aumenta. Vediamo<br />
adesso l’algoritmo per l’approssimazione dell’integrale definito con il metodo dei<br />
trapezi composito.<br />
Algoritmo 6.1 (Trapezi composito).<br />
function integrale=trapezi(f,a,b,n)<br />
%La funzione trapezi, calcola l’integrale della funzione<br />
%f, nell’ intervallo [a,b], approssimandolo con la<br />
%formula composita dei trapezi.<br />
%<br />
%INPUT<br />
% f funzione da integrare<br />
% a estremo destro dell’intervallo<br />
% b estremo sinistro dell’intervallo<br />
% n numero di intervalli<br />
h=(b-a)/n;<br />
x=[a:h:b];<br />
%y=inline(f);<br />
%yy=feval(f,x);<br />
yy=f(x);<br />
integrale=h*(0.5*yy(1)+sum(yy(2:n))+0.5*yy(n+1));<br />
Di seguito l’algoritmo con il metodo di Simpson.<br />
Algoritmo 6.2 (Simpson composito).<br />
function integrale=simpson(f,a,b,n)<br />
%La funzione simpson, calcola l’integrale della funzione<br />
%f, nell’ intervallo [a,b], approssimandolo con la<br />
%formula composita di Simpson.<br />
108
%<br />
%INPUT<br />
% f funzione da integrare<br />
% a estremo destro dell’intervallo<br />
% b estremo sinistro dell’intervallo<br />
% n numero di intervalli<br />
h=(b-a)/n;<br />
x=[a:h/2:b];<br />
y=inline(f);<br />
yy=feval(f,x);<br />
integrale=(h./3).*(sum(yy(1:2:n-1))+(2.*sum(yy(2:2:n-1)))+yy(1)+yy(n));<br />
6.4 Formule adattive<br />
Spesso si ha a che fare con funzioni integrande non molto regolari. I metodi<br />
visti fino ad adesso, risultano poco accurati se la derivata della funzione, assume<br />
valori elevati e cambia spesso di segno. Per questo vengono introdotti dei<br />
metodi che riescono ad ottenere una precisione prefissata, laddove serve. Dobbiamo<br />
stabilire un criterio di arresto, per la tolleranza richiesta. Consideriamo<br />
allora l’approssimazione con la formula dei trapezi dell’integrale su uno e due<br />
sottointervalli. L’errore su un intervallo è approssimativamente:<br />
I(f) − I (1) 1<br />
1 (f) ≈ −<br />
12 f(2) (ξ)(b − a) 3<br />
mentre quello su due sottointervalli risulta<br />
I(f) − I (2) 1<br />
1 (f) ≈ −<br />
12 f(2) (b − a)3<br />
(ξ)<br />
4<br />
Sottraendo membro a membro le due equazioni precedenti otteniamo che<br />
I (1)<br />
1<br />
<br />
1 (f) − I(2) 1 (f) ≈ I<br />
3<br />
(2)<br />
<br />
1 (f) − I1(f)<br />
L’algoritmo quindi opera con il principio divide et impera. Per ogni sottointervallo,<br />
se la stima dell’errore è maggiore della tolleranza richiesta, si procede a<br />
dividere il sottointervallo in due parti, e si riapplica l’algoritmo su entrambi i<br />
sottointervalli. Per questo si parla di formule adattive, perché sono in grado<br />
di ottenere una tolleranza prefissata, partizionando l’intervallo di integrazione<br />
in modo tale da ottimizzare le risorse di calcolo. Il caso limite rappresentato<br />
dall’integrale della funzione costante y = k, con k ∈ R. Infatti la formula adattiva<br />
si ferma alla prima iterazione, per ogni tolleranza fissata maggiore di zero.<br />
Presentiamo allora l’algoritmo adattivo che usa il metodo dei trapezi.<br />
Algoritmo 6.3 (Simpson composito).<br />
function [int,x]=trapeziAdpt(f,a,b,tol,hmin)<br />
109
%<br />
%usage: int=trapezi(f,a,b,tol,hmin)<br />
%Questa funzione calcola l’integrale della funzione f nell’intervallo [a,b]<br />
%con una tolleranza tol.<br />
%hmin la lunghezza pu raggiungere il segmento b-a.<br />
%E’ possibile che questo metodo non raggiunga la tolleranza prefissata.<br />
%<br />
%INPUT<br />
% f funzione integranda.deve essere una funizone che riceve in ingresso<br />
% un vettore e restituisce in output un vettore<br />
% a estremo sinistro dell’intervallo<br />
% b estremo destro dell’intervallo<br />
% tol la tolleranza che l’algoritmo dovrebbe rispettare.<br />
% hmin pi piccola lunghezza dell’intervallo sul quale pu<br />
% essere calcolato l’integrale<br />
x=[a,b];<br />
if b
%ritorna il vettore [0,1,2,3].<br />
a=sort(a);<br />
n=length(a);<br />
if(n==1)<br />
warning(’Il vettore ha solo un elemento,’);<br />
printf(’quindi non pu contenere duplicati’);<br />
x=a;<br />
return<br />
end<br />
i=2;<br />
while in) break; end<br />
end<br />
i=i+1;<br />
if (i>n) break; end<br />
end<br />
x=a;<br />
Esempio 26. Facciamo un esempio usando l’algoritmo dei trapezi adattivo. In<br />
particolare siamo interessati a vedere come si dispongono le ascisse per l’lagoritmo<br />
dei trapezi. Lo script per eseguito per generare l’esempio è il seguente:<br />
f=inline(’rdatan(x)’);<br />
a=0;<br />
b=5;<br />
[int,x]=trapeziAdpt(f,a,b,10^-3,10^-4);<br />
xx=linspace(a,b,201);<br />
yy=f(xx);<br />
hold on<br />
plot(xx,yy,’k’);<br />
y=f(x);<br />
plot(x,y,’ro’);<br />
Dove la funzione atan è definita come<br />
function [y]=datan(x)<br />
y=1./(1+(x.^2));<br />
In output viene generato il grafico 6.1, oltre al valore approssimato dell’integrale<br />
della funzione. Come si può notare, le ascisse sono più dense dove la derivata<br />
della funzione cambia di segno e il suo valore assoluto è alto. Nella prima parte<br />
111
0.9<br />
0.8<br />
0.7<br />
0.6<br />
0.5<br />
0.4<br />
0.3<br />
0.2<br />
0.1<br />
0<br />
runge(x)=1/1+x 2<br />
ascisse di quadratura<br />
−0.1<br />
0 0.5 1 1.5 2 2.5 3 3.5 4 4.5 5<br />
Figura 6.1: Grafico delle ascisse di quadratura<br />
applicata alla funzione di Runge.<br />
della funzione infatti si addensano la maggior parte delle ascisse, mentre man<br />
mano che x cresce occorrono sempre meno ascisse per ottenere la tolleranza<br />
richiesta.<br />
112
Esempio 27. Vediamo a quanto ammonta l’errore reale sull’approssimazione<br />
di un integrale con il metodo dei trapezi composito. Per far questo abbiamo<br />
bisogno di una funzione facilmente integrabile. La seguente funzione<br />
1<br />
1 + x 2<br />
ha come integrale<br />
b<br />
1<br />
= atan(x)|b<br />
1 + x2 a = atan(b) − atan(a)<br />
a<br />
(6.12)<br />
Il seguente script, mette in evidenza l’errore esatto tra l’integrale della funzione<br />
6.12 calcolato nell’intervallo [a, b] e l’integrale in forma analitica.<br />
imax=8;<br />
a=0;<br />
b=5;<br />
tol=zeros(1,imax);<br />
tol(1)=10^-1;<br />
for j=2:imax<br />
tol(j)=tol(j-1)./10;<br />
end<br />
hmin=10^-10;<br />
f=inline(’datan(x)’);<br />
i=1;<br />
printf(’ ------------------------------------------------ \n’);<br />
printf(’| tol | approssimazioni | errore |\n’);<br />
printf(’ ------------------------------------------------ \n’);<br />
temp=atan(b);<br />
while i
Come ci potevamo aspettare, la tolleranza richiesta rispetta l’errore esatto.<br />
114
Bibliografia<br />
[1] <strong>Calcolo</strong> <strong>Numerico</strong><br />
Prof. Luigi Brugnano<br />
Prof.ssa Cecilia Magherini<br />
Prof.ssa Alessandra Sestini<br />
Master Università & Professioni<br />
viale Morgagni, 39/r - 50134 Firenze<br />
tel. 055 4368577<br />
email masterlibri@libero.it<br />
[2] IEEE Standard 754 for Binary Floating-Point Arithmetic<br />
Prof. W. Kahan<br />
Elect. Eng. & Computer Science<br />
University of California<br />
Berkeley CA 94720-1776<br />
disponibile all’indirizzo web<br />
http://www.cs.berkeley.edu/~wkahan/ieee754status/IEEE754.PDF<br />
[3] Floating Point Unit<br />
Jidan Al-Eryani<br />
disponibile all’indirizzo web<br />
http://www.opencores.org/projects.cgi/web/fpu100/fpu_doc.pdf<br />
[4] Floating point - IEEE Standard unifies arithmetic model<br />
Cleve Moler<br />
chairman and co-founder of The MathWorks.<br />
moler@mathworks.com<br />
disponibile all’indirizzo web<br />
http://www.mathworks.com/company/newsletters/news_notes/pdf/<br />
Fall96Cleve.pdf<br />
[5] Esercizi svolti di calcolo numerico<br />
Stefano Berrone<br />
Sandra Pieraccini<br />
Edizioni C.L.U.T.<br />
corso Duca delgi Abruzzi, 24 - 10129 Torino<br />
tel. 0115647980<br />
ISBN: 88-7992-183-5<br />
[6] Matematica Numerica 2 a edizione<br />
Alfio Quarteroni<br />
115
Riccardo Sacco<br />
Fausto Saleri<br />
ed. Springer-Verlag italia, Milano<br />
ISBN: 88-470-0077-7<br />
[7] Algebra Lineare<br />
Seymour Lipshutz<br />
ed. Etas Libri<br />
ISBN: 88-453-0528-7<br />
116