21.05.2013 Views

Calcolo Numerico

Calcolo Numerico

Calcolo Numerico

SHOW MORE
SHOW LESS

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

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!