Sei sulla pagina 1di 25

Calcolo Numerico in Python

Fabio Marcuzzi, Maria Rosaria Russo


Dipartimento di Matematica Pura ed Applicata
Universita di Padova
Italy
email: marcuzzi@math.unipd.it, mrrusso@math.unipd.it

Versione 3.0
6 Giugno 2005

F.Marcuzzi - M.R.Russo

Contents
1 Introduzione

1.1

Sviluppo di programmi in Python . . . . . . . . . . . . . . . . . . . . . . .

1.2

Documentazione su Python . . . . . . . . . . . . . . . . . . . . . . . . . .

1.3

Moduli aggiuntivi per il calcolo scientifico

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

2 Modalit
a di esecuzione dei programmi scritti in Python

2.1

Caricamento di Moduli aggiuntivi (import e reload) . . . . . . . . . . . .

2.2

Lavorare con la shell interattiva di Python . . . . . . . . . . . . . . . . . .

2.2.1

Ripetizione dei comandi . . . . . . . . . . . . . . . . . . . . . . . .

2.2.2

Interazione con le directories . . . . . . . . . . . . . . . . . . . . . .

2.2.3

Help in linea . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3 Presentazione sintetica del Linguaggio

3.1

Tipi di dato . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3.2

Istruzioni composte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.2.1

La decisione if-then-else . . . . . . . . . . . . . . . . . . . . . . . . 10

3.2.2

Il ciclo for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

3.2.3

Il ciclo while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

3.3

Funzioni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

3.4

I/O da file e da schermo . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

3.5

3.4.1

I/O da file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

3.4.2

I/O da schermo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

misura dei tempi di esecuzione . . . . . . . . . . . . . . . . . . . . . . . . . 13

4 Operazioni con Vettori e Matrici


4.1

4.2

14

Basic Linear Algebra Subroutines (BLAS) e progetto ATLAS . . . . . . . . 16


4.1.1

Operazioni di tipo BLAS 1 . . . . . . . . . . . . . . . . . . . . . . . 16

4.1.2

Operazioni di tipo BLAS 2 . . . . . . . . . . . . . . . . . . . . . . . 17

4.1.3

Operazioni di tipo BLAS 3 . . . . . . . . . . . . . . . . . . . . . . . 17

Matrici Sparse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
4.2.1

Operazioni implementate in modo dedicato per il formato LL . . . . 18

4.2.2

Operazioni implementate in modo ottimizzato per il formato CSR


ed SSS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

Calcolo Numerico in Python

5 Creazione di Grafici

19

5.1

Grafici bi-dimensionali . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

5.2

Grafici tri-dimensionali . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

5.3

Immagini . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

6 Libreria di Algebra Lineare Numerica

22

6.1

Interfaccia di Numeric alla LAPACK . . . . . . . . . . . . . . . . . . . . . 22

6.2

Soluzione di sistemi lineari con matrice sparsa . . . . . . . . . . . . . . . . 22

7 Libreria per la soluzione di Equazioni Nonlineari

22

8 Libreria per lInterpolazione ed Approssimazione di funzioni e di dati

22

8.1

Interpolazione polinomiale . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

8.2

Approssimazione ai Minimi Quadrati Discreti . . . . . . . . . . . . . . . . 23

9 Libreria per lIntegrazione Numerica

24

10 Libreria per la soluzione di Problemi ai Valori Iniziali

24

11 Libreria per la soluzione di Problemi ai Limiti

24

12 Libreria per la Geometria Computazionale

24

13 Programmazione ad Oggetti in linguaggio Python

24

13.1 Classi e Oggetti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24


13.1.1 Esempio: la classe Matrice . . . . . . . . . . . . . . . . . . . . . . . 25

F.Marcuzzi - M.R.Russo

Introduzione

Python e un linguaggio di scripting ad oggetti. Come proprieta fondamentale, consente


la tipizzazione dinamica (dynamic typing), cioe:
1. riconosce automaticamente oggetti quali numeri, stringhe, liste, ..., e quindi non
richiede di dichiararne il tipo e la dimensione prima dellutilizzo;
2. effettua in modo automatico lallocazione e la gestione della memoria.
Questa caratteristica, presente in ambienti come il Matlab, contribuisce in modo
sostanziale a velocizzare la prototipazione di algoritmi di calcolo numerico.
Python e disponibile al sito www.python.it (www.python.org e il sito internazionale).
u
La versione a cui facciamo qui riferimento e dalla 2.3.4 in poi (in questo momento la pi
recente e la 2.4.1 ).
1.1

Sviluppo di programmi in Python

Lesecuzione di programmi scritti in Python avviene tramite la sua shell interattiva, che
viene semplicemente invocata con il comando python, sia in Linux che in DOS/Windows.
In generale, e utile dotarsi di unIDE (Integrated Development Environment, ovvero
un ambiente di sviluppo integrato). A questo proposito ci sono varie soluzioni. UnIDE
disponibile per Linux e Windows e Eclipse, per la quale e disponibile un plugin per
Python. Pi
u semplicemente:
per
Linux
e
conveniente
http://www.python.org/idle/ .

utilizzare

IDLE,

disponibile

al

sito

per Windows e conveniente utilizzare lIDE Pythonwin, disponibile al sito


http://starship.python.net/crew/mhammond/win32/ dentro alle Python for Windows Extensions.
1.2

Documentazione su Python

Documentazione relativa a Python:


un
tutorial
per
iniziare
e
disponibile
http://www.python.it/doc/Easytut/easytut-it/index.html .

al

sito

al sito http://www.python.it/ si trova una notevole quantita di informazioni in


generale sul linguaggio Python.

