Greedy Algorithms
Problemi di ottimizzazione. Vogliamo trovare non una semplice soluzione ma
la migliore soluzione.
Chapter 4
Un algoritmo greedy viene utilizzato per risolvere problemi di
ottimizzazione (in alcuni casi ci riesce, in altri no).
Greedy
Algorithms
Un algoritmo greedy lavora in passi:
  Ad ogni passo fa la scelta più promettente subito (secondo un criterio
locale)
  senza pensare alle conseguenze future
  senza mai più riconsiderare questa scelta
  La speranza è che la scelta di un ottimo locale ad ogni passo, conduce ad
un ottimo globale.
1
2
Greedy Algorithms
4.1 Interval Scheduling
Problemi che vedremo:
  Interval Scheduling
  Interval Partitioning
  Scheduling to Minimize Lateness
  Optimal Caching
  Shortest Paths in a Graph
  Minimum Spanning Tree
  Huffman Codes and Data Compression
Esercizi:
  Coin Changing
  Selecting Breakpoints
  Fractional Knapsack problem
  Connecting wires
  Collecting coins
3
Schedulazione intervalli
Schedulazione intervalli
Schedulazione intervalli.
Job j inizia a sj e finisce a fj.
Schedulazione intervalli.
Job j inizia a sj e finisce a fj.
 
 
 
 
Due job sono compatibili se hanno intersezione vuota.
Obiettivo: trovare sottoinsieme massimale di job mutuamente
compatibili.
 
 
Due job sono compatibili se hanno intersezione vuota.
Obiettivo: trovare sottoinsieme massimale di job mutuamente
compatibili.
Qual’è la soluzione ottimale?
a
a
b
b
c
c
d
d
e
e
f
f
g
g
h
0
1
2
3
4
5
6
7
8
9
10
11
h
tempo
0
1
2
3
4
5
6
7
8
9
10
11
tempo
5
6
Schedulazione intervalli
Schedulazione intervalli: Algoritmi Greedy
Scelta Greedy. Considera job in qualche ordine. Prendere job se è
compatibile con quelli già presi.
Schedulazione intervalli.
Job j inizia a sj e finisce a fj.
 
 
 
Due job sono compatibili se hanno intersezione vuota.
Obiettivo: trovare sottoinsieme massimale di job mutuamente
compatibili.
Qual’è la soluzione ottimale?
 
Sottoinsieme massimale = {b,e,h}
a
 
b
c
 
d
e
f
 
g
h
0
1
2
3
4
5
6
7
8
9
10
11
[tempo inizio minimo] Considera job in ordine crescente del tempo
di inizio sj.
[tempo fine minimo] Considera job in ordine crescente del tempo di
fine fj.
[intervallo più corto] Considera job in ordine crescente del tempo
della lunghezza dell intervallo fj - sj.
[minori conflitti] Per ogni job j, contare il numero cj di job che lo
intersecano. Considera job in ordine crescente di conflitti cj.
tempo
7
8
Schedulazione intervalli: Algoritmi Greedy
Schedulazione intervalli
Scelta Greedy. Considera job in qualche ordine. Prendere job se è
compatibile con quelli già presi.
Schedulazione intervalli.
Job j inizia a sj e finisce a fj.
 
 
 
tempo inizio minimo
Due job sono compatibili se non hanno intersezione vuota.
Obiettivo: trovare sottoinsieme massimale di job mutuamente
compatibili.
Osservare:
•  Job più corto c non è in alcuna
soluzione ottimale
•  Job che inizia per primo a non è
in alcuna soluzione ottimale
a
intervallo più corto
non portano
all’ottimo!
b
c
d
minori conflitti
e
f
g
h
0
1
2
3
4
5
6
7
8
9
10
11
9
Schedulazione intervalli: Algoritmo Greedy
tempo
10
Schedulazione intervalli: Algoritmo Greedy
Algoritmo Greedy. Considera job in ordine crescente del tempo di fine fj.
Prendere job se è compatibile con quelli già presi.
11
12
Schedulazione intervalli
Schedulazione intervalli
Schedulazione intervalli.
Job j inizia a sj e finisce a fj.
Schedulazione intervalli.
Job j inizia a sj e finisce a fj.
 
 
 
 
Due job sono compatibili se non hanno intersezione vuota.
Obiettivo: trovare sottoinsieme massimale di job mutuamente
compatibili.
Qual’è la soluzione greedy?
 
 
Due job sono compatibili se non hanno intersezione vuota.
Obiettivo: trovare sottoinsieme massimale di job mutuamente
compatibili.
Qual’è la soluzione greedy?
a
Sottoinsieme greedy = {b,e,h}
a
b
b
c
c
d
d
e
e
f
f
g
g
h
0
1
2
3
4
5
6
7
8
9
10
11
h
tempo
0
1
2
3
4
5
6
7
8
9
10
11
tempo
13
14
Schedulazione intervalli: Algoritmo Greedy
Schedulazione intervalli: Implementazione Algoritmo Greedy
Algoritmo Greedy. Considera job in ordine crescente del tempo di fine
fj. Prendere job se è compatibile con quelli già presi.
Implementazione Algoritmo Greedy. O(n log n).
Denota j* l ultimo job aggiunto ad A.
 
 
Ordina job per tempo di fine f1 ≤ f2 ≤ ... ≤ fn.
Job j è compatibile con A se sj ≥ fj*.
Ordina job per tempo di fine f1 ≤ f2 ≤ ... ≤ fn.
insieme job scelti
A ← {1}
j* = 1
for j = 2 to n {
if sj ≥ fj*
{A ← A ∪ {j}
j* = j
}
}
return A
A ← {1}
for j = 2 to n {
if (job j è compatibile con A)
A ← A ∪ {j}
}
return A
15
16
Schedulazione intervalli: Analisi
Schedulazione intervalli: Analisi
Teorema. L algoritmo greedy è ottimale.
Teorema. L algoritmo greedy è ottimale.
Prova. (per assurdo)
Assumiamo che la scelta greedy non sia ottimale.
Siano i1, i2, ... ik job scelti in modo greedy.
Siano j1, j2, ... jm job in una soluzione ottimale con
i1 = j1, i2 = j2, ..., ir = jr dove r è il più grande valore possibile.
Prova. (per assurdo)
Assumiamo che la scelta greedy non sia ottimale.
Siano i1, i2, ... ik job scelti in modo greedy.
Siano j1, j2, ... jm job in una soluzione ottimale con
i1 = j1, i2 = j2, ..., ir = jr dove r è il più grande valore possibile.
 
 
 
 
 
 
job ir+1 termina prima di jr+1
job ir+1 termina prima di jr+1
greedy:
i1
i1
ir
ottimo:
j1
j2
jr
ir+1
jr+1
...
greedy:
i1
i1
ir
ir+1
ottimo:
j1
j2
jr
ir+1
sostituiamo job jr+1 con job ir+1
...
soluzione ancora ottima,
ma contraddice la massimalità di r
17
18
Interval Partitioning
4.1 Interval Partitioning
Interval partitioning.
Lezione j inizia ad sj e termina a fj.
 
 
Obiettivo: trovare il minimo numero di aule per schedulare tutte le
lezioni in modo che non ci siano due lezioni contemporaneamente
nella stessa aula.
Esempio: Schedulazione con 4 aule per 10 lezioni.
e
c
j
g
d
b
h
a
9
9:30
f
10
10:30
11
11:30
12
12:30
1
1:30
i
2
2:30
3
3:30
4
4:30
tempo
20
Interval Partitioning
Interval Partitioning
Interval partitioning.
Lezione j inizia ad sj e termina a fj.
Interval partitioning.
Lezione j inizia ad sj e termina a fj.
 
 
 
Obiettivo: trovare il minimo numero di aule per schedulare tutte le
lezioni in modo che non ci siano due lezioni contemporaneamente
nella stessa aula.
 
Obiettivo: trovare il minimo numero di aule per schedulare tutte le
lezioni in modo che non ci siano due lezioni contemporaneamente
nella stessa aula.
Esempio: Schedulazione con 3 aule per le stesse 10 lezioni.
Si può far meglio?
Si possono usare 2 aule?
c
d
b
a
9
9:30
f
j
g
i
h
e
10
10:30
11
11:30
12
12:30
1
1:30
2
2:30
3
3:30
4
4:30
tempo
21
Interval Partitioning: Limiti inferiori per soluzione ottima
22
Interval Partitioning: Limiti inferiori per soluzione ottima
Definizione. La profondità di un insieme di intervalli è il massimo
numero di intervalli che contiene un dato tempo.
Definizione. La profondità di un insieme di intervalli è il massimo
numero di intervalli che contiene un dato tempo.
Osservazione. Numero di aule che necessitano ≥ profondità.
Esempio: Profondità insieme intervalli = 3
a, b, c contengono 9:30
Esempio: Aule nella schedulazione = 3
⇒
schedulazione ottimale
Domanda. Esiste sempre una schedulazione uguale alla profondità degli
intervalli?
c
d
b
a
9
9:30
f
j
g
i
10:30
11
11:30
12
12:30
1
1:30
2
2:30
3
d
b
a
h
e
10
c
3:30
4
4:30
9
tempo
23
9:30
f
j
g
i
h
e
10
10:30
11
11:30
12
12:30
1
1:30
2
2:30
3
3:30
4
4:30
tempo
24
Interval Partitioning: Algoritmo Greedy
Interval Partitioning: Algoritmo Greedy
Algoritmo Greedy. Consideriamo lezioni in ordine crescente di tempo di
inizio: assegniamo lezioni ad aule compatibili.
Algoritmo Greedy. Consideriamo lezioni in ordine crescente di tempo di
inizio: assegniamo lezioni ad aule compatibili.
Ordina intervalli per tempo di inizio s1 ≤ s2 ≤ ... ≤ sn.
d ← 0
Ordina intervalli per tempo di inizio s1 ≤ s2 ≤ ... ≤ sn.
d ← 0
for j = 1 to n {
if (lezione j è compatibile con qualche aula k)
schedula lezione j nell aula k
else
alloca una nuova aula d + 1
schedula lezione j nell aula d + 1
d ← d + 1
}
for j = 1 to n {
if (lezione j è compatibile con qualche aula k)
schedula lezione j nell aula k
else
alloca una nuova aula d + 1
schedula lezione j nell aula d + 1
d ← d + 1
}
numbero aule allocate
numbero aule allocate
Implementazione. O(n log n).
Per ogni aula k, manteniamo il tempo di fine dell’ultimo job aggiunto.
Coda a priorità per i tempi di fine per ogni aula.
 
25
26
Coda a priorità
Heap
Un heap è un albero binario pieno livello per livello
  Ultimo livello da sx a dx
Implementazioni:
5
min
14
89
32
30
24
15
6
. . . . .
24
28
15
9
17
81
  Rappresentato con un array
10
19
13
31
11
5
∅
14
Head
Operazione PQ
Lista ordinata Lista non ordinata
(a puntatori)
(array)
24
Binary heap
Insert
O(n)
O(1)
O(log n)
Min
O(1)
O(n)
O(1)
ExtractMin
O(1)
O(n)
O(log n)
ChangeKey
O(n)
O(1)
O(log n)
IsEmpty
O(1)
O(1)
O(1)
10
28
81
A=
27
17
19
13
31
5
14
10
24
17
19
13
28
81
31
28
05/11/12
Heap
Heap
Un heap è un albero binario pieno livello per livello
  Ultimo livello da sx a dx
