Algoritmo greedy: differenze tra le versioni
Contenuto cancellato Contenuto aggiunto
Nessun oggetto della modifica |
m clean up, fix template e parametri |
||
(34 versioni intermedie di 24 utenti non mostrate) | |||
Riga 1:
Un '''algoritmo greedy''' (dall'inglese ''greedy'', avido) è un [[paradigma algoritmico]] che costruisce una soluzione passo dopo passo, effettuando ad ogni iterazione la scelta localmente ottimale, con l'obiettivo di trovare un ottimo globale<ref>{{cita libro|cognome=Cormen|nome=Thomas H.|cognome2=Leiserson|nome2=Charles E.|cognome3=Rivest|nome3=Ronald L.|cognome4=Stein|nome4=Clifford|titolo=Introduction to Algorithms|edizione=4|editore=MIT Press|anno=2022|isbn=978-0-262-04630-5|p=414-442}}</ref>. Questi algoritmi non sempre garantiscono la soluzione ottimale, ma sono spesso efficienti e forniscono buone approssimazioni per problemi di [[ottimizzazione (matematica)|ottimizzazione]] complessi<ref>{{cita libro|cognome=Kleinberg|nome=Jon|cognome2=Tardos|nome2=Éva|titolo=Algorithm Design|editore=Pearson|anno=2013|isbn=978-0321295354|p=115-171}}</ref>.
Il paradigma greedy è caratterizzato da due proprietà fondamentali: la '''proprietà di scelta greedy''' (esiste sempre una soluzione ottimale che include la scelta localmente ottimale) e la '''sottostruttura ottima''' (la soluzione ottimale contiene soluzioni ottime ai sottoproblemi)<ref>{{cita libro|cognome=Demetrescu|nome=Camil|cognome2=Finocchi|nome2=Irene|cognome3=Liotta|nome3=Giuseppe|titolo=Algoritmi e strutture dati|edizione=3|editore=McGraw-Hill|anno=2019|isbn=978-8838615818|p=167-189}}</ref>.
== Descrizione del paradigma ==
Un algoritmo greedy effettua una sequenza di scelte, dove ogni scelta è localmente ottimale al momento in cui viene presa. L'algoritmo non riconsiderera mai le scelte precedenti, a differenza della [[programmazione dinamica]] che esplora tutte le possibili combinazioni di sottoproblemi<ref>{{cita libro|cognome=Sedgewick|nome=Robert|cognome2=Wayne|nome2=Kevin|titolo=Algorithms|edizione=4|editore=Addison-Wesley|anno=2011|isbn=978-0321573513|p=655-678}}</ref>.
La strategia greedy può essere schematizzata come segue:
# Ordinare gli elementi secondo un criterio di ottimalità locale
# Inizializzare una soluzione vuota
# Per ogni elemento, se è compatibile con le scelte precedenti, aggiungerlo alla soluzione
# Restituire la soluzione costruita
=== Confronto con altri paradigmi ===
{| class="wikitable"
|-
! Paradigma !! Strategia !! Garanzia di ottimalità !! Complessità tipica
|-
| '''Greedy''' || Scelta localmente ottima || Solo per problemi specifici || O(n log n)
|-
| [[Programmazione dinamica]] || Esplorazione di tutti i sottoproblemi || Sì, se esiste sottostruttura ottima || O(n²) - O(n³)
|-
| [[Divide et impera]] || Suddivisione ricorsiva || Dipende dal problema || O(n log n)
|-
| [[Backtracking]] || Esplorazione con ritorno || Sì, ma può essere esponenziale || O(2ⁿ) - O(n!)
|}
== Proprietà fondamentali ==
=== Proprietà di scelta greedy ===
La '''proprietà di scelta greedy''' stabilisce che una scelta localmente ottima porta sempre a una soluzione globalmente ottima. Formalmente, esiste sempre una soluzione ottima che contiene la scelta greedy effettuata al primo passo<ref>{{cita libro|cognome=Cormen|nome=Thomas H.|titolo=Introduction to Algorithms|anno=2022|p=418}}</ref>.
'''Dimostrazione tipica (Exchange Argument):'''
# Supporre l'esistenza di una soluzione ottima I* che non contiene la scelta greedy
# Costruire una nuova soluzione I' sostituendo un elemento di I* con la scelta greedy
# Dimostrare che |I'| ≤ |I*| e che I' è ammissibile
# Concludere che I' è ottima e contiene la scelta greedy
=== Sottostruttura ottima ===
La '''sottostruttura ottima''' garantisce che, dopo aver effettuato la scelta greedy, il problema residuo mantiene la stessa struttura di ottimalità. Questo permette di applicare ricorsivamente la strategia greedy sui sottoproblemi rimanenti<ref>{{cita libro|cognome=Kleinberg|nome=Jon|titolo=Algorithm Design|anno=2013|p=118}}</ref>.
== Esempi classici ==
=== Selezione di attività ===
{{Vedi anche|Problema di selezione delle attività}}
Il '''problema di selezione delle attività''' consiste nel selezionare il massimo numero di attività mutuamente compatibili da un insieme di attività, ciascuna caratterizzata da un tempo di inizio e un tempo di fine.
'''Strategia greedy:''' Selezionare sempre l'attività che termina prima tra quelle non ancora considerate.
<syntaxhighlight lang="text">
ACTIVITY_SELECTOR(s, f, n):
A = {a₁}
k = 1
for m = 2 to n:
if s[m] ≥ f[k]:
A = A ∪ {aₘ}
k = m
return A
</syntaxhighlight>
'''Complessità:''' O(n log n) per l'ordinamento iniziale, O(n) per la selezione.
=== Algoritmo di Kruskal ===
{{Vedi anche|Algoritmo di Kruskal}}
L'[[algoritmo di Kruskal]] trova l'[[albero di copertura minimo]] di un [[grafo]] pesato utilizzando una strategia greedy.
'''Strategia greedy:''' Selezionare sempre l'arco di peso minimo che non crea cicli.
<syntaxhighlight lang="text">
KRUSKAL(G):
A = ∅
for each vertex v ∈ G.V:
MAKE_SET(v)
sort edges of G.E in nondecreasing order by weight
for each edge (u,v) ∈ G.E:
if FIND_SET(u) ≠ FIND_SET(v):
A = A ∪ {(u,v)}
UNION(u,v)
return A
</syntaxhighlight>
'''Complessità:''' O(E log E) dove E è il numero di archi.
=== Codifica di Huffman ===
{{Vedi anche|Codifica di Huffman}}
La [[codifica di Huffman]] costruisce un codice a lunghezza variabile ottimale per la compressione di dati.
'''Strategia greedy:''' Unire sempre i due nodi con frequenza minima.
<syntaxhighlight lang="text">
HUFFMAN(C):
n = |C|
Q = C
for i = 1 to n-1:
allocate new node z
z.left = x = EXTRACT_MIN(Q)
z.right = y = EXTRACT_MIN(Q)
z.freq = x.freq + y.freq
INSERT(Q, z)
return EXTRACT_MIN(Q)
</syntaxhighlight>
'''Complessità:''' O(n log n) utilizzando una [[coda di priorità]].
== Analisi di correttezza ==
Per dimostrare la correttezza di un algoritmo greedy sono necessari due passi:
=== Dimostrazione della proprietà greedy ===
Utilizzando l''''exchange argument''':
# Assumere l'esistenza di una soluzione ottima che differisce dalla scelta greedy
# Mostrare che è possibile "scambiare" elementi per ottenere una soluzione altrettanto buona che include la scelta greedy
# Concludere che esiste sempre una soluzione ottima con la scelta greedy
=== Dimostrazione della sottostruttura ottima ===
# Mostrare che dopo la scelta greedy, il problema residuo ha la stessa struttura
# Dimostrare che una soluzione ottima del problema originale contiene soluzioni ottime dei sottoproblemi
== Limitazioni ==
Gli algoritmi greedy non sempre producono soluzioni ottime. Un esempio classico è il '''problema dello zaino frazionario''' vs '''problema dello zaino 0-1''':
* '''Zaino frazionario''': L'algoritmo greedy (ordinare per rapporto valore/peso) è ottimale
* '''Zaino 0-1''': L'algoritmo greedy può fallire e richiede [[programmazione dinamica]]
'''Esempio di fallimento:'''
Capacità zaino: 10, Oggetti: (peso=6, valore=30), (peso=5, valore=20), (peso=4, valore=15)
* Greedy: seleziona primo oggetto → valore totale = 30
* Ottimo: seleziona secondo e terzo oggetto → valore totale = 35
== Problemi di approssimazione ==
Quando gli algoritmi greedy non garantiscono l'ottimo, spesso forniscono buone [[algoritmo di approssimazione|approssimazioni]]:
* '''Set Cover''': Greedy garantisce approssimazione O(log n)
* '''Vertex Cover''': Greedy garantisce approssimazione 2-ottimale
* '''TSP metrico''': Algoritmi greedy garantiscono approssimazioni costanti
== Teoria dei matroidi ==
{{Vedi anche|Matroide}}
Un [[matroide]] M = (E, I) è una struttura matematica dove E è un insieme finito e I è una famiglia di sottoinsiemi "indipendenti" di E che soddisfa:
# ∅ ∈ I (insieme vuoto è indipendente)
# Se A ∈ I e B ⊆ A, allora B ∈ I (proprietà ereditaria)
# Se A, B ∈ I e |A| < |B|, esiste x ∈ B\A tale che A ∪ {x} ∈ I (proprietà di scambio)
'''Teorema fondamentale:''' Un algoritmo greedy trova sempre una soluzione ottima per problemi di ottimizzazione su matroidi pesati<ref>{{cita news|cognome=Edmonds|nome=Jack|titolo=Matroids and the greedy algorithm|rivista=Mathematical Programming|volume=1|numero=1|anno=1971|pp=127-136|doi=10.1007/BF01584082}}</ref>.
=== Algoritmo greedy per matroidi pesati ===
<syntaxhighlight lang="text">
GREEDY_MATROID(M, w):
A = ∅
sort elements of M.E in decreasing order by weight w
for each x ∈ M.E:
if A ∪ {x} ∈ M.I:
A = A ∪ {x}
return A
</syntaxhighlight>
== Esempi di implementazione ==
=== Problema del resto (cambio di monete) ===
Per sistemi monetari "canonici" (come Euro), l'algoritmo greedy è ottimale:
<syntaxhighlight lang="text">
CHANGE_MAKING(amount, coins):
result = []
sort coins in decreasing order
for each coin in coins:
while amount ≥ coin:
result.append(coin)
amount -= coin
return result
</syntaxhighlight>
'''Attenzione:''' Per sistemi non canonici, l'algoritmo può fallire.
=== Scheduling con deadline ===
Dato un insieme di lavori con profitti e deadline, massimizzare il profitto:
<syntaxhighlight lang="text">
JOB_SCHEDULING(jobs, n):
sort jobs by profit in decreasing order
result = []
for i = 0 to n-1:
for j = min(n, jobs[i].deadline)-1 down to 0:
if result[j] is empty:
result[j] = jobs[i]
break
return result
</syntaxhighlight>
== Voci correlate ==
* [[Programmazione dinamica]]
* [[Algoritmo di approssimazione]]
* [[Teoria della complessità computazionale]]
* [[Matroide]]
* [[Algoritmo di Kruskal]]
* [[Algoritmo di Prim]]
* [[Codifica di Huffman]]
* [[Problema di selezione delle attività]]
== Note ==
<references/>
== Bibliografia ==
* {{cita libro|cognome=Cormen|nome=Thomas H.|cognome2=Leiserson|nome2=Charles E.|cognome3=Rivest|nome3=Ronald L.|cognome4=Stein|nome4=Clifford|titolo=Introduction to Algorithms|edizione=4|editore=MIT Press|anno=2022|isbn=978-0-262-04630-5}}
* {{cita libro|cognome=Kleinberg|nome=Jon|cognome2=Tardos|nome2=Éva|titolo=Algorithm Design|editore=Pearson|anno=2013|isbn=978-0321295354}}
* {{cita libro|cognome=Edmonds|nome=Jack|titolo=Paths, trees, and flowers|rivista=Canadian Journal of Mathematics|volume=17|anno=1965|pp=449-467}}
* {{cita libro|cognome=Demetrescu|nome=Camil|cognome2=Finocchi|nome2=Irene|cognome3=Liotta|nome3=Giuseppe|titolo=Algoritmi e strutture dati|edizione=3|editore=McGraw-Hill|anno=2019|isbn=978-8838615818}}
* {{cita libro|cognome=Sedgewick|nome=Robert|cognome2=Wayne|nome2=Kevin|titolo=Algorithms|edizione=4|editore=Addison-Wesley|anno=2011|isbn=978-0321573513}}
== Altri progetti ==
{{interprogetto|preposizione=sugli}}
== Collegamenti esterni ==
* {{en}} [https://web.stanford.edu/class/cs161/schedule.html Stanford CS161: Greedy Algorithms]
* {{en}} [https://www.algorithm-archive.org/contents/greedy_algorithms/greedy_algorithms.html Algorithm Archive: Greedy Algorithms]
* {{Collegamenti esterni}}
{{Portale|matematica|informatica}}
[[Categoria:Algoritmi di ottimizzazione]]
[[Categoria:Teoria delle matroidi]]
|