Sei sulla pagina 1di 117

Annamaria Mazzia

Esercitazioni di Calcolo
Numerico in MATLAB e
Octave

Dipartimento di Ingegneria Civile Edile e Ambientale

Universit degli Studi di Padova


Creative Commons Attribuzione- Non commerciale -Non opere derivate 3.0 Italia License
a.a. 2012/2013

Indice
Indice
1

ii

Introduzione
1.1 Introduzione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2 Avvio di MATLAB e Octave . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2.1 Le variabili . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2.2 Prima introduzione (breve) su matrici e vettori in MATLAB . .
1.2.3 Funzioni vettorizzate . . . . . . . . . . . . . . . . . . . . . . . . .
1.2.4 Sulle variabili . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.3 Comandi utili . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.4 Introduzione alla programmazione . . . . . . . . . . . . . . . . . . . . . .
1.5 Problemi e Algoritmi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.6 MATLAB come linguaggio di programmazione . . . . . . . . . . . . . .
1.7 Primo script e prima function in MATLAB . . . . . . . . . . . . .
1.8 I predicati elementari . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.9 Strutture e cicli . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.9.1 Ciclo if . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.9.2 Ciclo while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.9.3 Ciclo for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.9.4 Introduzione a file di scrittura dati . . . . . . . . . . . . . . . . .
1.9.5 Modificare le function di punto fisso per creare nuove function

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

1
1
2
4
5
7
8
10
11
12
13
13
15
18
18
24
33
35
39

Su interpolazione e approssimazione
2.1 Interpolazione monomiale e con i polinomi di Lagrange . . . .
2.2 Interpolazione con la tabella delle differenze divise di Newton .
2.3 Interpolazione lineare a tratti e spline cubica . . . . . . . . . . .
2.3.1 Interpolazione lineare a tratti . . . . . . . . . . . . . . . .
2.4 Curve parametriche . . . . . . . . . . . . . . . . . . . . . . . . . .
2.4.1 Il ciclo switch . . . . . . . . . . . . . . . . . . . . . . . . .
2.5 Approssimazione di dati . . . . . . . . . . . . . . . . . . . . . . .
2.5.1 Retta di regressione sugli scarti verticali . . . . . . . . .
2.5.2 Modello potenza e modello esponenziale . . . . . . . .
2.5.3 Caricare i dati di input da file . . . . . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

43
44
50
54
54
59
60
62
62
64
65

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

Metodi diretti per sistemi lineari


69
3.1 Prodotti matrice-vettore, matrice-matrice, scalari . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
3.2 Metodi di sostituzione allindietro e in avanti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
3.3 Metodi diretti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
ii

Indice

3.4
4

Norme di vettori . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Metodi iterativi per sistemi lineari


4.1 Metodo di Jacobi . . . . . . . . . . . . . . . . . . . . . . . . .
4.2 Modificare jacobi.m per implementare gli altri metodi .
4.2.1 Metodo di Gauss-Seidel . . . . . . . . . . . . . . . .
4.2.2 Metodo di rilassamento . . . . . . . . . . . . . . . .

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

75
79
79
83
83
84

Problemi non lineari


87
5.1 Metodo di Newton per sistemi non lineari . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
5.2 Minimi quadrati non lineari . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91

Formule di integrazione numerica


95
6.1 Formule di quadratura numerica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
6.2 La formula dei trapezi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
6.3 La formula di Cavalieri-Simpson . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100

Equazioni Differenziali Ordinarie


7.1 Metodi per ODE . . . . . . . . . . . . . . . . . . . .
7.1.1 Confronto tra i metodi sullequazione test
7.2 I metodi . . . . . . . . . . . . . . . . . . . . . . . . .
7.3 Sistemi di equazioni differenziali . . . . . . . . . .
7.3.1 Function di MATLAB e Octave per ODE . .
7.3.2 Loscillatore semplice . . . . . . . . . . . .
7.3.3 Equazioni del moto di Keplero . . . . . . .

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

103
103
103
105
109
109
110
111

iii

C APITOLO

Introduzione
Luniverso non potr essere letto
finch non avremo imparato il
linguaggio ed avremo familiarizzato
con i caratteri con cui scritto.
scritto in linguaggio matematico, e
le lettere sono triangoli, cerchi ed
altre figure geometriche, senza le
quali umanamente impossibile
comprendere una singola parola.
Galileo Galilei

1.1
1.2

1.3
1.4
1.5
1.6
1.7
1.8
1.9

Introduzione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Avvio di MATLAB e Octave . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2.1 Le variabili . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2.2 Prima introduzione (breve) su matrici e vettori in MATLAB . .
1.2.3 Funzioni vettorizzate . . . . . . . . . . . . . . . . . . . . . . . . .
1.2.4 Sulle variabili . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Comandi utili . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Introduzione alla programmazione . . . . . . . . . . . . . . . . . . . . . .
Problemi e Algoritmi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
MATLAB come linguaggio di programmazione . . . . . . . . . . . . . .
Primo script e prima function in MATLAB . . . . . . . . . . . . .
I predicati elementari . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Strutture e cicli . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.9.1 Ciclo if . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.9.2 Ciclo while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.9.3 Ciclo for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.9.4 Introduzione a file di scrittura dati . . . . . . . . . . . . . . . . .
1.9.5 Modificare le function di punto fisso per creare nuove function

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

1
2
4
5
7
8
10
11
12
13
13
15
18
18
24
33
35
39

1.1 Introduzione
MATLAB un acronimo per MATrix LABoratory ed uno strumento utile per il calcolo numerico e per la
visualizzazione. MATLAB , infatti, pu essere considerato un linguaggio di programmazione ad alto livello
e, allo stesso tempo, un ambiente interattivo per lo sviluppo di algoritmi, per la visualizzazione e lanalisi di
dati, e per il calcolo numerico.

1. I NTRODUZIONE

Quindi, per imparare a usare bene MATLAB , dobbiamo imparare le tecniche di programmazione (cosa
un programma, quali sono le strutture di un programma, come si scrive, come si esegue). Ma dobbiamo anche tenere in conto che MATLAB ha le sue proprie funzioni (functions), che permettono di eseguire calcoli
molto sofisticati, ed capace di fare grafici e visualizzare i risultati in maniera diretta.
Molto spesso la conoscenza di MATLAB un requisito richiesto per molte posizioni lavorative in ambito ingegneristico proprio per la sua implementazione in numerosi problemi (dallingegneria aerospaziale a
quella chimica, alla meccanica ...).
MATLAB un programma complesso (originariamente fu scritto in FORTRAN e successivamente riscritto in linguaggio C) che va bene per risolvere programmi delaborazione numerica, per lavorare con matrici
e per la grafica. Questo software un prodotto della The MathWorks : vedremo in particolare la versione
MATLAB 8.0.0.783 (R2012b) lavorando in ambiente Linux.
Un prodotto simile a MATLAB ma open source GNU Octave (si vada sul sito http://www.gnu.
org/software/octave/). In queste dispense, faremo riferimento alla versione 3.6.2 di Octave.
Nel seguito vedremo come si lavora in MATLAB (e Octave) tenendo presente che quasi tutti i comandi che daremo in MATLAB valgono alla stessa maniera anche per Octave con alcune differenze, come
linterfaccia grafico o altri comandi, che sottolineeremo.

1.2 Avvio di MATLAB e Octave


Tralasciamo la parte relativa alla procedura di installazione di MATLAB (e di Octave), che dipende dal
computer e dal sistema operativo in uso, e diamo per scontato che il programma sia presente sul proprio
computer.
In ambiente Linux, per avviare MATLAB basta digitare il comando matlab da una finestra di terminale (analogamente, basta digitare octave per entrare in ambiente Octave). Una volta avviato MATLAB , si
aprir un ambiente che contiene molte finestre (la Command Window, la Workspace, la Command History, la Current Folder). Il prompt dei comandi dato dal simbolo >> (> in Octave) e comparir il prompt
dei comandi in una finestra come quella mostrata in Figura 1.1 (si veda Figura 1.2 per lanalogo di Octave).
Per uscire dallambiente si digita exit o quit dalla finestra dei comandi oppure dal menu File o ancora
dallicona di chiusura (x in alto a destra della finestra).
Per imparare a usare MATLAB , conviene prendere familiarit con la finestra dei comandi eseguendo
calcoli come se fosse una calcolatrice. Vediamo che il risultato viene assegnato ad una variabile detta ans e
che nella Workspace si trovano informazioni su di essa (si veda Figura 1.3).
Le principali operazioni aritmetiche sono date da

/
+

elevamento a potenza
moltiplicazione
divisione
addizione
sottrazione

Nel fare le operazioni aritmetiche, viene data la precedenza agli elevamenti a potenza, poi alle moltiplicazioni e divisioni, infine alla sottrazione e addizione. Quando due operatori hanno la stessa prorit vengono
eseguite le operazioni partendo da sinistra e andando verso destra. Tuttavia, quando le espressioni sono
abbastanza complicate e c il rischio di non capire bene quali operazioni vanno fatte prima e quali dopo,
conviene mettere sempre le parentesi.
Le funzioni di base (quelle che troviamo anche su una calcolatrice) sono date da

1.2. Avvio di MATLAB e Octave

Figura 1.1: Lambiente MATLAB consiste di una serie di finestre, alcune delle la Current Folder (la directory corrente in cui si sta lavorando), la Workspace (lo spazio di lavoro) e la Command History (la
finestra con la storia dei comandi dati).

Figura 1.2: Avvio di Octave: la finestra che si apre corrisponde alla Command Window di MATLAB .

1. I NTRODUZIONE

Figura 1.3: Primi calcoli in MATLAB : osservare cosa succede nella Command Window, nella Workspace
e nella Command History.

Funzione MATLAB (Octave)

sin(x)
cos(x)
tan(x)
asin(x)
acos(x)
atan(x)
exp(x)
log(x)
log10(x)
sqrt(x)
abs(x)

Significato
sin (x)
cos (x)
tan (x)
asi n(x)
acos(x)
at an(x)
ex
ln (x)
log (x)
p
x
|x|

La cosa nuova, da sottolineare, che ora queste operazioni si possono fare su matrici e vettori e che in
MATLAB (Octave) si lavora soprattutto su matrici e vettori.
Per lavorare meglio, nel seguito introduciamo il concetto di variabile e, successivamente, le matrici e i
vettori.

1.2.1 Le variabili
Abbiamo visto che, se scriviamo nella finestra di lavoro, sin(10) il risultato ans =-0.5440. Il risultato della funzione viene assegnato ad una variabile che, di default, viene chiamata ans. Se cambiamo il
calcolo, il risultato sar del tipo ans = cui associato il valore numerico del risultato. Tuttavia, noi possiamo
decidere di assegnare il risultato di una certa operazione o di una funzione ad una variabile a cui noi stessi assegniamo un nome ben preciso. Per esempio, vogliamo che il risultato di sin (10) sia assegnato ad una
variabile che chiamiamo b. Per fare ci, basta scrivere
>> b=sin(10)

1.2. Avvio di MATLAB e Octave

Figura 1.4: Variabili nella Workspace

b =
-0.5440

In questo modo il valore della funzione non pi assegnato alla variabile ans ma alla variabile b. Anche
10 pu diventare il valore di una variabile, in cui poi valutare la funzione seno.
>> a=10
a =
10
>> b=sin(a)
b =
-0.5440

Osserviamo che ora nella Workspace, troviamo il nome delle variabili introdotte e il loro valore (si veda
figura ??).

1.2.2 Prima introduzione (breve) su matrici e vettori in MATLAB


Ci che diremo ora su vettori e su matrici sar qualcosa di breve, (quando parleremo di vettori e matrici
nel corso di Calcolo Numerico, li rivedremo sotto unaltra luce) utile per alcune semplici e prime applicazioni
di MATLAB (o Octave).
I vettori si possono scrivere come vettori riga o vettori colonna.
Per esempio:
>>x=[1 2]
>> x=[1 2]
x =
1

1. I NTRODUZIONE

>> y=[10 20]


y =
10
20

Un vettore riga x viene scritto usando le parentesi quadre e scrivendo le componenti del vettore una dopo
laltra. Un vettore colonna pu essere creato facendo la trasposta di un vettore riga (mediante il simbolo ),
oppure mettendo un punto e virgola dopo ciascuna componente:
>> y=[10;20]
y =
10
20

In MATLAB i vettori altro non sono che un caso particolare di matrice a n righe e 1 colonna (vettore
colonna) o a 1 riga e n colonne (vettore riga). Quindi per scrivere una matrice si scrivono i valori della matrice
riga per riga andando a capo con il punto e virgola:
>> A=[1 2 3 4;
5 6 7 8;
9 10 11 12;
13 14 15 16]
A =
1
5
9
13

2
6
10
14

3
7
11
15

4
8
12
16

Per indicare un valore della matrice A basta specificare lindice di riga e di colonna: per esempio
>> A(2,2)
ans =
6

Per indicare gli elementi di tutta la colonna i si usa A(:,i), mentre A(i,:) indica gli elementi della riga
i.
>> A(:,2)
ans =
2
6
10
14
>> A(2,:)
ans =
5

1.2. Avvio di MATLAB e Octave

Loperatore due punti pu dunque essere usato per estrarre unintera riga o colonna da una matrice o
unintera sottomatrice. Se vogliamo estrarre le ultime due righe e colonne della matrice A, si digita il comando
>> M=A(3:4,3:4)
M =
11
15

12
16

In questo modo abbiamo creato la matrice M che ha come elementi quelli della sottomatrice di A con le ultime
due righe e colonne.
Per scrivere una matrice vuota A, invece, si usa listruzione A=[ ].

1.2.3 Funzioni vettorizzate


Le funzioni che abbiamo visto prima si possono applicare direttamente su matrici e vettori, sono cio
vettorizzate. Cosa significa questo? Significa che se abbiamo un vettore, ad esempio x = [1, 2, 3, 4] e valutiamo
sin(x), il risultato sar un vettore che ha come componenti il valore della funzione nelle singole componenti
del vettore, in questo caso [sin(1), sin(2), sin(3), sin(4)]. Stessa cosa vale per le matrici.
Vediamo un esempio
>> x=[2 4 6 8 10]
x =
2
>> log(x)

10

ans =
0.6931
1.3863
1.7918
>> A=[0.1 0.2 ; 0.3 0.4]

2.0794

2.3026

A =
0.1000
0.3000

0.2000
0.4000

>> sin(A)
ans =
0.0998
0.2955

0.1987
0.3894

Per quanto riguarda le operazioni aritmetiche, laddizione e la sottrazione sono vettorizzate per definizione. Invece, le operazioni di moltiplicazione, divisione ed elevamento a potenza vengono vettorizzate facendo
precendere il simbolo di moltiplicazione, divisione e elevamento a potenza dal simbolo del punto ( .*, ./,
. ) permettendo, in tal modo, che le operazioni vengano fatte componente per componente delle matrici (o
dei vettori) su cui sono applicate.
>> x=[2 4 6 8 10]
x =
2

10

1. I NTRODUZIONE

>> y=[1 3 5 7 9]
y =
1
>> x.*y

12

30

56

90

ans =
2

Se facessimo semplicemente x*y avremmo un messaggio di errore perch richiederemmo unoperazione


di prodotto tra due matrici che hanno n righe e 1 colonna ciascuna, e questa operazione non si pu fare
(vedremo in seguito che si pu fare il prodotto tra due matrici A e B se il numero di colonne di A corrisponde
al numero di righe di B ). Vediamo un altro esempio
>> A=[ 1 2; 3 4]
A =
1
3

2
4

>> B=[2 4; 6 8]
B =
2
6

4
8

>> A*B
ans =
14
30

20
44

>> A.*B
ans =
2
18

8
32

Questa volta, abbiamo considerato due semplici matrici A B . Se facciamo A*B, abbiamo come risultato la matrice prodotto (la studieremo pi avanti nel corso di Calcolo Numerico), se invece facciamo A.*B,
abbiamo come risultato la matrice in cui ogni componente dato dal prodotto dei corrispondenti elementi
sulle due matrici di partenza.

1.2.4 Sulle variabili


Negli esempi precedenti, abbiamo dati a matrici e vettori un nome, x,y,A,B... Abbiamo quindi
assegnato delle variabili.
Una variabile ha, quindi, un significato simile a quello che conosciamo gi nelle espressioni algebriche:
nel nostro caso, per, ad una variabile sempre associato un valore numerico, se si tratta di una variabile
scalare, oppure pi valori, se si tratta di vettori o di matrici. In figura 1.5 vediamo come nella Workspace,
8

1.2. Avvio di MATLAB e Octave

Figura 1.5: Workspace con diversi tipi di variabili.

ciascuna variabile con cui si sta lavorando nella finestra dei comandi, sia elencata con il suo nome e con il
suo valore (che il valore che le stato assegnato se si tratta di una variabile scalare, mentre dichiarato il
tipo di variabile se di tipo matriciale). Dalla figura, possiamo osservare come
ci sono due variabili, una chiamata A e una a: questo perch MATLAB (Octave) sensibile alle lettere
minuscole e maiuscole: una variabile chiamata A diversa da a!
il valore per A <10x10 double>: vuol dire che si tratta di una matrice 10 10 i cui valori sono
memorizzati in doppia precisione (double)
la matrice B, invece, 10 10 in singola precisione (single)
la matrice C 4 4 ed uint8 (che significa?, ora ci arriviamo)
abbiamo poi due scalari, a e b.
ci sono due vettori, uno riga e uno colonna, in doppia precisione
Ciascuna variabile, una volta che viene generata, di un certo tipo e viene classificata di conseguenza. Di
default, ogni variabile (scalare o matriciale) viene considerata in doppia precisione (quindi di tipo double).
Mediante apposite functions di MATLAB (Octave) possibile convertire il valore di una variabile in un altro
tipo: se scriviamo A=single(A), la matrice A viene convertita in una matrice che ha lo stesso nome, i cui
valori per sono ora memorizzati in singola precisione. La function uint8 converte una variabile (che pu
essere scalare o matriciale) in una variabile il cui valore ora un intero a 8 bit senza segno (con valori che
vanno da 0 a 255). Se la variabile gi di tipo intero con valori che si trovano in questo intervallo, non ci sono
problemi, ma se la variabile assume valori al di fuori di questo intervallo, allora i valori sono arrotondati al
pi vicino valore dellintervallo ammissibile. Questo tipo di dato ha senso quando si lavora con numeri interi
e per fare certi tipi di operazioni. Vediamo esempi semplici

G
G
G
G
G
G

>> x=[0 1 2 3]
x =
0

>> uint8(x)
ans =

1. I NTRODUZIONE

>> x=[0 -1 -2 3]
x =
0

-1

-2

>> x=uint8(x)
x =
0

Allinizio il vettore x ha tutti valori positivi e uint8 non cambia i valori del vettore (viene generato un
vettore ans identico a x). Nel secondo caso il vettore x ha elementi negativi che vengono trasformati in 0.
Questa volta il risultato della funcion uint8 assegnato alla stessa variabile x che viene quindi sovrascritta
e il vettore non pi quello di prima.
Se usiamo le function double e single non osserviamo nessun cambiamento a prima vista, ma in
realt lo spazio di memoria per la variabile che cambia.

1.3 Comandi utili