Un heap è un albero binario pieno livello per livello
  Ultimo livello da sx a dx
Parent(i) { return 'i/2(; }
  Rappresentato con un array
Proprietà di heap
  Rappresentato con un array
Left(i) { return 2*i; }
A[Parent(i)] ≥ A[i]
per tutti i nodi i > 1
right(i) { return 2*i + 1; }
5
5
14
10
24
28
17
81
A=
14
19
13
24
31
5
14
24
17
19
13
28
81
81
31
A=
13
31
5
14
10
24
17
19
13
28
81
31
30
05/11/12
05/11/12
Priority Queue con Binary Heap: inserimento
Un heap è un albero binario pieno livello per livello
  Ultimo livello da sx a dx
Inserimento 12
13
  Rappresentato con un array
  Il valore massimo è alla radice A[1]
21
  Altezza Θ(lg n)
5
25
14
37
35
43
10
24
17
81
A=
19
29
Heap
28
17
28
10
10
19
13
31
5
14
10
24
17
19
13
28
81
31
31
05/11/12
32
Priority Queue con Binary Heap: inserimento
Inserimento 12
Priority Queue con Binary Heap: inserimento
Inserimento 12
13
13
13
21
21
35
21
35
21
25
25
37
13
37
43
35
12
25
43
25
35
37
43
37
43
12
Violazione proprietà di heap
33
34
Priority Queue con Binary Heap: inserimento
Inserimento 12
Priority Queue con Binary Heap: inserimento
Inserimento 12
13
13
13
21
21
37
35
21
35
21
25
25
43
37
43
25
25
Violazione proprietà di heap
37
25
37
43
43
21
35
25
35
37
37
43
12
Violazione proprietà di heap
13
12
35
35
12
13
21
13
12
12
43
21
35
25
37
13
43
35
36
Priority Queue con Binary Heap: estrazione minimo
Priority Queue con Binary Heap: estrazione minimo
Minimo = 13
21
25
37
43
Minimo = 13
13
13
35
21
43
25
37
21
35
43
25
35
37
Violazione proprietà di heap
37
38
Priority Queue con Binary Heap: estrazione minimo
43
Minimo = 13
13
21
25
37
21
35
43
25
Priority Queue con Binary Heap: estrazione minimo
35
21
37
25
Violazione proprietà di heap
37
21
43
25
43
Minimo = 13
13
21
35
43
25
37
Violazione proprietà di heap
21
35
43
37
25
39
37
35
21
35
25
43
35
37
40
Priority Queue con Binary Heap: cambio chiave
Cambio da 21 a 11
Interval Partitioning: Analisi Algoritmo Greedy
Osservazione. L’algoritmo greedy non schedula mai due lezioni
incompatibili nella stessa aula.
13
13
11
21
Teorema. L’algoritmo greedy è ottimale.
Prova.
Sia d = numero aule allocate dall’algoritmo greedy.
Aula d è allocata perchè si deve schedulare un job, diciamo j, che è
incompatibile con le altre d-1 aule.
Dato l’ordinamento rispetto al tempo di inizio, tutte le incompatibiità
sono dovute a lezioni che iniziano prima di sj.
Quindi, ci sono d lezioni con intersezione al tempo sj + ε.
Profondità almeno d.
Tutte le schedulazioni necessitano di un numero di aule ≥ d. ▪
35
25
25
35
37
43
37
43
 
 
Violazione proprietà di heap
 
11
 
 
13
25
37
35
 
43
41
42
Schedulazione per minimizzare ritardo
4.2 Scheduling to Minimize Lateness
Problema minimizzazione ritardo.
Una singola risorsa processa un job alla volta.
 
 
 
 
 
Job j richiede tj unità di tempo e deve terminare al tempo dj.
Se j inizia al tempo sj, finisce al tempo fj = sj + tj.
Ritardo: j = max { 0, fj - dj }.
Obiettivo: schedulare tutti job per minimizzare massimo ritardo L = max j.
44
Schedulazione per minimizzare ritardo
Schedulazione per minimizzare ritardo: Algoritmi greedy
Problema minimizzazione ritardo.
Una singola risorsa processa un job alla volta.
Job j richiede tj unità di tempo ed deve terminare al tempo dj.
Se j inizia al tempo sj, finisce al tempo fj = sj + tj.
Ritardo: j = max { 0, fj - dj }.
Obiettivo: schedulare tutti job per minimizzare massimo ritardo L = max j.
Metodo Greedy. Considera job in qualche ordine.
 
 
[Minimo tempo di processamento] Considera job in ordine crescente di
tempo di processamento tj.
 
 
 
 
[Minima deadline] Considera job in ordine crescente di deadline dj.
 
Esempio:
1
2
3
4
5
tj
3
2
1
4
3
6
2
dj
6
8
9
9
14
15
ritardo = 2
d3 = 9
0
d2 = 8
1
2
d6 = 15
3
4
d1 = 6
5
6
ritardo = 0
max ritardo = 6
d5 = 14
7
8
9
[Slack minimo] Considera job in ordine crescente di tempo di slack dj - tj.
 
10
d4 = 9
11
12
13
14
15
45
46
Minimizzare Ritardo: Greedy Algorithms
Minimizzare Ritardo: Greedy Algorithms
Metodo Greedy. Considera job in qualche ordine.
Metodo Greedy. Considera job in qualche ordine.
[Minimo tempo di processamento] Considera job in ordine crescente di
tempo di processamento tj.
 
1
2
tj
1
10
dj
100
10
ritardo = 0
2
tj
1
10
dj
2
10
ritardo = 0
d2 = 10
scelta greedy
d2 = 10
1
d2 = 10
ritardo = 0
d1 = 100
10
10
ritardo = 0
ottimo
d1 = 2
11
0
47
controesempio
ritardo = 9
d1 = 2
0
11
ritardo = 0
0
controesempio
1
ritardo = 1
d1 = 100
0
[Slack minimo] Considera job in ordine crescente di tempo di slack dj - tj.
 
scelta greedy
11
ritardo = 1
ottimo
d2 = 10
1
11
48
Minimizzare Ritardo: Greedy Algorithm
Minimizzare Ritardo: Greedy Algorithm
Greedy algorithm. Minima deadline.
Greedy algorithm. Minima deadline.
Ordina n job per deadline d1 ≤ d2 ≤ … ≤ dn
Ordina n job per deadline d1 ≤ d2 ≤ … ≤ dn
t ← 0
for j = 1 to n
Assegna job j all intervallo [t, t + tj]
sj ← t, fj ← t + tj
t ← t + tj
output intervalli [sj, fj]
t ← 0
for j = 1 to n
Assegna job j all intervallo [t, t + tj]
sj ← t, fj ← t + tj
t ← t + tj
output intervalli [sj, fj]
tempo fine job assegnati
Esempio:
1
2
3
4
5
tj
3
2
1
4
3
6
2
dj
6
8
9
9
14
15
max ritardo = 1
d1 = 6
0
1
2
d2 = 8
3
4
d3 = 9
5
6
d4 = 9
7
8
d5 = 14
9
10
11
12
d6 = 15
13
14
49
Minimizzare Ritardo: Nessun tempo inattivo
d=4
1
d=6
2
3
2
3
d=4
0
1
4
6
5
6
d=6
4
Exchange argument.
  Consideriamo una schedulazione ottimale
  Modifichiamola gradualmente, preservando l’ottimalità ad ogni passo
  L’ultima schedulazione modificata è quella greedy
d = 12
5
7
50
Minimizzare Ritardo: Ottimalità Greedy Algorithm
Osservazione. Vi è una schedulazione ottimale senza tempi inattivi.
0
15
8
9
10
11
8
9
10
11
d = 12
7
Osservazione. La schedulazione greedy non ha tempi inattivi.
51
52
Minimizzare Ritardo: Inversions
Minimizzare Ritardo: Inversioni
Definizione. Una inversione nella schedulazione S è una coppia di job i e j
tale che: i < j ma j è schedulato prima di i.
Definizione. Una inversione nella schedulazione S è una coppia di job i e
j tale che: i < j ma j è schedulato prima di i.
inversione
inversione
j
prima dello scambio
i
dopo lo scambio
j
fi
i
i
j
f'j
Osservazione. La schedulazione greedy non ha inversioni.
Claim. Scambiando due job adiacenti ed invertiti, riduce il numero di
inversioni di 1 e non incrementa il ritardo massimo.
Osservazione. Se una schedulazione (senza tempi inattivi) ha una
inversione, allora ne ha una con job invertiti schedulati consecutivamente.
Prova. Sia  il ritardo prima dello scambio, e sia ' dopo lo scambio.
'k = k per tutti k ≠ i, j
'i ≤ i
' j = f!j - d j
(definizione)
Se job j è in ritardo:
= f -d
(j finisce al tempo f )
 
 
 
ricorda: j = max {0,fj-dj}
i
j
i
≤ fi - d i
(i < j)
≤ i
(definizione)
53
Minimizzare Ritardo: Analisi Algoritmo Greedy
54
Metodi per mostrare correttezza algoritmi greedy
Teorema. La schedulazione greedy S è ottimale.
L algoritmo greedy è sempre in vantaggio. Mostrare che dopo ogni passo
dell algoritmo greedy, la sua soluzione è almeno tanto buona come quella
Prova. Definiamo S* come una schedulazione ottimale con il minimo
numero di inversioni.
Possiamo assumere che S* non ha tempi inattivi.
Se S* non ha inversioni, allora S = S*.
Se S* ha almeno una inversione, sia i-j una inversione adiacente.
–  scambiando i e j non incrementiamo il ritardo massimo e
diminuiamo il numero di inversioni.
–  questo contraddice la definizione di S* ▪
di ogni altro algoritmo.
Argomento di scambio (Exchange argument). Trasformare gradualmente
una soluzione ottima a quella dell’algoritmo greedy lasciando il suo valore
ottimo.
 
 
 
Strutturale. Trovare un semplice limite strutturale che ogni soluzione
deve rispettare. Mostrare poi che l’algoritmo greedy raggiunge sempre
quel limite.
55
56
Caching offline ottimale
4.3 Optimal Caching
Caching.
Cache con capacità di memorizzare k elementi.
 
Sequenza di m richieste di elementi d1, d2, …, dm.
Cache hit: elemento già nella cache quando richiesto.
Cache miss: elemento non nella cache quando richiesto: è necessario
portarlo nella cache e rimuovere un altro elemento (se la cache è
piena).
Obiettivo. Schedulazione rimozioni che minimizzano il numero di cache
miss.
 
 
 
Esempio: k = 2, cache all’inizio = ab,
richieste: a, b, c, b, c, a, a, b.
Scedulazione ottimale rimozione: 2 cache miss
a
a
b
a
a
b
b
a
b
b
a
b
c
c
b
c
a
c
b
c
b
b
a
b
c
c
b
c
c
b
a
a
b
a
a
b
a
a
b
a
a
b
b
a
b
b
a
b
richieste
cache
58
Caching offline ottimale: Farthest-In-Future
Farthest-in-future. Rimuovere elemento nella cache che sarà richiesto il
più tardi possibile nel futuro.
occupazione cache:
richieste future:
a
b
c
d
e
4.4 Shortest Paths in a Graph
f
g a b c e d a b b a c d e a f a d e f g h ...
cache miss
rimuovere elemento f dalla cache
Cammino minimo dal campus Fisciano
alla stazione ferroviaria di Salerno
Teorema. Farthest-In-Future è una schedulazione ottimale delle rimozioni.
Prova. L’algoritmo ed il teorema sono intuitivi. Ma la prova non è immediata,
richiede attenzione e comporta una distinzione di casi. La trovate nel libro.
[L. Belady. A study of replacement algorithms for virtual storage computers.
IBM Systems Journal 5 (1966), 78-101.]
©2009 Google - Immagini ©2009 DigitalGlobe, Cnes/Spot Image, GeoEye, European Space Imaging, Map data ©2009 Tele Atlas -
Indicazioni stradali per Piazza Vittorio Veneto
14,5 km – circa 22 min
59
Problema cammino minimo
Algoritmo di Dijkstra
Dati input:
Grafo diretto G = (V, E).
Algoritmo di Dijkstra.
Mantenere l’insieme dei nodi esplorati S per i quali abbiamo
 
 
 
 
Sorgente s, destinazione t.
e = lunghezza arco e.
 
 
determinato le distanze dei cammini minimi d(u) da s ad u.
Inizializzare S = { s }, d(s) = 0.
Ripetutamente scegliere un nodo non esplorato v che minimizza
Problema del cammino minimo: trovare cammino minimo diretto da s a t.
π (v ) =
costo cammino = somma costi archi del cammino
24
2
9
s
30
aggiungere v a S, e porre d(v) = π(v).
Costo cammino s-2-3-5-t
= 9 + 24 + 2 + 16
= 51.
e
d(u)
Cammino minimo a qualche u nella
parte esplorata, seguito da un singolo
arco (u, v)
v
u
S
s
6
16
20
19
4
11
5
5
7
6
2
6
15
d (u ) +  e ,
3
18
14
min
e = (u , v ) : u ∈ S
t
44
61
Algoritmo di Dijkstra
62
Algoritmo di Dijkstra
Algoritmo di Dijkstra.
Mantenere l’insieme dei nodi esplorati S per i quali abbiamo
 
 
 
determinato le distanze dei cammini minimi d(u) da s ad u.
Inizializzare S = { s }, d(s) = 0.
Ripetutamente scegliere un nodo non esplorato v che minimizza
π (v ) =
min
e = (u , v ) : u ∈ S
d (u ) +  e ,
aggiungere v a S, e porre d(v) = π(v).
d(u)
e
π (v ) =
min
e = (u , v ) : u ∈ S
d (u ) +  e ,
Cammino minimo a qualche u nella
parte esplorata, seguito da un singolo
arco (u, v)
v
u
S
s
63
64
Algoritmo di Dijkstra: Prova di correttezza
Algoritmo di Dijkstra: Implementazione
Invariante. Per ogni nodo u ∈ S, d(u) è la lunghezza del cammino minimo s-u.
Per ogni nodo non ancora esplorato, calcola
Prova. (per induzione su |S|)
Caso base: |S| = 1 è banale.
 
Ipotesi induttiva: Assumiamo vera per |S| = k ≥ 1.
 
min
e = (u,v) : u ∈ S
d (u) +  e .
Prossimo nodo da esplorare = nodo con minimo π(v).
Quando esploriamo v, per ogni arco incidente e = (v, w), aggiorna
π (w) = min { π (w), π €
(v) +  e }.
Sia v il prossimo nodo aggiunto ad S, e sia u-v l’arco scelto.
 
π (v) =
Il cammino minimo s-u più (u, v) è un cammino minimo s-v di lunghezza π(v).
 
Sia P un cammino minimo s-v. Vediamo che non è più corto di π(v).
 
Sia x-y il primo arco in P che lascia S,
e sia P' il cammino da s a x (parte di P).
 
P'
u
S
v
 (P) ≥  (P') +  (x,y) ≥ d(x) +  (x, y) ≥ π(y) ≥ π(v)
pesi non
negativi
ipotesi
induttiva
 (P’) ≥ d(x)
€
y
x
s
P è già troppo lungo appena lascia S.
 
P
definizione
di π(y)
Dijkstra sceglie v
invece di y
65
66
Coda a priorità
Algoritmo di Dijkstra: Implementazione
Implementazioni:
Per ogni nodo non ancora esplorato, calcola π (v) =
5
min
14
89
32
30
24
15
6
. . . . .
24
28
15
10
9
17
81
19
 
 
13
d (u) +  e .
Prossimo nodo da esplorare = nodo con minimo π(v).
Quando esploriamo v, per ogni arco incidente e = (v, w), aggiorna
€+  }.
π (w) = min { π (w), π (v)
e
31
11
min
e = (u,v) : u ∈ S
Implementazione efficiente. Mantenere una coda a priorità dei nodi
non esplorati, sul campo π(v).
∅
€
Head
Priority Queue
Operazione PQ
Lista ordinata Lista non ordinata
(a puntatori)
(array)
Binary heap
Operazione PQ
Dijkstra
Array
Binary heap
Insert
O(n)
O(1)
O(log n)
Insert
n
n
log n
Min
O(1)
O(n)
O(1)
ExtractMin
n
1
log n
ExtractMin
O(1)
O(n)
O(log n)
ChangeKey
m
n
log n
ChangeKey
O(n)
O(1)
O(log n)
IsEmpty
n
1
1
IsEmpty
O(1)
O(1)
O(1)
Total
n2
m log n
67
68
Algoritmo di Dijkstra
Algoritmo di Dijkstra
Trovare cammino minimo da s a t.
S={ }
PQ = { s, 2, 3, 4, 5, 6, 7, t }
∞
∞
24
2
9
s
3
0
s
18
14
6
30
15
11
5
5
30
∞
11
5
5
6
16
t
7
distance label
∞
4
19
6
16
20
44
6
2
19
15
20
7
∞
6
4
3
18
14
6
2
24
2
9
t
44
∞
∞
69
70
Algoritmo di Dijkstra
Algoritmo di Dijkstra
S={ }
PQ = { s, 2, 3, 4, 5, 6, 7, t }
S={s}
PQ = { 2, 3, 4, 5, 6, 7, t }
decrease key
minimo
∞
∞
0
s
24
2
9
∞
0
s
30
15
∞
11
5
5
7
∞
30
19
16
44
∞
11
5
5
6
16
20
t
7
distance label
∞
71
∞ 15
X
6
2
6
∞
4
3
18
X
∞ 14
14
15
20
24
2
9
6
2
6
distance label
3
18
14
∞
∞ 9
X
44
∞
4
19
6
t
∞
72
Algoritmo di Dijkstra
Algoritmo di Dijkstra
S={s}
PQ = { 2, 3, 4, 5, 6, 7, t }
S = { s, 2 }
PQ = { 3, 4, 5, 6, 7, t }
minimo
∞
∞
X 9
0
s
24
2
9
30
∞
11
5
5
30
∞
11
5
5
6
t
7
∞
∞ 15
X
∞
4
19
6
16
20
44
6
2
6
19
3
18
X
∞ 14
14
∞
4
16
7
24
2
9
15
20
distance label
0
s
6
2
6
15
3
18
X
∞ 14
14
∞
∞
X 9
t
44
∞
∞ 15
X
73
74
Algoritmo di Dijkstra
Algoritmo di Dijkstra
S = { s, 2 }
PQ = { 3, 4, 5, 6, 7, t }
S = { s, 2 }
PQ = { 3, 4, 5, 6, 7, t }
decrease key
∞ 33
X
∞
X 9
0
s
24
2
9
30
∞
11
5
5
16
∞ 15
X
44
24
2
9
18
X
∞ 14
14
30
19
∞
11
5
5
6
16
20
t
7
∞
∞ 15
X
75
6
2
6
∞
4
3
minimo
15
20
7
0
s
6
2
6
15
3
18
X
∞ 14
14
∞ 33
X
∞
X 9
44
∞
4
19
6
t
∞
76
Algoritmo di Dijkstra
Dijkstra's Shortest Path Algorithm
S = { s, 2, 6 }
PQ = { 3, 4, 5, 7, t }
S = { s, 2, 6 }
PQ = { 3, 4, 5, 7, t }
∞
X 9
0
s
24
2
9
∞
X 9
3
0
s
30
44
X
∞
∞
11
5
5
30
19
44
X
∞
∞
11
5
5
6
16
t
7
∞
∞ 15
X
4
19
6
16
20
44
6
2
6
4
3
18
X
∞ 14
14
15
20
7
24
2
9
6
2
6
15
32
∞ 33
X
X
18
X
∞ 14
14
32
∞ 33
X
X
t
44
minimo
∞ 15
X
∞
77
78
Dijkstra's Shortest Path Algorithm
Dijkstra's Shortest Path Algorithm
S = { s, 2, 6, 7 }
PQ = { 3, 4, 5, t }
S = { s, 2, 6, 7 }
PQ = { 3, 4, 5, t }
∞
X 9
0
s
24
2
9
30
X 35
44
X
∞
5
5
∞ 15
X
∞
X 9
0
s
11
30
19
16
44
X 35
44
X
∞
5
5
6
t
7
∞ 15
X
79
∞
11
16
20
∞
59 X
6
2
6
4
3
18
X
∞ 14
14
6
∞
24
2
9
15
20
7
32
∞ 33
X
X
3
2
6
15
32
∞ 33
X
X
18
X
∞ 14
14
minimo
44
4
19
6
t
∞
59 X
80
Dijkstra's Shortest Path Algorithm
Algoritmo di Dijkstra
S = { s, 2, 3, 6, 7 }
PQ = { 4, 5, t }
S = { s, 2, 3, 6, 7 }
PQ = { 4, 5, t }
∞
X 9
0
s
24
2
9
∞
X 9
3
0
s
30
X 34
X 35
44
X
∞
5
5
∞
11
30
19
20
t
44
∞
11
4
19
6
16
minimo
7
∞
51 59
X X
∞ 15
X
X 34
X 35
44
X
∞
5
5
6
16
6
2
6
4
3
18
X
∞ 14
14
15
20
7
24
2
9
6
2
6
15
32
∞ 33
X
X
18
X
∞ 14
14
32
∞ 33
X
X
t
44
∞
51 59
X X
∞ 15
X
81
82
Dijkstra's Shortest Path Algorithm
Dijkstra's Shortest Path Algorithm
S = { s, 2, 3, 5, 6, 7 }
PQ = { 4, t }
S = { s, 2, 3, 5, 6, 7 }
PQ = { 4, t }
∞
X 9
0
s
24
2
9
30
X 34
X 35
44
X
∞
5
5
∞ 15
X
0
s
11
30
19
16
44
X 34
X 35
44
X
∞
5
5
6
t
7
∞ 15
X
83
∞
45 X
11
16
20
∞
50 51
X 59
X X
6
2
6
4
3
18
X
∞ 14
14
6
∞
45 X
24
2
9
15
20
7
∞
X 9
3
2
6
15
32
∞ 33
X
X
18
X
∞ 14
14
32
∞ 33
X
X
44
4
19
minimo
6
t
∞
50 51
X 59
X X
84
Dijkstra's Shortest Path Algorithm
Dijkstra's Shortest Path Algorithm
S = { s, 2, 3, 4, 5, 6, 7 }
PQ = { t }
S = { s, 2, 3, 4, 5, 6, 7 }
PQ = { t }
∞
X 9
0
s
24
2
9
∞
X 9
3
0
s
30
X 34
X 35
44
X
∞
5
5
∞
45 X
11
X 34
X 35
44
X
∞
5
5
6
16
7
30
19
t
7
∞
50 51
X 59
X X
∞ 15
X
∞
45 X
11
4
19
6
16
20
44
6
2
6
4
3
18
X
∞ 14
14
15
20
24
2
9
6
2
6
15
32
∞ 33
X
X
18
X
∞ 14
14
32
∞ 33
X
X
t
44
minimo
∞ 15
X
∞
50 51
X 59
X X
85
86
Algoritmo di Dijkstra
Algoritmo di Dijkstra
S = { s, 2, 3, 4, 5, 6, 7, t }
PQ = { }
S = { s, 2, 3, 4, 5, 6, 7, t }
PQ = { }
∞
X 9
0
s
24
2
9
30
X 34
X 35
44
X
∞
5
5
∞ 15
X
0
s
11
30
19
16
44
X 34
X 35
44
X
∞
5
5
6
t
7
∞ 15
X
87
∞
45 X
11
16
20
∞
50 51
X 59
X X
6
2
6
4
3
18
X
∞ 14
14
6
∞
45 X
24
2
9
15
20
7
∞
X 9
3
2
6
15
32
∞ 33
X
X
18
X
∞ 14
14
32
∞ 33
X
X
44
4
19
6
t
∞
50 51
X 59
X X
88
Edsger Wybe Dijkstra
4.5 Minimum Spanning Tree
Rotterdam, 11 maggio 1930 – Nuenen, 6 agosto 2002
A note on two problems in connection with graphs
Numerische Matematik, vol. 1, 1959, pp. 269-271
89
Minimum Spanning Tree
Minimum Spanning Tree
Abbiamo un insieme di locazioni e vogliamo costruire una rete di
comunicazione tra loro:
Dato un grafo connesso G = (V, E) con pesi a valori reali ce>0 sugli archi,
trovare un insieme di archi T ⊆ E tale che il grafo (V,T) è connesso e la
  rete connessa: ci deve essere un cammino tra ogni coppia
  economicità: costo totale più basso possibile
somma dei pesi degli archi in T è minimizzata.
24
4
23
6
16
18
5
9
14
10
9
6
5
11
8
7
24
4
4
8
6
11
16
7
18
5
9
14
9
6
5
11
8
10
21
4
23
7
8
11
7
21
Costo totale 50
G = (V, E)
91
T, Σe∈T ce = 50
92
Minimum Spanning Tree
Minimum Spanning Tree (MST)
Dato un grafo connesso G = (V, E) con pesi a valori reali ce>0 sugli archi,
trovare un insieme di archi T ⊆ E tale che il grafo (V,T) è connesso e la
Minimum spanning tree. Dato un grafo connesso G = (V, E) con pesi a
valori reali ce sugli archi, un MST è un sottoinsieme degli archi T ⊆ E
somma dei pesi degli archi in T è minimizzata.
24
4
16
18
5
9
14
10
9
6
5
11
8
7
24
4
4
23
6
tale che T è uno spanning tree la cui somma dei pesi sugli archi è
minimizzata.
8
6
11
16
7
18
5
9
14
9
6
5
11
8
10
21
4
23
7
8
11
7
21
G = (V, E)
G = (V, E)
T, Σe∈T ce = 50
Lemma. Sia T la soluzione. Allora (V,T) è un albero.
Prova. (V,T) è connesso. Facciamo vedere che non ha cicli.
Per assurdo: se ci fosse un ciclo, prendiamo un arco in tale ciclo.
Il grafo (V,T-{e}) è ancora connesso ed ha costo minore. Contraddizione.
T, Σe∈T ce = 50
Teorema di Cayley. Ci sono nn-2 spanning tree di Kn.
non si può risolvere con brute force
93
94
Applicazioni
Algoritmi Greedy
MST è un problema fondamentale con svariate applicazioni.
 
 
 
 
Algoritmo di Kruskal.
  Inizia con T = φ.
Network design.
–  telephone, electrical, hydraulic, TV cable, computer, road
  Considera archi in ordine crescente di costo.
  Inserisci l’arco in T se non crea un ciclo.
Approximation algorithms for NP-hard problems.
–  traveling salesperson problem, Steiner tree
Algoritmo di Reverse-Delete.
  Inizia con T = E.
  Considera archi in ordine decrescente di costo.
  Cancella l’arco da T se non disconnette T.
Indirect applications.
–  max bottleneck paths
–  LDPC codes for error correction
–  image registration with Renyi entropy
–  learning salient features for real-time face verification
–  reducing data storage in sequencing amino acids in a protein
–  model locality of particle interactions in turbulent fluid flows
–  autoconfig protocol for Ethernet bridging to avoid cycles in a network
Algoritmo di Prim.
  Inizia con T = φ e con un nodo radice s.
  Aggiungi arco a T che è incidente solo su un nodo in T e con costo minimo.
Nota bene. Tutti e tre gli algoritmi producono un MST.
Cluster analysis.
95
96
Algoritmi di Prim e di Kruskal
Algoritmo di Prim
Algoritmo di Prim.
 
Inizia con T = φ e con un nodo radice s.
 
Aggiungi arco a T che è incidente solo su un nodo in T e con il costo minimo.
Trovare Minimo Spanning Tree.
  Inizia con T = φ e con un nodo radice s.
 
Aggiungi arco a T che è incidente solo su un nodo in T e con costo minimo.
T=φ
24
2
9
s
3
18
14
30
15
11
5
5
Algoritmo di Kruskal.
 
Inizia con T = φ.
 
Considera archi in ordine crescente di costo.
 
Inserisci l’arco in T se non crea un ciclo.
6
2
6
4
19
7
16
20
7
t
44
97
98
Algoritmo di Prim
Algoritmo di Prim
Trovare Minimo Spanning Tree.
  Inizia con T = φ e con un nodo radice s.
 
Trovare Minimo Spanning Tree.
  Inizia con T = φ e con un nodo radice s.
Aggiungi arco a T che è incidente solo su un nodo in T e con costo minimo.
 
T = { {s,2} }
Aggiungi arco a T che è incidente solo su un nodo in T e con costo minimo.
T = { {s,2}, {s,6} }
24
2
9
s
3
s
18
14
30
15
11
5
5
16
20
7
30
19
15
44
11
5
5
7
16
20
t
7
99
6
2
6
4
3
18
14
6
2
6
24
2
9
44
4
19
7
t
100
Algoritmo di Prim
Algoritmo di Prim
Trovare Minimo Spanning Tree.
  Inizia con T = φ e con un nodo radice s.
 
Trovare Minimo Spanning Tree.
  Inizia con T = φ e con un nodo radice s.
Aggiungi arco a T che è incidente solo su un nodo in T e con costo minimo.
 
T = { {s,2}, {s,6}, {6,7} }
T = { {s,2}, {s,6}, {6,7}, {6,3} }
24
2
9
s
3
s
30
11
5
5
11
5
5
7
16
20
7
30
19
15
t
4
19
7
16
20
44
6
2
6
4
3
18
14
6
2
6
24
2
9
18
14
15
Aggiungi arco a T che è incidente solo su un nodo in T e con costo minimo.
7
t
44
101
102
Algoritmo di Prim
Algoritmo di Prim
Trovare Minimo Spanning Tree.
  Inizia con T = φ e con un nodo radice s.
 
Trovare Minimo Spanning Tree.
  Inizia con T = φ e con un nodo radice s.
Aggiungi arco a T che è incidente solo su un nodo in T e con costo minimo.
 
T = { {s,2}, {s,6}, {6,7}, {6,3}, {3,5} }
T = { {s,2}, {s,6}, {6,7}, {6,3}, {3,5}, {3,4} }
24
2
9
s
3
s
30
11
5
5
16
20
7
30
19
15
44
11
5
5
7
16
20
t
7
103
6
2
6
4
3
18
14
6
2
6
24
2
9
18
14
15
Aggiungi arco a T che è incidente solo su un nodo in T e con costo minimo.
44
4
19
7
t
104
Algoritmo di Prim
Algoritmo di Kruskal
Trovare Minimo Spanning Tree.
  Inizia con T = φ e con un nodo radice s.
 
Trovare Minimo Spanning Tree.
  Inizia con T = φ.
Aggiungi arco a T che è incidente solo su un nodo in T e con costo minimo.
 
 
T = { {s,2}, {s,6}, {6,7}, {6,3}, {3,5}, {3,4}, {4,t} }
Considera archi in ordine crescente di costo.
Inserisci l’arco in T se non crea un ciclo.
T=φ
24
2
9
s
3
s
18
14
30
15
11
5
5
11
5
5
7
16
20
7
30
19
15
t
4
19
7
16
20
44
6
2
6
4
3
18
14
6
2
6
24
2
9
7
t
44
105
106
Algoritmo di Kruskal
Algoritmo di Kruskal
Trovare Minimo Spanning Tree.
  Inizia con T = φ.
 
 
Trovare Minimo Spanning Tree.
  Inizia con T = φ.
Considera archi in ordine crescente di costo.
Inserisci l’arco in T se non crea un ciclo.
 
 
T = { {3,5} }
Considera archi in ordine crescente di costo.
Inserisci l’arco in T se non crea un ciclo.
T = { {3,5}, {6,7} }
24
2
9
s
3
s
18
14
30
15
11
5
5
16
20
7
30
19
15
44
11
5
5
7
16
20
t
7
107
6
2
6
4
3
18
14
6
2
6
24
2
9
44
4
19
7
t
108
Algoritmo di Kruskal
Algoritmo di Kruskal
Trovare Minimo Spanning Tree.
  Inizia con T = φ.
 
 
Trovare Minimo Spanning Tree.
  Inizia con T = φ.
Considera archi in ordine crescente di costo.
Inserisci l’arco in T se non crea un ciclo.
 
 
T = { {3,5}, {6,7}, {3,4} }
T = { {3,5}, {6,7}, {3,4}, {4,t} }
24
2
9
s
3
s
30
11
5
5
11
5
5
7
16
20
7
30
19
15
t
4
19
7
16
20
44
6
2
6
4
3
18
14
6
2
6
24
2
9
18
14
15
Considera archi in ordine crescente di costo.
Inserisci l’arco in T se non crea un ciclo.
7
t
44
109
110
Algoritmo di Kruskal
Algoritmo di Kruskal
Trovare Minimo Spanning Tree.
  Inizia con T = φ.
 
 
Trovare Minimo Spanning Tree.
  Inizia con T = φ.
Considera archi in ordine crescente di costo.
Inserisci l’arco in T se non crea un ciclo.
 
 
T = { {3,5}, {6,7}, {3,4}, {4,t}, {s,2} }
T = { {3,5}, {6,7}, {3,4}, {4,t}, {s,2} }
24
2
9
s
3
s
30
11
5
5
16
20
7
30
19
15
44
11
5
5
7
16
20
t
7
111
6
2
6
4
3
18
14
6
2
6
24
2
9
18
14
15
Considera archi in ordine crescente di costo.
Inserisci l’arco in T se non crea un ciclo.
44
4
19
7
t
112
Algoritmo di Kruskal
Algoritmo di Kruskal
Trovare Minimo Spanning Tree.
  Inizia con T = φ.
 
 
Trovare Minimo Spanning Tree.
  Inizia con T = φ.
Considera archi in ordine crescente di costo.
Inserisci l’arco in T se non crea un ciclo.
 
 
T = { {3,5}, {6,7}, {3,4}, {4,t}, {s,2}, {s,6} }
T = { {3,5}, {6,7}, {3,4}, {4,t}, {s,2}, {s,6} }
24
2
9
s
3
s
30
15
11
5
5
11
5
5
7
16
20
7
30
19
15
t
4
19
7
16
20
44
6
2
6
4
3
18
14
6
2
6
24
2
9
18
14
Considera archi in ordine crescente di costo.
Inserisci l’arco in T se non crea un ciclo.
7
t
44
113
114
Algoritmo di Kruskal
Algoritmo di Kruskal
Trovare Minimo Spanning Tree.
  Inizia con T = φ.
 
 
Trovare Minimo Spanning Tree.
  Inizia con T = φ.
Considera archi in ordine crescente di costo.
Inserisci l’arco in T se non crea un ciclo.
 
 
T = { {3,5}, {6,7}, {3,4}, {4,t}, {s,2}, {s,6} }
T = { {3,5}, {6,7}, {3,4}, {4,t}, {s,2}, {s,6}, {3,6} }
24
2
9
s
3
s
30
15
11
5
5
16
20
7
30
19
15
44
11
5
5
7
16
20
t
7
115
6
2
6
4
3
18
14
6
2
6
24
2
9
18
14
Considera archi in ordine crescente di costo.
Inserisci l’arco in T se non crea un ciclo.
44
4
19
7
t
116
Algoritmi Greedy
Cicli e tagli
Assunzione per semplificare. Tutti i costi degli archi ce sono distinti.
Ciclo. Insieme di archi della forma a-b, b-c, c-d, …, y-z, z-a.
Proprietà di taglio. Sia S un sottoinsieme di nodi, e sia e l’arco con il
minimo costo che è incidente su esattamente un nodo in S. Allora l’MST
contiene e.
1
2
3
6
4
Ciclo C = 1-2, 2-3, 3-4, 4-5, 5-6, 6-1
5
Proprietà del ciclo. Sia C un ciclo, e sia f l’arco con il massimo costo in C.
Allora l’MST non contiene f.
f
S
8
7
Cutset (Insieme di taglio). Un cut (taglio) è un insieme di nodi S.
L’insieme di taglio corrispondente D è il sottoinsieme di archi che sono
incidenti su esattamente un nodo in S.
C
e
1
2
3
6
e è nell’MST
Cut S
= { 4, 5, 8 }
Cutset D = 5-6, 5-7, 3-4, 3-5, 7-8
4
5
f non è nell’MST
7
8
117
118
Intersezione Ciclo-Taglio
Algoritmi Greedy
Claim. Un ciclo ed un cutset si intersecano in un numero pari di archi.
2
1
3
6
4
Assunzione per semplificare. Tutti i costi degli archi ce sono distinti.
Proprietà del taglio. Sia S un sottoinsieme di nodi e sia e l’arco di costo
minimo che incide su esattamente un nodo in S. Allora l’MST T*
contiene e.
Ciclo C = 1-2, 2-3, 3-4, 4-5, 5-6, 6-1
Cutset D = 3-4, 3-5, 5-6, 5-7, 7-8
Intersezione = 3-4, 5-6
5
Prova. (per assurdo, usando una argomentazione di scambio)
Supponiamo che e non appartiene a T*.
Aggiungere e a T* crea un ciclo C in T*.
L’arco e è sia nel ciclo C e nel cutset D corrispondente ad S ⇒
esiste un altro arco, diciamo f, che è sia in C che in D.
8
7
 
 
Prova.
 
C
S
f
S
V-S
e
119
T*
120
Algoritmi Greedy
Algoritmi greedy
Assunzione per semplificare. Tutti i costi degli archi ce sono distinti.
Assunzione per semplifare. Tutti i costi degli archi ce sono distinti.
Proprietà del taglio. Sia S un sottoinsieme di nodi e sia e l’arco di costo
minimo che incide su esattamente un nodo in S. Allora l’MST T*
contiene e.
Proprietà del ciclo. Sia C un ciclo in G, e sia f l’arco di costo massimo in C.
Allora l’MST T* non contiene f.
Prova. (per assurdo, usando una argomentazione di scambio)
Supponiamo che f sia in T*.
La cancellazione di f da T* crea un taglio S in T*.
L’arco f è sia nel ciclo C sia nel cutset D corrispondente ad S ⇒
esiste un altro arco, diciamo e, che è sia in C che in D.
Prova. (per assurdo, usando una argomentazione di scambio)
Supponiamo che e non appartiene a T*.
Aggiungere e a T* crea un ciclo C in T*.
L’arco e è sia nel ciclo C e nel cutset D corrispondente ad S ⇒
esiste un altro arco, diciamo f, che è sia in C che in D.
T' = T* ∪ { e } - { f } è ancora uno spanning tree.
Dato che ce < cf, cost(T') < cost(T*).
f
Questa è una contraddizione. ▪
 
 
 
 
 
 
 
 
f
S
 
S
e
e
T*
T*
121
Algoritmi greedy
122
Algoritmo di Prim: Prova di correttezza
Assunzione per semplifare. Tutti i costi degli archi ce sono distinti.
Algoritmo di Prim. [Jarník 1930, Dijkstra 1957, Prim 1959]
Initializza S = un nodo qualsiasi.
 
Proprietà del ciclo. Sia C un ciclo in G, e sia f l’arco di costo massimo in C.
Allora l’MST T* non contiene f.
 
 
Prova. (per assurdo, usando una argomentazione di scambio)
Supponiamo che f sia in T*.
La cancellazione di f da T* crea un taglio S in T*.
L’arco f è sia nel ciclo C sia nel cutset D corrispondente ad S ⇒
esiste un altro arco, diciamo e, che è sia in C che in D.
T' = T* ∪ { e } - { f } è ancora uno spanning tree.
Dato che ce < cf, cost(T') < cost(T*).
Questa è una contraddizione.
Applica la proprietà del taglio ad S.
Aggiungi l’arco di costo minimo nel cutset corrispondente ad S a T,
ed aggiungi un nuovo nodo esplorato u ad S.
 
 
S
 
 
 
 
f
S
e
T*
123
124
Algoritmo di Prim: implementazione
Algoritmo di Kruskal: Prova di correttezza
Implementazione. Usare Coda a Priorità.
Mantenere insieme di nodi esplorati S.
Algoritmo di Kruskal. [Kruskal, 1956]
Considera archi in ordine crescente di peso.
 
 
 
 
Per ogni nodo non esplorato v, mantenere a[v] = costo minimo di un
cammino per v con nodi in S.
O(n2) con un array; O(m log n) con un binary heap.
Prim(G, c) {
foreach (v
Initialize
foreach (v
Initialize
 
 
Caso 1: Se l’aggiunta di e a T crea un ciclo, ignora e.
Caso 2: Altrimenti, inserisci e = (u, v) in T (proprietà del taglio
dove S = insieme di nodi nella componente connessa di u).
∈ V) a[v] ← ∞
an empty priority queue Q
∈ V) insert v onto Q
set of explored nodes S ← φ
v
while (Q is not empty) {
u ← delete min element from Q
S ← S ∪ { u }
foreach (edge e = (u, v) incident to u)
if ((v ∉ S) and (ce < a[v]))
decrease priority a[v] to ce
e
u
Case 2
Case 1
}
S
e
125
126
Algoritmo di Kruskal: implementazione
Lexicographic Tiebreaking
Implementazione. Usa la struttura dati union-find.
Costruisci insieme T di archi nel MST.
Per rimuovere l’assunzione che tutti gli archi hanno costi distinti:
perturba tutti i costi di piccolissime quantità per evitare lo stesso
 
 
 
Mantenere insieme per ogni componente connessa.
O(m log n) per ordinamento e O(m α(m, n)) per union-find.
m ≤ n2 ⇒ log m è O(log n)
costo.
Impatto. Kruskal e Prim effettuano solo confronti tra costi. Se le
perturbazioni sono molto piccole, l’MST con i costi perturbati è l’MST
con i costi originali.
essenzialmente una costante
Kruskal(G, c) {
Sort edges weights so that c1 ≤ c2 ≤ ... ≤ cm.
T ← φ
e.g., se tutti i costi fossero interi,
perturba il costo di ei di i / n2
Implementazione. Possiamo gestire perturbazioni arbitrariamente
piccole in modo implicito: lessicograficamente, secondo gli indici.
foreach (u ∈ V) costruisci insieme con solo u
Sono u e v in componenti connesse diverse?
for i = 1 to m
(u,v) = ei
if (u e v sono in insiemi diversi) {
T ← T ∪ {ei}
merge insiemi contenenti u e v
}
merge due componenti connesse
return T
boolean less(i, j) {
if
(cost(ei) < cost(ej))
else if (cost(ei) > cost(ej))
else if (i < j)
else
}
}
127
return
return
return
return
true
false
true
false
128
Esercizio 8 pag. 192
4.8 Huffman Codes and Data Compression
Sia G un grafo connesso in cui tutti gli archi hanno costi distinti.
Allora G ha un unico MST.
Prova. (per assurdo, usando una argomentazione di scambio)
Supponiamo che G abbia due spanning tree minimi diversi: T1 e T2.
Sia e l’arco di minimo costo che si trova in uno dei due spanning tree
e non nell’altro. Supponiamo che l’arco e sia in T1 ma non in T2.
Aggiungere l’arco e a T2 crea un ciclo C.
Vi deve essere almeno un arco nel ciclo C che non è in T1. (Altrimenti
T1 conterrebbe un ciclo). Sia f tale arco.
T2' = T2 ∪ { e } - { f } è ancora uno spanning tree.
Dato che ce < cf, cost(T2') < cost(T2).
Questa è una contraddizione della minimalità di T2.
 
 
 
 
 
 
 
129
Codifica simboli usando bit
Codice Morse
Codifica di 32 caratteri: 26 lettere, spazio, ed i cinque simboli , . ?!’
5 bit per un totale di 25=32 simboli
00000  a
00001  b
…
I simboli hanno diverse frequenze di occorrenza
“e” occorre più frequentemente di “q”
Samuel Finley Breese Morse
(Apr. 27, 1791-Apr. 2. 1872)
italiano
131
132
Codici
Compressione Dati
Spesso è importante trovare un modo efficiente per rappresentare i
dati, cercando di minimizzare il numero di bit usati
carattere
a
b
c
d
e
f
  si occupa meno spazio in memoria
  si risparmia sul tempo di trasferimento
Frequenza su 100
45
13
12
16
9
5
Lunghezza fissa
000
001
010
011
100
101
100
101
111
1101
1100
Lunghezza variabile 0
Codice a lunghezza fissa
(Tutti i caratteri sono codificati con lo stesso numero di bit)
per 100.000 caratteri servono 300.000 bit
Codice a lunghezza variabile
(I caratteri sono codificati con un numero variabile di bit)
per 100.000 caratteri servono solo
45.000x1 + 13.000x3 + 12.000x3 + 16.000x3 + 9.000x4 + 5.000x4 = 224.000 bit
133
134
Codifica e decodifica
Codifica e decodifica
carattere
a
b
c
d
e
f
carattere
a
b
c
d
e
f
Frequenza su 100
45
13
12
16
9
5
Frequenza su 100
45
13
12
16
9
5
Lunghezza fissa
000
001
010
011
100
101
Lunghezza fissa
000
001
010
011
100
101
100
101
111
1101
1100
Lunghezza variabile 0
100
101
111
1101
1100
Lunghezza variabile 0
Codice a lunghezza fissa:
aac…
Codice a lunghezza fissa:
000000010…
Codice a lunghezza variabile:
aac…
000000010…
aac…
Codice a lunghezza variabile:
00101…
aac…
Codice prefisso: nessuna parola codice
è prefisso di altra parola codice
00101…
135
136
Codifica e decodifica
Codifica e decodifica
carattere
a
b
c
d
e
f
carattere
a
b
c
d
e
f
Frequenza su 100
45
13
12
16
9
5
Frequenza su 100
45
13
12
16
9
5
Lunghezza fissa
000
001
010
011
100
101
Lunghezza fissa
000
001
010
011
100
101
100
101
111
1101
1100
Lunghezza variabile 0
100
101
111
1101
1100
Lunghezza variabile 0
Codice a lunghezza fissa:
aac…
Codice a lunghezza variabile:
aac…
000000010…
Codice prefisso: nessuna parola codice
è prefisso di altra parola codice
00101…
Decodifica codici prefisso: Scorrendo la stringa di bit,
Codice a lunghezza variabile:
aac…
o  si leggono bit in sequenza fino a che non troviamo una parola codice,
Codice prefisso: nessuna parola codice
è prefisso di altra parola codice
00101…
o  scriviamo il carattere corrispondente.
Se avessimo codificato a 1
Come si decodifica 1101 ?
ac e
137
138
Esercizio decodifica
Alberi binari e codici prefissi
I codici prefisso possono essere rappresentati come alberi binari.
A
B
C
D
E
0
11
100
1010
1011
11010010010101011
A
B
C
D
E
A
B
C
D
E
00
01
10
110
111
00
010
011
100
101
0
0
1
0
A
  Ogni foglia rappresenta un carattere
100100101010
1
0
B
0
1
C
1
D
E
  Ogni arco sinistro è etichettato con 0, ed ogni arco destro è
etichettato con 1
  Parola codice di ogni foglia è la sequenza di etichette del percorso
dalla radice
139
140
Alberi binari e codici prefissi
Lunghezza codifica
Abbiamo:
un file composto da caratteri nell alfabeto S
 
 
un albero T che rappresenta la codifica
Quanti bit occorrono per codificare il file con T ?
Per ogni x∈S, sia dT(x) la profondità in T della foglia che rappresenta x
La parola codice per x è lunga dT(x) bit
f(x) è il numero di volte che x occorre nel file.
 
 
 
La dimensione del file codificato è
∑ f (x)d
T
(x)
x∈S
141
142
€
Codici
Problema: trovare il codice prefisso ottimo
carattere
a
b
c
d
e
f
Frequenza su 100
45
13
12
16
9
5
Lunghezza fissa
000
001
010
011
100
101
100
101
111
1101
1100
Lunghezza variabile 0
Problema del codice prefisso ottimo: Dato un alfabeto S e le frequenze
dei caratteri f(x), per x∈S, trovare il codice prefisso T che minimizza
∑ f (x)d
T
(x)
albero
x∈S
∑ f (x)d
T
€
(x)
x∈S
45x3 + 13x3 + 12x3 + 16x3 + 9x3 + 5x3
= 300.000 bit
45x1 + 13x3 + 12x3 + 16x3 + 9x4 + 5x4
= 224.000 bit
143
€
144
Problema: trovare il codice prefisso ottimo
Domanda
Potrebbe essere ottimo per un alfabeto S con 6 caratteri e
frequenze f(x)>0, per x∈S ?
Problema del codice prefisso ottimo: Dato un alfabeto S e le frequenze
dei caratteri f(x), per x∈S, trovare il codice prefisso T che minimizza
∑ f (x)d
T
albero
(x)
x∈S
Vediamo qualche proprietà del codice/albero ottimale
€
A
000
B
001
C
010
D
011
E
100
F
101
145
146
Domanda
Proprietà: gli alberi ottimi sono pieni
Potrebbe essere ottimo per un alfabeto S con 6 caratteri e
frequenze f(x)>0, per x∈S ? No!
A
000
A
000
B
001
B
001
C
010
C
D
011
D
E
100
F
101
inutile
L’albero binario corrispondente ad un codice ottimo è pieno (full).
Ovvero, ogni nodo interno ha due figli.
A
000
A
000
B
001
B
001
010
C
010
C
010
011
D
011
D
011
E
10
E
100
E
10
F
11
F
101
F
11
E’ migliore!
147
inutile
E’ migliore!
148
Domanda
Domanda
Potrebbe essere ottimo questo codice prefisso?
frequenza
Potrebbe essere ottimo questo codice prefisso? No!
parola
codice
frequenza
parola
codice
A
25
00
A
25
00
B
25
010
B
25
010
C
6
0110
C
6
0110
D
6
0111
D
6
0111
E
13
10
E
13
10
F
25
11
F
25
11
Guadagno in lunghezza
scambio
∑ f (x)d
T
x∈S
(x) − ∑ f (x)dT$ (x)
x∈S
(25x3 + 13x2) – (25x2 + 13x3) = (75+26)-(50+39) = 101-89 = 12
149
150
Proprietà: associazione caratteri con parole codice
Proprietà: associazione caratteri con parole codice
Teorema. Sia T un albero prefisso ottimale per l’alfabeto S con
frequenze f(x), per x∈S. Se dT(x) > dT(y) allora f(x) ≤ f(y).
Teorema. Sia S un alfabeto con frequenze f(x), per x∈S. Siano x,y∈S
caratteri con le frequenze più basse, f(x) ≤ f(y). Allora esiste un codice
ottimale con albero T* in cui x,y corrispondono a foglie che sono fratelli.
Prova. (per assurdo) Supponiamo che f(x) > f(y).
Scambiamo le parole codice. Il guadagno in lunghezza è:
dT(x) f(x) + dT(y) f(y) – dT(x) f(y) - dT(y) f(x)
= (dT(x) - dT(y)) (f(x) – f(y)) > 0
Esempio
frequenza
frequenza
parola
codice
parola
codice
A
25
00
B
25
010
x
6
0110
y
6
0111
E
13
10
F
25
11
A
25
00
x
25
010
C
6
0110
D
6
0111
y
13
10
F
25
11
y
scambio
x
151
x
y
152
Proprietà: scelta greedy
Proprietà: scelta greedy
Teorema. Sia S un alfabeto S con frequenze f(x), per x∈S. Siano x,y∈S
caratteri con le frequenze più basse, f(x) ≤ f(y). Allora esiste un codice
Teorema. Sia S un alfabeto S con frequenze f(x), per x∈S. Siano x,y∈S
caratteri con le frequenze più basse, f(x) ≤ f(y). Allora esiste un codice
ottimale con albero T* in cui x,y corrispondono a foglie che sono fratelli.
ottimale con albero T* in cui x,y corrispondono a foglie che sono fratelli.
Prova. Sia T un albero che rappresenta un
codice ottimo.
Costruiamo un albero T* ancora ottimo ma
con i caratteri x,y foglie figlie dello stesso
padre z e a profondità massima in T*.
Prova. Sia T un albero che rappresenta un
codice ottimo.
Costruiamo un albero T* ancora ottimo ma
con i caratteri x,y foglie figlie dello stesso
padre z e a profondità massima in T*.
Assumiamo f(u) ≤ f(v).
Quindi f(x) ≤ f(u) e f(y) ≤ f(v).
Assumiamo f(u) ≤ f(v).
Quindi f(x) ≤ f(u) e f(y) ≤ f(v).
y
x
Scambiamo x ed u.
Il guadagno in lunghezza è:
dT(x) f(x) + dT(u) f(u) – dT(x) f(u) – dT(u) f(x)
= (dT(x) – dT(u)) (f(x) – f(u)) > 0
z
u
y
u
v
x
z
u
v
x
153
Proprietà: scelta greedy
154
Sottoproblema
Teorema. Sia S un alfabeto S con frequenze f(x), per x∈S. Siano x,y∈S
caratteri con le frequenze più basse, f(x) ≤ f(y). Allora esiste un codice
ottimale con albero T* in cui x,y corrispondono a foglie che sono fratelli.
Prova. Sia T un albero che rappresenta un
codice ottimo.
Costruiamo un albero T* ancora ottimo ma
con i caratteri x,y foglie figlie dello stesso
padre z e a profondità massima in T*.
Assumiamo f(u) ≤ f(v).
Quindi f(x) ≤ f(u) e f(y) ≤ f(v).
Scambiamo x ed u.
Il guadagno in lunghezza è:
dT(x) f(x) + dT(u) f(u) – dT(x) f(u) – dT(u) f(x)
= (dT(x) – dT(u)) (f(x) – f(u)) > 0
Scambiamo y e v.
Il guadagno in lunghezza è:
dT(y) f(y) + dT(v) f(v) – dT(y) f(v) – dT(v) f(y)
= (dT(y) – dT(v)) (f(y) – f(v)) > 0
y
u
x
v
z
u
v
x
y
155
156
Esempio
F:5
Esempio
E:9 C:12 B:13 D:16 A:45
C:12 B:13 D:16 A:45
F:5 E:9
157
158
Esempio
Esempio
C:12 B:13 D:16 A:45
C:12 B:13
14
D:16 A:45
F:5 E:9
14
F:5 E:9
159
160
Esempio
14
Esempio
D:16 A:45
14
F:5 E:9
D:16
F:5 E:9
25
A:45
C:12 B:13
25
C:12 B:13
161
162
Esempio
Esempio
25
A:45
25
C:12 B:13
C:12 B:13
14
D:16
F:5 E:9
30
14
A:45
30
D:16
F:5 E:9
163
164
Esempio
A:45
Esempio
100
55
25
A:45
30
C:12 B:13
D:16
14
55
25
F:5 E:9
C:12 B:13
30
14
D:16
F:5 E:9
165
Esempio
166
Algoritmo di Huffman
100
0
1
A:45
55
0
frequenza
parola
codice
A
45
0
B
13
101
C
12
100
D
16
111
E
9
1100
F
5
1101
1
25
0
30
1
0
C:12 B:13
D:16
14
0
1
1
F:5 E:9
167
168
Algoritmo di Huffman: implementazione
Codici di Huffman: correttezza
Huffman(A, n) {
Inizializza coda a priorità vuota Q
for i=1 to n {
insert A[i] in Q
}
for i=1 to n-1 {
x ← estrai elemento minimo da Q
y ← estrai elemento minimo da Q
Crea nuovo albero con radice z e
frequenza f(x)+f(y) e figli x e y
Insert z in Q
}
}
Teorema: L’algoritmo di Huffman produce un codice prefisso ottimo
Prova.
Dato che l algoritmo è ricorsivo, la prova è per induzione sulla cardinalità dell alfabeto.
L asserto è vero per k=2, cioè per un alfabeto con due simboli.
Supponiamo che sia ottimale per tutti gli alfabeti con k-1 simboli.
Mostreremo che è ottimale per gli alfabeti con k simboli.
Ricordiamo: Teorema. Sia S un alfabeto con frequenze f(x). Siano
x,y∈S caratteri con le frequenze più basse, f(x) ≤ f(y).
Allora esiste un codice ottimale con albero T in cui x,y
corrispondono a foglie che sono fratelli.
Operazione PQ
Huffman
Array
Binary Heap
Insert
2n-1
n
log n
ExtractMin
2n-1
n
log n
ChangeKey
0
1
log n
IsEmpty
0
1
1
O(n2)
O(n log n)
Total
Mostreremo che:
∑ f (x)d
T'
(x) = ∑ f (x)dT (x) − f (z)
x∈S
c∈S
Mostreremo che se T non fosse ottimale allora
T'
x∈S
170
x’
€Prova.
∑ f (x)d
T
(x) = f (x')dT (x') + f (y')dT (y') +
x∈S
Teorema: L algoritmo di Huffman produce un codice prefisso ottimo
Prova.
z
x∈S
∑ f (x)d
T
Dato che l algoritmo è ricorsivo, la prova è per induzione sulla cardinalità dell alfabeto.
L asserto è vero per k=2, cioè per un alfabeto con due simboli.
y’
Supponiamo che sia ottimale per tutti gli alfabeti con k-1 simboli.
Mostreremo che è ottimale per gli alfabeti con k simboli.
(x)
Ricordiamo: Teorema. Sia S un alfabeto con frequenze f(x). Siano
x≠x',y'
= ( f (x') + f (y'))(1+ dT (z)) +
x,y∈S caratteri con le frequenze più basse, f(x) ≤ f(y).
Allora esiste un codice ottimale con albero T in cui x,y
corrispondono a foglie che sono fratelli.
∑ f (x)dT ' (x)
x≠x',y'
= f (z)(1+ dT ' (z)) +
Abbiamo visto che:
x≠x',y'
∑ f (x)d
T'
(x)
∑ f (x)d
T'
x≠x',y'
x∈S
(x) = ∑ f (x)dT (x) − f (z)
c∈S
Mostreremo che se T non fosse ottimale allora
= f (z) + ∑ f (x)dT ' (x)
z
x’
y’
non lo sarebbe neanche T ‘.
x∈S
171
€
T
Sia T ‘ =T U {z} - {x’,y’}
∑ f (x)dT ' (x)
= f (z) + f (z)dT ' (z) +
y’
Codici di Huffman: correttezza
T
(x) = ∑ f (x)dT (x) − f (z)
x’
€
Codici di Huffman: sottostruttura ottima
∑ f (x)d
z
non lo sarebbe neanche T ‘.
169
Lemma: Sia T ‘ =T U {z} - {x’,y’}.
T
Sia T ’ =T U {z} - {x’,y’}
€
172
Codici di Huffman: correttezza
Esercizio
Teorema: L algoritmo di Huffman produce un codice prefisso ottimo
frequenza
Prova.
A
22
Dato che l algoritmo è ricorsivo, la prova è per induzione sulla cardinalità dell alfabeto.
B
12
L asserto è vero per k=2, cioè per un alfabeto con due simboli.
C
24
Supponiamo che sia ottimale per tutti gli alfabeti con k-1 simboli.
Mostreremo che è ottimale per gli alfabeti con k simboli.
Ricordiamo: Teorema. Sia S un alfabeto con frequenze f(x). Siano
x,y∈S caratteri con le frequenze più basse, f(x) ≤ f(y).
Allora esiste un codice ottimale con albero T in cui x,y
corrispondono a foglie che sono fratelli.
T
Sia T ‘ =T U {z} - {x’,y’}
Abbiamo visto che:
∑ f (x)d
T'
6
E
27
F
9
z
(x) = ∑ f (x)dT (x) − f (z)
x∈S
D
parola
codice
c∈S
Assumiamo T non ottimale. Sia T* ottimale della forma
x’
∑ f(x)d
y’
T
(x) = ?
xεS
Allora T* =T* U {z} - {x’,y’} sarebbe migliore di T ‘. Contraddizione.
€
173
174
Esercizio
frequenza
parola
codice
A
22
00
B
12
100
C
24
01
D
6
1010
E
27
11
F
9
∑ f(x)d
1011
T
Articolo di Huffman
100
David A. Huffman,
”A method for the construction of minimum-redundancy codes”,
Proceedings of the I.R.E., settembre 1952, pagg. 1098-1102
54
27
46
15
1098
PROCEEDINGS OF THE I.R.E.
September
1952
Huffman: A Method for the Construction of Minimum-Redundancy Codes
1099
A Method for the Construction of
Minimum-Redundancy Codes*
DAVID A. HUFFMAN+, ASSOCIATE, IRE
22 12 24 6 27 9
A B C D E F
(x) = 22⋅2 + 12⋅3 + 24 ⋅2 + 6⋅ 4 + 27 ⋅2 + 9 ⋅ 4 = 242
xεS
175
176
Cambio monete (Cambio monete)
Coin Changing (Cambio monete)
Obiettivo. Dati i valori delle monete U.S.A. : 1, 5, 10, 25, 100, trovare
un metodo per pagare un fissato ammontare ad un cliente usando il
numero minore di monete.
Esempio: 34¢.
Algoritmo del cassiere. Ad ogni iterazione, aggiungere moneta con il
maggior valore che non supera l’ammontare da pagare.
Esempio: $2.89.
178
Cambio monete: Algoritmo greedy
Cambio monete: Analisi algoritmo greedy
Algoritmo del cassiere. Ad ogni iterazione, aggiungere moneta di
maggior valore che non supera l’ammontare da pagare.
Teorema. Greedy è ottimale per il conio U.S.A. : 1, 5, 10, 25, 100.
Prova. (induzione su x)
 
 
Sort coins denominations by value: c1 < c2 < … < cn.
monete selezionate
S ← φ
while (x ≠ 0) {
sia k più grande intero tale che ck ≤ x
if (k = 0)
return soluzione non trovata"
x ← x - ck
S ← S ∪ {k}
}
return S
Considera il modo ottimale per ck ≤ x < ck+1 : greedy sceglie moneta k.
Ogni soluzione ottimale contiene la moneta k.
–  altrimenti, ci sarebbero monete di tipo c1, …, ck-1 che sommano ad x
–  nessuna soluzione ottimale può farlo, come si vede dalla tabella
k
ck
Tutte le soluzioni
ottimali soddisfano
Massimo valore delle monete
1, 2, …, k-1 in una sol. ottimale
1
1
penny ≤ 4
-
2
5
nickel ≤ 1
4
3
10
nickel + dime ≤ 2
4+5=9
4
25
quarter ≤ 3
20 + 4 = 24
5
100
Senza limiti
75 + 24 = 99
5 ≤ x < 10
Al massimo
•  4 penny
5 ≤Riduzione
x < 10
al cambio di x - ck centesimi, che per induzione, è risolto in
Se ci fossero 5 penny potrei migliorare con “1 nickel”
L algoritmo del cassiere è ottimale?
modo ottimale dall’algoritmo greedy. ▪
179
180
Cambio monete: Analisi algoritmo greedy
Cambio monete: Analisi algoritmo greedy
Teorema. Greedy è ottimale per il conio U.S.A. : 1, 5, 10, 25, 100.
Prova. (induzione su x)
 
 
Teorema. Greedy è ottimale per il conio U.S.A. : 1, 5, 10, 25, 100.
Prova. (induzione su x)
Considera il modo ottimale per ck ≤ x < ck+1 : greedy sceglie moneta k.
Ogni soluzione ottimale contiene la moneta k.
–  altrimenti, ci sarebbero monete di tipo c1, …, ck-1 che sommano ad x
–  nessuna soluzione ottimale può farlo, come si vede dalla tabella
 
 
Considera il modo ottimale per ck ≤ x < ck+1 : greedy sceglie moneta k.
Ogni soluzione ottimale contiene la moneta k.
–  altrimenti, ci sarebbero monete di tipo c1, …, ck-1 che sommano ad x
–  nessuna soluzione ottimale può farlo, come si vede dalla tabella
k
ck
Tutte le soluzioni
ottimali soddisfano
Massimo valore delle monete
1, 2, …, k-1 in una sol. ottimale
k
ck
Tutte le soluzioni
ottimali soddisfano
Massimo valore delle monete
1, 2, …, k-1 in una sol. ottimale
1
1
penny ≤ 4
-
1
1
penny ≤ 4
-
2
5
nickel ≤ 1
4
3
10
nickel + dime ≤ 2
4+5=9
4
25
quarter ≤ 3
20 + 4 = 24
5
100
Senza limiti
75 + 24 = 99
10 ≤ x < 25
Al massimo
•  4 penny e
•  1 nickel
10
≤ x < 25
  Riduzione
al cambio di x - ck centesimi, che per induzione, è risolto in
Se ci fossero 5 penny potrei migliorare con “1 nickel”
modo ottimale dall’algoritmo greedy. ▪
Se ci fossero 2 nickel potrei migliorare con “1 dime”
2
5
nickel ≤ 1
4
3
10
nickel + dime ≤ 2
4+5=9
4
25
quarter ≤ 3
20 + 4 = 24
5
100
Senza limiti
75 + 24 = 99
25 ≤ x < 100
Al massimo
•  4 penny e
•  2 dime
25 ≤ x < 100
Se ci fossero 3 dime potrei migliorare con “1 quarter + 1 nickel”
nickel + dime ≤ 2
Se ci fossero 2 dime e 1 nickel potrei migliorare con “1 quarter”
Se ci fossero 1 dime e 1 nickel avrebbe valore inferiore a “2 dime”
181
182
Cambio monete: Analisi algoritmo greedy
Cambio monete: Analisi algoritmo greedy
Teorema. Greedy è ottimale per il conio U.S.A. : 1, 5, 10, 25, 100.
Prova. (induzione su x)
 
 
Teorema. Greedy è ottimale per il conio U.S.A. : 1, 5, 10, 25, 100.
Prova. (induzione su x)
Considera il modo ottimale per ck ≤ x < ck+1 : greedy sceglie moneta k.
Ogni soluzione ottimale contiene la moneta k.
–  altrimenti, ci sarebbero monete di tipo c1, …, ck-1 che sommano ad x
–  nessuna soluzione ottimale può farlo, come si vede dalla tabella
 
 
Considera il modo ottimale per ck ≤ x < ck+1 : greedy sceglie moneta k.
Ogni soluzione ottimale contiene la moneta k.
–  altrimenti, ci sarebbero monete di tipo c1, …, ck-1 che sommano ad x
–  nessuna soluzione ottimale può farlo, come si vede dalla tabella
k
ck
Tutte le soluzioni
ottimali soddisfano
Massimo valore delle monete
1, 2, …, k-1 in una sol. ottimale
k
ck
Tutte le soluzioni
ottimali soddisfano
Massimo valore delle monete
1, 2, …, k-1 in una sol. ottimale
1
1
penny ≤ 4
-
1
1
penny ≤ 4
-
2
5
nickel ≤ 1
4
2
5
nickel ≤ 1
4
3
10
nickel + dime ≤ 2
4+5=9
3
10
nickel + dime ≤ 2
4+5=9
4
25
quarter ≤ 3
20 + 4 = 24
5
100
Senza limiti
75 + 24 = 99
100 ≤ x
Al massimo
•  3 quarter
100
≤x
  Riduzione
al cambio di x - ck centesimi, che per induzione, è risolto in
Se ci fossero 4 quarter potrei migliorare con “1 dollaro”
4
25
quarter ≤ 3
20 + 4 = 24
5
100
Senza limiti
75 + 24 = 99
  Riduzione
al cambio di x - ck centesimi, che per induzione, è risolto in
modo ottimale dall’algoritmo greedy. ▪
modo ottimale dall’algoritmo greedy. ▪
183
184
Cambio monete: Analisi algoritmo greedy
Cambio monete: Esercizio
Osservazione. L algoritmo greedy non è ottimo per i valori dei
francobolli americani: 1, 10, 21, 34, 70, 100, 350, 1225, 1500.
Conio euro: 1, 2, 5, 10, 20, 50, 100, 200.
Controesempio. 140¢.
Greedy: 100, 34, 1, 1, 1, 1, 1, 1.
Ottimo: 70, 70.
 
 
Greedy è ottimale?
185
186
Selecting Breakpoints
Selecting Breakpoints
Selecting breakpoints (scelta fermate).
Viaggio in auto da Salerno a Mosca per una percorso fissato.
 
 
 
 
Distributori di benzina a punti fissi lungo il percorso.
Capacità serbatoio = C.
Obiettivo: minimizzare numero di fermate per rifornimento benzina.
Algoritmo Greedy. Viaggiare il più possibile prima del rifornimento.
C
Salerno
C
C
C
C
1
2
3
4
C
C
5
6
Mosca
7
188
Selecting Breakpoints: Algoritmo Greedy
Selecting Breakpoints: Correttezza
Algoritmo greedy.
Teorema. L’algoritmo greedy è ottimale.
Prova. (per assurdo)
Assumiamo che l’algoritmo greedy non sia ottimale.
Sia 0 = g0 < g1 < . . . < gp = L insieme di breakpoints scelto da greedy.
Sia 0 = f0 < f1 < . . . < fq = L insieme di breakpoints nella soluzione ottimale
con f0 = g0, f1 = g1 , . . . , fr = gr per il massimo valore possibile per r.
Nota: gr+1 > fr+1 per la scelta greedy dell’algoritmo.
Sort breakpoints so that: 0 = b0 < b1 < b2 < ... < bn = L
 
breakpoints selected
current location
S ← {0}
x ← 0
 
 
while (x ≠ bn)
let p be largest integer such that bp ≤ x + C
if (bp = x)
return "no solution"
x ← bp
S ← S ∪ {p}
return S
 
g0
g1
g2
gr
f0
f1
f2
fr
gr+1
Greedy:
...
Ottimo:
Implementazione. O(n log n)
Usare ricerca binaria per scegliere ogni breakpoint p.
 
fr+1
fq
Perchè in questa soluzione ottimale
non ci si ferma un pò dopo?
189
190
Selecting Breakpoints: Correttezza
Fractional Knapsack problem
Teorema. L’algoritmo greedy è ottimale.
Prova. (per assurdo)
Assumiamo che l’algoritmo greedy non sia ottimale.
Sia 0 = g0 < g1 < . . . < gp = L insieme di breakpoints scelto da greedy.
Sia 0 = f0 < f1 < . . . < fq = L insieme di breakpoints nella soluzione ottimale
con f0 = g0, f1 = g1 , . . . , fr = gr per il massimo valore possibile per r.
Nota: gr+1 > fr+1 per la scelta greedy dell’algoritmo.
 
 
 
 
g0
g1
g2
gr
f0
f1
f2
fr
gr+1
Greedy:
...
Ottimo:
fq
Altra soluzione ottimale con un valore di r maggiore
⇒ contraddizione
191
Fractional Knapsack problem
Fractional Knapsack problem
Fractional Knapsack problem (Problema dello zaino frazionato).
  n oggetti, ognuno con peso wi > 0 e valore pi > 0
Fractional Knapsack problem (Problema dello zaino frazionato).
  n oggetti, ognuno con peso wi > 0 e valore pi > 0
  Zaino con capacità M
  Obiettivo: Riempire lo zaino con gli oggetti (presi anche in parte)
massimizzando il valore totale
Massimizzare
  Zaino con capacità M
  Obiettivo: Riempire lo zaino con gli oggetti (presi anche in parte)
massimizzando il valore totale
∑ px
knapsack
i i
1≤i≤n
∑wx
Vincoli
i i
≤M
con 0 ≤ xi ≤ 1, 1 ≤ i ≤ n
1≤i≤n
oggetti
parte frazionaria presa
1
2
3
4
5
peso:
4 ml
8 ml
2 ml
6 ml
1 ml
valore:
€12
€32
€40
€30
€50
10 ml
193
194
Fractional Knapsack problem
Fractional Knapsack problem
Fractional Knapsack problem (Problema dello zaino frazionato).
  n oggetti, ognuno con peso wi > 0 e valore pi > 0
Fractional Knapsack problem (Problema dello zaino frazionato).
  n oggetti, ognuno con peso wi > 0 e valore pi > 0
  Zaino con capacità M
  Obiettivo: Riempire lo zaino con gli oggetti (presi anche in parte)
massimizzando il valore totale
Scelta greedy: selezionare l’oggetto con massimo valore
relativo e prenderne la maggior quantità possibile
  Zaino con capacità M
  Obiettivo: Riempire lo zaino con gli oggetti (presi anche in parte)
massimizzando il valore totale
Scelta greedy: selezionare l’oggetto con massimo valore
relativo e prenderne la maggior quantità possibile
knapsack
knapsack
Soluzione
oggetti
1
2
3
4
5
peso:
4 ml
8 ml
2 ml
6 ml
1 ml
valore:
€12
€32
€40
€30
€50
oggetti
10 ml
1
2
3
4
5
peso:
4 ml
8 ml
2 ml
6 ml
1 ml
valore:
valore:
€12
€32
€40
€30
€50
3
4
20
5
50
(€ per ml)
195
10 ml
•  1 ml di 5
•  2 ml di 3
•  6 ml di 4
•  1 ml di 2
•  0 ml di 1
x5=1
x3=1
x4=1
x2=1/8
x1=0
Valore totale = € 50+40+30+32/8
= € 124
196
Fractional Knapsack problem
Connecting wires
Algoritmo del cassiere. Ad ogni iterazione, aggiungere la massima parte
dell’oggetto di maggior valore relativo senza superare W.
Sort oggetti per valore relativo: p1/w1 < p2/w2 < … < pn/wn.
Peso degli oggetti selezionati
w ← 0
x1 ← 0; x2← 0; …; xn← 0
i ← 1
while (w < W) and (i < n){
if (wi < W - w)
then xi ← 1
w ← w + wi
else xi ← (W – w) / wi
w ← W
i ← i + 1
}
return (x1, x2 …, xn)
Running time O(n log n).
Provare che l’algoritmo è ottimale (quale tecnica usare?)
197
Connecting wires (Fili di connessione)
Connecting wires (Fili di connessione)
  Ci sono n punti bianchi ed n punti neri su una linea, equispaziati (cioè la
  Ci sono n punti bianchi ed n punti neri su una linea, equispaziati (cioè la
distanza tra 2 punti consecutivi è sempre la stessa)
distanza tra 2 punti consecutivi è sempre la stessa)
  Vogliamo connettere ogni punto bianco con uno nero minimizzando la
lunghezza totale di fili
  Vogliamo connettere ogni punto bianco con uno nero minimizzando la
lunghezza totale di fili
  Esempio:
  Esempio:
Lunghezza totale 1 + 1 + 1 + 5 = 8
Lunghezza totale 1 + 1 + 1 + 5 = 8
  Trovare un algoritmo greedy per risolvere il problema, analizzando le varie
scelte greedy.
  Per ogni scelta greedy individuata, verificare se
- è corretta (prova)
- non è corretta (mostrare un controesempio)
  Un esempio di scelta greedy:
  Connettere tutte le coppie a distanza 1
  Connettere tutte le coppie rimanenti a distanza 2
  …
199
200
Connecting wires (Fili di connessione)
Controesempio:
Collecting coins
Lunghezza totale 1 + 1 + 1 + 7 = 10
Lunghezza totale 1 + 3 + 1 + 3 = 8
  Un esempio di scelta greedy:
  Connettere tutte le coppie a distanza 1
  Connettere tutte le coppie rimanenti a distanza 2
  …
201
Collecting coins
Collecting coins
  Su una scacchiera ci sono alcune monete.
  Un robot parte dall’angolo in alto a sinistra e cammina fino
all’angolo in basso a destra
  Il robot può muovere solo in 2 direzioni: destra ed in giù
  Il robot colleziona monete al suo passaggio
  Problema: collezionare tutte le monete usando il numero minimo
di robot.
  Esempio:
  Su una scacchiera ci sono alcune monete.
  Un robot parte dall’angolo in alto a sinistra e cammina fino
all’angolo in basso a destra
  Il robot può muovere solo in 2 direzioni: destra ed in giù
  Il robot colleziona monete al suo passaggio
  Problema: collezionare tutte le monete usando il numero minimo
di robot.
  Esempio:
4 robot sono sufficienti a
collezionare tutte le 10 monete
203
204
Collecting coins
Collecting coins
  Su una scacchiera ci sono alcune monete.
  Un robot parte dall’angolo in alto a sinistra e cammina fino
all’angolo in basso a destra
  Il robot può muovere solo in 2 direzioni: destra ed in giù
  Il robot colleziona monete al suo passaggio
  Problema: collezionare tutte le monete usando il numero minimo
di robot.
  Esempio:
  Su una scacchiera ci sono alcune monete.
  Un robot parte dall’angolo in alto a sinistra e cammina fino
all’angolo in basso a destra
  Il robot può muovere solo in 2 direzioni: destra ed in giù
  Il robot colleziona monete al suo passaggio
  Problema: collezionare tutte le monete usando il numero minimo
di robot.
  Esempio:
Un esempio di scelta greedy:
•  Il primo robot prende il maggior numero di
monete
•  Il secondo robot prende il maggior numero delle
restanti monete
•  …
Trovare un algoritmo greedy per risolvere il
problema, analizzando le varie scelte greedy.
Per ogni scelta greedy individuata, verificare se
- è corretta (prova)
- non è corretta (mostrare un controesempio)
205
206
Collecting coins
Collecting coins
  Controesempio:
  Controesempio:
Un esempio di scelta greedy:
•  Il primo robot prende il maggior numero di
monete
•  Il secondo robot prende il maggior numero delle
restanti monete
•  …
Scelta greedy: 3 robot
•  Il primo prende 7 monete
•  Il secondo prende 3 monete
•  Il terzo prende l’ultima moneta
Ottimo: 2 robot
Un esempio di scelta greedy:
•  Il primo robot prende il maggior numero di
monete
•  Il secondo robot prende il maggior numero delle
restanti monete
•  …
Scelta greedy: 3 robot
•  Il primo prende 7 monete
•  Il secondo 3 monete
•  Il terzo l’ultima moneta
207
208
Collecting coins
Collecting coins
  Scelta Greedy: “peeling the next
leftmost strip from top to bottom”
  Scelta Greedy: “peeling the next
leftmost strip from top to bottom”
  Celle disgiunte: una è sotto ed a sinistra
dell’altra
  Lunghezza max catena di celle disgiunte
è limite inferiore al problema
Qual’è la lunghezza
max della catena?
Ogni coppia di celle
consecutive è disgiunta
Occorre un robot per
ogni cella della catena
209
210
Riepilogo Capitolo 4, Greedy Algorithms
Collecting coins
4.1 Interval Scheduling
4.1 Interval Partitioning
  Scelta Greedy: “peeling the next
leftmost strip from top to bottom”
4.2
4.3
4.4
4.5
4.6
4.7
4.8
4.9
  Celle disgiunte: una è sotto ed a sinistra
dell’altra
  Lunghezza max catena di celle disgiunte
è limite inferiore al problema
  … ed è anche uguale alla soluzione ottima!
  infatti, ogni robot decrementa di 1 la
lunghezza max della catena
Scheduling to Minimize Lateness
Optimal Caching (senza prova correttezza)
Shortest Paths in a Graph
Minimum Spanning Tree
The Union-Find Data Structure (no)
Clustering (no)
Huffman Codes and Data Compression
Minimum-Cost Arborescences (no)
Esercizi:
  Coin Changing
  Selecting Breakpoints
  Fractional Knapsack problem
  Connecting wires
  Collecting coins
211
212