Capitolo 1
Un’introduzione informale
agli algoritmi
Ingegneria degli algoritmi Giuseppe F. Italiano
Cos’è un algoritmo?
Abū Jaʿfar Muhammad ibn Mūsā al-Khwārizmī
• Nato nell’attuale Khwarezm (Uzbekistan) ca 780
• Autore di al-Kitāb al-mukhtaṣar fī ḥisāb al-ǧabr wa al-
muqābala (soluzioni eq. lineari 2° grado, algebra)
• Algoritmi de numero Indorum (suo libro tradotto in
latino) introdusse notazione posizionale e numero 0 nel
mondo occidentale nel XII secolo
Francobollo commemorativo
russo del 1983 (1200 anni
dopo la sua nascita)
2
Ingegneria degli algoritmi Giuseppe F. Italiano
Cos’è un algoritmo?
Insieme di istruzioni, definite passo per passo, in
modo da poter essere eseguite meccanicamente e
tali da produrre un determinato risultato
3
Ingegneria degli algoritmi Giuseppe F. Italiano
5
Ingegneria degli algoritmi Giuseppe F. Italiano
7
Ingegneria degli algoritmi Giuseppe F. Italiano
8
Ingegneria degli algoritmi Giuseppe F. Italiano
9
Ingegneria degli algoritmi Giuseppe F. Italiano
10
Ingegneria degli algoritmi Giuseppe F. Italiano
13
Ingegneria degli algoritmi Giuseppe F. Italiano
14
Ingegneria degli algoritmi Giuseppe F. Italiano
15
Ingegneria degli algoritmi Giuseppe F. Italiano
16
Ingegneria degli algoritmi Giuseppe F. Italiano
17
Ingegneria degli algoritmi Giuseppe F. Italiano
18
Ingegneria degli algoritmi Giuseppe F. Italiano
Pseudocodice
Per mantenere massimo grado di generalità,
descriveremo algoritmi in pseudocodice:
– ricorda linguaggi di programmazione reali
come Python, C, C++ o Java
– può contenere alcune frasi in italiano
Introduzione a progetto e
analisi di algoritmi efficienti
tramite un esempio “giocattolo”:
(problema semplice ma
con molte soluzioni)
22
Ingegneria degli algoritmi Giuseppe F. Italiano
25
Ingegneria degli algoritmi Giuseppe F. Italiano
I conigli di Fibonacci
Ingegneria degli algoritmi Giuseppe F. Italiano
27
Ingegneria degli algoritmi Giuseppe F. Italiano
Regola di espansione
Un possibile approccio
• Possiamo usare direttamente una soluzione alla
relazione di Fibonacci:
dove:
Sezione aurea
30
Ingegneria degli algoritmi Giuseppe F. Italiano
Sezione aurea
31
Ingegneria degli algoritmi Giuseppe F. Italiano
Algoritmo fibonacci1
32
Ingegneria degli algoritmi Giuseppe F. Italiano
Correttezza?
• Qual è l’accuratezza di Φ e Φˆ necessaria per
ottenere un risultato corretto?
• Ad esempio, se usiamo solo 3 cifre decimali:
n fibonacci1(n) arrotondamento Fn
3 1.99992 2 2
16 986.698 987 987
18 2583.1 2583 2584
33
Ingegneria degli algoritmi Giuseppe F. Italiano
Algoritmo fibonacci2
Poiché fibonacci1 non dà risultati corretti,
come approccio alternativo potremmo utilizzare
direttamente la definizione (ricorsiva) :
Tempo di esecuzione
algoritmo fibonacci2(intero n) → intero
if (n ≤ 2) then return 1
else return fibonacci2(n-1) +
fibonacci2(n-2)
Se n ≤ 2, una sola linea di codice
Se n = 3, 4 linee di codice:
• 2 per la chiamata fibonacci2(3)
• 1 per la chiamata fibonacci2(2)
• 1 per la chiamata fibonacci2(1)
36 da Demetrescu et al. Mc Graw Hill 2004
Ingegneria degli algoritmi Giuseppe F. Italiano
Tempo di esecuzione
algoritmo fibonacci2(intero n) → intero
if (n ≤ 2) then return 1
else return fibonacci2(n-1) +
fibonacci2(n-2)
37
Ingegneria degli algoritmi Giuseppe F. Italiano
Relazione di ricorrenza
Per n ≥ 3 in ogni chiamata si eseguono 2 linee
di codice, oltre a quelle eseguite nelle
chiamate ricorsive:
2 + T(n-1) + T(n-2) se n ≥ 3
T(n) =
1 se n = 1, 2
A parte il 2, è come per i conigli di Fibonacci!
Relazioni di ricorrenza
In generale, tempo richiesto da algoritmi ricorsivi
genera relazioni di ricorrenza
Il tempo di ogni funzione è pari al tempo speso
all’interno della chiamata più il tempo speso nelle
chiamate ricorsive
Risolvendo la relazione di ricorrenza otteniamo
l’espressione del tempo
Come si risolvono relazioni di ricorrenza?
40
Ingegneria degli algoritmi Giuseppe F. Italiano
43
Ingegneria degli algoritmi Giuseppe F. Italiano
44
Ingegneria degli algoritmi Giuseppe F. Italiano
Dimostrazione
P (k) : se albero ha k foglie ha (k-1) nodi interni
Induzione sul numero di foglie:
• Base. P (1) : 1 foglia, 0 nodi interni. Banale.
• Passo induttivo. P (k) implica P (k+1)
Per generare albero con k+1 foglie, attacchiamo
due figli ad una (vecchia) foglia
Numero di foglie: k -1 + 2 = k + 1
Numero di nodi interni: (k -1) + 1 = k
45
Ingegneria degli algoritmi Giuseppe F. Italiano
Calcolare T(n)
• Numero di foglie dell’albero della ricorsione di
fibonacci2(n) è pari a F(n)
47
Ingegneria degli algoritmi Giuseppe F. Italiano
Fib[i] memorizza Fi
2 3 5 8 13 21 34 55 89 144
1 1
1 2 3 4 5 6 7 8 9 10 11 12
Algoritmo fibonacci3
Ingegneria degli algoritmi Giuseppe F. Italiano
Algoritmo fibonacci3
50
Ingegneria degli algoritmi Giuseppe F. Italiano
Programmazione Dinamica
1. Definire opportunamente sottoproblemi
(tabella)
2. Inizializzare la tabella
3. Dove sta la soluzione?
4. Riempire la tabella (da condizioni iniziali a
soluzione)
Ingegneria degli algoritmi Giuseppe F. Italiano
52
Ingegneria degli algoritmi Giuseppe F. Italiano
Cambiamento di prospettiva
Siamo passati da:
Those who cannot remember the past are
doomed to repeat it.
George Santayana, The Life of Reason, Introduction and Reason in
Common Sense (1905)
a:
Those who cannot forget the past are doomed
to remember it.
Jane Ace
53
Ingegneria degli algoritmi Giuseppe F. Italiano
array-fibonacci.c
algoritmo fibonacci3(intero n) → intero
sia Fib un array di n interi
Fib[1] ← Fib[2] ← 1
for i = 3 to n do
Fib[i] ← Fib[i-1] + Fib[i-2]
return Fib[n]
55
Ingegneria degli algoritmi Giuseppe F. Italiano
Occupazione di memoria
• Tempo di esecuzione non è sola risorsa che ci
interessa.
• Tempo di programmazione e lunghezza del
codice (Ingegneria del Software)
• Anche quantità di memoria richiesta può essere
cruciale.
• Se algoritmo lento, basta attendere più a lungo
• Ma se algoritmo richiede più spazio (RAM) di
quello a disposizione, rischiamo di non ottenere
mai la soluzione!
56
Ingegneria degli algoritmi Giuseppe F. Italiano
Algoritmo fibonacci4
• fibonacci3 usa un array di dimensione n
• In realtà non ci serve mantenere tutti i valori di Fn
precedenti, ma solo gli ultimi due, riducendo lo
spazio a poche variabili in tutto:
algoritmo fibonacci4(intero n) → intero
iter-fibonacci.c
a←b←1
for i = 3 to n do
c ← a+b
a←b
b←c
return b
57
Ingegneria degli algoritmi Giuseppe F. Italiano
Programmazione Dinamica
1. Definire opportunamente sottoproblemi
(tabella)
2. Inizializzare la tabella
3. Dove sta la soluzione?
4. Riempire la tabella (da condizioni iniziali a
soluzione)
5. Ci dobbiamo portare appresso tutta la tabella?
Ingegneria degli algoritmi Giuseppe F. Italiano
Notazione asintotica (1 / 4)
• Misurare T(n) come numero di linee di
codice mandate in esecuzione è una misura
molto approssimativa del tempo di
esecuzione
• Ipotesi: ogni linea di codice genera codice
assembler equivalente
59
Ingegneria degli algoritmi Giuseppe F. Italiano
Notazione asintotica (2 / 4)
• Vorremmo un modo per descrivere ordine di
grandezza di T(n) ignorando dettagli
inessenziali come costanti moltiplicative…
• Si utilizza a questo scopo la notazione
asintotica O( )
60
Ingegneria degli algoritmi Giuseppe F. Italiano
Notazione asintotica (3 / 4)
• Diremo che f(n) = O ( g(n) ) se f(n) ≤ c g(n)
per qualche costante c, ed n abbastanza grande
cg (n )
f(n) = Ο( g(n) )
f(n)
n0 n
61
Ingegneria degli algoritmi Giuseppe F. Italiano
Potenze ricorsive
• Da dove deriva questa proprietà?
Fn+1 1 1 Fn
=
Fn 1 0 Fn-1
n
1 1 Fn+1 Fn
=
1 0 Fn Fn-1
64
Ingegneria degli algoritmi Giuseppe F. Italiano
Algoritmo fibonacci5
65
Ingegneria degli algoritmi Giuseppe F. Italiano
Calcolo di potenze
• Esempio: calcolare 38
32 = 9 34 = (9)2 = 81 38 = (81)2 = 6561
66
Ingegneria degli algoritmi Giuseppe F. Italiano
Divide et impera
Sun Zi, The Art of War (c. 400 C.E., VI cent. BC),
translated by Lionel Giles (1910)
67
Ingegneria degli algoritmi Giuseppe F. Italiano
Divide et impera
Tecnica top-down:
1. Dividi il problema in più sottoproblemi
2. Risolvi (ricorsivamente) i sottoproblemi
3. Ricombina soluzioni dei sottoproblemi per
ottenere la soluzione del problema originario
68
Ingegneria degli algoritmi Giuseppe F. Italiano
Algoritmo fibonacci6
69
Ingegneria degli algoritmi Giuseppe F. Italiano
Tempo di esecuzione
• Tutto il tempo è speso nella funzione
potenzaDiMatrice
– All’interno della funzione si spende tempo costante
– Si esegue una chiamata ricorsiva con input n/2
70
Ingegneria degli algoritmi Giuseppe F. Italiano
Metodo dell’iterazione
T(n) ≤ c + T(n/2) ≤ c + c + T(n/4) = 2c + T(n/22)
In generale:
T(n) ≤ c k + T(n/2k)
Per k = log2 n si ottiene
T(n) ≤ c log2 n + T(1) = O(log2 n )
Riepilogo
Tempo di Occupazione di
esecuzione memoria
72
Ingegneria degli algoritmi Giuseppe F. Italiano
73
Ingegneria degli algoritmi Giuseppe F. Italiano
k
1 1 Fk+1 Fk
=
1 0 Fk Fk-1
74
Ingegneria degli algoritmi Giuseppe F. Italiano
2k
1 1 Fk+1 Fk Fk+1 Fk F2k+1 F2k
= =
1 0 Fk Fk-1 Fk Fk-1 F2k F2k-1
75
Ingegneria degli algoritmi Giuseppe F. Italiano
2k
1 1 Fk+1 Fk Fk+1 Fk F2k+1 F2k
= =
1 0 Fk Fk-1 Fk Fk-1 F2k F2k-1
F2k+1 = ( Fk+1 ) 2 + ( Fk ) 2
F2k = Fk Fk+1 + Fk Fk-1
F2k-1 = ( Fk ) 2 + ( Fk-1 ) 2
Ingegneria degli algoritmi Giuseppe F. Italiano
F2k+1 = ( Fk+1 ) 2 + ( Fk ) 2
F2k = Fk ( Fk + 2 Fk-1 )
F2k-1 = ( Fk ) 2 + ( Fk-1 ) 2
Algoritmo fibonacci7
F2k = Fk ( Fk + 2 Fk-1 )
F2k-1 = ( Fk ) 2 + ( Fk-1 ) 2
81
Ingegneria degli algoritmi Giuseppe F. Italiano