Per lavorare meglio sia nella finestra dei comandi sia, successivamente, per scrivere ed eseguire dei veri e
propri programmi, risultano utili le seguenti funzioni:
who fornisce lelenco di tutte le variabili presenti nella finestra dei comandi (lo si pu vedere anche
nella Workspace;
whos fornisce lelenco di tutte le variabili insieme allo spazio in memoria da esse occupato (con questo comando si pu osservare come una stessa variabile, memorizzata come double o come single,
occupa un diverso spazio di memoria);
help pu essere usato da solo o insieme al nome di una function propria di MATLAB (Octave)
o creata dallutente, e mostra tutte le informazioni utili per capire come usare MATLAB o quella
function;
clear se usata da sola cancella tutte le variabili presenti nella finestra dei comandi, se invece
seguita da un elenco di variabili (messe una di seguito allaltra senza virgole) cancella tutte le variabili
dellelenco;
il punto e virgola ; messo dopo unistruzione non fa vedere il risultato dellistruzione nella finestra
dei comandi;
il simbolo % il simbolo per scrivere commenti: ci che viene scritto dopo % rappresenta un
commento;
clc ha la funzione di pulire la Command Window e di portare il cursore di nuovo in alto a sinistra nella
finestra (la dove era nel momento in cui abbiamo avviato MATLAB (Octave). Le variabili non vengono
cancellate.
diary permette di salvare, su un file che viene chiamato diary, il contenuto di ci che viene scritto
nella finestra dei comandi. Il file diary si trova nella directory corrente in cui si sta lavorando;
diary off chiude il file aperto mediante listruzione diary;
diary filediary comando analogo a diary, ma il file non si chiamer diary bens
filediary, dove filediary rappresenta il nome del file definito dallutente;
save filesave salva tutte le variabili presenti nel Workspace, nel file filesave.mat con
filesave nome scelto dallutente, in modo da conservare tutte le variabili con cui si stava lavorando.
Questo comando utile se si deve chiudere la sessione di lavoro ma si vuole poi ripartire a lavorare
proprio da quelle variabili;

G
G

G
G
G

G
G
G
G

10

1.4. Introduzione alla programmazione

G load filesave ripristina lo stato del Workspace, caricando tutte le variabili che erano state

salvate in filesave.mat in modo da poterci lavorare di nuovo. Si era chiusa la sessione di lavoro e
ora si pu ripartire a lavorare con le stesse variabili di prima.
Ce una notevole differenza di significato tra i files generati dallistruzione diary e quelli generati mediante save. Ci che salviamo con il comando diary paragonabile a ci che pu essere scritto alla lavagna e di cui prendiamo appunti: scriviamo un file di testo che possiamo elaborare o da cui possiamo trarre
dei risultati per i nostri problemi. Al contrario, quello che viene salvato mediante il comando save costituito da una o pi variabili, che possono essere riutilizzate nuovamente in MATLAB (Octave) nella finestra
dei comandi, in sessioni successive a quella in cui sono state create, senza dover rieseguire tutti i comandi
che hanno portato alla creazione delle variabili stesse. Infatti, quando si chiude MATLAB (Octave), tutte le
variabili e i dati vengono persi!
Il comando save utile anche per salvare singole matrici o una lista di matrici nella directory corrente.
Ci soffermiamo sulla possibilit di salvare i dati in formato ASCII, in modo da poter utilizzare i dati che salviamo non solo in MATLAB (Octave) ma anche in programmi scritti con altri linguaggi di programmazione.
Supponiamo di avere una matrice A e di volerla salvare nel file matriceA.dat. Scriveremo il comando

save matriceA.dat A -ascii


Quando vogliamo caricare in MATLAB la matrice dal file useremo il comando

load(matriceA.dat)
e in questo modo avremo la matrice nella variabile matriceA (il nome del file senza lestensione dopo il
punto).

1.4 Introduzione alla programmazione


MATLAB (e di conseguenza Octave, dora in poi quando parleremo di MATLAB ometteremo di scrivere
anche Octave, intendendo che il discorso vale anche per Octave e sottolineeremo solo le differenze importanti) si pu intendere come un linguaggio di programmazione, anche se non rientra in nessuna delle due
categorie di base dei linguaggi di programmazione.
Ci sono infatti due categorie di linguaggi per scrivere programmi:
linguaggi di alto livello (come FORTRAN, C, C++)
linguaggi di basso livello (come assembler).
Il linguaggio macchina, invece, il linguaggio specifico dellelaboratore e consiste di cifre binarie 0 e 1 che
identificano istruzioni elementari. Ogni elaboratore ha il suo linguaggio macchina.
I linguaggi di basso e alto livello si possono tradurre in un qualsiasi linguaggio macchina e possono essere
utilizzati su qualsiasi elaboratore (sono portabili). Con i linguaggi di basso livello, i codici binari (fatti da
0 e 1) vengono sostituiti da opportune parole chiave che permettono una corrispondenza uno-uno tra il
linguaggio di basso livello e il linguaggio macchina.
Con i linguaggi di alto livello, una singola istruzione pu tradurre pi istruzioni di linguaggio macchina.
Inoltre un linguaggio di alto livello facile da capire (nella sua sintassi, nelle sue regole, nel suo modo di
essere utilizzato) da chi programma.
Perci, quando si programma con un linguaggio di alto livello, il programmatore deve conoscere e sapere bene la grammatica, la sintassi, il vocabolario del linguaggio stesso. Uno volta scritto il programma
in modo corretto, occorre fare capire al computer che c un programma da eseguire: bisogna quindi tradurre in linguaggio macchina il programma scritto con il linguaggio di alto livello: questo passaggio lo si fa
mediante la compilazione: un comando particolare chiama un programma di compilazione che viene applicato al programma scritto nel linguaggio di alto livello (che chiamamo programma sorgente) in un programma equivalente scritto in linguaggio macchina e che potr essere eseguito dal calcolatore, detto programma
eseguibile.
In MATLAB , noi scriveremo qualcosa di equivalente al programma sorgente ma non lo compileremo
perch ogni volta che lo vorremo eseguire, esso verr automaticamente compilato ed eseguito.
Abbiamo due tipi di files eseguibili:
lo script, che presenta una lista di comandi da eseguire in ambiente MATLAB . Al suo interno ci
pu essere la chiamata a functions proprie di MATLAB o a functions definite dallutente;

G
G

11

1. I NTRODUZIONE

G le functions (di MATLAB o definite dallutente), che possono avere uno o pi variabili di ingresso

(dati di input) e una o pi variabili in uscita (dati di output).


Sia lo script sia le functions si scrivono su files chiamati M-files perch sono files che vanno salvati
con lestensione .m (ad esempio prova.m, fun.m, . . . ). I files vanno scritti con leditor di testo di MATLAB (nella barra dei comandi di MATLAB in alto a sinistra compare la scritta New Script o New) o con
un altro editor di testo in formato ASCII (in Octave non c un editor e quindi i files vanno scritti con un altro
editor di testo come gedit, ad esempio).
Per eseguire uno script salvato in nomefile.m basta scrivere il nome del programma (senza lestensione .m) nella finestra dei comandi o mediante il comando run(nomefile.m) o run(nomefile)
oppure posizionandosi con il mouse sul nome del programma nella lista che compare nella finestra di Current Folder e con il tasto destro del moouse andare sulla scritta run che compare sulla finestra che si apre (pi
difficile a scriversi che a farsi!).
Ovviamente, sia lo script sia le function definite dallutente devono trovarsi nella directory in cui si
aperto MATLAB , altrimenti bisogna spostarsi nella directory con i files che servono (da MATLAB lo si fa
direttamente o tramite la Current Folder o utilizzando la riga che mostra la directory in cui ci si trova o con i
comandi dellambiente Linux, vale a dire cd e il percorso da fare, invece, in Octave, ci si sposta di directory
solo con i comandi dellambiente Linux).
Per quanto riguarda le function, possono essere eseguite o tramite uno script oppure direttamente
nella finestra dei comandi, specificando le variabili di ingresso e di uscita.

1.5 Problemi e Algoritmi


Gli script e functions che scriveremo ed eseguiremo in ambiente MATLAB serviranno a risolvere
dei problemi.
Cosa intendiamo per problema? Se vediamo alletimologia del nome, esso deriva dal verbo grevo proballein, dove pro significa davanti e ballein significa mettere: mettere davanti... problema ha il significato
di ostacolo, promontorio, impedimento. E difatti, se si ha un problema, la prima cosa che si pensa come
risolvere il problema (come superare lostacolo!).
Per risolvere un problema, bisogna conoscerlo e saperlo descrivere bene. A questo scopo, noi ci serviamo
del linguaggio. Ma il linguaggio naturale va usato con cautela: lo stesso evento descritto, infatti, in modo
diverso da un bambino rispetto ad un adulto; e lo stesso evento viene descritto con un linguaggio diverso da
un matematico, da un fisico, da un ingegnere e da un letterato.
Accanto al linguaggio naturale c il linguaggio artificiale, che si presenta sotto forma di termini tecnici e
notazioni (pensiamo a termini tecnici della fisica e della chimica o ai simboli matematici).
A volte, per, le stesse parole possono essere usate per dire cose completamente diverse! Basti pensare a termini come temperatura, pressione, massa...: hanno significati ben diversi se usati in unofficina per
riparare il motore di unautomobile o se usati in un ambulatorio medico nei confronti di un paziente...
Una volta che, cono attenzione e precisione, si capito il problema, si pu passare alla fase di soluzione.
Concentrando ora la nostra attenzione su problemi da risolvere con laiuto del calcolatore, dobbiamo fare
capire al calcolatore quale il problema da risolvere e come lo deve risolvere. Ma siamo noi che dobbiamo
dare precise istruzioni da eseguire, quindi dobbiamo sapere quale tecnica di soluzione dobbiamo applicare.
Queste precise istruzioni da dare al calcolatore rappresentano quello che chiamiamo algoritmo.
Un algoritmo una sequenza di passi che permettono di risolvere tutto o parte di un problema.1
Un algoritmo si pu paragonare ad una ricetta di cucina. La ricetta fatta di due parti
la lista degli ingredienti da utilizzare
la sequenza dei passi da fare per realizzare la ricetta.

G
G

1 La parola algoritmo entrata in uso negli anni 50 in sostituzione di algorismo, termine con cui si indicava il processo di calcolo
utilizzando i numeri arabi. Il termine algoritmo deriva dal nome di al-Khwarizmi, importante matematico arabo del nono secolo grazie
al quale lEuropa impar ad usare i numeri arabi, oltre alla notazione in base 10. Le procedure che permettevano di effettuare calcoli in
notazione decimale presero il nome di algorismi o algoritmi. Anche la parola algebra viene da questo matematico e, in particolare, dalla
sua opera Al-mukhtasar fi hisab al-jabr wa al-muqabala.
Nel medioevo (e forse anche per qualche studente di oggi!!!), si pensava che questa parola derivasse dal greco algiros (panico, dolore)
e arithmos (numero).

12

1.6. MATLAB come linguaggio di programmazione

Nel realizzare una ricetta si possono avere problemi nel cercare alcuni ingredienti. Una parte dellesecuzione
richieder poco tempo, altre parti richiederanno pi tempo. Alcuni passi non richiedono che si segua un
certo ordine, altri passi richiedono che si mantenga lordine scritto sulla ricetta. . . Le stesse analogie troviamo
in un algoritmo.

1.6 MATLAB come linguaggio di programmazione


Per imparare a usare MATLAB come uno strumento di programmazione, dobbiamo imparare ad usare
il linguaggio che ci permetter di scrivere script e function. E, come tutti i linguaggi, dovremo imparare
alcune regole ben precise.
Un linguaggio di programmazione costituito da dichiarazioni (statements):
descrizione dei dati: che genere di dati abbiamo? Se vogliamo scrivere un programma in cui per
ogni studente calcoliamo la media dei suoi voti, c differenza tra i nomi degli studenti (una stringa
di caratteri) e la loro media (un numero). Si parla di tipo di dati. In MATLAB non si dichiarano le
variabili, come avviene invece per altri linguaggi di alto livello. Ci facilita la programmazione ma pone
pi rischi (se ci si dimentica il tipo di una variabile!). Conviene, perci, prestare sempre attenzione al
tipo di variabili utlizzate.
strutture di controllo. Un programma pu essere visto come una sequenza di istruzioni per risolvere un certo problema. Alcune istruzioni vanno ripetute, altre vanno eseguite solo in determinate
condizioni. . .
lavorazione dei dati (data processing). In un programma occorre poter lavorare sui dati e poterli
manipolare opportunamente.
dichiarazioni di ingresso e uscita (input e output). In genere, un programma scritto in modo che i
dati su cui si lavora possano esistere fuori del programma stesso.

G
G

1.7 Primo script e prima function in MATLAB


Con un editor di testo scriviamo finalmente il nostro primo script. Uno script un programma (una
serie di istruzioni) che si differenzia dai programmi scritti con altri linguaggi di programmazione perch non
si devono dichiarare le variabili. Nel programma che scrivamo, introduciamo due vettori ma non dobbiamo
usare istruzioni che dichiarano il tipo di variabili (vettori, singola o doppia precisione o variabile di tipo intero,
...).
% questa e una r i g a di commento
x =[ 1 , 0.5 , 0 , 0 . 5 , 1]
y=sin ( x )
disp ( ho eseguito il mio primo script ) %disp e una function per la
% visualizzazione
% in questo caso la s t r i n g a
% ho e s e g u i t o i l mio primo s c r i p t

Gi da questo primo script impariamo cose nuove. Intanto per eseguirlo, dopo averlo salvato, scriviamo
il nome con cui abbiamo salvato il file (in questo caso scegliamo il nome primoscript.m) sulla Command
Window. Vediamo cosa succede
>> primoscript
x =
-1.0000

-0.5000

0.5000

1.0000

-0.4794

0.4794

0.8415

y =
-0.8415

13

1. I NTRODUZIONE

ho eseguito il mio primo script

Nello script abbiamo assegnato a due variabili x e y il valore di due vettori riga di 5 componenti e
abbiamo stampato una scritta sulla Command Window. Le due istruzioni x = ... e y= ... si chiamano
istruzioni di assegnazione. Abbiamo assegnato, in questo caso, i valori delle componenti del vettore x e del
vettore y. Nel file, ci che segue il simbolo % una riga di commento. La function disp una function
di MATLAB che serve a visualizzare il contenuto di una variabile che pu essere uno scalare, una matrice,
ma anche una stringa di caratteri, come in questo caso (una stringa di caratteri pu essere considerata a
sua volta una variabile che, per, non numerica). Modifichiamo il nostro script mettendo un ; dopo
ogni istruzione. Se eseguiamo di nuovo lo script, i due vettori non vengono visualizzati e compare solo il
messaggio di esecuzione del primo script. I due vettori, tuttavia, ci sono (basti vedere nella Workspace) e se
si digita x e si schiaccia il tasto di Invio nella Command Window, ci viene visualizzata la variabile x. Stessa
cosa vale per y. Si provi a vedere invece cosa succede se facciamo disp(x) e disp(y). Quando si eseguono
programmi pi lunghi, conviene usare il ; dopo ogni istruzione di assegnazione, in modo da non vedere valori
che scorrono e che comunque non riusciamo a leggere (si pensi a matrici di dimensioni elevate). In tal modo
si velocizzano i tempi di esecuzione dello script.
E se vogliamo cambiare il vettore iniziale x, come facciamo? Usiamo listruzione input. Modifichiamo
lo script
% questa e una r i g a di commento
x=input ( scrivi il vettore x ) ;
y=sin ( x ) ;
disp ( ho eseguito il mio primo script ) ; %disp e una function per la
% visualizzazione
% in questo caso la s t r i n g a
% ho e s e g u i t o i l mio primo s c r i p t

Quando eseguiamo questo script, sulla Command Window compare la frase che abbiamo scritto tra apici e
noi dovremo scrivere il vettore che vogliamo (ad esempio, [ 1 2 3]) e schiacciare il tasto di invio.
>> primoscript
scrivi il vettore x [1 2 3]
ho eseguito il mio primo script

Proviamo ora a voler scrivere un programma che, oltre a darci il valore di sin (x) ci dia il segno della funzione (1 se positivo, 0 se uguale a zero, 1 se negativo). Per fare ci noi possiamo usare la funzione sign, propria
di MATLAB . Ma siccome vogliamo imparare a scrivere noi una function, la scriviamo noi: una function che
dia come output sia il valore di sin (x) sia il suo segno.
Scriviamo dunque un file, che salveremo con il nome mysin.m, in questo modo
function [ y , b]=mysin ( x )
% function [ y , b]= mysin ( x )
% input : x ( sc al ar e , v e t t o r e , matrice )
% output : y= sin ( x )
%
b= sign ( y )
y=sin ( x ) ;
b=sign ( y ) ;
end

La prima riga fondamentale per dire che stiamo scrivendo una function: la regola da rispettare la seguente

function [variabili output] = nomefunction(variabili input)


Se le variabili di output si riducono ad una sola, possiamo evitare di mettere le due parentesi quadre. Le
variabili di input e di output possono essere una o pi di una (e a volte anche nessuna). Subito dopo questa
14

1.8. I predicati elementari

istruzione, conviene mettere delle righe di commento per dire cosa fa questa function. Questo perch, facendo help nomefunction sulla Command Window, avremo disponibili tutte le informazioni che abbiamo
scritto in quelle righe di commento e ci sar utile per ricordare cosa fa quella determinata funzione.
Una function termina con listruzione end.
Una volta salvata, la funzione pu essere chiamata direttamente nella Command Window, oppure allinterno di uno script. Se scriviamo semplicemente y=mysin(x), la function restituisce solo il primo vettore che viene generato. Se invece scriviamo [y,b]=mysin(x), allora ci vengono restituiti i due vettori.
Possiamo usare anche nomi diversi rispetto a y b.
La function pu essere richiamata anche allinterno di uno script. Modifichiamo lo script primoscript
in questo modo:
% questa e una r i g a di commento
x=input ( scrivi il vettore x ) ;
[ y , b]=mysin ( x )
disp ( ho eseguito il mio secondo script )

Osserviamo che, in questo caso, non abbiamo messo il ; dopo la chiamata alla function, in modo da
visualizzare subito il risultato.
Dagli esempi che abbiamo visto, possiamo chiederci quando serve scrivere uno script piuttosto di una
function. Vediamo, intanto, le principali differenze.
Le variabili usate allinterno di uno script non vengono cancellate a meno che non venga fatto tramite la funzione clear. In una function tutte le variabili usate al suo interno e che non compaiono
nella lista delle variabili di output vengono cancellate una volta che la function viene eseguita.
Una function pu essere usata allinterno di uno script, per snellirne la sua struttura (se determinate istruzioni vanno ripetute pi e pi volte, la function ci permette di scriverle una volta sola e di
richiamarle con parametri di input diversi). In tal caso, la function agisce da sottoprogramma.

G
G

1.8 I predicati elementari


Le istruzioni che traducono algoritmi di soluzione di problemi numerici non sono sempre istruzioni
di tipo sequenziale, cio istruzioni da eseguire luna dopo laltra (fai questo, poi questo, poi questo ancora...esempio poni a=10, b=sin(a), c=a*b...). Molte volte alcune istruzioni vanno eseguite se sono
vere determinate condizioni piuttosto che altre, o fino a quando vera una determinata condizione...

Esempio
Esempio 1.8.1 Per calcolare le radici di unequazione di secondo grado, ax 2 + bx + c = 0 sappiamo che
dobbiamo calcolare il discriminante = b 4 4ac e se = 0 le due radici coincidono, se > 0 abbiamo
due radici distinte, se invece < 0 le due radici non sono reali.
Abbiamo una condizione su e, a seconda della condizione, facciamo una cosa piuttosto di un altra.
I simboli =, >, < sono degli operatori logici. La proposizione < 0 pu essere vera o falsa a seconda del
valore assunto dalla variabile . Gli operatori logici, quindi, ci permettono di costruire dei predicati. Vediamo
quali sono gli operatori logici che useremo

15

1. I NTRODUZIONE

Operatore
>

Significato
maggiore

Esempio
(a >b)

>=

maggiore o uguale

(a>=b)

<

minore

(a<b)

<=

minore o uguale

(a<=b)

==

uguale

(a==b)

non uguale

(a =b)

Valore
Vero se a > b
Falso se a b
Vero se a b
Falso se a < b
Vero se a < b
Falso se a b
Vero se a b
Falso se a > b
Vero se a = b
Falso se a 6= b
Vero se a 6= b
Falso se a = b

Se il predicato vero, MATLAB restituisce come risultato 1, se falsa d 0. Luso delle parentesi per scrivere
un predicato facoltativo (provare).
>> a=12;
>> b=5;
>> (a<b)
ans =
0
>> (a==b)
ans =
0
>> (a>=b)
ans =
1

Il predicato esso stesso una variabile (si osservi che il risultato associato alla variabile ans): vale 1 se
vero, 0 se falso.
Un operatore logico pu essere applicato anche a matrici e vettori: se A e B sono due matrici, il predicato
(A>B) restituisce una matrice i cui elementi sono il risultato del confronto tra ciascun elemento della matrice
A con il corrispondente elemento della B.
>> A=[1 2; 8 9]
A =
1
8

2
9

>> B=[ 1 4; 5 10]


B =
1
5

16

4
10

1.8. I predicati elementari

>> A>=B
ans =
1
1

0
0

In molti algoritmi, tuttavia, non basta vedere se un singolo predicato sia vero o falso. A volte ci servono
pi predicati da mettere insieme per formare una proposizione logica.

Esempio
Esempio 1.8.2 Supponiamo di dover implementare un algoritmo in cui vanno eseguite alcune istruzioni fintantoch vero che (1) il numero di iterazioni, it, minore di un numero massimo prefissato,
itmax, e (2) il valore assoluto della differenza di due valori che sono generati dallalgoritmo (chiamiamo questa quantit sc) maggiore di una tolleranza prefissata, tol. Abbiamo una proposizione fatta
di due predicati (it <itmax) e (sc >tol). I due predicati sono messi insieme tramite la congiunzione e. Fintantoch vera tutta la proposizione (quindi sono veri tutti e due i predicati) allora ci
saranno da eseguire determinate istruzioni, altrimenti non si eseguiranno. Quando la proposizione non
pi vera? Diventa falsa quando il primo o il secondo predicato diventano falsi, cio quando le iterazioni diventano maggiori del massimo prefissato oppure quando la variabile sc diventa minore della
tolleranza.
Vediamo allora gli operatori logici per unire due proposizioni:
Operatore
&
|

Significato
congiunzione di pi predicati
disgiunzione di pi predicati
negazione di un predicato o di una proposizione

Esempio
Esempio 1.8.3 Riprendiamo i predicati di prima it < itmax e sc > tol. La proposizione (it
<itmax) & (sc >tol) un proposizione che vera quando entrambi i predicati sono veri,
diventa falsa quando uno dei due predicati falso.
La proposizione (it <itmax) | (sc >tol) vera quando uno dei due predicati vero (pu essere uno vero e uno falso, la proposizione comunque vera perch | significa o, oppure). La proposizione
falsa quando entrambi i predicati sono falsi.
La proposizione
(it <itmax) significa negare il contenuto del predicato, quindi equivalente a
it >= itmax. Quindi vera se it >= itmax e sar falsa se it <itmax.
La proposizione
( (it <itmax) & (sc >tol)) significa negare la proposizione che
congiunge i due predicati. vera quando uno dei due predicati falso.
Pi in generale possiamo dire che

(& ) due predicati veri d come risultato una proposizione vera.


G Congiungere
(&) due predicati falsi d come risultato una proposizione falsa.
G Congiungere
(&) due predicati, uno vero ed uno falso, d come risultato una proposizione falsa.
G Congiungere
(|) due predicati veri d come risultato una proposizione vera.
G Disgiungere
(|) due predicati falsi d come risultato una proposizione falsa.
G Disgiungere
(|) due predicati, uno vero ed uno falso, d come risultato una proposizione vera.
G Disgiungere
( )un predicato falso d come risultato un predicato vero.
G Negare
G Negare ( ) un predicato vero d come risultato un predicato falso.
Importanti sono da ricordare le regole di De Morgan. Dati due predicati P1 e P2
G ( ( (P1)&(P2) ) equivale a scrivere ( (P1) | (P2) ) Negare una congiunzione significa disgiungere le
negazioni dei due predicati che la compongono.
G ( ( (P1)|(P2) ) equivale a scrivere ( (P1) & (P2) ) Negare una disgiunzione significa congiungere la
negazione dei due predicati che la compongono.

17

1. I NTRODUZIONE

1.9 Strutture e cicli


Vediamo, in generale, adesso come si possono eseguire alcuni tipi di istruzioni.

1.9.1 Ciclo if
p
Supponiamo di voler calcolare la radice quadrata positiva di un numero reale : + x. Sappiamo che se
largomento x negativo, la funzione non d un valore reale (si passa infatti nel campo dei numeri complessi:
provare la function di MATLAB sqrt con un numero negativo e vedere il risultato che d). Proviamo allora
a scrivere una nostra function che calcoli la radice quadrata solo per valori positivi dellargomento.
function [ y ]= mysqrt ( x )
% function [ y ]= mysqrt ( x )
% input x
% output y= s q r t ( x ) per x >=0
%
a l t r i m e n t i s i ha un messaggio di e r r o r e
%
e y = [ ] v a r i a b i l e vuota
i f ( x >=0)
y=sqrt ( x ) ;
else
disp ( largomento e negativo )
y=[];
end

Abbiamo usato il cosiddetto ciclo if. Se (if) (x>0) allora fai una determinata cosa, altrimenti (else)
fai unaltra cosa. Osserviamo che per visualizzare una stringa di caratteri in cui c lapostrofo o laccento,
abbiamo usato due volte gli apici.
Il ciclo if si pu schematizzare nei seguenti modi a seconda che si abbia una o pi condizione.
Ciclo if con pi condizioni
Ciclo if con una condizione
i f ( espr . l o g i c a )
{ i s t r u z i o n e 1a
{ i s t r u z i o n e 2a
{
....
el se
{ i s t r u z i o n e 1b
{ i s t r u z i o n e 2b
{
....
end

}
}
}
}
}
}

i f ( espr . logi ca1 )


{ i s t r u z i o n e 1a }
{ i s t r u z i o n e 2a }
{
....
}
e l s e i f ( espr . logi ca2 )
{ i s t r u z i o n e 1b }
{ i s t r u z i o n e 2b }
{
....
}
....
el s e
{ i s t r u z i o n e 1z }
{ i s t r u z i o n e 2z }
{
....
}
end

Osserviamo che in MATLAB elseif va scritto tutto attaccato altrimenti si apre un altro ciclo if concatenato
al precedente.
Se non c nessuna istruzione in alternativa alle condizioni poste, si omette lelse.
Scriviamo uno script che risolve unequazione
di secondo grado ax 2 + bx + c = 0. Usiamo un ciclo if per
p
controllare il segno del discriminante = b 2 4ac e, di conseguenza, scrivere le radici.
a=input ( valore di a ) ;
b=input ( valore di b ) ;
c=input ( valore di c ) ;
d e l t a =sqrt (b^2 4* a * c ) ;

18

1.9. Strutture e cicli

i f ( d e l t a ==0)
x1=b/ ( 2 * a ) ;
x2=x1 ;
disp ( le radici sono coincidenti )
disp ( [ x1 x2 ] )
e l s e i f ( d e l t a >0)
x1= (b + d e l t a ) / ( 2 * a ) ;
x2= (b d e l t a ) / ( 2 * a ) ;
disp ( le radici sono )
disp ( [ x1 x2 ] )
else
disp ( non ci sono radici reali )
end

Salviamo lo script con il nome radici.m. Per visualizzare su una sola riga il valore delle due radici abbiamo creato il vettore che ha come componenti x1 e x2 e lo abbiamo visualizzato mediante la function disp.
Osserviamo che, quando eseguiamo questo script, dobbiamo dare noi in input i valori dei coefficienti dellequaazione. Tutte le variabili che vengono generate nello script rimangono nella Workspace (a meno che non
decidiamo noi di cancellarle usando il comando clean). Per capire meglio la differenza tra script e function,
scriviamo ora una function che fa la stessa cosa. Chiamiamo la function funradicieq2.m.
function [ x1 , x2 ]= funradicieq2 ( a , b , c )
% function [ x1 , x2 ]= radicieq2 ( a , b , c )
% input : a , b , c v a r i a b i l i s c a l a r i d e l l equazione di secondo grado
% ax^2+bx+c=0
% output : x1 e x2 , l e due r a d i c i d e l l equazione
d e l t a =sqrt ( b^2 4* a * c ) ;
i f d e l t a ==0
x1=b/ ( 2 * a ) ;
x2=x1 ;
e l s e i f d e l t a >0
x1= (b + d e l t a ) / ( 2 * a ) ;
x2= (b d e l t a ) / ( 2 * a ) ;
else
disp ( non ci sono radici reali )
x1 = [ ] ;
x2 = [ ] ;
end
end

I comandi sono quasi gli stessi dello script. Per avere sempre dei valori in uscita, abbiamo posto x1, x2
uguali a due variabili vuote (luso delle parentesi quadre senza nessun valore allinterno []) insieme ad un
messaggio di spiegazione, per discriminanti negativi. Questa volta possiamo eseguire la function allinterno
della Command Window o mediante uno script.
>> [x1, x2]=funradicieq2(1,-2,1)
x1 =
1

x2 =
1

Tutte le variabili che sono usate allinterno della function non sono salvate nella Workspace, ad eccezione
delle variabili di output.
Sia nello script che nella function abbiamo visto un esempio di uso del ciclo if.
19

1. I NTRODUZIONE

Proviamo a complicare le cose, inserendo altri cicli if allinterno del ciclo if.
Nello studiare la propagazione degli errori, abbiamo visto che, per effetto della cancellazione numerica,
le due radici di unequazione di secondo grado possono non essere arrotondate correttamente se b 2 >> 4ac.
c
In tal caso, applicando la formula x 1 x 2 = possiamo evitare il fenomeno della cancellazione. Consideriamo
a
p
p
b b 2 4ac
b + b 2 4ac
e x2 =
:
due casi, assumendo x 1 =
2a
2a
b > 0: per effetto della cancellazione numerica x 1 affetta da errore. In tal caso dobbiamo correggere
x 1 mediante la formula x 1 = c/(x 2 a).
b < 0: ora x 2 affetto da errore (b positivo e va sottratto ad una quantit molto vicina a b stesso).
Correggiamo x 2 mediante la formula x 2 = c/(x 1 a).
Andiamo a correggere la function (stessa cosa si pu fare con lo script precedente).

G
G

function [ x1 , x2 ]= funradicieq2nocanc ( a , b , c )
% function [ x1 , x2 ]= radicieq2 ( a , b , c )
% input : a , b , c v a r i a b i l i s c a l a r i d e l l equazione di secondo grado
% ax^2+bx+c=0
% output : x1 e x2 , l e due r a d i c i d e l l equazione
% s i usa la formula per e v i t a r e la cancellazione numerica
d e l t a =sqrt (b^2 4* a * c ) ;
i f d e l t a ==0
x1=b/ ( 2 * a ) ;
x2=x1 ;
e l s e i f d e l t a >0
i f b<0
x1=(b + d e l t a ) / ( 2 * a ) ;
x2= c / ( a * x1 ) ;
el se
x2= (b d e l t a ) / ( 2 * a ) ;
x1=c / ( a * x2 ) ;
end
else
disp ( non ci sono radici reali )
x1 = [ ] ;
x2 = [ ] ;
end
end

Abbiamo cambiato il nome alla function per confrontare i risultati. Unimportante osservazione riguarda lo
stile con cui abbiamo scritto le istruzioni: le istruzioni non sono scritte una sotto laltra ma sono rientrate
rispetto a if else/elseif end, in modo da capire che ci sono dei cicli if.
Per poter vedere il fenomeno di cancellazione con queste due function dobbiamo inserire valori molto
grandi per b e molto piccoli per c, come b = 106 (b=1.e+6) e c = 0.1.
>> [x1, x2]=funradicieq2(1,1e+6,0.1)
x1 =
-1.000007614493370e-07

x2 =
-9.999999999999000e+05
>> x1*x2
ans =

20

1.9. Strutture e cicli

0.100000761449327
>> [x1, x2]=funradiceeq2nocanc(1,1e+6,0.1)
x1 =
-1.000000000000100e-07

x2 =
-9.999999999999000e+05
>> x1*x2
ans =
0.100000000000000

Lerrore sul prodotto x 1 x 2 dellordine di 7.6 107 , ma lerrore sulla radice x 1 comunque un errore
molto basso. Ci dovuto al fatto che le nostre variabili sono tutte in doppia precisione e MATLAB esegue
le operazioni con precisione di macchina.
Se inseriamo i valori di a, b e c in singola precisione mediante la function single, si vede qualche
differenza in pi. Proviamo:
>>
>>
>>
>>

a=single(1);
b=single(1.e+6);
c=single(0.1);
[x1, x2]=funradicieq2(a,b,c)

x1 =
0

x2 =
-1000000
>> x1*x2
ans =
0
>> [x1, x2]=funradicieq2nocanc(a,b,c)
x1 =
-1.0000000e-07

x2 =
-1000000
>> x1*x2

21

1. I NTRODUZIONE

ans =
0.1000000

In questo caso la prima function ci d x 1 = 0 al posto di x 1 = 1 107 . Lerrore pi alto rispetto al caso
precedente ma non cos appariscente.
Proviamo allora a creare una function che ci permetta di lavorare solo con un certo numero di cifre decimali, come se avessimo una macchina in virgola mobile normalizzata a n cifre decimali, con n stabilito
dallutente (pi piccolo n, maggiore sar il fenomeno di cancellazione numerica). Attenzione, per: le
operazioni che eseguiremo con MATLAB saranno sempre eseguite in doppia precisione mentre il risultato
dovr essere convertito nella precisione che vogliamo noi.
Per capire la function che scriveremo, partiamo con un esempio. Supponiamo di avere il numero x =
12.987654. Vogliamo rappresentare questo numero in una macchina in virgola mobile normalizzata con
n = 4 cifre decimali. Quindi passeremo al numero x = 1.2988 101 .
Lalgoritmo che implementeremo si basa sui seguenti passi
considero il numero in valore assoluto, cio 12.987654;
valuto log10 del numero: in questo caso ottengo il valore 1.113530710205556, che, se viene arrotondato
allintero pi vicino per difetto, mi d il valore 1, cio proprio lesponente della base (101 );
adesso divido il valore assoluto del numero per 101 in modo da avere la parte frazionaria del numero
stesso (eventualmente, come in questo caso, in forma normalizzata): 12.987654/101 = 1.2987654;
moltiplico questo valore per 10n , dove n il numero di cifre decimali che ho deciso di avere nella
rappresentazione finale, in questo caso 4: ottengo 1.2987654e + 04 (cio 12987.654)
arrotondo il valore allintero pi vicino: ho 12988;
divido per 10n : ricavo 1.2988;
ora prendo questo valore, lo moltiplico per il segno del numero di partenza e per 101 (lesponente
che avevo trovato al secondo passo): arrivo al valore 12.988. Il numero non espresso in forma
normalizzata, ma in sostanza il numero che andavo cercando (12.988 = 1.2988 101 ).
Per completare la function ci serve qualcosa che ci permetta di arrotondare allintero pi vicino per difetto
e di arrotondare allintero pi vicino. Fortunatamente, in MATLAB , esistono gi due function che fanno
queste cose:
la function floor arrotonda allintero pi vicino per difetto;
la function round arrotonda allintero pi vicino con la regola dellarrotondamento simmetrico.
Queste function (come altre simili ceil, fix per la cui spiegazione rimandiamo allhelp on line)
possono essere applicate a variabili matriciali (vettori e scalari vengono visti come casi particolari di matrici).

G
G
G
G
G
G
G
G
G

>> floor(2.5)
ans =
2
>> round(2.5)
ans =
3
>> floor(1.1)
ans =
1
>> round(1.1)

22

1.9. Strutture e cicli

ans =
1

Per avere il segno di una variabile, usiamo la function sign (che vale +1 o -1 a seconda di segno positivo
o negativo). Ecco allora la function, che chiamiamo roundnorm
function y=roundnorm( x , n)
% function y=roundnorm ( x , n)
% input x : puo e s s e r e s c al are , v e t t o r e o matrice
%
n : numero di c i f r e decimali in un sistema normalizzato
%
pensiamo i l numero s c r i t t o come a . b_1b_2b_3 . . . b_n x 10^p
%
con a ~= 0
% output y : arrotondamento di x in un sistema normalizzato a n c i f r e decimali
%
di default , in MATLAB i l numero non viene v i s u a l i z z a t o in v i r g o l a
%
mobile normalizzata .
%
%
% Esempi
%
x= si n (3)=0.141120008059867
%
n=4 % 4 c i f r e decimali
%
y=roundnorm ( x , n)= 0.141120000000000
%
( in v i r g o l a mobila normalizzata , y= 1.4112 10^(1)
%
% x=exp (1)=2.718281828459046
% y=roundnorm ( x , n)= 2.718300000000000 (=2.7183 10^0)
%
% x=exp (10)=2.202646579480672 e+04
% y=roundnorm ( x , n)= 22026 (= 2.2026 10^4)
%
% s i possono avere c a s i p a r t i c o l a r i
% x=55.981999999999999
% in MATLAB y=roundnorm ( x , n)= 55.981999999999999 (= 55.982)
% in questo caso , i n f a t t i ,
% f * 10^ e = 5.598200000000000 * 10=55.981999999999999
% in Octave y=roundnorm ( x , n)= 55.9820000000000
xx = abs ( x ) ; % s i considera i l valore a s s o l u t o di x
e = f l o o r ( log10 ( xx ) ) ; %esponente di x
f = xx . / 1 0 . ^ e ;
%parte f r a z i o n a r i a di x
f =round ( f * 10^n)/10^n ;
y=sign ( x ) . * f . * 10^ e ;
end

Proviamo a vedere cosa succede se applichiamo questa function per risolvere unequazione di secondo
grado. Nelle due function precedenti sulla soluzione di unequazione di secondo grado, dobbiamo andare
a convertire le variabili delta, x1 e x2 applicando la function roundnorm: aggiungeremo delle istruzioni del tipo delta=roundnorm(delta,n); x1=roundnorm(x1,n); x2=roundnorm(x2,n);,

23

1. I NTRODUZIONE

mentre lintero n viene dato in input.

Esercizio 1.9.1 Come esercizio si creino, dunque, due nuove function, una che risolve lequazione di secondo grado senza andare a considerare la correzione del fenomeno di cancellazione numerica e laltra,
invece, che corregge la cancellazione numerica, in modo che, in input, oltre ai parametri a,b,c venga
chiamato anche lintero n. Allinterno delle function si aggiungano le istruzioni di chiamata alla function
roundnorm.
Si trovino, quindi, le radici delle equazioni
0.1x 2 42x + 0.3 = 0
x 2 56x + 1 = 0
x 2 18x + 0.03 = 0
Si confrontino i risultati tra le due function, lavorando con n = 4 cifre decimali e utilizzando anche le
function che lavorano in doppia precisione.

G
G
G

1.9.2 Ciclo while


Unaltra struttura molto importante data dal ciclo while. Ci possono essere situazioni in cui determinate
istruzioni sono da ripetere fintantoch vera una determinata condizione. Prendiamo in esame lo schema
di bisezione: ad ogni passo del metodo si prende il punto medio dellintervallo, si confronta il valore della
funzione nel punto medio con il valore agli estremi e si prende, come nuovo sottointervallo, lintervallo che
ha come estremi il punto medio e uno dei estremi dellintervallo precedente. Queste istruzioni vanno ripetute
fino a quando lampiezza dellintervallo su cui si lavora diventa molto piccola (minore di una certa tolleranza
prefissata) oppure siamo cos fortunati che il punto medio proprio la radice della funzione, oppure non
stiamo arrivando a convergenza ma abbiamo fatto un numero elevato di iterazioni.
La struttura del cilclo while fatta nel seguente modo
Ciclo while
while ( espressione
{ istruzione
{ istruzione
{
...
{ istruzione
end

logica )
1 }
2 }
}
n }

Le istruzioni 1, 2, . . . , n vengono ripetute ciclicamente e non una sola volta come accade nel ciclo if: infatti
ogni volta che si esegue lultima istruzione allinterno del ciclo while, si torna poi allespressione logica posta
subito dopo la parola while e se vera si eseguono di nuovo le istruzioni 1, 2, . . . , n, se falsa, invece, si esce
dal ciclo. importante, dunque, avere unespressione logica che eviti di creare cicli infiniti, che farebbero
entrare in stallo lesecuzione di uno script o di una function!
Vediamo un esempio di ciclo while, scrivendo una function che implementa lo schema delle bisezioni.
Vedendo questa function, impareremo nuove potenzialit di MATLAB .
function [ c , i t e r , scarto ]= funbisez ( fun , a , b , t o l l , itmax )
% function [ c , i t e r , s c a r t o ]= funbisez ( fun , a , b , t o l l , itmax )
% function che c a l c o l a una radice d e l l a funzione fun d e f i n i t a
% nell intervallo [a , b]
% input : function fun : puo e s s e r e una function i n l i n e , una
%
function .m ( in questo caso i l nome d e l l a function
%
va s c r i t t o t r a a p i c i ) oppure una function_handle
%
estremi d e l l i n t e r v a l l o a e b

24

1.9. Strutture e cicli

%
tolleranza t o l l
%
numero massimo di i t e r a z i o n i itmax
% output : approssimazione d e l l a radice data dalla v a r i a b i l e c
%
numero di i t e r a z i o n i e f f e t t u a t e i t e r
%
scarto finale
%
% Esempi con i n l i n e function e handle function
%
%
f = i n l i n e ( 2 . * xcos ( x ) + 1 ) ;
%
a=6; b=4; t o l l =1. e 10; itmax =100;
%
[ c , i t e r , s c a r t o ]= funbisez ( f , a , b , t o l l , itmax )
% restituisce
% c = 1.4552e11
% i t e r =36
% s c a r t o =7.2760 e11
%
%
f = i n l i n e ( x.^2 sin (3x ) + 2 ) ;
%
a=2; b=1; t o l l =1. e 10; itmax =100;
%
[ c , i t e r , s c a r t o ]= funbisez ( f , a , b , t o l l , itmax )
% restituisce
%
estremi d e l l o s t e s s o segno
%
c =[]
%
iter =[]
%
scarto =[]
%
%
%
a = 0 . ; b=3; t o l l =1. e 10; itmax =100;
%
[ c , i t e r , s c a r t o ]= funbisez ( @cos , a , b , t o l l , itmax )
%
restituisce
%
c =1.5708
%
i t e r =34
%
s c a r t o =8.7311 e11
%
aux= f e v a l ( fun , a ) * f e v a l ( fun , b ) ; %aux= v a r i a b i l e d appoggio per
% c o n t r o l l a r e i l segno
% d e l l a funzione a g l i estremi a e b
%f e v a l e una function che permette di valutare
% i l valore d e l l a funzione fun n e l l a v a r i a b i l e a
% ( f e v a l ( fun , a ) ) oppure fun ( b ) in f e v a l ( fun , b ) )
i f aux>=0
disp ( estremi dello stesso segno )
c =[ ] ;
i t e r =[ ] ;
scarto =[ ] ;
return % l i s t r u z i o n e return interrompe l esecuzione d e l l a function
% s e g l i estremi sono d e l l o s t e s s o segno non s i puo
% applicare l o schema d e l l e b i s e z i o n i
end
i t e r =0; % i t e r e la v a r i a b i l e i n t e r a che conta l e i t e r a z i o n i che vengono
% effettuate
c =( a+b ) * 0 . 5 ;
scarto =abs ( ba ) * 0 . 5 ; % v a r i a b i l e che permette di c o n t r o l l a r e di quanto c i
% s i s t a avvicinando a l l a radice
while i t e r <=itmax && f e v a l ( fun , c)~=0 && scarto > t o l l
i t e r = i t e r +1;
aux= f e v a l ( fun , a ) * f e v a l ( fun , c ) ;
i f aux <0

25

1. I NTRODUZIONE

b=c ;
el se
a=c ;
end
c =( a+b ) * 0 . 5 ;
scarto=abs ( ba ) * 0 . 5 ;
end
i f ( i t e r >itmax )
disp ( raggiunto il numero massimo di iterazioni )
end

Oltre alluso del ciclo while (e di un ciclo if allinterno del ciclo while), la novit nella function funbisez
dato dal fatto che, tra i parametri di input, compare la funzione di cui si vuole approssimare una radice. In
linea di massima il nostro schema pu essere applicato su una generica funzione f (x) (funzione reale di una
sola variabile reale), al fine di poter approssimare (se esiste) una sua radice. Possiamo scrivere la funzione del
nostro problema utilizzando una function (quindi scrivere un file e salvarlo con lestensione .m). Esempio
function y=fun ( x )
% function y=fun ( x )
% function da usare nel metodo di b i s e z i o n i
% function di esempio
y = 2 . * xcos ( x )+1
end

Questa function la salviamo come fun.m e la chiamiano tra i parametri di input della function funbisez
tra apici [c, iter ,scarto]=funbisez(fun,a,b,toll,itmax) In tal modo, noi diamo il nome della function su cui
applicheremo il metodo di bisezione. Potremmo chiamare la nostra function anche in modo diverso, non
fun.m ma, ad esempio, g.m: limportante mettere tra apici il nome della function. Daltra parte, non
importante il nome dato alla variabile ma il significato di ciascuna variabile e lordine con cui compare.
corretto chiamare la function in questo modo [x, it ,sc]=funbisez(fprova,extra,extrb,toller,maxit) Ci
significa che fprova.m la function di cui vogliamo calcolare lo zero, extra e extrb sono gli estremi
dellintervallo, etc etc. Ogni variabile ha un nome diverso rispetto a quello che abbiamo scritto nella function
ma il significato corrisponde.
Non corretto invece scrivere [c, iter ,scarto]=funbisez(a,b,fun,toll,itmax) perch ora abbiamo la
variabile a come prima variabile e non la funzione su cui applicare il metodo!
Ci sono anche altri modi per inserire una funzione tra i parametri di ingresso di una function. Se la funzione gi predefinita si pu scrivere il nome della function tra apici: per esempio, vogliamo calcolare gli zeri
della funzione f (x) = cos (x): basta scrivere [c, iter ,scarto]=funbisez(cos,a,b,toll,itmax)
Se la funzione pi complicata si pu usare la cosiddetta inline function. Sulla Command Window (o
allinterno di uno script che poi chiamer la funbisez) scriviamo il seguente comando
>> f=inline(2.*x-cos(x)+1)
f =
Inline function:
f(x) = 2.*x-cos(x)+1

La function di MATLAB inline ci permette di creare una function che dipende da una o pi variabili.
Esempi:
f=inline(cos(x)-2) (dipende da una sola variabile),
f=inline(cos(x)+sin(y)) (dipende da due variabili).
Rispetto alle function .m, questa function caratterizzata da una sola istruzione (non possiamo costruire function che dipendono da cicli o da pi righe di istruzioni). Una volta che chiudiamo la session di
MATLAB , perdiamo questa function (se ci serve in unaltra sessione dovremo riscriverla).

26

1.9. Strutture e cicli

Un altro modo per passare una funzione tra i parametri di una function di usare una cosiddetta function
handle: una function handle si costruisce mettendo il simbolo @ prima del nome della function gi definita
(ad esempio @sin, @cos) oppure definita dallutente come M-file (ad esempio @myfun). Esempi:
[c, iter ,scarto]=funbisez(@cos,a,b,toll,itmax)
[c, iter ,scarto]=funbisez(@myfun,a,b,toll,itmax) ,

dove myfun.m una function che abbiamo definito noi. In maniera equivalente, si pu assegnare ad una
variabile il nome di una function handle nella Command Window o in uno script. Esempio:
>> f=@fun
f =
@fun
>> [c,iter,scarto]=funbisez(f,a,b,toll,itmax);

Ora che abbiamo visto che una funzione pu essere chiamata tra i parametri di input di una function,
vediamo come valutarla al suo interno Nellesempio che stiamo considerando, come valutare allinterno della
funbisez la funzione fun (che pu essere un M-file, una function inline o una function handle)? Si usa la
seguente istruzione (che possiamo leggere nella function funbisez) feval(fun,a) dove fun il nome che diamo
alla funzione allinterno della function nellesempio, funbisez, mentre a la variabile in cui dobbiamo
valutare la fun. Quindi feval una function di MATLAB che permette di valutare il valore di una function:
corrisponde a fun(a). Se la funzione una funzione di pi variabili, vanno messe tutte le variabili da cui
dipende: feval(fun,x1,x2 ,...)

Esercizio 1.9.2 Si applichi il metodo di bisezione per trovare gli zeri di funzione delle seguenti funzioni,
imponendo una tolleranza pari a 1010 e fissando itmax=100:
f (x) = ln (x) + x 2 x (ammette come radice = 1)
2
f (x) = e 1x x sin (x) (ammette pi di una radice)

G
G

Se risolviamo lesercizio precedente, ci accorgiamo che non sempre facile trovare un intervallo in cui la
funzione assegnata abbia segno opposto agli estremi. utile quindi avere unidea del grafico della funzione
stessa. In questo senso MATLAB ci permette di visualizzare facilmente una funzione tramite la function
ezplot. La function ezplot pu avere uno o pi argomenti di input. Si pu dare solo la funzione (inline,
m-file o function handle) da visualizzare, e il grafico viene fatto di default per x che varia in [6, 6] (se
definita per valori negativi) o in [0, 6] se non definita per valori negativi. Possiamo cambiare gli estremi
dellintervallo, aggiungendo come variabile lintervallo stesso.
Esempi
ezplot(f) %f e una function inline o una function handle
ezplot(f) %f e una function Mfile definita dallutente o di MATLAB
ezplot(f ,[ a,b]) % si visualizza il grafico della f per x in [a,b]

Per visualizzare tutte gli usi della function ezplot si controlli mediante lhelp sulla Commans Window.
Del tutto simile a ezplot la function fplot in cui, tuttavia, va specificato lintervallo [a, b]. Vedremo,
comunque, che ci sono altri modi per fare grafici.
Ora, seguendo le stesse linee della function funbisez, scriviamo una function che applichi lo schema del
punto fisso. Chiamiamo questa function pfisso0.m (capiremo poi perch abbiamo scritto quello zero nel
nome della function).
Questa volta, per vedere se ci stiamo avvicinando a convergenza, controlliamo la differenza in valore
assoluto tra due approssimazioni successive. Quindi, la variabile scarto assume davvero il significato del
nome (al contrario di quanto abbiamo fatto in funbisez). Nella function diamo anche una stima del fattore
di convergenza (o costante asintotica di convergenza) M tramite le variabili asint1 e asint2. Vediamo
questa function
27

1. I NTRODUZIONE

function [ xkp1 , i t e r , scartokp1 , asint1 , asi nt2 ]= p f i s s o 0 ( fun , dfun , x0 , t o l l , itmax )


%function [ xkp1 , i t e r , scartokp1 , asint1 , asint2 ]= p f i s s o 0 ( fun , dfun , x0 , t o l l , itmax )
% significato delle variabili
%
i t e r : i t e r a z i o n e del metodo del punto f i s s o
%
itmax : numero massimo di i t e r a z i o n i
%
t o l l : t o l l e r a n z a p r e f i s s a t a per l approssimazione del punto f i s s o
%
x0 : punto i n i z i a l e d e l l a s u c c e s s i o n e
%
xk : approssimazione al passo k
%
xkp1 : approssimazione al passo k+1
%
s c a r to k : s c a r t o a l l i t e r a t a precedente
%
scartokp1 : valore a s s o l u t o t r a l i t e r a t a c o r r e n t e e quella al
%
passo precedente
%
asint1 : scartokp1 / s cart ok approsimazione del f a t t o r e di convergenza M
%
asint2 : abs ( dfun ( xkp1 ) )
approssimazione del f a t t o r e di convergenza M
%
fun : funzione di cui s i vuole c a l c o l a r e un approssimazione del punto f i s s o
%
dfun : derivata d e l l a funzione fun
%
%
Esempio
%
x0 = 0 . 1 ; t o l l =1. e 12; itmax =100;
%
dfun= i n l i n e ( sin ( x ) ) ;
%
[ xkp1 , i t e r , scartokp1 , asint1 , asint2 ]= p f i s s o 0 ( @cos , dfun , x0 , t o l l , itmax )
%
restituisce
%
xkp1=0.7391
%
i t e r =70
%
scartokp1 =9.4613 e13
%
asint1= 0.6735
%
asint2 =0.6736
scartokp1 =2.0 * t o l l ;
scartok=scartokp1 ;
iter = 0;
xk=x0 ;
while ( scartokp1 >= t o l l )&& ( i t e r <=itmax )
i t e r = i t e r +1;
xkp1= f e v a l ( fun , xk ) ;
scartokp1=abs ( xkp1 xk ) ;
asi nt1 = scartokp1 / scartok ;
asi nt2 =abs ( f e v a l ( dfun , xkp1 ) ) ;
xk=xkp1 ;
scartok=scartokp1 ;
end
i f ( i t e r >itmax )
disp ( raggiunto il numero massimo di iterazioni )
end
end

Con questa function implementiamo il metodo del punto fisso e conosciamo lapprossimazione finale del
punto fisso, il numero di iterazioni effettuate, lo scarto finale, una stima della costante asintotica. Con questa
function, tuttavia, non possiamo fare nessun grafico di convergenza perch perdiamo tutte le informazioni
intermedie (i valori delle approssimazioni, degli scarti, etc, ad ogni iterazione). In effetti, per alcune variabili
possiamo farci stampare su un file il loro valore in modo da sapere cosa successo ad ogni passo di iterazione.
Per altre, invece, utile metterle in un grafico.
Esaminiamo ciascuna variabile:
i valori x0,xk,xkp1 rappresentano i valori dellapprossimazione iniziale al passo 0, al passo precedente iter e al nuovo passo di iterazione iter+1. Questi valori ci servono per calcolare lo scarto ad
ogni iterazione e per approssimare il fattore di convergenza tramite la variabile asint2. Potremmo solo stampare questi valori ad ogni passo oppure salvarceli in un vettore (e calcolare la variabile asint2

28

1.9. Strutture e cicli

come vettore applicando il valore assoluto della derivata della funzione di punto fisso al vettore delle
approssimazioni).
gli scarti scartok e scartokp1 servono per calcolare asint1 ma soprattutto se vogliamo fare un
grafico di convergenza! Quindi ci servono i valori degli scarti ad ogni iterazione. Possiamo creare
un vettore in cui la componente i -sima corrisponde allo scarto al passo i . In tal modo potremo sia
calcolare asint1 in modo vettoriale, sia fare un grafico semilogaritmico di convergenza.
la variabile iter un contatore scalare. Quando occorre, creeremo il vettore che ha come componenti
gli interi 1, 2, . . . , i t er dove i t er rappresenter il numero finale delle iterazioni effettuate.
Modifichiamo quindi la function lavorando su vettori (la possibilit di scrivere alcuni risultati su file la
lasciamo per il seguito). Scriviamo il seguente file pfisso.m.

function [ x , i t e r , scarto , asint1 , asint2 ]= p f i s s o ( fun , dfun , x0 , t o l l , itmax )


%function [ x , i t e r , scarto , asint1 , asint2 ]= p f i s s o ( fun , dfun , x0 , t o l l , itmax )
% significato delle variabili
%
i t e r : i t e r a z i o n e del metodo del punto f i s s o
%
itmax : numero massimo di i t e r a z i o n i
%
t o l l : t o l l e r a n z a p r e f i s s a t a per l approssimazione del punto f i s s o
%
x0 : punto i n i z i a l e d e l l a s u c c e s s i o n e
%
x:
v e t t o r e d e l l e approssimazioni del punto f i s s o
%
scarto : vettore degli scarti
%
asint1 : v e t t o r e che approssimazione i l f a t t o r e di convergenza M usando
%
i l vettore degli scarti
%
asint2 : v e t t o r e che approssima i l f a t t o r e di convergenza M usando
%
i l valore a s s o l u t o d e l l a derivata prima d e l l a funzione di punto
%
fisso
%
fun : funzione di cui s i vuole c a l c o l a r e un approssimazione del punto f i s s o
%
dfun : derivata d e l l a funzione fun
%
Esempio
%
x0 = 0 . 1 ; t o l l =1. e 12; itmax =100;
%
dfun= i n l i n e ( sin ( x ) ) ;
%
[ x , i t e r , scarto , asint1 , asint2 ]= p f i s s o ( @cos , dfun , x0 , t o l l , itmax )
%
restituisce
%
i l v e t t o r e x di lunghezza 70
%
i t e r =70
%
i l vettore scarto
%
i l v e t t o r e asint1
%
i l v e t t o r e asint2
%
per f a r e i l g r a f i c o di convergenza semilogaritmico basta s c r i v e r e
%
semilogy ( [ 1 : 1 : i t e r ] , s c a r t o )
scarto =2 * t o l l ;
iter = 1;
x=x0 ;
while ( scarto ( i t e r )>= t o l l )&& ( i t e r <=itmax )
i t e r = i t e r +1;
x ( i t e r )= f e v a l ( fun , x ( i t e r 1 ) ) ;
scarto ( i t e r )= abs ( x ( i t e r ) x ( i t e r 1 ) ) ;
end
a s i n t 1 = scarto ( 2 : i t e r ) . / scarto ( 1 : i t e r 1);
a s i n t 2 =abs ( f e v a l ( dfun , x ) ) ;
scarto =scarto ( 2 : i t e r ) ; % togliamo dal v e t t o r e s c a r t o la prima componente
% 2 * t o l l che s e r v i v a s o l o per entrare nel c i c l o
% while
i t e r = i t e r 1; % togliamo dal conto d e l l e i t e r a z i o n i l i t e r a z i o n e 0
i f ( i t e r >itmax )
disp ( raggiunto il numero massimo di iterazioni )
end

29

1. I NTRODUZIONE

end

Osserviamo in che modo abbiamo creato i due vettori asint1 e asint2.


sc ar t o i
Per il vettore asint1 la generica componente i -sima deve essere uguale a
. Supponiamo
sc ar t o i 1
che il vettore scarto abbia queste componenti: scarto=[ 2 0.90 0.45 0.31 0.20 0.14] dove scarto(1) corrisponde al valore che si ha alliterazione 0 (il valore che, nella function, abbiamo posto
uguale a 2*tol in modo da poter entrare nel ciclo while). Per approssimare il fattore di convergenza al primo passo di iterazione dobbiamo fare il rapporto tra lo scarto alliterazione 1 e lo scarto alliterazione 0, cio
0.90
. Alla seconda iterazione dobbiamo fare il rapporto tra lo scarto corrente e lo scarto al passo precedente,
2
0.45
e cos via. Nel vettore scarto abbiamo 6 componenti, la prima corrisponde alliterazione 0, ci vuol
cio
0.90
dire che sono state effettuate 5 iterazioni. Dobbiamo fare dunque 5 rapporti per approssimare il fattore di
convergenza ad ogni iterazione:
0.90
,
2

0.45
,
0.90

0.31
,
0.45

0.20
,
0.31

0.14
.
0.20

A tal fine costruiamo il vettore (a cui ora per comodit diamo il nome sc1) che ha come componenti quelle del vettore scarto dalla seconda componente in poi, cio sc1=[0.90 0.45 0.31 0.20
0.14]. Costruiamo poi il vettore (che chiamiamo sc2) che ha come componenti quelle del vettore scarto
dalla prima alla penultima componente, vale a dire sc2=[2 0.90 0.45 0.31 0.20]. Ora, se disc1
componente per componente, abbiamo proprio i rapporti che abbiamo scritvidiamo i due vettori
sc2
to prima. Questa operazione si pu fare senza dover introdurre nuovi vettori. Possiamo scrivere, infatti,
asint1= scarto(2:iter )./ scarto(1:iter1);

Per quanto riguarda asint2, abbiamo semplicemente valutato la funzione dfun nel vettore delle
approssimazioni x.
Poi, poich la prima componente che abbiamo dato al vettore scarto non ci interessa, la togliamo
andando ad aggiornare il vettore scarto=scarto(2:iter);
Questa istruzione ci permette di prendere il vettore che ha come componenti quelle del vettore scarto
dalla seconda componente in poi e di chiamare questo vettore di nuovo con la stessa variabile.
Infine, aggiorniamo il numero delle iterazioni, togliendo ununit perch eravamo partiti dal contatore
delle iterazioni pari a uno in corrispondenza delliterazione 0.
A questo punto, in uscita abbiamo dei vettori.
Per fare il grafico di convergenza dello schema, ci serve fare un grafico semilogaritmico dove, sullasse delle ascisse ci sono le iterazioni effettuate e sullasse delle ordinate i logaritmi (in base 10) degli scarti. La function di MATLAB che ci permette di fare grafici in scala semilogaritmica sullasse delle ordinate
prende il nome di semilogy. Nel nostro caso, basta creare il vettore delle ordinate, che deve avere i valori
1, 2, 3, . . . , i t er e applicare questa function. Per creare un vettore che parte dal valore 1 e arriva al valore iter
con passo unitario, basta scrivere it =[1:1: iter ];
Perci possiamo usare il comando
semilogy(it, scarto),
oppure, in modo equivalente,
semilogy([1:1:iter], scarto) (si veda figura 1.6).
Introduzione alla grafica
Abbiamo visto le function ezplot, fplot, semilogy. Vediamo ora le altre function di base per
poter fare un grafico. Abbiamo semilogx (analogo di semilogy, il grafico semilogaritmico sullasse
delle ascisse), loglog (il grafico in scala logaritmica su entrambi gli assi) e infine plot.
Le function plot, semilogx, semiloy e loglog hanno le stesse caratteristiche. Vediamo quindi
gli elementi principali di come si usa la function plot. In maniera analoga si usano le altre function che
abbiamo detto.
plot(x,y) dove x e y sono dei vettori della stessa dimensione, produce il grafico in cui sullasse delle ascisse
c il vettore x e sullasse delle ordinate il vettore y.
Esempio:

30

1.9. Strutture e cicli

Figura 1.6: Grafico generato dallistruzione semilogy(it, scarto). per lo schema di punto fisso applicato alla
funzione di punto fisso g (x) = cos (x), con x 0 = 0.1.

>> x=[0, 0.1 , 0.2, 0.3, 0.4, 0.5];


>> y=sin(x);
>> plot(x,y)

I comandi precedenti producono il grafico di figura 1.7


Si pu anche usare semplicemente listruzione plot(y) che produce il grafico del vettore in funzione degli
indici delle componenti del vettore (quindi sullasse delle ascisse ci saranno gli indici 1, 2, . . . , n del vettore y
mentre sullasse delle ordinate le componenti del vettore y di lunghezza n).
Si possono fare pi grafici sovrapposti in diversi modi. Uno di questi di avere pi coppie di vettori x1,y1, x2, y2 e cos via e scrivere listruzione plot(x1,y1,x2,y2, ...) Un altro modo di sovrascrivere i grafici luno sullaltro mediante il comando hold on Abbinato poi il comando hold off che chiude il
processo.
Vediamo degli esempi
>>
>>
>>
>>
>>

x1=[0, 0.1 , 0.2, 0.3, 0.4, 0.5];


y1=sin(x1);
x2=[-0.5, -0.2 0.2 0.5];
y2=cos(x2);
plot(x1,y1,x2,y2)

Si faccia poi
>>
>>
>>
>>

plot(x1,y1) % il grafico precedente non ce piu ma si crea questo


hold on
plot(x2,y2)
hold off

Per esercizio si provino i comandi precedenti. La figura generata nel primo caso mostra le due curve di
colore diverso, mentre nel secondo caso le curve hanno lo stesso colore.
31

1. I NTRODUZIONE

Figura 1.7:

Esempio di uso della function plot con x=[0, 0.1 , 0.2, 0.3, 0.4, 0.5] e

y=sin(x).

Per cambiare colore e tipo di linea della curva, oppure fare un grafico per punti, si possono fare le modifiche direttamente dal menu che si presenta sulla finestra del grafico oppure tramite comandi in linea.
Vediamo questi ultimi (comuni ad Octave).
Listruzione plot(x1,y1,s1,x2,y2,s2, ...) dove s1, s2, ... sono delle stringhe di caratteri (da scrivere
tra apici, quindi) permette di cambiare colore, linea o punto della curva.
Esempi: plot(x,y, g:) produce il grafico in cui la curva di colore verde (green) e la curva a puntini.
plot(x,y, r-.) d come risultato una curva di colore rosso con linea fatta a tratteggio del tipo -.-.-..
plot(x,y, yo) produce una curva dove i punti non sono legati tra loro mediante una linea ma per punti,
ciascuno dei quali ha la forma di un cerchietto (o) mentre il colore giallo (yellow)
plot(x,y, c--*) combina la linea di tipo tratteggio con i punti a forma di asterisco * mentre il colore il
celeste (cyan). Per vedere tutti i colori, punti e linee a disposizione basta fare help plot dalla Command
Window.
Altri comandi utili sono
inserire un titolo al grafico, mediante la function title.
Esempio: title ( grafico di prova)
inserire una descrizione sullasse delle x (e delle y) mediante la function xlabel (ylabel).
Esempio: xlabel(iterazioni), ylabel(scarti);
Inserire una legenda mediante la function legend.
Esempio: abbiamo fatto un grafico con listruzione plot(x,y1,x,y2) dove y1 corrisponde ad
una certa funzione f mentre y2 corrisponde ad una certa funzione g .
Con listruzione
legend(funz f, funz g) sul grafico compare la legenda che abbiamo scritto unita al tipo di linea
o punti associati a quel vettore.
inserire una griglia di fondo al grafico o toglierla, mediante il comando grid
Esempio: grid on introduce linee di griglia; grid off le toglie.
Per ciaascuno di queste function fare delle prove e controllare lhelp in linea.
Negli esempi fatti, tuttavia, abbiamo creato dei vettori di lunghezza molto ridotta. Se avevamo in mente
di fare il grafico della funzione sin (x) o cos (x), il risultato che abbiamo avuto stato molto povero perch

G
G
G

32

1.9. Strutture e cicli

avevamo pochi punti a disposizione. Potevamo certamente usare le function ezplot o fplot per questo
scopo, ma poich stiamo imparando ad usare MATLAB ci conviene prendere spunto da questa occasione
per imparare qualcosa in pi sui vettori.
Nel fare il grafico semilogaritmico, abbiamo visto un modo per creare un vettore, mediante listruzione
[1:1: iter ] .
Listruzione x=[x0: incr: xf] produce un vettore che ha come valore iniziale x0 e come valore finale xf
e le altre componenti sono date a partire da x0 con incremento dato dal valore incr: x0, x0+incr,
x0+2incr, ...., xf. Con questa istruzione possiamo creare dei vettori che hanno molte componenti
senza doverle scrivere a mano. Per vedere la lunghezza del vettore, basta scrivere il comando size(x) (che
pu essere applicato anche a matrici) : restituisce il numero di righe e di colonne della variabile x. Si pu
anche usare listruzione length(x) che restituisce, invece, la lunghezza del vettore.
>> x=[0:0.1:1]
x =
Columns 1 through 6
0

0.1000

0.2000

0.3000

0.4000

0.5000

Columns 7 through 11
0.6000

0.7000

0.8000

0.9000

1.0000

>> size(x)
ans =
1

11

>> length(x)
ans =
11

Un altro modo di creare vettori dato dalla function linspace, il cui uso il seguente: x=linspace(a,b);
crea, di default, un vettore (in questo caso x) che ha 100 componenti,con valori equidistanti a partire da a
per finire a b: quindi il vettore ha come prima componente a, poi a + (b-a)/99, ..., fino ad arrivare alla
centesima componente che vale b. Si applica la formula x i = x 1 + (i 1)h, per i = 2, 3, . . . , 100 , dove x 1 = a e
ba
(in tal modo: x 2 = x 1 + h; x 3 = x 1 + 2h = x 2 + h, fino ad arrivare a x 100 = x 1 + 99h = a + (b a) = b.
h=
99
Se vogliamo un vettore con un certo numero n di punti equidistanti tra a e b, si scrive listruzione
x=linspace(a,b,n);

A questo punto, vediamo anche un altro modo per creare dei vettori, utilizzando un ciclo che non
abbiamo visto fino ad ora, e che prende il nome di ciclo for.

1.9.3 Ciclo for


Il ciclo for strutturato nel modo seguente

33

1. I NTRODUZIONE

Ciclo for
for

ind= v a l i n i z : i ncr : v a l f i n
{ istruzioni }
end

Un esempio di ciclo for per creare un vettore di 11 elementi con componenti equidistanti tra 0 e 1 pu
essere il seguente
x (1)=0;
for i =2:11
x ( i )= x ( i 1)+0.1;
end

Osserviamo che usare un ciclo for per creare vettori non conveniente n ottimale. Questo non vuol dire
che non lo useremo mai e che possiamo dimenticarci che esiste! Dobbiamo solo prestare molta attenzione
quando lo usiamo e usarlo solo quando effettivamente serve!!!!
Vediamo un esempio, in cui misuriamo il tempo che impiega MATLAB per creare un vettore di lunghezza n con n grande, usando la forma compatta x=[x0:incr:xn], la function linspace e il ciclo
for.
Per misurare il tempo che impiega ciascuno procedimento, applichiamo due functions di MATLAB tic
e toc che sono da usare combinate insieme perch permettono di misurare il tempo per effettuare le
istruzioni che si trovano nel mezzo.
Scriviamo uno script allo scopo di creare un vettore x di lunghezza n=100001 tra a=0 e a=1 applicando
1
= 105 .
i diversi approcci che abbiamo visto. La distanza tra due componenti del vettore data da h =
100000
clear
tic
x =[0:1. e 5:1];
toc
disp ( lunghezza vettore )
disp ( length ( x ) )
clear x
tic
x=linspace ( 0 , 1 , 1 0 0 0 0 1 ) ;
toc
disp ( lunghezza vettore )
disp ( length ( x ) )
clear x
tic
x (1)=0;
for i =2:100001
x ( i )= x ( i 1)+1.e5;
end
toc
disp ( lunghezza vettore )
disp ( length ( x ) )

Eseguiamo questo script (salviamolo prima dandogli un nome con lestesione .m, in questo caso
confrontotictoc.m). In MATLAB otteniamo
>> confrontotictoc
Elapsed time is 0.000631 seconds.
lunghezza vettore
100001

34

1.9. Strutture e cicli

Elapsed time is 0.003618 seconds.


lunghezza vettore
100001
Elapsed time is 0.058935 seconds.
lunghezza vettore
100001

Vediamo cosa succede in ambiente Octave:


octave:3> confrontotictoc
Elapsed time is 2.90871e-05 seconds.
lunghezza vettore
100001
Elapsed time is 0.001910925 seconds.
lunghezza vettore
100001
Elapsed time is 1.404992 seconds.
lunghezza vettore
100001

Come possiamo osservare dai risultati, il primo approccio per scrivere i vettori quello che va
decisamente meglio.

1.9.4 Introduzione a file di scrittura dati


Riprendiamo a studiare lo schema di punto fisso e i risultati ottenuti. Immaginiamo di volerli stampare
su un file per poterli studiare ed esaminare con calma. La function pfisso ci ha dato dei vettori, noi abbiamo fatto il grafico di convergenza. Ora vogliamo salvare, per ogni iterazione, i valori delle approssimazioni,
degli scarti e delle stime asint1 e asint2 inserendoli in una tabella con una riga di intestazione in cui
scriviamo il significato della colonna corrispondente. Vediamo un modo compatto per fare tutto ci. Creiamo una matrice in cui ciascuna riga corrisponde a ci che vogliamo mettere in tabella: la prima riga avr le
iterazioni fatte, la seconda i valori approssimati, la terza gli scarti, la quarta le stime asint1 e la quinta le
stime asint2. La matrice deve avere lo stesso numero di colonne, quindi dobbiamo stare attenti al fatto che
alcuni vettori hanno come prima componente un valore che corrisponde alliterazione 0.
Per scrivere su un file di testo, dobbiamo aprire da MATLAB un file e dare ad esso un nome: ci viene
fatto con la function fopen: questa function ha come parametri il nome del file su cui andremo a scrivere
i dati, scritto tra apici, e aggiungeremo poi dei permessi (ad esempio r per file di sola lettura, w per file di
scrittura,... si faccia help fopen). Loutput della function una variabile scalare di tipo intero, a cui diamo
nome fid (file identifier). Questa variabile sar usata come identificatore del file su cui dobbiamo andare
a scrivere mediante la function fprintf. Una volta che si scritto, si chiude il file mediante la function
fclose, scrivendo semplicemnte fclose(fid).
La function fprintf permette di scrivere su un file utilizzando un certo formato. Ci che diciamo adesso
serve in maniera analoga per la function sprintf che permette di scrivere con un certo tipo di formato sulla
Command Window.
I dati di input di fprintf sono la variabile fid, alcune istruzioni che riguardano il formato, da scrivere
tra apici, e una o pi matrici. Se, si pone fid=1 loutput sar lo schermo della Command Window. Quindi
listruzione da dare fprintf(fid, formato, A, B, ...) con A,B matrici o array (un array pu
essere un vettore o una matrice fatta di numeri o di stringhe di caratteri). Bisogna prestare attenzione al fatto
che la scrittura avviene colonna per colonna, (vengono letti gli elementi della prima colonna, poi gli elementi
della seconda colonna, ...).
Il formato una stringa di caratteri da scrivere tra apici che possono avere diversi significati: c il formato
associato al tipo di rappresentazione della variabile (se in formato esponenziale, fisso, di tipo intero, di stringa

35

1. I NTRODUZIONE

di caratteri...) che si scrive nella forma %e (formato esponenziale) o %12.6e (formato esponenziale cui sono
riservati 12 spazi di cui 6 per la mantissa)...; ci sono i caratteri che hanno il significato di riga bianca, andare
a capo, ... che sono preceduti dal simbolo \ ( \n, nuova linea, \r andare a capo,...); ci possono essere stringhe
di caratteri. In tabella vediamo i principali simboli che ci interessano.
formato
%s
%d
%f
%e
%E
%g
\n
\r
\\

Significato
stringhe di caratteri
formato intero
formato decimale in virgola fissa
formato esponenziale (del tipo 3.5e + 00)
formato esponenziale (del tipo 3.5E + 00)
formato che una via di mezzo tra %f e %e senza gli zeri che non servono
nuova linea (il risultato come schiacciare il tasto di invio)
per andare a capo
\

Il significato associato a \ n molto importante, perch permette di andare a capo ogni volta che stata
letta una riga, altrimenti viene scritta solo una riga sul file, lunghissima a seconda del contenuto da scrivere!
Al formato che specifica il valore di una variabile numerica pu essere aggiunto il numero dei caratteri da
utilizzare per rappresentare la variabile: oltre allesempio visto prima %12.6e, possiamo vedere %10d : sono
riservati 10 caratteri ad una variabile di tipo intero.
Vediamo degli esempi per capire meglio. Scriviamo ed eseguiamo i seguenti script.
f i d =fopen ( fileprova.txt , w )
x =10.5;
f p r i n t f ( f i d , Ho scritto questo numero %f , x ) ;
s p r i n t f ( Ho scritto questo numero %f , x )
fclose ( fid ) ;

Se eseguiamo questo script, sulla Command Window, compare quanto richiesto dalla function sprintf,
cio Ho scritto questo numero 10.500000 (associato ad una variabile ans) mentre nella directory in cui stiamo lavorando in MATLAB , troveremo il file fileprova.txt. Se lo apriamo con un editor
di testo troveremo Ho scritto questo numero 10.500000.
Proviamo a voler stampare pi elementi sulla stessa riga. Introduciamo un vettore.
f i d =fopen ( fileprova.txt , w )
a =12;
b=2;
c=a * b ;
f p r i n t f ( f i d , il prodotto di %g per %g da %g \n , [ a b c ] ) ;
fclose ( fid )

Questa volta sul file fileprova.txt troviamo (al posto della frase precedente, abbiamo sovrascritto!), la
riga il prodotto di 12 per 2 da 24.
Consideriamo ora sia un vettore sia una stringa di caratteri. Questa volta usiamo la function sprintf.
s t r i n g a =numeri reali ;
v e t t o r e = [ 1 . 1 1.2 1.3 1 . 4 ] ;
s p r i n t f ( %2g %2g %2g e %2g sono %s \n ,

vettore , s t r i n g a )

Otteniamo: 0.1 0.2 0.3 e 0.4 sono reali.


Se vogliamo visualizzare una matrice, dobbiamo tener conto del fatto che la lettura viene fatta sugli elementi di ogni colonna e, se andiamo a capo, questi elementi vengono disposti su riga. Perci, se vogliamo
visualizzare la matrice in modo corretto dobbiamo lavorare sulla sua trasposta e scrivere il formato per ciascun elemento di colonna della trasposta (o di riga della matrice di partenza). Vediamo con degli esempi
(il primo uso di sprintf non corretto perch non abbiamo la matrice A che scriviamo, nel secondo caso il
risultato quello giusto).
36

1.9. Strutture e cicli

>> A=[1 2 3; 4 5 6; 7 8 9]
A =
1
4
7

2
5
8

3
6
9

>> sprintf( %g %g %g \n, A)


ans =
1 4 7
2 5 8
3 6 9

>> sprintf( %g %g %g \n, A)


ans =
1 2 3
4 5 6
7 8 9

Vediamo cosa succede con matrici rettangolari.


>> A=[ 1 2 3 4; 5 6 7 8; 9 10 11 12]
A =
1
5
9

2
6
10

3
7
11

4
8
12

>> sprintf( %2d %2d %2d

%2d \n, A)

ans =
1 2 3
5 6 7
9 10 11

4
8
12

In questo caso, dobbiamo visualizzare quattro elementi per riga, e difatti abbiamo scritto quattro formati
(%2d). Se proviamo a scrivere togliendo delle informazioni sul formato o applicando la function alla matrice
A e non alla sua trasposta, abbiamo risultati scorretti.
>> sprintf( %2d %2d %2d

%2d \n, A)

ans =
1 5 9
6 10 3
11 4 8

2
7
12

37

1. I NTRODUZIONE

>> sprintf( %2d %2d %2d

\n, A)

ans =
1
2
3
4

5 9
6 10
7 11
8 12

>> sprintf( %2d %2d %2d

\n, A)

ans =
1
4
7
10

2
5
8
11

3
6
9
12

Provare a fare altri esempi.


Torniamo allora alla visualizzazione dei risultati dello schema di punto fisso. Ci interessano i dati dalla
prima allultima iterazione, ma alcuni vettori hanno anche delle informazioni sulliterazione zero. Inoltre,
siccome noi vogliamo scrivere una tabellina, dove ciascuna colonna ha il significato di iterazioni, approssimazioni, scarto, etc.... conviene scrivere ciascuno di questi vettori come righe della matrice in modo che poi,
senza fare la trasposta, la function fprintf ci mette quelle righe in colonna facendo la trasposta. In tal modo dobbiamo scrivere il formato solo per il generico elemento di ciascuno vettore e non per tutti gli elementi
dei vettori (5 formati e non in numero che corrisponde al numero delle iterazioni).
Lo script da eseguire dopo la function pfisso il seguente (che abbiamo chiamato salvadati.m. Lo
script tiene conto che i vettori in uscita dalla pfisso sono dei vettori riga.
f i d =fopen ( rispfisso.txt , w ) ;
f p r i n t f ( f i d , %5s %12s %12s %12s %12s \n , iter , x , scarto , asint1 , asint2 )
f p r i n t f ( f i d , \n%5d %12.8e , [0 x ( 1 ) ] ) ; %stampiamo i l valore i n i z i a l e x0
i t = [ 1 : 1 : i t e r ] ; %creo i l v e t t o r e d e l l e i t e r a z i o n i
A=[ i t ; x ( 2 : length ( x ) ) ; scarto ; asi nt1 ; asi nt2 ( 2 : length ( asi nt2 ) ) ] ;
% la prima r i g a e data dal v e t t o r e i t
% la seconda r i g a da x , . . .
% non consideriamo la prima componente dei
% v e t t o r e x e asint2 che corrispondono a x0
f p r i n t f ( f i d , \n%5d %12.8e %12.8e %12.8e %12.8e , A ) ; %stampa la matrice A
% in modo t r a s p o s t o
fclose ( fid ) ;

Applichiamo questo script una volta eseguita la function pfisso per approssimare il punto fisso della funzione g (x) = cos (x) partendo da x 0 = 0.1 con una tolleranza t ol = 1.e 10. Viene generato il file
rispfisso.txt. Vediamo come fatto (togliendo diverse righe centrali in modo da vedere linizio e la
fine).
iter
0
1
2
3
4
5
6

38

x
1.00000000e-01
9.95004165e-01
5.44499396e-01
8.55386706e-01
6.55926664e-01
7.92483102e-01
7.02079268e-01

scarto

8.95004165e-01
4.50504769e-01
3.10887310e-01
1.99460042e-01
1.36556438e-01
9.04038340e-02

asint1

4.47502083e+09
5.03354942e-01
6.90086612e-01
6.41583094e-01
6.84630549e-01
6.62025424e-01

asint2

8.38761234e-01
5.17989945e-01
7.54824623e-01
6.09893870e-01
7.12098800e-01
6.45806605e-01

1.9. Strutture e cicli

7 7.63501034e-01 6.14217657e-02 6.79415496e-01 6.91454893e-01


8 7.22419636e-01 4.10813975e-02 6.68841037e-01 6.61201836e-01
.............................................................
53
54
55
56
57
58
59

7.39085134e-01
7.39085133e-01
7.39085133e-01
7.39085133e-01
7.39085133e-01
7.39085133e-01
7.39085133e-01

7.81694154e-10
5.26558575e-10
3.54696161e-10
2.38927544e-10
1.60944480e-10
1.08414167e-10
7.30291383e-11

6.73612013e-01
6.73612016e-01
6.73611975e-01
6.73611870e-01
6.73612079e-01
6.73612208e-01
6.73612505e-01

6.73612029e-01
6.73612029e-01
6.73612029e-01
6.73612029e-01
6.73612029e-01
6.73612029e-01
6.73612029e-01

Attenzione! Osserviamo ancora due elementi sulle function di punto fisso che abbiamo scritto.
Nella function pfisso abbiamo operato con dei vettori. Il primo elemento del vettore x e del
vettore scarto li abbiamo assegnati con listruzione x=x0; scarto=2*toll; Avremmo potuto anche scrivere x(1)=x0; scarto(1)=2*toll; Nel primo caso ( x=x0;) come se partissimo da una variabile scalare e poi dicessimo creiamo un vettore, anche se in realt sappiamo che creeremo un
vettore e che quella la prima componente. Nel secondo caso diciamo in maniera esplicita che
stiamo creando un vettore e che quella la prima componente.
Le function di punto fisso che abbiamo scritto sono pensate per il caso generale di schema con
ordine di convergenza p = 1 (convergenza lineare). Se lo schema di punto fisso ha ordine di
convergenza maggiore, le stime delle costanti asintotiche non vanno pi bene (che risultati ci
daranno?). Dagli scarti, tuttavia, e dal grafico di convergenza otteniamo informazioni utili per la
convergenza.

Esercizio 1.9.3 Applicare lo schema di punto fisso alle seguenti funzioni g (x). Per ciascun caso, fare un
grafico di convergenza semilogaritmico e stampare i risultati in un file. Dai risultati capire se c convergenza lineare oppure no. In caso contrario, cosa si pu fare per stabilire lordine di convergenza? (1) si
possono considerare le derivate successive della g e valutarle nellapprossimazione di punto fisso ricavata
allultima approssimazione quali derivate e quando mi posso fermare in questo procedimento?; (2) si fac|x k+1 x k |
cia il rapporto tra gli scarti tra due iterazioni successive
con p > 1 (cosa si deve osservare per
|x k x k1 |p
dire che un certo p lordine di convergenza?).
Ai fini dellimplementazione, ricordarsi di scrivere le function, in particolare la derivata prima, in forma
vettorizzata per poterle valutare su vettori quindi . .*
./
3x + 2
g (x) =
, x 0 = 0.5, t ol l = 1.e 12, i t max = 100.
2x + 3
g (x) = ln (3 x 2 ), x 0 = 0.1, t ol l = 1.e 12, i t max = 100.
x2 + 4
g (x) =
, x 0 = 0.5, t ol l = 1.e 12, i t max = 100.
2x

G
G
G

1.9.5 Modificare le function di punto fisso per creare nuove function


Le function di punto fisso che abbiamo scritto possono essere usate come base per creare function in cui
applichiamo altri metodi iterativi, come quello di Newton-Raphson e della secante variabile.

39

1. I NTRODUZIONE

Quali saranno le differenze? Per lo schema di Newton-Raphson,


x k+1 = x k

f (x k )
f 0 (x k )

abbiamo bisogno non solo della funzione f ma anche della sua derivata prima f 0 . Inoltre, per stimare la
costante asintotica di convergenza, nel caso generale di convergenza quadratica, dobbiamo ricordarci che
d k+1
abbiamo due modi possibili da usare, il rapporto tra gli scarti
(dove d k+1 = |x k+1 x k |), e il rapporto
d k2
f 00 (x k+1 )
|.
| 0
2 f (x k+1 )
Quindi, tra le variabili di input della function, dovremo inserire non solo la funzione f ma anche le sue
derivate prima e seconda.
Il resto dello schema sar simile a quello visto per il punto fisso. Al posto della formula iterativa dello schema di punto fisso, metteremo la formula iterativa dello schema di Newton-Raphson. Al posto delle formule
usate per le variabili asint1 e asint2 useremo le analoghe formule dello schema di Newton-Raphson.
Perci, modificare le function pfisso0.m e pfisso.m per creare le newton0.m e newton.m non
comporta chiss quali difficolt.
Maggiore attenzione invece bisogna prestare per creare le function sul metodo della secante variabile.
Infatti, oltre alla f , f 0 e f 00 , ( f 0 e f 00 servono per stimare la costante asintotica) sappiamo che lo schema parte
da due approssimazioni iniziali, x 0 e x 1 , quindi tra le variabili di input bisogna aggiungere anche x 1 .
Lo schema della secante variabile e le stime della costante asintotica sono date mediante le formule
x k+1 = x k

f (x k )(x k x k1 )
f (x k ) f (x k1 )

d k+1
d k1.618
|

f 00 (x k+1 0.618
|
2 f 0 (x k+1 )

Nello schema da implementare, la difficolt non si ha nelle formule per asint1 e asint2 quanto nel
lavorare usando le approssimazioni x k e x k1 e aggiornarle nel modo corretto, quando si implementa la
formula lavorando con variabili scalari (quindi nella function rfalsi0.m).
Partiamo da due variabili x 0 e x 1 : al primo passo queste due variabili saranno per noi xkm e xk (lapprossimazione x k1 e x k rispettivamente). La variabile iter non parte dal valore 0 ma da 1 avendo anche
lapprossimazione x 1 . Alla variabile scartokp1 possiamo dare il valore giusto dello scarto (abs(x1-x0))
mentre il valore da dare alla variabile scartok sar, la prima volta, un valore fittizio (diverso da zero) che
serve per calcolare asint1 al primo passo.
Quando dobbiamo applicare la formula del metodo, per semplificare le cose, conviene introdurre una
variabile di appoggio, che possiamo chiamare c, cui assegniamo il valore del rapporto incrementale
c= ( f e v a l ( fun , xk) f e v a l ( fun , xkm ) ) / ( xkxkm ) ;
xkp1= xk f e v a l ( fun , xk ) / c ;

Una volta valutato il nuovo scarto scartokp1, e fatta una stima della costante asintotica mediante
asint1 e asint2, bisogna aggiornare le variabili da utilizzare al passo successivo.
Qui bisogna fare attenzione:
Iterazione x k1 x k
x k+1
1
x0
x1
2
x0
x1 xkp=x 2
3
x1
x2
xkp=x 3
4
x2
x3
xkp=x 4
..
..
..
..
.
.
.
.
Quando dobbiamo passare dalliterazione 2 alliterazione 3, x1 non dovr pi avere il significato di x k
ma quello di x k1 , mentre il valore che abbiamo appena ottenuto xkp=x 2 dovr passare al significato di x k .
40

1.9. Strutture e cicli

Laggiornamento delle variabili deve essere fatto sapendo quello che si fa, altrimenti c il rischio di perdere il
contenuto di alcune variabili.
Le istruzioni da fare per laggiornamento quali sono?
xk=xkm ;
xk=xkp1 ;

oppure
xkm=xk ;
xk=xkp1 ;

oppure
xk=xkp1 ;
xkm=xk ;

oppure .... ?
Immaginiamo di avere tre variabili, a, b e c dove a = 1, b = 2 e c = 3. Vogliamo poi che sia a = 2e b = 3:
come facciamo lavorando sulle variabili? Questo quello che dobbiamo fare nella function rfalsi0.m.
Osserviamo che in queste function in versione 0, la stima delle costanti asintotiche viene sempre sovrascritta e i valori intermedi vengono persi. Avrebbe pi senso scriverli su un file di dati, in modo da non perderli, oppure valutarli solo alla fine. Tuttavia, poich useremo quasi sempre le function con limplementazione
fatta con vettori, trascuriamo questo particolare.
Nella function rfalsi.m, invece, limplementazione del metodo molto pi semplice, perch partiamo
ponendo x(1)=x0 e x(2)=x1 e appplicheremo la formula considerando i vettori. Qui il contatore delle
iterazioni, partir da iter=2, in modo da avere concordanza con i vettori che creiamo. Alla fine, torneremo al
vettore degli scarti che parte dalliterazione corrispondente a x 1 , e toglieremo al contatore ununit (quello
che stato fatto anche con lo schema di punto fisso) in modo da avere vettori con lo stesso significato rispetto
a quanto fatto con lo schema di punto fisso e di Newton-Raphson.
Una volta scritte queste function possiamo confrontare i metodi di Newton-Raphson e della secante variabile, facendo ad esempio un grafico di convergenza semilogaritmico (ovviamente sulla stessa equazione
f (x) = 0). Conviene, a tal fine, eseguire le due function dando nomi diversi per le variabili di output e in
particolare per la variabile delle iterazioni e quella del vettore scarto. Supponiamo di chiamare con itnr e
scartonr le variabili corrispondenti a iter e scarto rispettivamente nello schema di Newton-Raphson,
mentre chiamiamo con itrf e scartorf quelle relative allo schema della secante variabile.
Possiamo fare il grafico semilogaritmico in questo modo.
semilogy ( [ 1 : 1 : i t n r ] , scartonr , [ 1 : 1 : i t r f ] , s c a r t o r f )
legend ( Newton-Raphson , Regula Falsi )
xlabel ( iterazioni )
ylabel ( scarti )
t i t l e ( Grafico di convergenza )
print djpeg g r a f i c o . jpg

Allinterno dellistruzione per fare il grafico semilogaritmico abbiamo creato i vettori [1:1:itnr] e
[1:1:itrf]. La function legend permette di distinguere le due curve (a quale metodo si riferiscono);
poi ci sono le etichette sui due assi e un titolo. Infine abbiamo usato un comando che permette direttamente
di salvare in formato .jpg la figura creata utilizzando la function print dopo abbiamo scritto -d seguito da
jpg per specificare il tipo di file e infine il nome del file che vogliamo creare. Questultimo comando molto
utile in Octave oppure se vogliamo salvare delle figure tramite uno script o dalla Command Window.
Supponiamo di voler fare diverse figure e di volerle vedere contemporaneamente senza sovrascriverle. Un
modo per risolvere questo problema di creare pi figure attraverso la function figure. Capiamo con un
esempio a cosa serve:
figure ( 1 )
ezplot ( @cos , [ 0 , 2 ] )
x =0:0.1:2;
y=cos ( x ) ;

41

1. I NTRODUZIONE

figure ( 2 )
plot ( x , y )

Se vogliamo salvare le due figure dalla Command Window (o da uno script) si riattiva la figura da salvare
mediante la function figure e si salva la figura.
figure ( 1 )
print djpeg f i g 1 . jpg
figure ( 2 )
print djpeg f i g 2 . jpg

42

C APITOLO

Su interpolazione e approssimazione
Lo scienziato descrive ci che esiste,
lingegnere crea ci che non era mai
stato.
Theodore von Krmn (1881-1963)

2.1
2.2
2.3

Interpolazione monomiale e con i polinomi di Lagrange . . . . . . . . . . . . . . . . . . . . . . . . 44


Interpolazione con la tabella delle differenze divise di Newton . . . . . . . . . . . . . . . . . . . . . 50
Interpolazione lineare a tratti e spline cubica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
2.3.1 Interpolazione lineare a tratti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
2.4 Curve parametriche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
2.4.1 Il ciclo switch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
2.5 Approssimazione di dati . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
2.5.1 Retta di regressione sugli scarti verticali . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
2.5.2 Modello potenza e modello esponenziale . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
2.5.3 Caricare i dati di input da file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
Per interpolare n + 1 coppie di punti (x i , y i ), in MATLAB esiste una function, chiamata polyfit. La
function polyfit ha come dati di input tre variabili, il vettore x che contiene le ascisse dei dati da interpolare, il vettore y che contiene le ordinate dei dati da interpolare e infine lintero n del grado del polinomio di
interpolazione. In output, si ottiene il vettore p, di lunghezza n+1, che contiene i coefficienti del polinomio di
grado n, dal coefficiente corrispondente al grado n fino ad arrivare al coefficiente corrispondente al grado 0.
Quindi p=(p n , p n1 , p n2 , . . . , p 0 ), tale che il polinomio di interpolazione sia p n (x) = p 0 +p 1 x +p 2 x 2 +. . . p n x n .
Lalgoritmo della function polyval basato su un procedimento ai minimi quadrati (che studieremo con
lapprossimazione). Difatti, la function polyval ci servir anche per approssimare dei dati. Nel caso
dellinterpolazione, la funzione genera la matrice di Vandermonde.
Una volta ottenuto il vettore p dalla polyfit, per poter valutare il polinomio di interpolazione si pu
usare unaltra function di MATLAB chiamata polyval che ha come parametri di input il vettore p dei
coefficienti del polinomio da valutare (in ordine decrescente) e il punto (o vettore o matrice) xval in cui
valutare il polinomio. La funzione, infatti, vettoriale: pu restituire il valore del polinomio valutato in un
punto o in un vettore o in una matrice.
Vediamo un esempio. Siano date le coppie di punti da interpolare (0, 1), (1, 0) e (2, 2). Costruiamo i vettori
x=[0,1,2] e y=[ 1,0,2]. Il grado del polinomio di interpolazione n = 2. Quindi
>> x=[0 1 2];
>> y=[1 0 2];
>> p=polyfit(x,y,2)
p =

43

2. S U INTERPOLAZIONE E APPROSSIMAZIONE

1.5000

-2.5000

1.0000

Il vettore p che abbiamo ottenuto ci permette di dire che il polinomio di interpolazione dato da p 2 (x) =
1.5x 2 2.5x1 = 12.5x+1.5x 2 (lo abbiamo scritto in due modi equivalenti). Valutiamo ora questo polinomio
proprio nelle ascisse di interpolazione, per verificare che la condizione di interpolazione verificata. Usiamo
la function polyval.
>> y1=polyval(p,x)
y1 =
1.0000

-0.0000

2.0000

Se proviamo a vedere lerrore assoluto commesso,


>> y-y1
ans =
1.0e-15 *
0.222044604925031

0.444089209850063

0.222044604925031

ci accorgiamo che lerrore dellordine di 1015 . In questo caso non andiamo a vedere lerrore relativo
perch una delle ordinate di interpolazione vale 0.

2.1 Interpolazione monomiale e con i polinomi di Lagrange


Proviamo ora a scrivere noi due function per interpolare n +1 coppie di dati. In particolare scriviamo una
function che applica il procedimento di interpolazione con funzioni base monomiali: dovremo dunque risolvere un sistema di n +1 equazioni in n +1 incognite in cui la matrice del sistema la matrice di Vandermonde
(e chiederemo a MATLAB di risolverci il sistema). Successivamente scriveremo una function che applica il
procedimento di interpolazione di Lagrange.
La prima function la chiamiamo interpmonom.m (per interpolazione monomiale). Eseguiremo i
seguenti passaggi:
i due vettori x e y, che contengono, rispettivamente, le ascisse e le ordinate da interpolare, vogliamo
che siano dei vettori colonna. In input, per, potrebbero essere dati come vettori riga. Quindi usiamo il comando x=x(:); e y=y(:); per renderli colonna. Se sono gi vettori colonna, queste due
istruzioni non alterano i vettori;
controlliamo, con un ciclo if se i due vettori hanno la stessa lunghezza: se hanno lunghezza diversa
non ha senso procedere con la function e si esce dando un messaggio di errore (si veda luso di error:
stampa il messaggio di errore, che scriviamo noi, e interrompe lesecuzione della function);
il grado del polinomio che dobbiamo costruire deve essere di grado n se in ingresso sono state date
n + 1 coppie di punti. Poniamo perchi pari a n il valore della lunghezza del vettore x meno uno;
inizializziamo la matrice di Vandermonde, V, come una matrice di tutti uno, usando la function di
MATLAB ones; la matrice di Vandermonde deve avere n + 1 righe e n + 1 colonne perch sono n + 1 i
coefficienti da determinare;
A questo punto, ricordiamo come fatta la matrice V .

1 x 0 x 02 . . . x 0n
1 x
x 12 . . . x 1n
1

1 x
x 22 . . . x 2n

2
V =
.
..
..
..
.

.
.
.
.
1 x n x n2 . . . x nn

G
G

44

2.1. Interpolazione monomiale e con i polinomi di Lagrange

La prima colonna ha tutti uno, la seconda colonna ha il vettore x, la terza colonna ha il vettore con le
potenze al quadrato di x e cos via. Possiamo scrivere la matrice in modo ricorsivo tenendo presente
che ogni colonna uguale alla precedente moltiplicata, componente per componente, per il vettore x.
Ora, la prima colonna ha gi gli elementi tutti uguali a uno, perci applichiamo un ciclo for per scrivere
le colonne successive.
for i : 2 : n+1
V ( : , i )= x . * V ( : , i 1);
end

Ogni colonna il risultato del prodotto, componente per componente (.*) del vettore x con la colonna
precedente;
una volta creata la matrice usiamo una function di MATLAB che ci permette di risolvere il sistema di
equazioni lineari in cui la matrice del sistema V mentre il vettore dei termini noti il vettore colonna
y. Listruzione p=V\y; ci permette di avere nel vettore p il vettore soluzione del sistema V p = y.
Il vettore ottenuto contiene i coefficienti del polinomio di interpolazione in ordine crescente, cio
p(1) corrisponde al coefficiente di grado 0 e p(n+1) corrisponde al coefficiente che moltiplica x n .
Se, successivamente, vogliamo usare la function polyval per poter valutare il polinomio di interpolazione, conviene scrivere il vettore con i coefficienti in ordine decrescente. Facciamo questo con listruzione p=p(n+1:1:1); che legge il vettore p dallultima alla prima componente, partendo dallindice
n+1 e andando indietro con passo -1, e riassegna il vettore dato in questo ordine alla stessa variabile.
La function ha come parametri di output sia il vettore p, sia la matrice di Vandermonde V. Se, tuttavia, scriviamo (in uno script o nella Command Window) p=interpmonom(x,y) in uscita abbiamo
solo il vettore p. Impariamo, infatti, questa importante caratteristica delle function in MATLAB . Se
una function ha pi di una variabile di output supponiamo m - e se eseguiamo la function con una
lista di variabili di output inferiore a quella che c nella definizione della function, per esempio r ,
MATLAB restituisce solo le prime r variabili di output.
Vediamo, dunque, la function interpmonom.m

function [ p , V]=interpmonom ( x , y )
% i n t e r p o l a z i o n e monomiale
% dati i v a l o r i x e y da i n t e r p o l a r e s i c o s t r u i s c e i l v e t t o r e p
% dei c o e f f i c i e n t i del polinomio di i n t e r p o l a z i on e
% applicando i l metodo dei c o e f f i c i e n t i indeterminati
% Esempio
% x =[0 1 2 ] ;
% y =[1 0 2 ] ;
% [ p , V]=interpmonom ( x , y )
% p =
%
%
1.5000
%
2.5000
%
1.0000
%
%
V =
%
%
1
0
0
%
1
1
1
%
1
2
4
%
x=x ( : ) ; %con questo comando rendiamo i l v e t t o r e come v e t t o r e colonna
%nel caso in cui s i a s t a t o gia dato come v e t t o r e colonna
%l i s t r u z i o n e non cambia i l v e t t o r e
y=y ( : ) ;
i f length ( x )~= length ( y )
error ( MATLAB:interpmonom , errori sui dati )
end

45

2. S U INTERPOLAZIONE E APPROSSIMAZIONE

n=length ( x ) 1; % i v e t t o r i x y hanno n+1 componenti e i l polinomio


% di i n t e r p ol a z i o n e sara di grado n
V=ones (n+1 ,n+ 1 ) ; %crea la matrice V di t u t t i uno
%i n i z i a l i z z a z i o n e d e l l a matrice V
% in questo modo la prima colonna ha gia
% g l i elementi t u t t i uguali a uno
for i =2:n+1
V ( : , i )= x . * V ( : , i 1); %ogni colonna ha g l i elementi del t i p o
% x_j ^( i 1). Si possono vedere anche
% come i l prodtto di x_j per i l corrispondente
% elemento d e l l a colonna precedente
end
p=V\y ;
% i l v e t t o r e p contiene i c o e f f i c i e n t i del polinomio i n t e r p o l a t o r e
% in ordine c r e s c e n t e p0 p1 p2 . . .
% s e vogliamo usare la function del MATLAB polyval per valutare
% t a l e polinomio in piu punti , dobbiamo porre l e componenti
% del v e t t o r e p in ordine d e c r e s c e n t e
p=p(n+ 1 : 1 : 1 ) ;
end

Ora possiamo provare a eseguire questa function e vedere cosa succede con lesempio che abbiamo visto
prima
>> x=[0 1 2];
>> y=[1 0 2];
>> [p, V]=interpmonom(x,y)
p =
1.5000
-2.5000
1.0000

V =
1
1
1

0
1
2

0
1
4

>> y1=polyval(p,x)
y1 =
1

>> y1-y
ans =
0

Anche questa volta, valutiamo il polinomio di interpolazione nei nodi di interpolazione e lerrore vale
esattamente zero.

46

2.1. Interpolazione monomiale e con i polinomi di Lagrange

Passiamo ora allinterpolazione di Lagrange. Il polinomio di Lagrange si scrive come


p n (x) = L 0 (x)y 0 + L 1 (x)y 1 + . . . L n (x)y n
e ciascun polinomio di Lagrange dato da
L i (x) =

n x x
Y
j
j =0
j 6=i

xi x j

Rispetto al caso precedente, non abbiamo direttamente i coefficienti del polinomio di interpolazione,
perch la scrittura del polinomio fatta in modo diverso (anche se equivalente nel senso che il polinomio
finale lo stesso). Perci dobbiamo pensare ad una function che ci permette di valutare direttamente il
polinomio nei punti di interesse. A tal fine, dobbiamo essere capaci di valutare i polinomi di Lagrange (in
modo da avere i valori L 0 (x), L 1 (x), ...) ,fare i prodotti L i (x)y i e sommare i vari contributi in modo da avere il
valore del polinomio di interpolazione nel punto x. A tal fine ci serviremo di due function, una che permette
di valutare li -simo polinomio di Lagrange L i (x) e laltra che ci permette di valutare il valore del polinomio di
interpolazione.
Chiamiamo con lagrange.m la function che restituisce la funzione L i (x), a seconda dellindice i assegnato. I dati di input saranno le ascisse di interpolazione, il punto (o il vettore) in cui andare a valutare il
polinomio di Lagrange, e da non trascurare lindice del polinomio di Lagrange. A tal proposito, consideriamo che, se nella teoria, parliamo di n +1 punti con indice da 0 fino a n (x 0 , x 1 , x 2 , . . . , x n ), in MATLAB lindice
0 corrisponde alla prima componente del vettore, per cui avremo gli indici che vanno da 1 a n + 1.
La produttoria della formula del generico i -simo polinomio di Lagrange viene fatta con un ciclo for. Osserviamo che, per fare il prodotto, la variabile viene inizializzata a 1 in modo da poter applicare la formula in
modo ricorsivo.
Q
Vediamo un esempio: dobbiamo fare y = nj=1 (x x j ). Inizializziamo y = 1; poi facciamo y = y(x x 1 ) =
(x x 1 ), quindi y = y(x x 2 ) = (x x 1 )(x x 2 ) e cos via (mediante un ciclo for) fino allindice n. Alla fine y
sar proprio il prodotto di tutti i termini indicati nella formula. Nel nostro caso, dobbiamo considerare che
possiamo valutare il polinomio di Lagrange non sono in un valore scalare ma anche in un vettore. Quindi
come risultato possiamo avere un vettore. Vediamo dunque la function e leggiamo i commenti per capire ci
che viene fatto.
function yval=lagrange ( xval , x , i )
% function yval=lagrange ( xval , x , i )
% function che c a l c o l a i l polinomio isimo di Lagrange L_i ( xval )
% valutandolo in xval ( xval puo e s s e r e uno s c a l a r e o un v e t t o r e )
% x e i l v e t t o r e con i nodi di i n t e r p o l a z i o n e
% i e l i n d i c e del polinomio di Lagrange
% yval=L_i ( xval )
% Esempio
%>> x =[0 1 2 ] ;
%>> xval = 0 . 5 ;
%>> yval=lagrange ( xval , x , 1 )
% yval =
%
0.375000000000000
%>> yval=lagrange ( xval , x , 2 )
% yval =
%
0.750000000000000
%>> yval=lagrange ( xval , x , 3 )
% yval =
% 0.125000000000000
%
%>> xval=x ;
%>> yval=lagrange ( xval , x , 1 )
%

47

2. S U INTERPOLAZIONE E APPROSSIMAZIONE

%yval =
%
%
1
%
0
%
0
%
xval=xval ( : ) ;
m=length ( x ) ;
yval=ones ( length ( xv a l ) , 1 ) ; %i n i z i a l i z z i a m o a uno l e componenti
% di yval in modo da poter f a r e poi
% i l prodotto in modo r i c o r s i v o
% yval= ( xvalx0 ) ( xvalx1 ) . . . . . ( xvalxn ) / ( ( xix0 ) ( xix1 ) . . . . ( xixn ) )
% dove , t r a x0 , x1 , . . . , xn non va considerato x i
% un modo c l a s s i c o e usare i l c i c l o f o r
for j =1: i 1
yval=yval . * ( xvalx ( j ) ) / ( x ( i ) x ( j ) ) ;
end
for j = i +1:m
yval=yval . * ( xvalx ( j ) ) / ( x ( i ) x ( j ) ) ;
end
end

Osserviamo che questa function non dipende dalle ordinate dei nodi di interpolazione ma solo dalle ascisse.
La function pu essere utile, tra le altre cose, per fare il grafico di questi polinomi.
Passiamo ora a scrivere la function per ottenere il valore del polinomio di interpolazione di Lagrange
in un punto o in un vettore. Poich il punto (variabile scalare) un caso particolare di vettore di lunghezza uno, organizziamo la function in modo da valutare il polinomio su vettori. La function, che chiamiamo
interlagrange.m organizzata nel modo seguente:
innanzitutto controlla se le lunghezze dei vettori x e y sono uguali;
il vettore delle ordinate lo si pone come vettore colonna;
si pone uguale a n la lunghezza del vettore x (o y). Sappiamo che il polinomio ha grado di interpolazione n 1 (ricordiamo la notazione n + 1 punti di interpolazione implica grado n; in questo caso n punti
implica grado n 1);
si calcola la lunghezza del vettore xval per vedere in quanti punti dobbiamo valutare il polinomio di
interpolazione;
si inizializza a zero una matrice, A, che ci servir daiuto per costruire il polinomio: questa matrice avr
un numero di righe pari alla lunghezza del vettore xval e un numero di colonne pari a n;
a ciascuna colonna di A assegniamo il valore delli -simo polinomio di Lagrange valutato nel vettore
xval (perci n colonne). La matrice A sar dunque del tipo

L 0 (xv al (1))
L 1 (xv al (1)) L n (xv al (1))
L (xv al (2))
L 1 (xv al (2)) L n (xv al (2))
0

L (xv al (3))
L 1 (xv al (3)) L n (xv al (3))

0
A=

..
..
..
..

.
.
.
.
L 0 (xv al (m)) L 1 (xv al (m)) L n (xv al (m))

G
G
G

G
G
G

Se la matrice scritta in questo modo, se facciamo il prodotto di ogni riga per i corrispondenti elementi
del vettore y avremo

L 0 (xv al (1))y 0 + L 1 (xv al (1))y 1 + + L n (xv al (1))y n


p n (xv al (1)
L (xv al (2))y + L (xv al (2))y + + L (xv al (2))y
0
0
1
1
n
n p n (xv al (2))

..

...

.
p
(xv
al
(m))
n
L 0 (xv al (m))y 0 + L 1 (xv al (m))y 1 + + L n (xv al (m))y n

G perci facciamo il prodotto della matrice A per il vettore y.


48

2.1. Interpolazione monomiale e con i polinomi di Lagrange

Vediamo la function.
function yval=interplagrange ( xval , x , y )
% function yval=interplagrange ( xval , x , y )
% dati i v e t t o r i x e y da i n t e r p o l a r e
% la function fa l i n t e r p o l az i o n e di Lagrange valutandola
% in xval ( che puo e s s e r e un v e t t o r e )
% costruiamo la matrice A che ha come colonne g l i isimi polinomi di Lagrange
% v a l u t a t i nel v e t t o r e xval
% ciascuna r i g a j di A contiene dunque L_1 ( xval ( j ) ) L_2 ( xval ( j ) . . . .
% i l prodotto di ciascuna r i g a per i l v e t t o r e colonna y r e s t i t u i s c e quindi
% i l valore del polinomio di Lagrange in yval ( j )
% Per questo faremo i l prodotto matricev e t t o r e
% Esempio
% >> x = [ 0 , 1 , 2 ] ;
% >> y =[1 0 2 ] ;
% >> xval = 0 . 5 ;
% >> yval=interplagrange ( xval , x , y )
%
% yval =
%
%
0.1250
% >> yval=interplagrange ( x ( 1 ) , x , y )
%
% yval =
%
%
1
%
% >> yval=interplagrange ( x ( 2 ) , x , y )
%
% yval =
%
%
0
%
% >> yval=interplagrange ( x ( 3 ) , x , y )
%
% yval =
%
%
2
%
%
i f length ( x )~= length ( y )
error ( MATLAB:lagrange , x e y non hanno la stessa lunghezza )
end
y=y ( : ) ;
n=length ( x ) ;% n1 e i l grado del polinomio
m=length ( x v a l ) ;
A=zeros (m, n ) ;
A ( : , 1 ) = lagrange ( xval , x , 1 ) ;
for i =2:n
A ( : , i )= lagrange ( xval , x , i ) ;
end
yval=A * y ;
end

49

2. S U INTERPOLAZIONE E APPROSSIMAZIONE

Esercizio 2.1.1 Date le coppie di punti (0, 1), (0.5, 0.1), (1, 0.3), (1.2, 1.2) e (2, 3), fare il grafico del polinomio di interpolazione nellintervallo [0, 2]. Si faccia uno script in modo da poter scegliere, in input, se usare
la function polyfit, o la interpmonom o la interplagrange associando la scelta ad una variabile (per esempio scelta : se scelta==1 applica lapproccio della polyfit, se scelta==2 si usa la
interpmonom, se scelta==3 si applica linterpolazione di Lagrange). Si valuti il polinomio nel vettore
xval=0:0.02:2 e se ne faccia il grafico.

2.2 Interpolazione con la tabella delle differenze divise di Newton


Proviamo ora a calcolare il polinomio di interpolazione utilizzando le differenze divise di Newton.
Ricordiamo che, date n + 1 coppie di punti da interpolare, (x i , f (x i )), i = 0, 1, . . . , n, la tabella delle
differenze divise si costruisce considerando la formula
f [x i ] = f (x i )
f [x i , . . . , x j ] =

f [x i +1 , . . . x j ] f [x i , . . . , x j 1 ]
x j xi

Possiamo costruire una tabella nel modo seguente:


xi
x0

f []
f (x 0 )

x1

f (x 1 )

x2

f (x 2 )

x3

f (x 3 )

x4

f (x 4 )

..
.

..
.

f [, ]

f [, , ]

f [, , , ]

f [, , , , ]

f (x 1 ) f (x 0 )
x1 x0
f (x 2 ) f (x 1 )
x2 x1
f (x 3 ) f (x 2 )
x3 x2
f (x 4 ) f (x 3 )
x4 x3
..
.

f [x 2 , x 1 ] f [x 0 , x 1 ]
x2 x0
f [x 2 , x 3 ] f [x 1 , x 2 ]
x3 x1
f [x 3 , x 4 ] f [x 2 , x 3 ]
x4 x2
..
.

f [x 1 , x 2 , x 3 ] f [x 0 , x 1 , x 2 ]
x3 x0
f [x 2 , x 3 , x 4 ] f [x 1 , x 2 , x 3 ]
x4 x1
..
.

f [x 1 , x 2 , x 3 , x 4 ] f [x 0 , x 1 , x 2 , x 3 ]
x4 x0
..
.

Di questa tabella, ci serviranno, poi, i valori della diagonale principale presi a partire da f (x 0 ).
Possiamo allora costruire, in MATLAB, una matrice in cui salviamo i valori a partire dalla colonna delle
ordinate.
Nel caso di n + 1 = 5 coppie di punti, la matrice che andremo a costruire sar:
f (x 0 )
f (x 1 )
f (x 2 )
f (x 3 )
f (x 4 )

50

0
f (x 1 ) f (x 0 )
x1 x0
f (x 2 ) f (x 1 )
x2 x1
f (x 3 ) f (x 2 )
x3 x2
f (x 4 ) f (x 3 )
x4 x3

f [x 2 , x 1 ] f [x 0 , x 1 ]
x2 x0
f [x 2 , x 3 ] f [x 1 , x 2 ]
x3 x1
f [x 3 , x 4 ] f [x 2 , x 3 ]
x4 x2

f [x 1 , x 2 , x 3 ] f [x 0 , x 1 , x 2 ]
x3 x0
f [x 2 , x 3 , x 4 ] f [x 1 , x 2 , x 3 ]
x4 x1

0
f [x 1 , x 2 , x 3 , x 4 ] f [x 0 , x 1 , x 2 , x 3 ]
x4 x0

2.2. Interpolazione con la tabella delle differenze divise di Newton

Di questa matrice, che chiamiamo A; ci serviranno, poi, i valori


A(1, 1) = f (x 0 ),
f (x 1 ) f (x 0 )
,
x1 x0
f [x 2 , x 1 ] f [x 0 , x 1 ]
,
A(3, 3) =
x2 x0
f [x 1 , x 2 , x 3 ] f [x 0 , x 1 , x 2 ]
A(4, 4) =
,
x3 x0
f [x 1 , x 2 , x 3 , x 4 ] f [x 0 , x 1 , x 2 , x 3 ]
A(5, 5) =
x4 x0
A(2, 2) =

, cio gli elementi della diagonale principale della matrice A (lindice di riga uguale allindice di colonna).
In particolare, A(2, 2) = f [x 0 , x 1 ], A(3, 3) = f [x 0 , x 1 , x 2 ], A(4, 4) = f [x 0 , x 1 , x 2 , x 3 ] e A(5, 5) =
f [x 0 , x 1 , x 2 , x 3 , x 4 ]. Questi sono i coefficienti del polinomio di interpolazione che va scritto come
p 4 (x) = f (x 0 ) + f [x 0 , x 1 ](x x 0 ) + f [x 0 , x 1 , x 2 ](x x 0 )(x x 1 ) + f [x 0 , x 1 , x 2 , x 3 ](x x 0 )(x x 1 )(x x 2 )+
f [x 0 , x 1 , x 2 , x 3 , x 4 ](x x 0 )(x x 1 )(x x 2 )(x x 3 )
Partiamo con il costruire una function che, date le ascisse e le ordinate dei punti da interpolare, ci
restituisce questa tabella delle differenze divise. Chiamiamo questa function divdif.m
function t a b l e = d i v d i f ( x , y )
%function t a b l e = d i v d i f ( x , y )
% x
a s c i s s e dei dati da i n t e r p o l a r e
% y
ordinate dei dati da i n t e r p o l a r e
% table tabella delle differenze divise
% la t a b e l l a ha l e colonne d i s p o s t e nel modo seguente
%
f
f [. ,.]
f [. ,. ,.] f [. ,. ,. ,.] f [. ,. ,. ,. ,.]
% al f i n e di c o s t r u i r e i l polinomio di interpolazione , la
% t a b e l l a parte dalla colonna d e l l e ordinate da i n t e r p o l a r e
%
% Esempio
% x =[0 0 .5 1 1.2 2 ] ;
% y=[1 0.1 0.3 1.2 2 ] ;
% table=divdif (x , y )
%t a b l e =
%
%
1.0000
0
0
0
0
%
0.1000
2.2000
0
0
0
%
0.3000
0.8000
3.0000
0
0
%
1.2000
7.5000
11.8571
12.3810
0
%
2.0000
1.0000
6.5000 12.2381 12.3095
%
x=x ( : ) ;
y=y ( : ) ;
n=length ( x ) ; % n numero t o t a l e di coppie di punti da i n t e r p o l a r e
% quindi i l grado del polinomio sara n1
i f n~=length ( y )
error ( MATLAB:differenze_divise , errore sui dati )
else
t a b l e =zeros (n , n ) ; % la t a b e l l a deve a r r i v a r e a c a l c o l a r e la d i f f e r e n z a
% d i v i s a di ordine n
t a b l e ( : , 1 ) = y ; % la prima colonna ha l e ordinate d e l l e coppie di punti da i n t e r p o l a r e
for j =2:n
for k =2: j

51

2. S U INTERPOLAZIONE E APPROSSIMAZIONE

t a b l e ( j , k )= ( t a b l e ( j , k1) t a b l e ( j 1,k1) ) / ( x ( j ) x ( j k+1) ) ;


end
end
% con la formula r i c o r s i v a usata nei due c i c l i f o r andiamo a c o s t r u i r e i
% v a l o r i d e l l a t a b e l l a r i g a dopo r i g a
% j =2 k=2 abbiamo s o l o t a b l e ( 2 , 2 ) che corrisponde a l l a prima d i f f e r e n z a
% d i v i s a t r a x0 e x1
% j =3 , k = 2 , 3 ; ricaviamo t a b l e ( 3 , 2 ) e t a b l e ( 3 , 3 ) , dove t a b l e ( 3 , 2 )
% corrisponde a l l a d i f f e r e n z a d i v i s a del primo ordine t r a x1 e x2
% t a b l e ( 3 , 3 ) corrisponde a l l a d i f f e r e n z a d i v i s a del secondo ordine
% t r a x0 , x1 e x2 . E c o s i via .
end

Osserviamo che abbiamo chiamato table la matrice che contiene i valori della tabella delle differenze
divise. I valori sono costruiti riga per riga.
Di questa tabella, abbiamo detto, ci servono solo i valori della diagonale principale, in modo da poter
valutare il polinomio di interpolazione.
Per valutare il polinomio di interpolazione nel modo pi efficiente, applichiamo lalgoritmo di Horner,
che un algoritmo molto semplice. Cerchiamo di capire con un esempio come funziona.
Supponiamo di dover calcolare il polinomio p(x) = 2 + 3(x 1) + 4(x 1)(x 2) + 10(x 1)(x 2)(x 3).
Se facciamo i calcoli cos come leggiamo la formula dobbiamo fare somme e prodotti e, in particolare, dobbiamo fare 3(x 1) (una moltiplicazione) 4(x 1)(x 2) (due moltiplicazioni) e 10(x 1)(x 2)(x 3) (tre
moltiplicazioni). Riscriviamo la formula nel modo seguente
p(x) = 2 + (x 1)(3 + 4(x 2) + 10(x 2)(x 3))
p(x) = 2 + (x 1)(3 + (x 2)(4 + 10(x 3)))
Abbiamo messo in evidenza i termini (x 1) e poi (x 2). Ora dobbiamo fare 10(x 3) (una moltiplicazione), poi sommiamo 4 e moltiplichiamo il tutto per (x 2) (unaltra moltiplicazione), sommiamo 3 e
moltiplichiamo per (x 1) (unaltra moltiplicazione). Rispetto alle 6 moltiplicazioni di prima ora ne facciamo solo 3. Lalgoritmo di Horner si pu scrivere nel modo seguente, per calcolare il polinomio p(x) =
a 0 + a 1 (x x 0 ) + a 2 (x x 0 )(x x 1 ) + a 3 (x x 0 )(x x 1 )(x x 2 ) + . . . a n (x x 0 )(x x 1 )(x x 2 ) (x x n1 ):
p = an
p = p(x x n1 ) + a n1
= a n (x x n1 ) + a n1
p = p(x x n2 ) + a n2
= a n (x x n1 )(x x n2 ) + a n1 (x x n2 ) + a n2
..
.
p = p(x x 0 ) + a 0
= a n (x x n1 )(x x n2 ) . . . (x x 1 )(x x 0 ) + . . . + a 1 (x x 1 )(x x 0 ) + a 0
= a 0 + a 1 (x x 0 )(x x 1 ) + . . . + a n (x x 0 )(x x 1 ) . . . (x x n2 )(x x n1 )
Se a il vettore che contiene i coefficienti del polinomio (in questo caso sar un vettore di lunghezza n +1), se
x il vettore delle ascisse e xval il punto in cui valutare il polinomio p, le istruzioni precedenti si scriveranno
in MATLAB come
p=a (n+ 1 ) ;
for i =n: 1:1
p=p * ( xvalx ( j ) ) + a ( j ) ;
end

Scriviamo dunque la function interpdivdif.m (teniamo conto del fatto che, nella function n la lunghezza del vettore x, quindi il grado del polinomio n 1). Poich possiamo valutare il polinomio sia in
52

2.2. Interpolazione con la tabella delle differenze divise di Newton

uno scalare sia in un vettore, dobbiamo tenere conto anche di questo fatto quando andiamo ad applicare
lalgoritmo di Horner: si veda listruzione yval=table(n,n)*ones(length(xval),1); e luso del . allinterno del ciclo
for.
function yval= i n t e r p d i v d i f ( xval , x , t a b l e )
% function yval= i n t e r p d i v d i f ( xval , x , t a b l e )
% x a s c i s s e dei dati da i n t e r p o l a r e
% t a b l e t a b e l l a d e l l e d i f f e r e n z e d i v i s e , ottenuta dalla function d i v d i f
% xval array di v a l o r i in cui c a l c o l a r e i l polinomio i n t e r p o l a t o r e
%
puo e s s e r e un s i n g o l o punto o un insieme di punti
% yval valore ( o v a l o r i ) del polinomio i n t e r p o l a t o r e valutato in xval
% nel c a l c o l o del polinomio i n t e r p o l a t o r e ,
% s i parte dalla f i n e e s i applica l algoritmo di Horner ( s i veda dispensa
% per la spiegazione s u l l algoritmo di Horner )
% Esempio
% x =[0 0 .5 1 1.2 2 ] ;
% y=[1 0.1 0.3 1.2 2 ] ;
% table=divdif (x , y ) ;
% xval = [ 0 : 0 . 1 : 2 ] ;
% yval= i n t e r p d i v d i f ( xval , x , t a b l e ) ;
% p l o t ( x , y , o , xval , yval )
xval=xval ( : ) ;
x=x ( : ) ;
n=length ( x ) ; % n lunghezza del v e t t o r e x , quindi n1 e i l grado del
% polinomio di i n t e r p o l a z i o n e
yval= t a b l e (n , n ) * ones ( length ( xv a l ) , 1 ) ;
for j =n1: 1:1
yval=yval . * ( xvalx ( j ) ) + t a b l e ( j , j ) ;
end
end

Un altro modo per costruire il polinomio di interpolazione di Newton pu essere quello di richiamare la
function che genera la tabella delle differenze divise allinterno della stessa function che valuta il polinomio di
interpolazione. In MATLAB, infatti, una function pu richiamare al suo interno unaltra function e questa pu
essere scritta in forma concatenata alla prima, cio allinterno della function che la richiama! Si parla di nested functions. Ci si pu fare se la function interna non chiamata allinterno di un ciclo come if, for,
while, .... Osserviamo che la function interna deve necessariamente essere chiusa con listruzione end.
In questo modo, al posto di usare due functions, ne usiamo solo una. Se ci interessa conoscere la tabella delle differenze divise, possiamo metterla tra i parametri di output. Scriviamo allora la function che
chiamiamo intdivdif1.m
function [ yval , t a b l e ]= i n t d i v d i f 1 ( x , y , xv a l )
% function yval= i n t d i v d i f 1 ( xval , x , y )
% x a s c i s s e dei dati da i n t e r p o l a r e
% y ordinate dei dati da i n t e r p o l a r e
% xval array di v a l o r i in cui c a l c o l a r e i l polinomio i n t e r p o l a t o r e
%
puo e s s e r e un s i n g o l o punto o un v e t t o r e
% yval valore ( o v a l o r i ) del polinomio i n t e r p o l a t o r e valutato in xval
% nel c a l c o l o del polinomio i n t e r p o l a t o r e ,
% s i parte dalla f i n e e s i applica l algoritmo di Horner
% a l l interno di questa function s i richiama un a l t r a function che
% c a l c o l a la t a b e l l a d e l l e d i f f e r e n z e d i v i s e
t a b l e =tab ( x , y ) ;
%%%%%%%%%%%%% function chiamata e s c r i t t a a l l interno d e l l a function %%%
function t a b l e =tab ( x , y )
%function t a b l e = d i v d i f ( x , y )
% x a s c i s s e dei dati da i n t e r p o l a r e

53

2. S U INTERPOLAZIONE E APPROSSIMAZIONE

% y ordinate dei dati da i n t e r p o l a r e


% table tabella delle differenze divise
x=x ( : ) ;
y=y ( : ) ;
n=length ( x ) ;
m=length ( y ) ;
i f n~=m
error ( MATLAB:differenze_divise , errore sui dati )
else
t a b l e =zeros (n , n ) ;
table ( : , 1 ) = y ;
for j =2:n
for k =2: j
t a b l e ( j , k )= ( t a b l e ( j , k1) t a b l e ( j 1,k1) ) / ( x ( j ) x ( j k+1) ) ;
end
end
end
end
%%%%%%%%%%%%%%%%%%%%%% f i n e function tab
%
%
xval=xval ( : ) ;
x=x ( : ) ;
n=length ( x ) ;
yval= t a b l e (n , n ) * ones ( length ( xv a l ) , 1 ) ;
for j =n1: 1:1
yval=yval . * ( xvalx ( j ) ) + t a b l e ( j , j ) ;
end
end

Esercizio 2.2.1 Si riprendano i dati (0, 1), (0.5, 0.1), (1, 0.3), (1.2, 1.2) e (2, 3), e si applichi il procedimento
di interpolazione delle differenze divise di Newton per calcolare il polinomio di interpolazione. Lo si valuti
nei punti del vettore xval=0:0.01:2. Si faccia il grafico del polinomio.

2.3 Interpolazione lineare a tratti e spline cubica


2.3.1 Interpolazione lineare a tratti
Abbiamo visto, nella teoria, che, date m coppie di punti (x i , y i ) possiamo costruire il polinomio di interpolazione lineare su ciascun intervallo [x i , x i +1 ]. In questo caso importante che le ascisse da interpolare,
oltre ad essere distinte tra loro, siano ordinate in senso crescente, in modo da poter considerare gli intervalli
indicati [x i , x i +1 ]. Il polinomio di interpolazione si pu scrivere come v(x) tale che
v(x) = y i + f [x i , x i +1 ](x x i ),

x i x x i +1 ,

i = 1, 2, . . . , m 1.

Dato un punto x bisogna capire a quale intervallo appartiene per poter applicare la formula di interpolazione
lineare corretta.
Come scrivere una function in MATLAB che faccia tutto questo?
Dato il vettore che contiene le ascisse dei punti da interpolare, x=(x(1), x(2), . . ., x(m)) e assegnato un
punto xval, il valore del polinomio di interpolazione lineare a tratti si calcola in due passaggi:
54

2.3. Interpolazione lineare a tratti e spline cubica

1. si individua lintervallo [x(i ), x(i + 1)] a cui appartiene xval;


2. si calcola, quindi il valore del polinomio applicando la formula per quellintervallo.
Per scrivere una function che faccia tutto questo, useremo due strumenti di MATLAB:
Visto che, una volta individuato lintervallo in cui valutare la funzione lineare a tratti, ci serve la differenza divisa del primo ordine (che altro non che la pendenza del segmento di retta), consideriamo
un vettore con le differenze divise del primo ordine. Usiamo la function di MATLAB diff che calcola le differenze delle componenti del vettore dato in input. Quindi, se x un vettore di lunghezza m,
diff(x) un vettore che ha come componenti x(2)-x(1), x(3)-x(1), ..., x(m) -x(m-1).
Il vettore diff(x) ha lunghezza m-1. Possiamo costruirci due vettori, diff(x) e diff(y). Dividendo questi due vettori, componente per componente (usando quindi il comando ./) avremo il
vettore delle differenze divise del primo ordine. Chiamiamo p questo vettore (che sar dunque dato da

p=diff(y)./diff(x);

G La cosa pi difficile individuare lintervallo in cui si trova ciascuna componente del vettore u in cui
andare a valutare il polinomio di interpolazione lineare a tratti. Nel caso di una sola componente,
potremmo pensare a qualcosa del genere
for i =1: m1
i f x ( i ) <= u
j=i
end
end
v=y ( j ) (ux ( j ) ) * p( j ) ;

Con questo ciclo for andiamo a controllare su tutti gli m 1 sottointervalli se x i u. Se vale x i u,
consideriamo lintervallo in cui si trova. Alla fine del ciclo for, la variabile j contiene lultimo indice che
verifica la relazione e, quindi, d lesatta posizione di u tra le componenti del vettore x, vale a dire in
quale sottointervallo si trova. Possiamo quindi valutare il valore del polinomio lineare a tratti, usando
la formula appropriata.
Immaginiamo di avere ora un vettore u. Per fare qualcosa del genere, dovremmo introdurre un
vettore di indici, della stessa lunghezza del vettore u, e fare qualcosa del genere
k=ones ( lenght (u ) , 1 ) ;
for i =1: m1
for j =1: length (u ) ;
i f x ( i ) <= u( j )
k ( j )= i
end
end
v=y ( k) (ux ( k ) ) . * p( k ) ;

Alla fine dei due cicli for, il vettore k sar un vettore in cui k(j) contiene lindice del sottointervallo
in cui si trova la componente u(j) del vettore u. In questo modo possiamo valutare il polinomio di
interpolazione lineare a tratti, componente per componente.
Tuttavia, al posto di questo doppio ciclo for con allinterno un ciclo if, le stesse istruzioni si possono
scrivere in questo modo
for i =1:

m1
k ( x ( i )<= u)= i ;

end

Quando si applica la proposizione logica x(i) <= u sul vettore u, il risultato un vettore di zeri o
uno a seconda che la proposizione sia vera o falsa in corrispondenza delle componenti del vettore u:
di conseguenza, in corrispondenza della componente del vettore in cui il risultato della proposizione
logica vale uno, viene cambiato anche il valore della componente del vettore k e viene posto uguale a
i.
Per capire meglio queste istruzioni, si provi a eseguire il seguente script

55

2. S U INTERPOLAZIONE E APPROSSIMAZIONE

x =[0 1 2 3 4 ] ;
u= [ 1 . 5 2 . 4 ] ;
k=ones ( 2 , 1 ) ;
for i : 1 : lenght ( x)1
k ( x ( i )<=u)= i
end

La function, che chiamiamo atratti.m dunque data da


function v= a t r a t t i ( x , y , u)
% function v= a t r a t t i ( x , y , u)
% x v e t t o r e d e l l e a s c i s s e da i n t e r p o l a r e
% y v e t t o r e d e l l e ordinate da i n t e r p o l a r e
% u s c a l a r e o v e t t o r e in cui andare a c a l c o l a r e i l polinomio
%
di i n t e r p o l a z i o n e l i n e a r e a t r a t t i
% v v (u) polinomio di i n t e r p o l az i o n e l i n e a r e a t r a t t i valutato in
%
u
% Esempio
% x =[0 0.5 1 1.2 2 ] ;
% y=[1 0.2 0.2 0.3 1 . 5 ] ;
% u=[0:0.01:2];
% v= a t r a t t i ( x , y , u ) ;
% plot (x , y , o , u, v )
x=x ( : ) ;
y=y ( : ) ;
u=u ( : ) ;
m=length ( x ) ; % lunghezza del v e t t o r e x
i f m~=length ( y )
error ( MATLAB:function:atratti , errore sui dati )
end
p= d i f f ( y ) . / d i f f ( x ) ; % v e t t o r e d e l l e d i f f e r e n z e d i v i s e del primo ordine
% d i f f ( x ) : v e t t o r e che contiene l e d i f f e r e n z e
% x(2) x ( 1 ) , x(3) x ( 2 ) , . . . x (m) x (m1)
% d i f f ( y ) : v e t t o r e che contiene l e d i f f e r e n z e
% y (2) y ( 1 ) , y (3) y ( 2 ) , . . . y (m)y (m1)
k=ones ( length (u ) , 1 ) ; % v e t t o r e di componenti t u t t e uguali a 1 , di lunghezza
% uguale al v e t t o r e u
for i =1:m1
k ( x ( i )<= u)= i ;
end
s=ux ( k ) ;
v= y ( k ) + s . * p( k ) ;
end

Abbiamo quindi una function che ci permette di costruire il polinomio di interpolazione lineare a tratti.
Vediamo ora come costruire una function che costruisca il polinomio di interpolazione spline cubica.
Osserviamo che in MATLAB esiste gi una function che genera il polinomio di interpolazione spline cubica:
la function si chiama spline e, in genere, usa le condizioni not-a-knot. Questa function si pu usare nel
seguente modo:
p=spline(x,y) genera i coefficienti del polinomio di interpolazione spline cubica. Per poter valutare il
polinomio in un vettore u, si usa la function ppval mediante listruzione v=ppval(pp,u)
v=spline(x,y,u) genera direttamente il vettore v della spline valutata in u;
se il vettore y ha la stessa lunghezza del vettore x, allora viene generata la spline not-a-knot; se invece
y ha due componenti in pi rispetto a x, allora il primo e lultimo valore del vettore y sono usati come
i valori della derivata prima della spline cubica nei punti finali del vettore x, e si ha quindi la cosiddetta
spline completa.
Proviamo a costruire la spline cubica naturale sulle coppie di punti x=[0 0.5 1 1.2 2] e y=[-1
0.2 -0.2 0.3 1.5]. Eseguiamo i seguenti comandi

G
G
G

56

2.3. Interpolazione lineare a tratti e spline cubica

x =[0 0 .5 1 1.2 2 ] ;
y=[1 0 .2 0.2 0.3 1 . 5 ] ;
pp=spline ( x , y ) ;
u=0:0.01:2;
v=ppval (pp , u ) ;

Oppure, pi semplicemente, proviamo a scrivere


x =[0 0 .5 1 1.2 2 ] ;
y=[1 0 .2 0.2 0.3 1 . 5 ] ;
u=0:0.01:2;
v=spline ( x , y , u ) ;

Dopo facciamo il grafico plot(x,y, o, u,v).


Proviamo adesso a scrivere noi una function che costruisca la spline cubica. Noi abbiamo studiato in tutti
i passaggi come si arriva alla costruzione della spline cubica naturale ed proprio una function che genera
questo tipo di spline che andremo a costruire.
Ricordiamo che lalgoritmo per arrivare alla spline cubica naturale prevede la soluzione di un sistema
lineare. La spline cubica ha la forma
v(x) = s i (x) = a i + b i (x x i ) + c i (x x i )2 + d i (x x i )3 ,
I coefficienti c i sono ricavati risolvendo il sistema

2(h 1 + h 2 )
h2
0

h2
2(h 2 + h 3 )
h3

0
h3
2(h 3 + h 4 )

A=
..
..

.
.

..

.
h
2(h
m3

x i x x i +1 , i = 1, 2, . . . m 1

Ac = , con A e dati da,

0
h4
..
.

m3 + h m2 )

h m2

0
..
.
...
0
h m2
2(h m2 + h m1 )

3( f [x 2 , x 3 ] f [x 1 , x 2 ])

3( f [x 3 , x 4 ] f [x 2 , x 3 ])

=
..

.
3( f [x m1 , x m ] f [x m2 , x m1 ])
dove h 1 , h 2 , . . . , h m1 sono le ampiezze dei singoli sottointervalli.
I passi da seguire (per i dettagli, si controlli la dispensa del corso) sono:
1. risolvere il sistema Ac = che, risolto, fornisce i coefficienti c 2 , c 3 , . . . , c m1 delle spline;
2. aggiungere al vettore c, i valori c 1 = c m = 0
3. applicare, per i = 1, . . . , m 1 le relazioni
ai = y i
b i = f [x i , x i +1 ]
di =

c i +1 c i
3h i

(2c i + c i +1 )h i
3

Osserviamo che la matrice A ha elementi tutti uguali a zero tranne che gli elementi della diagonale principale (i valori A i i ) e gli elementi che si trovano sulla diagonale immediatamente sopra e sotto la diagonale
principale. Per costruire questa matrice in MATLAB usiamo la function diag che costruisce matrici diagonali o estrae diagonali da una matrice. Vediamo come si usa: supponiamo di avere un vettore d=[1 2 3],
se scrivamo diag(d) il risultato la matrice
57

2. S U INTERPOLAZIONE E APPROSSIMAZIONE

1
0
0

0
2
0

0
0
3

La matrice ha tutti zeri, tranne sulla diagonale principale in cui ci sono gli elementi del vettore d. La matrice
ha dunque la dimensione del vettore: in questo caso, 3 righe e 3 colonne Se invece scriviamo il comando
diag(d,1) abbiamo
0
0
0
0

1
0
0
0

0
2
0
0

0
0
3
0

La matrice ha gli elementi del vettore d sulla diagonale che si trova sopra la diagonale principale. Ora la matrice 44 perch il vettore d deve riempire tutta la diagonale considerata. Quindi, se scriviamo diag(d,-1)
la matrice sar con gli elementi del vettore d sulla sottodiagonale principale
0
1
0
0

0
0
2
0

0
0
0
3

0
0
0
0

In genere listruzione diag(d,n) crea una matrice che ha tutti zeri tranne quelli che si trovano sulla
diagonale spostata di n rispetto alla diagonale principale, in cui ci sono gli elementi del vettore d. La matrice
di dimensione uguale alla lunghezza del vettore d + il valore assoluto di n. La diagonale principale come
se avesse il valore n = 0, quindi ci spostiamo di n sopra o sotto la diagonale principale a seconda che n
sia positivo o negativo. La function diag si pu applicare anche a matrici (si consulti lhelp in linea per
approfondire).
A noi interessa questa function perch, grazie ad essa, possiamo scrivere la matrice del sistema che
dobbiamo risolvere:
h= d i f f ( x ) ;
n=length ( x ) 1;
a= 2 * (h ( 1 : n1)+h ( 2 : n ) ) ;
bi= h ( 2 : n1);
A=diag ( a ) + diag ( bi , 1 ) + diag ( bi , 1 ) ;

Infatti diag(a) ci d la matrice con tutti zero tranne che sulla diagonale principale e questi elementi corrispondono proprio a quelli che vogliamo noi sulla matrice A. Se osserviamo poi come fatta la matrice A gli
elementi sulla sovra e sotto diagonale sono gli stessi. Perci usiamo il vettore b e creiamo altre due matrici.
Con un operazione di somma, mettiamo insieme i vari contributi e otteniamo la matrice A. Il vettore termine
noto fa uso delle differenze divise del primo ordine. Scriviamo ora la function e osserviamo bene luso degli
indici nei vettori per i vari coefficienti b, c,d.
function v=splinecubiche ( x , y , u)
% function v=splinecubiche ( x , y , u)
% co stru zione d e l l a s p l i n e cubica naturale a t r a t t i
% x v e t t o r e d e l l e a s c i s s e da i n t e r p o l a r e
% y v e t t o r e d e l l e ordinate da i n t e r p o l a r e
% u v e t t o r e in cui andare a c a l c o l a r e la s p l i n e cubica naturale
% v v e t t o r e d e l l a s p l i n e cubica naturale valutata nel v e t t o r e u
% Esempio
% x =[0 0.5 1 1.2 2 ] ;
% y=[1 0.2 0.2 0.3 1 . 5 ] ;
% u=[0:0.01:2];
% v=splinecubiche ( x , y , u ) ;

58

2.4. Curve parametriche

% plot (x , y , o , u, v )
x=x ( : ) ;
y=y ( : ) ;
u=u ( : ) ;
h= d i f f ( x ) ; % v e t t o r e che da l e ampiezze dei s i n g o l i s o t t o i n t e r v a l l i
p= d i f f ( y ) . / h ; % v e t t o r e d e l l e d i f f e r e n z e d i v i s e del primo ordine
n=length ( x ) 1;
a= 2 * (h ( 1 : n1)+h ( 2 : n ) ) ;
bi= h ( 2 : n1);
A=diag ( a ) + diag ( bi , 1 ) + diag ( bi , 1 ) ;
psi= 3 * (p ( 2 : n) p ( 1 : n 1 ) ) ;
c=A\ psi ;
c =[0; c ; 0]; % c o e f f i c i e n t i c
d=( c ( 2 : n+1)c ( 1 : n ) ) . / ( 3 * h ) ; % c o e f f i c i e n t i d
b=ph . / 3 . * ( 2 . * c ( 1 : n)+ c ( 2 : n + 1 ) ) ; % c o e f f i c i e n t i b
k=ones ( length (u ) , 1 ) ;
for i =1:n
k ( x ( i )<= u)= i ;
end
s=ux ( k ) ;
v= y ( k ) + s . * ( b( k ) + s . * ( c ( k ) + s . * d( k ) ) ) ; % algoritmo di Horner per
% i l c a l c o l o del polinomio
% s p l i n e cubico a t r a t t i
end

2.4 Curve parametriche


Per costruire in MATLAB curve parametriche, dobbiamo ricordarci che ora le coordinate dei punti
attraverso cui far passare le curve sono funzioni di un parametro t .
La rappresentazione che dobbiamo avere sar del tipo
(t 1 , x 1 ), (t 2 , x 2 ) . . . (t m , x m )
(t 1 , y 1 ), (t 2 , y 2 ) . . . (t m , y m )

dove ora x i = x(t i ) e y i = y(t i ). I valori del parametro t (t 1 , t 2 , . . . , t n ) dovranno essere valori crescenti in
modo da poter applicare il procedimento dellinterpolazione lineare o spline cubica a tratti.
Fissiamo in [0, 1] lintervallo in cui far variare t . Se abbiamo n punti prenderemo t 1 = 0 e t i = (i 1)h =
1
con h =
, cos che t m = 1.
m 1
Si tratta quindi di costruire due polinomi di interpolazione a tratti, il primo che interpola i dati
(t 1 , x 1 ), (t 2 , x 2 ) . . . (t m , x m )
e il secondo che interpola i dati
(t 1 , y 1 ), (t 2 , y 2 ) . . . (t m , y m )
Una volta che abbiamo i due polinomi, che chiamiamo x(t ) e y(t ), possiamo valutarli in un vettore di punti
dellintervallo [0, 1] per poter poi fare il grafico.
Questa volta, al posto di una function, scriviamo uno script che ci permette di scegliere i punti (senza
dover scrivere noi le ascisse e le ordinate) tramite il mouse. Inoltre, scegliamo se fare la curva utilizzando
un polinomio di interpolazione lineare a tratti o una spline cubica naturale oppure not-a-knot (richiamando
quindi le function che abbiamo gi visto).
A tal fine useremo la function ginput che ci permette di ottenere le coordinate dei punti tramite il mouse. Se usiamo il comando [x,y]=ginput(n) con n dato in input, siamo invitati a scegliere n punti dalla figura
59

2. S U INTERPOLAZIONE E APPROSSIMAZIONE

che si aprir dopo aver schiacchiato il tasto di invio. Se invece scriviamo [x,y]=ginput prendiamo un numero
di punti a piacere fino a che non schiacchiamo il tasto di invio. Subito dopo, sia nel primo che nel secondo
caso, troveremo le coordinate dei punti nei vettori x e y. Infine, si pu usare ginput mediante listruzione [x,y,but]=ginput(n) che d in output anche una terza variabile, but, che contiene un vettore di interi che
specificano quale tasto del mouse stato usato (1, 2 o 3 a partire da sinistra).
Useremo questa soluzione per scegliere i punti. Porremo but=1, che associato al tasto sinistro del
mouse e prenderemo i punti con il tasto sinistro del mouse. Per scegliere lultimo punto, lo scegliamo con
il tasto destro (eventualmente anche con il tasto centrale), in modo tale da cambiare il valore della variabile
but.
Una volta ottenuti i punti scegliamo il tipo di interpolazione. Approfittiamo delloccasione per imparare
un altro ciclo che si pu usare in MATLAB, il ciclo switch.

2.4.1 Il ciclo switch


Il ciclo switch si usa in questo modo:
Ciclo switch
switch ( espressione ) % ( l e s p r e s s i o n e puo e s s e r e uno s c a l a r e o una s t r i n g a )
case { valore1 } % e s e g u i t a s e l e s p r e s s i o n e e valutata al valore1 )
{ istruzioni }
{
...
}
case { valore2 } % ( e s e g u i t a s e l e s p r e s s i o n e e valutata al valore2 )
{ istruzioni }
{
...
}
otherwise
{ istruzioni }
{
...
}
end

Il ciclo con switch confronta i valori dati nellespressione che si trova subito dopo switch, con ciascun
valore assegnato a case ed esegue le istruzioni relative al case in cui valore ed espressione coincidono.
Vediamo un semplice esempio dove lespressione da confrontare una stringa:
s c e l t a =test1 ;
switch s c e l t a
case { test1 }
x0= 0 . 1 ;
x1= 0 . 2 ;
case { test2 }
x0= 0 . 0 ;
x1= 1 . 0 ;
otherwise
disp ( nessun caso test scelto )
end

A seconda del caso cambiano i valori x0,x1.


Oltre al ciclo switch, per scegliere il tipo di interpolazione usiamo unaltra function, di MATLAB, chiamata menu. La function menu genera un menu che permette di fare delle scelte, ognuna associata ad
un numero. Questo menu, in MATLAB compare come una finestra separata dalle altre finestre di MATLAB. In Octave, invece, il menu rimane nella finestra di lavoro. In genere la function si usa in questo modo scelta= menu(titolo del menu, scelta1,scelta2,scelta3,...) dove scelta1,scelta2,... sono delle
stringhe che dicono la possibile scelta da fare. Il valore della variabile scelta corrisponde al numero che
corrisponde alla stringa della scelta fatta.
Vediamo un esempio
60

2.4. Curve parametriche

Figura 2.1: Esempio di menu in MATLAB

s c e l t a =menu( scegli un metodo , bisezioni , punto fisso , Newton-Raphson ,


Regula Falsi )

In MATLAB vedremo qualcosa come mostrato in figura 2.1. Con il mouse sceglieremo quale metodo
applicare e la variabile scelta sar 1, 2, 3 o 4 a seconda del metodo.
In Octave invece, vediamo questo:
scegli un metodo
[
[
[
[

1]
2]
3]
4]

bisezioni
punto fisso
Newton-Raphson
Regula Falsi

pick a number, any number:

Vediamo dunque lo script per le curve parametrice, che chiamiamo curveparam.m


%
%
%
%
%

questo e uno s c r i p t per f a r e g r a f i c i di curve parametriche , potendo


s c e g l i e r e di f a r l e utilizzando un polinomio di i n t e r p o l a z i on e l i n e a r e
a t r a t t i oppure una s p l i n e cubica di t i p o naturale o notaknot
i punti d e l l a curva vengono s c e l t i dall utente mediante la function
ginput :

close a l l % chiude t u t t e l e eventuali f i g u r e e s i s t e n t i


disp ( **************** CURVE PARAMETRICHE************* )
disp ( Usa il tasto sinistro del mouse per scegliere i punti. )
disp ( Per lultimo punto usare il tasto destro del mouse )
disp ( Scegli dal menu il tipo di interpolazione )
s c e l t a =menu( tipo di interpolazione a tratti , lineare , spline naturale , . . .
spline not-a-knot ) ;
figure ( 1 ) % apre una f i g u r a
axis ( [ 0 1 0 1 ] ) % posiziona l as s e d e l l e a s c i s s e e d e l l e ordinate t r a 0 e 1
% Scegliamo i punti s u l l a f i n e s t r a d e l l a f i g u r a che s i e aperta
% con punti n e l l i n t e r v a l l o [ 0 , 1 ] x [ 0 , 1 ]
hold on % i g r a f i c i verranno t u t t i s o v r a s c r i t t i
x = zeros ( 2 0 , 1 ) ; % i n i z i a l i z z i a m o a zero i v e t t o r i x e y
y = zeros ( 2 0 , 1 ) ; % s e saranno p r e s i piu di 20 punti , i v e t t o r i
% aumenteranno la l o r o lunghezza
n = 0;
but = 1 ; % but e una v a r i a b i l e che s e r v e per la function ginput

61

2. S U INTERPOLAZIONE E APPROSSIMAZIONE

while but == 1
n=n+1;
[ x (n ) , y (n ) , but ] = ginput ( 1 ) ; % ginput s e r v e per a c q u i s i r e i punti
% sulla finestra della figura
% a nostro piacere
plot ( x (n ) , y (n ) , g* , markersize , 6 )
% t e x t ( x i +0.01 , y i +0.01 , i n t 2 s t r (n ) ) % questo comando s e r v e s e vogliamo
% v i s u a l i z z a r e l ordine con cui sono
% s c e l t i i nodi
end
x=x ( 1 : n ) ;
y=y ( 1 : n ) ;
t = 0 : 1 / (n 1 ) : 1 ; % facciamo v a r i a r e i l parametro t t r a 0 e 1 , con passo h= 1 / (n1)
xx=linspace ( 0 , 1 ) ; % prendiamo 100 punti e q u i d i s t a n t i n e l l i n t e r v a l l o in cui varia t
switch s c e l t a
case 1
u= a t r a t t i ( t , x , xx ) ;
v= a t r a t t i ( t , y , xx ) ;
s t r i n g a =interpolazione lineare a tratti ;
case 2
u=splinecubiche ( t , x , xx ) ;
v=splinecubiche ( t , y , xx ) ;
s t r i n g a =spline cubica naturale ;
case 3
u=spline ( t , x , xx ) ;
v=spline ( t , y , xx ) ;
s t r i n g a =spline cubica not-a-knot ;
end
plot ( u , v , linewidth , 2 )
t i t l e ( stringa )
hold o f f % i g r a f i c i s u c c e s s i v i non verranno s o v r a s c r i t t i

E ora divertiamoci a prendere punti e a costruire curve parametriche che passano per essi.

2.5

Approssimazione di dati

2.5.1 Retta di regressione sugli scarti verticali


Abbiamo visto, nella teorica, che i coefficienti della retta di regressione sugli scarti verticali si trovano
risolvendo il sistema di equazioni
(
P
P
(n + 1)a 0 + a 1 ni=0 x i = ni=0 y i
P
P
P
a 0 ni=0 x i + a 1 ni=0 (x i )2 = ni=0 x i y i
Lipotesi da cui partiamo che abbiamo n + 1 coppie di punti (x i , y i ) i = 0, 1, . . . , n. La retta che troviamo pu
essere scritta come y = a 0 + a 1 x.
Lo stesso sistema di equazioni si pu scrivere in forma matriciale come
Aa = b
dove

n +1
A = Pn
i =0 x i

Pn
x
Pn i =0 i 2
i =0 (x i )

Pn

yi
b = Pni =0
i =0 x i y i

Vogliamo risolvere in MATLAB questo problema. Come fare? La risposta immediata ce la fornisce MATLAB con la function che abbiamo gi incontrato nellinterpolazione e, precisamente, la function polyfit.
62

2.5. Approssimazione di dati

Ricordiamo che i dati di input che abbiamo usato per la polyfit sono i vettori x e y e il grado del polinomio
di interpolazione (quindi length(x)-1). In generale, la polyfit ha, come dati di input, oltre ai vettori x
e y, un numero intero minore o uguale a length(x)-1: per valori minori di length(x)-1, la function
polyfit restituisce i coefficienti del polinomio di migliore approssimazione del grado che abbiamo dato
noi in input. Perci, se vogliamo una retta di approssimazione, basta scrivere p=polyfit(x,y,1) e nel vettore p
troveremo i coefficienti a 1 e a 0 della retta di approssimazione. Usando la polyval potremo fare il grafico
della retta.
Lalgoritmo che costruisce la retta di approssimazione molto semplice. Perch non fare una nostra
function MATLAB? Approfittiamo delloccasione per imparare qualche altra function. In particolare, introduciamo la function sum che, applicata a un vettore, fornisce come risultato la somma delle componenti del
vettore. Vediamo degli esempi:
>> x=[-1 -0.4 0.2 0.8 1];
>> sum(x)
ans =
0.6000
>> x=[0 1 2 3 4 5 6 ];
>> a=sum(x)
a =
21
>> b=sum(x.^2)
b =
91

Le prime due istruzioni che abbiamo dato, ci hanno restituito, in ans e in a, la somma delle componenti
del vettore x. Nel primo caso, sum(x) stata la stessa cosa delloperazione: 1 0.4 + 0.2 + 0.8 + 1 = 0.6.
Nel secondo caso, a = 0 + 1 + 2 + 3 + 4 + 5 + 6 = 21. Infine abbiamo fatto b=sum(x.2 ), vale a dire, abbiamo
prima elevato al quadrato ogni componente del vettore x ottenendo come risultato un vettore, e di questo
vettore abbiamo fatto la somma delle componenti. b = 02 + 12 + 22 + 32 + 42 + 52 + 62 = 91. A cosa ci serve
la function sum? A costruire in maniera immediata e diretta la matrice del sistema e il vettore termine noto.
Infatti, considerando m la lunghezza dei vettori dei dati da approssimare, possiamo scrivere
A=[m sum( x ) ; sum( x ) sum( x . ^ 2 ) ] ;
b=[sum( y ) ; sum( x . * y ) ] ;

Nel vettore b, la seconda componente si ha costruendo prima il vettore x.*y che fa il prodotto componente
per componente tra i due vettori, e poi facendo la somma delle componenti.
La function che possiamo scrivere dunque la seguente:
function [ p , A , b]= funapprox ( x , y )
% function p=funapprox ( x , y )
% x
a s c i s s e dei dati da approssimare
% y
ordinate dei dati da approssimare
% p=[ a1 a0 ] v e t t o r e dei c o e f f i c i e n t i d e l l a r e t t a
%
di r e g r e s s i o n e l i n e a r e s u g l i s c a r t i v e r t i c a l i
%
y=a0+a1x
%
i c o e f f i c i e n t i sono in ordine d e c r e s c e n t e
%
per p o t e r l i usare in combinazione con la
%
function polyval
% A
matrice del sistema da r i s o l v e r e

63

2. S U INTERPOLAZIONE E APPROSSIMAZIONE

% b
v e t t o r e termine noto del sistema
% Esempio
% x=[1 0.6 0 0.6 1 ] ;
% y =[1.194 0.430 0.052 0.422 1 . 0 3 4 ] ;
% [ p , A , b]= funapprox ( x , y )
% restituisce
% p =
%
0.0606
%
0.6264
%
% A =
%
5.0000
0
%
0
2.7200
%
% b =
%
3.1320
%
0.1648
%
% s i g n i f i c a che la r e t t a e y=0.1648 +3.1320x
m=length ( x ) ;
i f m~=length ( y )
error ( MATLAB:funapprox , errore sui dati )
end
% costruiamo la matrice del sistema
% A=[ m somma_ascisse ;
% somma_ascisse somma_( a s c i s s e ^ 2 ) ]
% i l v e t t o r e termine noto e
% b= [ somma_ordinate ; somma_ascisseperordinate ]
% per f a r e la somma d e l l e componenti di un v e t t o r e usiamo la function
% sum che permette di f a r e la somma d e l l e componenti di un v e t t o r e
% facendo sum( x . ^ 2 ) prima eseguiamo i quadrati d e l l e componenti
% del v e t t o r e x e poi facciamo la somma dei v a l o r i r i c a v a t i
A=[m sum( x ) ; sum( x ) sum( x . ^ 2 ) ] ;
b=[sum( y ) ; sum( x . * y ) ] ;
p=A\b ;
% In p la prima componente corrisponde ad a0 e la seconda ad a1
% invertiamo l ordine del v e t t o r e
p=p ( 2 : 1 : 1 ) ;

Data questa function, possiamo (invertendo il ruolo delle ascisse e delle ordinate nei dati di input),
calcolare i coefficienti della retta di regressione sugli scarti orizzontali.

2.5.2 Modello potenza e modello esponenziale


Possiamo scrivere una function che richiami questa che abbiamo appena creato, al fine di calcolare i
coefficienti delle funzioni di approssimazione, modello esponenziale e modello potenza.
Per il modello potenza diamo, ora, delle linee da seguire per costruire una function che restituisca i coefficienti a e b della funzione del modello potenza, e successivamente, per fare un grafico della funzione stessa.
Nel modello potenza cerchiamo i coefficienti a b della funzione di approssimazione y = ax b . I passi da fare
sono i seguenti:
x e y siano i vettori con le ascisse e le ordinate dei dati da interpolare;
costruiamo due nuovi vettori, X e Y (possiamo usare le lettere maiuscole) tali che X=log(x); Y=log(y); (abbiamo usato il logaritmo naturale (in MATLAB log il logaritmo naturale mentre log10 il logaritmo
in base 10);
chiamiamo la function funapprox che ci restituisce p,A,b ; p(1) e p(2) sono i coefficienti della
retta, di grado decrescente;

G
G

64

2.5. Approssimazione di dati

G sappiamo che, per il modello potenza, si ha la relazione p(2)=log(a) e p(1)=b, da cui


a=exp(p(2)); b=p(1)
una
G volta ricavati questi coefficienti, se vogliamo fare il grafico, dobbiamo ricondurci alla funzione
potenza, quindi

x v a l =x ( 1 ) : h : x ( end ) ; % con h passo di d i s c r e t i z z a z i o n e opportuno


% per esempio s i puo d e f i n i r e , prima
% di questa i s t r u z i o n e
% h=( x ( end)x ( 1 ) ) / 1 0 0 ;
% x ( end ) porta direttamente a l l ultima
% componente del v e t t o r e
yval=a * xv a l . ^b ;
plot ( x , y , o,xval,yval)

Istruzioni analoghe a queste si possono dare per il modello esponenziale.

Esercizio 2.5.1 Si costruiscano due function, da chiamare, rispettivamente, modpotenza.m e


modesponenziale.m in cui i dati di input siano i vettori x e y dei dati da approssimare e in output
diano i coefficienti a e b rispettivamente del modello potenza e del modello esponenziale.

2.5.3 Caricare i dati di input da file


A volte, i dati da utilizzare per risolvere determinati problemi, possono essere vettori o matrici di
dimensione elevata. Scrivere i dati dalla Command Window diventa oneroso.
Immaginiamo di dover approssimare i seguenti dati:
xi
yi
0.0
0.0
0.2
3.22
0.39 6.61
0.59 9.69
0.78 13.22
0.99 16.40
1.08 18.01
1.18 19.70
1.28 21.33
1.37 22.75
In questo esempio abbiamo 10 coppie di punti. Se dobbiamo scrivere tutti questi dati dalla Command Window e scriviamo male anche uno solo dei dati, se ce ne accorgiamo dobbiamo riscrivere o correggere il vettore
e rieseguire lo script o la function. Se non ce ne accorgiamo, avremo i risultati decisamente scorretti. Se poi
dobbiamo, dopo qualche giorno, ripetere lo stesso esempio, dobbiamo riscrivere di nuovo il vettore sperando di non sbagliare i dati. Questo solo con 10 coppie di punti. Pensiamo se abbiamo 20, 100, 1000, .... dati.
Molte volte i dati, proprio perch tanti, sono in un file di dati... Come procedere in questi casi? La cosa pi
semplice di salvare i dati di input in un file esterno (non in uno script o in una function) e di caricare questi
dati quando occorre. Tutto questo si fa nel modo seguente.
Con un editor di testo scriviamo un file in cui mettiamo i dati (in questo caso i valori delle ascisse e delle
ordinate da approssimare) esattamente come nella tabellina che abbiamo scritto prima:
0.0
0.2
0.39
0.59

0.0
3.22
6.61
9.69

65

2. S U INTERPOLAZIONE E APPROSSIMAZIONE

0.78
0.99
1.08
1.18
1.28
1.37

13.22
16.40
18.01
19.70
21.33
22.75

Salviamo questo file (in formato testo, o ASCII) con un nome, ad esempio xy.txt o xy.dat. Ora in
MATLAB, dalla Command Window, carichiamo questi dati in una matrice, dopodich, salviamo la prima
colonna nel vettore x e la seconda colonna nel vettore y che ci servono per fare lapprossimazione dei dati
stessi.
A=load ( xy.txt ) ;
x=A ( : , 1 ) ;
y=A ( : , 2 ) ;

In questo modo, scriviamo i dati solo una volta nel file xy.txt e li carichiamo ogni volta che serve. In
questo caso la matrice A ha due colonne, una che rappresenta il vettore x e una il vettore y.
Potremmo anche scrivere la matrice con due righe: in tal caso dovremmo prendere la prima riga e salvarla
come vettore x e la seconda riga e salvarla come vettore y.
Nel caso di molti dati, comunque, conviene salvare i dati come colonne (anche per facilit di lettura di
essi).

Esercizio 2.5.2 Scrivere il file di dati xy.txt con i dati dellesempio precedente. Utilizzare poi la function
funapprox.m per approssimare i dati, sia costruendo la retta di regressione lineare sugli scarti verticali
sia costruendo la retta di regressione lineare sugli scarti orizzontali. Fare il grafico delle due rette.

Un altro modo per caricare dati da file esterni abbinare la function input con la function load. Dapprima diamo ad una variabile il nome del file di dati da caricare (dando quindi una stringa di caratteri), poi
carichiamo il file che ha quel nome. Vediamo con lesempio precedente come fare.
>> stringa=input(scrivi il file
scrivi il file
dati.txt

, s)

stringa =
dati.txt
>> A=load(stringa)
A =
0
0.2000
0.3900
0.5900
0.7800
0.9900
1.0800
1.1800
1.2800
1.3700

0
3.2200
6.6100
9.6900
13.2200
16.4000
18.0100
19.7000
21.3300
22.7500

>>

Allinterno di input abbiamo scritto la frase scrivi il file e poi, dopo la virgola, abbiamo scritto
s. Questa istruzione s dice che quanto scriveremo in risposta alla function input sar una stringa
66

2.5. Approssimazione di dati

di caratteri che verr assegnata alla variabile stringa. Successivamente, noi carichiamo il file, messo nella
stringa dando alla matrice il nome A. Limportante scrivere il nome del file senza apici e senza lasciare spazi
bianchi prima di iniziare a scrivere il nome (altrimenti avremmo un messaggio di errore).

67

C APITOLO

Metodi diretti per sistemi lineari


Parte della disumanit del computer
sta nel fatto che, una volta
programmato e messo in funzione,
si comporta in maniera
perfettamente onesta.
Isaac Asimov

3.1 Prodotti matrice-vettore, matrice-matrice, scalari . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71


3.2 Metodi di sostituzione allindietro e in avanti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
3.3 Metodi diretti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
3.4 Norme di vettori . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
Nello studiare i metodi diretti per la soluzione di sistemi lineari, entriamo pienamente ad usare matrici e
vettori.
MATLAB lavora con matrici e vettori e ha gi molte function predefinite che ci permettono di risolvere
semplicemente problemi dellalgebra lineare.
Fino ad ora, abbiamo visto che, se abbiamo un sistema lineare Ax = b e lo vogliamo risolvere, basta
scrivere in MATLAB x=A\b per risolvere il sistema (limportante che il vettore b sia una vettore colonna).
Abbiamo anche gi visto le function:
zeros che agisce nel modo seguente:
zeros(n) crea una matrice quadrata di dimensione n
zeros(m,n) crea una matrice rettangolare di dimensione m n (abbiamo usato questo comando per
creare vettori riga o colonna)
size dice la dimensione della matrice o di un vettore
size(A) restituisce un vettore in cui la prima componente dice il numero di righe e la seconda
componente il numero di colonne della matrice A
length restituisce la lunghezza di un vettore
diag crea matrici diagonali
Abbiamo usato questa function per creare la matrice del sistema da risolvere per ottenere le spline
naturali.
Vediamo degli esempi di uso di questa function per poter prendere maggiore pratica.

G
G

>> v=[1 2 3];


>> A=diag(v)
A =
1
0

0
2

0
0

69

3. M ETODI DIRETTI PER SISTEMI LINEARI

0
0
>> A=diag(v,1)

A =
0
1
0
0
0
0
0
0
>> A=diag(v,-1)

0
2
0
0

0
0
3
0

A =
0
0
1
0
0
2
0
0
>> A=[1 2 3; 4 5
>> b=diag(A)

0
0
0
0
0
0
3
0
6; 7 8 9];

b =
1
5
9
>> a=diag(diag(A))
a =
1
0
0

0
5
0

0
0
9

Altre function e comandi utili gi esistenti in MATLAB sono (non esauriamo tutto lelenco delle function
a disposizione ma diamo solo le principali!!!):
ones : analogamente a zeros crea matrici con elementi tutti uguali a 1.
eye : crea la matrice identit.
A=eye(n) crea la matrice identit di dimensione n
A=eye(m, n) crea la matrice identit di dimensione m n
Se abbiamo gi una matrice (per esempio A): B=eye(size(A)) crea una matrice identit della stessa
dimensione di A.
det : applicato ad una matrice quadrata, restituisce il determinante della matrice (esempio: d=det(A) )
inv : applicato ad una matrice quadrata, restituisce la matrice inversa. (Se la matrice quasi singolare
o singolare, si ha un messaggio di errore).
tril e triu : applicate ad una matrice estraggono la parte triangolare inferiore (o bassa) e superiore (o
alta) rispettivamente. Se, tra i parametri di input, oltre alla matrice, aggiungiamo uno scalare, k, allora
viene estratta la parte triangolare (inferiore o superiore) a partire dalla diagonale che si trova in alto o in
basso (a seconda che k abbia segno positivo o negativo) di k volte sulla diagonale principale. Vediamo
qualche esempio.

G
G

G
G
G

>> A=[1 2 3; 4 5 6; 7 8 9];


>> L=tril(A)
L =
1

70

3.1. Prodotti matrice-vettore, matrice-matrice, scalari

4
7

5
8

0
9

>> U=triu(A)
U =
1
2
0
5
0
0
>> L1=tril(A,1)

3
6
9

L1 =
1
2
0
4
5
6
7
8
9
>> L_1=tril(A,-1)
L_1 =
0
0
4
0
7
8
>> U=triu(A,1)

0
0
0

U =
0
2
0
0
0
0
>> U=triu(A,-1)

3
6
0

U =
1
4
0

2
5
8

3
6
9

Si provi a fare qualche altro esempio, con matrici 4 4 o 5 5.

3.1 Prodotti matrice-vettore, matrice-matrice, scalari


Ora, se vogliamo fare il prodotto matrice-vettore, con altri linguaggi di programmazione dobbiamo fare
qualcosa del genere (scriviamo ora una function matrprod.m)
function y=matrprod (A , x )
% supponiamo che A s i a quadrata di dimensione n e che x s i a un v e t t o r e
% di lunghezza n . Se non siamo s i c u r i , dobbiamo f a r e un c o n t r o l l o
% s u l l e dimensioni
% calcoliamo y=Ax
n=length ( x ) ;
y=zeros (n , 1 ) ; % i n i z i a l i z z i a m o i l v e t t o r e y
% y _ i = sum_( j =1)^n A_ ( i j ) x_j % per f a r e questa somma usiamo un c i c l o f o r
for i =1:n
for j =1:n
y ( i )= y ( i )+A( i , j ) * x ( j ) ;

71

3. M ETODI DIRETTI PER SISTEMI LINEARI

end
end
% ora abbiamo t u t t e l e componenti del v e t t o r e y
end

In MATLAB, al posto di dover fare qualcosa del genere (osservare il doppio ciclo for), basta scrivere y=A*x e
viene generato il vettore x: bisogna solo avere laccortezza di scrivere x come vettore colonna.
Se dobbiamo fare un prodotto tra matrici, anche qui MATLAB ci evita di scrivere righe e righe di codice
(che ora vediamo per capire cosa dovremmo fare e non facciamo) e ci permette di usare loperazione di moltiplicazione anche per fare il prodotto tra matrici. (Attenzione, quindi al prodotto .* da usare per fare prodotti
componente per componente e al prodotto * che ci permette di fare queste altre operazioni). Se abbiamo due
matrici A e B e dobbiamo scrivere la matrice prodotto C = AB , dalla teoria sappiamo che:
ci j =

n
X

ai k bk j = ai 1 b1 j + ai 2 b2 j + . . . + ai n bn j

k=1

per i = 1, 2, . . . , n e j = 1, 2, . . . , n.

Tutto questo si pu tradurre mediante le righe di codice (supponiamo per semplicit che le due matrici A
e B siano quadrate e di dimensione n).
C=zeros (n , n ) ;
for i =1:n
for j =1:n
for k =1:n
C( i , j )= C( i , j ) + A( i , k ) * B( k , j ) ;
end
end
end

In MATLAB, scriviamo semplicemente C=A*B e abbiamo la matrice prodotto (evitando di fare un triplo
ciclo for).
P
Se dobbiamo fare il prodotto scalare tra due vettori = xT y = ni=1 x i y i , possiamo vederlo come il prodotto tra due matrici (il vettore riga x per il vettore colonna y). Se vogliamo vedere in codice cosa fare
abbiamo
a l f a =0;
for i =1:n
a l f a = a l f a +x ( i ) * y ( i )
end

In MATLAB, per, proprio perch il prodotto scalare si pu vedere come caso particolare di prodotto tra
matrici, usiamo la forma alfa=x*y se x un vettore riga e y un vettore colonna. Se i vettori sono entrambi
colonna, si scrive alfa= x* y (facciamo cio il trasposto del primo vettore in modo da poterlo avere come riga).
Bisogna quindi stare attenti a come sono stati definiti i vettori di cui fare il prodotto scalare.

3.2 Metodi di sostituzione allindietro e in avanti


Nello studiare il metodo di eliminazione di Gauss, abbiamo visto che, dal sistema di partenza Ax = b si arriva al sistema LU x = b (supponiamo che sia verificato il teorema LDU e che abbiamo usato la fattorizzazione
di Crout o di Doolittle). Per risolvere gli esercizi, risolveremo due sistemi:
1. Poniamo U x = y da cui il sistema diventa Ly = b. Risolviamo quindi il sistema Ly = b mediante
sostituzione in avanti.
2. Una volta ricavato y risolviamo il sistema U x = y mediante sostituzione allindietro.
Scriviamo allora due function che applichino il metodo di sostituzione in avanti e di sostituzione allindietro
(possono tornarci utili per verificare gli esercizi che dobbiamo fare per prepararci allesame scritto...)
72

3.2. Metodi di sostituzione allindietro e in avanti

Lalgoritmo per risolvere il sistema Ax = b dove A adesso una matrice triangolare triangolare inferiore :
per i = 1 fino a i = n, procedendo in avanti con passo 1
P
b i ij1
=1 a i j x j
xi =
ai i
Scriviamo una function che traduce questo algoritmo, ricordando che in MATLAB dobbiamo cercare di vettorizzare il pi possibile le operazioni tra matrici e tra matrici e vettori. In questo caso, cerchiamo di fare il
P
meno possibile i cicli for. E, infatti, evitiamo di farlo per la somma ij1
=1 a i j x j . Vediamo come (nella function
facciamo anche un controllo sulle dimensioni della matrice e del vettore termine noto).
function x = s o s t a v a n t i (A , b)
% function x = s o s t a v a n t i (A , b )
% A e una matrice t r i a n g o l a r e i n f e r i o r e di dimensione n
% b e un v e t t o r e di lunghezza n
% applichiamo i l metodo di s o s t i t u z i o n e in avanti per poter
% r i s o l v e r e i l sistema Ax=b
% Esempio
% A= A=[1 0 0 ; 2 1 0 ; 1 2 3 ] ;
% b=[1; 2; 3];
% x= s o s t a v a n t i (A , b )
%
%x =
%
%
1.0000
%
0
%
0.6667
% Se scriviamo x=A\b abbiamo la s t e s s a r i s p o s t a
m= s i z e (A ) ;
i f m( 1 ) ~= m( 2 )
error ( MATLAB:sostavanti , matrice rettangolare )
end
n=length ( b ) ;
i f m( 1 ) ~= n
error ( MATLAB:sostavanti , matrice e vettori di lunghezze diverse )
end
x=zeros (n , 1 ) ;
x (1 )=b ( 1 ) /A ( 1 , 1 ) ;
for i =2:n
x ( i )= ( b( i ) A( i , 1 : i 1) * x ( 1 : i 1) ) /A( i , i ) ;
end
end

P
Come si vede dal listato, per calcolare ciascuna componente del vettore x, la somma ij1
=1 a i j x j viene fatta
come prodotto tra la sottomatrice di A che considera la riga i -sima e tutti gli elementi di colonna che vanno
dalla prima colonna fino a quella i 1 (quindi questa sottomatrice un vettore riga) per il vettore x con le
componenti dalla prima alla i 1 (e x stato inizializzato come un vettore colonna). Quindi il risultato che
otteniamo uno scalare (in pratica stiamo facendo il prodotto scalare tra due vettori). C da dire, inoltre, che
la prima componente del vettore x stata gi definita prima di entrare nel ciclo for quindi, quando i=2 nel
ciclo for, dobbiamo considerare solo la prima componente di x che gi abbiamo.
naturale ora pensare ad una function che traduca in modo simile lalgoritmo di sostituzione allindietro:
per i = n fino a i = 1, procedendo allindietro con passo 1
P
b i nj=i +1 a i j x j
xi =
ai i
In MATLAB scriviamo
73

3. M ETODI DIRETTI PER SISTEMI LINEARI

function x = s o s t i n d i e t r o (A , b)
% function x = s o s t i n d i e t r o (A , b )
% A e una matrice t r i a n g o l a r e su pe ri ore di dimensione n
% b e un v e t t o r e di lunghezza n
% applichiamo i l metodo di s o s t i t u z i o n e a l l i n d i e t r o per poter
% r i s o l v e r e i l sistema Ax=b
% Esempio
% A=[1 2 3 ; 0 2 1 ; 0 0 1 ] ;
% b = [ 1 ; 2 ; 3]
% >> x= s o s t i n d i e t r o (A , b )
%
% x =
%
%
7.0000
%
0.5000
%
3.0000
% Se scriviamo x=A\b abbiamo la s t e s s a r i s p o s t a
m= s i z e (A ) ;
i f m( 1 ) ~= m( 2 )
error ( MATLAB:sostindietro , matrice rettangolare )
end
n=length (b ) ;
i f m( 1 ) ~= n
error ( MATLAB:sostindietro , matrice e vettori di lunghezze diverse )
end
x=zeros (n , 1 ) ;
x (n)=b(n) /A(n , n ) ;
for i =n1: 1:1
x ( i )= (b( i ) A( i , i +1:n ) * x ( i +1:n) ) /A( i , i ) ;
end
end

Osserviamo che queste function sono pensate esclusivamente per matrici che siano o triangolari inferiori
o triagolari superiore.

3.3 Metodi diretti


Per risolvere sistemi lineari mediante metodi diretti, abbiamo visto la fattorizzazione LU e, per matrici
simmetriche definite positive, la fattorizzazione di Cholesky.
In MATLAB ci sono gi delle function che permettono di fare queste fattorizzazioni.
C infatti la function lu che fa la fattorizzazione LU, nel senso di Doolittle e mediante una matrice di
permutazione: si fa la fattorizzazione mediante una matrice di permutazione P per cui otteniamo P A = LU .
Gli usi pi semplici sono
[L,U]= lu(A) d in output la matrice U triangolare superiore e L che il prodotto di P 1 per la matrice L
della fattorizzazione (quindi possiamo anche non avere come matrice una triangolare inferiore!).
Se vogliamo capire chi sia questa matrice di permutazione, basta scrivere [L,U,P]=lu(A)
Per quanto riguarda la fattorizzazione di Cholesky, dalla teoria, abbiamo visto che, se esiste la fattorizzazione, possiamo scrivere A = LL T . Se invece di considerare L triangolare inferiore, pensiamo in termini di
U = L T , abbiamo A = U T U .
In MATLAB c la function chol che, di default, restituisce la matrice triangolare superiore U .
Se vogliamo avere la L, dobbiamo aggiungere una stringa tra i parametri di input.
In particolare
U=chol(A) restituisce la matrice triangolare superiore tale che U T U = A
L=chol(A,lower) restituisce la matrice triangolare inferiore tale che LL T = A.
Se la matrice di input non definita positiva si ha un messaggio di errore.

74

3.4. Norme di vettori

Esercizio 3.3.1 Si provi a risolvere qualche esercizio di quelli proposti nei temi desame degli anni passati,
implementando le function proposte (lu e chol) unitamente alle due function per la sostituzione in avanti
e allindietro per risolvere i sistemi lineari degli esercizi proposti.

3.4 Norme di vettori


Dato un vettore x abbiamo visto che possibile misurare in un certo modo il vettore (estendendo il
concetto del valore assoluto di un numero) attraverso una misura chiamata norma.
In particolare abbiamo visto tre norme:
P
Norma assoluta (o norma l 1 ), indicata con k k1 : kxk1 = ni=1 |x i |
Norma massima (o norma infinito, l ), indicata con k k : kxkq= max1i n |x i |
p
Pn
2
Norma euclidea (o norma l 2 ), indicata con k k2 : kxk2 = xT x =
i =1 |x i |
Come implementare queste norme in MATLAB?
Per la norma 1, ricordiamoci della function cum gi utilizzata e consideriamo come norma 1 di un vettore
la variabile norma data da

G
G
G

norma=cum( abs ( x ) ) ;

Per la norma infinito dobbiamo calcolare il massimo in valore assoluto delle componenti del vettore x.
In MATLAB la function max calcola il massimo della variabile (scalare o vettoriale) data in input 1 , perci la
norma infinito data da
norma=max( abs ( x ) ) ;

Per la norma 2, la formula si pu scrivere come


norma=sqrt (cum( x . ^ 2 ) ) ;

oppure come
norma=sqrt ( x * x ) ; % con x dato come v e t t o r e colonna

C tuttavia una function di MATLAB che fa gi tutto questo e si chiama norm

G
G
G

alfa=norm(x,1) restituisce la norma 1


alfa=norm(x) restituisce la norma 2 (potremmo anche scrivere alfa=norm(x,2) )
alfa=norm(x,inf) restituisce la norma infinito (al posto di inf possiamo anche scrivere Inf).

Questa function ci torner utile anche per le norme su matrici.


Per maggiori dettagli su questa e su tutte le altre function che abbiamo incontrato si rimanda allhelp
online di MATLAB (o Octave).
In molte occasioni ci serviranno vettori di norma unitaria (cio la cui norma vale 1).
2
Eseguiamo allora uno script per visualizzare graficamente, nello spazio R , i vettori di norma unitaria
nelle varie norme 1, infinito e 2.
2
Se un vettore x dello spazio R , di componenti (x, y), ha norma unitaria in norma 1 vuol dire che |x|+|y| =
1. Quindi, se facciamo variare la componente x nellintervallo [1, 1], sar |y| = 1 |x|. In questo modo
delimitiamo la regione dei vettori unitari di norma 1.
Per la norma infinito, deve essere max (|x|, |y|) = 1: quindi se x [1, 1], vuol dire che se non vale |x| = 1
sar |y| = 1.
p
p
Infine, per la norma 2, dovendo essere x 2 + y 2 = 1, si ha x 2 + y 2 = 1 da cui y = 1 x 2 .
1 Se largomento di input una matrice, in output max restituisce il valore massimo di ogni colonna.

75

3. M ETODI DIRETTI PER SISTEMI LINEARI

Quindi consideriamo il vettore delle ascisse, in cui facciamo variare x nellintervallo [1, 1] (non possiamo
prendere ascisse al di fuori di questo intervallo perch poi, qualunque valore prendessimo per y, la norma di
(x, y) sarebbe maggiore di 1 mentre noi vogliamo identificare i vettori di norma unitaria).
A seconda del tipo di norma scelto, andremo a costruire il vettore delle corrispondenti ordinate, in modo
da avere vettori di componenti (x i , y i ) in norma unitaria.
Per fare il grafico dei risultati che otterremo procederemo seguendo due strade: intanto faremo ununica
figura suddivisa in tre grafici che mostreranno la regione individuata dai vettori di norma unitaria per ciascuna delle tre norme considerate. A ciascuno di questi grafici faremo vedere un campione dei vettori di
norma unitaria.
Per fare ununica figura suddivisa in pi grafici, usiamo il comando subplot che funziona cos: immaginiamo di scomporre la figura in un certo numero di caselle disposte su m righe e n colonne, in modo da
dover poi fare m n grafici. I grafici vengono contati a partire dalla casella (1,1), riga dopo riga. Eseguiremo
le seguenti istruzioni:
subplot (m, n , 1 )
plot ( x1 , y1 )
subplot (m, n , 2 )
plot ( x2 , y2 )
subplot (m, n , 3 )
plot ( x3 , y3 )
.
.
.

%dobbiamo c r e a r e i l primo g r a f i c o n e l l a prima


% c a s e l l a in a l t o a s i n i s t r a
% i l g r a f i c o viene f a t t o s u l l a c a s e l l a ( 1 , 1 )
% attiviamo la seconda c a s e l l a ( 1 , 2 )
% facciamo i l secondo g r a f i c o
% attiviamo la seconda c a s e l l a ( 1 , 3 )
% facciamo i l secondo g r a f i c o

Per tornare a fare grafici nel modo solito (un unico grafico su ununica figura) possiamo chiudere la figura
corrente, con il comando close(1) (se la figura la figura 1) oppure close all (e chiudiamo tutte le figure).
Oppure possiamo scrivere subplot(1,1,1) e poi fare il nuovo plot.
Per poter poi visualizzare in due dimensioni dei vettori (come siamo abituati dalla fisica), useremo la function compass: compass(x,y) fa il grafico dei vettori di componenti [x(i), y(i)] come frecce che partono
dallorigine del sistema di assi cartesiani.
Ecco allora lo script (come nome possiamo dargli normeunitarie.m 2
% s c r i p t per vedere n e l l e norme 1 , i n f i n i t o e 2 e n e l l o spazio R^2
% i v e t t o r i di norma unitaria .
x=linspace ( 1 , 1 );
% norma1= | x | + | y |
% norma1=1 > | y | = 1|x |
y1=1abs ( x ) ;
y2=y1 ;
subplot ( 3 , 1 , 1 ) % abbiamo suddiviso la f i g u r a in 3 righe e 1 colonna
% quindi i g r a f i c i saranno incolonnati uno dopo l a l t r o
plot ( x , y1 , r , linewidth , 3)
hold on
plot ( x , y2 , r , linewidth , 3 )
axis ([ 1 1 1 1 ] )
axis ( square )
compass ( x ( 1 : 1 5 : 1 0 0 ) , y1 ( 1 : 1 5 : 1 0 0 ) ) % non consideriamo t u t t i e 100 i v e t t o r i
% ma s o l o alcuni , di 15 in 15.
compass ( x ( 1 : 1 5 : 1 0 0 ) , y2 ( 1 : 1 5 : 1 0 0 ) )
legend ( norma 1 , location , eastoutside ) % location , e a s t o u t s i d e
% pone la legenda al di f u o r i
% del g r a f i c o , a e s t
hold o f f
2 Abbiamo usato, allinterno di plot le istruzioni linewidth,3 per aumentare lo spessore delle linee (in questo caso di misura

3).

76

3.4. Norme di vettori

% normainf = max ( | x | , | y | )
% normainf =1 > max ( | x | , | y | ) = 1
% s e | x | ~= 1 > | y | ==1
y1=zeros ( 1 0 0 , 1 ) ;
y2=y1 ;
for i =1:100
i f ( abs ( x ( i ) ) ~= 1)
y1 ( i ) = 1 ;
y2 ( i )= 1;
end
end
subplot ( 3 , 1 , 2 )
plot ( x , y1 , b , linewidth , 3)
hold on
plot ( x , y2 , b , linewidth , 3)
axis ([ 1 1 1 1 ] )
axis ( square )
compass ( x ( 1 : 1 5 : 1 0 0 ) , y1 ( 1 : 1 5 : 1 0 0 ) )
compass ( x ( 1 : 1 5 : 1 0 0 ) , y2 ( 1 : 1 5 : 1 0 0 ) )
legend ( norma inf , location , eastoutside )
hold o f f
% norma2 = s q r t ( x^2+y ^2)
% norma2 =1 > s q r t ( x^2+y ^2)= 1
% > x^2 +y^2 =1 > y^2= 1x^2
y1=sqrt (1x . ^ 2 ) ;
y2=y1 ;
subplot ( 3 , 1 , 3 )
plot ( x , y1 , g , linewidth , 3)
hold on
plot ( x , y2 , g , linewidth , 3)
compass ( x ( 1 : 1 5 : 1 0 0 ) , y1 ( 1 : 1 5 : 1 0 0 ) )
compass ( x ( 1 : 1 5 : 1 0 0 ) , y2 ( 1 : 1 5 : 1 0 0 ) )
axis ([ 1 1 1 1 ] )
axis ( square )
legend ( norma 2 , location , eastoutside )
hold o f f

77

C APITOLO

Metodi iterativi per sistemi lineari


Una macchina in grado di lavorare
come cinquanta uomini comuni,
ma nessuna macchina pu svolgere
il lavoro di un uomo straordinario.
Elbert Hubbard

4.1
4.2

Metodo di Jacobi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Modificare jacobi.m per implementare gli altri metodi . . . . . . . . . . . . . . . . . . .
4.2.1 Metodo di Gauss-Seidel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.2.2 Metodo di rilassamento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Continuiamo la nostra rassegna di function di MATLAB utili per lavorare con matrici e vettori.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

79
83
83
84

norm serve anche per calcolare la norma di matrici. In particolare


G la function
norm(A) o norm(A,2) restituisce la norma 2 della matrice A;

norm(A,1) restituisce la norma 1 della matrice A;


norm(A,inf) restituisce la norma infinito della matrice A;
norm(A,fro) restituisce la norma di Frobenius o euclidea della matrice A;
la function eig applicata ad una matrice A restituisce un vettore con gli autovalori della matrice. Applicata nel modo [V,D]=eig(A) restituisce in V la matrice con gli autovettori della matrice, corrispondenti
agli autovalori che si trovano sulla diagonale della matrice diagonale D.

Possiamo vedere ora nei dettagli i metodi iterativi per sistemi lineari. Abbiamo visto che la matrice del
sistema lineare Ax = b si pu scomporre come A = L + D + U dove L la matrice triangolare inferiore, D
la diagonale e U la triangolare superiore i cui elementi sono i corrispondenti di A. In MATLAB potremmo
definire queste matrici con le seguenti righe di comandi
L= t r i l (A, 1 ) ;
D=diag ( diag (A ) ) ;
U= t r i u (A , + 1 ) ;

Questa scomposizione pu essere utile per avere, a priori, informazioni sui metodi che andremo a usare, ma
non per la loro implementazione. Vediamo nei dettagli come implementare il metodo di Jacobi

4.1 Metodo di Jacobi


Nel metodo di Jacobi, la matrice di iterazione vale E J = I D 1 A = I D 1 (L + D +U ) = D 1 (L +U ).
Lo schema dato da
x(k+1) = E J x(k) + D 1 b
x(k+1) = D 1 (L +U )x(k) + D 1 b
79

4. M ETODI ITERATIVI PER SISTEMI LINEARI

Componente per componente abbiamo


(D 1 )i i

x i(k+1) =

(Lx(k) )i
iX
1

(U x(k) )i
n
X

b i
a i j x (k)

a i j x (k)

j
j
ai i
j =i +1
j =1

per i = 1, . . . , n

Quello che faremo per implementare il metodo di Jacobi sar proprio usare questultima formula. Ciascuna componente del nuovo vettore x (k+1) sar scritto come x(i)= (b(i) sum1 sum2)/A(i,i) dove sum1
P
Pn
(k)
(k)
corrisponde a ij1
=1 a i j x j e sum2 a j =i +1 a i j x j .
Lo schema iterativo si basa sempre su un ciclo while e si proceder con le iterazioni fintantoch le iterazioni fatte sono minori di un numero massimo prefissato e (attenzione!) la norma del vettore scarto sar
maggiore di una tolleranza prefissata. Stiamo lavorando su vettori e quindi lo scarto, visto come la differenza
tra le approssimazioni a due passi successivi un vettore! Per controllare che lo scarto sia minore di una certa tolleranza, utilizziamo una misura globale, vale a dire una norma vettoriale (in genere useremo la norma
euclidea su vettori). In modo del tutto analogo a quanto fatto per gli schemi iterativi per gli zeri di funzione,
facciamo unapprossimazione della costante asintotica del metodo (che, ricordiamo, il raggio spettrale della matrice di iterazione), mediante il rapporto tra le norme degli scarti a due iterazioni successive. Useremo
questo valore, per avere una stima della velocit asintotica di convergenza R = log10 ((E )).
Vediamo, allora, la function, in modo da capire bene cosa facciamo, cosa diamo in input e cosa ci facciamo
dare in output.
%
%
%
%
%
%
%
%
%
%
%
%
%
%
%
%
%
%
%
%
%
%
%
%
%
%
%
%
%
%
%
%
%
%

function [ xnew , i t e r , scarto ]= jacobi (A , b , itmax , t o l , x0 , s t r i n g a )


function [ xnew , i t e r , s c a r t o ]= j a c o b i (A , b , itmax , t o l , x0 , s t r i n g a )
implementazione del metodo di Jacobi per r i s o l v e r e i l sistema l i n e a r e
Ax=b
dati di input
A : matrice quadrata del sistema l i n e a r e
b : v e t t o r e termine noto
itmax : numero massimo di i t e r a z i o n i da e f f e t t u a r e
t o l : t o l l e r a n z a s u l l a soluzione
x0 : v e t t o r e di approssimazione i n i z i a l e
s t r i n g a : nome del f i l e di r i s u l t a t i , da s c r i v e r e come s t r i n g a di c a r a t t e r i
esempio : s t r i n g a = r i s j a c o b i . r i s
la v a r i a b i l e s t r i n g a puo anche e s s e r e omessa e , in t a l caso ,
non viene generato nessun f i l e di r i s u l t a t i
Esempio
A=[10 3 4 ; 2 8 5 ; 7 6 1 5 ] ;
b = [ 1 7 ; 15; 2 8 ] ;
itmax =200; t o l =1. e 10;
x0= z e r o s ( 3 , 1 ) ;
[ xnew , i t e r , s c a r t o ]= j a c o b i (A , b , itmax , t o l , x0 )
s i ricava
xnew=
1.0000
1.0000
1.0000
i t e r = 121
e i l v e t t o r e s c a r t o di 121 componenti
aggiungiamo la v a r i a b i l e
stringa = risjacobi . ris ;
[ xnew , i t e r , s c a r t o ]= j a c o b i (A , b , itmax , t o l , x0 , s t r i n g a )
o l t r e ai dati di prima , viene generato i l f i l e r i s j a c o b i . r i s
da cui s i puo vedere come la stima del raggio s p e t t r a l e
s i a 8.17131760 e01 e per la v e l o c i t a di convergenza s i ha
8.77079092 e02

80

4.1. Metodo di Jacobi

m= s i z e (A ) ;
i f m(1)~=m( 2 )
error ( MATLAB:jacobi , matrice A rettangolare )
end
n=length (b ) ;
i f m(1)~=n
error ( MATLAB:jacobi , matrice e termine noto: diverse dimensioni )
end
i t e r =1;
scarto=ones ( itmax , 1 ) ;
x0=x0 ( : ) ;
xold=x0 ;
xnew=zeros (n , 1 ) ; % i n i z i a l i z z a z i o n e del v e t t o r e xnew per
% rendere piu e f f i c i e n t e l implementazione
while i t e r <=itmax && scarto ( i t e r )>= t o l
i t e r = i t e r +1;
for i =1:n
som1=A( i , 1 : i 1) * xold ( 1 : i 1);
som2=A( i , i +1:n ) * xold ( i +1:n ) ;
xnew( i ) = (b( i )som1som2) /A( i , i ) ;
end
sc=xnew xold ;
scarto ( i t e r )=norm( sc , 2 ) ;
xold=xnew ;
end
i f nargin==6
a s i n t =scarto ( 2 : i t e r ) . / scarto ( 1 : i t e r 1);
vel_conv=log10 ( a s i n t ) ;
scarto=scarto ( 2 : i t e r ) ;
i t e r = i t e r 1;
% scarto , a s i n t e vel_conv sono v e t t o r i colonna , percio l i mettiamo
% come v e t t o r i r i g a n e l l a matrice A che c i s e r v e per la stampa
A = [ [ 1 : i t e r ] ; scarto ; asint ; vel_conv ] ;
f i d =fopen ( stringa , w ) ;
f p r i n t f ( f i d , %5s %12s %12s %12s , iter , norma scarto , M , R ) ;
f p r i n t f ( f i d , \n%5d %12.8e %12.8e %12.8e , A ) ;
f p r i n t f ( f i d , \n \r ) ;
fclose ( fid ) ;
e l se
scarto=scarto ( 2 : i t e r ) ;
i t e r = i t e r 1;
end
end

I dati di input (rispetto alle function che abbiamo visto fino ad ora) possono variare: sono contemplati due
casi
Nel primo caso i dati di input sono la matrice del sistema A, il vettore termine noto b, il numero
massimo di iterazioni itmax, la tolleranza tol, lapprossimazione iniziale x0.
Nel secondo caso, aggiungiamo, ai dati precendenti una stringa che corrisponde al nome di un file di
risultati.
La function viene definita con il numero massimo di dati di input possibile. Ci accorgiamo che possibile
usare luno o laltro caso andando sulla parte finale della function dove c un ciclo if che controlla una variabile chiamata nargin. Questa variabile, per, non definita allinterno della function come accade per
iter, xold o altre variabili. Infatti nargin una function di MATLAB che, usata allinterno di una function,
dice il numero delle variabili di input della function stessa. In questo caso diciamo: se i parametri di input
sono 6 (la matrice, il termine noto, itmax, tol, x0, stringa) allora andiamo a calcolare le stime della costan-

G
G

81

4. M ETODI ITERATIVI PER SISTEMI LINEARI

te asintotica e della velocit asintotica di convergenza e questi dati, insieme alle iterazioni e alla norma degli
scarti, li salviamo su un file (il file chiamato stringa). In caso contrario (avremo quindi solo le prime 5 variabili
di input) non andremo a salvare questi dati su un file di output.
Avere o meno la sesta variabile, comporta la scrittura o meno di un file di risultati. Invece, in output
abbiamo il vettore finale che approssima la soluzione del sistema lineare, il numero effettivo delle iterazioni
effettuate e il vettore con le norme del vettore scarto. La stima della costante asintotica e della velocit di
convergenza viene stampata, se si vuole, solo sul file di risultati (e le stime sono per ogni iterazione effettuata).
La function strutturata nel modo seguente:
controlla che la matrice del sistema sia quadrata;
controlla che la dimensione della matrice sia uguale alla lunghezza del vettore termine noto
inizializza a uno, un vettore chiamato scarto in cui andremo a salvare la norma euclidea del vettore
sc. Il vettore sc rappresenta il vettore scarto tra il vettore che approssima la soluzione alliterazione
corrente meno il vettore approssimazione alliterazione precedente. Facciamo questa inizializzazione
per una maggiore efficienza dellesecuzione della function. In questo modo, la prima componente del
vettore (come le altre) vale uno, valore maggiore della tolleranza data in input;
inizializziamo a 1 la variabile che conta le iterazioni (con la convenzione che iter=1 corrisponde alliterazione 0: questo ci serve per poter dire che scarto(iter) corrisponde, formalmente, alliterazione
iter-1;
rendiamo il vettore x0, lapprossimazione iniziale, come vettore colonna (nel caso non fosse gi vettore
colonna);
introduciamo la variabile xold e la poniamo uguale a x0. xold ha il significato di vettore
approssimazione al passo precedente;
inizializziamo a zero il vettore approssimazione al passo corrente, che chiamiamo xnew (operazione,
questa, fatta per ragioni di efficienza);
parte il ciclo while con il controllo sul numero delle iterazioni e sul vettore scarto: allinterno del
ciclo while...
... si aggiorna la variabile iter
si aggiorna la variabile xnew andando a salvare in sum1 e sum2 le somme che abbiamo scritto prima: queste somme possono essere fatte in forma compatta, come vediamo dallistruzione
scritta
si scrive la formula per la componente i-sima di xnew.
si scrive il vettore scarto sc
si calcola la norma del vettore scarto, salvando il valore nella componente di posto iter del
vettore scarto
si controlla se abbiamo 6 variabili di input per fare una stima della costante asintotica (E j ) e di R,
usando il vettore degli scarti (si hanno le due variabili asint e vel_conv). Se c da fare la stampa, si
stampano sul file anche le iterazioni e le norme degli scarti. Si sistema il vettore scarto considerando i
valori effettivi degli scarti (scarto=scarto(2:iter)) e si aggiorna iter sottraendo ad esso ununit (in questo
modo non abbiamo pi quella traslazione fatta allinizio);
se invece le variabili di input non sono 6, allora sistemiamo solo il vettore scarto e la variabile iter
In uscita abbiamo quindi lultimo vettore xnew che stato approssimato (quindi il vettore che approssima il
vettore soluzione del sistema da risolvere), il numero delle effettive iterazioni, e il vettore delle norme euclidee
degli scarti. In questo modo possiamo anche fare un grafico semilogaritmico di convergenza.

G
G
G

G
G
G
G

82

4.2. Modificare jacobi.m per implementare gli altri metodi

Esercizio 4.1.1 Si provi ad implementare la function jacobi.m per risolvere il sistema Ax = b dove


4 1 0 1 0
0
0
0
0
2
1 4 1 0 1 0
1
0
0
0


0 1 4
2
0
0 1 0
0
0


1 0

1
0
4 1 0 1 0
0


A = 0 1 0 1 4 1 0 1 0
b = 0


0
1
0 1 0 1 4
0
0 1

2
0
0
1
0
0
4
1
0


0
1
0
0
0 1 0 1 4 1
0
0
0
0
0 1 0 1 4
2
La matrice viene dalla discretizzazione di unequazione alle derivate parziali che si incontra spesso in di2 u 2 u
verse applicazioni (lequazione di Poisson 2 2 = g (x, y)) mentre il termine noto stato scelto somx
y
mando gli elementi sulle righe di A in modo che la soluzione del sistema lineare sia esattamente il vettore
di tutti uno.
Si ponga il vettore iniziale x0 come il vettore di tutti zero, itmax=100, tol=1.e-10.
Si provi ad eseguire la function la prima volta senza inserire tra gli input la variabile stringa e la seconda
volta inserendo come stringa, il nome di un file di risultati (per esempio stringa=jacobi.ris e si chiama
la function come [xnew,iter,scarto]=jacobi(A,b,itmax,tol,x0,stringa) oppure direttamente si chiami la function
come [xnew,iter,scarto]=jacobi(A,b,itmax,tol,x0,jacobi.ris)) Si faccia poi il grafico di convergenza semilogaritmico. Si verifichi che il vettore xnew approssima correttamente la soluzione esatta (per esempio si
calcoli la norma euclidea dellerrore).

Esercizio 4.1.2 Considerando il sistema lineare dellesercizio precedente e usando le function di MATLAB,
si provi a scrivere la matrice di iterazione del metodo di Jacobi, si calcoli il suo raggio spettrale e si confronti
il valore ottenuto con quello stimato dalla function jacobi.m

4.2 Modificare jacobi.m per implementare gli altri metodi


A questo punto siamo pronti a implementare anche il metodo di Gauss-Seidel e di rilassamento.

4.2.1 Metodo di Gauss-Seidel


Copiamo la function jacobi.m dando il nome seidel.m (facciamo cp jacobi.m seidel.m da
una finestra di terminale).
La function che abbiamo scritta va modificata in modo da avere lalgoritmo di Gauss-Seidel. Cosa cambia?
Scriviamo la formula per la componente i -sima del vettore che approssima la soluzione al nuovo passo
iterativo (per i dettagli si rimanda alla dispensa):
#
"
iX
1
n
X
1
(k+1)
(k)
(k+1)
bi
ai j x j

ai j x j
per i = 1, . . . , n
xi
=
ai i
j =1
j =i +1
Cosa cambia rispetto alla formula scritta per Jacobi? Cosa va modificato, quindi nellalgoritmo che
implementa Gauss-Seidel?
83

4. M ETODI ITERATIVI PER SISTEMI LINEARI

Viene lasciato per esercizio, modificare la function di Jacobi per implementare in modo corretto il metodo
di Gauss-Seidel. Non va cambiato niente a parte UNA riga della function! (oltre a cambiare il nome della
function, e la scrittura jacobi con seidel dove occorre).

Esercizio 4.2.1 Si esegua la function seidel.m per risolvere lesercizio precedente.

4.2.2 Metodo di rilassamento


Questa volta copiamo la function seidel.m dando il nome del file copiato come sor.m o

rilassamento.m.
Tra i dati di input, va aggiunto il parametro . Quindi questa volta i dati di input saranno o 6 o 7:
ci significa che nel ciclo if dove si fa il controllo sul numero delle variabili di input (nargin) va fatta una
correzione!
Scriviamo la formula per la componente i -sima del vettore che approssima la soluzione al passo k + 1:
"
#
iX
1
n
X

(k+1)
(k)
(k+1)
(k)
bi
ai j x j

ai j x j
per i = 1, . . . , n
xi
= (1 )x i +
ai i
j =1
j =i +1
Cosa va modificato adesso, nella formula da implementare?

Esercizio 4.2.2 Si risolva lesercizio precedente per diversi valori di . Si confrontino, per vari valori di il
numero delle iterazioni effettuate per arrivare a convergenza.

Esercizio 4.2.3 Si provi a scrivere uno script che implementa il metodo sor per diversi valori di . Come
esempio da implementare si consideri sempre il sistema lineare considerato fino ad ora, mentre si faccia
variare tra 1 e 1.5 con incremento 0.1. La function di rilassamento va dunque chiamata allinterno di un
ciclo for o di un ciclo while. Quale dei due cicli preferibile?

Suggerimenti sulla soluzione: Si provi a implementare un ciclo for, nei modi seguenti (equivalenti)
for omega = 1 : 0 . 1 : 1 . 5
omega
end

Poi si controlli che lultimo valore di omega sia effettivamente corretto. omega <= 1.5 (si ha 1 come risposta:
quindi tutto corretto). In modo analogo, ma pi compatto, si pu scrivere
om= [ 1 : 0 . 1 : 1 . 5 ] ;
for omega=om
omega
end
om <= 1.5
omega <=1.5

84

4.2. Modificare jacobi.m per implementare gli altri metodi

Va tutto bene. Proviamo ora a scrivere un ciclo while


omega=1;
while omega <= 1.5
omega=omega+0.1
end
omega <= 1 .5

Questa volta, anche se la visualizzazione dei valori di omega ci d, come ultimo valore, 1.5000, il controllo
della proposizione logica omega <= 1.5 ci d 0: il valore non esattamente 1.5 ma un po pi grande di 1.5
(con errore di 4.4 1016 ). Ci significa che se vogliamo implementare il metodo di rilassamento, con il ciclo
while non avremo il valore di = 1.5 perch la proposizione logica sar falsa per quello che per noi 1.5. Allora cosa fare? Se vogliamo usare un ciclo while, basta scrivere la proposizione logica come while omega <= 1.501
(prendiamo un po di pi di 1.5 per essere sicuri che quel valore = 1.5 lo si prende) oppure scriviamo diversamente la formula per incrementare (lerrore che otteniamo dovuto ad errori di arrotondamento e di
conversione binaria-decimale).
i =0;
omega=1;
while omega <=1.5
i = i +1
omega= i * 0.1+1
end

Osserviamo che cos facendo, il ciclo arriva a generare anche il valore di = 1.6. In che modo, ora, richiamare
la function sor? Se usiamo un ciclo for, basta scrivere qualcosa del genere
for omega=1_0 . 1 : 1 . 5
[ output ]= sor ( input )
end

Se usiamo il ciclo while, dobbiamo chiamare la function sor prima di aggiornare la variabile omega (cos
quando arriver al valore pi grande di 1.5 si fermer nellesecuzione del ciclo e non applicher la function
sor):
omega= 1 . 0 ;
while omega <= 1.5
[ output ]= sor ( input )
omega = . . . .
end

Per salvare i dati per ogni valore di possiamo generare, allesterno della function di rilassamento, un vettore
in cui salviamo il numero delle iterazioni per arrivare a convergenza per ogni valore di e una matrice sulle
cui colonne porremo il vettore soluzione (che sar sempre lo stesso) per ogni . Se usiamo il ciclo for per
ottenere i valori di omega si pu scrivere qualcosa del genere:
om= [ 1 : 0 . 1 : 1 . 5 ] ;
m=length (om) ;
iteromega=zeros (m, 1 ) ;
SOL=zeros (n ,m) ;

%v e t t o r e in cui andremo a s a l v a r e l e i t e r a z i o n i
% f a t t e per ogni valore di omega
% matrice di n righe ( l e componenti del v e t t o r e soluzione )
% e m colonne ( t u t t i i v a l o r i di omega)

i =0;
for omega=om
i = i +1;
[ output ]= sor ( input )
iteromega ( i )= i t ;
SOL ( : , i )= x ( : ) ;
end

85

4. M ETODI ITERATIVI PER SISTEMI LINEARI

Gli altri dati (le norme degli scarti, le stime della costante asintotica, e della velocit di convergenza)
vengono stampati sul file di risultati generato allinterno della function sor: basta aprire un file di risultati
in cui i dati vengano appesi e non sovrascritti. Limportante stampare anche il valore di omega per la
simulazione effettuata. Quindi nella function sor.m le righe relative alla stampa dei dati possono essere le
seguenti
f i d =fopen ( stringa , a ) ;
f p r i n t f ( f i d , %12s %12.8g , omega = , omega ) ;
f p r i n t f ( f i d , \n \r ) ;
f p r i n t f ( f i d , %5s %12s %12s %12s , iter , norma scarto , M , R ) ;
f p r i n t f ( f i d , \n%5d %12.8e %12.8e %12.8e , A ) ;
f p r i n t f ( f i d , \n \r ) ;
fclose ( fid ) ;

Come si pu osservare, per la stampa dei dati fatta internamente alla function, rispetto alla function di Jacobi
abbiamo cambiato ben poco.

86

C APITOLO

Problemi non lineari


Un computer quasi umano, a parte
il fatto che non attribuisce i propri
errori a un altro computer.
Anonimo

5.1
5.2

Metodo di Newton per sistemi non lineari . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87


Minimi quadrati non lineari . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91

5.1 Metodo di Newton per sistemi non lineari


Affrontiamo in questa sezione lalgoritmo per risolvere sistemi di due equazioni non lineari in due
incognite, utilizzando il metodo di Newton (per la parte che riguarda la teoria si vedano le dispense).
Abbiamo un sistema di due equazioni in due incognite. In genere scriviamo il sistema come
f (x, y) = 0
g (x, y) = 0
dove f e g sono due funzioni che dipendono dalle variabili x e y (x e y variabili scalari).
Per introdurre il metodo e implementarlo, facciamo un cambio di notazione e pensiamo a vettori.
2
Pensiamo ad un punto (o vettore) nello spazio R le cui componenti sono x e y: chiamiamo queste componenti come x 1 e x 2 e il punto (o vettore) come x. Quindi x ha coordinate x 1 e x 2 e pu essere visto come un
vettore di componenti x 1 e x 2 .
Mettiamo insieme le due funzioni e abbiamo una funzione vettoriale le cui componenti sono le due funzioni stesse. Chiamiamo, cambiando notazione, f 1 e f 2 le due funzioni che dipendono quindi da x 1 e x 2 .
Possiamo scrivere f 1 (x 1 , x 2 ) o f 1 (x) (e analogamente possiamo fare per f 2 ). Quindi introduciamo la funzione
vettoriale f le cui componenti sono f 1 e f 2 . Quindi f = ( f 1 , f 2 ) e f(x 1 , x 2 ) = f(x) = ( f 1 (x), f 2 (x)).
Riprendiamo lesempio visto nella teoria:
(
9x 12 + 4x 22 36 = 0
x 12 x 2 1

=0

In questo caso abbiamo f 1 (x 1 , x 2 ) = 9x 12 + 4x 22 36 e f 2 (x 1 , x 2 ) = x 12 x 2 1. La funzione f ha dunque queste


due componenti e x il vettore di componenti x 1 , x 2 .
Possiamo visualizzare graficamente il sistema da risolvere, utilizzando in MATLAB la function ezplot.
Creiamo prima le function inline che ci danno f 1 e f 2 come funzioni di due variabili (si pu fare), poi usiamo la function ezplot che, in questo caso, ci visualizzer, nel piano [2, 2] [2, 2] tutti i punti in cui la
funzione che ha come argomento vale zero.
87

5. P ROBLEMI NON LINEARI

f = i n l i n e ( 9.*x1.^2+4*x2.^2-36 )
g= i n l i n e ( x1.^2-x2-1 )
ezplot ( f )
hold on
ezplot ( g )
hold o f f

Per implementare lalgoritmo, tuttavia, non abbiamo bisogno solo delle due funzioni del sistema da
risolvere, ma abbiamo bisogno anche della matrice Jacobiana che, valutata in un punto x(0) si scrive come

f 1 (x 1(0) , x 2(0) )

x 1
J (x(0) ) =
f 2 (x 1(0) , x 2(0) )
x 1

f 1 (x 1(0) , x 2(0) )

x 2
(0) (0)
f 2 (x 1 , x 2 )
x 2

Il metodo di Newton da implementare sintetizzato nel modo seguente:


Partire da unapprossimazione iniziale x(0)
Per k = 0, 1, 2, . . . fino a convergenza
Risolvere il sistema J (x(k) )p(k) = f(x(k) )
Porre la nuova approssimazione x(k+1) = x(k) + p(k)
Rivedendo lalgoritmo ci accorgiamo che, ad ogni passo, ci serve sia f(x(k) ) sia J (x(k) ). Allora, ci conviene
scrivere una function come M-file, che in input abbia il vettore di due componenti x e che in output ci dia sia
la funzione vettoriale f(x) sia la matrice Jacobiana.
Vediamo come scrivere la funzione vettoriale e la matrice Jacobiana dellesempio che stiamo considerando. Chiamiamo la function fun2comp.m per sottolineare che stiamo lavorando su una funzione vettoriale
che ha due funzioni componenti e due incognite.

G
G

function [ f , J f ]=fun2comp ( x )
% in input x v e t t o r e di due componenti , la prima corrisponde a x1 ,
%
la seconda a x2
% in output v e t t o r e d e l l a funzione v e t t o r i a l e valutata in x
%
quindi f e un v e t t o r e di due componenti ,
%
la prima componente corrisponde a f 1 ( x1 , x2 )
%
la seconda componente corrisponde a f 2 ( x1 , x2 )
%
J f e la matrice jacobiana valutata in x
%
l e componenti corrispondono a l l e d e r i v a t e p a r z i a l i
%
di f1 e f 2
%
J f =[ f1_x f1_y ; f2_x f2_y ]
% Esempio
% x =[1 2 ] ; % va bene anche x = [ 1 ; 2 ] ;
% [ f , J f ]=fun2comp ( x )
% f =
%
%
11
%
2
%
%
% Jf =
%
%
18
16
%
2
1
%
f = [ 9 . * x ( 1 ) . ^ 2 + 4 . * x ( 2 ) . ^ 2 3 6 . ; x (1).^2 x ( 2 ) 1 . ] ;
J f =[ 1 8 . * x ( 1 ) , 8 . * x ( 2 ) ; 2 . * x ( 1 ) , 1. ] ;
end

88

5.1. Metodo di Newton per sistemi non lineari

Osserviamo come f sia un vettore di componenti f 1 (x) e f 2 (x), mentre Jf rappresenta la matrice Jacobiana.
Per implementare il metodo di Newton, si tratta ora di estendere le nostre conoscenze sul metodo di
Newton-Raphson e la sua implementazione nel caso scalare.
Dal listato che ora vedremo, noteremo qualche differenza non solo sul fatto di usare ora dei vettori ma
anche sulle variabili usate.
Lavoriamo solo una variabile (vettore) che chiamiamo x e non su due variabili xold e xnew: questo
perch aggiorniamo ogni volta il vettore x mediante la formula x = x+p dove p
La soluzione del sistema lineare, dove la matrice del sistema la matrice Jacobiana, viene risolto usando
la function di MATLAB implementata tramite il simbolo \. il vettore soluzione del sistema lineare
con la matrice Jacobiana che corrisponde al vettore scarto (oltrech alla nuova direzione del vettore
approssimazione).
Il ciclo while controlla non solo le iterazioni e la norma del vettore scarto, ma anche la norma della
funzione vettoriale calcolata nella nuova approssimazione (un controllo in pi per vedere se ci stiamo
avvicinando a convergenza). Usiamo la norma perch la funzione vettoriale e ha due componenti.
La stampa dei valori intermedi viene fatta su un file di risultati che viene scritto allinterno del ciclo
while (questo per evitare di salvare ogni volta il vettore x andrebbe salvato su una matrice e la
norma della funzione vettoriale che non ci serve successivamente. Salviamo su vettore solo la norma
del vettore p (cio la norma del vettore scarto), in modo da poter successivamente fare il grafico di
convergenza semilogaritmico.
Viste le principali differenze/aggiunte/cambiamenti rispetto a quello che era lo schema di Newton-Raphson
per funzioni scalari, vediamo la function (che chiamiano nonlinsis2.m per dire che stiamo risolvendo
sistemi di due equazioni non lineari).

G
G
G
G

function [ x , i t e r , scarto ]= nonlinsis2 ( f , x0 , t o l , itmax , s t r i n g a )


%function [ x , i t e r , s c a r t o ]= non linsis2 ( f , x0 , t o l , itmax )
%
% dati di input : funzione v e t t o r i a l e che f o r n i s c e in output s i a la
%
funzione v e t t o r i a l e del sistema da r i s o l v e r e , s i a
%
la matrice Jacobiana l e g a t a al sistema s t e s s o
%
Questa function va s c r i t t a come m f i l e e dato in input
%
scrivendo i l nome d e l l a function t r a a p i c i
%
x0 v e t t o r e approssimazione i n i z i a l e , di due componenti
%
tol tolleranza
%
itmax numero massimo di i t e r a z i o n i
%
s t r i n g a s t r i n g a con i l nome del f i l e di r i s u l t a t i
% dati di output : x v e t t o r e che approssima la soluzione del sistema
%
i t e r numero di i t e r a z i o n i e f f e t t u a t e
%
s c a r t o v e t t o r e d e l l e norme e u c l i d e e del v e t t o r e s c a r t o
%
u t i l e per f a r e i l g r a f i c o di convergenza
% Esempio
% utilizzando la function fun2comp .m ( vedasi dispensa ) d e f i n i t a come
% function [ f , J f ]=fun2comp ( x )
% f = [ 9 . * x ( 1 ) . ^ 2 + 4 . * x ( 2 ) . ^ 2 3 6 . ; x (1).^2 x ( 2 ) 1 . ] ;
% J f =[ 1 8 . * x ( 1 ) , 8 . * x ( 2 ) ; 2 . * x ( 1 ) , 1. ] ;
% end
% dalla Command Window o da uno s c r i p t , s i eseguono l e segu en ti i s t r u z i o n i
% x0 =[1 1 ] ;
% t o l =1. e 12; itmax =100;
% stringa = sisnonlineari . ris ;
% [ x , i t e r , s c a r t o ]= nonli nsis2 ( fun2comp , x0 , t o l , itmax , s t r i n g a )
% s i ricava
% x =
%
%
1.645049516952767
%
1.706187913226531
%

89

5. P ROBLEMI NON LINEARI

%
% iter =
%
%
6
%
%
% scarto =
%
%
1.228623445541495
%
0.272914827357931
%
0.019246539508239
%
0.000111222483488
%
0.000000003759668
%
0.000000000000000
%
% viene generato i l f i l e di r i s u l t a t i ed e p o s s i b i l e f a r e i l g r a f i c o
% di convergenza
x0=x0 ( : ) ; % scriviamo i l v e t t o r e come v e t t o r e colonna per poter
% f a r e la v i s u a l i z z a z i o n e dei r i s u l t a t i nel f i l e di r i s u l t a t i
f i d =fopen ( stringa , w ) ;
f p r i n t f ( f i d , %3s %12s %12s %18s %18s \n , iter , norma scarto , ||f(x_k)|| , x1 , x2 ) ;
scarto =zeros ( itmax , 1 ) ;
scarto ( 1 ) = 2 . * t o l ;
i t e r =1;
x=x0 ;
[ fx , J x ]= f e v a l ( f , x ) ;
f p r i n t f ( f i d , %3d %12.6e %12.5e %18.16f %18.16f \n , [ i t e r scarto ( i t e r ) norm( f x ) x0 ] ) ;
% s i o s s e r v i in f p r i n t f che abbiamo s c r i t t o i l v e t t o r e x0 t r a s p o s t o
while i t e r <=itmax && scarto ( i t e r ) > t o l && norm( f x ) >eps
% s i o s s e r v i l u l t e r i o r e c o n t r o l l o s u l l a norma d e l l a funzione v e t t o r i a l e
i t e r = i t e r +1;
p= J x \ f x ;
x=x +p ;
scarto ( i t e r )=norm(p ) ;
[ fx , J x ]= f e v a l ( f , x ) ;
f p r i n t f ( f i d , %3d %12.6e %12.5e %18.16f %18.16f \n , [ i t e r 1 scarto ( i t e r ) norm( f x ) x ] ) ;
end
scarto =scarto ( 2 : i t e r ) ;
i t e r = i t e r 1;
end

A questo punto possiamo risolvere il sistema proposto, eseguendo (tramite script o sulla Command Window)
le istruzioni che troviamo nellhelp della function nonlinsis2. E possiamo risolvere tanti altri problemi,
scrivendo semplicemente la function che fornisce in output la funzione vettoriale delle equazioni del sistema
e la matrice jacobiana. Se chiamiamo questa function (per esempio) fun2.m poi andremo a chiamarla nella
nonlinsis2 inserendola come fun2 (tra apici).

90

5.2. Minimi quadrati non lineari

Esercizio 5.1.1 Si consideri il sistema


x 12 2x 1 x 2 1 = 0
x 12 + x 22 1 = 0
Si faccia il grafico delle due equazioni del sistema per capire, graficamente, la/le soluzioni del sistema stesso.
Si scriva una function dal nome funes.m da utilizzare come function di input per la nonlinsis2 per
risolvere numericamente il sistema di equazioni. Si consideri tol=1.e-12, itmax=50 e x0=[1, 1] e
successivamente x0=[-1,1]. Per ogni simulazione si veda la soluzione che si ricava e si faccia un grafico
di convergenza semilogaritmico.

5.2 Minimi quadrati non lineari


In questa sezione affrontiamo il problema di risolvere il problema ai minimi quadrati non lineare che
si incontra nellambito dellindividuazione delle coordinate di una posizione tramite il sistema GPS. Sono
date n misure d i tra un punto incognito P 0 di coordinate (x 0 , y 0 ) (il ricevitore) ed n punti noti P i (x i , y i ) (i
satelliti GPS). La distanza osservata affetta da errore e, per trovare le coordinate di P 0 si minimizza una
certa funzione (simile a quella incontrata per calcolare la retta di approssimazione ai minimi quadrati).
Poich la funzione da minimizzare non lineare, si opera una linearizzazione tramite la formula di Taylor
utilizzando un valore provvisorio di coordinate note, denotate come (x, y).
I passaggi principali da considerare sono (per le formule complete si rimanda alla dispensa di teoria):
La funzione da minimizzare

S(x 0 , y 0 ) =

n
X

(d i

(x i x 0 )2 + (y i y 0 )2 )2

i =1

non lineare in x 0 , y 0 .

G Si introduce la funzione (x, y) = p(x x) + (y y) , per i = 1, 2, . . . , n in modo che d = (x , y )+


( lerrore della misura rilevata).
G Si applica la formula di Taylor a ciascuna funzione con centro nel punto provvisorio x, y).
G In questo modo abbiamo
i

i (x 0 , y 0 ) = i (x, y) +

i (x, y)
i (x, y)
(x 0 x) +
(y 0 y)
x
y

il vettore b di componenti b = d (x, y) (dipende dalle derivate parziali di ). Si ha


G Introduciamo
(x, y)
(x, y)
i

(x 0 x) +
(y 0 y) + i .
x
y
Introduciamo il vettore = (1 , 2 , . . . , n )T e la matrice A di n righe e 2 colonne data da

1 (x, y) 1 (x, y)
(x 1 x)
(y 1 y)

(x, y) (x, y)
x
y

1
2 (x, y) 2 (x, y) (x 2 x)
(y 2 y)

x
y
2 (x, y)
= 2 (x, y)
A=

..
..
..
..

.
.
.
.

n (x, y) n (x, y) (x n x)
(y n y)

x
y
n (x, y)
n (x, y)
bi =

91

5. P ROBLEMI NON LINEARI

G In base alle formule scritte prima, esiste una relazione tra A, i vettori b e : infatti, ponendo = (x
0

x, y 0 y)T si ha

A + = b
o
= b A
P
Tornando alla funzione da minimizzare, si pu vedere che vale S(x 0 , y 0 ) = ni=1 2i = T
Poich dipende da , si pu anche scrivere, in forma matriciale, (saltiamo tutti i passaggi intermedi)
S() = bT b bT A = T A T b + T A T A
Per trovare per quale valore di la S minima, si deve imporre uguale a zero la derivata di S rispetto al vettore
, vale a dire rispetto a ciascuna componente di . Si ricava:
A T A = A T b
Risolvendo questo sistema si trova che minimizza S. E una volta ricavato , possiamo ricavare i valori x 0 e
y 0 , ricordando che = (x 0 x, y 0 y)T .
Fatta questa breve premessa, vediamo cosa dobbiamo fare in MATLAB per risolvere il problema. I dati
a disposizione saranno: le distanze osservate d i , le ascisse e le ordinate dei satelliti (per semplicit stiamo
lavorando in uno spazio bidimensionale), le coordinate del valore di riferimento provvisorio (x, y).
Vediamo la function
function [ x0 , A]= lsn ( doss , xsat , ysat , pprov ) ;
% function [ coord , A]= l s n ( doss , xsat , ysat , pprov )
% dati di input
%
doss : v e t t o r e d e l l e distanze o s s e r v a t e
%
xsat : v e t t o r e d e l l e a s c i s s e dei s a t e l l i t i
%
y s a t : v e t t o r e d e l l e corrispondenti ordinate dei s a t e l l i t i
%
pprov : punto p r o v v i s o r i o di r i f e r i m e n t o di due componenti
%
( a s c i s s a e ordinata del valore di r i f e r i m e n t o )
% dati di output
%
x0 : v e t t o r e che contiene l a s c i s s a e l ordinata del
%
punto incognito
%
A : matrice A d e l l a formula ( con l e d e r i v a t e p a r z i a l i )
% A^T A x i = A^T b con b=dossdistanza_rispetto_pprov
% x i = A^A A / A^T b
% x0= x i +pprov
% Esempio
% xsat =[7
2
1
10
5
20]
% y s a t =[ 9
7
4
15
8
15]
% pprov =[4.04 4 . 9 6 ]
% doss =[5 2.83 3.16 11.66 9.48 3 1 . 2 4 ]
% [ x0 , A]= l s n ( doss , xsat , ysat , pprov )
% restituisce
% x0=
%
3.997633885126340
%
5.001312558881406
% A=
% 0.591017363980430 0.806658834621938
%
0.707106781186548 0.707106781186548
%
0.953582665134142
0.301131367937097
% 0.510459597546841 0.859901738149376
%
0.947841163176306 0.318743046023890
%
0.769374270742105
0.638798271381548

92

5.2. Minimi quadrati non lineari

xsat=xsat ( : ) ;
ysat= ysat ( : ) ;
doss=doss ( : ) ;
pprov=pprov ( : ) ;
x=xsatpprov ( 1 ) ;
y=ysatpprov ( 2 ) ;
dcalc= sqrt ( x .^2 + y . ^ 2 ) ;
A=[ x . / dcalc y . / dcalc ] ;
tn=A * ( dossdcalc ) ; %termine noto
B=A * A ; % matrice del sistema
s o l =B\ tn ; %soluzione del sistema
x0= s o l +pprov ;
end

Come esercizio si provi a verificare lesempio fornito nella function stessa.

93

C APITOLO

Formule di integrazione numerica


Lesperienza la madre della
scienza.
Henry George Bohn (1796-1884)

6.1
6.2
6.3

Formule di quadratura numerica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95


La formula dei trapezi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
La formula di Cavalieri-Simpson . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100

6.1 Formule di quadratura numerica


Sia dato il problema di risolvere lintegrale di una funzione f (x) nellintervallo [a, b]:
Z
I=

f (x)d x
a

In MATLAB ci sono gi delle function predefinite che servono per il calcolo di un integrale. Ricordiamo le
function quad e integral per il calcolo di integrali di funzioni scalari e rimandiamo allhelp on line di MATLAB
per capire come funzionano.
Noi per vogliamo imparare a scrivere le nostre function per calcolare numericamente lintegrale di una
funzione usando i metodi che abbiamo conosciuto dalla teoria e, in particolare, applicando il metodo dei
trapezi e di Cavalieri-Simpson.
Le formule dei trapezi e di Cavalieri-Simpson sono state applicate su tutto lintervallo di integrazione:
in questo caso abbiamo parlato di formula semplice. Tuttavia, per avere accuratezza nei risultati, si preferisce applicare la formula semplice (dei trapezi o di Cavalieri-Simpson) su un certo numero di suddivisioni
dellintervallo di integrazione, sommando tutti i contributi per avere lapprossimazione finale.
Focalizziamo lattenzione sul metodo dei trapezi.

6.2 La formula dei trapezi


Chiamiamo f la funzione (inline, handle o m-file) di cui dobbiamo calcolare lintegrale. Gli estremi di
integrazione siano assegnati alle variabili a e b. La formula dei trapezi semplice si pu vedere come il risultato
della function
function [ I t r a p ] = trapsempl ( f , a , b)
% function [ I t r a p ] = trapsempl ( f , a , b )
% function per applicare la formula semplice dei t r a p e z i
% I t r a p = ( ba ) / 2 ( f ( a)+ f ( b ) )
% dati di input : f funzione da i n t e g r a r e

95

6. F ORMULE DI INTEGRAZIONE NUMERICA

Figura 6.1: Intervallo di integrazione [a, b]: ununica suddivisione, 6 suddivisioni in parti non uguali, 9
suddivisioni in parti uguali.

%
a e b estremi d e l l i n t e r v a l l o di in tegraz ione
% dati di output : I t r a p valore d e l l i n t e g r a l e con la formula dei t r a p e z i
I t r a p = f e v a l ( f , a )+ f e v a l ( f , b ) ;
I t r a p = I t r a p * ( ba ) * 0 . 5 ;
end

Abbiamo applicato la formula


IT =

ba
( f (a) + f (b))
2

Poich la formula semplice si pu vedere come caso particolare della formula composta con n = 1
suddivisione, la nostra attenzione ora si concentra sulla formula composta con m suddivisioni.
Dalla teoria, applicare la formula dei trapezi composta su m suddivisioni dellintervallo [a, b] vuol dire
applicare la formula semplice su ciascuna suddivisione e sommare i contributi di tutte le suddivisioni: infatti
il valore dellintegrale si pu vedere come la somma degli integrali su ciascuna suddivisione.
In figura 6.1 vediamo lintervallo [a, b] visto come ununica suddivisione (sul quale possiamo applicare,
quindi, la formula di integrazione semplice), oppure suddiviso in pi suddivisioni. Nellesempio ci sono 6
suddivisioni in parti non uguali e 9 suddivisioni in parti uguali.
Per semplicit costruiremo le nostre function che implementano la formula composta su un numero n di
suddivisioni in parti uguali.
Suddividiamo lintervallo [a, b] in n sottointervalli definiti dai punti dappoggio x 0 , x 1 , . . . , x n ( i punti sono
ba
equidistanti con passo h =
, in modo che x 0 = a e x n = b, x i = x 0 +i h, i = 0, . . . , n). Quindi n suddivisioni,
n
n + 1 punti da considerare: questi punti, presi a due a due, sono gli estremi dei sottointervalli.
Implementiamo la formula composta dei trapezi considerando che
Z

b
a

f (x)d x =

n Z
X

xi

f (x)d x

i =1 x i 1

Rx
Ciascun integrale xii1 f (x) viene approssimato applicando la formula semplice. Allora la function da
considerare sar la seguente
96

6.2. La formula dei trapezi

function [ I t r a p ] = trapcomposta ( f , a , b , n)
% function [ I t r a p ] = trapcomposta ( f , a , b , n)
% function per applicare la formula composta dei t r a p e z i
% I t r a p = somma d e l l a formula dei t r a p e z i semplice su ciascun
%
sottointervallo
% dati di input : f funzione da i n t e g r a r e
%
a e b estremi d e l l i n t e r v a l l o di int egrazi one
%
n numero di s u d d i v i s i o n i
% dati di output : I t r a p valore d e l l i n t e g r a l e con la formula dei t r a p e z i
% La function trapcomposta richiama al suo interno la function trapsempl
% che applica la formula semplice dei t r a p e z i .
% Esempio di applicazione
% a=0; b = 0 . 2 ;
% n=4;
% f = i n l i n e ( cos ( x ) )
% I t r a p =trapcomposta ( f , a , b , n) r e s t i t u i s c e
% I t r a p = 0.198627939626483
h=(ba ) /n ;
x0=a ;
I t r a p =0;
for i =1:n
x1=x0+h ;
I t r a p = I t r a p + trapsempl ( f , x0 , x1 ) ;
x0=x1 ;
end

function [ I t r a p ] = trapsempl ( f , a , b)
% function [ I t r a p ] = trapsempl ( f , a , b )
% function per applicare la formula semplice dei t r a p e z i
% I t r a p = ( ba ) / 2 ( f ( a)+ f ( b ) )
% dati di input : f funzione da i n t e g r a r e
%
a e b estremi d e l l i n t e r v a l l o di int egrazi one
% dati di output : I t r a p valore d e l l i n t e g r a l e con la formula dei t r a p e z i
I t r a p = f e v a l ( f , a )+ f e v a l ( f , b ) ;
I t r a p = I t r a p * ( ba ) * 0 . 5 ;
end

end

Osserviamo che al suo interno la function trapcomposta richiama la function trapsempl che implementa la formula semplice. Quello che viene fatto nella function si pu riassumere nei seguenti punti.
Dovendo suddividere lintervallo in n suddivisioni
lampiezza di ogni suddivisione data da h=(b-a)/n;
il primo estremo da considerare vale x0=a (in questa function le variabili x0 e x1 hanno il significato
di estremo inferiore ed estremo superiore del singolo sottointervallo;
si inizializza il valore approssimato dellintegrale come Itrap=0
ora si fa un ciclo for su ciascun sottointervallo (for i=1:n)
si considera il secondo estremo del sottointervallo dato da x1=x0+h
si applica la formula semplice dei trapezi e il valore ottenuto lo si aggiunge alla variabile Itrap
(in modo da sommare tutti i contributi dati da ciascun sottointervallo)
quando si passer al successivo sottointervallo quello che adesso lestremo superiore diventer
lestremo inferiore: perci si fa laggiornamento x0=x1
In questo modo applichiamo in MATLAB quello che il procedimento visto nella teoria per le formule
composte.

G
G
G
G

97

6. F ORMULE DI INTEGRAZIONE NUMERICA

Si potrebbe dire: ma se si fanno tutti i calcoli, la formula composta dei trapezi si pu scrivere in forma
compatta come
f (a) + f (b)
+ f (x 1 ) + f (x 2 ) + . . . f (x n1 )]
2
Allora perch non usare poche istruzioni MATLAB per fare tutto questo? Nella function che abbiamo scritto,
la funzione integranda viene valutata due volte nei punti interni dellintervallo [a, b], non ottimale... vero!
E difatti la function di prima pu essere sostituita dalla function
I T = h[

function [ I t r a p ] = trapcompcompatta ( f , a , b , n)
% function [ I t r a p ] = trapcompcompatta ( f , a , b , n)
h=(ba ) /n ;
x =[ a : h : b ] ;
y= f e v a l ( f , x ) ;
I t r a p =sum( y ( 2 : n ) ) ;
I t r a p = I t r a p +( y (1)+ y (n + 1 ) ) * 0 . 5 ;
I t r a p = I t r a p *h ;
end

Poche righe per avere la formula dei trapezi. Tuttavia, preferiamo continuare a lavorare con la function
iniziale, bench non ottimale, perch in questo modo ricordiamo meglio due cose (si spera):
1. la formula semplice
2. il concetto che la formula composta deriva dallapplicare la formula semplice su pi suddivisioni;
Se, al posto della function che chiama la formula semplice dei trapezi, chiamiamo unaltra function che applica la formula semplice di Cavalieri-Simpson, abbiamo gi la formula composta di Cavalieri-Simpson senza
dover ricordare la formula compatta... Dobbiamo ricordare solo le formule semplici!
Fatta questa premessa, vediamo di implementare la formula composta dei trapezi per approssimare
lintegrale di diverse funzioni.
Si considerino
i seguenti casi test (calcolando per ciascun integrale una primitiva)1
R1
1. 0 cos (x)d x
R1
2
2. 2 xe x d x
Scriviamo uno script che ci permetta di eseguire uno di questi integrali (o altri che ci verranno da scrivere)
in modo del tutto generale. Se lintegrale non si pu calcolare analiticamente, non scriveremo il valore esatto
dellintegrale. In input daremo quindi gli estremi di integrazione, la funzione integranda e una sua primitiva
(se esiste o se labbiamo calcolata) e il numero di suddivisioni per applicare la formula dei trapezi composta.
Lo script pu essere sviluppato nel modo seguente
a=input ( estremo di integrazione a ) ;
b=input ( estremo di integrazione b ) ;
f =input ( scrivi la function - inline o handle ) ;
exact=input ( conosci una primitiva della f ? si 1 no 0 ) ;
i f exact==1
F=input ( scrivi la primitiva come function inline ) ;
Iex= f e v a l ( F , b) f e v a l ( F , a ) ;
end
n=input ( # suddivisioni per la formula dei trapezi composta ) ;
I t r a p =trapcomposta ( f , a , b , n ) ;
i f exact == 1
errore=IexI t r a p ;
end

Osserviamo che, se conosciamo il valore esatto dellintegrale, calcoliamo anche lerrore esatto.

Esercizio 6.2.1 Si applichi lo script ai due casi test proposti, con n = 4 e poi n = 8: cosa succede allerrore?
R
1 Se F una primitiva di f , allora b f (x)d x = F (b) F (a). Sfrutteremo questa propriet per calcolare lintegrale esatto.
a

98

6.2. La formula dei trapezi

In questo script siamo noi a dare in input il numero di suddivisioni da applicare nella formula composta.
Potremmo per pensare di fare anche unaltra cosa. Potremmo pensare di applicare la formula dei trapezi partendo dallintervallo [a, b], poi di suddividere lintervallo in due parti uguali, e cos via: raddoppiare
ogni volta il numero di suddivisioni. Prima 1, poi 2, quindi 4, 8, 16, ... Si spera che aumentando il numero di
sottointervalli, lintegrale da approssimare abbia unaccuratezza via via maggiore (e quindi lerrore esatto sia
via via pi piccolo). Inoltre, dalla teoria, se la funzione integranda continua insieme alla derivata seconda,
1
lerrore della formula dei trapezi tende a zero come h 2 o 2 . Quindi il rapporto tra gli errori tra due suddivin
sioni successive, in queste ipotesi, tende ad un valore ben preciso (quale?). Cerchiamo di implementare tutto
questo in uno script da applicare per calcolare lintegrale di una funzione (di cui si conosca una primitiva in
modo da calcolare anche lerrore esatto), partendo da una suddivisione dellintervallo di integrazione e raddoppiando ogni volta il numero di suddivisioni fino ad arrivare ad un certo numero di suddivisioni del tipo
2ns se operiamo ns suddivisioni dellintervallo iniziale. Tenendo conto anche del valore dellintegrale ottenuto senza effettuare suddivisioni (lintervallo iniziale, che possiamo anche indicare come n = 1 suddivisione),
avremo ns + 1 valori approssimati di cui poter calcolare lerrore esatto. E degli errori possiamo calcolare i
rapporti. Scriviamo uno script dal nome trapezi.m
a=input ( estremo di integrazione a ) ;
b=input ( estremo di integrazione b ) ;
f =input ( scrivi la function - inline o handle ) ;
F=input ( scrivi la primitiva come function inline ) ;
Iex= f e v a l ( F , b) f e v a l ( F , a ) ;
ns=input ( Fino a quante suddivisioni, 2^ns vuoi arrivare? ) ;
n=1;
% applicheremo la formula dei t r a p e z i su
% 2^0 ( nessuna suddivisione e f f e t t u a t a , o
%
una suddivisione== i n t e r v a l l o di partenza :
%
formula semplice ) ,
% 2^1 ( due s u d d i v i s i o n i : dividiamo a meta l i n t e r v a l l o la
%
prima v o l t a ) ,
% 2^2 (4 s u d d i v i s i o n i : dividiamo a meta l e s u d d i v i s i o n i precedenti )
% arriviamo a 2^ns s u d d i v i s i o n i
% La procedura viene e f f e t t u a t a ns+1 v o l t e
% Quindi ricaviamo l o s t e s s o valore d e l l i n t e g r a l e , ns+1 v o l t e
I t r a p =zeros ( ns + 1 , 1 ) ;
i =0;
while m <= 2^ns
i = i +1;
I t r a p ( i )= trapcomposta ( f , a , b ,m) ;
n=n * 2 ;
end
% in i troviamo la lunghezza dei v e t t o r i
errore=IexI t r a p ;
r a t e =errore ( 1 : i 1)./ errore ( 2 : i ) ; %rapporto t r a g l i e r r o r i

99

6. F ORMULE DI INTEGRAZIONE NUMERICA

Se applichiamo questo scritp per risolvere

0.770151152934070
0.823866857412221

0.837083751352227

0.840375034027387

0.841197050636942

Itrap=
0.841402504609252
0.841453864967223

0.841466704860789

0.841469914821936

0.841470717311458
0.841470917933791

R1
0

cos (x)d x con ns = 10 ricaviamo

7.131983187382662e 02
1.760412739567518e 02

4.387233455669381e 03

1.095950780509725e 03

2.739341709541154e 04

errore=
6.848019864458266e 05
1.711984067342964e 05

4.279947107166393e 06

1.069985960278075e 06

2.674964384441481e 07
6.687410580852315e 08

4.051313096685940
4.012580496013116

4.003130007014446

4.000781562564893

4.000195332023702
rate=

4.000048829360041

4.000012206871431

4.000003052427055

4.000000771978438

4.000000227443122

Questo esempio in buon accordo con la teoria (lerrore decresce con un rapporto 4).

Esercizio 6.2.2 Si trasformi lo script trapezi in una function che riceve in input la funzione integranda
f , la funzione primitiva F , gli estremi di integrazione a e b e il numero ns (in modo da fare 1, 2, . . . , 2ns
suddivisioni). In output questa function dia i vettori Itrap, errore, rate e il valore esatto Iex. Si
chiami questa function funtrapezi.m.

Esercizio 6.2.3 Si applichi la function funtrapezi per risolvere lintegrale

R1

2 xe

x2

d x con ns = 8

6.3 La formula di Cavalieri-Simpson


A questo punto, passare dalla formula dei trapezi a quella di Cavalieri-Simpson in MATLAB qualcosa di
molto semplice (baster modificare solo la function che applica la formula semplice). Abbiamo detto che per
ora non ci interessa la formula compatta ( qualcosa che pu servire una volta che si capita bene la teoria e
se si vuole migliorare lefficienza dei programmi). Ci interessa la formula semplice e questa verr richiamata
ed applicata su ciascuna suddivisione dellintervallo [a, b] al fine di ottenere la formula composta. La formula
semplice di Cavalieri-Simpson data da
IC S =

ba
( f (a) + 4 f (c) + f (b))
6

a +b
.
2
Per implementare la formula composta di Cavalieri-Simpson, dobbiamo applicare la formula semplice su
ogni suddivisione (e di ogni sottointervallo ci servir il punto centrale).
Da ci consegue che lossatura della function trapcomposta.m rimarr essenzialmente la stessa (daremo il nome cavcomposta.m ma lidea di applicare la formula su ciascun intervallino rimane la stessa).
Ci che cambier sar la function trapsempl.m (che chiamereremo cavsempl.m) in cui dobbiamo applicare la formula di Cavalieri-Simpson. Ma i parametri di input rimarranno gli stessi (infatti, dagli estremi
dellintervallo in cui stiamo applicando la formula possiamo ricavare il punto c che ci serve, allinterno della
function).
con c =

100

6.3. La formula di Cavalieri-Simpson

Esercizio 6.3.1 Si modifichi la function trapcomposta.m dando il nome cavcomposta.m in modo


da applicare la formula di Cavalieri-Simpson composta.

Esercizio 6.3.2 Si modifichi lo script che applica la formula composta dei trapezi con n suddivisioni fissate,
in modo da poter applicare anche la formula di Cavalieri-Simpson con n suddivisioni.

Esercizio 6.3.3 Si modifichi lo script trapezi.m e la function funtrapezi.m in modo da applicare la


formula composta di Cavalieri-Simpson fino ad un certo numero ns di suddivisioni.

Esercizio 6.3.4 Si faccia una function che esegue sia la formula composta dei trapezi, sia la formula composta di Cavalieri-Simpson, in modo da poter confrontare i risultati ottenuti con i due metodi in termini di
errori e di rapporti tra errori.

101

C APITOLO

Equazioni Differenziali Ordinarie


Una volta un tale che doveva fare
una ricerca andava in biblioteca,
trovava dieci titoli sullargomento e
li leggeva; oggi schiaccia un bottone
del suo computer, riceve una
bibliografia di diecimila titoli, e
rinuncia.
Umberto Eco, La Bustina di
Minerva, 2000

7.1
7.2
7.3

Metodi per ODE . . . . . . . . . . . . . . . . . . . .


7.1.1 Confronto tra i metodi sullequazione test
I metodi . . . . . . . . . . . . . . . . . . . . . . . . .
Sistemi di equazioni differenziali . . . . . . . . . .
7.3.1 Function di MATLAB e Octave per ODE . .
7.3.2 Loscillatore semplice . . . . . . . . . . . .
7.3.3 Equazioni del moto di Keplero . . . . . . .

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

103
103
105
109
109
110
111

7.1 Metodi per ODE


Tra i metodi per la risoluzione di equazioni alle derivate ordinarie, abbiamo visto il metodo di Eulero
esplicito, di Eulero implicito e di Crank-Nicolson. Li abbiamo studiati per la soluzione di una equazione
differenziale del tipo
y 0 = f (t , y(t ))

T0 t T f

con condizione iniziale y(T0 ) = y 0 . Abbiamo detto, tuttavia, che questi metodi si possono anche applicare a sistemi di equazioni differenziali (dove non abbiamo una funzione scalare y da approssimare ma una
funzione vettoriale y).
Cerchiamo allora di capire come tradurre in MATLAB i metodi che abbiamo appena citato e come
applicarli non solo per ODE scalari, ma anche a sistemi di ODE.

7.1.1 Confronto tra i metodi sullequazione test


Nella teoria abbiamo introdotto il concetto di stabilit e abbiamo visto che il metodo di Eulero esplicito
stabile sotto condizione, mentre i metodi di Eulero implicito e di Crank-Nicolson sono stabili incondizionatamente (cio senza nessuna condizione sul passo di discretizzazione). Abbiamo preso in esame, a tale

103

7. E QUAZIONI D IFFERENZIALI O RDINARIE

scopo, lequazione test y 0 = y con condizione iniziale y(0) = y 0 . Per il parametro si ha > 0. La soluzione
esatta di questa equazione differenziale y(t ) = y 0 e t .
Fissato un passo di discretizzazione h, il metodo di Eulero esplicito, applicato allequazione test, diventa
y i +1 = y i (1 h)
Perch il metodo sia stabile, deve valere la condizione 0 < h <
Il metodo di Eulero implicito, invece, diventa
y i +1 =

yi
(1 + h)

In questo caso, riusciamo ad avere la soluzione y i +1 in maniera esplicita.


Analogamente, per il metodo di Crank-Nicolson si ha

2 h
yi
y i +1 =
2 + h
Scriviamo allora uno script che applica i tre metodi per lequazione test, da studiare nellintervallo [0, 20],
con condizione iniziale data da y 0 = 1. Daremo in input il valore di , e un passo di discretizzazione h. Verificheremo se la condizione di stabilit per lo schema di Eulero esplicito verificata, e graficamente vedremo
le curve ottenute dai vari metodi insieme alla soluzione esatta.
Chiamiamo lo script metodiode_a_confronto.m
clear
lambda=input ( valore lambda ) ;
h=input ( passo h ) ;
Tfin = 2 0 . ;
y0 =1;
f i d =fopen ( ode_a_confronto.ris , w ) ;
log=h 2/lambda <0;
i f log==1
disp ( Eulero esplicito stabile )
else
disp ( Eulero esplicito instabile )
end
t =0:h : Tfin ;
nstep=length ( t ) ;
yespl=zeros ( nstep , 1 ) ; %v e t t o r e con l e s o l u z i o n i di Eulero e s p l i c i t o
yimpl=zeros ( nstep , 1 ) ; % v e t t o r e con l e s o l u z i o n i di Eulero i m p l i c i t o
ycn=zeros ( nstep , 1 ) ;
% v e t t o r e con l e s o l u z i o n i di CrankNicolson
yex=y0 * exp(lambda * t ) ; %v e t t o r e d e l l a soluzione e s a t t a
yespl (1 )= y0 ;
yimpl (1 )= y0 ;
ycn (1)= y0 ;
for i =2: nstep
yespl ( i )= (1h * lambda ) * yespl ( i 1);
yimpl ( i )= yimpl ( i 1)/(1+h * lambda ) ;
ycn ( i )= (2h * lambda ) / ( 2 +h * lambda ) * ycn ( i 1) ;
end
plot ( t , yex , k , linewidth ,2 )
hold on
plot ( t , yespl , b , linewidth , 2 )
plot ( t , yimpl , r , linewidth , 2 )
plot ( t , ycn , g , linewidth , 2 )
legend ( soluzione esatta , Eulero esplicito , Eulero implicito , Crank-Nicolson )
hold o f f
f p r i n t f ( f i d , Valore di lambda per lequazione test %12.6g , lambda ) ;

104

7.2. I metodi

f p r i n t f ( f i d , \n%5s %12s %12s %12s %12s , tempo , sol. esatta , Eul. espl. , Eul. impl. , Crank-Nic. ) ;
f p r i n t f ( f i d , \n%5.2f %12.6e %12.6e %12.6e %12.6e , [ t , yex , yespl , yimpl , ycn ] ) ;
fclose ( fid ) ;

Sia dal grafico che dai risultati nel file ode_a_confronto.ris possiamo vedere le differenze tra i vari
metodi.

Esercizio 7.1.1 Si esegua lo script metodiode_a_confronto.m per i seguenti valori


1. = 1, h = 0.5
2. = 1, h = 2
3. = 1, h = 0.1
4. = 0.5, h = 1
5. = 0.5, h = 0.1
6. = 0.2, h = 1.0
7. = 0.2, h = 0.1

7.2 I metodi
Vediamo ora come implementare questi metodi per ODE pi generali.
Lalgoritmo di Eulero esplicito quello pi semplice da implementare.
Supponiamo, per il momento, di dover risolvere una ODE del tipo y 0 = f (t , y(t )) con f funzione scalare.
Oltre alla funzione dellequazione test, abbiamo visto f (t , y(t )) = y + t oppure f (t , y(t )) y 2 ... la funzione f pu essere scritta in MATLAB come una funzione che dipende da t e da y (per semplicit, la definiamo
come dipendente da due variabili anche se pu dipendere solo da una delle due). Per far ci definiamo la funzione come funzione di tipo handle: scriviamo il nome della funzione, poi a destra del segno di uguaglianza
scriviamo il simbolo @ e tra parentesi le variabili t,y, quindi la funzione.
f =@( t , y ) y+ t ;
f =@( t , y ) y . ^ 2 ;

Introduciamo altre variabili: Tiniziale e Tfinale che rappresentano lintervallo in cui vogliamo
studiare lequazione differenziale, y0 la condizione iniziale, h il passo di discretizzazione.
Sottolineiamo il fatto che, in genere, nei metodi per ODE il passo di discretizzazione viene fatto variare
(si parla di adattivit) seguendo determinati criteri che permettono di arrivare alla soluzione approssimata
in un minor numero di passi, rispetto allo stesso problema risolto con un passo di discretizzazione costante.
Noi non operiamo questa scelta, perch richiederebbe spiegazioni di tipo teorico che vanno al di l del corso
di base di Calcolo Numerico. Vedremo, comunque, che le function di MATLAB che risolvono ODE utilizzano
tutte delle tecniche di adattivit del passo di discretizzazione.
Fatta questa premessa, ricordiamo la formula del metodo di Eulero esplicito
y i +1 = y i + h f (t i , y i )
Il metodo pu essere implementato nel modo seguente:
function [ t , y ]= e u l e r o e s p l i c i t o ( f , y0 , T i n i z i a l e , Tfinale , h)
%function [ t , y ]= e u l e r o e s p l i c i t o ( f , y0 , T i n i z i a l e , Tfinale , h)
% dati di input :
%
f funzione d e l l equazione d i f f e r e n z i a l e y = f ( t , y ( t ) )
%
di t i p o handle
%
s e e di t i p o v e t t o r i a l e , deve e s s e r e data come
%
funzione colonna
%
y0 condizione i n i z i a l e

105

7. E QUAZIONI D IFFERENZIALI O RDINARIE

%
T i n i z i a l e tempo i n i z i a l e
%
T f i n a l e tempo f i n a l e
% dati di output :
%
t v e t t o r e dei tempi
%
y v e t t o r e d e l l e s o l u z i o n i approssimate
%
%
%
t = T i n i z i a l e : h : T f i n a l e ; % v e t t o r e dei tempi
nstep=length ( t ) ; % nstep 1 e i l numero di p a s s i t o t a l i che saranno e f f e t t u a t i
y0=y0 ;
m=length ( y0 ) ;
% lunghezza del v e t t o r e condizione i n i z i a l e
y=zeros (m, nstep ) ;
y ( : , 1 ) = y0 ;
for i =2: nstep
y ( : , i )= y ( : , i 1)+h * f e v a l ( f , t ( i 1) , y ( : , i 1 ) ) ;
end
y=y ; %i l v e t t o r e d e l l e s o l u z i o n i approssimate l o s i rende come v e t t o r e
% di nstep+1 righe e m colonne per uniformita r i s p e t t o a l l e
% function di MATLAB che r i s o l v o n o ODE
end

Per poter eseguire questo script, possiamo ad esempio, dare i dati


f =@( t , y ) y+ t ;
y0 =1;
T i n i z i a l e =0;
T f i n a l e =2;
h= 0 . 0 1 ;
[ t , y ]= e u l e r o e s p l i c i t o ( f , y0 , T i n i z i a l e , Tfinale , h ) ;

In questo caso, sapendo che la funzione esatta vale fex=@(t) t-1+2*exp(-t), possiamo calcolare i
valori della soluzione esatta negli stessi punti del vettore t e fare il grafico che mette a confronto soluzione
esatta e soluzione approssimata.
yex= f e v a l ( fex , t ) ;
plot ( t , y , t , yex ) ;
legend ( soluzione approssimata , soluzione esatta )

Per applicare lo schema di Eulero implicito, invece, dobbiamo fare pi attenzione. Nello script sullequazione test y 0 = y abbiamo sfruttato la linearit della f per poter esplicitare le approssimazioni y i +1 .
Ricordiamo la formula del metodo:
y i +1 = y i + h f (t i +1 , y i +1 ))
Se la funzione f dipende in modo non lineare da y allora il metodo resta implicito. Potremmo scrivere, allora,
due tipi di function, una per risolvere equazioni differenziali in cui si riesce a esplicitare y i +1 (come nel caso
dellequazione test), quando la funzione f del problema lineare rispetto a y, e unaltra function per risolvere
problemi in cui la f non lineare.
Potremmo farlo, ma visto che ci serve capire come funziona lo schema nel caso pi generale, lo pensiamo
come schema implicito. Come facciamo allora a trovare y i +1 se dipende da y i +1 stesso? Abbiamo visto dalla
teoria, che possiamo ricondurci ad uno schema di punto fisso o di ricerca di zeri di funzione. Lo schema pi
semplice da applicare quello di punto fisso ed proprio quello che faremo.1 Dato il valore y i , per ricavare
y i +1 , la formula da applicare si pu leggere come lo schema di punto fisso
y i +1 = g (t i +1 , y i +1 )
1 Sicuramente va meglio applicare uno schema di tipo Newton-Raphson o secante variabile. Non lo facciamo per ragioni di
semplicit. Vogliamo solo capire come si risolvono questi metodi di tipo implicito.

106

7.2. I metodi

dove g (t , y) = y i + h f (t , y). Si pu partire da un punto iniziale x 0 = y i e poi iterare lo schema iterativo fino a
che non si trova unapprossimazione del punto fisso della funzione g che altro non che unapprossimazione
di y i +1 . Il valore appena trovato per y i +1 diventer il valore iniziale x 0 per fare partire di nuovo lo schema di
punto fisso e trovare la successiva approssimazione y i +2 , e cos via. La function che scriviamo sar:
function [ t , y ]= e u l e r o i m p l i c i t o ( f , y0 , T i n i z i a l e , Tfinale , h)
%function [ t , y ]= e u l e r o i m p l i c i t o ( f , y0 , T i n i z i a l e , Tfinale , h)
% dati di input :
%
f funzione d e l l equazione d i f f e r e n z i a l e y = f ( t , y ( t ) )
%
di t i p o handle
%
s e e di t i p o v e t t o r i a l e , deve e s s e r e data come
%
funzione colonna
%
y0 condizione i n i z i a l e
%
T i n i z i a l e tempo i n i z i a l e
%
T f i n a l e tempo f i n a l e
% dati di output :
%
t v e t t o r e dei tempi
%
y v e t t o r e d e l l e s o l u z i o n i approssimate
%
%
%
t=Tiniziale : h : Tfinale ;
nstep=length ( t ) ;
y0=y0 ;
m=length ( y0 ) ;
y=zeros (m, nstep ) ;
y ( : , 1 ) = y0 ;
for i =2: nstep
x0=y ( : , i 1); %punto i n i z i a l e per l o schema di punto f i s s o
scarto =2;
% valore i n i z i a l e d e l l o s c a r t o
i t =0;
% contatore d e l l e i t e r a z i o n i per l o schema di punto f i s s o
while scarto >=1.e6 && i t <=10
i t = i t +1;
xk=y ( : , i 1)+h * f e v a l ( f , t ( i ) , x0 ) ; % schema di punto f i s s o
scarto=norm( xkx0 ) ;
% s c a r t o t r a due approssimazioni s u c c e s s i v e
x0=xk ;
end
i f scarto >=1.e6 && i t ==10
error ( EuleroImplicito , warning nel punto fisso )
end
y ( : , i )= xk ; % nuova approssimazione dallo schema di punto f i s s o
end
y=y ;
end

Nello schema di punto fisso abbiamo considerato una tolleranza sulla soluzione pari a 106 e un numero
massimo di iterazioni pari a 10. Abbiamo messo un segnale di avvertimento nel caso in cui lo schema di
punto fisso non converge. Sottolineiamo che lo schema di punto fisso potrebbe non convergere, ma per
valori di h sufficientemente piccoli, lo schema converge e riusciamo ad avere una buona approssimazione
per la soluzione numerica.
Se, invece, usiamo questa function per studiare la stabilit del metodo applicandola allequazione test
y 0 = y vedremo che, per valori di h grandi, non avremo convergenza in quanto lo schema di punto fisso non
converger. Nel caso di Eulero implicito infatti, per lequazione test ora indicata, si ha y i +1 = y i h y i +1 . Se
consideriamo la funzione di punto fisso g (y) = y i h y vediamo che g 0 (y) = h. Perci per valori di h > 1 lo
schema non converge e quindi non otteniamo neanche i valori dello schema di Eulero implicito. In questo
caso, sarebbe preferibile applicare lo schema di Newton-Raphson perch avremmo i risultati corretti. Come
abbiamo detto, comunque, la scelta di applicare lo schema di punto fisso esclusivamente di tipo didattico.
107

7. E QUAZIONI D IFFERENZIALI O RDINARIE

Per problemi pi difficili, comunque, useremo passi di discretizzazione sufficientemente piccoli e tali che lo
schema di punto fisso andr bene. Perci, lasciamo il punto fisso come metodo che approssima la nuova
approssimazione.
Gli stessi discorsi valgono anche per lo schema di Crank-Nicolson, la cui formula data da
y i +1 = y i +

h
f (t i , y i ) + f (t i +1 , y i +1 )
2

Per implementare lo schema, ci serviamo ancora del metodo di punto fisso, applicato ora alla funzione di
punto fisso
g (t , y) = y i +

h
f (t i , y i ) + f (t , y)
2

La function che ricaviamo


function [ t , y ]= cranknicolson ( f , y0 , T i n i z i a l e , Tfinale , h)
%function [ t , y ]= cranknicolson ( f , y0 , T i n i z i a l e , Tfinale , h)
% dati di input :
%
f funzione d e l l equazione d i f f e r e n z i a l e y = f ( t , y ( t ) )
%
di t i p o handle
%
s e e di t i p o v e t t o r i a l e , deve e s s e r e data come
%
funzione colonna
%
y0 condizione i n i z i a l e
%
T i n i z i a l e tempo i n i z i a l e
%
T f i n a l e tempo f i n a l e
% dati di output :
%
t v e t t o r e dei tempi
%
y v e t t o r e d e l l e s o l u z i o n i approssimate
%
%
%
t=Tiniziale : h : Tfinale ;
nstep=length ( t ) ;
y0=y0 ;
m=length ( y0 ) ;
y=zeros (m, nstep ) ;
y ( : , 1 ) = y0 ;
for i =2: nstep
x0=y ( : , i 1);
scarto =2;
i t =0;
fm= f e v a l ( f , t ( i 1) , y ( : , i 1 ) ) ; %valore d e l l a f a l l approssimazione
% i 1
% s e r v e n e l l o schema di CrankNicolson
while scarto >=1.e6 && i t <=10
xk=y ( : , i 1)+0.5 * h * (fm+ f e v a l ( f , t ( i ) , x0 ) ) ;
scarto=norm( xkx0 ) ;
x0=xk ;
end
i f scarto >=1.e6 && i t ==10
error ( CrankNicolson , warning nel punto fisso )
end
y ( : , i )= x0 ;
end
y=y ;
end

108

7.3. Sistemi di equazioni differenziali

Notiamo come lo schema sia stato implementato in modo del tutto analogo allo schema di Eulero implicito.
Valgono perci le stesse considerazioni fatte rispetto allo schema di punto fisso applicato.
Ora, alla stessa maniera con cui abbiamo eseguito il metodo di Eulero esplicito, possiamo vedere i risultati
che si ottengono con gli altri due metodi (Eulero implicito e Crank-Nicolson).

7.3 Sistemi di equazioni differenziali


Ci che abbiamo detto sulle equazioni differenziali scalari, valgono anche per sistemi di equazioni differenziali. Lo schema si applica componente per componente, per le singole equazioni che compongono il
sistema. Per i metodi impliciti, lo schema di punto fisso sar applicato sulle singole equazioni (se si vanno a
rivedere le function sul metodo di Eulero implicito e di Crank-Nicolson, si pu notare che il controllo della
convergenza dello schema di punto fisso stato fatto calcolando la norma euclidea che coincide con il valore assoluto nel caso di quantit scalari in modo che la function possa andare bene anche per sistemi di
equazioni!)
In tutte le function che abbiamo scritto, inoltre, abbiamo considerato la lunghezza della variabile che
contiene la condizione iniziale (per capire se stiamo lavorando su quantit scalari o su vettori).

7.3.1 Function di MATLAB e Octave per ODE


Ci sono tante function sviluppate in MATLAB (solo in MATLAB per) per risolvere equazioni differenziali.
Tra queste ricordiamo

G ode45
G ode23

Come parametri di base in input occorre dare, nellordine, la function handle dellequazione differenziale, un
vettore che contiene i valori T0 e T f in cui risolvere lequazione differenziale e la condizione iniziale y 0 . La
funzione deve essere data come vettore colonna nel caso in cui ci sia un sistema di ODE. La function (ode45
o ode23) restituisce il vettore dei tempi e delle soluzioni approssimate.
Per gli esempi precedenti, dobbiamo quindi scrivere listruzione [t ,y]=ode45(f,[Tiniziale, Tfinale], y0); per
poter risolvere lequazione differenziale con la function ode45 (analogamente si far per ode23).
Facendo un help di queste function, MATLAB ci rimanda a tantissime altre function, tutte utili per
risolvere ODE.
In Octave, tra le function da ricordare per risolvere equazioni differenziali, troviamo la lsode, la cui sintassi
diversa da quelle di MATLAB e da quelle che abbiamo costruito fino ad ora. La sintassi di base cambia un
po. Abbiamo infatti
[y,stato,messaggio]=lsode(f,y0,t)

dove f una function (inline o handle) che deve avere la forma yd=f(y,t) (notiamo linversione di ordine nelle
variabili di input), con t scalare e y,yd vettori (o scalari a seconda della funzione). La funzione da dare in input
(per problemi complicati) pu essere costituita come stringa di due function handle, in cui la prima componente data dalla funzione f dellequazione differenziale e la seconda componente data dalla funzione che
contiene la matrice la matrice Jacobiana, scritta nella forma JAC=j(y,t). Per questi casi, in input, daremo una
function del tipo F={f, j } (si osservino le parentesi graffe che definiscono una stringa di function). Nei nostri
problemi, tuttavia, non useremo la matrice Jacobiana e quindi bisogna prestare attenzione solo a scrivere la
function f con le variabili invertite e a seguire la sintassi, (come vedremo nellesempio).
Il parametro y0 rappresenta la condizione iniziale, mentre t il vettore dei tempi, in cui la prima
componente il tempo iniziale e le altre componenti sono gli istanti di tempo in cui si vuole risolvere il
problema.
In uscita, stato vale 2 se la function stata eseguita con successo, altrimenti si ha un valore diverso da 2.
La variabile messaggio contiene informazioni aggiuntive.
Vediamo un esempio: dallequazione y 0 = y 2 , lo script da lanciare sar
f =@( y , t ) y . ^ 2 ;
y0 =1;
T i n i z i a l e =0;

109

7. E QUAZIONI D IFFERENZIALI O RDINARIE

T f i n a l e =10;
t=Tiniziale : h : Tfinale ;
[ y , i s t a t e , messaggio ]= lsode ( f , y0 , t ) ;

7.3.2 Loscillatore semplice


Un esempio che ci porta ad un sistema di equazioni differenziali dato dal modello costituito da massamolla-smorzatore. Se si vuole studiare levoluzione dinamica del sistema (vale a dire la posizione e la velocit
della massa m) al variare di alcuni parametri (lo smorzamento e lelasticit della molla) in presenza o meno
di una forza esterna F (t ), si ottiene unequazione differenziale data da
m

d x(t )
d 2 x(t )
+c
+ kx(t ) = F (t )
dt2
dt

dove x(t ) rappresenta lo spostamento della massa m dalla posizione di equilibrio,

d x(t )
la sua velocit,
dt

d 2 x(t )
rappresenta la sua accelerazione. I valori m, c e k rappresentano la massa, il coefficiente di
dt2
smorzamento e la costante elastica della molla, rispettivamente.
Scriviamo diversamente lequazione come

mentre

F (t ) c

d 2 x(t )
=
dt2

d x(t )
kx(t )
dt
m

Per passare da questa equazione differenziale del secondo ordine (perch compare una derivata seconda)
ad un sistema di equazioni differenziali del primo ordine, si fanno le seguenti trasformazioni. Si introduce il
dx
vettore y = (y 1 , y 2 ) tale che y 1 = x e y 2 =
. Allora (usiamo il simbolo 0 per indicare la derivata rispetto a t ).
dt
y 10 = x 0 =
y 20

dx
= y2
dt

d x(t )

F (t ) c
kx(t )
d dx
d 2 x(t )
F (t ) c y 2 k y 1
dt
=
=
=
=
2
dt dt
dt
m
m

Abbiamo quindi il sistema


y0 = f(t , y)
dove f(t , y) una funzione vettoriale di due componenti:

y2
f(t , y) = F (t ) c y 2 k y 1
m
Possiamo introdurre una function handle di questo tipo (specificando i vari parametri) da applicare alle
nostre funzioni che risolvono ODE o alle function di MATLAB/Octave per risolvere ODE. Ad esempio, per
m = 1kg , k = 10N /m, c = 0.5N s/m e F (t ) = 0N e dando come condizione iniziale (sullo spostamento e sulla
sua velocit) x(0) = 1m x 0 (0) = 0m/s possiamo scrivere,
k =10; c = 0 . 5 ; m=1;
f =@( t , y ) [ y ( 2 ) ; (k * y(1) c * y ( 2 ) ) /m] ;

110

%scriviamo una funzione v e t t o r i a l e


% come v e t t o r e colonna
% come s e r v e anche per l e function
% proprie di MATLAB

7.3. Sistemi di equazioni differenziali

y0 = [ 1 ; 0 ] ;
h= 0 . 0 1 ;
T i n i z i a l e =0;
T f i n a l e =60;
[ tespl , yespl ]= e u l e r o e s p l i c i t o ( f , y0 , T i n i z i a l e , Tfinale , h ) ;
[ timpl , yimpl ]= e u l e r o i m p l i c i t o ( f , y0 , T i n i z i a l e , Tfinale , h ) ;

Possiamo confrontare i due metodi, oppure applicare la function ode45 o altre ancora... Se vogliamo applicare
in Octave la function lsode scriveremo invece
k =10; c = 0 . 5 ; m=1;
f =@( y , t ) [ y ( 2 ) ; (k * y(1) c * y ( 2 ) ) /m] ;
y0 = [ 1 ; 0 ] ;
h= 0 . 0 1 ;
T i n i z i a l e =0;
T f i n a l e =60;
t=Tiniziale : t : Tfinale ;
[ y , i s t a t e , messaggio ]= lsode ( f , y0 , t ) ;

Come grafici, possiamo fare un grafico in cui mettiamo sullasse delle ascisse il vettore dei tempi e sullasse
delle ordinate i due valori di spostamento e velocit che abbiamo ottenuto. Basta scrivere (ad esempio per
Eulero esplicito)
plot ( tespl , yespl )

Possiamo anche fare un grafico in cui vediamo come varia la velocit in funzione dello spostamento con
listruzione plot(yespl (:,1), yespl (:,2)) (si parla di piano delle fasi in questo caso).

7.3.3 Equazioni del moto di Keplero


La legge di gravitazione universale di Newton dice che due corpi si attraggono con una forza direttamente
proporzionale alle loro rispettive masse m 1 e m 2 e inversamente proporzionale al quadrato della distanza |r |
(inteso come norma euclidea del vettore distanza) tra essi:
F =G

m1 m2
|r |2

Nella formula G rappresenta la costante gravitazionale, G = 6.67 1011 m 3 K g 1 s 2 .


In un sistema di due corpi (pensiamo a due pianeti), la forza di attrazione del secondo corpo agisce sul
primo di massa m 1 e la forza del primo corppo agisce sul secondo di massa m 2 . Entrambe le forze sono uguali
e dirette lungo la direzione r tra i due corpi (con versi opposti).
Ci significa che, rispetto ad un sistema di riferimento in cui r1 e r2 rappresentano la distanza dei due
corpi rispetto allorigine del sistema di riferimento, vale r = r2 r1 . Applicando la seconda legge di Newton
F = ma (Forza=massa per accelerazione) per ogni corpo, e considerando che per laccelerazione si ha a i =
d 2 ri
, otteniamo
dt2
m1

d 2 r1
m1 m2
=G
r,
dt2
|r |3

m2

d 2 r2
m1 m2
= G
r
dt2
|r |3

Abbiamo considerato, a destra, il vettore unitario che d la direzione della forza, dato da
e sottraendo abbiamo

r
. Semplificando
|r |

d 2 r2 r1
m1 + m2
= G
r
2
dt
|r |3
cio
d 2r
m1 + m2
= G
r
2
dt
|r |3
111

7. E QUAZIONI D IFFERENZIALI O RDINARIE

Nel caso in cui i due pianeti siano il sole e la terra, poich la massa del sole 333000 volte pi grande
della massa della terra, si considera solo il prodotto Gm sol e : questa quantit prende il nome di costante
gravitazionale geocentrica della Terra e si indica con G M . Lequazione del moto della Terra attorno al sole si
pu quindi vedere come
GM
d 2r
= 3 r
dt2
|r |
Abbiamo unequazione alle derivate ordinarie, vettoriale, del secondo ordine perch compare la derivata
d 2r
.
seconda
dt2
Per rendere il problema pi semplice, si pu scegliere un sistema di riferimento in cui la quantit G M non
sia n troppo grande n troppo piccola. Per descrivere lorbita della Terra, si pone la convenzione di definire
come unit di lunghezza il semiasse maggiore dellorbita della terra. Questa unit di lunghezza si chiama
unit astronomica (AU) e vale
1AU = 1.496 1011 m
Come unit di tempo si considera lanno (o 3.15 107 s). In queste unit, il periodo (per compiere un intero
giro attorno al sole) per la Terra vale T = 1 anno e il suo semiasse maggiore vale a = 1AU . In questo sistema
abbiamo
GM =

42 a 3
= 42 AU 3 /anni 2
T2

Studiando questa equazione differenziale nel caso pi semplice (vale a dire considerando il vettore distanza come un vettore nello spazio bidimensionale), abbiamo unequazione differenziale di secondo grado
da ridurre ad un sistema di equazioni differenziali del primo ordine. Si consideri allora il vettore che ha come
componenti il vettore r = (r x , r y ) e il vettore velocit di v di componenti (v x , v y ). Introduciamo il vettore y
fatto in questo modo: y = (y 1 , y 2 , y 3 , y 4 ) = (r x , r y , v x , v y ) Allora

vx
y3
v
y

y1
y
4

y2 G M G M

y0 =
=
=

r
y

x
1
y 0
|r |3 |r |3
3
GM GM
y 40
3 ry
3 y2
|r |
|r |

Abbiamo trovato le equazioni del sistema (dette anche equazioni di Keplero). Poich |r | =
q
y 12 + y 22 , in MATLAB scriveremo (usiamo le unit astronomiche):
GM=4 * pi ^2;
f =@( t , y ) [ y ( 3 ) ; y ( 4 ) ; GM* y ( 1 ) / sqrt ( y (1)^2+ y ( 2 ) ^ 2 ) ^ 3 ;
GM* y ( 2 ) / sqrt ( y (1)^2+ y ( 2 ) ^ 2 ) ^ 3 ] ;

q
r x2 + r y2 =

...

p
Come condizione iniziale consideriamo r x = 1, r y = 0, v x = 0 e v y = G M (dalle leggi gravitazioniali vale
s
GM
infatti per la velocit |v| =
). Eseguiremo, quindi le seguenti righe di codice (usiamo, questa volta, il
|r |
metodo di Crank-Nicolson) che ci permettono di risolvere lequazione e fare diversi grafici:
GM=4 * pi ^2;
f =@( t , y ) [ y ( 3 ) ; y ( 4 ) ; GM* y ( 1 ) / sqrt ( y (1)^2+ y ( 2 ) ^ 2 ) ^ 3 ;
y0 =[1 0 0 sqrt (GM) ] ;
T i n i z i a l e =0;
T f i n a l e = 1 . 0 ; %anno
h= 1 . / 3 6 5 ;

112

GM* y ( 2 ) / sqrt ( y (1)^2+ y ( 2 ) ^ 2 ) ^ 3 ] ;

7.3. Sistemi di equazioni differenziali

[ t , y ]= cranknicolson ( f , y0 , T i n i z i a l e , Tfinale , h ) ;
figure ( 1 )
plot ( t , y ( : , 3 ) , t , y ( : , 4 ) ) % v e l o c i t a e a c c e l e r a z i o n e al v a r i a r e del tempo
figure ( 2 )
plot ( y ( : , 1 ) , y ( : , 2 ) ) % l o r b i t a d e l l a Terra ( rx , ry )
figure ( 3 )
plot ( y ( : , 3 ) , y ( : , 4 ) ) % v e l o c i t a e a c c e l e r a z i o n e

Uno script completo per eseguire tutti questi esempi con i vari metodi proposti scaricabile sul sito delle
dispense dispense.dmsa.unipd.it/mazzia con nome scriptODE.m.

113

Potrebbero piacerti anche