Calcolo Numerico in Python

1.3

Moduli aggiuntivi per il calcolo scientifico

Lutilizzo di Python per limplementazione di algoritmi numerici e possibile principalmente grazie alle sue estensioni, tra cui segnaliamo, in particolare:

Numeric
(ci
riferiamo
alla
versione
23.8
disponibile
al
sito
http://sourceforge.net/project/showfiles.php?group id=1369&package id=1351
): e lestensione che offre gli strumenti per lavorare con vettori e matrici, di importanza fondamentale; documentazione ed informazioni
sono disponibili al sito http://numeric.scipy.org/ , in particolare
http://numeric.scipy.org/numpydoc/numdoc.htm .

SciPy ( ci riferiamo alla versione disponibile al sito http://www.scipy.org/ ): e


unestensione che offre vari strumenti di calcolo scientifico; si appoggia a Numeric.

PySparse
(
ci
riferiamo
alla
versione
disponibile
al
sito
http://pysparse.sourceforge.net/ ): e lestensione che offre limplementazione
per Python delle matrici sparse, e di alcuni algoritmi per la risoluzione di sistemi
lineari sparsi; si appoggia a Numeric.

Pygist ( ci riferiamo alla versione disponibile al sito http://bonsai.ims.utokyo.ac.jp/%7Emdehoon/software/python/pygist.html


):
e
lestensione
che offre gli strumenti per creare grafici 2D (ed anche 3D);
il
manuale
online
e
disponibile
al
sito
http://bonsai.ims.utokyo.ac.jp/%7Emdehoon/software/python/pygist html/pygist.html .

Gnuplot-py ( ci riferiamo alla versione disponibile al sito http://gnuplotpy.sourceforge.net/ ): e unestensione alternativa a Pygist, che interfaccia Python
al popolare Gnuplot.

Gmsh ( ci riferiamo alla versione disponibile al sito http://www.geuz.org/gmsh/ ):


e unestensione per la creazione di griglie 1,2,3-dimensionali irregolari (adatte ad es.
alla simulazione mediante il Metodo degli Elementi Finiti).

F.Marcuzzi - M.R.Russo

Parte I
2

Programmazione

Modalit
a di esecuzione dei programmi scritti in Python

Ci sono due modalita principali per avviare un programma, scritto in linguaggio Python,
dal prompt della shell di Linux:
1. impartire il seguente comando (esegue il programma e ritorna alla shell di Linux):
python <nome file programma>.py

2. invocare lambiente basilare di sviluppo IDLE e poi lanciare il programma:


idle
(viene aperta la finestra di IDLE)
selezionare File>Open e poi selezionare il file contenente il programma;
(viene aperta la finestra delleditor con il file selezionato)
sulla finestra delleditor con il programma da avviare, selezionare Run
>RunModule
(sulla shell di IDLE appaiono i risultati dellesecuzione e rimangono disponibili).
2.1

Caricamento di Moduli aggiuntivi (import e reload)

In entrambe le modalita di avvio di un programma, precedentemente citate, lambiente di


esecuzione viene inizializzato in modo minimale: tutti i moduli built-in e standard sono
disponibili, ma non sono stati inizializzati, con leccezione di sys (vari servizi di sistema),
builtin (funzioni built-in, eccezioni e None) e main .
Di conseguenza, prima di eseguire una funzione e necessario verificare di aver importato
(mediante listruzione import) il modulo che la contiene.
Nota bene: la chiamata della funzione varia a seconda di come si e importato il modulo.
Ad esempio, per chiamare la generica funzione <nome funzione>() del generico modulo
<nome modulo>, e possibile agire in uno dei seguenti modi:
caricamento di un modulo mantenendone il nome:
import <nome modulo>
chiamata: <nome modulo>.<nome funzione>()

Calcolo Numerico in Python

caricamento di un modulo nascondendone il nome:


from <nome modulo> import *
chiamata: <nome funzione>()
caricamento di alcune funzioni di un modulo, nascondendone il nome:
from <nome modulo> import <nome funzione> [, <altro nome funzione>, ...]
chiamata: <nome funzione>()

Per vedere i comandi disponibili nei moduli standard e possibile accedere al sito ufficiale
http://www.python.org/doc/current/lib/lib.html .
Se un modulo gia importato e stato successivamente modificato, e necessario caricarlo
nuovamente nellambiente. In questo caso, pero, listruzione import non farebbe nulla (in
quanto il modulo e gia stato importato), mentre e necessario utilizzare listruzione reload:
reload(<nome modulo>) .
2.2

Lavorare con la shell interattiva di Python

Dalla shell interattiva di Python e possibile impartire qualunque istruzione eseguibile


dallinterprete Python. Quindi: le istruzioni dei programmi possono essere singolarmente
provate sulla shell (ad es. per verificarne lesecuzione). Un intero programma pero non va
scaricato direttamente sulla shell (es. mediante cut-and-paste), ma salvato su un file di
testo ed eseguito come script.
2.2.1

Ripetizione dei comandi

E utile ricordare che unistruzione precedentemente impartita alla shell di Python, nella
sessione corrente, puo essere facilmente richiamata:
con IDLE (Linux): muovendosi con le combinazioni di tasti <Alt-p> e <Alt-n>
nellelenco storico progressivo memorizzato dallambiente;
con la shell interattiva (Linux) o con pythonWin (Windows): muovendosi con le
combinazioni di tasti <ctrl-freccia s
u> e <ctrl-freccia gi
u> nellelenco storico
progressivo memorizzato dallambiente .
Questa funzione e analoga a quella ottenuta in Matlab con <freccia-s
u> e <freccia-gi
u>)
.
2.2.2

Interazione con le directories

E necessario che il modulo os (funzioni del sistema operativo) venga prima importato:
import os

F.Marcuzzi - M.R.Russo

Nome della directory corrente:


os.getcwd()
Cambio della directory corrente:
os.chdir(<nome dir figlia>)
os.chdir(..)
os.chdir(<full path>)

# passa alla directory figlia specificata


# passa alla directory padre
# passa alla directory specificata

Elenco del contenuto di una directory:


os.listdir(.)
os.listdir(..)
os.listdir(<nome dir figlia>)
os.listdir(<full path>)
Creazione di una directory:
os.mkdir(<nome dir figlia>)
os.mkdir(<full path>)

2.2.3

#
#
#
#

mostra
mostra
mostra
mostra

la
la
la
la

directory
directory
directory
directory

corrente
padre
figlia specificata
specificata

# crea la directory figlia specificata


# crea la directory specificata

Help in linea

Si utilizza il comando help, che fornisce informazioni testuali su:


un modulo intero:
help(<nome modulo>)
una funzione di un modulo:
help(<nome modulo>.<nome funzione>)

Nota: la funzione help() richiede che il modulo <nome modulo> sia gia stato importato.

3
3.1

Presentazione sintetica del Linguaggio


Tipi di dato
string:
s = "Ciao"
# creazione di una stringa
print len(s) # lunghezza in caratteri di una stringa
>>> 4
print s[0:2] # estrazione di una sotto-stringa

Calcolo Numerico in Python

>>> Ci
# NB: s[da,a] considera gli indici da "da" fino ad "a-1"
# ripetizione di una stringa:
s = "Ciao"
print s * 3
>>> CiaoCiaoCiao
# concatenazione di due o piu stringhe:
s1 = "Ciao"
s2 = "Mondo"
print s1 + " " + s2
>>> Ciao Mondo

int: Python supporta i numeri interi a 32 bit, rappresentati mediante la notazione


complemento a 2.
double: Python supporta i numeri in virgola mobile in doppia precisione (la singola
precisione non e prevista).
ATTENZIONE: se si scrive una costante senza il punto (.) viene rappresentata
come numero intero. Ad esempio, 1 e un int, mentre 1. e un double, per cui si
ha:
>>> 1/2
0
>>> 1./2
0.5
>>> 1/2.
0.5
# arrotondamenti:
y = ceil(x)
# "y" e il double pari al piu piccolo intero >= x
y = floor(x) # "y" e il double pari al piu piccolo intero <= x
y = round(x) # "y" e il double pari allintero piu vicino a "x"

complex: Python supporta i numeri complessi in virgola mobile. Esempi:


z = complex(3.1,2.2) # crea il numero complesso "3.1 + j2.2"
z.real
# restituisce la parte reale di "z"
z.imag
# restituisce la parte immaginaria di "z"

lista:
e un tipo di dato utile per immagazzinare pi
u di un valore in ununica variabile.
Vediamo le principali operazioni possibili:
# creazione di una lista (in generale, una lista e eterogenea):
listino = [panino,3.70,acqua,0.50,gelato,0.99]
listino[2] # accesso allelemento di indice 2 (NB: gli indici partono da 0)

F.Marcuzzi - M.R.Russo

listino[2] = 3
del listino[2]
len(listino)
"vino" in listino
"vino" not in listino
list.sort()
list.index("acqua")
list.append("vino")

3.2

#
#
#
#
#
#
#
#
#

imposta a 3 lelemento di indice 2


cancella lelemento di indice 2
restituisce la lunghezza della lista
e true se "vino" e un elemento della lista
e vero se "vino" non e un elemento della lista
ordina la lista
restituisce lindice dove viene trovata la
prima occorrenza di "acqua"
aggiunge lelemento "vino" alla fine della lista

Istruzioni composte

3.2.1

La decisione if-then-else

Permette di esprimere unalternativa in base ad una condizione da testare durante


lesecuzione del programma :
if <condizione>:
<istruzioni ....>
else:
<istruzioni ....>
#end
Dal punto di vista del calcolo numerico, questo `e un costrutto poco favorevole poiche, in
generale:
nella valutazione della condizione non vengono eseguiti propriamente dei conti;
non favorisce la creazione di un flusso omogeneo di calcoli (condizione ideale per
ottenere una buona velocita di esecuzione nelle macchine di calcolo moderne).
Dunque, esso va messo in un algoritmo solo se strettamente necessario e preferibilmente
non allinterno di un ciclo.
3.2.2

Il ciclo for

Permette di ripetere un certo insieme di istruzioni per un numero prefissato di iterazioni


:
for <variabile> in <vettore di interi>:
<istruzioni ...>
#end

10

Calcolo Numerico in Python

Il <vettore di interi> pu`o essere espresso mediante una lista oppure un array (Numeric.array), e <variabile> assume al passo i-esimo il valore della sua i-esima componente
. Esempi:
1. for i in range(1,2000,10), che significa i parte da 1, si incrementa con
passo 10 ed il ciclo si arresta quando i >= 2000 (in linguaggio C, sarebbe
for (i=1; i<2000; i+=10) {...});
2. for i in [1 2 4 6 25], che significa il ciclo esegue 5 iterazioni; alla prima i vale
1, alla seconda 2, alla terza 4, alla quarta 6, alla quinta 25.
3. for i in stringa, che significa i assume valore pari ai singoli caratteri della
stringa, partendo dal primo e fino allultimo.
Questo costrutto `e largamente utilizzato nel calcolo numerico e si presta a vari tipi di
ottimizzazioni, sia su calcolatori sequenziali che paralleli.
Tipicamente la <variabile> assume valori da 1 a N , dove N `e una dimensione fondamentale del problema, ad es. il numero di componenti di un vettore o di righe (o colonne)
di una matrice.
3.2.3

Il ciclo while

Permette di ripetere un insieme di istruzioni per un numero di iterazioni condizionato dal


soddisfacimento di una condizione di arresto :
while <variabile> == <espressione>:
<istruzioni ...>
#end
Questo costrutto e frequentemente utilizzato nel calcolo numerico, ad es. per
limplementazione di metodi iterativi (largamente utilizzati per la risoluzione di varie
classi di problemi numerici), e cioe di metodi che, partendo da unapprossimazione iniziale
della soluzione esatta, la migliorano per incrementi successivi utilizzando un metodo di
dimostrata convergenza.
3.3

Funzioni

Un modulo Python (lo identifichiamo qui con un file, <nome file>.py) puo contenere una
o pi
u funzioni al suo interno. Importando il modulo, si rendono disponibili le funzioni in
esso contenute.
In generale, una funzione la si definisce nel seguente modo:
def <nome funzione>([<parametro 1>, <parametro 2>, ...]):
<istruzioni...>
<...con eventuale "return">

11

F.Marcuzzi - M.R.Russo

Lidentificativo def (abbreviazione di define, definisci) inizializza la definizione di una


funzione. La presenza di parametri nella definizione di una funzione e opzionale, cioe si
puo definire una funzione che non riceve alcun parametro in ingresso.
Le istruzioni dopo il : vengono eseguite ogni volta che la funzione viene chiamata dal
programma e sono indentate rispetto a def. Quando lindentazione torna al livello della
funzione o quando incontra listruzione return (che e quindi opzionale), la funzione termina.
Le variabili passate come argomenti dal programma chiamante non vengono modificate
dalla funzione (chiamata per valore).
Le funzioni permettono alle variabili locali di esistere solo ed unicamente allinterno della
funzione stessa, e di nascondere alle istruzioni di questa le altre variabili definite allesterno
della funzione.
3.4

I/O da file e da schermo

3.4.1

I/O da file

Scrittura di un file di testo:


out_file = open("prova.txt","w") # apertura
out_file.write("Prima riga di testo\nSeconda
# scrittura del file: "\n" manda
out_file.close()
# chiusura

del file in scrittura ("w")


riga di testo\n...\n")
a capo sulla riga successiva
del file

Lettura di un file di testo in una sola operazione:


in_file = open("prova.txt","r")
# apertura del file in lettura ("r")
testo = in_file.read()
# lettura del file e memorizzazione
# nella variabile string testo
in_file.close()
# chiusura del file

Lettura di un file di testo riga-per-riga:


in_file = open("prova.txt","r")
# apertura del file in lettura ("r")
riga = in_file.read()
# lettura del file
while len(riga) > 0:
# la funzione readline() ritorna una stringa vuota
# quando viene raggiunta la fine del file.
riga = in_file.read()
# leggo la prossima riga del file di testo
<altre istruzioni ...>
#end
in_file.close()
# chiusura del file

Nota: lestensione del file puo essere qualunque, e non necessariamente txt.

12

Calcolo Numerico in Python

3.4.2

I/O da schermo

stampa su schermo:
print "2 + 2 = ", 2+2
>>> 2 + 2 = 4

richiesta di un numero da tastiera:


num = input("scrivi un numero:")

richiesta di una stringa da tastiera:


str = raw_input("scrivi una stringa:")

3.5

misura dei tempi di esecuzione

E necessario che il modulo time venga prima importato:


import time
dopodiche listante attuale, misurato in secondi, viene preferibilmente fornito dalla
funzione:

in Linux:
istante_1 = time.time()

in Windows:
istante_1 = time.clock()

# listante attuale viene memorizzato


# nella variabile "istante_1"

# listante attuale viene memorizzato


# nella variabile "istante_1"

Quindi, e molto semplice misurare lintervallo di tempo necessario allesecuzione di un


insieme di istruzioni (al limite un intero programma): basta calcolare la differenza tra
finale ed istante iniziale.
Attenzione, pero: il programma scritto in Python non viene compilato in linguaggio
macchina (come avviene per i programmi scritti in linguaggio C/C++ o in Fortran),
bensi compilato in bytecode (analogamente a quanto avviene in Java) e questo poi viene
interpretato ed eseguito. Questo significa che:

13

F.Marcuzzi - M.R.Russo

1. il tempo di esecuzione, misurato da time.clock(), puo essere in gran parte


dovuto ad operazioni esterne allalgoritmo di calcolo numerico in esecuzione, e
che quindi prendere il tempo di esecuzione come tempo di calcolo puo risultare
unapprossimazion alquanto grossolana;
2. lo stile di programmazione incide sul tempo di esecuzione molto di pi
u di quanto
avvenga con i linguaggi compilati (es. C/C++ e Fortran); e necessario dunque fare
la dovuta attenzione. Ad esempio, evitare il pi
u possibile di fare cicli (for oppure
while) innestati.

Operazioni con Vettori e Matrici

Lelaborazione di vettori e matrici non puo essere fatta con gli strumenti base di Python,
ad es. liste e cicli for, in quanto risulterebbe assai lenta se confrontata con implementazioni
in linguaggio C o Fortran. Per questo motivo e stata sviluppata lestensione Numeric, detta
anche NumPy, che consente di eseguire operazioni su vettori e matrici con unefficienza
paragonabile a quella che si ha con i linguaggi compilati (ad es. C e Fortran, appunto).
La documentazione HTML relativa allestensione Numeric puo essere trovata al sito:
Vediamo una sintesi delle operazioni principali:
from Numeric import *

# caricamento del modulo Numeric

Creazione di Vettori e Matrici:


v = zeros(n)
# crea un vettore "v" di "n" componenti
# di tipo int e di valore zero
v = zeros(n, Double) # crea un vettore "v" di "n" componenti
# di tipo complex e di valore 0+j0
v = zeros(n, double) # crea un vettore "v" di "n" componenti
# di tipo double e di valore zero
v = ones(n, double) # crea un vettore "v" di "n" componenti
# di tipo double e di valore zero
M = zeros((m,n), double) # crea una matrice "M" di "m" righe ed "n" colonne,
# di tipo double e di valore uno
M = ones((m,n), double) # crea una matrice "M" di "m" righe ed "n" colonne,
# di tipo double e di valore uno
v = arrayrange(a, b, delta, double) # crea il vettore di double:
# (a, a+delta, ..., max(a+x*delta < b))
v = arange(a, b, delta, double) # arange e sinonimo di arrayrange
Nota: il tipo double corrisponde al numero in virgola mobile in doppia precisione
(il double del linguaggio C).
Conversione da/in liste:
pl = [1.1, -0.9, 5, 23]; v = array(pl) # crea il vettore "v" dalla lista "pl"
r1 = [1.1, -0.9, 5]; r2 = [-3.1, 5, 2.1]; M = array([r1, r2]) # crea "M"

14

Calcolo Numerico in Python

Interazione con la dimensionalita di Vettori e Matrici:


v = array([2, 0, 3.1, 0.1, 6, 13])
v.shape
# restituisce una tupla con la lunghezza di ogni dimensione di "v"
v.shape = (2,3)
# trasforma "v" in una matrice 2x3
v = transpose(v)
# assegna a v (che adesso e una matrice) la sua trasposta
size(v)
# restituisce il numero totale di elementi di "v"
v.shape = (size(v),)
# trasforma "v" nuovamente in un vettore di 6 elementi
len(v)
# restituisce la lunghezza della prima dimensione di "v"
Indicizzazione di Vettori e Matrici:
v = arange(-1, 0.25, 3.1) #
v[-1] = v[0]
# setta lultimo elemento al valore del primo
v[2:5] = 0.28
# setta v[2], v[3] e v[4] al valore 0.28
M = array([[-1, 0.25, 3.1],[0.1, 0.3, -0.55]]) #
print M[0,1]
# stampa il valore dellelemento di indici 0,1
M[r,c] = 9.77
# assegna lelemento di indici r,c al valore 9.77
print M[:,1]
# stampa la seconda colonna di M
M[:,:] = 1.1
# assegna tutti gli elementi di M al valore 1.1
b = M[:,2] # NB:crea un riferimento alla terza colonna di M,
#
non una copia !
#
Quindi, modificando b si modifica anche M e viceversa
b = M[:,2].copy()
# NB: crea una copia della terza colonna di M
Calcoli con Vettori e Matrici:
NB: fare cicli (for o while) sugli elementi di un vettore o di una matrice dovrebbe
essere evitato, per non rallentare troppo lesecuzione. E consigliabile utilizzare il
pi
u possibile le molte operazioni vettoriali e matriciali implementate in Numeric,
presentate qui nel seguito.
b = v*5.5 - 1.0 # crea il vettore b in cui ogni componente e pari alla
# corrispondente nel vettore v, moltiplicata per 5.5
# e a cui viene sottratto il valore 1.0
# operatori aritmetici vettoriali "sul posto" (analogo per le matrici):
v *= 1.155
# moltiplica per 1.155 ogni componente di v
v -= 0.1
# sottrae 0.1 ad ogni componente di v
v /= 1.44
# divide per 1.44 ogni componente di v
v += 3.1
# somma 3.1 ad ogni componente di v
v **= 2
# eleva alla potenza 2 ogni componente di v
# le funzioni trigonometriche,... sono applicabili a vettori e matrici:
v = cos(v)
# ogni componente di v viene sostituita dal suo coseno
b = sin(v)
# crea il vettore b in cui ogni componente e pari al
# seno della componente corrispondente del vettore v
b = log(v)
# (idem)... logaritmo naturale
b = exp(v)
# (idem)... esponenziale
b = sqrt(v) # (idem)... radice quadrata

15

F.Marcuzzi - M.R.Russo

Nota: lestensione Numeric dispone anche di un modulo, MLab.py, che implementa


una serie di funzioni con una sintassi compatibile con Matlab (cfr. la documentazione di Numeric) :
from MLab import *
v = rand(n)
# creazione di un vettore random di lunghezza "n"
M = rand(m,n) # creazione di una matrice random di lunghezza "mxn"
L = tril(M) # crea la matrice "L" con la parte triangolare inferiore di "M"
U = triu(M) # crea la matrice "U" con la parte triangolare superiore di "M"

Verifica e modifica del tipo di dato:


v = array([1.2, 3.3, 2])
isinstance(v, ArrayType) # dice se v e un oggetto di tipo array
print v.typecode() # restituisce:
# d per double
# D per complex
# i per int
# conversione di formato:
v = v.astype(int)
# converte v in formato int per troncamento
v.astype(int)
# restituisce una copia di v convertita in int
4.1

Basic Linear Algebra Subroutines (BLAS) e progetto ATLAS

4.1.1

Operazioni di tipo BLAS 1

prodotto interno (o prodotto scalare) tra due vettori v (riga) e w (colonna) di


lunghezza n:
c = innerproduct(v, w)
dove c risulta essere uno scalare, pari a:
c = v[0]*w[0] + ... + v[n-1]*w[n-1]

somma dei vettori v e w, di lunghezza n, scalati di alpha e beta:


b = alpha*v + beta*w
dove b risulta essere un vettore, di lunghezza n, il cui i-esimo componente e pari a:
b[i] = alpha*v[i] + beta*w[i]

prodotto per componenti dei vettori v e w, di lunghezza n:


b = v * w
dove b risulta essere un vettore, di lunghezza n, il cui i-esimo componente e pari a:
b[i] = v[i] * w[i]

16

Calcolo Numerico in Python

4.1.2

Operazioni di tipo BLAS 2

prodotto esterno tra due vettori v (colonna) e w (riga), di lunghezza n:


C = outerproduct(v, w)
dove C risulta essere una matrice, di dimensione n n, la cui componente di
posizione (i, j) e pari a:
C[i,j] = v[i]*w[j]
prodotto matrice-vettore (matrice A di dimensione n n e vettore colonna v di
lunghezza n o matrice di dimensione n 1 ):
b = matrixmultiply(A, v)
dove b risulta essere un vettore, di lunghezza n, il cui i-esimo componente e pari a:
b[i] = A[i,0]*v[0] + A[i,1]*v[1] + ... + A[i,n-1]*v[n-1]
prodotto di matrici (di dimensione n n) per componenti:
C = A * B
dove C risulta essere una matrice, di dimensione n n, la cui componente di
posizione (i, j) e pari a:
C[i,j] = A[i,j]*B[i,j]

4.1.3

Operazioni di tipo BLAS 3

prodotto di matrici (di dimensione n n):


C = matrixmultiply(A, B)
dove C risulta essere una matrice, di dimensione n n, la cui componente di
posizione (i, j) e pari al prodotto interno della riga i-esima di A per la colonna
j-esima di B :
C[i,j] = A[i,0]*B[0,j] + A[i,1]*B[1,j] + ... + A[i,n-1]*B[n-1,j]

4.2

Matrici Sparse

La matrice sparsa non e ovviamente un tipo di dato standard del linguaggio Python. La
troviamo nellestensione PySparse, in tre formati differenti. Il primo, LL, e pi
u versatile nel
creare e manipolare la matrice sparsa, mentre gli altri due, Compressed Sparse Row (CSR)
e Sparse Symmetric Skyline (SSS ), sono pi
u efficienti nelleseguire con essa operazioni di
tipo BLAS2 o BLAS3. E preferibile dunque convertire la matrice in un formato efficiente
prima di eseguire tali operazioni. A questo scopo sono disponibili le funzioni opportune.
NB: ricordiamo che in una matrice sparsa ci sono in genere molte componenti non implementate, e trattate come zeri, e relativamente poche componenti implementate, dette
nonzeri. Le prime sono zeri strutturali, le seconde sono valori in generale diversi da zero
ma che possono anche essere uguali a zero (zeri accidentali ). La disposizione dei nonzeri si

17

F.Marcuzzi - M.R.Russo

dice anche struttura di sparsita della matrice. Il rapporto tra numero di nonzeri e numero
totale di componenti e detto indice di densit
a, ed e compreso nellintervallo [0, 1]. Una
matrice con indice di densita pari a 1 si dice densa.
Vediamo una sintesi delle operazioni principali:
from spmatrix import *
from spmatrix_util import *

# caricamento del modulo spmatrix


# dellestensione PySparse
# caricamento del modulo spmatrix_util
# dellestensione PySparse

Creazione di Matrici Sparse (in formato LL):


M = ll_mat(nrighe, ncol)
# ogni componente e di tipo double
M = ll_mat(nrighe, ncol, nnz) # cosi viene inizialmente allocato spazio
# per nnz componenti (di default sono 1000)
M.shape
# restituisce una tupla con la lunghezza di ogni dimensione di "v"
M.nnz
# questo attributo contiene il numero di nonzeri:
0
# appena creata, una matrice sparsa non ha nonzeri
float(M.nnz)/(M.shape[0]*M.shape[1])
# indice di densita di M
M = ll_mat_rand(nrighe, ncol, ids) # genera una matrice sparsa e la inizializza
# con valori random e posizione casuale dei
# nonzeri scelta in modo che lindice di
# densita risultante sia minore o uguale
# a ids. I valori stanno in [0.0, 1.0)
B = M.copy()
# crea una copia di M
Conversione di formato:
M.to_csr()
M.to_sss()

# conversione di M al formato CSR


# conversione di M al formato SSS

Indicizzazione di Vettori e Matrici:


laccesso e la modifica di singole componenti della matrice sono disponibili in tutti
e tre i formati, ed hanno modalita analoghe a quelle viste per gli array di Numeric
(PySparse e costruita sopra Numeric):
print M[0,1]
# stampa il valore dellelemento di indici 0,1
M[r,c] = 9.77
# assegna lelemento di indici r,c al valore 9.77

4.2.1

Operazioni implementate in modo dedicato per il formato LL

prodotto matrice-vettore (matrice A di dimensione n n e vettore colonna v di


lunghezza n):
b = matvec(A, v) # equivale a "b = A * v"
b = matvec_transp(A, v) # equivale a "b = transpose(A) * v"

18

Calcolo Numerico in Python

dove b risulta essere un vettore, di lunghezza n, il cui i-esimo componente e pari a:


b[i] = A[i,0]*v[0] + A[i,1]*v[1] + ... + A[i,n-1]*v[n-1]
copia:
W = M.copy()

# crea una copia di "M" e "W" ne e il riferimento

calcolo della norma:


M.norm(p)
# "p" \e una stringa; valori possibili: 1,2,...,inf,fro

4.2.2

Operazioni implementate in modo ottimizzato per il formato CSR ed SSS

prodotto matrice-vettore (matrice A di dimensione n n e vettore colonna v di


lunghezza n):
b = matvec(A, v) # equivale a "b = A * v"
b = matvec_transp(A, v) # equivale a "b = transpose(A) * v"
dove b risulta essere un vettore, di lunghezza n, il cui i-esimo componente e pari a:
b[i] = A[i,0]*v[0] + A[i,1]*v[1] + ... + A[i,n-1]*v[n-1]

Creazione di Grafici

Utilizziamo il modulo gplt facente parte dellestensione SciPy. Esso si appoggia a Gnuplot.
import scipy
# caricamento del modulo scipy
from scipy import gplt
# caricamento del modulo gplt
from Numeric import *
# caricamento del modulo Numeric
5.1

Grafici bi-dimensionali

# caso generale: gplt.plot(x1,y1,format_string1, x2,y2,format_string2, ...)


# in cui tutti gli argomenti tranne y1 sono opzionali
# e dove:
# xi e un array o una lista di ascisse (i=1,2,...)
# yi e un array o una lista di ordinate (i=1,2,...)
# format_string1,...2,... sono stringhe di formattazione
#
che seguono lo stile di Gnuplot:
#
title \<title>\ with <style>, dove
#
<title> puo essere un mnemonico che per il vettore,
#
ad esempio dati misurati, oppure notitle;
#
<style> puo essere lines (linea continua), points
#
(punti singoli), linespoints, impulses,

19

F.Marcuzzi - M.R.Russo

#
#

dots, steps, fsteps, histeps, ...


es. notitle with lines

# esempi:
gplt.plot((1,2,3))

# grafica una lista di valori in funzione dellindice,


# interpolandoli linearmente
gplt.plot([1,5,3])
# come sopra, con una lista
gplt.plot(array([1,2,3,5]))
# come sopra, con un array
# caso completo:
x = arange(0.0, 1.0, 0.05)
# scelgo un insieme di valori per le ascisse
y = x**3
# scelgo un insieme di valori per le ordinate
gplt.plot(x,y) # stampa per punti linearmente interpolati il grafico
# di y in funzione di x
gplt.title(grafico di funzione cubica)
gplt.xtitle(ascisse) # stampa letichetta ascisse sullasse delle ascisse
gplt.ytitle(ordinate) # stampa letichetta ordinate sullasse delle ordinate
gplt.autoscale() # fa lo scalamento automatico del grafico
gplt.text((x,y),string)
# stampa la stringa string alle coordinate x,y
gplt.legend()
# crea la legenda del grafico
gplt.hold(on) # i prossimi comandi plot vengono sovrapposti al
# grafico attuale
gplt.hold(off) # il prossimo comando plot sovrascrive il
# grafico attuale
Nota: quando si usa gplt.hold(on) ricordarsi poi di mettere gplt.hold(off) alla
fine, altrimenti ad ogni esecuzione successiva si accumulano i grafici delle precedenti
esecuzioni, inutilmente.
gplt.xaxis((min,max)) # visualizza lintervallo dellasse x tra min e max
gplt.yaxis((min,max)) # visualizza lintervallo dellasse y tra min e max
gplt.grid(on)
# visualizza una griglia cartesiana
gplt.grid(off) # nasconde la griglia
gplt.logx(on)
# imposta la scala logaritmica sullasse x
gplt.logx(off) # toglie la scala logaritmica sullasse x
# (ripristina la scala naturale)
gplt.logy(on)
# imposta la scala logaritmica sullasse y
gplt.logy(off) # toglie la scala logaritmica sullasse y
# (ripristina la scala naturale)
gplt.close()
# chiude il grafico corrente e distrugge la finestra corrispondente

5.2

Grafici tri-dimensionali

Per fare il grafico di una superficie, in 3D, definita per punti interpolati linearmente, si
usa la funzione
# Per fare il grafico di una superficie in 3D definita da un insieme di

20

Calcolo Numerico in Python

# punti interpolati linearmente:


gplt.surf(x,y,z)
# in cui tutti gli argomenti tranne z sono opzionali
# e dove:
# x e un array o una lista di ascisse (i=1,2,...)
# y e un array o una lista di ordinate (i=1,2,...)
# z e una matrice di valori il cui elemento generico
#
z[i,j] e relativo alle coordinate x[i] e y[j]
gplt.zaxis((min,max)) # visualizza lintervallo dellasse z tra min e max
gplt.hidden(remove)
gplt.view(x_rotation, z_rotation, scale, z_scale) # uso:
# gli angoli sono espressi in gradi .
gplt.view("default") # "default" corrisponde a:
# x_rotation=60, z_rotation=30, scale=1, z_scale=1
gplt.text(x,y,z,string)
# stampa la stringa string alle coordinate x,y,z
# esempio:
x=(arange(50.)-25)/2.
y=(arange(50.)-25)/2.
r = sqrt(x[:,NewAxis]**2+y**2)
z = scipy.special.j0(r)
gplt.surf(x,y,z)
#
# per fare il grafico di un insieme di punti in 3-D:
#
from RandomArray import normal
points = normal(0,1.,(500,3))
gplt.plot3d(points,notitle with points)
points = normal(2,1.,(500,3))
gplt.hold(on)
gplt.plot3d(points,notitle with points)
gplt.ticlevel(0)

5.3

Immagini

21

F.Marcuzzi - M.R.Russo

Parte II

6
6.1

Librerie

Libreria di Algebra Lineare Numerica


Interfaccia di Numeric alla LAPACK

from Numeric import *


# caricamento del modulo principale dellestensione Num
from LinearAlgebra import *
# caricamento del modulo LinearAlgebra di Numeric
soluzione di un sistema di equazioni lineari rappresentato mediante una matrice A
di dimensione n n e vettore colonna v di lunghezza n:
x = solve_linear_equations(A, b) # "x" e un vettore colonna di lunghezza "n"

soluzione di un sistema di equazioni lineari con un membro destro multiplo, ovvero


di p sistemi di equazioni lineari aventi la stessa matrice di coefficienti e differenti
vettori di coefficienti a membro destro, rappresentati mediante una matrice A di
dimensioni n n ed una matrice B di dimensioni n p:
X = solve_linear_equations(A, B) # "X" e una una matrice di dimensioni "n x p"

6.2

Soluzione di sistemi lineari con matrice sparsa

Lestensione PySparse (vedi documentazione) contiene moduli che implementano metodi


diretti e metodi iterativi:
superlu contiene funzioni per il pre-ordinamento di matrici sparse, per la fattorizzazione LU e per la conseguente soluzione del sistema lineare;
itsolvers contiene funzioni per la soluzione di sistemi lineari mediante metodi
iterativi, ad es. lalgoritmo del Gradiente Coniugato Precondizionato.

Libreria per la soluzione di Equazioni Nonlineari

Libreria per lInterpolazione ed Approssimazione di funzioni


e di dati
import scipy
# caricamento del modulo scipy
from Numeric import *
# caricamento del modulo Numeric

22

Calcolo Numerico in Python

8.1

Interpolazione polinomiale

Utilizziamo il modulo interpolate facente parte dellestensione SciPy.


from scipy import interpolate
#
p
#
d
#
x
y

# carica il modulo interpolate

definizione di un polinomio:
= poly1d([1,3,4]) # definisce il polinomio: x^2 + 3*x + 4
derivata di un polinomio:
= p.deriv() # "d" e il polinomio uguale alla derivata di "p"
valutazione di un polinomio:
= [1.2,3.55,7.0,14.9] # insieme di valori
= p(x) # "y" e il vettore di valori che assume "p" nei punti "x"

# interpolazione lineare a tratti di una funzione uni-variata:


x = [1,2,3,4,5]
y = [2.1,3.0,6.1,2.5,6.99]
f = interpolate.interp1d(x,y)
xnew=[1,1.5,2,2.5]
gplt.plot(xnew,f(xnew))

# interpolazione di una funzione uni-variata mediante splines cubiche:


x = [1,2,3,4,5]
y = [2.1,3.0,6.1,2.5,6.99]
s1 = interpolate.splrep(x,y,s=0.0)
xnew=[1,1.5,2,2.5]
ys1 = interpolate.splev(xnew,s1,der=0)
gplt.plot(xnew,ys1)

8.2

Approssimazione ai Minimi Quadrati Discreti

Utilizziamo il modulo optimize facente parte dellestensione SciPy.


from scipy import optimize

# carica il modulo optimize

Lapprossimazione ai minimi quadrati, cioe la soluzione la soluzione x al problema


min kf (x)k22 , si ottiene chiamando la funzione leastsq(...) (vedere istruzioni con
help(optimize.leastsq)).
La funzione f (x) puo anche essere lineare, ad esempio f (x) = A x b, con matrice A di
dimensione m n e vettori colonna x di lunghezza n e b di lunghezza m.

23

F.Marcuzzi - M.R.Russo

Libreria per lIntegrazione Numerica

10

Libreria per la soluzione di Problemi ai Valori Iniziali

11

Libreria per la soluzione di Problemi ai Limiti

12

Libreria per la Geometria Computazionale

13

Programmazione ad Oggetti in linguaggio Python

13.1

Classi e Oggetti

Implementazione della classe:


definizione di una classe: class < nome classe > : . Nelle righe successive, vengono
dichiarate le variabili ed i metodi della classe, indentandole.
definizione di una classe derivata: class < nome classe > ( < classe padre > ):
. Nel caso in cui un metodo non sia presente, viene cercato ricorsivamente nella
gerarchia delle classi padre; questo avviene anche per il costruttore.
definizione del costruttore: def

init (self , < argomenti > ) :

definizione del distruttore: def


del < nomei stanza > .

del (self , < argomenti > ) : . Lo si usa cos:

definizione di un metodo: def < nome metodo >(self , < argomenti > ) :
definizione di una variabile: self.< nome variabile > = < valore >
Nota: self e il riferimento allistanza (oggetto) che sta chiamando il metodo della classe.
Nota: i metodi di una classe si comportano come una normale funzione Python; e possibile
assegnare valori di default nel seguente modo: < argomento >=< valore di def ault >.
Utilizzo della classe:
creazione di unistanza della classe: < variabile > = < nome classe >()
accesso ai suoi metodi : < nome istanza >.< nome metodo >( < argomenti > )
oppure < nome classe >.< nome metodo >( < nome istanza > , < argomenti >
)
accesso alle sue variabili : < nome istanza >.< nome variabile >
Ispezione di classi e oggetti:
la funzione (built-in) type( < nome > ) ci dice se nome e class oppure instance.

24

Calcolo Numerico in Python

la funzione (built-in) dir( < nome > ) ritorna una lista dei nomi delle proprieta e
dei metodi, se nome e una classe, ed una lista dei nomi delle variabili, se nome e
unistanza.
la proprieta bases
questa e derivata.

di una classe, contiene la lista dei nomi delle classi da cui

la proprieta dict di unistanza, contiene la lista delle coppie < nome >:<
valore > relative alle sue variabili interne.
la proprieta
13.1.1

class

di unistanza, contiene il nome della classe che lha generata.

Esempio: la classe Matrice

25