Algoritmi e Strutture Dati 2 - lucacostante.com 2 - Riassunto.pdf · Algoritmi e Strutture Dati 2:...
-
Upload
hoangthuan -
Category
Documents
-
view
280 -
download
1
Transcript of Algoritmi e Strutture Dati 2 - lucacostante.com 2 - Riassunto.pdf · Algoritmi e Strutture Dati 2:...
Algoritmi e Strutture Dati 2
Alidorante Domenico, Capobianco Antonello, Caputo Luca, Cimmino Giovanni, Costante
Luca, Davino Cristiano, Di Giacomo Ivan, Ferro Amedeo, Ferri Vincenzo, Fierro Nunzio,
Giardino Daniele, Giordano Antonio, Palo Umberto, Pepe Valeriano, Vitale Pasquale
2009- 2010
Algoritmi e Strutture Dati 2
Sommario
Lezione 1 – Indipendent Set e Vertex Cover ..................................................................................................... 1
Introduzione .................................................................................................................................................. 1
Riduzione polinomiale tra problemi .............................................................................................................. 1
Problema degli invitati alla festa (Indipendent Set) .................................................................................. 1
Problema delle guardie nel museo (Vertex Cover) ................................................................................... 2
Versione di decisione ................................................................................................................................. 2
Problema della soddisfacibilità di formule (SAT) ....................................................................................... 3
3-SAT ................................................................................................... Errore. Il segnalibro non è definito.
Lezione 2 – Soluzione intere .............................................................................................................................. 5
Riduzione polinomiale secondo Karp ............................................................................................................ 5
Proprietà transitiva .................................................................................................................................... 5
Soluzioni Intere .............................................................................................................................................. 5
Vertex Cover ≤p Soluzioni intere. ................................................................................................................... 5
Lezione 3- Problemi NP, P.................................................................................................................................. 7
Problemi NP, P ............................................................................................................................................... 7
Lezione 4 – Soddisfacibilità di circuito ............................................................................................................... 9
1° problema NP-Completo: Soddisfacibilità di un Circuito ............................................................................ 9
Soddisfacibilità di circuito ≤p 3-SAT ............................................................................................................. 10
Lezione 5 - Problema della pianificazione delle attività .................................................................................. 13
Problema della pianificazione delle attività ................................................................................................ 13
Progetto genoma ......................................................................................................................................... 13
Circuito Hamiltoniano .................................................................................................................................. 13
Problema del Cammino Hamiltoniano ........................................................................................................ 14
Circuito Hamiltoniano ≤ p Cammino Hamiltoniano...................................................................................... 14
3-SAT ≤p Circuito Hamiltoniano ................................................................................................................. 15
Problema del Commesso Viaggiatore (Traveling Salesman Problem) TSP ................................................. 17
Circuito Hamiltoniano ≤p TSP ....................................................................................................................... 18
Lezione 6 - 3-Sat ≤p 3-Colorabilità .................................................................................................................... 19
Problema delle Reti Radio ........................................................................................................................... 19
COLORAZIONE DEI GRAFI ................................................................................................................................... 19
3-SAT ≤P 3-COLORABILITÀ................................................................................................................................. 20
3-COLORABILITÀ ≤P K-COLORABILITÀ ................................................................................................................... 21
Set Cover ...................................................................................................................................................... 21
Hitting Set .................................................................................................................................................... 21
Algoritmi e Strutture Dati 2
Problema di Costantino ............................................................................................................................... 21
Insieme Dominante ..................................................................................................................................... 22
VERTEX COVER ≤P INSIEME DOMINANTE .............................................................................................................. 22
Lezione 7 - Problemi CO-NP ............................................................................................................................ 24
Catalogazione .............................................................................................................................................. 24
Problemi CO-NP .......................................................................................................................................... 24
Concetto di P-SPACE .................................................................................................................................... 25
𝐍𝐏 ⊆ 𝐏𝐒𝐏𝐀𝐂𝐄 ....................................................................................................................................... 25
Lezione 8 - Proprietà generali degli algoritmi ................................................................................................. 26
Problema della trasmissione in una rete (contention resolution randomizzato, risoluzione dei conflitti) 26
Lezione 9 - Teoria della probabilità ................................................................................................................. 28
Cenni sulla teoria della probabilità .............................................................................................................. 28
Esempio: Lancio di una moneta............................................................................................................... 28
Proprietà di due variabili casuali ................................................................................................................. 28
Un esempio : Indovinare le carte ............................................................................................................ 28
MAX 3-SAT probabilistico ........................................................................................................................ 29
Lezione 10 - Algoritmi probabilistici ................................................................................................................ 30
Variabili casuali ........................................................................................................................................ 30
Disuguaglianza di Chernoff ...................................................................................................................... 30
Problema dell’allocazione di risorse (bilanciamento del carico randomizzato) ...................................... 30
Problema Contention Resolution ................................................................................................................ 31
Analisi delle performance ........................................................................................................................ 32
Lezione 11 - Problemi di ottimizzazione .......................................................................................................... 34
Problemi di ottimizzazione .......................................................................................................................... 34
Vertex Cover: stima di OPT ...................................................................................................................... 34
Maximum Cut .......................................................................................................................................... 36
Lezione 12 - Set Cover e copertura massima .................................................................................................. 38
SET COVER ................................................................................................................................................... 38
Algoritmo greedy per il problema della Copertura Massima ...................................................................... 40
Lezione 13 – K-centro ...................................................................................................................................... 42
Lezione 14 - PTAS e FPTAS ............................................................................................................................... 46
FTAS E FPTAS ............................................................................................................................................... 46
Steneir Tree ................................................................................................................................................. 48
Lezione 15 – TSP (commesso viaggiatore)....................................................................................................... 52
Lezione 16 – Algoritmi di approssimazione tramite PL ................................................................................... 56
Algoritmi e Strutture Dati 2
Vertex Cover ................................................................................................................................................ 56
Set Cover ...................................................................................................................................................... 57
Set MultiCover ............................................................................................................................................. 59
Hitting set .................................................................................................................................................... 60
Esercizi d’esame .......................................................................................................................................... 61
Insiemi dominanti .................................................................................................................................... 61
Lezione 17 – Problemi con PL ed arrotondamento probabilistico .................................................................. 63
Set Cover ...................................................................................................................................................... 63
MaxSat ......................................................................................................................................................... 65
Lezione 18 – Principio della dualità in programmazione lineare .................................................................... 68
Teorema 5 (della dualità nella PL) ........................................................................................................... 69
Teorema 6 (della dualità debole) ............................................................................................................ 70
Teorema 7 (Condizioni complementari di slackness) .............................................................................. 70
Set Cover greedy via duale .......................................................................................................................... 70
Lezione 19 – Hitting Set via duale e Vertex Cover Primale-Duale ................................................................... 74
Hitting set .................................................................................................................................................... 74
Algoritmi di approssimazione via Primale-Duale......................................................................................... 75
Vertex Cover ................................................................................................................................................ 76
Lezione 20 – Set-Cover con PL Primale-Duale ................................................................................................. 78
Lezione 21 – Algoritmi on-line e organizzazione della cache .......................................................................... 80
Algoritmo online – offline ........................................................................................................................ 80
Organizzazione della cache ......................................................................................................................... 80
Analisi competitiva degli algoritmi .......................................................................................................... 82
Lezione 22 – Accesso e gestione di liste dinamiche ........................................................................................ 86
Lezione 23 – Algoritmi on line ......................................................................................................................... 91
Scheduling di Job ......................................................................................................................................... 91
Bin packing on-line ...................................................................................................................................... 92
Affitto sci...................................................................................................................................................... 93
Compravendita di azioni .............................................................................................................................. 94
Algoritmi e Strutture Dati 2: Lezione 1 – Indipendent Set e Vertex Cover
1
Lezione 1 – Indipendent Set e Vertex Cover
Introduzione Esiste una classe di problemi per i quali, pur applicando le tecniche avanzate per la risoluzione, non si riesce
ad ottenere risultati efficienti (di complessità polinomiale). Queste tecniche falliscono per 2 motivi:
1. esistono altre tecniche che risolvono tali problemi;
2. oppure questi problemi sono molto complicati, per cui non si possono produrre algoritmi efficienti.
Questi problemi, in pratica, possono accadere nella vita reale e quindi non possono non essere presi in
considerazione. È importante riuscire a riconoscere ed ad individuare i problemi difficili. Il primo obiettivo è
quello di conoscere se un problema è difficile e cercare di risolverlo non con tecniche comuni.
Riduzione polinomiale tra problemi Siano X e Y due problemi algoritmici.
Informalmente diremo che un problema di tipo X è riducibile ad un problema algoritmico di tipo Y se e solo
se sapendo risolvere arbitrarie istanze di input a Y, allora sappiamo risolvere arbitrarie istanze di input a X.
Questo ci dice che X non è più difficile di Y.
Es:
X: trovare il minimo in un vettore ≤p Y: ordinare un vettore
X: risolvere equazioni di 2 grado ≤p Y: calcolare +, -, *, /
Il concetto di riduzioni serve a mettere in relazione i problemi.
Formalmente: X ≤p Y ↔ ∀ input x al problema X, posso risolvere X (ovvero calcolare l’output relativo),
mediante:
un numero polinomiale di passi computazionali, più
un numero polinomiale di chiamate ad un algoritmo di risoluzione per il problema
computazionale Y.
(polinomiale = polinomiale nella taglia dell’input x).
La soluzione asserisce che se so risolvere Y in tempo polinomiale, lo stesso vale per X. Se non so risolvere X
in tempo polinomiale, non so risolvere Y in tempo polinomiale.
𝑝 𝑥 + 𝑟 𝑞 𝑦 = 𝑝 𝑥 + 𝑟 𝑞 𝑝 𝑥 = 𝑎 ( 𝑥 )
Se Y è “facile”, allora anche X lo è.
Problema degli invitati alla festa (Indipendent Set)
Supponiamo di dover organizzare una festa con molti invitati, non tutti amici tra loro. Si vorrebbe invitare il
numero massimo di amici che non si odiano. Il problema si definisce attraverso un grafo, in cui i vertici
rappresentano gli amici mentre un arco identifica 2 amici che si odiano.
Si vuole individuare il maggior numero di vertici che non hanno archi che li collegano.
Input: G(V,E) dove V è l’insieme dei vertici (le persone) ed E è l’insieme degli archi: esiste un arco tra due
persone se e solo se i 2 non si sopportano.
Output: 𝑆 ⊆ 𝑉 𝑑𝑖 𝑐𝑎𝑟𝑑𝑖𝑛𝑎𝑙𝑖𝑡à 𝑚𝑎𝑠𝑠𝑖𝑚𝑎 𝑡. 𝑐. ∀ 𝑢, 𝑣 ∈ 𝑆, 𝑢, 𝑣 ∉ 𝐸 (S è l’insieme detto indipendente)
Numero polinomiale
di passi un numero polinomiale di chiamate ad
un algoritmo
Algoritmi e Strutture Dati 2: Lezione 1 – Indipendent Set e Vertex Cover
2
Questo problema, per come è stato formulato, può essere paragonato al problema di selezione dei corsi
per un’aula in modo tale che non si intersechino. Se risolviamo uno di questi problemi, si risolvono tutti gli
altri dell’insieme siffatto.
Problema delle guardie nel museo (Vertex Cover)
Siamo nel caso in cui un museo vuole avere ogni corridoio sorvegliato dai guardiani, in modo tale da avere
tutto sotto controllo (l’interno del museo è costituito da una serie di corridoi) ma con la peculiarità di avere
il minor numero di guardiani necessari da poter controllare tutti i corridoi. L’idea è di posizionare i guardiani
nei punti di intersezione per fare in modo che tutti i corridoi vengano guardati con il numero minimo di
guardiani.
Input: G(V,E) dove V sono i guardiani, gli archi rappresentano i corridoi.
Output: 𝐴 ⊆ 𝑉 𝑑𝑖 𝑐𝑎𝑟𝑑𝑖𝑛𝑎𝑙𝑖𝑡à 𝑚𝑖𝑛𝑖𝑚𝑎 𝑡. 𝑐. 𝑡𝑢𝑡𝑡𝑖 𝑔𝑙𝑖 𝑎𝑟𝑐𝑖 𝑠𝑖𝑎𝑛𝑜 𝑐𝑜𝑝𝑒𝑟𝑡𝑖 ∀ 𝑢, 𝑣 ∈ 𝐸, 𝑢, 𝑣 ∩ 𝐴 ≠ ∅
C’è una relazione tra i due problemi?
I due problemi presentati sono problemi di ottimizzazione.
Versione di decisione
Studieremo la versione di decisione (problema con risposta SI - NO) come aiuto alle riduzioni.
1. In riferimento al problema degli invitati alla festa, abbiamo:
Input: G(V,E) e un intero k
Domanda: ∃ 𝑖𝑛 𝐺 𝑢𝑛 𝑖𝑛𝑠𝑖𝑒𝑚𝑒 𝑖𝑛𝑑𝑖𝑝𝑒𝑛𝑑𝑒𝑛𝑡𝑒 𝑑𝑖 𝑐𝑎𝑟𝑑𝑖𝑛𝑎𝑙𝑖𝑡à ≥ 𝑘?
Il problema di decisione non è più difficile del problema di ottimizzazione. Però se il problema
decisionale è difficile, allora il problema di ottimizzazione è ancora più difficile. Avere un algoritmo
risolvibile in tempo polinomiale ci aiuta almeno a trovare la taglia. Per questo motivo ci
concentriamo sulla versione decisionale.
2. In riferimento al problema dei guardiani:
Input: G(V,E) e un intero s
Domanda: ∃ 𝑖𝑛 𝐺 𝑢𝑛 𝑣𝑒𝑟𝑡𝑒𝑥 𝑐𝑜𝑣𝑒𝑟 𝑑𝑖 𝑐𝑎𝑟𝑑𝑖𝑛𝑎𝑙𝑖𝑡à ≤ 𝑠?
Chi dei due è più difficile?
𝐼𝑛𝑑𝑖𝑝𝑒𝑛𝑑𝑒𝑛𝑡 𝑆𝑒𝑡 ≤ 𝑝 𝑉𝑒𝑟𝑡𝑒𝑥 𝐶𝑜𝑣𝑒𝑟
Prova: ∀ 𝑔𝑟𝑎𝑓𝑜 𝐺, 𝑆 è 𝑢𝑛 𝐼𝑛𝑑𝑖𝑝𝑒𝑛𝑑𝑒𝑛𝑡 𝑆𝑒𝑡 ↔ 𝑉 − 𝑆 è 𝑢𝑛 𝑉𝑒𝑟𝑡𝑒𝑥 𝐶𝑜𝑣𝑒𝑟.
V - S S
Algoritmi e Strutture Dati 2: Lezione 1 – Indipendent Set e Vertex Cover
3
Gli archi o sono in V-S o un estremo in S e l’altro in V-S (ricordiamo che S è un Indipendent set). Prendo
un’istanza arbitraria di Indipendent Set ed un parametro k. La corrispondente istanza di Vertex Cover è cosi
formata: G rimane inalterato, s =|V| – k.
𝐺, 𝑘 → 𝐺, 𝑉 − 𝑘
∃ 𝑢𝑛 𝐼𝑛𝑑𝑖𝑝𝑒𝑛𝑑𝑒𝑛𝑡 𝑆𝑒𝑡 𝑑𝑖 𝑐𝑎𝑟𝑑𝑖𝑛𝑎𝑙𝑖𝑡à ≥ 𝑘 ↔ 𝑉 − 𝑆 è 𝑉𝑒𝑟𝑡𝑒𝑥 𝐶𝑜𝑣𝑒𝑟 𝑑𝑖 𝑐𝑎𝑟𝑑𝑖𝑛𝑎𝑙𝑖𝑡à ≤ 𝑠 = 𝑉 − 𝑘
Problema della soddisfacibilità di formule (SAT)
Supponiamo X insieme di variabili booleane 𝑋 = 𝑥1 , … , 𝑥𝑛 𝑑𝑜𝑣𝑒 𝑥𝑖 ∈ 0,1 .
A ciascuna variabile, possiamo associare un letterale ti che sarà 𝑡𝑖 ∈ 𝑥1, … , 𝑥𝑛 , 𝑥1 , … , 𝑥𝑛 .
Definiamo una clausola 𝐶𝑗 = (𝑡1 𝑡2 … 𝑡𝑚 )
Definiamo una formula 𝐹 = (𝐶1 ∧ 𝐶2 …∧ 𝐶𝑘).
Una funzione di assegnazione di valori di verità è 𝛾 = 𝑥 ∈ 𝑋 → 𝛾 𝑥 ∈ {0,1}.
Esempio: F =(𝑥1 𝑥2 ) ∧ (𝑥3 𝑥1 ) ∧ (𝑥1 𝑥2 𝑥3 )
Input: X = un insieme di variabili booleane, F formula di X.
Domanda:
∃ 𝑢𝑛′𝑎𝑠𝑠𝑒𝑔𝑛𝑎𝑧𝑖𝑜𝑛𝑒 𝑑𝑖 𝑣𝑎𝑙𝑜𝑟𝑖 𝑑𝑖 𝑣𝑒𝑟𝑖𝑡à 𝑎𝑙𝑙𝑒 𝑣𝑎𝑟𝑖𝑎𝑏𝑖𝑙𝑖 𝑥𝑖 𝑐𝑒 𝑟𝑒𝑛𝑑𝑒 𝑙𝑎 𝑓𝑜𝑟𝑚𝑢𝑙𝑎 𝐹 𝑣𝑒𝑟𝑎? (𝑐𝑖𝑜è = 1)
3-SAT ≤ 𝒑 Insieme Indipendente
Il problema 3-SAT è uguale al problema SAT sopra descritto solo che le clausole sono tutte composte solo
da 3 letterali: 𝐶𝑗 = (𝑡1 𝑡2 𝑡3 ).
Poiché ho bisogno che almeno un letterale nella clausola sia vero, metto tutti e 3 in conflitto (disegno
l’arco) e ottengo così un triangolo.
1. Passo: ∀ 𝑐𝑙𝑎𝑢𝑠𝑜𝑙𝑎 𝐶𝑖 = 𝑡𝑖1 𝑡𝑖2 𝑡𝑖3 𝑑𝑖𝑠𝑒𝑔𝑛𝑜 𝑢𝑛 𝑡𝑟𝑖𝑎𝑛𝑔𝑜𝑙𝑜
= { 𝑡𝑖1 , 𝑡𝑖2 , 𝑡𝑖2 , 𝑡𝑖3 , 𝑡𝑖1 , 𝑡𝑖3 }
𝑘
𝑖=1
2. Passo: metto l’arco tra due letterali se e solo se la t è la stessa variabile ma negata.
Metto un arco tra tij e tlj ↔ 𝑖 ≠ 𝑙 𝑒 𝑡𝑖𝑗 = 𝑡𝑙𝑗
Esempio.
𝐹 = 𝑋1 𝑋2 𝑋3 ⋀ 𝑋1
𝑋2 𝑋3 ⋀ 𝑋1 𝑋2 𝑋3
X2
x1 𝑥1
X2 𝑥3 X3 X3 𝑥2
x1
t13 t12
t11
t23 t22
t21
tk3 tk2
tk1
𝑡13 = 𝑡23
𝑡21 = 𝑡𝑘1 G
Algoritmi e Strutture Dati 2: Lezione 1 – Indipendent Set e Vertex Cover
4
Si deve partire da istanze arbitrarie.
𝐹 è 𝑠𝑜𝑑𝑑𝑖𝑠𝑓𝑎𝑐𝑖𝑏𝑖𝑙𝑒 ↔ 𝑛𝑒𝑙 𝑔𝑟𝑎𝑓𝑜 𝑜𝑡𝑡𝑒𝑛𝑢𝑡𝑜, ∃ 𝑢𝑛 𝐼. 𝑆. 𝑑𝑖 𝑐𝑎𝑟𝑑𝑖𝑛𝑎𝑙𝑖𝑡à ≥ 𝑘; 𝑑𝑜𝑣𝑒 𝑘 =
𝑛𝑢𝑚𝑒𝑟𝑜 𝑑𝑖 𝑐𝑙𝑎𝑢𝑠𝑜𝑙𝑒 = 𝑛𝑢𝑚𝑒𝑟𝑜 𝑑𝑖 𝑡𝑟𝑖𝑎𝑛𝑔𝑜𝑙𝑖 .
Ho individuato k letterali tale che nessuno è il negato dell’altro rendendo la formula soddisfacibile. Per
risolvere il problema impiego un tempo polinomiale per 3-SAT e una sola chiamata polinomiale di I.S.
Dim.
𝑆𝑒 ⇒) Supponiamo che esista un assegnamento alle variabili di 3-SAT soddisfacibile. Allora ogni clausola
(triangolo) avrà uno o più letterali (vertici) a vero. Se sono più di uno, ne scegliamo uno solo e lo
inseriamo nell’Indipendet Set S, ne abbiamo quindi k. Data la costruzione del grafo, per ogni coppia di
vertici di S, non ci sono archi tra loro perché: non vengono presi vertici della stessa clausola e non
vengono presi vertici con archi tra clausole diverse in quanto una variabile non può essere sia vera che
falsa, visto che due vertici sono collegati se le variabili sono una negata dell’altra. Quindi S è un I.S di
cardinalità k.
𝑆𝑜𝑙𝑜 𝑠𝑒 ⇐) Assumiamo che esista un I.S. S di dimensione k. Ovviamente nell’I.S. non possono esserci due
vertici della stessa clausola, quindi ogni clausola ha un vertice in S. Per ogni vertice in S, settiamo la
clausola corrispondente come vera. Quindi 𝑥𝑗𝑖 𝑒𝑑 𝑥 𝑙𝑖 non possono essere entrambe vere ed entrambe in
S. Tutte le variabili non in S possono essere vere o false. Tale assegnazione renderà vera F.
Algoritmi e Strutture Dati 2: Lezione 2 – Soluzione intere
5
Lezione 2 – Soluzione intere
Riduzione polinomiale secondo Karp X ≤p Y↔ ∃ una funzione f che trasforma istanze di input di X in istanze input di Y, calcolabile in tempo
polinomiale, t.c. ∀ x (istanza di input a X) è un' istanza di tipo SI per problemi in X ↔f(x)(istanza di input di
Y) è un'istanza di tipo SI per Y
La freccia rappresenta una trasformazione tra istanza di tipo SI di X in istanza di tipo SI di Y (e viceversa).
Se l’input di X è SI, viene trasformata in y e si ottiene SI come output.
Proprietà transitiva
1. 𝑋 ≤𝑝 𝑌 ↔ ∃𝑓 𝑐𝑎𝑙𝑐𝑜𝑙𝑎𝑡𝑎 𝑖𝑛 𝑡𝑒𝑚𝑝𝑜 𝑝𝑜𝑙𝑖𝑛𝑜𝑚𝑖𝑎𝑙𝑒 𝑡. 𝑐. ∀𝑥, 𝑥 è 𝑑𝑖 𝑡𝑖𝑝𝑜 𝑆𝐼 ↔ 𝑓 𝑥 è 𝑑𝑖 𝑡𝑖𝑝𝑜 𝑆𝐼
2. 𝑌 ≤𝑝 𝑍 ↔ ∃ 𝑔 𝑐𝑎𝑙𝑐𝑜𝑙𝑎𝑡𝑎 𝑖𝑛 𝑡𝑒𝑚𝑝𝑜 𝑝𝑜𝑙𝑖𝑛𝑜𝑚𝑖𝑎𝑙𝑒 𝑡. 𝑐. ∀𝑦, 𝑦 è 𝑑𝑖 𝑡𝑖𝑝𝑜 𝑆𝐼 ↔ 𝑔 𝑦 è 𝑑𝑖 𝑡𝑖𝑝𝑜 𝑆𝐼
𝑋 ≤𝑝 𝑌 𝑌 ≤𝑝 𝑍 → 𝑋 ≤𝑝 𝑍
𝑓 𝑔
= 𝑔 ∗ 𝑓 𝑓𝑢𝑛𝑧𝑖𝑜𝑛𝑒 𝑡𝑟𝑎 𝑋 𝑒𝑍 𝑥 = 𝑔(𝑓 𝑥 )
Il tempo è sempre polinomiale.
Soluzioni Intere Input: matrice di interi A, di dimensione 𝑛 × 𝑚, vettore di interi b di dimensione m × 1.
Domanda: Esiste un vettore x a componenti intere tale che 𝐴𝑥𝑇 ≥ 𝑏?
Vertex Cover ≤p Soluzioni intere. Sia G = (V,E) e k una generica istanza di input al problema del Vertex Cover, con V ={1, 2, . . . , n} ed E = {e1,
..., em}. Trasformiamo tale istanza in una istanza di input (A, b) al problema della Soluzioni intere nel modo
seguente: A è una matrice con 𝑚 + 2𝑛 + 2 righe (una per ciascun arco nel grafo G più 2n (le prime n righe
sono quelle di una matrice identità In, le altre successive n righe sono quelle di una matrice −In , matrice con
tutti 0 tranne −1 sulla diagonale) + 2 righe speciali di cui una formata da tutti 1 e l’altra da tutti -1, ed n
colonne (una per ciascun vertice nel grafo G), in modo tale che la generica riga i-esima di A (1 ≤ 𝑖 ≤ 𝑚)
sia composta da tutti 0, tranne che nella posizione k ed s, dove vale 1, e k ed s sono tali che ei = (k, s).
Il vettore di interi b è invece composto da tutti 1 nelle prime m componenti, di tutti 0 nelle successive n
componenti, di tutti −1 nelle altre successive n componenti, del valore k nella m+2n+1-esima componente,
e del valore −k nella m + 2n + 2-esima componente. Vediamo un esempio considerando il grafo di sotto
rappresentato.
y f(x)
x
Algoritmi
Algoritmo
di riduzione
Algoritmo
per Y
SI se input di tipo SI
NO se input di tipo NO
X
istanza di
tipo SI per X
istanza di
tipo SI per Y
Y
Algoritmi e Strutture Dati 2: Lezione 2 – Soluzione intere
6
Esplicitando il sistema di equazioni 𝐴𝑥𝑇 = 𝑏 otteniamo un sistema di m+2(n+1) equazioni in n incognite,
dove le prime m equazioni sono della forma 𝑥𝑖 + 𝑥𝑗 ≥ 1, (una per ogni arco (i, j) ∈ E), le equazioni che
vanno dalla (m+1)-esima alla (m+n)-esima sono della forma 𝑥𝑖 ≥ 0, le equazioni che vanno dalla (m+ n +
1)-esima alla (m+ 2n)-esima sono della forma −𝑥𝑖 ≥ −1, ovvero 𝑥𝑖 ≤ 1, la (m + 2n + 1)-esima equazione
è della forma 𝑥1 + 𝑥2 + . . . + 𝑥𝑛 ≥ 𝑘, e la (m + 2n + 2) esima equazione è della forma −𝑥1 −
𝑥2 − . . . − 𝑥𝑛 ≥ −𝑘 (𝑜𝑣𝑣𝑒𝑟𝑜 𝑥1 + 𝑥2 + . . . + 𝑥𝑛 ≤ 𝑘).
𝐷𝑖𝑚 𝑆𝐸 ⇒) Se l’istanza che abbiamo costruito per Soluzioni Intere ha risposta SI, sia x il vettore a
componenti intere per cui 𝐴𝑥𝑇 ≥ 𝑏. Tale vettore, in virtù delle disuguaglianze xi ≥ 0 e xi ≤ 1, deve
essere necessariamente binario. Definiamo V ′ = {i : xi = 1}. Vale che per ogni ∀ (u, v) ∈ E o u ∈ V ′,
oppure v ∈ V ′, in quanto per avere 𝑥𝑢 + 𝑥𝑣 ≥ 1 nel sistema o vale xu = 1 oppure xv = 1. Vale inoltre
che |V ′| = k in quanto 𝑥1 + 𝑥2 + . . . + 𝑥𝑛 ≥ 𝑘 e 𝑥1 + 𝑥2 + . . . + 𝑥𝑛 ≤ 𝑘 ossia
𝑥1 + 𝑥2 + . . . + 𝑥𝑛 = 𝑘.
Pertanto, V′ è un vertex cover per il grafo G, con |V′| = k, e quindi l’istanza G = (V,E) e l’intero k
rappresentano un’istanza per il problema del Vertex Cover con risposta SI.
𝐷𝑖𝑚 𝑆𝑂𝐿𝑂 𝑆𝐸 ⇐) Viceversa, se l’istanza G = (V,E) e l’intero k rappresentano un’istanza per il problema del
Vertex Cover con risposta SI, sia V ′ ⊆ V un vertex cover di cardinalità k e definiamo il vettore
𝑥 = (𝑥1, . . . , 𝑥𝑛) con la regola: xi = 1 se i ∈ V ′, e xi = 0 se i ∉ V ′.
È facile vedere che il vettore x è soluzione al sistema 𝐴𝑥𝑇 ≥ 𝑏, pertanto l’istanza data dalla matrice A
e dal vettore b rappresentano una istanza con risposta SI al problema della Soluzioni Intere.
Abbiamo quindi costruito una riduzione R, calcolabile in tempo polinomiale, che trasforma istanze di input
𝛼 al problema del Vertex Cover in istanze di input 𝛽 al problema della Soluzioni Intere, in modo tale che 𝛼 è
una istanza con risposta SI a Vertex Cover se e solo se 𝛽 è una istanza con risposta SI a Soluzioni Intere.
Quindi Vertex Cover è riducibile in tempo polinomiale a Soluzioni Intere.
Algoritmi e Strutture Dati 2: Lezione 3- Problemi NP, P
7
Lezione 3- Problemi NP, P Noi siamo interessati alla risoluzione di problemi “interessanti”, tra quelli che abbiamo già visto ci sono:
Problema delle guardie nel museo (Vertex Cover)
Problema degli invitati alla festa (Indipendent Set)
Problema della soddisfacibilità di formule (SAT)
Soluzioni Intere
Data una soluzione di un problema deve essere possibile verificarne la correttezza efficientemente. Questo
significa che la verifica della correttezza delle soluzioni non deve avere tempi esponenziali ma polinomiali.
Tutte le soluzioni dei problemi sopra elencati sono verificabili in tempo polinomiale, ma in generale non
tutte lo sono.
In particolare per verificare una soluzione per cui una formula 3-SAT è soddisfacibile, basta assegnare i
valori di verità a X in modo tale da rende la formula vera. Se invece volessimo verificare che una formula 3-
SAT non è soddisfacibile dovremmo provare tutti i possibili valori di verità per X e questo lo rende un
problema esponenziale (2n) quindi non efficiente.
Formalmente:
Assumiamo che tutti gli input ai problemi algoritmici sono stringhe binarie (grafi, matrici, numeri,
formule,.. si possono rappresentare tutti in binario).
X è un problema algoritmico (di tipo decisionale):
X = { 𝑥 ∈ 0,1 ∗ ∶ 𝑥 è 𝑢𝑛′ 𝑖𝑠𝑡𝑎𝑛𝑧𝑎 𝑑𝑖 𝑡𝑖𝑝𝑜 "SI" 𝑝𝑒𝑟 𝑋 }
Es. Vertex Cover = { x ∈ {0,1}* : x è una corretta codifica di un grafo G ed un intero k, tale che G ha
un V.C. di dimensione ≤k }
Un algoritmo A risolve il problema X ↔ ∀ 𝑥 ∈ 0,1 ∗ A(x)=”SI” ↔ 𝑥 ∈ 𝑋
Un algoritmo A risolve X in tempo polinomiale ↔
∃ 𝑢𝑛 𝑝𝑜𝑙𝑖𝑛𝑜𝑚𝑖𝑜 𝑝 ⋅ 𝑡. 𝑐. ∀𝑥 ∈ 0,1 ∗ 𝑙′𝑎𝑙𝑔𝑜𝑟𝑖𝑡𝑚𝑜 A risolve X e la complessità di A è polinomiale
in |X|
Nota: " ∙ " sta per Certificato.
Un algoritmo polinomiale di verifica per un problema X, è un algoritmo B( ∙ , ∙ ) tale che:
1. ∃ 𝑝 ∙ polinomio per cui ∀ 𝑥 ∈ 0,1 ∗ x ∈ X ↔ ∃ 𝑦 ∈ 0,1 ∗ 𝑦 ≤ 𝑝 𝑥 per cui 𝐵 𝑥, 𝑦 = 𝑆𝐼
Se x ∉ X -> ∀ 𝑦 ∈ 0,1 ∗ 𝐵 𝑥, 𝑦 = 𝑁𝑂
Da notare che con x ∈ X intendiamo le istanze di tipo “SI” e con x ∉ X quelle di tipo “NO”.
2. B( ∙ , ∙ ) è polinomiale sia in |x| che |y|.
ES. su Indipendet Set
S -> sequenza binaria (Grafo, k) di tipo SI
(PROVA): y -> codifica binaria dei k vertici che risolvono IS
B -> algoritmo: esempio for su adiacenze dei k vertici
Problemi NP, P NP = 𝑋: 𝑝𝑒𝑟 𝑋 𝑒𝑠𝑖𝑠𝑡𝑒 𝑢𝑛 𝑎𝑙𝑔𝑜𝑟𝑖𝑡𝑚𝑜 𝑑𝑖 𝑣𝑒𝑟𝑖𝑓𝑖𝑐𝑎 𝑝𝑜𝑙𝑖𝑛𝑜𝑚𝑖𝑎𝑙𝑒 ES: {IS, VC, 3-SAT, …-
P = 𝑋: 𝑝𝑒𝑟 𝑋 𝑒𝑠𝑖𝑠𝑡𝑒 𝑢𝑛 𝑎𝑙𝑔𝑜𝑟𝑖𝑡𝑚𝑜 𝑑𝑖 𝑠𝑜𝑙𝑢𝑧𝑖𝑜𝑛𝑒 𝑝𝑜𝑙𝑖𝑛𝑜𝑚𝑖𝑎𝑙𝑒 ES: {MST, Tutti gli esempi di ASD1}
P ⊆ NP
NP
P
Algoritmi e Strutture Dati 2: Lezione 3- Problemi NP, P
8
Se un problema è risolvibile in tempo polinomiale 𝑝 ∙ (P) allora è verificabile in tempo polinomiale 𝑝 ∙
(NP).
P ⊆ NP ↔ ∀ 𝑋 ∈ P -> 𝑋 ∈ NP
𝑋 ∈ P ↔ ∃ A di complessità polinomiale tale che ∀ 𝑥 ∈ 0,1 ∗ 𝑥 ∈ 𝑋 ↔ A(𝑥)=”SI”
Es. di algoritmo di verifica polinomiale:
𝐵 𝑥, 𝑦 -> Return A(x). Soddisfa le proprietà del certificatore?
Se 𝑥 ∈ 𝑋 allora ∀ 𝑦 ∈ 0,1 ∗ 𝐵 𝑥, 𝑦 = 𝑆𝐼
Se x ∉ X allora ∀ 𝑦 ∈ 0,1 ∗ 𝐵 𝑥, 𝑦 = 𝑁𝑂
P = NP se non c’è differenza tra trovare una soluzione e verificare se una soluzione è corretta.
Intuitivamente cercare è molto più difficile di verificare (dicotomia tra cercare e verificare).
Per cui intuitivamente P ≠ NP ma P ⊆ NP
Cioè
Vorremmo provare P ⊆ NP cioè che ∃ 𝑋 ∈ NP e 𝑋 ∉ P
Supponiamo X sia più difficile di tutti i problemi in NP ↔ ∀ 𝑌 ∈ 𝑁𝑃 𝑌 ≤𝑝 𝑋
Se X ∈ P -> ∀ 𝑌 ∈ 𝑁𝑃 𝑌 ∈ 𝑃 allora 𝑃 = 𝑁𝑃
X è NP-Completo ⟺ 𝑋 ∈ 𝑁𝑃 ∀ 𝑌 ∈ 𝑁𝑃 𝑌 ≤𝑝 𝑋 sappiamo che Y è verificabile in tempo polinomiale.
Se P ≠ NP -> ∀ 𝑋 NP-Completo, 𝑋 ∉ P. Se risolvessimo un problema NP-Completo allora potremmo risolvere
tutti i problemi NP per riduzione (dato che gli NP-C sono i più difficili).
Finora abbiamo soltanto definito un problema NP-C, in seguito ne proveremo l’esistenza.
NP
X P
Algoritmi e Strutture Dati 2: Lezione 4 – Soddisfacibilità di circuito
9
Lezione 4 – Soddisfacibilità di circuito Abbiamo introdotto 3 concetti:
1. Verificatore polinomiale: X dato problema computazionale, 𝐵 ∙,∙ è un algoritmo a 2 componenti,
verificatore polinomiale per X, se soddisfa 2 proprietà:
a. ∃ 𝑝 ∙ tale che ∀ 𝑥 ∈ 0,1 ∗ se x ∈ X (dove x è input di tipo SI) allora ∃ 𝑦 ∈ 0,1 ∗ 𝑦 ≤
𝑝 𝑥 per cui 𝐵 𝑥, 𝑦 = 𝑆𝐼.
Se x ∉ X allora ∀ 𝑦 ∈ 0,1 ∗ 𝐵 𝑥, 𝑦 = 𝑁𝑂.
b. 𝐵 ∙,∙ è 𝑝𝑜𝑙𝑖𝑛𝑜𝑚𝑖𝑎𝑙𝑒 𝑖𝑛 𝑥 𝑒 |𝑦|
2. NP = 𝑋: 𝑋 è 𝑢𝑛 𝑝𝑟𝑜𝑏𝑙𝑒𝑚𝑎 𝑑𝑖 𝑑𝑒𝑐𝑖𝑠𝑖𝑜𝑛𝑒 𝑝𝑒𝑟 𝑐𝑢𝑖 𝑒𝑠𝑖𝑠𝑡𝑒 𝑢𝑛 𝑣𝑒𝑟𝑖𝑓𝑖𝑐𝑎𝑡𝑜𝑟𝑒 𝑝𝑜𝑙𝑖𝑛𝑜𝑚𝑖𝑎𝑙𝑒
3. Per provare che un problema è NP-Completo
X è NP-Completo ⟺ 𝑋 ∈ 𝑁𝑃
∀ 𝑌 ∈ 𝑁𝑃 𝑌 ≤𝑝 𝑋 sappiamo che Y è verificabile in tempo polinomiale.
1° problema NP-Completo: Soddisfacibilità di un Circuito Soddisfacibilità di un Circuito Booleano ≡ Grafo aciclico direzionato
Vi è un sottoinsieme di vertici di grado entrante 0 (non entrano archi) diviso in vertici “costanti”:
etichettati con valori 𝑥1 … 𝑥𝑛 e vertici “input”: etichettati con variabili booleane 𝑥 ∈ 0,1
Tutti gli altri vertici sono etichettati con valori booleani: ⋀, , ¬
o se di tipo ¬ : allora ha un solo arco entrante altrimenti 2.
ESEMPIO:
Input : Circuito booleano codificato in binario
Domanda: esiste un’assegnazione delle variabili 𝑥1 , … , 𝑥𝑛 che rende l’output del circuito = 1 ?
∀ 𝑿 ∈ 𝑵𝑷 , 𝑿 ≤𝒑 𝑪𝒊𝒓𝒄𝒖𝒊𝒕𝒐 𝑩𝒐𝒐𝒍𝒆𝒂𝒏𝒐
Osservazione: Sia A un algoritmo per cui esiste un polinomio 𝑝 ∙ tale che ∀ 𝑥 ∈ 0,1 ∗, A produce
l’output 𝐴 𝑥 = {𝑆𝐼, 𝑁𝑂} in tempo 𝑝 𝑥
∀ 𝑛 𝑓𝑖𝑠𝑠𝑎𝑡𝑜 ∃ 𝐶𝑛 circuito booleano con un numero di nodi 𝑝 𝑛 per qualche polinomio 𝑝 ∙ tale
che ∀ 𝑥 ∈ 0,1 ∗, 𝑥 = 𝑛 vale che A(x)=SI ⟺ Cn ha output 1 con input x. Inoltre Cn è calcolabile in
tempo polinomiale in n = 𝑥 a partire da A e |x|.
Qualunque algoritmo è simulabile in un circuito.
Sia dato 𝑥 ∈ 0,1 𝑛 ⟹ A esegue un numero di passi p(n) per produrre A(x) ⟹ A accederà al più a p(n)
locazioni di memoria.
I dati creati da A hanno valore al più polinomiale.
o Ogni valore creato da A può essere rappresentato da p(n) bits. La descrizione di tutta la
memoria usata da A nel corso della sua esecuzione richiede un numero polinomiale di bits.
o A può accedere al più p(n)+k locazioni di memoria = (O(log n)) dove k = O(1).
Memoria totale di A
Algoritmi e Strutture Dati 2: Lezione 4 – Soddisfacibilità di circuito
10
Mem passo 1 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Mem passo 2
…..
…..
…..
Mem passo p(n)
È un polinomio
Quindi:
𝑋 ∈ 𝑁𝑃 ⟹ ∃ 𝐵 ∙,∙ 𝑐𝑒𝑟𝑡𝑖𝑓𝑖𝑐𝑎𝑡𝑜𝑟𝑒 𝑝𝑒𝑟 𝑋, 𝑡𝑎𝑙𝑒 𝑐𝑒 𝑥 ∈ 𝑋 ⟹ ∃ 𝑦 | 𝑦 ≤ 𝑝 𝑥 𝑝𝑒𝑟 𝑐𝑢𝑖 𝐵 𝑥, 𝑦 = 𝑆𝐼
𝑥 ∉ 𝑋 ⟹ ∀ 𝑦 𝐵 𝑥, 𝑦 = 𝑁𝑂
In tempo polinomiale.
∀ 𝑥 ∈ 0,1 ∗ input a X, 𝑥 = 𝑛, 𝐵 𝑥,∙ = 𝐴(∙) 𝑆𝐼𝑁𝑂
⟹ 𝐵(𝑥,∙) è simulabile con un circuito p(∙)
nota: " ∙ " sta per Certificato.
𝑋 → circuito booleano che simula 𝐵(𝑥,∙).
Se 𝑥 ∈ 𝑋 ⟹ ∃ 𝑦 per cui B(x,y) = SI ⟺ Circuito è soddisfacibile
Se 𝑥 ∉ 𝑋 ⟹ ∀ 𝑦 𝐵 𝑥, 𝑦 = 𝑁𝑂 e il circuito non è soddisfacibile ovvero non esiste un’assegnazione di
input per renderlo soddisfacibile.
Sia X NP-Completo, 𝑋 ≤𝑝 𝑌 ⟹ 𝑌 è 𝑁𝑃 − 𝐶𝑜𝑚𝑝𝑙𝑒𝑡𝑜
Tutti i problemi in NP sono riducibili polinomialmente ad X. Quindi se 𝑋 ≤𝑝 𝑌, allora i problemi in NP sono
riducibili a Y. Possiamo usare la proprietà transitiva:
𝑋 ≤𝑝 𝑍 ⟸ 𝑋 ≤𝑝 𝑌
𝑌 ≤𝑝 𝑍
Ora se volessi provare che un problema è NP-Completo, confronto solo Circuito Booleano ≤𝑝 nuovo
problema. Questo implica che X è NP-Completo. Qualunque problema di fatto è equivalente alla
soddisfacibilità dei circuiti. Bisogna identificare i problemi difficili.
Sappiamo che: 3-SAT ≤𝑝 I.S. ≤𝑝 V.C. ≤𝑝 S.I.
Soddisfacibilità di circuito ≤p 3-SAT Vogliamo provare che Soddisfacibilità di circuito ≤𝒑 3-SAT.
Se riuscissimo a provare questo, proveremmo che tutti i problemi sopra elencati sono NP-Completo.
3-SAT:
o Input: 𝐹 = (𝐶1 ∧ 𝐶2 …∧ 𝐶𝑛)
𝐶𝑖 = (𝑡𝑖1 𝑡𝑖2 𝑡𝑖3)
𝑡𝑖𝑗 ∈ 𝑥1 …𝑥𝑛 , 𝑥1 … 𝑥𝑛
o Domanda: ∃ un’associazione di valori 0/1 alle xi che vede F=1?
Soddisfacibilità di circuito ≤𝑝 3-SAT: devo trovare una trasformazione da input a circuito in input a formule
per 3-SAT. Ricordiamo che un circuito è un grafo aciclico (senza cicli).
Sia V= insieme dei vertici del circuito C.
X = {xv t.c v ∈ insieme dei valori booleani}
v
Algoritmi e Strutture Dati 2: Lezione 4 – Soddisfacibilità di circuito
11
Bisogna imporre delle limitazioni. Ai nodi associamo le variabili.
1. NEGAZIONE:
Devo imporre che 𝑥𝑣 = 𝑥𝑢 ⟺ 𝑥𝑣 𝑥𝑢 ⋀ 𝑥𝑢 ∨ 𝑥𝑣 se fossero già uguali
all’inizio avrei problemi. Questo perché 3-SAT non risolve da solo la negazione.
Per essere 1 alla fine le 2 variabili devono assumere valori opposti
2. OR
𝑥𝑣 = 𝑥𝑢 𝑥𝑤 ⟺ 𝑥𝑣 𝑥𝑢 ⋀ 𝑥𝑣 ∨ 𝑥𝑤 ∧ 𝑥𝑣 ∨ 𝑥𝑢 ∨ 𝑥𝑤
3. AND
𝑥𝑣 = 𝑥𝑢 ∧ 𝑥𝑤 ⟺ 𝑥𝑢 𝑥𝑣 ⋀ 𝑥𝑤 ∨ 𝑥𝑣 ∧ 𝑥𝑤 ∨ 𝑥𝑢 ∨ 𝑥𝑣
4. Costanti
5. Radice
Esempio:
𝐹
= 𝑥1 ⋀ 𝑥2 ⋀ 𝑥5 𝑥1 ⋀ 𝑥5 𝑥2 ⋀ 𝑥5 𝑥1 𝑥2 ⋀ 𝑥6 𝑥2 ⋀ 𝑥6 𝑥3 ⋀ 𝑥6 𝑥2 𝑥3 ⋀ 𝑥7 𝑥4 ⋀ 𝑥7 𝑥4 ⋀
𝑥8 𝑥6 ⋀ 𝑥8 𝑥7 ⋀ 𝑥8 𝑥6 𝑥7 ⋀ 𝑥9 𝑥5 ⋀(𝑥9 𝑥8)⋀ 𝑥9 𝑥5 𝑥8
𝑥𝑣
𝑥𝑢
v
u w
𝑥𝑤
𝑥𝑢
𝑥𝑣
v
u w
𝑥𝑤
𝑥𝑢
𝑥𝑣
1
0
v
v
xv
xv
xv
𝑥𝑣
x0 con x0=1
6
1 0 1 2
3 4
5
7
8
9
Algoritmi e Strutture Dati 2: Lezione 4 – Soddisfacibilità di circuito
12
Questa formula calcola il circuito. Per poter ridurre a 3-SAT, bisogna che le clausole abbiano tutte 3
letterali. Per fare ciò introduciamo 4 variabili: 𝑧1 , 𝑧2 , 𝑧3 , 𝑧4 in modo tale che non diano fastidio al risultato
del circuito con gli stessi input.
Devo fare in modo che 𝑧1 , 𝑧2 valgano entrambi zero (0).
Per fare questo creo la seguente regola:
𝑍 = 𝑧1 ∨ 𝑧3 ∨ 𝑧4 ∧ 𝑧1 ∨ 𝑧3 ∨ 𝑧4 ∧ 𝑧1 ∨ 𝑧3 ∨ 𝑧4 ∧ 𝑧1 ∨ 𝑧3 ∨ 𝑧4
𝑧2 ∨ 𝑧3 ∨ 𝑧4 ∧ 𝑧2 ∨ 𝑧3 ∨ 𝑧4 ∧ 𝑧2 ∨ 𝑧3 ∨ 𝑧4 ∧ 𝑧2 ∨ 𝑧3 ∨ 𝑧4 è soddisfatta (vale 1) ⟺ 𝑧1 =
0, 𝑧2 = 0
Ora introduciamo le variabili appena specificate nella formula.
Se la clausola ha un solo letterale : 𝐶𝑖 = 𝑡𝑖1 ⟹ 𝐶𝑖 = (𝑡𝑖1 𝑧1 𝑧2)
Se ve ne sono 2 : 𝐶𝑖 = 𝑡𝑖1 ∨ 𝑡𝑖2 ⟹ 𝐶𝑖 = (𝑡𝑖1 𝑡𝑖2 𝑧2)
E infine inserisco la formula della Z
𝑧1 ∨ 𝑧3 ∨ 𝑧4 ∧ 𝑧1 ∨ 𝑧3 ∨ 𝑧4 ∧ 𝑧1 ∨ 𝑧3 ∨ 𝑧4 ∧ 𝑧1 ∨ 𝑧3 ∨ 𝑧4 ∧ 𝑧2 ∨ 𝑧3 ∨ 𝑧4 ∧ 𝑧2 ∨ 𝑧3 ∨ 𝑧4 ∧
𝑧2 ∨ 𝑧3 ∨ 𝑧4 ∧ 𝑧2 ∨ 𝑧3 ∨ 𝑧4
Quindi la soluzione dell’esercizio sopra riportato sarà:
𝐹 = 𝑥1 𝑧1 𝑧2 ⋀ 𝑥2 𝑧1 𝑧2 ⋀ 𝑥5 𝑥1 𝑧2 ⋀ 𝑥5 𝑥2 𝑧2 ⋀ 𝑥5 𝑥1 𝑥2 ⋀ 𝑥6 𝑥2 𝑧2 ⋀ 𝑥6 𝑥3 𝑧2 ⋀
𝑥6 𝑥2 𝑥3 ⋀ 𝑥7 𝑥4 𝑧2 ⋀ 𝑥7 𝑥4 𝑧2 ⋀ 𝑥8 𝑥6 𝑧2 ⋀ 𝑥8 𝑥7 𝑧2 ⋀ 𝑥8 𝑥6 𝑥7 ⋀ 𝑥9 𝑥5 𝑧2
⋀(𝑥9 𝑥8 𝑧2)⋀ 𝑥9 𝑥5 𝑥8 ∧ 𝑧1 ∨ 𝑧3 ∨ 𝑧4 ∧ 𝑧1 ∨ 𝑧3 ∨ 𝑧4 ∧ 𝑧1 ∨ 𝑧3 ∨ 𝑧4 ∧ 𝑧1 ∨ 𝑧3 ∨ 𝑧4
∧ 𝑧2 ∨ 𝑧3 ∨ 𝑧4 ∧ 𝑧2 ∨ 𝑧3 ∨ 𝑧4 ∧ 𝑧2 ∨ 𝑧3 ∨ 𝑧4 ∧ 𝑧2 ∨ 𝑧3 ∨ 𝑧4
Soddisfacibilità di circuito ≤𝑝 3-SAT≤𝑝 𝐼𝑛𝑑. 𝑆𝑒𝑡 ≤𝑝 Vertex Cover ≤𝑝 soluzione intera≤𝑝 insieme dominante
Sono tutti problemi NP-Completo.
Algoritmi e Strutture Dati 2: Lezione 5 - Problema della pianificazione delle attività
13
Lezione 5 - Problema della pianificazione delle attività
Problema della pianificazione delle attività Il problema che andremo ad affrontare risulta essere un problema molto comune nella vita reale, in quanto molto spesso nasce l’esigenza di dover pianificare l'ordine di esecuzione di determinate attività, come ad esempio l'assemblaggio dei componenti di un computer oppure l’assegnazione di un percorso ad un autobus etc. Vi sono dei processi in cui il montaggio di un pezzo può impedire il montaggio dell’altro. L’input di un Processo Pi ha bisogno dell’output Pi-1.
Dato P = {p1, …, pn} un insieme di azioni (jobs da eseguire), ∀pi ∃ S(pi) ⊆ {pi , … , pn}, ossia per ogni jobs da eseguire, esiste un sottoinsieme di azioni che possono essere effettuate solo dopo aver effettuato pi. L’obiettivo è quello di eseguire tutti i job in un qualche ordine ed pi1, pi2 …, pin in maniera tale che questo
ordine sia legittimo cioè ogni job pi può essere eseguito pij+1 ∈ S(pij
).
∃ un ordine, una permutazione dei jobs p1 , … , pn tale che pi+1 ∈ S(pi) ∀ i = 1, … , n ?
Progetto genoma Una stringa di DNA risulta essere composta da circa 50 milioni di simboli, una lunghezza enorme, ne
consegue che l’analisi dell’intera sequenza sarebbe stato un lavoro spropositato da realizzare da parte di un
solo laboratorio di ricerca. Di conseguenza, i singoli laboratori di volta in volta hanno operato solo su alcuni
pezzi, muovendosi in maniera indipendente nel selezionare ed analizzare singoli frammenti. Naturalmente
operando in questo modo, spesso in alcuni casi si sono verificate delle sovrapposizioni nella lettura di
alcune porzioni della stringa, quindi è nata l’esigenza di dover eliminare le ridondanze in fase di unione dei
risultati. Si pensò di prendere le parti che avevano più lunghe sequenze in comune e considerarle
consecutive, il problema che ne nasceva era un Cammino Hamiltoniano.
Supponiamo per semplicità che il DNA sia costituito dai caratteri A, T, G, C e supponiamo che ogni
laboratorio abbia letto solo stringhe di tre lettere. Quindi disegneremo un arco tra due triple che fanno
coincidere le ultime due cifre di una con le prime due di un'altra, ossia seguiremo la seguente regola
XYZ YZK.
ATG1C13G37T78G84 G42 G43 C25A56 (con i pedici abbiamo indicato la stringa di partenza e quella di destinazione)
La stringa da definire è il risultato dell’unione delle stringhe contenenti sottostringhe in comune.
Nel grafo che si genererà, dovremo trovare un cammino hamiltoniano.
Input: Grafo diretto G = (V, E).
Domanda: ∃ un ciclo in G che attraversa tutti i suoi vertici, una ed una sola volta?
Circuito Hamiltoniano
Input: Dato P = {p1, …, pn} un insieme di azioni (jobs da eseguire), ∀pi ∃ S(pi) ⊆ {pi , … , pn }, ossia per ogni jobs da eseguire, esiste un sottoinsieme di azioni che possono essere effettuate solo dopo aver effettuato pi.
Domanda: ∃ un ordine, una permutazione dei jobs p1 , … , pn tale che pi+1 ∈ S pi , ∀ i = 1, … , n ?
Ossia è possibile determinare un ordine di esecuzione delle attività tale che il job successivo a pi sia una delle attività che deve essere necessariamente eseguita dopo pi? Possiamo tradurre tale problema in un grafo, definiamo quindi un Grafo diretto G = (V, E), così costruito:
i vertici V = {pi , … , pn} sono costituiti dai pi jobs da eseguire;
ATG 1 TGG 2 TGC 3 GTG 4 GGC 5 GCA 6 GCG 7 CGT 8
Algoritmi e Strutture Dati 2: Lezione 5 - Problema della pianificazione delle attività
14
∀(u, v) ∊ E ⇔ v ∊ S u , ossia tra due attività u e v, vi sarà un arco direzionato che le collega, che va da u a v (u → v), se solo se sarà possibile eseguire v dopo di u (v job appartenente al sottoinsieme di attività che devono necessariamente essere eseguite dopo u).
Il grafo così costruito dal problema del Circuito Hamiltoniano o (Ciclo Hamiltoniano) risulta essere equivalente al problema del Cammino Hamiltoniano.
Problema del Cammino Hamiltoniano Dato un grafo non orientato G = (V, E), diciamo che un cammino C è Hamiltoniano se visita tutti i vertici ed ogni vertice esattamente una volta. Ossia costituisce un “tour” di tutti i vertici senza ripetizioni.
Come abbiamo visto in precedenza, si ha un ciclo hamiltoniano quando in un cammino hamiltoniano esiste un arco che collega l'ultimo vertice con il primo, realizzando così un ciclo che visita tutti i vertici per poi ritornare al punto di partenza. Infatti, la domanda posta dal problema del Circuito Hamiltoniano:
Domanda: Esiste un modo per eseguire in un determinato ordine tutte le azioni, svolgendo ognuna di esse una sola volta?
Risulta essere simile a quella posta dal problema del Cammino Hamiltoniano:
Domanda: Esiste in G un cammino che visita tutti i vertici di G una ed una sola volta?
A questo punto, vista la somiglianza tra i due problemi potremmo provare a ridurne uno dall’altro.
Circuito Hamiltoniano ≤ p Cammino Hamiltoniano Input: un grafo direzionato G = (V, E)
Domanda: ∃ in G un ciclo che attraversa tutti i vertici di G una ed una sola volta?
G
V
f
G’
V
f
u’
f
x
f
y
f
b
f
c
f
a
f
u’’
u
f
x
f
y
f
a
f
b
f
c
f
Istanza di un circuito
Hamiltoniano
Istanza di un cammino
Hamiltoniano
1 3
2 4
Algoritmi e Strutture Dati 2: Lezione 5 - Problema della pianificazione delle attività
15
Data una generica istanza di un circuito Hamiltoniano, un grafo diretto G, scelgo a caso un vertice u e verifico attraverso gli archi entranti i vertici raggiungibili da u e attraverso quelli uscenti i vertici che permettono di tornare in u.
Supponiamo che G sia una istanza di tipo “SI” che contiene un Ciclo Hamiltoniano, pertanto da u dovrò attraversare seguendo gli archi diretti, prima a e poi b, poi ritornerò in u continuando il cammino attraverso i nodi a, b ed u. Ottengo una istanza di un Cammino Hamiltoniano, costruendo un grafo diretto G’ simile a G, ma separando u in due vertici u’ e u’’, u’ avrà solo archi uscenti, mentre u’’ solo archi entranti.
Se G’ contiene un cammino, questo dovrà necessariamente partire da u’, perché non ci sono archi entranti in u’ e quindi questo sarebbe l’unico modo affinché sia visitato. Poiché gli altri vertici hanno tutti archi diretti verso u’’, il cammino dovrà obbligatoriamente terminare in u’’. Con un tale cammino, avremo quindi una istanza di tipo “Si” anche per G’. Abbiamo dimostrato quindi che trovare un cammino hamiltoniano in un grafo non è più difficile di trovare un circuito hamiltoniano.
Un Circuito Hamiltoniano ∊ NP, dobbiamo dimostrare che un Circuito Hamiltoniano è verificabile in tempo polinomiale. Dato un grafo diretto, il certificato che ci garantisce che ci sia una soluzione, sarà la lista ordinata dei vertici del ciclo Hamiltoniano. Potremo quindi verificare, in tempo polinomiale, che la lista dei vertici contiene un vertice esattamente una volta ed ogni coppia consecutiva di vertici della lista ordinata è collegata da una arco; ciò sarebbe sufficiente a garantire di avere un Ciclo Hamiltoniano.
3-SAT ≤p Circuito Hamiltoniano Mostriamo che Ciclo Hamiltoniano è riducibile a 3-SAT, nonostante i problemi sembrino differenti, faremo uso di 3-SAT, poiché la sua struttura combinatoria risulta essere basilare e quindi applicabile a più contesti.
Prendiamo in considerazione una istanza di 3-SAT, ossia che bisogna soddisfare una formula F costituita da
𝐶1 , …𝐶𝑘 clausole, ognuna delle quali composta da 𝑥1 … 𝑥𝑛 variabili. Il nostro obiettivo sarà quello di
risolvere tale istanza cercando di individuare nel grafo diretto che andremo a costruire un Ciclo
Hamiltoniano.
Costruiremo un grafo che contiene 2𝑛 differenti Cicli Hamiltoniani che corrispondono esattamente ai 2𝑛
possibili assegnamenti di verità delle variabili.
Costruiamo quindi il grafo ponendo tali vincoli:
Costruiamo n path 𝑃1 …𝑃𝑛 , dove ogni path 𝑃𝑖è costituito da 𝑣𝑖1 , 𝑣𝑖2 , …𝑣𝑖𝑏 nodi con b che risulta
essere uguale a b = 3k + 3, dove k è il numero di clausole;
Ci sono archi che collegano i nodi adiacenti in entrambe le direzioni, ossia da 𝑣𝑖𝑗 𝑎 𝑣𝑖𝑗 +1 e da 𝑣𝑖𝑗 +1
a 𝑣𝑖𝑗 ;
Ogni path 𝑃𝑖 potrà essere attraversato da “sinistra a destra”, da 𝑣𝑖1 𝑎 𝑣𝑖𝑏 oppure da “destra a
sinistra”, da 𝑣𝑖𝑏 𝑎 𝑣𝑖1.
Tutti i nodi di ogni path dal primo all’ultimo saranno tutti connessi, inoltre avremo altri nodi extra, s
e t, s collegato tramite due archi a 𝑣11 𝑎 𝑣1𝑏 𝑒 𝑡 collegato anche’esso attraverso due archi a
𝑣𝑛1 𝑎 𝑣𝑛𝑏 .
u
a b
u’
a b
u’’
Algoritmi e Strutture Dati 2: Lezione 5 - Problema della pianificazione delle attività
16
Se entro in un livello, lo devo visitare tutto, altrimenti si ha che visito un nodo 2 volte. Per ogni livello ho 2 scelte. Come è possibile vedere dall’immagine, il nostro grafo avrà 2 clausole (k = 2) e di conseguenza 9
vertici, b = 3k + 3 ⟹ b = 6 + 3 = 9.
Per costruzione abbiamo un solo arco da t ad s, quindi dovrà essere attraversato da Ciclo Hamiltoniano C.
Il ciclo C entrato in s, potrà attraversare il primo path, da sinistra o da destra, allo stesso modo avremo due possibili modi di attraversare i path restanti, fino a concludere il ciclo in t.
Il modo di attraversare il grafo attraverso n scelte indipendenti, sarà anche il modo in cui andremo a settare ogni variabile dell’istanza 3-SAT, questo ci permetterà di identificare un Ciclo Hamiltoniano unicamente attraverso un assegnamento di verità:
Se il ciclo C attraversa il path 𝑃𝑖 da sinistra a destra, setteremo 𝑥𝑖 ad 1;
Altrimenti setteremo 𝑥𝑖 ad 0.
Settiamo nel nostro grafo due clausole, 𝐶1 = 𝑥1 𝑥2 𝑥3 e 𝐶2 = 𝑥1 𝑥2 𝑥3
Per ogni clausola, definiamo un nodo 𝑐𝑗 , per ogni variabile della clausola 𝐶𝑗 , riserveremo i nodi del path 𝑃𝑗 ,
Algoritmi e Strutture Dati 2: Lezione 5 - Problema della pianificazione delle attività
17
in posizione 3𝑗 e 3𝑗 + 1, ed aggiungeremo degli archi per connettere tali nodi alla variabile 𝑐𝑗 .
Se la variabile 𝑥𝑗 della clausola 𝐶𝑗 avrà valore di verità 1, avremo un arco ( 𝑣𝑖 ,3𝑗 , 𝑐𝑗 ) ed uno (𝑐𝑗 , 𝑣𝑖,3𝑗+1) con
una visita del path da sinistra a destra, mentre se avremo un valore di verità 0 della variabile, avremo un arco (𝑣𝑖 ,3𝑗+1 , 𝑐𝑗 ) ed uno ( 𝑐𝑗 , 𝑣𝑖,3𝑗 ) con una visita del path da destra a sinistra.
Nel nostro grafo di esempio avremo:
La prima clausola 𝐶1 = 𝑥1 𝑥2 𝑥3, ci dice che dovremo attraversare:
Il path 1, attraverso i nodi in posizione 3 e 4, da sinistra a destra (nel grafo gli archi in rosso).
Il path 2, attraverso i nodi in posizione 3 e 4, da destra a sinistra (nel grafo gli archi in verde).
Il path 3, attraverso i nodi in posizione 3 e 4, da sinistra a destra (nel grafo gli archi in blu).
La seconda clausola 𝐶2 = 𝑥1 𝑥2 𝑥3 , ci dice che dovremo attraversare:
Il path 1, attraverso i nodi in posizione 6 e 7, da destra a sinistra (nel grafo gli archi in rosso).
Il path 2, attraverso i nodi in posizione 6 e 7, da destra a sinistra (nel grafo gli archi in verde).
Il path 3, attraverso i nodi in posizione 6 e 7, da destra a sinistra (nel grafo gli archi in blu).
Con la costruzione di tale grafo, siamo riusciti a ridurre una istanza di 3-SAT in una istanza del problema del Circuito Hamiltoniano. Ora per completare la dimostrazione, dovremo mostrare che l’istanza 3-SAT è soddisfacibile se e solo se il grafo G ha un Ciclo Hamiltoniano. Se abbiamo una istanza di tipo “SI” del ciclo hamiltoniano, avremo una istanza di tipo “SI” anche di 3-SAT.
Supponiamo di aver un assegnamento che soddisfi l’istanza 3-SAT, ciò significa che la clausola avrà almeno una delle variabili settate ad 1, e di conseguenza nel grafo almeno un path sarà visitato verso la variabile 𝑐𝑗
in maniera tale da permettere di visitare tutti i nodi di ogni livello una volta sola, rispettando il ciclo hamiltoniano.
Problema del Commesso Viaggiatore (Traveling Salesman Problem) TSP Il problema del commesso viaggiatore è analogo al problema del Ciclo Hamiltoniano il quale risulta essere uno dei problemi fondamentali della teoria dei grafi.
Consideriamo un commesso viaggiatore che deve visitare n città etichettate come v1, v2, …, vn ritornando alla fine del viaggio alla città di partenza v1. L'obiettivo sarà quello di trovare un percorso (tour) con distanza totale quanto più piccola possibile; ossia dato un insieme di distanze, minimizzare la distanza totale data dalla somme delle distanze.
Sia G(V,E) con
V = insieme delle città
E= { (u,v): u,v ∈ V con u≠v}
d(u,v)≥0 la distanza o costo tra le città.
Problema: trovare una permutazione di vertici v1, v2, …, vn che minimizzi la somma della distanze percorse
d vj , vj+1 𝑛−1𝑗 =1 + d(vn , v1) (quest’ultima distanza è quella relativa all’arco che collega l’ultima città
visitata con quella di partenza).
La formulazione di questo problema, è stata riutilizzata anche in altri contesti, come nella programmazione dei movimenti dei bracci robotici destinati a compiere le punzonature dei circuiti delle schede madri in maniera più efficiente; o per ottimizzare le operazioni di I/O delle testine dei hard disk, etc.
Poiché come abbiamo visto in precedenza, siamo maggiormente interessati a problemi decisionali, più che di ottimizzazione, formuleremo il problema in questi termini:
Dato un insieme di distanze di n città, ed un parametro B, ∃ un tour di lunghezza ≤ B?
Algoritmi e Strutture Dati 2: Lezione 5 - Problema della pianificazione delle attività
18
Circuito Hamiltoniano ≤p TSP E’ semplice poter affermare che il problema del commesso viaggiatore è in NP, infatti il certificato è una permutazione delle città e verifica che la lunghezza del tour corrispondente è al più uguale al limite impostato.
Dato una grafo diretto G = (V, E) con B=|V| istanza di un ciclo hamiltoniano, definiamo una istanza per TSP nel modo seguente:
Ogni nodo vi rappresenta una città v’i.
Definiamo d(vi, vj) = = 1 se ∃ vi, vj ∈ E , ossia c′è in G tale arco
= 2 altrimenti
Quindi un ciclo in G ha costo 1*n dove n è il numero di archi |E|. Se in G’ esistesse un ciclo di costo n, allora esso sarebbe anche in G in quanto se non ci fosse almeno un arco, il suo costo sarebbe 2 e quindi il costo totale sarebbe > n.
G’ è un’istanza di tipo TSP ⇔ in G ∃ un ciclo Hamiltoniano -> ∃ in G’ un ciclo di costo ≤ B. G’ è una visita di tipo commesso viaggiatore -> ∃ un ciclo di costo B=|V|. Potremo affermare che G ha un ciclo hamiltoniano se e solo se un tour all’interno della nostra istanza TSP ha lunghezza al più n.
1
2 3
G’ 4 1
2 3
G 4
Algoritmi e Strutture Dati 2: Lezione 6 - 3-Sat ≤p 3-Colorabilità
19
Lezione 6 - 3-Sat ≤p 3-Colorabilità
Problema delle Reti Radio
Ci sono n stazioni radio che vogliono trasmettere. Se nel loro raggio di azione non c’è accavallamento di
frequenza, possono trasmettere con la stessa frequenza. Se invece i segnali si sovrappongono devono
necessariamente usare frequenze diverse. Il problema sorge nella zona di intersezione. È un problema di
ottimizzazione perché le frequenze costano.
Problema: I segnali si sovrappongono e quindi si ha collisione
Soluzione: Se i segnali si sovrappongono uso frequenze diverse
Formalizzando il problema possiamo vedere tutto come un grafo:
G(V,E)
V = insieme delle stazioni radio
𝐸 = { 𝑢, 𝑣 : 𝑢 𝑒 𝑣 𝑐𝑜𝑟𝑟𝑖𝑠𝑝𝑜𝑛𝑑𝑜𝑛𝑜 𝑎𝑑 𝑎𝑛𝑡𝑒𝑛𝑛𝑒 𝑐𝑜𝑛 𝑝𝑜𝑠𝑠𝑖𝑏𝑖𝑙𝑒 𝑖𝑛𝑡𝑒𝑟𝑓𝑒𝑟𝑒𝑛𝑧𝑎}
f : V {1,2,..,k} [insieme delle frequenze] con la condizione che ∀ 𝑢, 𝑣 ∈ V se (𝑢, 𝑣) ∈ E
𝑙𝑎 𝑓𝑢𝑛𝑧𝑖𝑜𝑛𝑒 𝑑𝑒𝑣𝑒 𝑎𝑠𝑠𝑒𝑔𝑛𝑎𝑟𝑒 𝑓𝑟𝑒𝑞𝑢𝑒𝑛𝑧𝑒 𝑑𝑖𝑣𝑒𝑟𝑠𝑒 𝑜𝑠𝑠𝑖𝑎 𝑓 𝑢 ≠ 𝑓(𝑣)
Vogliamo trovare il più piccolo k per cui ciò è possibile.
𝑆 = {𝑢 ∶ 𝑓 𝑢 = 1 }
S Insieme indipendente che racchiude tutti i vertici con frequenza 1
Problemi simili a questo sono: il problema degli invitati al matrimonio e il problema della colorazione delle
nazioni. Questi problemi sono più noti come: COLORAZIONE DEI GRAFI
COLORAZIONE DEI GRAFI Se due vertici sono collegati da un arco, si coloravano di colore diverso. Gli studiosi notarono che bastavano
4 colori per colorare ogni mappa geografica dove ad ogni nazione viene assegnato un colore differente
dalle nazioni vicine.
Input : G(V,E), intero k
Domanda : Esiste una colorazione di G che usa ≤ k colori? Esiste una funzione
𝑓: 𝑉 → 1, … . , 𝑘 𝑡𝑎𝑙𝑒 𝑐𝑒 ∀ 𝑢, 𝑣 ∈ 𝐸, 𝑣𝑎𝑙𝑒 𝑐𝑒 𝑓 𝑢 ≠ 𝑓 𝑣 ?
Se k=1 il grafo è senza archi
Se k = 2 Il problema è risolvibile in tempo polinomiale ∈ P. Il grafo ha due insiemi indipendenti.
Se k = 3 Il problema non è risolvibile in tempo polinomiale e quindi ∈ NP-C
NB: Un grafo G è 2-Colorabile ↔ ∄cicli di lunghezza dispari
Esempio con ciclo dispari
Algoritmi e Strutture Dati 2: Lezione 6 - 3-Sat ≤p 3-Colorabilità
20
Esempio BFS senza cicli dispari
3-SAT ≤P 3-COLORABILITÀ
Impostiamo l’istanza di 3-SAT:
𝐹 = 𝐶1 ⋀ 𝐶2 ⋀ … ⋀ 𝐶𝑛 𝐶𝑖 = 𝑡𝑖1 ∨ 𝑡𝑖2 ∨ 𝑡𝑖3 𝑡𝑖𝑗 ∈ {𝑥1, … , 𝑥𝑛, 𝑥1 , . . . 𝑥𝑛 }
Associo ad ogni formula soddisfacibile di 3-SAT la colorabilità del grafo. Se 3-SAT non è soddisfacibile il
grafo non è 3-colorabile.
𝐿𝑒 𝑐𝑜𝑝𝑝𝑖𝑒 𝑥1 𝑒 𝑥 1 , 𝑎𝑛𝑛𝑜 𝑑𝑒𝑣𝑜𝑛𝑜 𝑎𝑣𝑒𝑟𝑒 𝑐𝑜𝑙𝑜𝑟𝑖 𝑑𝑖𝑣𝑒𝑟𝑠𝑖. 𝐼𝑛𝑜𝑙𝑡𝑟𝑒 𝑑𝑒𝑣𝑜𝑛𝑜 𝑎𝑣𝑒𝑟𝑒 𝑐𝑜𝑙𝑜𝑟𝑖 𝑑𝑖𝑣𝑒𝑟𝑠𝑖 𝑑𝑎𝑙𝑙𝑎 𝑏𝑎𝑠𝑒. 𝑄𝑢𝑖𝑛𝑑𝑖 𝑥1 𝑒 𝑥 1𝑎𝑛𝑛𝑜 𝑟𝑖𝑠𝑝𝑒𝑡𝑡𝑖𝑣𝑎𝑚𝑒𝑛𝑡𝑒 𝑖 𝑐𝑜𝑙𝑜𝑟𝑖 𝑣𝑒𝑟𝑜 𝑒 𝑓𝑎𝑙𝑠𝑜
ESEMPIO
Data la clausola 𝐶 = 𝑥1 𝑥2 𝑥3
Se scegliamo di assegnare 3 colori diversi al nostro grafo, notiamo che la nostra radice avrà un figlio che ha come colore Base impossibile
Se assegno vero a tutti e 3 i nodi il grafo non è colorabile
Se assegno falso a tutti e 3 i nodi (esempio sotto) 3-SAT non è soddisfacibile
Data la clausola 𝐶 = 𝑥 1 𝑥2 𝑥3
Algoritmi e Strutture Dati 2: Lezione 6 - 3-Sat ≤p 3-Colorabilità
21
Se supponiamo che la clausola è tutta falsa, se nessuno dei 3 riceve valore vero, il grafo non è colorabile.
Con k ≥ 4 di K-colorabilità risulta
3 𝑐𝑜𝑙𝑜𝑟𝑎𝑏𝑖𝑙𝑖𝑡à ≤𝑝 𝑘 − 𝑐𝑜𝑙𝑜𝑟𝑎𝑏𝑖𝑙𝑖𝑡à ∀𝑘 ≥ 4
3-COLORABILITÀ ≤P K-COLORABILITÀ
G = Istanza 3-Colorabilità
G’ = Istanza k-Colorabilità (G’ grafo completo formato da k-3 colori non contenuti in G)
Dato che G’ è un grafo completo ed ha k-3 vertici, ho usato k-3 colori diversi per colorarlo. Connettendo
ogni vertice di G con G’ c’è la necessità di usare colori diversi siccome G è 3-Colorabilità l’unione tra G
e G’ = ((k-3)+3) colori il grafo che si forma sarà K-Colorabilità.
Set Cover In input abbiamo numerosi insiemi, con qualche elemento in comune. Si deve selezionare il minimo
numero di questi insiemi tale che gli insiemi selezionati contengano tutti gli elementi comuni agli insiemi in
input. U è l’universo e 𝔉 è una famiglia (insieme di insiemi).
𝑈 = 𝑢1 , 𝑢2 , … , 𝑢𝑛 𝑠𝑖𝑎 𝔉 = {𝐹1 , 𝐹2 , …𝐹𝑚 ⊆ 𝑈}
Lo scopo è di trovare una sottofamiglia di
𝔉′ ⊆ 𝔉 𝑡. 𝑐. 𝐹 ⊆ 𝑈𝐹 ∈ 𝔉′ e 𝔉′ 𝑠𝑖𝑎 𝑚𝑖𝑛𝑖𝑚𝑎
Vertex cover è un suo caso molto particolare.
Hitting Set È equivalente a Set Cover. Un’istanza di Set Cover può essere vista come un grafo arbitrario bipartito con gli
insiemi rappresentati dai vertici sulla sinistra e l’universo rappresentato dai vertici sulla destra. Gli archi
rappresentano l’inclusione degli elementi dell’universo negli insiemi. Il task è quindi quello di trovare un
sottoinsieme dei vertici a sinistra di cardinalità minima in modo tale da includere tutti i vertici a destra.
𝑈 = 𝑢1 , 𝑢2 , … , 𝑢𝑛 𝑠𝑖𝑎 𝔉 = {𝐹1 , 𝐹2 , …𝐹𝑚 ⊆ 𝑈}
Lo scopo è di trovare una sottofamiglia di
𝐻 ⊆ 𝑈 𝑑𝑖 𝑐𝑎𝑟𝑑𝑖𝑛𝑎𝑙𝑖𝑡à 𝑚𝑖𝑛𝑖𝑚𝑎 𝑡. 𝑐. 𝐻 ∩ 𝐹𝑖 ≠ ∅ 𝑒 𝐹𝑖 ∈ 𝔉
Vertex cover è un suo caso molto particolare.
Problema di Costantino L’imperatore Costantino organizzò il suo impero in modo che in ogni città ci fosse una guarnigione o ce ne
fossero 2 in una città vicina. Lo scopo è quello di trovare il numero minimo di città in cui posizionare le
guarnigioni in modo da tener sotto controllo tutto l’impero.
Organizzo tutto con un grafo:
G(V,E) V = città
E = strade che uniscono le città
f = funzione che associa ad ogni vertice {0, 1, 2} guarnigioni
Algoritmi e Strutture Dati 2: Lezione 6 - 3-Sat ≤p 3-Colorabilità
22
Vogliamo trovare un sottoinsieme di vertici 𝐷 ⊆ 𝑉dove ∀ 𝑢 ∈ 𝑉 − 𝐷, ∃ 𝑣 ∈ 𝐷 𝑡. 𝑐. 𝑢, 𝑣 ∈ 𝐸 𝑒 𝑓 𝑣 = 2
Insieme Dominante Un insieme S ⊆ V di vertici è dominante se ogni vertice di V-S è adiacente ad almeno un nodo di S.
Input: Grafo G(V, E), intero k
Domanda: Esiste un sottoinsieme D ⊆ V con |D|≤ k tale che ∀ v ∈ (V – D), ∃ u ∈ D tale che (u,v) ∈ E.
La questione è trovare un insieme dominante di cardinalità minima. Questo problema per come è stato
posto è analogo a quello sorto negli Stati Uniti per la disposizione dei vigili del fuoco. Si vuole il numero
minimo di stazioni (poiché costa mantenerle) t.c. un grosso gruppo di case in legno siano vicine. Stesso
problema anche per i supermercati e i depositi.
VERTEX COVER ≤P INSIEME DOMINANTE
Input: Grafo G(V, E), intero k
Domanda: Esiste in G un INSIEME DOMINANTE di cardinalità ≤ k?
Sia (G=(V,E), k) un arbitraria istanza di input a VERTEX COVER, costruisco un’istanza (G’ =(V’,E’),k) input ad
INSIEME DOMINANTE.
1. 𝑉’ = 𝑉 ∪ 𝑢𝑣 ∶ 𝑢, 𝑣 ∈ 𝐸 . ∀ 𝑢, 𝑣 ∈ 𝐸 𝑑𝑖 𝐺 introduco un nuovo vertice collegandolo ai 2
vertici.
2. 𝐸’ = 𝐸 ∪ {(𝑢, 𝑢𝑣), (𝑣, 𝑢𝑣) ∶ (𝑢, 𝑣) ∈ 𝐸}.
3. Vediamo se è corretta, cioè vediamo se istanze SI di VERTEX COVER = istanze SI per INSIEME DOMINANTE
G ha un VERTEX COVER di cardinalità ≤ k ↔ G’ ha un INSIEME DOMINANTE di cardinalità ≤ k.
𝑆𝑒 ⇒ ) Abbiamo 3 possibilità per definire l’insieme dominante in G’:
1. Se u ∈ V del VERTEX COVER u è sicuro dominante
2. Se u è adiacente ad un vertice del VERTEX COVER u è dominato da v ∈ V del VERTEX COVER
3. Se u è un nuovo vertice sarà sicuramente adiacente ad un vertice del VERTEX COVER
Proviamo che A={c,d} è esso stesso un Insieme Dominante in G’. Supponiamo per il momento che x ∈ V , e
sia (x, y) ∈ E un arbitrario arco incidente su x. Per definizione di A, almeno uno tra x e y appartiene ad A,
pertanto o x ∈ A oppure è dominato da qualche vertice in A.
Supponiamo ora che x ∈ V’, ciò implica che 𝑥 ∈ {𝑢𝑣 ∶ (𝑢, 𝑣) ∈ 𝐸} e, per costruzione, x è adiacente sia a u
che a v. Per definizione di vertex cover, ∀(u, v) ∈ E, almeno uno tra u e v appartiene ad A, di conseguenza x
è dominato da qualche vertice in A. Concludiamo quindi che G’ ha un insieme dominante A di cardinalità ≤
k.
a c
b d
a c
b d
ad
db
b
bc
ac
G G’
Algoritmi e Strutture Dati 2: Lezione 6 - 3-Sat ≤p 3-Colorabilità
23
𝑆𝑜𝑙𝑜 𝑠𝑒 ⟸ ) Supponiamo che G’ abbia un insieme dominante di cardinalità ≤ k. Proviamo che in G esiste
un VERTEX COVER di cardinalità ≤ k
1. Se in G’ ci sono tutti i vertici di G OK
2. Se in G’ c’è un vertice che ho aggiunto lo scambio con i vertici di partenza a cui è collegato, in modo
da ottenere 2 nodi del VERTEX COVER precedente
Partendo da D ⊆ V’, eliminiamo da D gli eventuali vertici x ∈ {uv : (u, v) ∈ E}, sostituendoli con uno qualsiasi
tra u, v ∈ V , ricordando che x è vicino, nel grafo G’, solamente ad u ed a v. In tal modo otteniamo un
insieme A ⊆ V , con |V| = |D| = k.
Proviamo che A è un vertex cover di G. Consideriamo a tale scopo un arbitrario arco (u, v) ∈ E. Supponiamo
per ipotesi assurda che nessuno tra u e v sia in A. Ciò comporta, per come abbiamo ottenuto A, che u, v, uv
∉ D, il che comporta che uv ∈ V’ non era dominato da nessun vertice in D, chiaramente un assurdo.
Concludiamo quindi che G ha un vertex cover di cardinalità ≤ k.
3-SAT ≤P INSIEME INDIPENDENTE ≤P VERTEX COVER ≤P INSIEME DOMINANTE
Algoritmi e Strutture Dati 2: Lezione 7 - Problemi CO-NP
24
Lezione 7 - Problemi CO-NP
Catalogazione Si può effettuare una catalogazione dei problemi NP-C.
1. Problema di impacchettamento (Packing):
a. Input: oggetti con dei vincoli di incompatibilità tra di loro
b. Output: massima collezione di oggetti non compatibili
Es. Indipendent Set
2. Problema di copertura
a. Input: 0ggetti con delle proprietà “locali” godute da ogni singolo oggetto.
b. Output: collezione minima di oggetti con una proprietà globale
Es. vertex cover
3. Problemi di partizione
a. Input: oggetti con delle proprietà
b. Output: una partizione/suddivisione di minima cardinalità di tutti gli oggetti con la
proprietà.
Es. colorazione di un grafo
4. Problemi di permutazione
a. Input: azioni che possono essere eseguite solo in un certo ordine
b. Output: un ordine che esegue tutte le azioni, una ed una sola volta.
Es. Ciclo hamiltoniano
5. Problemi numerici
a. Input: N numeri interi, ed un numero w
b. Domanda: esiste un sottoinsieme S degli indici t.c. La somma è uguale a w?
Es. problema dello zaino, pubblicità
6. Problemi di soddisfacibilità con vincoli
Es. 3-SAT
Problemi CO-NP Finora ci siamo occupati solo della classe dei problemi NP. Ora analizzeremo anche la parte complementare
dei problemi NP : i problemi CO-NP
Rivediamo la visione di problema NP:
X ∈ NP x ∈ X → ∃ y ∈ {0,1}* |y|≤ p(|x|) per cui un certificatore B(x,y) = SI.
CO-NP (Complemento di NP, ma non proprio in senso insiemistico)
Infatti CO-NP contiene tutte le istanze di input al problema X di tipo NO.
X ∈ CO-NP ↔ 𝑋 ∈ NP → , x ∈ {0,1}* : x non appartiene ad X }
X ∈ CO-NP: x ∈ X → ∃ y ∈ {0,1}* |y|≤ p(|x|) per cui un certificatore B(x,y) = NO.
Osservazione:
X ∈ P ↔ 𝑋 ∈ P → P⊆ CO-NP
X ∈ P ↔ ∃ un algoritmo A polinomiale per cui x ∈ X ↔ A(x)=SI
𝑋 ∈ P ↔ ∃ un algoritmo A’ polinomiale per cui se A(x)=SI allora A’(X)=NO e viceversa.
CO-NP = Istanza del problema di tipo NO efficacemente certificate
NP = Istanze del problema di tipo Si efficacemente certificate
CO-NP NP P
Algoritmi e Strutture Dati 2: Lezione 7 - Problemi CO-NP
25
La classe 𝐶𝑂 − 𝑁𝑃 ∩ 𝑁𝑃 contiene i problemi certificabili efficientemente per istanze sia di tipo SI che di
tipo NO. Es. problemi di programmazione lineare. Inoltre se un problema X appartiene a questa classe, ha la
proprietà che quando la risposta è SI, esiste una prova semplice e quando la risposta è NO altrettanto.
Quindi i problemi che appartengono a questa intersezione sono detti avere una “buona caratterizzazione”
in quanto hanno sempre un buon certificato per la soluzione.
Inoltre, ci si chiede se NP= CO −NP?
Dobbiamo provare che se 𝑁𝑃 ≠ 𝐶𝑂 − 𝑁𝑃 allora P ≠ 𝑁𝑃. Inizialmente dobbiamo provare che se P=NP
allora NP=CO-NP. P è chiuso rispetto il complemento, così se P=NP, allora NP deve essere chiuso rispetto al
complemento. Formalmente, partendo dall’assunzione che P = NP
𝑋 ∈ 𝑁𝑃 → 𝑋 ∈ 𝑃 → 𝑋 ∈ 𝑃 ⊆ 𝑁𝑃 → 𝑋 ∈ 𝑁𝑃 → 𝑋 ∈ 𝐶𝑂 − 𝑁𝑃 → 𝑁𝑃 ⊆ 𝐶𝑂 − 𝑁𝑃
e
𝑋 ∈ 𝐶𝑂 − 𝑁𝑃 → 𝑋 ∈ 𝑁𝑃 → 𝑋 ∈ 𝑃 → 𝑋 ∈ 𝑃 ⊆ 𝑁𝑃 → 𝑋 ∈ 𝑁𝑃 → 𝐶𝑂 − 𝑁𝑃 ⊆ 𝑁𝑃
Queste assunzioni ci vogliono dimostrare che NP⊆ CO −NP e CO-NP⊆NP quando NP= CO −NP.
Concetto di P-SPACE Possiamo usare come unità di misura non il tempo che l’algoritmo impiega, bensì lo spazio di memoria che
occupa durante la sua esecuzione.
PSPACE →Dato un problema di decisione X, ∃ un algoritmo A (di decisione) tale che , ∀ x ∈{0,1}*, x ∈ X ↔
A(x) = SI e, inoltre, A utilizza uno spazio polinomiale su |x|.
P⊆PSPACE? Ovviamente si, dato che in tempo polinomiale non posso che accedere ad un numero
polinomiale di locazioni di memoria.
NP⊆PSPACE? Si in quanto lo spazio si può riutilizzare, il tempo no.
ESEMPIO 1
Input: Vettore binario V [1....n]
For i=0 to 2𝑛 − 1 polinomiale ->riutilizzo memoria
Scrivo in V la rappresentazione Binaria di i
Lo spazio è O(n) perché si può riutilizzare. Tempo = Θ(2𝑛). In spazio polinomiale posso risolvere problemi di
tempo esponenziale.
𝐍𝐏 ⊆ 𝐏𝐒𝐏𝐀𝐂𝐄
3-SAT ∈ P-SPACE: li risolvo in spazio lineare. Genero uno spazio con tutti 0, verifico la formula e verifico se
la formula è soddisfacibile. Se va bene, termino, altrimenti cancello i valori e provo con 00…..01 e così via
fino a quando la formula non diventa soddisfacibile. Genero tutti i 2𝑛 valori di verità con spazio n.
Mediante il precedente algoritmo abbiamo dimostrato che la verifica della soddisfacibilità di una formula di
3 – SAT impiega uno spazio polinomiale → 3-SAT ha spazio O(n) e tempo 𝜃(2𝑛 ).
CONCLUSIONI
∀ X ∈ NP si ha che X ≤ p 3-SAT ∈ 𝑃𝑆𝑃𝐴𝐶𝐸. Esiste un algoritmo che usa un numero polinomiale di passi più
un numero polinomiale di chiamate per 3-SAT. Usando l’algoritmo sopra descritto per 3-SAT, possiamo
concludere che X usa solo spazio polinomiale. Tutto ciò che si riesce a verificare in tempo polinomiale, lo si
risolve utilizzando spazio polinomiale. NOTA: non è stato provato che 𝑃 ≠ 𝑃𝑆𝑃𝐴𝐶𝐸. Comunque PSPACE
contiene problemi che non sono ne in NP che in co-NP.
PSPACE
NP CO-
NP P
Algoritmi e Strutture Dati 2: Lezione 8 - Proprietà generali degli algoritmi
26
Lezione 8 - Proprietà generali degli algoritmi
In generale un algoritmo di risoluzione di un problema dovrebbe rispettare 3 proprietà fondamentali:
Deve funzionare su tutti gli input
Deve essere polinomiale
Deve restituire in output la migliore soluzione possibile Per i problemi NP-C, fino ad oggi, non si è riuscito a trovare un algoritmo che soddisfi tutti e tre i requisiti. Tuttavia, la classe dei problemi NP completi contiene molti problemi di grande importanza pratica. Per essi è molto importante dover produrre una “qualche soluzione”, indipendentemente dal fatto che la soluzione “migliore” sia difficile da trovare o meno. Tipicamente, ci sono tre differenti approcci che si possono seguire quando ci si trova di fronte alla necessità di trovare soluzioni accettabili in pratica per problemi NP completi, che si ottengono combinando i requisiti sopra indicati.
1. Il primo approccio consiste nel progettare algoritmi che producano una soluzione in tempo
polinomiale, per ogni possibile istanza di input, non necessariamente di valore ottimo, ma che si discosti dal valore ottimo per “poco”, e che tale “poco” sia stimabile in funzione della taglia dell'input.
2. Se l'input al problema dettato dalla specifica situazione pratica in cui il problema sorge è piccolo, allora si può provare a trovare la “migliore” soluzione mediante una ricerca esaustiva, che essenzialmente genera tutte le possibili soluzioni associate all'istanza di input e poi se ne sceglie la migliore. Tale approccio genera algoritmi con complessità esponenziale. Tuttavia, se l'input è piccolo, in pratica può produrre soluzioni in un tempo ragionevole.
3. Il fatto che un problema sia NP completo essenzialmente implica che è molto improbabile che esista un algoritmo di complessità polinomiale che produce la soluzione desiderata in corrispondenza ad ogni possibile istanza di input. Può capitare, però, che per “specifiche” particolari istanze di input, un tale algoritmo possa essere trovato. Pertanto, un’analisi accurata delle possibili istanze di input che possono “ragionevolmente” accadere in pratica, può portare alla elaborazione di algoritmi efficienti.
In questo corso seguiremo il primo approccio.
Problema della trasmissione in una rete (contention resolution randomizzato,
risoluzione dei conflitti) Consideriamo una rete Ethernet:
Durante la trasmissione, siccome tutti i pc condividono lo stesso mezzo di trasmissione, c’è la possibilità che avvengano collisioni tra due messaggi inviati nello stesso momento da due pc diversi, provocando così un errore nella trasmissione stessa. Una volta che avviene una collisione, se le stazioni ritrasmettono subito il messaggio, molto probabilmente la collisione si verificherà una seconda volta. Bisogna trovare un modo per evitare che ciò accada. In particolare, si usa un semplice algoritmo: ogni stazione piuttosto che ritrasmettere subito, trasmette il messaggio con probabilità p. Si dimostra che, utilizzando questo algoritmo, la probabilità che la trasmissione vada a buon fine è molto vicina a 1. n = numero stazioni p = probabilità con cui ogni stazione ritrasmette
Algoritmi e Strutture Dati 2: Lezione 8 - Proprietà generali degli algoritmi
27
Pr 𝑙𝑎 𝑠𝑡𝑎𝑧𝑖𝑜𝑛𝑒 𝑗 𝑡𝑟𝑎𝑠𝑚𝑒𝑡𝑡𝑒 𝑛𝑒𝑙 𝑡𝑒𝑚𝑝𝑜 𝑖 = 𝑝 𝑐𝑜𝑛 0 < 𝑝 < 1 La probabilità che una data stazione trasmetta con successo all’istante j è uguale a: p (1-p)n-1 Voglio che la probabilità sia la più grande possibile. Sia f(p)= p (1-p)n-1, calcoliamo la sua derivata prima ottenendo: p ∙ (1-p)n-1 assume valore massimo per
f’ p = 1 − 𝑝 𝑛−1 − 𝑝 𝑛 − 1 ∙ 1 − 𝑝 𝑛−2 = 1 − 𝑝 𝑛−2 1 − 𝑝 − 𝑝 𝑛 − 1
= 1 − 𝑝 𝑛−2 1 − 𝑝 − 𝑛𝑝 + 𝑝 = 1 − 𝑝 𝑛−2 1 − 𝑛𝑝 = 0 ⟺ 𝑝 =1
n
Abbiamo scoperto che la probabilità che una stazione possa trasmettere con successo è 1
n
Questa quantità è usata spesso in matematica e gode delle seguenti proprietà:
lim𝑛→∞
1 +1
𝑛 𝑛
= 𝑒 ≈ 2,73
1
4 ≤ 1 −
1
𝑛 𝑛
≤ 1
𝑒
1
𝑒 ≤ 1 −
1
𝑛 𝑛−1
≤ 1
2 , ∀𝑛 ≥ 2
Sfruttando ciò possiamo affermare che:
1
𝑒𝑛 ≤ 𝑃𝑟 𝑃𝑖 𝑡𝑟𝑎𝑠𝑚𝑒𝑡𝑡𝑎 𝑐𝑜𝑛 𝑠𝑢𝑐𝑐𝑒𝑠𝑠𝑜 𝑎𝑙𝑙′ 𝑖𝑠𝑡𝑎𝑛𝑡𝑒 𝑗 = 𝑝 1 − 𝑝 𝑛−1 =
1
n ∙ 1 −
1
n
𝑛−1
≤ 1
2𝑛
Sia Pr 𝑠𝑖 𝑔𝑒𝑛𝑒𝑟𝑎 𝑢𝑛 𝑐𝑜𝑛𝑓𝑙𝑖𝑡𝑡𝑜 𝑎𝑙 𝑡𝑒𝑚𝑝𝑜 𝑖 = 1 −1
𝑒𝑛
Fissiamo un intervallo 1,..,t nel quale ogni stazione può trasmettere.
𝑃𝑟 𝑑𝑎𝑡𝑎 𝑠𝑡𝑎𝑧𝑖𝑜𝑛𝑒 𝑓𝑎𝑙𝑙𝑖𝑠𝑐𝑎 𝑠𝑒𝑚𝑝𝑟𝑒 𝑙𝑎 𝑠𝑢𝑎 𝑡𝑟𝑎𝑠𝑚𝑖𝑠𝑠𝑖𝑜𝑛𝑒 𝑛𝑒𝑙𝑙′ 𝑖𝑛𝑡𝑒𝑟𝑣𝑎𝑙𝑙𝑜1, . . , 𝑡 ≤ 1 −1
en
𝑡
Se fissiamo t = ⌈𝑒𝑛⌉
𝑃𝑟 ≤ 1 −1
en
⌈𝑒𝑛 ⌉≤ 1 −
1
en
𝑒𝑛≤
1
e
𝑄𝑢𝑖𝑛𝑑𝑖 𝑙𝑎 𝑃𝑟 𝑠𝑡𝑎𝑧𝑖𝑜𝑛𝑒 𝑡𝑟𝑎𝑠𝑚𝑒𝑡𝑡𝑒 𝑠𝑒𝑚𝑝𝑟𝑒 𝑐𝑜𝑛 𝑠𝑢𝑐𝑐𝑒𝑠𝑠𝑜 𝑎𝑙𝑚𝑒𝑛𝑜 𝑖𝑛 𝑢𝑛 𝑖𝑠𝑡𝑎𝑛𝑡𝑒 𝑛𝑒𝑙𝑙′ 𝑖𝑛𝑡𝑒𝑟𝑣𝑎𝑙𝑙𝑜 1, . . , 𝑡
≥ 1 −1
e
Ciò che abbiamo ottenuto è già un buon risultato. Ma si può ancora migliorare aumentando di un piccolo fattore (c = costante) la grandezza dell’intervallo 1,..t Se fissiamo 𝑡 = ⌈𝑒𝑛⌉ ⋅ 𝑐 ⋅ ln(𝑛) 𝑃𝑟 𝑑𝑎𝑡𝑎 𝑠𝑡𝑎𝑧𝑖𝑜𝑛𝑒 𝑓𝑎𝑙𝑙𝑖𝑠𝑐𝑎 𝑠𝑒𝑚𝑝𝑟𝑒 𝑙𝑎 𝑠𝑢𝑎 𝑡𝑟𝑎𝑠𝑚𝑖𝑠𝑠𝑖𝑜𝑛𝑒 𝑛𝑒𝑙𝑙′ 𝑖𝑛𝑡𝑒𝑟𝑣𝑎𝑙𝑙𝑜1, . . , 𝑡 ≤
≤ 1 −1
en
𝑡
= 1 −1
en
⌈𝑒𝑛 ⌉
𝑐⋅ ln(𝑛)
< 1 −1
en
𝑒𝑛
𝑐⋅ ln (𝑛)
≤ 1
e
𝑐⋅ ln(𝑛)
= 1
𝑒𝑐⋅ ln (𝑛 ) = 1
n
𝑐
Se consideriamo la probabilità 𝑃𝑟 che tutte le stazioni falliscano la trasmissione, cioè se facciamo l’unione delle singole probabilità di fallimento di ogni stazione, abbiamo che: 𝑃𝑟 ≤ 𝑃𝑟 𝑠𝑡𝑎𝑧𝑖𝑜𝑛𝑒 1 𝑓𝑎𝑙𝑙𝑖𝑠𝑐𝑒 + 𝑃𝑟 𝑠𝑡𝑎𝑧𝑖𝑜𝑛𝑒 2 𝑓𝑎𝑙𝑙𝑖𝑠𝑐𝑒 + ⋯ + 𝑃𝑟 𝑠𝑡𝑎𝑧𝑖𝑜𝑛𝑒 𝑛 𝑓𝑎𝑙𝑙𝑖𝑠𝑐𝑒 ≤
≤ 𝑛 ⋅ 1
n
𝑐=
1
n
𝑐−1
Calcolando il complemento di 𝑃𝑟 , avremo la probabilità che tutte le stazioni trasmettano con successo, quindi: 𝑃𝑟 𝑠𝑡𝑎𝑧. 1 𝑛𝑜𝑛 𝑓𝑎𝑙𝑙𝑖𝑠𝑐𝑒 𝑚𝑎𝑖 ∧ 𝑃𝑟 𝑠𝑡𝑎𝑧. 2 𝑛𝑜𝑛 𝑓𝑎𝑙𝑙𝑖𝑠𝑐𝑒 𝑚𝑎𝑖 ∧ …∧ 𝑃𝑟 𝑠𝑡𝑎𝑧. 𝑛 𝑛𝑜𝑛 𝑓𝑎𝑙𝑙𝑖𝑠𝑐𝑒 𝑚𝑎𝑖 ≥
≥ 1 − 1
n
𝑐−1 .
Dal risultato ottenuto, ci accorgiamo che espandendo di poco l’intervallo di tempo, la probabilità che le trasmissioni avvengano senza collisioni è molto vicina a 1. È da sottolineare che abbiamo incrementato di molto poco l’intervallo. Per risolvere questo problema, quindi, è bastato usare una semplice funzione che calcoli in modo casuale la probabilità che un nodo debba trasmettere o meno.
Probabilità che tutti gli
altri stiano zitti
log 𝑥𝑎 = 𝑎 log 𝑥
Algoritmi e Strutture Dati 2: Lezione 9 - Teoria della probabilità
28
Lezione 9 - Teoria della probabilità
Cenni sulla teoria della probabilità In teoria della probabilità, una variabile casuale X può essere pensata come il risultato numerico di un esperimento quando questo non è prevedibile con certezza (ossia non è deterministico). Ad esempio, il risultato del lancio di un dado a sei facce può essere matematicamente modellato come una variabile casuale che può assumere uno dei sei possibili valori 1,2,3,4,5,6. Il valore atteso di una variabile casuale X, è un numero E*X+ che formalizza l’idea euristica di valore medio di un fenomeno aleatorio. Ad esempio, schematizziamo matematicamente il gioco dei dati rappresentandolo con una variabile casuale che possa assume i valori 1,2,3,4,5,6, ciascuno con probabilità 1/6. Intuitivamente, il valore medio di questa variabile casuale sarà:
𝔼 𝑥 = 1 ∙1
6+ 2 ∙
1
6+ 3 ∙
1
6+ 4 ∙
1
6+ 5 ∙
1
6+ 6 ∙
1
6= 3,5
La formula per il calcolo del valore medio :
𝔼 𝑥 = 𝑥𝑖𝑝(𝑥𝑖)
∞
𝑖=1
Esempio: Lancio di una moneta
Lancio la moneta e mi fermo alla prima occorrenza di TESTA Prob { TESTA } = p Prob { CROCE } = 1-p Sia X una variabile casuale che assume valori con i= 1,2,…,n X = i nell’esperimento lancio la moneta i volte La probabilità che ottengo l’esito TESTA al i-esimo lancio è data da :
𝔼 𝑥 = 𝑥𝑖𝑝(𝑥𝑖)∞𝑖=1 = 𝑖(1 − 𝑝)𝑖−1𝑝 = 𝑝 𝑖(1 − 𝑝)𝑖−1 =
1
𝑝∞𝑖=1
∞𝑖=1 *
1
𝑝 Numero di volte che devo ripetere un esperimento per avere il successo
Proprietà di due variabili casuali Questa proprietà ha la conseguenza importante che date due variabili casuali X e Y (non necessariamente indipendenti) si ha
𝔼 𝑋 + 𝑌 = 𝔼 𝑋 + 𝔼 𝑌 Scomporre variabili casuali complesse per poterle risolvere più facilmente Questa proprietà non vale per il prodotto: in generale, E[X Y] è diverso da E[X] E[Y]. Quando queste due quantità sono uguali, si dice che X e Y sono “ non correlate”. In particolare, due variabili casuali indipendenti non sono correlate.
Un esempio : Indovinare le carte
Consideriamo i = 1,2,3….n come il numero di carte ( tutte diverse) e ci poniamo il problema di voler stimare il numero medio di carte correttamente indovinate: Prob { indovinare la carta i-esima } = 1 / n 𝔼 𝑥 = 𝑥𝑖𝑝(𝑥𝑖)
∞𝑖=1
Definisco Media di una variabile casuale X, e la indico con E[X]=
0
}Pr{}Pr{jx
ii jxjxx
𝑋𝑖 = 1 𝑠𝑒 𝑜 𝑖𝑛𝑑𝑖𝑣𝑖𝑛𝑎𝑡𝑜 𝑙𝑎 𝑐𝑎𝑟𝑡𝑎 𝑖 − 𝑒𝑠𝑖𝑚𝑎
0 𝑠𝑒 𝑛𝑜𝑛 𝑜 𝑖𝑛𝑑𝑜𝑣𝑖𝑛𝑎𝑡𝑜 𝑙𝑎 𝑐𝑎𝑟𝑡𝑎 𝑖 − 𝑒𝑠𝑖𝑚𝑎
𝑋 = 𝑋0 + 𝑋1 + ⋯ + 𝑋𝑛
𝔼 𝑋 = 1 Pr 𝑋𝑖 = 1 + 0 Pr 𝑋𝑖 = 0 = 𝑃𝑅 𝑋𝑖 = 1 =1
𝑛
Consideriamo ora l’esempio appena visto ricordando le carte già uscite, provo ad indovinare solo tra quelle non ancora scoperte.
Pr 𝑋𝑖 = 1 =1
𝑛−(𝑖−1)⇒ 𝔼 𝑋𝑖 =
1
𝑛−(𝑖−1) (i-1)=Numeri delle carte già estratte nei tentativi precedenti
Algoritmi e Strutture Dati 2: Lezione 9 - Teoria della probabilità
29
𝔼 𝑋 = 𝔼 𝑋𝑖 =
𝑛
𝑖=1
1
𝑛 − 𝑖 + 1= 1 +
1
2+
1
3+. . +
1
𝑛≈ ln(𝑛 + 1)
𝑛
𝑖=1
𝔼 𝑋 =1
𝑛+
1
𝑛 − 1+ ⋯ + 1 = Θ(log 𝑛)
MAX 3-SAT probabilistico
INPUT AL PROBLEMA: 𝑋 = 𝑥1 , … , 𝑥𝑛 𝑑𝑜𝑣𝑒 𝑥𝑖 ∈ 0,1 . 𝑡𝑖𝑗 ∈ 𝑥1 , … , 𝑥𝑛 , 𝑥1 , … , 𝑥𝑛
𝐶 = (𝑡𝑖1 𝑡𝑖2 𝑡𝑖3 ) 𝐹 = (𝐶1 ∧ 𝐶2 …∧ 𝐶𝑘).
OUTPUT AL PROBLEMA: Vogliamo un’assegnazione di valori di verità alle Xi, che massimizzi il maggior numero di clausole soddisfatte. L’idea è di assegnare a caso a ciascuna variabile Xi valore 1 con probabilità ½ (TESTA), valore 0 con probabilità ½ (CROCE). L’obiettivo è quello di valutare il numero medio di clausole soddisfatte, quindi analizziamo per prima cosa cosa succede a 3-SAT con l’utilizzo della probabilità. 𝑋 = 𝑗 ⇔ 𝑗 𝑐𝑙𝑎𝑢𝑠𝑜𝑙𝑒 𝑠𝑜𝑛𝑜 𝑠𝑜𝑑𝑑𝑖𝑠𝑓𝑎𝑡𝑡𝑒
𝑋𝑖 = 1 𝑠𝑒 𝑙𝑎 𝑐𝑙𝑎𝑢𝑠𝑜𝑙𝑎 è 𝑠𝑜𝑑𝑑𝑖𝑠𝑓𝑎𝑡𝑡𝑎
0 𝑠𝑒 𝑙𝑎 𝑐𝑙𝑎𝑢𝑠𝑜𝑙𝑎 𝑛𝑜𝑛 è 𝑠𝑜𝑑𝑑𝑖𝑠𝑓𝑎𝑡𝑡𝑎
definiamo
𝑋 = 𝑋1 + ⋯ + 𝑋𝑘 ⇒ 𝔼 𝑋 = 𝔼 𝑋𝑗
𝑘
𝑗 =0
𝔼 𝑋𝑗 = Pr 𝑙𝑎 𝑐𝑙𝑎𝑢𝑠𝑜𝑙𝑎 𝐶𝑖 è 𝑠𝑜𝑑𝑑𝑖𝑠𝑓𝑎𝑡𝑡𝑎 = 0 Pr 𝑋𝑗 = 0 + 1 Pr 𝑋𝑗 = 1 = Pr 𝑋𝑗 = 1
= 1 − Pr 𝑋𝑗 = 0 = 1 − 12 ∗ 1
2 ∗ 12 = 7
8
Poiché la clausola è formata da 3 termini, abbiamo in totale 8 combinazioni possibili. La probabilità che
Pr 𝑋𝑗 = 0 è data dalla possibilità di avere la clausola Xj falsa. L’unico caso è quando tutti i termini sono
falsi. Conseguenze: per ogni formula di 3-SAT, attraverso un’assegnazione random, esiste un’assegnazione di valori di verità alle Xi che soddisfa almeno i 7/8 del totale di clausole. Supponiamo di non essere soddisfatti di questo algoritmo che produce un singolo assegnamento con il maggior numero di clausole. Si vuole un algoritmo randomizzato che garantisca una assegnazione a vero di almeno i 7/8 delle clausole totali. In questo caso utilizziamo la probabilità del lancio della moneta per l’assegnazione del valore di verità. Numero medio di volte che eseguo l’assegnazione con il lancio della monta per avere successo = 1/p *
𝔼 𝑋 = 𝑗 Pr{𝑋 = 𝑗}
𝑘
𝑗=1
= 𝑝𝑟𝑜𝑏𝑎𝑏𝑖𝑙𝑖𝑡à 𝑐𝑒 𝑢𝑛′𝑎𝑠𝑠𝑒𝑔𝑛𝑎𝑧𝑖𝑜𝑛𝑒 𝑑𝑖 𝑝𝑟𝑜𝑏. 𝑠𝑜𝑑𝑑𝑖𝑠𝑓𝑖 𝑒𝑠𝑎𝑡𝑡𝑎𝑚𝑒𝑛𝑡𝑒 𝑗 𝑐𝑙𝑎𝑢𝑠𝑜𝑙𝑒
Pr {Successo } = Pr 𝑋 =7
8𝑘 + Pr 𝑋 =
7
8𝑘 + 1 + ⋯ + Pr 𝑋 = 𝑘 = Pr 𝑋 = 𝑗
𝑗≥7𝑘 8
7
8𝑘 = 𝔼 𝑋 = Pr 𝑋 = 𝑗 =𝑘
𝑗=0 Pr 𝑋 = 𝑗 𝑗 <7𝑘 8 + Pr 𝑋 = 𝑗 𝑗≥7𝑘 8
Assumendo che sia 𝑘’ = ⌊7𝑘/8⌋ risulta 7
8𝑘 ≤ 𝑘 ′𝑃𝑟 𝑋 = 𝑗
𝑗<7𝑘 8
+ 𝑘 𝑃𝑟 𝑋 = 𝑗
𝑗≥7𝑘 8
= 𝑘′ 𝑃𝑟 𝑋 = 𝑗
𝑗<7𝑘 8
+ 𝑘 𝑃𝑟 𝑋 = 𝑗
𝑗≥7𝑘 8
A questo punto possiamo sostituire le sommatorie evidenziate precedentemente nelle relative probabilità, in particolare sostituiamo la probabilità di insuccesso con “( 1-p) ” e la probabilità di successo con “p”. Otteniamo quindi :
7
8𝑘 ≤ 𝑘’ 1 − 𝑝 + 𝑘𝑝 ≤ 𝑘 ′ + 𝑘𝑝 𝑞𝑢𝑖𝑛𝑑𝑖 𝑘𝑝 ≥
7
8 𝑘 − 𝑘 ′ ⇒ 𝑘𝑝 ≥
7
8 𝑘 −
7
8 𝑘 ≥
1
8 ⇒ 𝑝 ≥
78 𝑘 − 𝑘′
𝑘≥
1
8𝑘
Abbiamo ottenuto la nostra soluzione e possiamo vedere che il numero atteso di tentativi necessari per trovare un assegnamento di verità è al massimo 8k.
insuccesso successo
Algoritmi e Strutture Dati 2: Lezione 10 - Algoritmi probabilistici
30
Lezione 10 - Algoritmi probabilistici
Ora analizzeremo algoritmi probabilistici per la risoluzione di problemi, cercando di stimare anche quante
volte sono “costretto” ad eseguirli per ottenere il risultato desiderato.
Variabili casuali
Sia X una variabile casuale che assume valori j=1,2…n con Pr={X=j}
Definisco Media di una variabile casuale X, e la indico con E[X]=
0
}Pr{}Pr{jx
ii jxjxx
Esempio
Considero una moneta Pr{testa}=p e Pr{croce}=1-p
Esperimento => Lancio la moneta e mi fermo alla prima occorrenza di testa.
X=j < = > Nell’esperimento lancio la moneta j volte.
0 0
11 1)1()1(}Pr{][
j j
jj
j ppjpppjjXjXE
0 1
1
k
k
10
0 00
1
1
1//
k k k
k
k
k
k
k
k
d
dddddk
somma di derivate
Disuguaglianza di Chernoff
μ....Xn]X2E[X1μE[X]
....XnX2X1X
tiindipenden binarie casuali variabilidelleX2...Xn X1, Siano
1)1(})1(Pr{ 0
eX ]Chernoff di anzaDisuguagli[
Problema dell’allocazione di risorse (bilanciamento del carico randomizzato)
Problema: Ci sono j1, j2, …. jm job che si presentano in modo sequenziale
Ci sono p1,p2….pn processori distinti che possono eseguire i job
Obiettivo: fornire un’assegnazione di job ai processori che sia la “più bilanciata” possibile.
Osservazione (5): In presenza di un controllore è possibile assegnare i job ai processori in modo che ogni
processore riceva al più
n
mjob.
Algoritmo => Assegna i job a caso equiprobabilmente ai processori (nel caso in cui m=n ogni processore
riceverebbe uno ed un solo job).
altrimenti
s
0
esimo-i processore al assegnato è esimo-J job il se1Y
jobk riceve p processore il ek X
ij
ii
𝑋𝑖 = 𝑌𝑖1 + 𝑌𝑖2 + ⋯ + 𝑌𝑖𝑚 𝑒𝑑 𝐸 𝑌𝑖𝑗 = 1𝑛 𝑐𝑜𝑠𝑖 𝐸 𝑋𝑖 = 𝐸 𝑌𝑖𝑗
𝑛
𝑗 =1
= 1𝑛 ∙ 𝑛 = 1
Vediamo la probabilità che un processore Xi venga sovraccaricato
Algoritmi e Strutture Dati 2: Lezione 10 - Algoritmi probabilistici
31
Pr{Xi>c}=> Processore sovraccaricato o assegnazioni non uniformi di jobs.
Per avere una limitazione superiore, utilizziamo la disuguaglianza di Chernoff. Ponendo 1 e c1
Pr 𝑋𝑖 > 𝑐 < 𝑒𝑐−1
𝑐𝑐 < 𝑒𝑐
𝑐𝑐
Questa quantità deve essere piccola. Al denominatore abbiamo 𝑐𝑐 e ci
chiediamo quanto deve valere questo c. Ci chiediamo: per quale valore della x vale che xx =n ? => Svolgendo
otteniamo che
𝑥𝑥 = 𝑛 𝑎𝑝𝑝𝑙𝑖𝑐𝑎𝑛𝑑𝑜 𝑖𝑙 𝑙𝑜𝑔𝑎𝑟𝑖𝑡𝑚𝑜 𝑎𝑏𝑏𝑖𝑎𝑚𝑜 𝑐𝑒 𝑥 ⋅ log 𝑥 = log 𝑛 ; 𝑎𝑝𝑝𝑙𝑖𝑐𝑎𝑛𝑑𝑜 𝑖𝑙 𝑙𝑜𝑔𝑎𝑟𝑖𝑡𝑚𝑜 𝑢𝑛′𝑎𝑙𝑡𝑟𝑎
𝑣𝑜𝑙𝑡𝑎 𝑜𝑡𝑡𝑒𝑛𝑖𝑎𝑚𝑜 𝑐𝑒 log 𝑥 + log log 𝑥 = log log 𝑛 . 𝐼𝑛𝑜𝑙𝑡𝑟𝑒 𝑠𝑎𝑝𝑝𝑖𝑎𝑚𝑜 𝑐𝑒
2 log x > 𝑙𝑜𝑔 𝑥 + log log 𝑥 = log log 𝑛 > 766 log 𝑥
Utilizziamo quanto appena scoperto per dividere attraverso l’equazione 𝑥 ⋅ log 𝑥 = log 𝑛 abbiamo
1
2𝑥 ≤
log 𝑛
log log 𝑛≤ 𝑥 = 𝛾(𝑛)
Cosi 𝛾 𝑛 = Θ log 𝑛
log log 𝑛
Poniamo )(nec
2
2)()(2)()(
1
)(
1
)(
1
)(
1
)(Pr
1
nnnnne
e
c
e
c
ecX
nnnenec
c
c
i
ncXcXcX n
11)Pr()....Pr()Pr(co]sovraccari sia processorenessun [chePr 21
NOTA: Assegnazione casuale, con alta probabilità, non da mai a nessun processore più di n
n
loglog
log jobs.
Esempio. Voglio stimare
Pr{𝑋1 𝑟𝑖𝑐𝑒𝑣𝑎 𝑝𝑖ù 𝑑𝑖 𝑒𝛾 𝑛 𝑗𝑜𝑏𝑠 ∨ 𝑋2 𝑟𝑖𝑐𝑒𝑣𝑎 𝑝𝑖ù 𝑑𝑖 𝑒𝛾 𝑛 𝑗𝑜𝑏𝑠 ∨ …∨ 𝑋𝑛 𝑟𝑖𝑐𝑒𝑣𝑎 𝑝𝑖ù 𝑑𝑖 𝑒𝛾 𝑛 𝑗𝑜𝑏𝑠 }
≤ Pr{𝑋𝑖 > 𝑒𝛾 𝑛 }
𝑛
𝑖=1
≤1
𝑛
Pr 𝑛𝑒𝑠𝑠𝑢𝑛 𝑝𝑟𝑜𝑐𝑒𝑠𝑠𝑜𝑟𝑒 𝑟𝑖𝑐𝑒𝑣𝑎 𝑝𝑖ù 𝑑𝑖 𝑒𝛾 𝑛 𝑗𝑜𝑏𝑠 ≥ 1 −1
𝑛
Scegliendo m >> n, supponiamo che il numero di job sia 𝑚 = 16𝑛 ln 𝑛
𝔼 𝑋𝑖 = 𝑝𝑒𝑟 𝑙′𝑜𝑠𝑠𝑒𝑟𝑣𝑎𝑧𝑖𝑜𝑛𝑒 5 =𝑚
𝑛=
16 𝑛 ln 𝑛
𝑛= 16 ln 𝑛 = 𝜇 ≈ ln 𝑛
Vogliamo calcolare la probabilità che l’i-esimo processore riceva un numero di job > 2 volte la media 𝜇
Pr 𝑋𝑖 > 2𝜇 = Pr 𝑋𝑖 > )1( =
1)1(
e 𝑐𝑜𝑛 = 1 <
𝑒
4
16 ln 𝑛
= 𝑒16
416
ln 𝑛
≤ 1
𝑒2
ln 𝑛
=1
𝑛2
Quindi, Pr 𝑛𝑒𝑠𝑠𝑢𝑛 𝑝𝑟𝑜𝑐𝑒𝑠𝑠𝑜𝑟𝑒 𝑟𝑖𝑐𝑒𝑣𝑎 𝑝𝑖ù 𝑑𝑖 2 𝜇 𝑗𝑜𝑏𝑠 ≥ 1 −1
𝑛
Problema Contention Resolution Input: {P1, P2, … ,Pn} processi, Memoria condivisa
nnncX
n
i
i
11)Pr(c)(XPr.....c)(XPrc)Pr(Xcato]sovraccari sia [XPr
X...XXX Sia
21
n21
n21
Algoritmi e Strutture Dati 2: Lezione 10 - Algoritmi probabilistici
32
Abbiamo n processi P1, P2, …, Pn ciascuno dei quali contende agli altri processi l’accesso ad una memoria
condivisa. Supponiamo di dividere il tempo in round, ed in ognuno dei round solo un processo può avere
accesso al database per l’intera durata dello stesso.
Se all’inizio di un round due processi contemporaneamente tentano l’accesso alla memoria si genera una
collisione e nessuno può accedere alla memoria per tutta la durata del round.
Supponiamo che i processi non comunichino tra di loro per accordarsi sull’accesso alla memoria, l’unico
modo per gestire questa situazione è utilizzare un algoritmo randomizzato.
Per un certo valore di 𝑝 > 0 ogni processo tenterà di accedere al database con probabilità 𝑝,
indipendentemente da ciò che decidono gli altri processi.
Se un processo tenta l’accesso abbiamo successo se due o più processi provano ad accedere
contemporaneamente il round è perso e viene definito waste.
Utilizzando, dunque, un semplice algoritmo probabilistico si riesce ad ovviare ai problemi generati da un
accesso ripetuto e senza comunicazione degli stessi nella memoria, il che avrebbe condotto allo stallo.
Analisi delle performance
Innanzitutto definiamo gli eventi possibili di base.
Consideriamo un generico processo Pi ed un round t, da cui sia
𝐴 𝑖, 𝑡 l’evento che denota il tentativo di accesso di Pi nel round t
la probabilità di tale evento per qualsiasi Pi e t sarà 𝑃𝑟 𝐴 𝑖, 𝑡 = 𝑝;
inoltre definiamo l’evento complementare per cui
𝑃𝑟 𝐴 𝑖, 𝑡 = 1 − 𝑝 ossia Pi non accede alla memoria nel round t.
Ciò che effettivamente vogliamo valutare è la probabilità di successo dell’evento.
Denotando con 𝑆[𝑖, 𝑡] tale circostanza
𝑆 𝑖, 𝑡 = 𝐴 𝑖, 𝑡 ∩ 𝐴[𝑗, 𝑡]𝑗≠𝑖 ossia il caso in cui Pi tenta di accedere alla memoria mentre ogni
altro processo ,P1,…Pi-1, Pi+1, …Pn- non accede alla memoria.
Ciascuno di questi eventi è indipendente, non essendoci comunicazione tra di essi da cui
𝑃𝑟 𝑆[𝑖, 𝑡] = Pr 𝐴 𝑖, 𝑡 ⋅ Pr 𝐴[𝑖, 𝑡] = 𝑝(1 − 𝑝)𝑛−1
𝑗≠𝑖
Per trovare ora il massimo valore di 𝑝 in modo da massimizzare la probabilità di successo calcoliamo la
derivata prima
𝑓 𝑝 = 𝑝(1 − 𝑝)𝑛−1 → 𝑓1 𝑝 = (1 − 𝑝)𝑛−1 − 𝑛 − 1 𝑝(1 − 𝑝)𝑛−2
Che assume valore 0 per 𝑝 =1
𝑛
Sostituiamo tale valore negli eventi appena esposti ed otteniamo
𝑃𝑟 𝑆 𝑖, 𝑡 = 1
𝑛 1 −
1
𝑛 𝑛−1
⇒ 1
𝑒𝑛≤ 𝑃𝑟 𝑆 𝑖, 𝑡 ≤
1
2𝑛
Definiamo ora un’altra serie di probabilità che ci aiutino a capire la bontà dell’algoritmo randomizzato.
Supponiamo di voler stimare quanto bisogna attendere prima che il processo Pi acceda al database almeno
una volta.
Consideriamo più round e denotiamo con
ℱ 𝑖, 𝑡 l’evento che Pi fallisca nei round da 1 a t, abbiamo l’intersezione di eventi complementari 𝑆 𝑖, 𝑡
𝑃𝑟 ℱ 𝑖, 𝑡 = 𝑃𝑟 𝑆 𝑖, 𝑡
𝑡
𝑖=1
= 𝑆 𝑖, 𝑡 = 1 −1
𝑛 1 −
1
𝑛 𝑛
𝑡
≤ 1 −1
𝑒𝑛 𝑡𝑡
𝑖=1
Dato che 1
𝑒𝑛≤
1
𝑛 1 −
1
𝑛 𝑛
Poniamo per semplicità 𝑡 = ⌈𝑒𝑛⌉ otterremo che
Algoritmi e Strutture Dati 2: Lezione 10 - Algoritmi probabilistici
33
𝑃𝑟 ℱ 𝑖, 𝑡 ≤ 1 −1
𝑒𝑛 ⌈𝑒𝑛 ⌉
≤ 1 −1
𝑒𝑛 𝑒𝑛
≤ 1
𝑒
La probabilità, dunque, che il processo Pi non sia eseguito nei round tra 1 e ⌈𝑒𝑛⌉ è limitata superiormente
della costante 1
𝑒 indipendente da n.
Quindi con probabilità 𝟏 −𝟏
𝒆 il processo Pi viene eseguito almeno una volta nei round tra 1 e ⌈𝒆𝒏⌉. Inoltre,
utilizzando 𝑡 = ⌈𝑒𝑛⌉ ⋅ 𝑐 ln 𝑛
𝑃𝑟 ℱ 𝑖, 𝑡 ≤ 1 −1
𝑒𝑛 ⌈𝑒𝑛 ⌉
𝑐 ln 𝑛
≤1
𝑛𝑐
Ciò che vorremmo ora stimare è quanti round sono necessari affinché ci sia un’alta probabilità che tutti i
processi abbiano accesso al database almeno una volta.
Sia
Ϝ𝑡 = ℱ[𝑖, 𝑡]
𝑛
𝑖=1
L’evento che denota il fallimento del protocollo, ossia almeno un processo non è eseguito nei rounda 1 a t
𝑃𝑟 Ϝ𝑡 ≤ 𝑃𝑟 ℱ 𝑖, 𝑡
𝑛
𝑖=1
Avendo in precedenza ottenuto che 𝑃𝑟 ℱ 𝑖, 𝑡 ≤1
𝑛𝑐 si ricava che
𝑃𝑟 Ϝ𝑡 ≤ 1
𝑛𝑐
𝑛
𝑖=1
E per 𝑡 = ⌈𝑒𝑛⌉ ⋅ 2 ln 𝑛, si ha che
𝑃𝑟 Ϝ𝑡 ≤ 1
𝑛2=
1
𝑛
𝑛
𝑖=1
Da cui con probabilità 𝟏 −𝟏
𝒏 tutti i processi accedono alla memoria almeno una volta nei round da 1 a
𝟐⌈𝒆𝒏⌉ 𝐥𝐧𝒏. Abbiamo dunque dimostrato che per un valore estremamente piccolo di 2⌈𝑒𝑛⌉ ln 𝑛, otteniamo
un limite superiore al problema in casi di fallimento.
Algoritmi e Strutture Dati 2: Lezione 11 - Problemi di ottimizzazione
34
Lezione 11 - Problemi di ottimizzazione Dalla Teoria della NP-Completezza abbiamo appreso che esiste una classe di problemi (NP-hard) per cui non
è noto alcun algoritmo di soluzione di complessita polinomiale ed è inoltre molto improbabile che per tali
problemi possa essere mai trovato un algoritmo di soluzione di complessita polinomiale. Tuttavia, la classe
dei problemi NP completi contiene molti problemi di grande importanza pratica. Per essi è molto
importante dover produrre una “qualche soluzione", indipendentemente dal fatto che la soluzione
“migliore" sia difficile da trovare o meno. Tipicamente, ci sono tre differenti approcci che si possono seguire
quando ci si trova di fronte alla necessita di trovare soluzioni accettabili in pratica per problemi NP
completi. L’approccio che ci interesssa consiste nel progettare algoritmi che producano una soluzione in
tempo polinomiale, per ogni possibile istanza di input, non necessariamente di valore ottimo, ma che si
discosti dal valore ottimo per “poco", e che tale “poco" sia stimabile in funzione della taglia dell'input.
Problemi di ottimizzazione Innanzitutto diciamo che ci occuperemo di problemi di ottimizzazione. Informalmente un problema di
ottimizzazione Π è definito da:
Iπ= insieme delle istanze di input
∀ i ∈Iπ S(i)=insieme delle possibili soluzioni al problema per l’istanza i, ∀ s ∈ S(i) è associato un
costo c(s)≥0 (c funzione costo)
In linea di principio, l'obiettivo sarebbe di trovare in maniera efficiente, per ogni istanza di input i ∈ Iπ, una
soluzione di minimo costo (o massimo costo, a seconda che il problema sia di minimo o di massimo,
rispettivamente), associata alla istanza i. Sia OPT(i) il costo di una tale soluzione. Per i problemi di
ottimizzazione che studieremo in questo corso, calcolare OPT(i) è difficile, ovvero il corrispondente
problema di decisione è NP completo.
Informalmente, un algoritmo di approssimazione A per un problema di ottimizzazione Π produce, in tempo
polinomiale ed in corrispondenza ad ogni istanza di input di Π, una soluzione di valore (costo) “prossimo”
all'ottimo, dove per prossimo intendiamo che differisce dal valore ottimo per un certo fattore,
sperabilmente piccolo.
Consideriamo l’algoritmo A, di approssimazione per un problema di ottimizzazione Π
A è polinomiale in |i|, con i istanza del problema Π
∀ i, il costo della soluzione (SOL) prodotta da S in corrispondenza all’istanza i soddisfa
- SOL ≤ ρ(|i|)OPT(i) per problemi di minimo
- SOL ≥ OPT(i)/ ρ(|i|) per problemi di massimo
ρ(|i|) è detto fattore di approssimazione alla soluzione ottima. ρ(|i|)≥1 per problemi di minimo, infatti se
ρ(|i|)=1 SOL=OPT(i), mentre ρ(|i|)≤1 per problemi di massimo.
Dalla definizione di algoritmi di approssimazione discende che per provare che un algoritmo A abbia un
fattore di approssimazione ρ occorre provare che il costo della soluzione trovata da A si discosti dal valore
ottimo OPT della soluzione al più per un fattore ρ. Si pone il problema di come dimostrare questo fatto,
visto che per i problemi che studieremo non conosciamo ovviamente a priori OPT(n) né riusciamo a
calcolarlo. Il “trucco" consiste nello stimare OPT con quantità di più facile calcolo. In pratica cerchiamo di
stimare OPT(i), che non può essere noto.
OPT(i) ≥ STIMA INF → SOL ≤ ρ*STIMA INF ≤ ρ*OPT
Vertex Cover: stima di OPT
Input: Grafo G=(V,E)
Output: S⊆V di cardinalità minima tale che ∀(u,v) ∈ E, {u,v}∩S≠∅
Algoritmi e Strutture Dati 2: Lezione 11 - Problemi di ottimizzazione
35
L'insieme delle possibili istanze di input a Vertex Cover consiste di tutti i possibili grafi G = (V,E). Per ogni
grafo G, l'insieme delle possibili soluzioni ad esso associato consiste di tutti i sottoinsiemi S ⊆ V tali che per
ogni arco e ∈ E, almeno uno dei due vertici incidenti su e appartiene a S. Ogni tale S viene chiamato vertex
cover di G. Il costo di una soluzione S ⊆ V associata al grafo G corrisponde alla sua cardinalità |S|. Il
problema di ottimizzazione consiste nel trovare per ogni grafo G un vertex cover di minima cardinalità.
Supponiamo di voler stimare la soluzione ottima.
OPT = cardinalità del più piccolo vertex cover in questo caso OPT≥3
L'intuizione alla base di un algoritmo di approssimazione per il problema del Vertex Cover è la seguente. Se
nel grafo G abbiamo un certo numero k di archi disgiunti, ovvero di archi in cui nessuno di essi è adiacente
all'altro, allora occorreranno almeno k vertici per coprirli tutti. Ora, un insieme M ⊆ E di archi disgiunti
viene chiamato matching. L'osservazione appena fatta ci permette di trarre la seguente conclusione: ogni
Vertex Cover per G deve essere grande almeno quanto ogni matching di G. Ciò vale ovviamente anche per il
Vertex Cover ottimo (ovvero quello di cardinalità minima). Sia OPT la cardinalità del Vertex Cover di taglia
minima.
Consideriamo ora il concetto di Matching
M⊆E è detto Matching ↔ tutti gli archi di M sono disgiunti
Osservazione: ∀ Matching M nel grafo, ∀ Vertex Cover S nel grafo, |M|≤|S|→OPT≥|M|
M⊆E è detto Matching massimale ↔ ∀ e ∈ E, 𝑀 ∪ {𝑒} non è un matching. L'osservazione chiave è che
l'insieme A dei vertici che incidono sugli archi di un matching massimale formano un Vertex Cover per G.
Infatti, se ciò non fosse, ovvero se esistesse un arco e ∈ E non coperto dai vertici di A, ciò vorrebbe dire che
l'arco e non è adiacente ad alcun arco in M, ovvero 𝑀 ∪ {𝑒} è ancora composto da archi non adiacenti,
quindi 𝑀 ∪ 𝑒 è ancora un matching, contraddicendo il fatto che M è un matching massimale. Quindi, il
seguente algoritmo produce un Vertex Cover.
Valutiamo ora il fattore di approssimazione dell'algoritmo. Sia SOL il valore della soluzione restituito
dall'algoritmo, ovvero il numero di vertici nell'insieme output dell'algoritmo. Abbiamo che
𝑆𝑂𝐿 = 2|𝑀| ≤ 2 𝑂𝑃𝑇
e quindi l'algoritmo ha un fattore di approssimazione costante pari a 2. Resta da vedere come costruire in
tempo polinomiale un matching massimale in G. Ciò è semplicemente fatto mediante il seguente algoritmo.
Algoritmo per la costruzione di un matching massimale
M ← e, (e arco qualunque di E) Cancella nel grafo G tutti gli archi adiacenti a e Itera nel grafo rimanente fino a quando non diventa vuoto Output M
È istruttivo chiedersi se è possibile migliorare il fattore di approssimazione 2, mediante un'analisi più
accurata dell'algoritmo. La risposta è no. Si consideri il seguente esempio di grafo in cui l'algoritmo da noi
proposto produrrebbe una soluzione dal valore esattamente pari a 2OPT.
Costruisci un matching massimale M in G
Output tutti i vertici che toccano gli archi di M
Algoritmi e Strutture Dati 2: Lezione 11 - Problemi di ottimizzazione
36
Il grafo è un grafo bipartito con 2n nodi, in cui ogni nodo del lato sinistro è connesso ad ogni nodo del lato
destro e viceversa. Un Vertex Cover di cardinalità minima è dato da uno dei due lati dei vertici, quindi
𝑂𝑃𝑇 = 𝑛. D'altra parte, l'algoritmo considererebbe un matching massimale di cardinalità n (rappresentato
ad esempio dagli archi di maggior spessore nella figura di sotto) e di conseguenza la soluzione prodotta
dall'algoritmo avrebbe cardinalità SOL = 2n.
Inoltre, esiste una classe di grafi in cui ogni matching massimale ha cardinalità esattamente pari alla metà di
un Vertex Cover ottimale. Tale classe di grafi è composta da tutti i grafi completi (un grafo è completo se
esiste un arco tra ogni coppia di vertici) su n nodi, con n dispari. Da qui si evince che se si insiste ad usare la
tecnica del matching, non si potrà mai migliorare il fattore di approssimazione 2 appena provato. A
tutt'oggi, algoritmi di approssimazione per Vertex Cover con fattore di approssimazione costante inferiore a
2 non sono noti.
Maximum Cut
Il problema è NP completo. Un algoritmo di approssimazione per tale problema può essere ottenuto
mediante la tecnica delle ricerca locale, che consiste, data una possibile soluzione, nel tentare di migliorarla
mediante “piccole" modifiche di tipo locale. Nel nostro caso, si parte con una arbitraria partizione di V nei
due insiemi S1 e S2. Fin quando esiste un vertice che portato da S1 a S2 (o da S2 a S1) aumenta il corrente
valore c(S1; S2), lo si faccia. Si termina quando non esiste alcun vertice con questa proprietà.
Algoritmo per Maximum Cut
𝑆𝑖𝑎 (𝑆1 , 𝑆2) una partizione arbitraria di V While esiste un vertice 𝑥 ∈ 𝑉 𝑡𝑎𝑙𝑒 𝑐𝑒
𝑐 𝑆1 ∪ 𝑥 , 𝑆2 − 𝑥 > 𝑐(𝑆1 , 𝑆2) oppure 𝑐 𝑆1 − 𝑥 , 𝑆2 ∪ 𝑥 > 𝑐(𝑆1, 𝑆2) Do 𝑆1 = 𝑆1 ∪ 𝑥 , 𝑆2 = 𝑆2 − 𝑥 oppure 𝑆1 = 𝑆1 − 𝑥 , 𝑆2 = 𝑆2 ∪ 𝑥
Output: la partizione (𝑆1, 𝑆2)
Esempio: Miglioramento locale
Consideriamo una caratteristica di una rete, ovvero il numero di connessioni tra “parti” della rete stessa
Grafo G=(V,E), S1,S2 partizione di V ↔ S1,S2 ⊆V, S1US2=V, S1∩S2=∅
c(S1,S2)= # di archi che connettono vertici di S1 con vertici di S2.
Problema: trovare un partizionamento S1,S2 che massimizza c(S1,S2)
Miglioramento locale: ad ogni passo selezioniamo un nodo v in S1. Se v ha più vicini in S1 di quanti ne ha in
S2, allora v viene spostato in S2 e viceversa. In questo modo per ogni vertice si decide se mantenerlo nella
sua partizione o spostarlo nell’altra in modo da aumetarne gli archi nel confine. In questo modo, perdiamo
un arco ma ne guadagnamo di più nel confine. Il numero di iterazioni dell'algoritmo è chiaramente al più
pari a |E|, visto che ogni iterazione dell’algoritmo aumenta il valore di c( . , . ), e questo non può superare
Input: grafo non diretto 𝐺 = (𝑉, 𝐸)
Output: partizione dei vertici V in due sottoinsiemi 𝑆1, 𝑆2 con 𝑆1 ∪ 𝑆2 = 𝑉, 𝑆1 ∩ 𝑆2 = ∅ ,
in modo tale che il numero di archi 𝑐(𝑆1, 𝑆2) tra 𝑆1 e 𝑆2 sia massimizzato.
Algoritmi e Strutture Dati 2: Lezione 11 - Problemi di ottimizzazione
37
|E|. Inoltre, al termine dell'algoritmo, ogni vertice x ∈ V avrà almeno deg(x)/2 vertici nell’altra partizione,
dove deg(x) è il grado di x nel grafo G. Infatti, se ciò se non fosse, allora sarebbe possibile portare x
nell’altra partizione ed aumentare il valore P di c(S1; S2), contro l'ipotesi. Quindi, usando il fatto che
deg(𝑥)𝑥∈𝑉 = 2|E|, otteniamo che:
2c(S1,S2) = (numero di archi che vanno da x all′altro lato della partizione)𝑥∈𝑉 ≥ (deg 𝑥 )𝑥∈𝑉 /2 =
½*2|E| = |E|
Pertanto, il valore della soluzione S restituita dall'algoritmo soddisfa:
SOL = c(S1,S2) ≥|E|/2 ≥ OPT/2 OPT ≤ |E|
Problema: trovare una partizione di A e B di V che si avvicina a c(A,B); bisogna trovare il numero massimo di
archi che attraversano la frontiera.
Da questa soluzione, si ricerca per ogni vertice, se mantenerlo nella sua partizione posizione o spostarlo per
aumentare gli archi nel confine.
Algoritmi e Strutture Dati 2: Lezione 12 - Set Cover e copertura massima
38
Lezione 12 - Set Cover e copertura massima
Tra le tecniche per il progetto di algoritmi di approssimazione un ruolo importante è giocato dalla tecnica
greedy. Tale tecnica produce una soluzione al problema in esame in maniera iterativa, effettuando ad ogni
passo la scelta che in quel momento sembra la migliore. Detto in altri termini, se ci trovassimo di fronte ad
un problema di ottimizzazione in cui occorre massimizzare una data funzione f su di un dominio D, la
tecnica greedy costruirebbe in maniera iterativa una soluzione S = {s1,…, sn- ⊆ D, in maniera tale che ad
ogni istante i viene scelto quell'elemento 𝑠𝑖 che, a “parità di condizioni" (tali condizioni dipenderanno
ovviamente dal problema in questione), tra tutte le legittime scelte massimizzerebbe l'incremento
𝑓(𝑠1, … , 𝑠𝑖) − 𝑓(𝑠1, . . , 𝑠𝑖−1) , analogamente per problemi di minimo. Illustriamo l'uso della tecnica greedy
per algoritmi di approssimazione sull'importante esempio del Set Cover .
SET COVER
Input: Insieme 𝑈 = {𝑒1 , … , 𝑒𝑛 } , famiglia 𝑺 = {𝑆1 , … , 𝑆𝑘} con 𝑆𝑖 ⊆ 𝑈per i=1….k Funzione di costo𝑐: 𝑆 ∈ 𝑺 → 𝑐 𝑆 ∈ 𝑅+ 𝑒 𝑐 𝑠 ≥ 0;
Output: sottofamiglia 𝑺′ ⊆ 𝑺 di costo minimo 𝑐 𝑺′ = 𝑐(𝑆)𝑆 ∈𝑺′ minimo tale che 𝑆 ⊇ 𝑈𝑆 ∈𝑺′
Il problema del Set Cover include, come casi particolari, molti problemi di ottimizzazione che occorrono in
pratica. Anche il problema del Vertex Cover visto nella lezione precedente è un caso particolare di Set
Cover . Infatti, dato un grafo G = (V,E), se poniamo U = E, e per ogni vertice v ∈ V poniamo Sv = {e ∈ E : e
incide su v}, otteniamo una famiglia S = {Sv : v ∈ V}, con funzione costo c(Sv) = 1, per ogni v ∈ V . È facile
vedere che ogni Vertex Cover A ⊆ V per il grafo G corrisponde ad una qualche sottofamiglia 𝑆’ = {𝑆𝑣 ∶
𝑣 ∈ 𝐴} ⊆ 𝑆 che copre tutto U. Di conseguenza, un Vertex Cover di cardinalità minima è equivalente ad
un Set Cover di costo minimo per la particolare istanza sopra considerata.
Algoritmo Greedy per Set Cover 1. 𝐶 = ∅, 𝑆 ′ = ∅ // (S’ è il cover che vogliamo costruire, C è l’insieme degli elementi di U finora coperti 2. 𝑊𝑖𝑙𝑒 𝐶 ≠ 𝑈 𝑑𝑜
𝑇𝑟𝑜𝑣𝑎 𝑙’𝑖𝑛𝑠𝑖𝑒𝑚𝑒 𝑆 ∈ 𝑺 𝑐𝑜𝑛 𝑖𝑙 𝑣𝑎𝑙𝑜𝑟𝑒 𝛼 =𝑐 𝑆
𝑆−𝐶 𝑚𝑖𝑛𝑖𝑚𝑜
∀ 𝑒 ∈ 𝑆 − 𝐶 𝑝𝑜𝑛𝑖 𝑝𝑟𝑒𝑧𝑧𝑜 𝑒 = 𝛼 //prezzo(e)= quanto mi costa coprire l’arco e
𝑃𝑜𝑛𝑖 𝑆 ′ = 𝑆 ′ ∪ 𝑆 , 𝐶 = 𝐶 ∪ 𝑆 3. Output S’
Iterativamente, aggiungi a S’ l'insieme 𝑆 ∈ 𝑺 che ha il miglior (nel senso di più basso) rapporto
costo/(numero di elementi di U coperti da S e non ancora coperti 𝑆 − 𝐶 ) , rimuovi da U tutti gli elementi
ricoperti da S (𝐶 = 𝐶 ∪ 𝑆) e continua fin quando non abbiamo coperto tutto U.
Analisi delle performances
Numeriamo gli elementi di U nell'ordine in cui l'algoritmo li copre per la prima volta e sia 𝑒1 , 𝑒2 , … , 𝑒𝑛 tale
ordinamento. Proviamo innanzitutto il seguente risultato.
Lemma 1 ∀ 𝑘 ∈ {1,2, … , 𝑛} vale che 𝑝𝑟𝑒𝑧𝑧𝑜(𝑒𝑘) ≤𝑂𝑃𝑇
𝑛−𝑘+1 dove OPT è il costo della soluzione ottima a Set
Cover, ovvero il costo della famiglia di minimo costo che copre tutto U.
Dim. Consideriamo il momento in cui viene assegnato il prezzo all'elemento ek, ovvero il momento in cui
viene coperto ek per la prima volta. Ciò vuol dire che all'istante precedente l'elemento ek non era ancora
coperto, ovvero si era in una situazione del tipo
e1 , e2 , e3 , e4 , e5 , … , ek-1 , ek , ek+1 , ….. en
S1 S2 Sl Sl-1 (6)
Algoritmi e Strutture Dati 2: Lezione 12 - Set Cover e copertura massima
39
Tutti gli insiemi della soluzione ottima non presi e messi in S’ dall'algoritmo greedy, copriranno tutto U-C
(visto che tutti gli insiemi della soluzione ottima coprono tutto U), ad un costo al più OPT . Siano S1,…, St tali
insiemi. Vogliamo innanzitutto mostrare che ∃ 𝑖 ∈ {1, … , 𝑡} tale che
𝑐 𝑆𝑖
𝑡
𝑖=1
≤ 𝑂𝑃𝑇 𝑒 𝑐 𝑆𝑖
|𝑆𝑖 − 𝐶|≤
𝑂𝑃𝑇
|𝑈 − 𝐶|
Infatti, se ciò non fosse, avremmo che per ogni i vale la disuguaglianza 𝑐 𝑆𝑖
|𝑆𝑖−𝐶|>
𝑂𝑃𝑇
|𝑈−𝐶|, da cui 𝑂𝑃𝑇 ≥
𝑐 𝑆𝑖 𝑡𝑖=1 >
𝑂𝑃𝑇
|𝑈−𝐶| |𝑆𝑖 − 𝐶|𝑡
𝑖=1 (7)
Ricordiamo ora che per gli insiemi S1,…,St vale che (Siano S1,…,St gli elementi della soluzione ottima NON
scelti da greedy)
𝑆𝑖
𝑡
𝑖=1
⊇ 𝑈 − 𝐶 ⇒ (𝑆𝑖 − 𝐶)
𝑡
𝑖=1
⊇ 𝑈 − 𝐶 ⇒ |𝑆𝑖 − 𝐶|
𝑡
𝑖=1
≥ (𝑆𝑖 − 𝐶)
𝑡
𝑖=1
≥ 𝑈 − 𝐶
Ritornando alla (7) otteniamo che 𝑂𝑃𝑇 >𝑂𝑃𝑇
|𝑈−𝐶| |𝑆𝑖 − 𝐶|𝑡
𝑖=1 > 𝑂𝑃𝑇 il che è ovviamente assurdo.
Riassumendo abbiamo quindi dimostrato che esiste un insieme Si non ancora scelto dall’algoritmo greedy
per cui vale che 𝑐 𝑆𝑖
|𝑆𝑖−𝐶|≤
𝑂𝑃𝑇
|𝑈−𝐶|.
L’algoritmo “può” aver scelto qualche soluzione ottimale.
L'algoritmo greedy sceglie ad ogni passo un insieme S che ha il miglior rapporto 𝑐 𝑆
|𝑆−𝐶|. Pertanto, l'algoritmo
sceglierà sicuramente un insieme S che copre ek per cui 𝑐 𝑆
|𝑆−𝐶|≤
𝑂𝑃𝑇
|𝑈−𝐶|. D'altra parte, quando ek verrà
coperto per la prima volta, C contiene meno di k elementi (vedi la (6)), ovvero|U-C|≥n-k+1. Pertanto
𝑝𝑟𝑒𝑧𝑧𝑜 𝑒𝑘 =𝑐 𝑆
|𝑆−𝐶|≤
𝑂𝑃𝑇
|𝑈−𝐶| ≤
𝑂𝑃𝑇
𝑛−𝑘+1
OPT
t
Siano 𝑆1 , 𝑆1 , . . , 𝑆𝑙 ∈ 𝑆 ′𝑔𝑙𝑖 𝑖𝑛𝑠𝑖𝑒𝑚𝑖 𝑑𝑒𝑙𝑙𝑎 𝑠𝑜𝑙𝑢𝑧𝑖𝑜𝑛𝑒 𝑠𝑐𝑒𝑙𝑡𝑖 𝑑𝑎 𝐺𝑟𝑒𝑒𝑑𝑦.
𝑆𝑂𝐿 = 𝑐 𝑆𝑖
𝑙
𝑖=1
Sia Hn = 1 + 1/2 + 1/3 +…+ 1/n, ovvero produce una soluzione del valore SOL per cui
SOL ≤ HnOPT (8)
𝐿𝑎 𝑛𝑜𝑠𝑡𝑟𝑎 𝑆𝑂𝐿 = 𝑝𝑟𝑒𝑧𝑧𝑜 𝑒 + 𝑝𝑟𝑒𝑧𝑧𝑜 𝑒 +
𝑒 ∈𝑆2− 𝑆1
𝑒 ∈𝑆1
… = 𝑝𝑟𝑒𝑧𝑧𝑜 𝑒𝑘
𝑛
𝑘=1
≤ 𝑂𝑃𝑇
𝑛 − 𝑘 + 1
𝑛
𝑘=1
= 𝑂𝑃𝑇 1
𝑛 − 𝑘 + 1
𝑛
𝑘=1
= 𝑝𝑒𝑟 𝑙𝑎 8 = 𝑂𝑃𝑇 ∗ 1 +1
2+
1
3+ ⋯ +
1
𝑛 = 𝑂𝑃𝑇
1
𝑖
𝑛
𝑖=1
< log 𝑛 + 1 ∗ 𝑂𝑃𝑇
Presentiamo ora un esempio di una istanza di Set Cover su cui l'algoritmo greedy produce una soluzione
che si discosta dall'ottimo per un fattore pari a log 𝑛. Da ciò discenderà che l'analisi prima fatta
dell'algoritmo greedy non è migliorabile in generale.
𝑆𝑖𝑎 𝑈 = 𝑒1 , 𝑒2 , … , 𝑒𝑛 , 𝑆 = 𝑆1, … , 𝑆𝑛+1 𝑐𝑜𝑛 𝑆1 = 𝑒1 , 𝑆2 = 𝑒2 , … , 𝑆𝑛 = 𝑒𝑛 ,
𝑆𝑛+1 = 𝑒1 , 𝑒2 , … , 𝑒𝑛
𝑠𝑖 𝑎 𝑐𝑒 𝑐 𝑆1 =1
𝑛, 𝑐 𝑆2 =
1
𝑛 − 1, … , 𝑐 𝑆𝑛 = 1, 𝑐 𝑆𝑛+1 = 1 + 𝜀
Algoritmi e Strutture Dati 2: Lezione 12 - Set Cover e copertura massima
40
Eseguendo l'algoritmo greedy su questa istanza, l'output sarà composto dagli n insiemi di cardinalità 1
ciascheduno, di costo totale pari a 1 + 1/2 +… + 1/n = Hn, mentre la soluzione ottima ha ovviamente costo
pari a 1 + 𝜀.
𝑂𝑃𝑇 = 𝑐 𝑆𝑛+1 = 1 + 𝜀 ≈ 1
Nota:produrre algoritmi greedy è semplice, l’analisi di questi è complessa.
Algoritmo greedy per il problema della Copertura Massima Vediamo ora un' applicazione dell'algoritmo greedy a problemi di ottimizzazione di massimo. Consideriamo
il cosiddetto problema della Copertura Massima.
Input: Insieme 𝑈 = {𝑢1, … , 𝑢𝑛} , famiglia 𝑺 = {𝑆1, … , 𝑆𝑚 } con 𝑆𝑖 ⊆ 𝑈 𝑝𝑒𝑟 𝑖 = 1 … . 𝑚 Funzione profitto w: 𝑢 ∈ 𝑈 → 𝑤 𝑢 ∈ 𝑅+; Intero k>0
Output: k insiemi 𝑆𝑖1 , … , 𝑆𝑖𝑘 in 𝑺 di profitto totale 𝑤 𝑆𝑖1 ∪ …∪ 𝑆𝑖𝑘 = 𝑤(𝑢)𝑢 ∈ 𝑆𝑖1∪…∪𝑆𝑖𝑘
𝑚𝑎𝑠𝑠𝑖𝑚𝑜
Il problema può essere visto come una generalizzazione del problema dello zaino visto in ASD1. La
differenza sta nel fatto che mentre nel problema dello zaino possiamo prendere un qualunque elemento di
U, nel problema della Copertura Massima possiamo prendere solo gruppi di oggetti, specificati dagli insiemi
in S. Un algoritmo greedy per il problema della Copertura Massima può essere quello che ad ogni passo
sceglie un insieme in S che dà il maggior incremento al profitto attuale.
Algoritmo Greedy per Copertura Massima
1. 𝐶 = ∅ 2. 𝑓𝑜𝑟 𝑖 = 1 𝑡𝑜 𝑘 𝑑𝑜
Seleziona 𝑆 ∈ 𝑺 che massimizza il valore 𝑤 𝐶 ∪ 𝑆 − 𝑤 𝐶 𝐶 = 𝐶 ∪ 𝑆
3. Output C
Osserviamo che l'incremento del profitto avviene solo in relazione ai nuovi elementi di U effettivamente
inseriti. Vogliamo provare che il valore w(C) della soluzione C restituita dall'algoritmo greedy soddisfa la
relazione
𝑤 𝐶 ≥ 1 − 1 −1
𝑘 𝑘
𝑂𝑃𝑇 > 1 −1
𝑒 𝑂𝑃𝑇
dove e è il numero di Nepero, ovvero che l’algoritmo greedy ha fattore di approssimazione 1 −1
𝑒 ≈
0.632. Proviamo innanzitutto il seguente risultato:
Lemma 2: Supponiamo che l'algoritmo greedy prenda gli insiemi 𝑆1, … , 𝑆𝑘 nell'ordine. Allora, per ogni
ℓ = 1,…, k abbiamo
𝑤 𝑆𝑖
𝑙
𝑖=1
− 𝑤 𝑆𝑖
𝑙−1
𝑖=1
>𝑂𝑃𝑇 − 𝑤 𝑆𝑖
𝑙−1𝑖=1
𝑘
DIM.
Alla fine del passo ℓ − 1 − 𝑒𝑠𝑖𝑚𝑜 dell'algoritmo greedy abbiamo scelto ℓ − 1 insiemi 𝑆1, … , 𝑆𝑙−1 di profitto
totale 𝑤 𝑆𝑖𝑙−1𝑖=1 . Se a 𝑆1, … , 𝑆𝑙−1 aggiungiamo passo passo tutti i k insiemi della soluzine ottima,
arriveremo ad un profitto almeno OPT. Supponiamo che la soluzione ottima sia 100 e i passi siano 10. Di
conseguenza, vi deve essere almeno un passo in cui l’incremento è di almeno
Algoritmi e Strutture Dati 2: Lezione 12 - Set Cover e copertura massima
41
𝑂𝑃𝑇 − 𝑤 𝑆𝑖𝑙−1𝑖=1
𝑘 (9)
Ovvero, deve esistere almeno un insieme che aggiunto ai precedenti aumenta il profitto almeno della
quantità (9). D'altra parte, nell'algoritmo greedy viene scelto ad ogni passo sempre l'insieme che
massimizza l'incremento del profitto. Ovvero, l'insieme scelto dall'algoritmo greedy ottiene sicuramente un
incremento di profitto dato da 𝑤 𝑆𝑖𝑙𝑖=1 − 𝑤 𝑆𝑖
𝑙−1𝑖=1 almeno pari a (9), da cui il lemma.
Dal lemma appena dimostrato otteniamo che:
𝑤 𝑆𝑖
𝑙
𝑖=1
≥𝑂𝑃𝑇 − 𝑤 𝑆𝑖
𝑙−1𝑖=1
𝑘+ 𝑤 𝑆𝑖
𝑙−1
𝑖=1
=𝑂𝑃𝑇
𝑘+ 1 −
1
𝑘 𝑤 𝑆𝑖
𝑙−1
𝑖=1
(10)
Lemma 3: Per ogni ℓ = 1,…, k vale che
𝑤 𝑆𝑖
𝑙
𝑖=1
≥ 1 − 1 −1
𝑘 𝑙
𝑂𝑃𝑇 (11)
DIM. La dimostrazione avviene per induzione su ℓ.
(BASE) Proviamo innanzitutto per ℓ = 1. In tal caso la (11) è equivalente a provare che 𝑤 𝑆1 ≥ 𝑂𝑃𝑇
𝑘, che
risulta essere vera a causa della (10).
(PASSO INDUTTIVO)
Supponiamo ora la (11) vera per la ℓ, proviamola per ℓ + 1. Si ha
𝑤 𝑆𝑖
𝑙+1
𝑖=1
= 𝑤 𝑆𝑖
𝑙
𝑖=1
𝑎𝑔𝑔𝑖𝑢𝑛𝑔𝑜 + 𝑤 𝑆𝑖
𝑙+1
𝑖=1
− 𝑤 𝑆𝑖
𝑙
𝑖=1
𝑠𝑜𝑡𝑡𝑟𝑎𝑔𝑔𝑜
≥ 𝑤 𝑆𝑖
𝑙
𝑖=1
+𝑂𝑃𝑇 − 𝑤 𝑆𝑖
𝑙𝑖=1
𝑘 𝑑𝑎𝑙 𝑙𝑒𝑚𝑚𝑎 2 = 1 −
1
𝑘 𝑤 𝑆𝑖
𝑙
𝑖=1
+𝑂𝑃𝑇
𝑘
≥ 1 −1
𝑘 1 − 1 −
1
𝑘 𝑙
𝑂𝑃𝑇 + 𝑂𝑃𝑇
𝑘 𝑑𝑎𝑙𝑙′ 𝑖𝑝𝑜𝑠𝑡𝑒𝑠𝑖 𝑖𝑛𝑑𝑢𝑡𝑡𝑖𝑣𝑎
= 1 − 1 −1
𝑘 𝑙+1
𝑂𝑃𝑇
A questo punto, ponendo ℓ = k nel Lemma 3, otteniamo che
𝑤 𝑆𝑖
𝑘
𝑖=1
= 𝑤 𝐶 = 𝑆𝑂𝐿 ≥ 1 − 1 −1
𝑘 𝑘
𝑂𝑃𝑇
Ora ricordando che
lim𝑘→∞
1 −1
𝑘 𝑘
=1
𝑒≈ 0.632 𝑒 𝑐𝑒 1 −
1
𝑘 𝑘
≤ 1 −1
𝑘 + 1 𝑘+1
≤ 1
𝑒
Otteniamo finalmente
𝑆𝑂𝐿 = 𝑤 𝐶 > 1 −1
𝑒 𝑂𝑃𝑇
Vale la pena di notare che in alcune applicazioni pratiche la implementazione del passo 2 dell'algoritmo
(ovvero la scelta di un S che massimizza la differenza 𝑤 𝐶 ∪ 𝑆 − 𝑤(𝐶) può essere onerosa dal punto di
vista computazionale. Pertanto, potrebbe essere fattibile solo la selezione di un insieme S che incrementa
la diferenza 𝑤 𝐶 ∪ 𝑆 − 𝑤(𝐶) di un fattore β < 1 dell'incremento massimo. In tale caso non è difficile
vedere, seguendo i passi dell'analisi appena effettuata, che l'algoritmo greedy assicura una soluzione dal
valore 𝑆𝑂𝐿 ≥ 1 −𝛽
𝑘 𝑘𝑂𝑃𝑇 > 1 −
1
𝑒𝛽 𝑂𝑃𝑇.
𝑠𝑖 𝑎 ℓ 𝑝𝑒𝑟𝑐è 𝑙𝑖 𝑙𝑒 𝑠𝑜𝑚𝑚𝑎𝑡𝑜𝑟𝑖𝑒 𝑒𝑟𝑎𝑛𝑜 𝑐𝑜𝑛 ℓ 𝑒𝑑 ℓ
− 1 𝑒𝑑 𝑖𝑛 𝑞𝑢𝑒𝑠𝑡𝑜 𝑐𝑎𝑠𝑜 𝑐𝑜𝑛 ℓ + 1 𝑒𝑑 ℓ
Algoritmi e Strutture Dati 2: Lezione 13 – K-centro
42
Lezione 13 – K-centro
In questa lezione descriveremo un algoritmo di approssimazione per il seguente problema. Approfitteremo
dell'occasione per introdurre una nuova tecnica per il progetto di algoritmi di approssimazione, che va
sotto il nome di Pruning Parametrico.
K-CENTRO
Input: Grafo completo 𝐺 = (𝑉, 𝐸) Funzione costo 𝑐: 𝐸 → 𝑅+ 𝑠𝑢𝑔𝑙𝑖 𝑎𝑟𝑐𝑖, 𝑠𝑜𝑑𝑑𝑖𝑠𝑓𝑎𝑐𝑒𝑛𝑡𝑒 𝑙𝑎 𝑑𝑖𝑠𝑢𝑔𝑢𝑎𝑔𝑙𝑖𝑎𝑛𝑧𝑎 𝑡𝑟𝑖𝑎𝑛𝑔𝑜𝑙𝑎𝑟𝑒 Intero k>0
Output: 𝑖𝑛𝑠𝑖𝑒𝑚𝑒 𝑆 ⊆ 𝑉, 𝑆 = 𝑘, 𝑐𝑒 𝑚𝑖𝑛𝑖𝑚𝑖𝑧𝑧𝑎 𝑚𝑎𝑥𝑣∈𝑉 𝑐𝑜𝑛𝑛𝑒𝑐𝑡 𝑣, 𝑆 , 𝑑𝑜𝑣𝑒 𝑐𝑜𝑛𝑛𝑒𝑐𝑡 𝑣, 𝑆 = 𝑚𝑖𝑛 𝑢∈𝑆𝑐(𝑣, 𝑢)
Immaginiamo il caso in cui vogliamo distribuire dei server
nel modo migliore. Per scegliere la sua posizione, selezioni-
amo un nodo che abbia alcuni vicini molto simili a lui. Ad
ogni passo deve cercare di minimizzare la distanza di un nodo che sta all’esterno con uno che sta all’interno
di S. L’idea è quella di scegliere la distanza maggiore così che il vertice più lontano appartiene a S. La qualità
della soluzione aumenta facendo diminuire il max di d(v,S) da 20 a 19. All'inizio mettiamo le risorse a caso
da qualche parte. Poi metto le risorse sui nodi più lontani per migliorare il caso pessimo.
L'assunzione che la funzione costo sugli archi di G soddisfi la diseguaglianza triangolare è necessaria,
altrimenti si può dimostrare che il problema del K-Centro non può essere approssimato a meno di un
qualsiasi fattore α(n) polinomialmente computabile, assumendo che P ≠ NP.
Elaboreremo un algoritmo di approssimazione per il problema dei K-Centro usando la tecnica del Pruning
Parametrico. Tale tecnica è basata sulle seguenti considerazioni. Se conoscessimo il costo di una soluzione
ottima ad un problema, potremmo eliminare le parti non rilevanti dell'input e pertanto semplificare la
ricerca di una buona soluzione. Ad esempio, se sapessimo che il costo di un ciclo di costo minimo in una
istanza di TSP fosse 100, potremmo eliminare dal grafo tutti gli archi di costo superiore a 100, in quanto essi
sicuramente non interverranno nella soluzione ottima. Purtroppo, calcolare il costo di una soluzione ottima
è esattamente la parte difficile dei problemi di ottimizzazione NP-hard.
La tecnica del Pruning Parametrico cerca di evitare questa difficoltà nel modo seguente. Supponiamo, per
fare un esempio, di considerare un problema di ottimizzazione di minimo. Viene scelto un parametro t (che
può essere interpretato come un tentativo iniziale di stimare il valore della soluzione ottima). Per ogni
valore di t, eliminiamo dalla istanza di input I sotto esame tutte le parti che sicuramente non intervengono
in una qualche soluzione di costo ≤ t. Denotiamo con I(t) tale istanza ridotta.
L'algoritmo consiste in due passi:
1. Nel primo passo la famiglia di istanze I(t) viene usata per calcolare una limitazione inferiore per
OPT. Sia esso t* (questo calcolo viene tipicamente fatto nel modo seguente: se si riesce in qualche
modo a far vedere che in I(t*) non vi è soluzione al problema, allora è chiaro che occorre
aggiungere altre parti a I(t*) e quindi OPT sarà sicuramente ≥ t*).
2. Nel secondo passo, si trova una soluzione in I(αt*), per un opportuno valore di α. Ciò porterà ad
una soluzione di valore SOL ≤ αt* ≤ αOPT.
Algoritmi e Strutture Dati 2: Lezione 13 – K-centro
43
Per vedere come applicare la tecnica del Pruning Parametrico al problema dei KCentro, procediamo nel
modo seguente. Ordiniamo gli archi del grafo G = (V,E) in ordine crescente di costo, ovvero poniamo
𝐸 = {𝑒1, . . . 𝑒𝑚} 𝑐𝑜𝑛 𝑐(𝑒1) ≤ . . . ≤ 𝑐(𝑒𝑚).
Definiamo Gi = (V,Ei), dove Ei = {e1, ... ei}. Un insieme dominante in un grafo H = (U,F) è un sottoinsieme S ⊆
F tale che ogni vertice in U - S è adiacente a qualche vertice in S. Sia dom(H) la cardinalità di un insieme
dominante in H di cardinalità minima. E' abbastanza ovvio verificare che il problema del K-Centro è
equivalente a trovare il più piccolo indice i tale che il grafo Gi contiene un insieme dominante di cardinalità
≤ k, ovvero che Gi contenga k "stelle" (cioè alberi di altezza 1) che ricoprono tutto l'insieme V.
Se i* è tale più piccolo indice, allora è ovvio che c(ei*) è il costo di un K-Centro ottimo. Denoteremo con
OPT tale valore c(ei*).
Il problema con la procedura di sopra consiste nel fatto che determinare se un grafo contiene un insieme
dominante di una data cardinalità ed esso stesso è un problema NPhard.
Cercheremo di aggirare questa difficoltà lavorando su grafi in cui si possa stimare tale cardinalità con
parametri di più facile calcolo.
Dato un grafo H = (U,F), definiamo il quadrato di H, e lo denoteremo con H2, come il grafo che contiene gli
stessi vertici di H e per ogni coppia di vertici u, v, esiste un arco in H2 tra u e v se e solo se nel grafo H c'è un
cammino di lunghezza al più 2 tra gli stessi vertici u e v. Ricordiamo infine che un insieme I ⊆ U è detto
indipendente se ∀ 𝑢, 𝑣 ∈ 𝐼 𝑣𝑎𝑙𝑒 𝑐𝑒 (𝑢, 𝑣) ∉ 𝐹. Il seguente risultato ci darà un modo per limitare
inferiormente il valore di OPT.
Lemma 4: Dato un grafo H = (U, F), sia I un generico insieme indipendente in H2. Vale che |I| ≤ dom(H).
Dim. Sia D un insieme dominante di cardinalità minima in H. Da quanto detto in precedenza, ciò implica che
esistono |D| stelle che ricoprono tutti i vertici di H. I vertici in ciascuna di queste stelle sono ovviamente
connessi da cammini di lunghezza al più due.
Per definizione, nel grafo H2 tali cammini si trasformano in archi, pertanto ogni stella in H si trasforma in un
piccolo sottografo completo in H2 (ovvero in un sottografo in cui esistono archi tra ogni coppia di vertici).
Un qualsivoglia insieme indipendente I di H2 non può contenere più di un vertice di ciascuno di questi
sottografi completi (altrimenti non sarebbe composto da vertici non collegati da archi). Pertanto, la
cardinalità di un qualsiasi insieme indipendente I di H2 non può essere più grande del numero |D| di stelle
che ricoprono H. Ciò implica il risultato del lemma.
Prima di introdurre l'algoritmo per il problema del K-Centro , ricordiamo che un sottoinsieme I di vertici è
detto massimale indipendente se I è indipendente ed inoltre per ogni vertice u vale che I ∪ {u} non è più
indipendente. Mentre il calcolo di un insieme indipendente di cardinalità massima è un altro problema NP-
Hard, il calcolo di un insieme massimale indipendente è agevole e lo si può effettuare mediante una
semplice procedura greedy:
Algoritmo per il calcolo di un insieme massimale indipendente
Si scelga nel grafo un vertice arbitrario u e lo si inserisca in I; Si eliminano dal grafo il vertice u e tutti i suoi vicini; Si itera il procedimento sul grafo rimanente, fin quando esso non diventi vuoto Ritorna I.
Presentiamo ora l'algoritmo di approssimazione per il problema del K-Centro.
Algoritmo di approssimazione per K-Centro
1. Costruisci i grafi 𝐺12 , 𝐺2
2, … , 𝐺𝑚2
2. Calcola un insieme massimale indipendente M, in ciascun grafo 𝐺𝑖2
3. Trova il più piccolo intero i tale che 𝑀𝑖 ≤ 𝑘, 𝑠𝑖𝑎 𝑒𝑠𝑠𝑜 𝑗 4. Return 𝑀𝑗
Vogliamo provare che questo algoritmo ha un fattore di approssimazione 2. Proviamo innanzitutto il
seguente risultato che ci dà una limitazione inferiore al valore OPT.
Algoritmi e Strutture Dati 2: Lezione 13 – K-centro
44
Lemma 5: Per l'indice j definito dall'algoritmo, vale che c(ej) ≤ OPT.
Dim. Dalla definizione dell'indice j abbiamo che per ogni indice ℓ < j vale che |𝑀ℓ | > k.
Pertanto, dal Lemma 4 abbiamo che dom(𝐺ℓ) ≥ |𝑀ℓ | > k. Ricordando che i* è il più piccolo indice i per cui
dom(Gi) ≤ k, abbiamo che i* > ℓ, e quindi i* ≥ j. Ma OPT = c(ei*), e ricordando che i pesi c(es) degli archi
erano crescenti nell'indice s, abbiamo che c(ej) ≤ c(ei*) = OPT.
Possiamo ora provare il seguente
Teorema 3: L'algoritmo ha un fattore di approssimazione 2 per il problema del K-Centro.
Dim. Partiamo con l'effettuare l'osservazione chiave che un qualunque insieme indipendente massimale I in
un grafo è anche un insieme dominante. Infatti, se non lo fosse, vorrebbe dire che esisterebbe un vertice u
che non è adiacente ad alcun vertice in I, pertanto potrebbe essere inserito in I e l'insieme I continuerebbe
a rimanere un insieme indipendente, contraddicendo la massimalità di I. Sulla base di questa osservazione,
possiamo concludere che l'insieme Mj restituito dall'algoritmo è un insieme dominante di cardinalità al più
k in G2j. In altri termini, esistono |Mj| "stelle" in G2
j, centrate sui vertici di Mj , che ricoprono tutti i vertici
del grafo. Ricordando che ogni arco in G2j corrisponde ad un cammino di lunghezza al più 2 in Gj , e che vale
la diseguaglianza triangolare, abbiamo che ogni arco di queste stelle ha peso al più pari a 2c(ej).
Ricordando che il costo SOL della soluzione è pari al costo dell'arco più costoso che si è usato, abbiamo che,
in virtù del Lemma 5, vale SOL =Mj ≤ 2c(ej) ≤ 2OPT; il che prova il Teorema.
Si può provare che esistono esempi su cui l'algoritmo da noi proposto produce effettivamente una
soluzione di costo pari a 2 volte l'ottimo. Consideriamo infatti il grafo completo G = (V,E), con V = { 1, 2, ... ,
n, n + 1}, con funzione costo c(i,j) sugli archi così definita
𝑐 𝑖, 𝑗 = 1 𝑠𝑒 𝑖 = 𝑛 + 12 𝑎𝑙𝑡𝑟𝑖𝑚𝑒𝑛𝑡𝑖
Per k = 1, la soluzione ottima consiste nello scegliere il singolo vertice n+1, che è connesso ad ogni altro
vertice da un arco di peso 1, pertanto avremmo OPT = 1 in questo caso.
D'altra parte, l'algoritmo produrrebbe un indice j = n ed in questo caso G2n sarebbe di nuovo un grafo
completo. Se, per sfortuna, scegliessimo come insieme indipendente massimale un vertice s ≠ n + 1,
avremmo che il costo della soluzione ritornata sarebbe pari a 2, ovvero 2 volte il costo di OPT.
Proviamo ora che il fattore di approssimazione 2 appena ottenuto non è essenzialmente migliorabile.
Teorema 4: Se esistesse un algoritmo di approssimazione con fattore di approssimazione pari a 2 − 𝜀 per il
problema del K-Centro , per un qualche 𝜀 > 0 , allora P = NP.
Dim. Proveremo che se fosse possibile in tempo polinomiale produrre una approssimazione del problema
del K-Centro a meno di un fattore 2 − 𝜀, allora sarebbe possibile in tempo polinomiale decidere se un
arbitrario grafo possiede un insieme dominante di cardinalità al più k. Dalla NP-completezza del problema
degli insiemi dominanti, si ha la tesi.
Sia G = (V,E) un grafo arbitrario, definiamo il grafo completo G'(V,E') e la funzione costo 𝑐 ∶ 𝐸′ → 𝑅+ come
∀ 𝑢, 𝑣 ∈ 𝐸′ , 𝑐 𝑢, 𝑣 = 1 𝑠𝑒 (𝑢, 𝑣) ∈ 𝐸
2 𝑠𝑒 𝑢, 𝑣 ∉ 𝐸
Il grafo G' soddisfa la diseguaglianza triangolare. Notiamo inoltre che:
1. se dom(G) ≤ k allora la soluzione ottima per il problema del K-Centro in G' ha valore 1 (infatti se
esiste un insieme dominante D di cardinalità al più k in G, allora in G' ogni vertice può essere
connesso a vertici in D mediante archi di peso pari a 1, e meglio non si può fare).
2. se dom(G) > k, allora la soluzione ottima per il problema del K-Centro in G' ha valore pari a 2
(infatti, l'ipotesi che dom(G) > k ci forza necessariamente ad usare archi in G' non presenti in G, e
quindi di peso 2 in G').
Supponiamo ora di avere un algoritmo polinomiale di approssimazione per il problema del K-Centro che in
tempo polinomiale produce una soluzione di valore SOL ≤ (2 − 𝜀)OPT.
Algoritmi e Strutture Dati 2: Lezione 13 – K-centro
45
Eseguiamo tale algoritmo sull'istanza G' = (V,E') appena definita. L'algoritmo restituirà un valore SOL.
Possono verificarsi due casi:
1. SOL < 2. Allora necessariamente OPT = 1 e quindi, per quanto prima detto, dom(G) ≤ k.
2. SOL ≥ 2. Allora necessariamente OPT = 2 e quindi, per quanto prima detto, dom(G) > k.
Avremmo quindi una procedura polinomiale per determinare se dom(G) ≤ k o meno, da cui la tesi del
Teorema.
Algoritmi e Strutture Dati 2: Lezione 14 - PTAS e FPTAS
46
Lezione 14 - PTAS e FPTAS
FTAS E FPTAS Tra le varie questioni studiate finora, abbiamo anche scoperto che esistono problemi di ottimizzazione che
non possono essere approssimati al di sotto di una certa soglia, a meno di improbabili conseguenze, quali
𝑃 = 𝑁𝑃. Ma esistono anche problemi di ottimizzazione NP-hard la cui soluzione ottima può essere invece
approssimata con un fattore di approssimazione arbitrariamente prossimo ad 1, a costo però di tempi di
risoluzione alti.
Sia Π un problema di ottimizzazione NP-hard. Diremo che un algoritmo di approssimazione A è uno schema
di approssimazione per Π se avendo in input (I, ε), dove I è una istanza di input di Π e ε > 0 è un parametro
d'errore, esso produce una soluzione s di valore SOL(I, ε) tale che :
SOL(I, ε) ≤ (1 + ε)OPT(I), nel caso in cui Π sia un problema di minimo;
SOL(I, ε) ≥ (1 - ε)OPT(I), nel caso in cui Π sia un problema di massimo.
PTAS: L'algoritmo 𝐴 è detto schema di approssimazione polinomiale PTAS se per ogni fissato ε, il tempo di
esecuzione è polinomiale nella taglia dell'istanza I.
FPTAS: L'algoritmo A è uno schema di approssimazione polinomiale FPTAS se per ogni fissato ε, il tempo di
esecuzione è polinomiale sia in |I| che in 1
ε. (Minore sarà il parametro di errore ε richiesto, di conseguenza
maggiore sarà il rapporto 𝑛
ε e di conseguenza il tempo di esecuzione dell’algoritmo).
Problemi di ottimizzazione che ammettono PTAS, o FPTAS, possono essere approssimati ad un qualsivoglia
fattore arbitrariamente prossimo a 1. Un esempio di tali problemi è il problema dello zaino 0-1:
Zaino 0-1
Input: Insieme 𝑆 = 𝑎1 , … , 𝑎𝑛 𝑑𝑖 𝑜𝑔𝑔𝑒𝑡𝑡𝑖; Funzione peso 𝑤: 𝑎 ∈ 𝑆 → 𝑤(𝑎) ∈ 𝑅+ Funzione profitto 𝑝: 𝑎 ∈ 𝑆 → 𝑝(𝑎) ∈ 𝑅+ Capacità di carico totale 𝐵 ∈ 𝑅+
Output: 𝑠𝑜𝑡𝑡𝑜𝑖𝑛𝑠𝑖𝑒𝑚𝑒 𝑆 ′ ⊆ 𝑆 𝑡𝑎𝑙𝑒 𝑐𝑒 𝑤 𝑎 𝑎∈𝑆′ ≤ 𝐵, 𝑒 𝑑𝑖 𝑝𝑟𝑜𝑓𝑖𝑡𝑡𝑜 𝑝 𝑆 ′ = 𝑝 𝑎 𝑎∈𝑆′ 𝑚𝑎𝑠𝑠𝑖𝑚𝑜
La soluzione al problema offerta dalla Programmazione Dinamica per il problema dello Zaino 0-1 è la
seguente:
Sia P = 𝑚𝑎𝑥𝑎∈𝑆 𝑝(𝑎) il profitto massimo. Per ogni indice i ∈ 1, … , 𝑛 e valore p ∈ 1, … , 𝑛𝑃 , sia 𝑆𝑖,𝑝 un
sottoinsieme di 𝑎1 , … , 𝑎𝑛 di peso totale minimo, il cui profitto totale sia esattamente P. Sia A(i, p) il peso
𝑤(𝑎)a∈𝑆𝑖,𝑝 dell’insieme 𝑆𝑖,𝑝 . Porremo per convenzione A(i, p) = ∞ se un tale insieme 𝑆𝑖 ,𝑝 non esiste.
Ovviamente per p ∈ 1, … , 𝑛𝑃 vale che:
- A(1, p) = w(𝑎1) se p(𝑎1) = 𝑝; (se il profitto dato in input è uguale a quello di 𝑎1 il peso w
restituito da A sarà il peso di 𝑎1 )
- A(1, p) = ∞ altrimenti.
A(i, p) restituisce il minimo peso del sottoinsieme costituito dai primi i oggetti (𝑎1 , … , 𝑎𝑛) di profitto totale
p. In generale avremo:
𝐴 𝑖 + 1, 𝑝 = min{𝐴 𝑖, 𝑝 , 𝑤 𝑎𝑖+1 + 𝐴 𝑖, 𝑝 − 𝑝(𝑎𝑖+1) } 𝑠𝑒 𝑝 𝑎𝑖+1 < 𝑝
𝐴 𝑖, 𝑝 𝑎𝑙𝑡𝑟𝑖𝑚𝑒𝑛𝑡𝑖
Qualora fosse possibile, ad ogni passo aumenteremo il profitto senza far crescere il peso del sottoinsieme.
Quindi calcoleremo il massimo profitto ottenibile con sottoinsiemi di peso totale al più B che sarà quindi
dato da:
max p ∶ A(n, p) ≤ B
Algoritmi e Strutture Dati 2: Lezione 14 - PTAS e FPTAS
47
Il calcolo di A(n, p) può essere fatto dal seguente algoritmo, basandoci sulla equazione di ricorrenza. Gli
input in questione sono i profitti.
Calcolo di A(n,P) via Programmazione Dinamica
𝑃 = 𝑚𝑎𝑥𝑖 𝑝 𝑎𝑖 𝐹𝑜𝑟 𝑖 = 1 𝑡𝑜 𝑛 𝑑𝑜
𝐴(𝑖, 0) = 0; 𝐹𝑜𝑟 𝑝 = 1 𝑡𝑜 𝑛𝑃 𝑑𝑜
𝐴(1, 𝑝) = 𝑤 𝑎1 𝑠𝑒 𝑝 𝑎1 = 𝑝
∞ 𝑎𝑙𝑡𝑟𝑖𝑚𝑒𝑛𝑡𝑖
𝐹𝑜𝑟 𝑖 = 1 𝑡𝑜 𝑛 𝑑𝑜 𝐹𝑜𝑟 𝑝 = 1 𝑡𝑜 𝑛𝑃 𝑑𝑜
𝑖𝑓 𝑝 𝑎𝑖 ≤ 𝑝 𝑡𝑒𝑛 𝐴(𝑖, 𝑝) = min{𝐴 𝑖 − 1, 𝑝 , 𝑤 𝑎𝑖 + 𝐴 𝑖 − 1, 𝑝 − 𝑝(𝑎𝑖) }
𝑒𝑙𝑠𝑒 𝐴 𝑖, 𝑝 = 𝐴(𝑖 − 1, 𝑝)
Pertanto tutti i valori A(i, p) possono essere calcolati in tempo O(𝑛2 P) [il primo ciclo è O(n), il secondo è
O(np), il terzo è O(𝑛2 P)] e quindi nello stesso tempo possiamo calcolarci, e risolvere il problema dello Zaino
0-1. Ciò ovviamente non implica che abbiamo trovato un algoritmo polinomiale per il problema dello Zaino
0-1, che è un problema NP-completo (tenendo conto dei bit per rappresentarlo).
Infatti, il nostro algoritmo è in generale esponenziale nella taglia dell'input, P = 2𝑛 .
Consideriamo un algoritmo che prende in input un numero k:
Input(k)
for i ← 1 to k do
i ← i + 1
La complessità risulta essere 𝛩(𝑘), poiché l’input viene rappresentato in bit, la complessità sarà
esponenziale 𝛰(2|𝑖|), quindi con un input i, saranno neccessari |i| = log k bits.
La complessità del nostro algoritmo sarà quindi in generale uguale a O(log n + log P).
Se il valore di P fosse piccolo, ad esempio P = O(n), allora il nostro algoritmo sarebbe sì polinomiale. Se P=2n
abbiamo che l’algoritmo diventa esponenziale (n22n) con taglia (n log 2n)=(n*n)=(n2). Il problema sorge
quando i numeri sono grandi e ci vogliono molti bit per rappresentarli.
Il trucco quindi per ottenere uno PTAS per il problema dello Zaino 0-1 si basa proprio su questa
osservazione: ignoriamo una parte dell'input, ovvero una parte dei bits che rappresentano i valori dei
profitti degli oggetti. La parte meno significativa è la parte destra di una rappresentazione binaria e quando
diciamo che la scartiamo, si intende che dividiamo il numero per un fattore. Si ha una perdita di profitti e si
passa a profitti meno precisi senza discostarsi di molto dal loro corretto valore. La parte che ignoriamo
dipenderà dal valore del parametro di errore ε che siamo disposti a tollerare. In questo modo, otterremo
una nuova istanza per il problema dello Zaino 0-1 in cui i valori dei profitti degli oggetti possono essere visti
come numeri limitati da un polinomio in n e 1
ε.
Ciò ci permetterà di ottenere una soluzione di profitto almeno (1- ε ) OPT (problema di massimo), in tempo
polinomiale in n e 1
ε (più è piccolo ε più si lavora con numeri grandi) .
FPTAS per Zaino 0-1
1. Dato 𝜀 > 0, 𝑠𝑖𝑎 𝐾 =𝜀𝑃
𝑛
2. 𝑃𝑒𝑟 𝑜𝑔𝑛𝑖 𝑜𝑔𝑔𝑒𝑡𝑡𝑜 𝑎𝑖 , 𝑠𝑖𝑎 𝑝′ 𝑎𝑖 = 𝑝 𝑎𝑖
𝐾
3. 𝐴𝑝𝑝𝑙𝑖𝑐𝑎 𝑙𝑎 𝑃𝑟𝑜𝑔𝑟𝑎𝑚𝑚𝑎𝑧𝑖𝑜𝑛𝑒 𝑑𝑖𝑛𝑎𝑚𝑖𝑐𝑎 𝑠𝑢𝑙𝑙′ 𝑖𝑠𝑡𝑎𝑛𝑧𝑎𝑑𝑖 𝑖𝑛𝑝𝑢𝑡 𝑐𝑜𝑛 𝑞𝑢𝑒𝑠𝑡𝑖 𝑛𝑢𝑜𝑣𝑖 𝑝𝑟𝑜𝑓𝑖𝑡𝑡𝑖 𝑒 𝑠𝑖𝑎 𝑆 ′ 𝑙𝑎 𝑠𝑜𝑙𝑢𝑧𝑖𝑜𝑛𝑒 𝑜𝑡𝑡𝑖𝑚𝑎 𝑜𝑡𝑡𝑒𝑛𝑢𝑡𝑎
4. 𝑂𝑢𝑡𝑝𝑢𝑡 𝑆′
Algoritmi e Strutture Dati 2: Lezione 14 - PTAS e FPTAS
48
𝑆𝑂𝐿 = 𝑝(𝑆′) = 𝑝(𝑎)
𝑎 ∈𝑆′
Proviamo innanzitutto che p(S’) ≥ (1 - 𝛆) OPT.
Osserviamo che per ogni elemento 𝑎 ∈ 𝑆 si ha :
p(a) ≥ K p’(a) = K 𝑝(𝑎)
𝐾 > K (
𝑝(𝑎)
𝐾 - 1) = p(a) – K (21)
in quanto per ogni numero x vale che ⌊𝒙⌋ > x – 1. Sia O la soluzione ottima al problema originale con gli
oggetti di profitto p(a), 𝑎 ∈ 𝑆, valutiamo il profitto totale di O mediante i nuovi profitti p’(a).
Avremo :
𝐾𝑝′ 𝑂 = 𝐾 𝑝′(𝑎)
𝑎∈𝑂
> 𝑝 𝑎 − 𝐾
𝑎∈𝑂
𝑖𝑛 𝑣𝑖𝑟𝑡ù 𝑑𝑒𝑙𝑙𝑎 21 = 𝑝(𝑎)
𝑎∈𝑂
− 𝐾
𝑎∈𝑂
≥ 𝑝 𝑂 − 𝑛𝑘 𝑝𝑜𝑖𝑐è 𝑙𝑎 2 𝑠𝑜𝑚𝑚𝑎 𝑐𝑜𝑛𝑡𝑖𝑒𝑛𝑒 𝑎𝑙 𝑝𝑖ù 𝑛 𝑡𝑒𝑟𝑚𝑖𝑛𝑖 . (22)
dove O ⊆ S e w(O) ≤ B di profitto p(O) massimo.
Da ciò, e ricordando la definizione di K e di p’, abbiamo che
𝑆𝑂𝐿 = 𝑝 𝑆 ′ = 𝑝(𝑎)
𝑎∈𝑆′
≥ 𝐾 𝑝′ 𝑎 (𝑑𝑎𝑙𝑙𝑎 21)
𝑎∈𝑆′
= 𝐾𝑝′ 𝑆 ′
≥ 𝐾𝑝′ 𝑂 𝑖𝑛 𝑞𝑢𝑎𝑛𝑡𝑜 𝑆 è 𝑜𝑡𝑡𝑖𝑚𝑎 𝑝𝑒𝑟 𝑖 𝑝𝑟𝑜𝑓𝑖𝑡𝑡𝑖 𝑝′ ≥ 𝑝 𝑂 − 𝑛𝑘 𝑑𝑎𝑙𝑙𝑎 22
= 𝑂𝑃𝑇 − 𝑛𝐾 = 𝑂𝑃𝑇 − 𝑛𝜀𝑃
𝑛= 𝑂𝑃𝑇 − 𝜀𝑃 (𝑑𝑎𝑙 𝑝𝑎𝑠𝑠𝑜 1 𝑑𝑒𝑙𝑙′𝑎𝑙𝑔𝑜𝑟𝑖𝑡𝑚𝑜𝐹𝑃𝑇𝐴𝑆)
≥ (1 − 𝜀)𝑂𝑃𝑇
dove l'ultima diseguaglianza segue dal fatto che ovviamente OPT ≥ P.
O è ottima rispetto ai profitti di P e non di P’. La soluzione è più grande di (1- ε)OPT. La cosa importante è la
filosofia: abbiamo risolto in modo esatto un problema decisionale.
Ci resta solo da provare che l'algoritmo proposto è polinomiale in n e 1
ε .
A tal fine, ricordiamo che abbiamo applicato la programmazione dinamica alla nuova istanza di input,
pertanto il tempo di esecuzione sarà
𝑃′ =𝑃
𝐾= 𝑃 ∙
𝑛
𝜀 𝑃=
𝑛
𝜀, 𝑞𝑢𝑖𝑛𝑑𝑖 = 𝑂 𝑛2
𝑃
𝐾 = 𝑂 𝑛2
𝑛
𝜀 𝑖𝑙 𝑐𝑒 è 𝑝𝑜𝑙𝑖𝑛𝑜𝑎𝑚𝑖𝑎𝑙𝑒 𝑖𝑛 𝑛 𝑒
1
𝜀.
Steneir Tree In questa lezione deriveremo algoritmi di approssimazione per alcuni classici problemi su grafi pesati.
Iniziamo con il considerare il seguente problema
Steiner Tree
Input: 𝑔𝑟𝑎𝑓𝑜 𝐺 = 𝑉, 𝐸 𝐹𝑢𝑛𝑧𝑖𝑜𝑛𝑒 𝑝𝑒𝑠𝑜 𝑤: 𝐸 → 𝑅+ 𝑠𝑢𝑔𝑙𝑖 𝑎𝑟𝑐𝑖 𝑠𝑜𝑡𝑡𝑜𝑖𝑛𝑠𝑖𝑒𝑚𝑒 𝑅 ⊆ 𝑉
Output: 𝑠𝑜𝑡𝑡𝑜𝑎𝑙𝑏𝑒𝑟𝑜 𝑑𝑖 𝐺 𝑑𝑖 𝑚𝑖𝑛𝑖𝑚𝑜 𝑐𝑜𝑠𝑡𝑜 𝑡𝑜𝑡𝑎𝑙𝑒 𝑐𝑒 𝑐𝑜𝑝𝑟𝑎 𝑡𝑢𝑡𝑡𝑖 𝑖 𝑣𝑒𝑟𝑡𝑖𝑐𝑖 𝑑𝑖 𝑅, 𝑑𝑜𝑣𝑒 𝑖𝑙 𝑐𝑜𝑠𝑡𝑜 𝑑𝑒𝑙𝑙′𝑎𝑙𝑏𝑒𝑟𝑜 è 𝑑𝑒𝑓𝑖𝑛𝑖𝑡𝑜 𝑐𝑜𝑚𝑒 𝑙𝑎 𝑠𝑜𝑚𝑚𝑎 𝑑𝑒𝑖 𝑐𝑜𝑠𝑡𝑖 𝑑𝑒𝑖 𝑠𝑢𝑜𝑖 𝑎𝑟𝑐𝑖.
Ci sono delle similitudini tra questo problema e quello di determinare lo spanning tree di peso minimo in un
grafo. Infatti, se R = V allora i due problemi coincidono esattamente. Come conseguenza, il problema dello
Steiner Tree è risolubile in tempo polinomiale nel caso particolare che R = V . In generale, il problema dello
Steiner Tree è NP-hard. Il seguente esempio mostra in cosa il problema dello Steiner Tree differisce dal
problema del Minimum Spanning Tree. Consideriamo il grafo a sinistra nella figura di sotto, in cui solo i
vertici anneriti sono richiesti. La figura immediatamente a destra mostra un Minimum Spanning Tree sui
vertici richiesti, di costo totale pari a 4. All'estremità destra è invece mostrato un albero di Steiner che fa
Algoritmi e Strutture Dati 2: Lezione 14 - PTAS e FPTAS
49
uso anche di vertici non richiesti (nel caso in questione, quello centrale), di costo totale pari a 3. Può
accadere, come in questo caso, che si copre di più ma costa di meno.
Quindi, includere dei nodi non necessariamente richiesti nell'albero può far abbassare il costo della
soluzione. Questo è in effetti il tratto che distingue il problema del Minimum Spanning Tree dal problema
dello Steiner Tree . Il fatto che nel problema dello Steiner Tree si possano scegliere o meno nodi in V – R fa
sì che l’insieme delle possibili soluzioni al problema aumenti enormemente, rendendo difficile
l’individuazione della soluzione ottima.
Passiamo ora a considerare il progetto di algoritmi di approssimazione per il problema dello Steiner Tree.
Per prima cosa, mostriamo che è sufficiente considerare istanze del problema in cui il grafo G = (V, E) è un
grafo completo, ed in esso vale la diseguaglianza triangolare, ovvero
∀ 𝒖, 𝒗, 𝒛 ∈ 𝑽, 𝒘(𝒖, 𝒗) ≤ 𝒘(𝒖, 𝒛) + 𝒘(𝒛, 𝒗) (1)
Più precisamente, mostreremo che se siamo in grado di produrre un algoritmo di approssimazione con
fattore di approssimazione 𝜌 per il problema dello Steiner Tree in grafi completi in cui vale la diseguaglianza
triangolare, allora siamo anche in grado di produrre un algoritmo di approssimazione con lo stesso fattore
di approssimazione 𝜌 in istanze arbitrarie del problema dello Steiner Tree.
Procederemo come segue. Data una istanza I = (G, R, w) arbitraria del problema dello Steiner Tree, dove G è
un grafo, R è il sottoinsieme dei vertici richiesti, e w è la funzione peso sugli archi di G, trasformiamo
innanzitutto I in tempo polinomiale in una istanza I’= (G’, R, w’), dove G’ è un grafo completo sugli stessi
vertici di G, l'insieme dei vertici R richiesto è immutato, e la funzione peso w’ sugli archi (u, v) di G’ è
definita come
𝑤′(𝑢, 𝑣) = 𝑤(𝑒)
𝑒∈ 𝑝(𝑢 ,𝑣)
,
dove p(u,v) è un cammino di peso totale minimo tra i vertici u e v nel grafo G. Osserviamo ora che per ogni
arco (u, v) ∈ G, vale che
𝒘(𝒖, 𝒗) ≥ 𝒘′(𝒖, 𝒗) (2)
𝑤 𝑢, 𝑣 ≤ 𝑤 𝑢, 𝑧 + 𝑤 𝑧, 𝑣 (𝑝𝑢ò 𝑒𝑠𝑠𝑒𝑟𝑐𝑖 𝑢𝑛 𝑐𝑎𝑚𝑚𝑖𝑛𝑜 𝑝𝑖ù 𝑝𝑖𝑐𝑐𝑜𝑙𝑜)
Ciò è ovvio in quanto il costo dell'arco (u, v) in G’ è pari al costo del cammino di minimo costo tra u e v in G.
Sia OPT(I) il costo della soluzione ottima in G, e sia OPT(I’) il costo della soluzione ottima in G’. Come
conseguenza della (2) otteniamo che
OPT(I) ≥ OPT(I’). (3)
Sia ora T’ un albero di Steiner in G’ di costo minimo OPT(I’). Consideriamo il sottografo H di G composto da
tutti i cammini di G che corrispondono agli archi di T’. Ovviamente vale che il costo totale di H (ovvero la
somma dei costi degli archi di H) è esattamente pari al costo di T’.
U Z
V V V
G
7 22
U
G’
U Z
≤ 7
≤ 22 V
Algoritmi e Strutture Dati 2: Lezione 14 - PTAS e FPTAS
50
Il sottografo H non è necessariamente un albero. Eliminando da H tutti gli archi che creano cicli, otteniamo
un sottoalbero A di G che copre tutti i vertici richiesti, di costo al più pari al costo di T’ (visto che abbiamo
eliminato degli archi da T’ per ottenere A). D’altra parte, per definizione, il costo OPT(I) di un albero di
Steiner di G è non superiore ad A, pertanto otteniamo
OPT(I) ≤ 𝒄𝒐𝒔𝒕𝒐(𝑨) ≤ 𝒄𝒐𝒔𝒕𝒐(𝑻′) = OPT(I’). (4)
Mettendo insieme la (3) e la (4) otteniamo che
OPT(I) = OPT(I’) (5)
Riassumendo, abbiamo fatto vedere che il costo di una soluzione ottima in un grafo arbitrario G è uguale al
costo di una soluzione ottima in un grafo completo G’ facilmente ottenibile da G. Non solo, abbiamo anche
fatto vedere che data una soluzione ottima in G’ è semplice ottenere da essa una soluzione ottima
nell'istanza originale G. Di conseguenza, possiamo limitarci a progettare algoritmi per il problema dello
Steiner Tree in grafi completi, in cui valga la diseguaglianza triangolare. L'algoritmo di approssimazione in
tali grafi è molto semplice.
Algoritmo di approssimazione per Steiner Tree
1. Costruisci un Minimun Spanning Tree T sui vertici in R del grafo in input G 2. Return T
Dimostriamo che l'algoritmo sopra esposto ha fattore di approssimazione pari a 2. Sia S uno Steiner tree di
costo minimo. Sostituiamo ogni arco (u, v) di S con la coppia di archi direzionati (u, v) e (v, u) e si procede ad
una visita di tutti i nodi del grafo così ottenuto.
Il percorso relativo alla visita (esempio Depth First) può passare più di una volta per uno stesso vertice, e
passerà sia attraverso vertici in R che attraverso vertici non in R (denotati con un cerchio vuoto nella figura
di sotto). Il costo di questo percorso è pari a 2OPT, visto che usiamo ogni arco di S esattamente due volte
(una volta in un verso, e la seconda nell'altro verso). A questo punto, usiamo la diseguaglianza triangolare
per evitare di passare due volte attraverso uno stesso vertice e per evitare di passare attraverso vertici non
in R.
In questo modo otterremo un ciclo che attraversa tutti i vertici di R, di costo al più 2OPT (a causa della
diseguaglianza triangolare). Eliminando un qualsiasi arco da questo ciclo ci darà un albero Z che attraversa
tutti e solo i vertici di R, di costo ancora inferiore, ovvero il costo di Z sarà al più 2OPT. D'altra parte, il costo
del Minimim Spanning Tree T (output del nostro algoritmo di approssimazione) sarà per definizione
inferiore al costo dell'albero Z, che abbiamo prima mostrato essere inferiore a 2OPT. Otteniamo quindi che
la nostra soluzione al problema dello Steiner Tree , ovvero un Minimum Spanning Tree su R, ha costo al più
2OPT.
Algoritmi e Strutture Dati 2: Lezione 14 - PTAS e FPTAS
51
Possiamo mostrare che esistono classi di grafi in cui il costo di un Minimum Spanning Tree è circa 2 volte il
costo di uno Steiner Tree, quindi l'analisi della tecnica prima esposta non può essere essenzialmente
migliorata. Consideriamo ad esempio il grafo completo G = (V, E), dove 𝑉 = {1, … , 𝑛, 𝑛 + 1}, insieme
richiesto 𝑅 = {1, . . . , 𝑛}, e funzione peso sugli archi w : E → R+ così definita
∀ 𝑖, 𝑗 ∈ 𝐸, 𝑤 𝑖, 𝑗 = 1 𝑠𝑒 𝑖 = 𝑛 + 12 𝑎𝑙𝑡𝑟𝑖𝑚𝑒𝑛𝑡𝑖
Il costo della soluzione prodotta dal nostro algoritmo di approssimazione è pari al costo di un MST su R, e
quindi pari a 2(n − 1). D’altra parte, lo Steiner Tree di costo minimo è composto da tutti gli archi dal nodo
𝑛 + 1 (non richiesto) a tutti gli altri nodi del grafo. Tale Steiner Tree ha costo totale pari a n, cioè circa la
metà del costo di un MST su R. Le tecniche appena sviluppate sono utili anche per la progettazione di
algoritmi di approssimazione per il seguente importante problema: Problema del Commesso Viaggiatore
(TSP).
Algoritmi e Strutture Dati 2: Lezione 15 – TSP (commesso viaggiatore)
52
Lezione 15 – TSP (commesso viaggiatore) TSP
Input: 𝑔𝑟𝑎𝑓𝑜 𝐺 = (𝑉, 𝐸) 𝑓𝑢𝑛𝑧𝑖𝑜𝑛𝑒 𝑐𝑜𝑠𝑡𝑜 𝑐: 𝐸 → 𝑅+ 𝑠𝑢𝑔𝑙𝑖 𝑎𝑟𝑐𝑖
Output: 𝑢𝑛 𝑐𝑖𝑐𝑙𝑜 𝑑𝑖 𝑚𝑖𝑛𝑖𝑚𝑜 𝑐𝑜𝑠𝑡𝑜 𝑡𝑜𝑡𝑎𝑙𝑒 𝑐𝑒 𝑎𝑡𝑡𝑟𝑎𝑣𝑒𝑟𝑠𝑎 𝑡𝑢𝑡𝑡𝑖 𝑖 𝑣𝑒𝑟𝑡𝑖𝑐𝑖 𝑑𝑖 𝐺 𝑢𝑛𝑎 𝑒𝑑 𝑢𝑛𝑎 𝑠𝑜𝑙𝑎 𝑣𝑜𝑙𝑡𝑎
Questo problema non è approssimabile in tempo polinomiale. Proviamolo con un circuito Hamiltoniano.
Proveremo che se esistesse un algoritmo di approssimazione con fattore di approssimazione 𝜌(n) per TSP,
allora sarebbe possibile decidere in tempo polinomiale se un grafo arbitrario G possiede un ciclo
Hamiltoniano.
Sia a tale scopo G = (V,E) (istanza di circuito hamiltoniano) un grafo arbitrario con 𝑛 = |𝑉|. Trasformiamo G
in una istanza di TSP nel modo seguente. Sia G’ = (V,E’) un grafo completo sullo stesso insieme dei vertici di
G. Inoltre, G’ ha una funzione costo c ∶ E’ −> 𝑹+ sugli archi definita nel modo seguente:
∀ 𝑢, 𝑣 ∈ 𝐸′, 𝑐 𝑢, 𝑣 = 1 𝑠𝑒 𝑢, 𝑣 ∈ 𝐸𝐶 > 𝑛𝜌(𝑛) 𝑠𝑒 𝑢, 𝑣 ∉ 𝐸
Supponiamo di avere un algoritmo di approssimazione A per TSP.
Possono accadere 2 casi:
1. 𝑆𝑂𝐿 < 𝑛𝜌 𝑛 ⇒ G (grafo di partenza) vi è un Hamiltoniano. Sotto questa ipotesi, e per come è
definito il grafo G’ , possiamo dire che l'algoritmo A ha trovato un ciclo che visita tutti i vertici di G’
ed il ciclo è composto solo da archi di costo 1. Ciò implica, per come sono definiti i costi degli archi
di G’, che il ciclo trovato da A è composto solo da archi di G. Ovvero, possiamo concludere che G
possiede un ciclo Hamiltoniano.
2. 𝑆𝑂𝐿 ≥ 𝑛𝜌 𝑛 ⇒ G non ha un ciclo Hamiltoniano. Sotto questa ipotesi, e per come è definito il
grafo G’, possiamo dire che il grafo G non possiede un ciclo Hamiltoniano. Infatti, se lo possedesse,
vorrebbe dire che la soluzione ottima del problema del TSP in G’ ha valore pari a n, contraddicendo
il fatto che l'algoritmo A ha fattore di approssimazione pari a 𝜌(𝑛).
Se G fosse Hamiltoniano, allora OPT=n, quindi con 𝜌(𝑛) a piacere è impossibile approssimare TSP.
In conclusione, l’esistenza di un algoritmo di approssimazione con fattore di approssimazione 𝜌 (n) per TSP
implica l’esistenza di una procedura polinomiale per decidere se un grafo arbitrario ha un ciclo
Hamiltoniano o meno, il che implicherebbe che P = NP a causa della NP-completezza del problema del ciclo
Hamiltoniano.
Nell' ipotesi che la funzione costo sugli archi del grafo G soddisfi la diseguaglianza triangolare, è abbastanza
semplice produrre un algoritmo di approssimazione per il problema del TSP con fattore di approssimazione
2. L'algoritmo è simile all'algoritmo di approssimazione per Steiner Tree. L’algoritmo visita ogni vertice una
sola volta e ritorna al punto di partenza.
G grafo completo, 𝑤: 𝐸 → 𝑅+ in cui vale la disuguaglianza triangolare:
Algoritmo di approssimazione per TSP
1. Costruisci un Minimum Spanning Tree T del grafo input G 2. Sostituisci ogni arco (u,v) di T con la coppia di archi (u,v) e (v,u) 3. Costruisci un tour T del grafo così ottenuto, passando attraverso tutti i suoi archi 4. Output il ciclo C che visita i vertici di G nell’ordine della loro prima apparizione nel tour T.
Il seguente esempio illustra il funzionamento dell'algoritmo. L'albero di sotto è il Minimum Spanning Tree
costruito dall'algoritmo. Su di esso costruiamo il tour T rappresentato dagli archi tratteggiati, più o meno
come si procedeva nel caso dello Steiner Tree.
Algoritmi e Strutture Dati 2: Lezione 15 – TSP (commesso viaggiatore)
53
Dopodiché, in accordo all'algoritmo, otteniamo un ciclo che enumera i vertici dell'albero in accordo all'ordine in cui essi compaiono per la prima volta nel tour T. Per la diseguaglianza triangolare, i percorsi che vanno da un vertice direttamente ad un altro senza passare per vertici intermedi, sono di costo minore e quindi non aumentano il costo del ciclo C rispetto al costo del tour T . In questo modo ho costruito un ciclo.
Proviamo ora che l'algoritmo ha fattore di approssimazione pari a 2. Osserviamo innanzitutto che:
𝑐𝑜𝑠𝑡𝑜 𝐶 ≤ 2 𝑐𝑜𝑠𝑡𝑜 (𝑀𝑆𝑇) 𝑐𝑜𝑠𝑡𝑜 𝑀𝑆𝑇 ≤ 𝑂𝑃𝑇
Sia un Grafo con un ciclo. Se togliamo un arco, abbiamo un caso particolare di albero (come se fosse una
linea). Infatti, se dal ciclo di costo OPT togliamo un arco, otteniamo un albero T’, di costo inferiore al ciclo,
ed in più T’ avrà sicuramente costo maggiore od al più uguale a T, che è un MST. Pertanto il costo SOL della
soluzione prodotta dall'algoritmo di sopra sarà:
𝑆𝑂𝐿 = 𝑐𝑜𝑠𝑡𝑜 𝐶 ≤ 𝑐𝑜𝑠𝑡𝑜 𝑇 𝑃𝑒𝑟 𝑙𝑎 𝑑𝑖𝑠𝑢𝑔𝑢𝑎𝑔𝑙𝑖𝑎𝑛𝑧𝑎 𝑡𝑟𝑖𝑎𝑛𝑔𝑜𝑙𝑎𝑟𝑒 = 2 𝑐𝑜𝑠𝑡𝑜 𝑀𝑆𝑇 ≤ 2𝑂𝑃𝑇
Quindi l’algoritmo ha un fattore di approssimazione pari a 2.
Ci poniamo ora il problema di elaborare un algoritmo per il problema del TSP con un migliore fattore di
approssimazione. A tale scopo, è utile comprendere meglio come abbiamo ottenuto il semplice algoritmo
con fattore di approssimazione pari a 2. Siamo partiti con uno MST T del grafo G ed abbiamo ottenuto un
tour che visita tutti gli archi di T, essenzialmente raddoppiando gli archi di T. Ciò ci costa 2 volte il costo di T.
Da questo tour, abbiamo ottenuto un ciclo in G prendendo delle "scorciatoie" nel tour. Grazie alla
diseguaglianza triangolare, queste scorciatoie non hanno aumentato il costo della soluzione. La prova si
concludeva con l'osservazione che 2(costo di T) è inferiore a 2 OPT. La chiave del miglioramento
dell'algoritmo prima esposto risiede nel fatto che è possibile ottenere un tour che attraversa tutti i vertici di
G ad un costo inferiore a 2(costo di T). A tale scopo abbiamo bisogno di introdurre il concetto di Tour (o
circuito) Euleriano di un grafo.
Un circuito Euleriano è un ciclo in G, che attraversa tutti gli archi una ed una sola volta. La differenza con un
circuito hamiltoniano è che visita i vertici (nel tour Euleriano gli archi) una ed una sola volta. Attraversare
tutti gli archi implica visitare tutti i vertici.
Una proprietà importante è che un grafo G possiede un ciclo Euleriano se e solo se G non ha vertici di
grado dispari.
Intuitivamente ogni volta che uso un arco per “uscire” da un vertice, per “tornare” ne devo usare un altro.
Osserviamo che ogni volta che con questo percorso usciamo da x e vi ritorniamo, usiamo due archi incidenti
su x. Non saremmo quindi in grado di visitare tutti gli archi incidenti su x una ed una sola volta con un
percorso che parte e ritorna in x, in quanto tali archi sono in numero dispari.
Algoritmi e Strutture Dati 2: Lezione 15 – TSP (commesso viaggiatore)
54
La prova che è possibile costruire un tour Euleriano di G se G ha solo vertici di grado pari la si effettua per
induzione sul numero di archi |E|. Se |E| = 1 non vi è nulla da provare. Assumiamo il teorema vero per tutti
i grafi con |E| ≤ k, per qualche k ≥ 1, e sia G un grafo con |E| = k + 1. Prendiamo un arbitrario vertice x in G,
scegliamolo come punto di partenza ed iniziamo a visitare il grafo, con l'accortezza di non passare mai due
volte su di uno stesso arco. Poiché il grado di ogni vertice v è pari, ogni volta che entriamo in un vertice v ne
possiamo anche uscire. Poiché il grafo G è finito, prima o poi ritorneremo nel vertice x. Se abbiamo visitato
tutti gli archi di G, allora abbiamo trovato il tour Euleriano che cercavamo. Altrimenti abbiamo trovato solo
un percorso che parte ed arriva in x e che ogni qualvolta è entrato in qualche vertice v ne è anche uscito. In
altre parole, questo percorso ha visitato, per ogni vertice v, un numero pari di archi incidenti su v. Togliamo
gli archi di tale percorso da G, rimane un grafo G’ con un numero di archi ≤ k, ed ogni vertice di G’ ha
ovviamente grado pari. Il grafo G’ ammette quindi un tour Euleriano per ipotesi induttiva. Il ciclo prima
trovato congiunto al tour di G’ formano ovviamente un tour che parte e arriva in x e che visita tutti gli archi
di G una ed una sola volta.
Diciamo che un grafo G è Euleriano se in G vi è un ciclo Euleriano. A questo punto dovrebbe essere anche
chiaro perché raddoppiavamo tutti gli archi del Minimum Spanning Tree T nel primo algoritmo di
approssimazione per TSP prima di trovare un tour nel grafo: raddoppiando tutti gli archi ottenevamo infatti
un grafo con tutti i nodi di grado pari e quindi il tour Euleriano esisteva sicuramente. Non è detto però che
questo sia il modo più economico per ottenere da T un grafo Euleriano. Anzi, in generale non lo è.
Banalmente, se un nodo ha già grado pari in T non vi è alcuna necessità di raddoppiare il suo grado. In virtù
del teorema precedente, sono solo i vertici di grado dispari che sono fonte di problemi. Questi problemi li
possiamo far scomparire aggiungendo un arco a ciascun nodo di grado dispari, ottenendo quindi un grafo
con tutti i vertici di grado pari in cui costruire un tour Euleriano e poi, usando le scorciatoie e la
diseguaglianza triangolare, ottenere un ciclo che attraversa tutti i vertici una ed una sola volta.
In un grafo, il numero di vertici di grado dispari è pari:
deg 𝑢 = 2 |𝐸|
𝑢 ∈𝑉
Conto gli archi e lo faccio 2 volte perché la 1 volta lo conto quando calcolo su u e la 2 su v. Pertanto, dato
un generico grafo G, per trasformare G in un grafo Euleriano basta individuare il sottoinsieme dei vertici V’
di grado dispari, dividerlo in due sottoinsiemi disgiunti di cardinalità |V’|/2 ciascuno, ed aggiungere un
matching (insieme di nodi disgiunti) tra tali due sottoinsiemi. Abbiamo quindi il seguente nuovo algoritmo
di approssimazione per TSP.
Algoritmo di approssimazione per TSP con fattore di approssimazione 3/2
1. Costruisci un MINIMUM SPANNING TREE T del grafo input G 2. Calcola un matching perfetto M di minimo costo sui vertici di grado dispari di T. Aggiungi M a T per
ottenere un grafo Euleriano 3. Costruisci un tour euleriano T del grafo ottenuto al passo precedente 4. Output il ciclo C che visita i vertici di G nell’ordine della loro prima apparizione nel tour T.
Analizziamo il costo della soluzione prodotta dall'algoritmo. A causa della diseguaglianza triangolare, il
costo SOL della soluzione prodotta non sarà superiore al costo del grafo Euleriano ottenuto al passo 2
dell'algoritmo, ovvero
𝑆𝑂𝐿 ≤ 𝐶𝑜𝑠𝑡𝑜 𝑇 ≤ 𝐶𝑜𝑠𝑡𝑜 𝑀𝑆𝑇 + 𝐶𝑜𝑠𝑡𝑜(𝑀) Già sappiamo che costo(MST) ≤ OPT, valutiamo quindi il costo di M. A tale scopo, effettuiamo le seguenti
osservazioni. Consideriamo la soluzione ottima al problema del TSP, ovvero il ciclo C che attraversa tutti i
vertici del grafo con un costo totale OPT. Tale ciclo C attraverserà anche tutti i vertici dell'insieme V’
(composto dai vertici di grado dispari nel MST T usato nel passo 1 dell'algoritmo), in un qualche ordine.
Numeriamo i vertici di V’ con i numeri 1, 2, …, |V’| secondo quest'ordine di attraversamento.
Algoritmi e Strutture Dati 2: Lezione 15 – TSP (commesso viaggiatore)
55
Ora, il ciclo C per andare dal vertice 1 al vertice 2 seguirà un certo percorso (rappresentato dalla linea
tratteggiata tra 1 e 2 nella figura di sopra) che, a causa della diseguaglianza triangolare, avrà un costo ≥ del
costo dell'arco tra 1 e 2. Stesso discorso per il percorso che C effettuerà per andare da 2 a 3, e così via. In
conclusione, la somma dei costi dei percorsi del ciclo C tra i vertici di {1, 2, ...} = V’, comprensivo del ritorno
al vertice 1 sarà ≥ della somma dei costi degli archi diretti tra i vertici {1, 2, …} = V’. Facendo attenzione, si
può comprendere che gli archi tra i vertici di V’ si possono decomporre in due matching disgiunti (nella
figura di sopra sono rappresentati con archi di differente spessore). Possiamo quindi dire che il costo OPT
del ciclo ottimo C sarà ≥ della somma dei costi dei percorsi del ciclo C tra i vertici di {1, 2,…} = V’ che, a sua
volta, è ≥ del costo dei due matching tra i vertici di V’.
𝑐𝑜𝑠𝑡𝑜 𝐶 = 𝑂𝑃𝑇 ≥ 𝑐𝑜𝑠𝑡𝑜 𝑀1 + 𝑐𝑜𝑠𝑡𝑜 (𝑀2)
Almeno uno dei due matching avrà quindi costo ≤ OPT/2. A maggior ragione, il matching di costo minimo M
aggiunto tra i vertici di V’ nel passo 2 dell'algoritmo avrà costo ≤ OPT/2. Riassumendo otteniamo
𝑆𝑂𝐿 ≤ 𝐶𝑜𝑠𝑡𝑜 𝑀𝑆𝑇 + 𝑐𝑜𝑠𝑡𝑜 𝑀 ≤ 𝑂𝑃𝑇 +1
2𝑂𝑃𝑇 ≤
3
2𝑂𝑃𝑇
Il che conclude l’analisi dell’algoritmo. La seguente figura mostra che l'analisi dell'algoritmo non può essere migliorata, ovvero esistono istanze di
input su cui l'algoritmo produce effettivamente una soluzione di costo pari a 3
2𝑂𝑃𝑇.
Il Minimum Spanning Tree trovato al Passo 1 dell'algoritmo è rappresentato da archi di maggior spessore. Notiamo che ha solo due vertici di grado dispari, pertanto il matching di minimo peso che viene aggiunto tra di essi è dato dall'arco di peso ⌊𝑛 2 ⌋. Abbiamo quindi che l'algoritmo produce un ciclo di peso totale 𝑆𝑂𝐿 = 𝑛 − 1 + ⌊𝑛 2 ⌋.
D'altra parte, è facile vedere che il ciclo ottimo nel grafo di sopra ha peso esattamente n. Da cui segue che
nel grafo di sopra il nostro algoritmo è forzato a produrre una soluzione di costo 3
2𝑂𝑃𝑇.
Algoritmi e Strutture Dati 2: Lezione 16 – Algoritmi di approssimazione tramite PL
56
Lezione 16 – Algoritmi di approssimazione tramite PL
In questa lezione inizieremo a studiare gli algoritmi di approssimazione per problemi di ottimizzazione NP-
hard in un contesto più ampio di quanto fatto finora. Introdurremo una tecnica di portata molto generale
per il progetto di algoritmi di approssimazione e rivedremo alcuni degli algoritmi che abbiamo studiato,
reinterpretandoli all'interno del nuovo contesto. La tecnica di cui intendiamo parlare è la Programmazione
Lineare (PL).
È ragionevole affermare che una gran parte della teoria degli algoritmi di approssimazione, come è nota a
tutt'oggi, è basata sulla PL. A titolo di esempio, iniziamo con il considerare una generalizzazione del
problema del Vertex Cover introdotto nella prima lezione.
Vertex Cover Input:
𝐺𝑟𝑎𝑓𝑜 𝐺 = (𝑉, 𝐸) 𝑓𝑢𝑛𝑧𝑖𝑜𝑛𝑒 𝑝𝑒𝑠𝑜 𝑤: 𝑉 → 𝑅+
Output: 𝑠𝑜𝑡𝑡𝑜𝑖𝑛𝑠𝑖𝑒𝑚𝑒 𝑆 ⊆ 𝑉 𝑑𝑖 𝑚𝑖𝑛𝑖𝑚𝑜 𝑝𝑒𝑠𝑜 𝑤 𝑆 = 𝑤 𝑢 𝑡𝑎𝑙𝑒 𝑐𝑒 𝑢∈𝑆 ∀(𝑢, 𝑣) ∈ 𝐸, {𝑢, 𝑣} ∩ 𝑆 ≠ ∅
Ritroviamo il vecchio problema del Vertex Cover studiato in precedenza nel caso in cui la funzione peso sui
vertici sia tale che w(u) = 1 per ogni u ∈ V .
Formuliamo il problema appena enunciato attraverso la PL. Per prima cosa descriviamo una qualsiasi
possibile soluzione S ⊆ V = 𝑣1 , … , 𝑣𝑛 mediante un vettore binario 𝑥 = (𝑥(𝑣1), … , 𝑥(𝑣𝑛)) tale che
𝑥 𝑣𝑖 = 1 𝑠𝑒 𝑣𝑖 ∈ 𝑆 0 𝑠𝑒 𝑣𝑖 ∉ 𝑆
(22)
Il problema di trovare un Vertex Cover di peso minimo in G può essere quindi formulato come
𝑚𝑖𝑛𝑖𝑚𝑖𝑧𝑧𝑎𝑟𝑒 𝑥 𝑣 𝑤 𝑣
𝑣 ∈𝑉
23
𝑠𝑜𝑔𝑔𝑒𝑡𝑡𝑜 𝑎 𝑥 𝑢 + 𝑥 𝑣 ≥ 1, ∀ 𝑢, 𝑣 ∈ 𝐸 (24)
𝑥 𝑣 ∈ 0,1 ∀𝑢 ∈ 𝑉 (25)
Il vincolo (25) (comunemente chiamato vincolo di interezza) ci assicura che ogni possibile vettore soluzione
x abbia componenti a valori binari, e quindi x definisca un sottoinsieme S ⊆ V attraverso la (22). Il vincolo
(24) ci assicura che per ogni arco (u, v) ∈ E almeno una delle due componenti x(u), x(v) del vettore x abbia
valore pari a 1. Ciò altresì assicura che ∀ (u, v) ∈ E almeno uno tra u e v appartenga all'insieme S
corrispondente al vettore x, ovvero che S è un Vertex Cover di G. Pertanto il problema di PL (23) è
perfettamente equivalente al problema del Vertex Cover di minimo peso prima enunciato.
Ovviamente, benché scritto in questa forma il problema continua ad essere difficile, ovvero non risolvibile
in tempo polinomiale (se P ≠ NP). L'approccio che seguiremo consiste nel derivare un nuovo sistema di PL,
differente da (23) (ma ad esso collegato), di “facile" soluzione, indi dedurre dalla soluzione al nuovo
problema di PL una soluzione (sperabilmente “buona") al problema originale di PL.
Il nuovo problema di PL che formuliamo lo si ottiene rilassando (ovvero indebolendo) il vincolo di interezza
(25), e sostituendolo con un semplice vincolo di non negatività delle variabili x(v), ∀v ∈ V . Otteniamo quindi
il seguente problema di PL
𝑚𝑖𝑛𝑖𝑚𝑖𝑧𝑧𝑎𝑟𝑒 𝑥 𝑣 𝑤 𝑣
𝑣 ∈𝑉
26
𝑠𝑜𝑔𝑔𝑒𝑡𝑡𝑜 𝑎 𝑥 𝑢 + 𝑥 𝑣 ≥ 1, ∀ 𝑢, 𝑣 ∈ 𝐸 (27)
𝑥 𝑣 ∈ [0,1] ∀𝑢 ∈ 𝑉 (28)
Questo è un problema standard di PL, risolubile ottimalmente in tempo polinomiale.
Quindi, in tempo polinomiale nella taglia del sistema è possibile trovare il vettore
𝑥∗ = (𝑥∗(𝑣1), … , 𝑥∗(𝑣𝑛)) che minimizza la funzione obiettivo x(v)w(v) v∈V e che rispetta entrambi i
Algoritmi e Strutture Dati 2: Lezione 16 – Algoritmi di approssimazione tramite PL
57
vincoli (27) e (28). Denotiamo con OPTR il valore ottimo della funzione obiettivo del sistema di PL (26) in
corrispondenza al vettore 𝑥∗, ovvero OPTR = x∗(v)w(v).v∈V
Denotiamo con OPT il valore minimo (ottimo) della funzione obiettivo del sistema di PL a vincoli interi (23),
ovvero OPT è il minimo peso di un Vertex Cover di G. Dato che nel sistema (26) minimizziamo la stessa
funzione obiettivo di (23), ma su di una regione più ampia, avremo che
OPTR ≤OPT. (29)
Vogliamo adesso scoprire se è possibile ottenere dal vettore soluzione x* del sistema (26) un vettore x a
componenti binarie che rispetti tutti i vincoli del sistema (23), ed in corrispondenza del quale la funzione
obiettivo di (23) assuma un valore al più pari ad 𝛼OPTR, per qualche valore 𝛼 ragionevolmente piccolo. Se
riuscissimo in ciò, allora in virtù della (29) avremmo ottenuto un vettore soluzione al sistema (23) per cui la
funzione obiettivo assume valore al più 𝛼OPT. In altri termini, avremmo ottenuto un Vertex Cover di G di
peso pari al più ad 𝛼 per il peso del Vertex Cover ottimo (cioè di minimo peso). Ovvero, otterremmo un
algoritmo di approssimazione per Vertex Cover in grafi pesati con coefficiente di approssimazione pari ad 𝛼.
Procediamo nel seguente modo. Dato il vettore x*, definiamo il vettore x a componenti intere nel seguente
modo
∀ 𝑣 ∈ 𝑉, 𝑥 𝑣 = 1 𝑠𝑒 𝑥∗ 𝑣 ≥ 1
2
0 𝑠𝑒 𝑥∗ 𝑣 < 12
(30)
Mostriamo innanzitutto che S = v ∶ x(v) = 1 è un Vertex Cover di G. Poiché il vettore 𝑥∗ soddisfa i
vincoli del sistema di PL: 𝑥 𝑢 + 𝑥 𝑣 ≥ 1, ∀(𝑢, 𝑣) ∈ 𝐸 o vale che 𝑥∗ 𝑢 ≥ 12 oppure che 𝑥∗ 𝑣 ≥ 1
2 (o
entrambe). Pertanto, dalla riformulazione di x(v) abbiamo che per ogni arco (u, v) ∈ E o vale che x(u) = 1,
oppure x(v) = 1. Valutiamo ora il peso di S. Si ha che esso è pari a
𝑥 𝑣 𝑤 𝑣
𝑣 ∈𝑉
≤ 2𝑥∗ 𝑣 𝑤 𝑣
𝑣 ∈𝑉
= 2𝑂𝑃𝑇𝑅 ≤ 2𝑂𝑃𝑇
In conclusione, l'algoritmo sopra esposto che costruisce un Vertex Cover di G “arrotondando" la soluzione
ottima del sistema di PL (26), restituisce una soluzione di valore al più 2OPT. Ovvero, abbiamo ottenuto un
algoritmo di approssimazione per Vertex Cover in grafi pesati con fattore di approssimazione pari a 2.
Set Cover Applichiamo ora la stessa tecnica al problema del Set Cover
Input: Insieme 𝑈 = {𝑒1 , … , 𝑒𝑛 } , famiglia 𝑺 = {𝑆1 , … , 𝑆𝑚 } con 𝑆𝑖 ⊆ 𝑈per i=1….m Funzione di costo𝑐: 𝑆 ∈ 𝑺 → 𝑐 𝑆 ∈ 𝑅+ 𝑒 𝑐 𝑠 ≥ 0;
Output: sottofamiglia 𝑺′ ⊆ 𝑺 di costo minimo 𝑐 𝑺′ = 𝑐(𝑆)𝑆 ∈𝑺′ minimo tale che 𝑆 ⊇ 𝑈𝑆 ∈𝑺′
Formuliamo innanzitutto il problema mediante la PL. Ad ogni sottofamiglia 𝑆′ ⊆ 𝐒 associamo un vettore
binario 𝑥(𝑺’) = (𝑥(𝑆1), … , 𝑥(𝑆𝑚 )) tale che
𝑥 𝑆𝑖 = 1 𝑠𝑒 𝑆𝑖 ∈ 𝑆′
0 𝑠𝑒 𝑆𝑖 ∉ 𝑆′ (31)
Il costo della famiglia S’ si esprimerà come x(S)c(S)𝑆∈𝑆′ , il vincolo che gli insiemi in S’ coprano tutto U lo
si esprime con la diseguaglianza: 𝑥 𝑆 ≥ 1, ∀𝑒 ∈ 𝑈𝑆:𝑒 ∈𝑺
Pertanto, il problema del Set Cover lo si potrà esprimere con il seguente sistema di PL
𝑚𝑖𝑛𝑖𝑚𝑖𝑧𝑧𝑎𝑟𝑒 𝑥 𝑆 𝑐 𝑆
𝑆 ∈𝑺
32
𝑠𝑜𝑔𝑔𝑒𝑡𝑡𝑜 𝑎 𝑥 𝑆 ≥ 1
𝑆:𝑒 ∈𝑆
, ∀𝑒 ∈ 𝑈 (33)
𝑥 𝑆 ∈ 0,1 ∀𝑆 ∈ 𝑺 (34)
Algoritmi e Strutture Dati 2: Lezione 16 – Algoritmi di approssimazione tramite PL
58
Il primo passo per derivare un algoritmo di approssimazione consiste nel passare alla versione rilassata del
sistema (32), in cui i vincoli di interezza (34) sulle variabili x(S) vengono sostituiti con dei semplici vincoli di
non negatività. La versione rilassata di (32) è
𝑚𝑖𝑛𝑖𝑚𝑖𝑧𝑧𝑎𝑟𝑒 𝑥 𝑆 𝑐 𝑆
𝑆 ∈𝑺
35
𝑠𝑜𝑔𝑔𝑒𝑡𝑡𝑜 𝑎 𝑥 𝑆 ≥ 1
𝑆:𝑒 ∈𝑆
, ∀𝑒 ∈ 𝑈 (36)
𝑥 𝑆 ∈ [0,1] ∀𝑆 ∈ 𝑺 (37)
Il problema di PL (35) è risolubile in tempo polinomiale.
Sia 𝑥∗ = (𝑥∗(𝑆1), … , 𝑥∗(𝑆𝑚 )) il vettore soluzione che minimizza la funzione obiettivo di (35) sotto i vincoli
(36) e (37), e sia OPTR il valore (minimo) della funzione obiettivo di (35) in corrispondenza al vettore x*. La
relazione che sussiste tra OPTR ed il valore OPT della soluzione ottima al sistema (35) è
OPTR ≤OPT (38)
Vediamo ora come sia possibile ottenere una soluzione al sistema di PL (32) (non necessariamente ottima,
ma per cui il valore della funzione obiettivo non si discosti troppo da quello ottimo) a partire da x*,
soluzione ottima del sistema (35).
Per ogni elemento e ∈ U sia f(e) = numero di insiemi S ∈ S che contengono e, e sia 𝑓 = 𝑚𝑎𝑥 𝑒∈𝑈 𝑓(𝑒):
Definiamo quindi il vettore 𝑥 = (𝑥(𝑆1), … , 𝑥(𝑆𝑚 )) nel seguente modo
𝑥 𝑆𝑖 = 1 𝑠𝑒 𝑥∗(𝑆𝑖) ≥ 1
𝑓
0 𝑠𝑒 𝑥∗ 𝑆𝑖 < 1𝑓
(39)
In generale, la diseguaglianza della (38) può essere anche stretta. Consideriamo infatti il seguente esempio.
Sia U = {a, b, c}, S = {S1, S2, S3}, con S1 = {a, b}; S2 = {b, c}; S3 = {a, c}. Inoltre supponiamo che c(S1) = c(S2) =
c(S3) = 1 e sappiamo che il valore di 𝑓 = 𝑚𝑎𝑥 𝑒∈𝑈 𝑓 𝑒 = max 2,2,2 = 2. È impossibile coprire U con un
solo insieme, mentre lo è con due insiemi. Pertanto OPT = 2. È facile inoltre verificare che il vettore
𝑥 = (𝑥(𝑆1), 𝑥(𝑆2), 𝑥(𝑆3)) = (1/2, 1/2, 1/2) soddisfa i vincoli di (35). Pertanto,
𝑂𝑃𝑇𝑅 ≤ 𝑥 𝑆 𝑐 𝑆 = 12 + 1
2 + 12 = 3
2 < 2 = 𝑂𝑃𝑇
𝑆∈𝑺
In altri termini, stiamo proponendo il seguente algoritmo per il problema del Set Cover.
1. Risolvi il sistema di PL rilassato, sia 𝑥∗ 𝑙𝑎 𝑠𝑢𝑎 𝑠𝑜𝑙𝑢𝑧𝑖𝑜𝑛𝑒 𝑜𝑡𝑡𝑖𝑚𝑎
2. Output la famiglia 𝑆 ′ ⊆ 𝑺, dove 𝑆 ′ = 𝑆 ∈ 𝑺: 𝑥∗ 𝑆 ≥ 1𝑓
Proviamo innanzitutto che l'algoritmo produce un Set Cover , ovvero che il vettore 𝑥 = (𝑥(𝑆1), … , 𝑥(𝑆𝑚 ))
soddisfa i vincoli del sistema (32) (o, come si dice in gergo, che x è una soluzione ammissibile di (32).
Partiamo dal fatto che il vettore x* è soluzione ammissibile a (35). In particolare, ciò implica che
𝑥∗(𝑆) ≥ 1S:e∈S , ∀ e ∈ U. D'altra parte, dalla definizione del parametro f, si ha che la somma
𝑥∗(𝑆)S:e∈S contiene al più f termini, quindi esiste almeno un S che contiene e ∈ U e per cui x*(S) ≥ 1/f. Di
conseguenza, per la definizione iniziale di 𝑥 𝑆𝑖 (31) vale che ∀e ∈ U esiste almeno un S ∈ S che contiene e
e per cui il valore x(S) viene posto a 1. Ciò implica che S’ = ,S : x(S) = 1- = ,S ∈ S : x*(S) ≥1/f} è un Set Cover ,
ovvero che x(S) ≥ 1S:e∈𝐒 , per ogni e ∈ U. Che il vettore x soddisfa anche il vincolo di interezza è ovvio.
Valutiamo ora il costo della soluzione prodotta dall'algoritmo, ovvero valutiamo il valore della funzione
obiettivo del sistema (32) in corrispondenza al vettore x definito dalla (39). Ricordiamo che per definizione
abbiamo 𝑥(𝑆) ≤ 𝑓 ∙ 𝑥∗(𝑆), ∀𝑆 ∈ 𝑺. Si ha quindi
𝑆𝑂𝐿 = 𝑥 𝑆 𝑐(𝑆)
𝑠∈𝒔
≤ 𝑓𝑥∗ 𝑆 𝑐(𝑆)
𝑠∈𝒔
= 𝑓 𝑥∗ 𝑆 𝑐(𝑆)
𝑠∈𝒔
= 𝑓𝑂𝑃𝑇𝑅 ≤ 𝑓𝑂𝑃𝑇
Il che implica che abbiamo ottenuto un algoritmo di approssimazione per Set Cover con fattore di
approssimazione pari a f (𝑓 = 𝑚𝑎𝑥 𝑒∈𝑈 𝑓 𝑒 𝑐𝑜𝑛 f(e) = numero di insiemi S ∈ 𝐒 che contengono e).
Algoritmi e Strutture Dati 2: Lezione 16 – Algoritmi di approssimazione tramite PL
59
In alcuni casi, tale fattore di approssimazione è migliore di quello derivato nella Lezione 12, mediante
l'algoritmo greedy.
La tecnica dell'arrotondamento della soluzione ottima alla versione rilassata di un problema di PL con
vincoli di interezza sulle variabili può ovviamente essere applicata anche in altre situazioni.
Consideriamo la seguente generalizzazione del problema del Set Cover.
Set MultiCover Input:
Insieme 𝑈 = {𝑒1 , … , 𝑒𝑛 } , famiglia 𝑺 = {𝑆1 , … , 𝑆𝑚 } con 𝑆𝑖 ⊆ 𝑈per i=1….m Funzione di costo𝑐: 𝑆 ∈ 𝑺 → 𝑐 𝑆 ∈ 𝑅+ 𝑒 𝑐 𝑠 ≥ 0; Vettore di interi 𝑎 = (𝑎𝑒1
, … , 𝑎𝑒𝑛)
Output: sottofamiglia 𝑺′ ⊆ 𝑺 di costo minimo 𝑐 𝑺′ = 𝑐(𝑆)𝑆 ∈𝑺′ minimo tale che ogni elemento 𝑒 ∈ 𝑈 appartenga ad almeno 𝑎𝑒 distinti insiemi in S’
Ritroviamo il problema del Set Cover nel caso in cui il vettore a sia a = (1,…, 1). Formuliamo Set MultiCover
come problema di PL. Avremo
𝑚𝑖𝑛𝑖𝑚𝑖𝑧𝑧𝑎𝑟𝑒 𝑥 𝑆 𝑐 𝑆
𝑆 ∈𝑺
40
𝑠𝑜𝑔𝑔𝑒𝑡𝑡𝑜 𝑎 𝑥 𝑆 ≥ 𝑎𝑒
𝑆:𝑒 ∈𝑆
, ∀𝑒 ∈ 𝑈 (41)
𝑥 𝑆 ∈ 0,1 ∀𝑆 ∈ 𝑺 (42)
La versione rilassata del problema (40) sarà
𝑚𝑖𝑛𝑖𝑚𝑖𝑧𝑧𝑎𝑟𝑒 𝑥 𝑆 𝑐 𝑆
𝑆 ∈𝑺
43
𝑠𝑜𝑔𝑔𝑒𝑡𝑡𝑜 𝑎 𝑥 𝑆 ≥ 𝑎𝑒
𝑆:𝑒 ∈𝑆
, ∀𝑒 ∈ 𝑈 (44)
𝑥 𝑆 ∈ [0,1] ∀𝑆 ∈ 𝑺 (45)
Sia ora, come in precedenza, f = 𝑚𝑎𝑥𝑒∈𝑈 f(e), dove f(e) = numero di sottoinsiemi S in S che contengono e ∈
U. Sia 𝑥∗ = 𝑥∗ 𝑆1 , … , 𝑥∗ 𝑆𝑚 una soluzione ottima al problema (43) rilassato. Vale ovviamente che
𝑂𝑃𝑇𝑅 = 𝑥∗ 𝑆 𝑐(𝑆)
𝑆∈𝑺
≤ 𝑂𝑃𝑇 = 𝑥 𝑆 𝑐(𝑆)
𝑆∈𝑺
dove OPT è il valore ottimo del problema di PL originario (ovvero il costo di un Set MultiCover di costo
minimo). Definiamo il vettore 𝑥 = (𝑥(𝑆1), … , 𝑥(𝑆𝑚 )) nel seguente modo
∀ 𝑆 ∈ 𝑺, 𝑥 𝑆 = 1 𝑠𝑒 𝑥∗(𝑆) ≥ 1
𝑓
0 𝑠𝑒 𝑥∗ 𝑆 < 1𝑓
(46)
Il vettore x così definito è una soluzione ammissibile al sistema (40). Infatti, sappiamo che per ipotesi
𝑥 𝑆 ≥ 𝑎𝑒𝑆:𝑒 ∈𝑆 , ∀𝑒 ∈ 𝑈 ed inoltre ∀e ∈ U la somma 𝑥∗(𝑆) S:e∈S consta di al più f termini,
ciascheduno di valore al più 1. Pertanto, per ogni e ∈ U la somma 𝑥∗(𝑆) S:e∈S contiene almeno ae termini
di valore almeno pari a 1/f. Di conseguenza, il vettore x definito dalla (46) soddisfa la relazione
𝑥 𝑆 ≥ 𝑎𝑒
𝑆:𝑒 ∈𝑆
, ∀𝑒 ∈ 𝑈 (47)
inoltre vale che 𝑥(𝑆) ≤ 𝑓 ∙ 𝑥∗(𝑆), ∀𝑆 ∈ 𝑺. Quindi il costo della famiglia 𝐒′ = { S ∶ x(S) = 1 } (che è un
legittimo Set MultiCover in virtù della (47)) è pari a
𝑆𝑂𝐿 = 𝑐𝑜𝑠𝑡𝑜 𝑆 ′ = 𝑥 𝑆 𝑐(𝑆)
𝑠∈𝒔
≤ 𝑓𝑥∗ 𝑆 𝑐(𝑆)
𝑠∈𝒔
= 𝑓 𝑥∗ 𝑆 𝑐(𝑆)
𝑠∈𝒔
= 𝑓𝑂𝑃𝑇𝑅 ≤ 𝑓𝑂𝑃𝑇
Algoritmi e Strutture Dati 2: Lezione 16 – Algoritmi di approssimazione tramite PL
60
Hitting set Input:
Insieme 𝑈 = {𝑒1 , … , 𝑒𝑛 } , famiglia 𝑺 = {𝑆1 , … , 𝑆𝑚 } con 𝑆𝑖 ⊆ 𝑈per i=1….m Funzione di costo𝑐: 𝑒 ∈ 𝑈 → 𝑐 𝑒 ∈ 𝑅+ 𝑒 𝑐 𝑒 ≥ 0; Vettore di interi 𝑎 = (𝑎(𝑆1), … , 𝑎(𝑆𝑚 ))
Output: sottoinsieme 𝐻 ⊆ 𝑈 di costo minimo 𝑐 𝐻 = 𝑐(𝑒)𝑒 ∈𝐻 minimo tale 𝐻 ∩ 𝑆 ≥ 𝑎 𝑆 , ∀𝑆 ∈ 𝑺
Si noti che il problema è una generalizzazione del problema del Vertex Cover considerato all'inizio di questa
Lezione. Si ritrova infatti il problema del Vertex Cover nel caso in cui ciascun Si ∈ S ha cardinalità |Si|= 2, ed
il vettore a è composto da tutti 1.
∀ 𝑒 ∈ 𝑈 , 𝑥 𝑒 = 1 𝑠𝑒 𝑒 ∈ 𝐻0 𝑠𝑒 𝑒 ∉ 𝐻
Vogliamo derivare un algoritmo di approssimazione per Hitting Set con fattore di approssimazione k, dove
𝑘 = 𝑚𝑎𝑥𝑆∈𝑺 |𝑆| (la taglia dell’insieme più grande). Per prima cosa formuliamo il problema mediante la PL.
𝑚𝑖𝑛𝑖𝑚𝑖𝑧𝑧𝑎𝑟𝑒 𝑥 𝑒 𝑐 𝑒
𝑒 ∈𝑈
48
𝑠𝑜𝑔𝑔𝑒𝑡𝑡𝑜 𝑎 𝑥 𝑒 ≥ 𝑎(𝑆)
𝑒 ∈𝑆
, ∀𝑆 ∈ 𝑺 (49)
𝑥 𝑒 ∈ 0,1 ∀𝑒 ∈ 𝑈 (50)
La versione rilassata del problema (48) sarà
𝑚𝑖𝑛𝑖𝑚𝑖𝑧𝑧𝑎𝑟𝑒 𝑥 𝑒 𝑐 𝑒
𝑒 ∈𝑈
51
𝑠𝑜𝑔𝑔𝑒𝑡𝑡𝑜 𝑎 𝑥 𝑒 ≥ 𝑎(𝑆)
𝑒 ∈𝑆
, ∀𝑆 ∈ 𝑺 (52)
𝑥 𝑒 ∈ [0,1] ∀𝑒 ∈ 𝑈 (53)
Sia 𝑥∗ = 𝑥∗ 𝑒1 , … , 𝑥∗ 𝑒𝑛 una soluzione ottima al problema (51) rilassato. Vale ovviamente che
𝑂𝑃𝑇𝑅 = 𝑥∗ 𝑒 𝑐 𝑒
𝑒 ∈𝑈
≤ 𝑂𝑃𝑇 = 𝑥 𝑒 𝑐 𝑒
𝑒 ∈𝑈
dove OPT è il valore ottimo del problema di PL originario (ovvero il costo di un Hitting Set di costo minimo).
Definiamo il vettore 𝑥 = (𝑥(𝑒1), … , 𝑥(𝑒𝑛)) nel seguente modo
∀ 𝑒 ∈ 𝑈, 𝑥 𝑒 = 1 𝑠𝑒 𝑥∗(𝑒) ≥ 1
𝑘
0 𝑠𝑒 𝑥∗ 𝑒 < 1𝑘
(54)
con 𝑘 = 𝑚𝑎𝑥𝑆∈𝑺 |𝑆|. Il vettore x così definito è una soluzione ammissibile al sistema (48). Infatti, sappiamo
che per ipotesi 𝑥∗ 𝑒 𝑒 ∈𝑆 ≥ 𝑎(𝑆), ∀𝑆 ∈ 𝑺 e tale somma consta di al più k termini, ciascheduno di valore
al più 1. Pertanto la somma contiene almeno a(S) termini di valore almeno pari a 1/k. Infatti, se ciò non
fosse, ovvero se la somma contenesse al più a(S) - 1 termini di valore almeno pari a 1/k, avremmo che
𝑥∗ 𝑒
𝑒 ∈𝑆
= 𝑥∗ 𝑒
𝑒 ∈𝑆:𝑥∗ 𝑒 ≥1 𝑘
+ 𝑥∗ 𝑒
𝑒 ∈𝑆:𝑥∗ 𝑒 <1 𝑘
≤ 𝑎 𝑆 − 1 + 𝑥∗ 𝑒
𝑒 ∈𝑆:𝑥∗ 𝑒 <1 𝑘
𝑖𝑛 𝑞𝑢𝑎𝑛𝑡𝑜 𝑜𝑔𝑛𝑖 𝑒𝑙𝑒𝑚𝑒𝑛𝑡𝑜 𝑑𝑒𝑙𝑙𝑎 𝑠𝑜𝑚𝑚𝑎 è ≤ 1
< 𝑎 𝑆 − 1 + 1(𝑖𝑛 𝑞𝑢𝑎𝑛𝑡𝑜 𝑙𝑎 𝑠𝑜𝑚𝑚𝑎 𝑐𝑜𝑛𝑡𝑖𝑒𝑛𝑒 𝑎𝑙 𝑝𝑖ù 𝑘 𝑡𝑒𝑟𝑚𝑖𝑛𝑖) = 𝑎(𝑆)
Per quanto appena provato, il vettore x definito dalla (54) soddisfa la relazione 𝑥 𝑒 ≥ 𝑎(𝑆)𝑒 ∈𝑆 , ∀𝑆 ∈ 𝑺
inoltre vale che 𝑥(𝑒) ≤ 𝑘𝑥 ∗ (𝑒), ∀𝑒 ∈ 𝑈. Quindi il costo dell'insieme 𝐻 = 𝑒 ∶ 𝑥(𝑒) = 1 (che è un
legittimo Hitting Set in virtù della (60)) è pari a
𝑐 𝐻 = 𝑥 𝑒 𝑐 𝑒
𝑒 ∈𝑈
≤ 𝑘 𝑥∗ 𝑒 𝑐 𝑒
𝑒 ∈𝑈
= 𝑘 𝑥∗ 𝑒 𝑐 𝑒
𝑒 ∈𝑈
= 𝑘𝑂𝑃𝑇𝑅 ≤ 𝑘𝑂𝑃𝑇
Algoritmi e Strutture Dati 2: Lezione 16 – Algoritmi di approssimazione tramite PL
61
Concludiamo la lezione riassumendo il principio generale mediante il quale abbiamo ottenuto gli algoritmi
di approssimazione descritti in questa lezione:
formulare il problema di ottimizzazione come un problema di PL,
rilassare i vincoli di interezza ed ottenere un problema di PL risolubile in tempo polinomiale,
arrotondare a valori interi le componenti della soluzione ottima al problema di PL rilassato per
ottenere una soluzione ammissibile al problema originale.
La bontà (o meno) della soluzione al problema originale così ottenuta dipende in maniera critica da che
criterio si è usato per arrotondare la soluzione ottime del problema rilassato. Il criterio usato in questa
lezione è molto semplice ed intuitivo, ma ha portata limitata (ovvero non sempre produce soluzioni intere
di “buon” valore). Nella lezione prossima vedremo una tecnica di arrotondamento di più ampia
applicabilità.
Nelle dispense è stato precisato che non è dato che la tecnica di arrotondamento è migliore di quelle viste
nelle lezioni precedenti e che non è dato il viceversa. Quindi bisogna usare le due tecniche studiate e
bisogna individuare la migliore relativamente al caso da analizzare.
Esercizi d’esame
Insiemi dominanti
Input: grafo G: (V,E)
Output: D⊆ 𝑉 di cardinalità minima t.c. ∀𝑢 ∈ 𝑉 o vale che 𝑢 ∈ 𝐷 oppure ∃𝑣 ∈ 𝐷 t.c. (u,v)∈ 𝐸
V={1,...,n}
x= (𝑥1 , … , 𝑥𝑚 )
x:= 1 𝑠𝑒 𝑖 ∈ 𝐷0 𝑎𝑙𝑡𝑟𝑖𝑚𝑒𝑛𝑡𝑖
min 𝑥𝑖𝑛𝑖=1
Il vincolo è ∀𝑢 ∈ 𝑉 … , quindi, il vincolo si riferisce ad ogni vertice e non ad ogni coppia.
Quindi 𝑥𝑖≥1 oppure per qualche suo vicino j tale che 𝑥𝑗 ≥1 ∀𝑖 ∈ 𝑉 il vincolo non può essere sulle coppie;
sulle coppie si deriva la condizione (come Vertex Cover).
Fino ad ora troppe parole, quindi
o 𝑥𝑖 ≥ 1 oppure 𝑥𝑗 ≥ 1𝑗 𝑣𝑖𝑐𝑖𝑛𝑖 𝑑𝑖 𝑖 ∀𝑖 ∈ 𝑉
Ora togliamo
𝑥𝑖 + 𝑥𝑗 ≥ 1𝑗 𝑣𝑖𝑐𝑖𝑛𝑖 𝑑𝑖 𝑖 ∀𝑖 ∈ 𝑉
𝑥𝑖 ∈ 0,1 ∀𝑖 ∈ 𝑉
Quindi quando si fanno gli esercizi è consigliato iniziare con le parole e poi passare alle formule.
Ora bisogna procedere con rilassamento e arrotondamento.
Per trovare la soglia(che è un parametro) tenere presente #sicuri+1.
Per Vertex Cover prendiamo il vertice con il maggiore numero di vicini.
𝛥 = max # 𝑑𝑖 𝑣𝑖𝑐𝑖𝑛𝑖 𝑑𝑖 𝑜𝑔𝑛𝑖 𝑣𝑒𝑟𝑡𝑖𝑐𝑒
x:= 1 𝑠𝑒 𝑥 ∗ ≥
1
𝛥+ 1
0 𝑎𝑙𝑡𝑟𝑖𝑚𝑒𝑛𝑡𝑖
N°2
Input: grafo G:(V,E)
Output: M⊆ 𝐸, di cardinalità max che sia un matching ∀𝑢 ∈ 𝑉 il # di archi incidenti
su U è S
Questo è solo un esercizio per la formalizzazione
E={𝑒1 , … , 𝑒𝑚 }
Algoritmi e Strutture Dati 2: Lezione 16 – Algoritmi di approssimazione tramite PL
62
x={𝑥1 , … , 𝑥𝑚 }
𝑥𝑖= 1 𝑠𝑒 𝑒𝑖 ∈ 𝑀0 𝑠𝑒 𝑒𝑖 ∉ 𝑀
max 𝑥𝑖𝑚𝑖=1 = quello che vogliamo massimizzare
La somma di tutti gli archi incidenti ∀𝑢 ∈ 𝐸
𝑥𝑖 ∈ 0,1 ∀𝑒𝑖 ∈ 𝐸
NOTA:
I problemi di massimo si possono tradurre in duali di minimo e viceversa, prima di procedere, questo lo
vedremo in seguito. È importantissimo inventarsi gli esercizi.
Algoritmi e Strutture Dati 2: Lezione 17 – Problemi con PL ed arrotondamento probabilistico
63
Lezione 17 – Problemi con PL ed arrotondamento probabilistico
Nella lezione scorsa abbiamo visto come esso possa essere implementato, in alcuni casi, arrotondando a
valori interi le componenti della soluzione ottima al problema rilassato. Come effettuare l'arrotondamento
dipende criticamente dal problema in questione. In questa lezione vedremo un criterio abbastanza
generale su come effettuare l'arrotondamento. Supponiamo di avere a disposizione una funzione random(∙)
così definita:
random:p ∈ *0; 1+ → random(p) ∈ {0; 1}
random(p) = 1 con probabilità p
random(p) = 0 con probabilità 1 - p.
La tecnica in questione per convertire una soluzione ottima al problema di PL rilassato in una “buona"
soluzione al problema di PL a vincoli interi è la seguente
Arrotondamento probabilistico
1. Formula il problema in esame mediante un sistema di PL a vincoli interi e con variabili 𝑥𝑖 ∈ {0,1} nella funzione obiettivo
2. Rilassa il problema, risolvilo ottimalmente e siano 𝑥𝑖∗ ∈ [0,1] i valori del vettore ottimo di
soluzione 3. Assegna valori interi alle variabili 𝑥𝑖 nel modo seguente
𝑖𝑓 𝑟𝑎𝑛𝑑𝑜𝑚 𝑥𝑖∗ = 1 𝑡𝑒𝑛 𝑥𝑖 = 1
𝑒𝑙𝑠𝑒 𝑥𝑖 = 0
In altri termini, interpretiamo i valori xi* come probabilità di porre le variabili xi a 0 oppure a 1 nel sistema
di PL a vincoli interi. Il passo successivo consiste nello stimare di quanto il valore della soluzione intera si
discosta da OPTR.
Set Cover Input:
Insieme 𝑈 = {𝑒1 , … , 𝑒𝑛 } , famiglia 𝑺 = {𝑆1 , … , 𝑆𝑘} con 𝑆𝑖 ⊆ 𝑈per i=1….k Funzione di costo𝑐: 𝑆 ∈ 𝑺 → 𝑐 𝑆 ∈ 𝑅+ 𝑒 𝑐 𝑠 ≥ 0;
Output: sottofamiglia 𝑺′ ⊆ 𝑺 di costo minimo 𝑐 𝑺′ = 𝑐(𝑆)𝑆 ∈𝑺′ minimo tale che 𝑆 ⊇ 𝑈𝑆 ∈𝑺′
la sua formulazione via PL a vincoli interi
𝑚𝑖𝑛𝑖𝑚𝑖𝑧𝑧𝑎𝑟𝑒 𝑥 𝑆 𝑐 𝑆
𝑆 ∈𝑺
61
𝑠𝑜𝑔𝑔𝑒𝑡𝑡𝑜 𝑎 𝑥 𝑆 ≥ 1
𝑆:𝑢 ∈𝑆
, ∀𝑢 ∈ 𝑈 (62)
𝑥 𝑆 ∈ 0,1 ∀𝑆 ∈ 𝑺 (63)
e la corrispondente versione rilassata del problema di PL
𝑚𝑖𝑛𝑖𝑚𝑖𝑧𝑧𝑎𝑟𝑒 𝑥 𝑆 𝑐 𝑆
𝑆 ∈𝑺
64
𝑠𝑜𝑔𝑔𝑒𝑡𝑡𝑜 𝑎 𝑥 𝑆 ≥ 1
𝑆:𝑢 ∈𝑆
, ∀𝑢 ∈ 𝑈 (65)
𝑥 𝑆 ∈ [0,1] ∀𝑆 ∈ 𝑺 (66)
Sia 𝑥∗ = 𝑥∗ 𝑆1 , … , 𝑥∗ 𝑆𝑚 una soluzione ottima al problema rilassato (64). In accordo allo schema di
algoritmo prima enunciato, costruiamo una possibile soluzione intera al sistema (61), ponendo la i-esima
variabile a 1 con probabilità pari al valore 𝑥∗ 𝑆𝑖 , ed a 0 con probabilità pari a 1 – 𝑥∗ 𝑆𝑖 . In altri termini,
stiamo costruendo una possibile soluzione S’ ⊆ S al problema del Set Cover inserendo l'insieme Si in S’ con
probabilità pari a 𝑥∗ 𝑆𝑖 , per ogni i = 1,…,m. Di conseguenza, il costo medio 𝐸[𝑐(𝑆’)] della soluzione S’ ⊆ S
è:
Algoritmi e Strutture Dati 2: Lezione 17 – Problemi con PL ed arrotondamento probabilistico
64
𝐸 𝑐 𝑆 ′ = 𝑐 𝑆 Pr 𝑆 𝑠𝑖𝑎 𝑠𝑡𝑎𝑡𝑜 𝑖𝑛𝑠𝑒𝑟𝑖𝑡𝑜 𝑖𝑛 𝑆 ′
𝑆 ∈𝑺
= 𝑐 𝑆 𝑥∗ 𝑆 = 𝑂𝑃𝑇𝑅 ≤ 𝑂𝑃𝑇
𝑆 ∈𝑺
Stimiamo ora la probabilità che S’ sia effettivamente un cover, ovvero stimiamo la probabilità che valga
l'evento 𝑈 ⊆ 𝑆𝑆 ∈𝑺′ .
Dato un generico u ∈ U, siano Si1 ,…,Sik tutti e solo gli elementi di S’ che contengono u. Avremo allora
𝑃𝑟 {𝑢 𝑠𝑖𝑎 𝑐𝑜𝑝𝑒𝑟𝑡𝑜 𝑑𝑎 𝑆’} = 1 – 𝑃𝑟 {𝑢 𝑛𝑜𝑛 𝑠𝑖𝑎 𝑐𝑜𝑝𝑒𝑟𝑡𝑜 𝑑𝑎 𝑆’}
= 1 – 𝑃𝑟 {𝑛𝑒𝑠𝑠𝑢𝑛 𝑖𝑛𝑠𝑖𝑒𝑚𝑒 𝑆𝑖𝑗 ; 𝑗 = 1; … ; 𝑘 è 𝑠𝑡𝑎𝑡𝑜 𝑖𝑛𝑠𝑒𝑟𝑖𝑡𝑜 𝑖𝑛 𝑆’}
= 1 – 𝑃𝑟 {𝑆𝑖1 𝑛𝑜𝑛 è 𝑠𝑡𝑎𝑡𝑜 𝑖𝑛𝑠𝑒𝑟𝑖𝑡𝑜 𝑖𝑛 𝑆’} ∙ … .
… . .∙ 𝑃𝑟 𝑆𝑖𝑘 𝑛𝑜𝑛 è 𝑠𝑡𝑎𝑡𝑜 𝑖𝑛𝑠𝑒𝑟𝑖𝑡𝑜 𝑖𝑛 𝑆’ = (1 − Pr(𝑆𝑖𝑗 ∉ 𝑆′)
𝑘
𝑗 =1
)
= 1 − 1 − 𝑥∗ 𝑆𝑖1 1 − 𝑥∗ 𝑆𝑖2 … 1 − 𝑥∗ 𝑆𝑖𝑘 = 1 − (1 − 𝑥∗(Sij ))
𝑘
𝑗 =1
.
Ricordiamo ora che i valori 𝑥∗ (Si1 ), 𝑥∗ (Si2),…, 𝑥∗ (Sik ) soddisfano la condizione 𝑥∗ 𝑆𝑖𝑗 𝑘𝑗=1 ≥ 1,
ciò in quanto gli insiemi Si1, Si2,… ,Sik sono tutti e solo quelli che contengono u ∈ U, e pertanto i valori
𝑥∗ (Si1 ), 𝑥∗ (Si2 ), …, 𝑥∗ (Sik ) soddisfano la (65), quindi 𝑆𝑖𝑗 può contenere u con probabilità 1
𝑘 . Sotto tale
ipotesi, faremo vedere che
1 − 𝑥∗ 𝑆𝑖1 1 − 𝑥∗ 𝑆𝑖2 … 1 − 𝑥∗ 𝑆𝑖𝑘 ≤ 1 −1
𝑘 𝑘
(67), quindi
Pr 𝑢 𝑛𝑜𝑛 𝑠𝑖𝑎 𝑐𝑜𝑝𝑒𝑟𝑡𝑜 𝑑𝑎 𝑆 ′ ≤ 1 −1
𝑘 𝑘
≤1
𝑒
Per il momento, assumiamo che la diseguaglianza di sopra valga, pertanto abbiamo che
Pr 𝑢 𝑠𝑖𝑎 𝑐𝑜𝑝𝑒𝑟𝑡𝑜 𝑑𝑎 𝑆 ′ ≥ 1 − 1 −1
𝑘 𝑘
≥ 1 −1
𝑒
Ripetiamo d log n volte l'esperimento casuale di scegliere S’ in accordo alle probabilità x*(Si), dove d è
scelto in modo tale che 1
𝑒 𝑑 𝑙𝑜𝑔 𝑛
≤1
4𝑛. In altre parole, costruiamo indipendentemente l'una dall'altra
𝑑 𝑙𝑜𝑔 𝑛 sottofamiglie S’1 ,…, S’d log n, dove la probabilità che il generico insieme Si ∈ S venga inserito nella
generica sottofamiglia S’t, è sempre x*(Si), per ogni i = 1,…,m e per ogni t = 1,…,d logn. Sia infine 𝐶 = 𝑆’1 ∪
… ∪ 𝑆’𝑑𝑙𝑜𝑔𝑛 .
Dato un generico elemento u ∈ U, avremo che (sto ripetendo l’esperimento d log n volte)
Pr 𝑢 𝑛𝑜𝑛 è 𝑐𝑜𝑝𝑒𝑟𝑡𝑜 𝑑𝑎 𝐶 = Pr 𝑢 𝑛𝑜𝑛 è 𝑐𝑜𝑝𝑒𝑟𝑡𝑜 𝑑𝑎 𝑛𝑒𝑠𝑠𝑢𝑛 𝑆’𝑖 , 𝑖 = 1, … , 𝑑𝑙𝑜𝑔 𝑛
= Pr{𝑢 𝑛𝑜𝑛 è 𝑐𝑜𝑝𝑒𝑟𝑡𝑜 𝑑𝑎 𝑆’𝑖}
𝑑 log 𝑛
𝑖=1
≤ 1
𝑒
𝑑 log 𝑛
𝑖=1
= 1
𝑒 𝑑𝑙 𝑜𝑔 𝑛
=1
𝑒𝑑 log 𝑛=
1
𝑑𝑛
≤1
4𝑛 (𝑝𝑒𝑟 𝑐𝑜𝑚𝑒 𝑎𝑏𝑏𝑖𝑎𝑚𝑜 𝑠𝑐𝑒𝑙𝑡𝑜 𝑑)
Di conseguenza, la probabilità che C non sia un cover per U è
𝑃𝑟 𝐶 𝑛𝑜𝑛 è 𝑢𝑛 𝑐𝑜𝑣𝑒𝑟 𝑝𝑒𝑟 𝑈 = Pr 𝑢𝑖 𝑛𝑜𝑛 è 𝑐𝑜𝑝𝑒𝑟𝑡𝑜 𝑑𝑎 𝐶, 𝑝𝑒𝑟 𝑞𝑢𝑎𝑙𝑐𝑒 𝑖 = 1, . . , 𝑛
≤ Pr 𝑢𝑖 𝑛𝑜𝑛 è 𝑐𝑜𝑝𝑒𝑟𝑡𝑜 𝑑𝑎 𝐶
𝑛
1
≤ 1
4𝑛
𝑛
𝑖=1
=1
4
Inoltre, il costo medio 𝐸[𝑐(𝐶)] di C soddisfa
𝐸 𝑐 𝐶 = 𝐸 𝑐 𝑆𝑖′
𝑑 log 𝑛
𝑖=1
≤ 𝑑 log 𝑛 𝑂𝑃𝑇𝑅
Algoritmi e Strutture Dati 2: Lezione 17 – Problemi con PL ed arrotondamento probabilistico
65
dove abbiamo usato il fatto che la media di una somma di variabili casuali è la somma delle medie delle
singole variabili casuali. Ricordiamo ora la diseguaglianza di Markov, la quale afferma che data una variabile
casuale X, con media E[X] ed un valore t, vale:
Pr 𝑋 ≥ 𝑡 ≤𝐸[𝑋]
𝑡
Applicando la diseguaglianza di Markov alla variabile casuale c(C), con t = 4d log n OPTR, otteniamo
Pr 𝑐 𝐶 ≥ 4𝑑 log 𝑛 𝑂𝑃𝑇𝑅 ≤𝐸[𝑐(𝐶)]
4𝑑 log 𝑛 𝑂𝑃𝑇𝑅=
1
4
Mettendo tutto insieme possiamo valutare la probabilità degli eventi a noi sfavorevoli, ovvero che C non sia
un cover o che C abbia un costo > 4d log n OPTR. Avremo quindi
Pr 𝐶 𝑛𝑜𝑛 è 𝑢𝑛 𝑐𝑜𝑣𝑒𝑟 𝑝𝑒𝑟 𝑈 𝑜𝑝𝑝𝑢𝑟𝑒 𝑎𝑏𝑏𝑖𝑎 𝑐𝑜𝑠𝑡𝑜 𝑐 𝐶 ≥ 4𝑑𝑙𝑜𝑔 𝑛 𝑂𝑃𝑇𝑅
≤ Pr 𝐶 𝑛𝑜𝑛 è 𝑢𝑛 𝑐𝑜𝑣𝑒𝑟 𝑝𝑒𝑟 𝑈 + Pr 𝑐 𝐶 ≥ 4𝑑𝑙𝑜𝑔 𝑛 𝑂𝑃𝑇𝑅 ≤1
4+
1
4=
1
2
Di conseguenza, la probabilità che l'algoritmo ci dia l'output che noi desideriamo, ovvero che C sia un cover
e che contemporaneamente abbia un costo ≤ 4d log nOPTR è pari a 1 meno la probabilità di sopra, ovvero è
almeno 1/2. Quindi, la probabilità che le scelte casuali effettuate dall'algoritmo abbiano prodotto un cover
di U di costo totale ≤ 4d log nOPTR è almeno 1/2.
Pr(𝑠𝑢𝑐𝑐𝑒𝑠𝑠𝑜) ≥ 1/2
Ciò implica che il numero medio di volte che dobbiamo eseguire l'algoritmo per avere il cover di U che
desideriamo, ovvero di costo ≤ 4d log nOPTR, è al più 2. Questo conclude la prova che l'arrotondamento
probabilistico produce un Set Cover di U di costo O(log n)OPTR ≤ O(log n)OPT, quindi confrontabile con il
costo della soluzione prodotta dall'algoritmo greedy che, ricordiamo, era limitato superiormente da
(log n + 1)OPT.
Prova della diseguaglianza di Markov per variabili casuali discrete.
Supponiamo che la variabile casuale X assuma al più n valori. Si ha che
𝐸 𝑋 = 𝑘 Pr{𝑋 = 𝑘}
𝑛
𝑘=1
≥ 𝑘 Pr{𝑋 = 𝑘}
𝑛
𝑘=𝑡
≥ 𝑡 Pr{𝑋 = 𝑘}
𝑛
𝑘=𝑡
= 𝑡𝑃𝑟{𝑋 ≥ 𝑡}
Prova: Vogliamo massimizzare 1 − 𝑥𝑖 𝑘𝑖=0 𝑠𝑜𝑡𝑡𝑜 𝑖𝑙 𝑣𝑖𝑛𝑐𝑜𝑙𝑜 𝑐𝑒 𝑥𝑖
𝑘𝑖=0 ≥ 1 . 𝑆𝑖 𝑎
1
𝑘𝑙𝑜𝑔 1 − 𝑥𝑖
𝑘
𝑖=0
=1
𝑘 log(1 − 𝑥𝑖)
𝑘
𝑖=0
≤ 𝑙𝑜𝑔1
𝑘 log(1 − 𝑥𝑖)
𝑘
𝑖=0
𝑑𝑎𝑙𝑙𝑎 𝑑𝑖𝑠𝑒𝑔𝑢𝑎𝑙𝑖𝑔𝑎𝑛𝑧𝑎 𝑑𝑖 𝐽𝑒𝑛𝑠𝑒𝑛
= 𝑙𝑜𝑔𝑘 − log(1 − 𝑥𝑖)
𝑘𝑖=0
𝑘= log 1 −
1
𝑘
𝑂𝑣𝑣𝑒𝑟𝑜 𝑙𝑜𝑔 1 − 𝑥𝑖
𝑘
𝑖=0
≤ 𝑘 log 1 −1
𝑘 = log 1 −
1
𝑘 𝑘
𝑖𝑙 𝑐𝑒 è 𝑝𝑒𝑟𝑓𝑒𝑡𝑡𝑎𝑚𝑒𝑛𝑡𝑒 𝑒𝑞𝑢𝑖𝑣𝑎𝑙𝑒𝑛𝑡𝑒 𝑎 𝑐𝑖ò 𝑐𝑒 𝑖𝑛𝑡𝑒𝑛𝑑𝑒𝑣𝑎𝑚𝑜 𝑝𝑟𝑜𝑣𝑎𝑟𝑒
MaxSat Input:
n variabili booleane 𝑥1 , … , 𝑥𝑛 m clausole 𝐶1 , … , 𝐶𝑚 dove 𝐶𝑖 è un OR di letterali, ovvero 𝐶𝑖 = 𝛼𝑖1
∨ …∨ 𝛼𝑖𝑘 , ed ogni 𝛼𝑖𝑗 è una
qualunque variabile booleana 𝑥𝑠 od un suo negato pesi 𝑤(𝐶𝑖) ≥ 0 per ogni clausola 𝐶𝑖
Output: un assegnamento di valori di verità VERO/FALSO alle 𝑥𝑖 che massimizzi la somma dei pesi delle
clausole 𝐶𝑖 soddisfatte.
Ricordiamo i 3 passi costituenti la tecnica dell'arrotondamento probabilistico, ed applichiamoli a MaxSat .
Algoritmi e Strutture Dati 2: Lezione 17 – Problemi con PL ed arrotondamento probabilistico
66
Passo 1. Modelliamo MaxSat con il seguente problema di PL a variabili intere, in cui introduciamo una
variabile z(C) per ogni clausola C, ed una variabile yi per ogni variabile booleana xi. Il significato delle
variabili z(C) e yi è il solito
∀ 𝐶 𝑧 𝐶 = 1 𝑠𝑒 𝐶 è 𝑠𝑜𝑑𝑑𝑖𝑠𝑓𝑎𝑡𝑡𝑎 0 𝑠𝑒 𝐶 𝑛𝑜𝑛 è 𝑠𝑜𝑑𝑑𝑖𝑠𝑓𝑎𝑡𝑡𝑎
∀ 𝑦 𝑦𝑖 = 1 𝑠𝑒 𝑥𝑖 𝑎 𝑣𝑎𝑙𝑜𝑟𝑒 𝑑𝑖 𝑣𝑒𝑟𝑖𝑡à 𝑉𝐸𝑅𝑂 0 𝑠𝑒 𝑥𝑖 𝑎 𝑣𝑎𝑙𝑜𝑟𝑒 𝑑𝑖 𝑣𝑒𝑟𝑖𝑡à 𝐹𝐴𝐿𝑆𝑂
Inoltre, per ogni clausola C, sia I+(C) l'insieme degli indici i delle variabili booleane xi che compaiono in C in
forma non negata, e sia analogamente I-(C) l'insieme degli indici j delle variabili booleane xj che compaiono
in C in forma negata. Pertanto, la clausola C è soddisfatta se e solo se almeno una delle variabili xi con i ∈
I+(C) assume valore VERO, oppure almeno una delle variabili xj con j ∈ I-(C) assume valore FALSO.
Ricordando le definizioni delle variabili z(C) e yi, avremo che z(C) = 1 se e solo se almeno una delle variabili
yi con i ∈ I+(C) assume valore 1, oppure almeno una delle variabili yi con i ∈ I+(C) assume valore 0.
Avremo allora il seguente sistema di PL che formalizza il problema MaxSat
𝑚𝑎𝑠𝑠𝑖𝑚𝑖𝑧𝑧𝑎𝑟𝑒 𝑤 𝐶 𝑧 𝐶
𝐶
68
𝑠𝑜𝑔𝑔𝑒𝑡𝑡𝑜 𝑎 𝑦𝑖
𝑖∈𝐼+(𝐶)
+ (1 − 𝑦𝑖)
𝑖∈𝐼−(𝐶)
≥ 𝑧 𝐶 , ∀𝐶 69
𝑦𝑖 ∈ 0,1 ∀𝑖 (70)
0 ≤ 𝑧(𝐶) ≤ 1 ∀𝐶 (71)
Passo 2. Rilassa i vincoli yi ∈ {0; 1} con ∀i a 0 ≤ yi ≤1.
Passo 3. Applicando la tecnica dell'arrotondamento probabilistico otteniamo il seguente Algoritmo
Arrotondamento probabilistico per MAX SAT
Risolvi il sistema (68), sia (𝒚∗, 𝒛∗) la soluzione ottima For i=1 to n do
If (random (𝑦∗𝑖) =1)
𝑥𝑖 = 1 else
𝑥𝑖 = 0 In altri termini, nel precedente algoritmo interpretiamo ciascun valore y*i come la probabilità di porre la
variabile booleana xi ad 1 (ovvero, a valore TRUE).
𝑧∗ 𝐶 𝑤 𝐶
𝑐
= 𝑂𝑃𝑇𝑅 𝑒𝑑 𝑆𝑂𝐿 = 𝑤 𝐶
𝐶 𝑠𝑜𝑑𝑑𝑖𝑠𝑓𝑎𝑡𝑡𝑒
Per definizione, avremo che la clausola C non sarà soddisfatta se e solo se tutte le variabili con indici in I+(C)
sono state poste a valore 0 e tutte le variabili con indici in I-(C) a valore 1. Abbiamo quindi
Pr 𝐶 𝑠𝑜𝑑𝑑𝑖𝑠𝑓𝑎𝑡𝑡𝑎 = 1 − Pr 𝐶 𝑛𝑜𝑛 è 𝑠𝑜𝑑𝑑𝑖𝑠𝑓𝑎𝑡𝑡𝑎 = 1 − 1 − 𝑦𝑗∗
𝑗∈𝐼+ 𝐶
∙ 𝑦𝑗∗
𝑗∈𝐼− 𝐶
(72)
Per valutare in maniera precisa la espressione (72) abbiamo bisogno di alcuni risultati intermedi.
Supponiamo di avere un insieme di numeri S, con |S| = k, e sia data una partizione di S in due insiemi
𝐴, 𝐵 ⊆ 𝑆, con 𝐴 𝑈 𝐵 = 𝑆, 𝑒 𝐴 ∩ 𝐵 = ∅. Supponiamo che valga
𝑎
𝑎∈𝐴
+ (1 − 𝑏)
𝑏∈𝐵
≥ 𝑧 73 , 𝑝𝑒𝑟 𝑞𝑢𝑎𝑙𝑐𝑒 𝑛𝑢𝑚𝑒𝑟𝑜 𝑧. 𝐴𝑙𝑙𝑜𝑟𝑎 𝑣𝑎𝑙𝑒 𝑎𝑛𝑐𝑒
𝑘 − 𝑧 ≥ 𝑎
𝑎∈𝐴
+ (1 − 𝑏)
𝑏∈𝐵
= 1
𝑎∈𝐴
+ 1
𝑏∈𝐵
− 𝑎
𝑎∈𝐴
− (1 − 𝑏)
𝑏∈𝐵
= (1 − 𝑎)
𝑎∈𝐴
+ (1 − 1 + 𝑏)
𝑏∈𝐵
= (1 − 𝑎)
𝑎∈𝐴
+ 𝑏
𝑏∈𝐵
Ricordando la diseguaglianza tra la media aritmetica e geometrica, che ci dice
Algoritmi e Strutture Dati 2: Lezione 17 – Problemi con PL ed arrotondamento probabilistico
67
𝛽𝑖𝑘𝑖=1
𝑘≥ 𝛽𝑖
𝑘
𝑖=1
1𝑘
, ∀𝛽𝑖 , 𝑜𝑡𝑡𝑒𝑛𝑖𝑎𝑚𝑜 𝑘 − 𝑧
𝑘≥
1
𝑘 (1 − 𝑎)
𝑎∈𝐴
+ 𝑏
𝑏∈𝐵
≥ 1 − 𝑎
𝑎∈𝐴
∙ 𝑏
𝑏∈𝐴
1𝑘
𝑜𝑣𝑣𝑒𝑟𝑜 1 −𝑧
𝑘 𝑘
≥ 1 − 𝑎
𝑎∈𝐴
∙ 𝑏
𝑏∈𝐴
Ritorniamo al nostro problema originario ed applichiamo i risultati appena ottenuti. Abbiamo che
Pr 𝐶 𝑠𝑜𝑑𝑑𝑖𝑠𝑓𝑎𝑡𝑡𝑎 = 1 − 1 − 𝑦𝑗∗
𝑗∈𝐼+ 𝐶
∙ 𝑦𝑗∗
𝑗∈𝐼− 𝐶
≥ 1 − 1 −𝑧∗ 𝐶
𝑘
𝑘
≥ 1 − 1
𝑒
𝑧∗ 𝐶
dove k è il numero di variabili nella clausola C. Possiamo osservare che per valori di x compresi tra 0 ed 1 la
curva di equazione 1 − 1
𝑒
𝑥 è sempre maggiore della retta di equazione 1 −
1
𝑒 𝑥 (vedi figura).
PertantoPr 𝐶 𝑠𝑜𝑑𝑑𝑖𝑠𝑓𝑎𝑡𝑡𝑎 ≥ 1 −1
𝑒 𝑧∗ 𝐶
Il costo medio della soluzione prodotta dall'algoritmo, ovvero il valor medio E della somma dei pesi delle
clausole soddisfatte in conseguenza dell'assegnamento di valori di verità sopra definito sarà quindi
𝐸 = 𝐶 𝑠𝑜𝑑𝑑𝑖𝑠𝑓𝑎𝑡𝑡𝑎 𝑤(𝐶)
𝐶
≥ 1 − 1
𝑒 𝑤(𝐶)𝑧∗ 𝐶
𝐶
= 1 −1
𝑒 𝑂𝑃𝑇𝑅 ≥ 1 −
1
𝑒 𝑂𝑃𝑇
Concludendo, l'algoritmo basato sulla tecnica dell'arrotondamento probabilistico produce una soluzione
che si discosta da quella ottima di un fattore moltiplicativo pari a 1 −1
𝑒 . Ci limitiamo qui a menzionare
che molti degli algoritmi ottenibili con la tecnica dell'arrotondamento probabilistico possono essere
“derandomizzati”, ovvero possono essere trasformati in algoritmi completamente deterministici, senza
alcuna perdita di performance.
Algoritmi e Strutture Dati 2: Lezione 18 – Principio della dualità in programmazione lineare
68
Lezione 18 – Principio della dualità in programmazione lineare
Nelle lezioni scorse abbiamo visto varie applicazione della PL al progetto di algoritmi di approssimazione
per problemi di ottimizzazione NP-hard. Essenzialmente abbiamo visto che in certi casi, arrotondando a
valori interi la soluzione ottima del sistema di PL rilassato, si poteva ottenere una soluzione abbastanza
buona al sistema di PL a vincoli interi. L’arrotondamento poteva essere sia deterministico che
probabilistico. In questa lezione e nella prossima vedremo altre tecniche per ottenere algoritmi di
approssimazioni, sempre basati sulla PL, ma che sfruttano altri principi. Le tecniche che studieremo hanno
una validità più grande rispetto a quelle viste nelle lezioni precedenti, e sono basate sul Principio della
Dualità della Programmazione Lineare. Illustriamo tale principio attraverso un semplice esempio.
Supponiamo di avere il seguente sistema di PL:
𝑚𝑖𝑛𝑖𝑚𝑖𝑧𝑧𝑎𝑟𝑒 7𝑥1 + 𝑥2 + 5𝑥3 74
𝑠𝑜𝑔𝑔𝑒𝑡𝑡𝑜 𝑎 𝑥1 − 𝑥2 + 3𝑥3 ≥ 10 (75)
5𝑥1 + 2𝑥2 − 𝑥3 ≥ 6 (76)
𝑥1 , 𝑥2 , 𝑥3 ≥ 0 (77)
Notiamo che in questo esempio tutti i vincoli sono del tipo “≥” e tutte le variabili sono vincolate ad essere
non negative. Questa è la forma standard dei problemi di minimizzazione di PL e una semplice
trasformazione ci permette di scrivere ogni sistema di PL di minimo in questo modo. Ricordiamo che ogni
soluzione del sistema, ovvero ogni assegnamento di valori alle variabili che soddisfi tutti i vincoli è detta
una soluzione ammissibile. Sia z* il valore ottimo del sistema di PL di sopra, e chiediamoci “E’ z* ≤ 𝛼?“,
dove 𝛼 è un dato numerico. Per esempio, chiediamoci se z* è minore o tutt’al più uguale a 30. Un
certificato SI per questa domanda è semplicemente una soluzione ammissibile al sistema di PL per cui la
funzione obiettivo assume valore 30. Ad esempio, x = (2,1,3) costituisce un tale certificato in quanto x
soddisfa tutti i vincoli del sistema di PL ed il valore della funzione obiettivo in corrispondenza ad x è
7 ∗ 2 + 1 + 5 ∗ 3 = 30. Pertanto, ogni certificato SI fornisca una limitazione superiore al valore z*.
Come possiamo fornire un certificato NO alla stessa domanda “E’ z* ≤ 𝛼?“, ovvero come possiamo
determinare una limitazione inferiore al valore z*? Nel nostro esempio una limitazione inferiore la
possiamo ottenere dal primo vincolo del sistema. Infatti, poiché le variabili sono costrette ad assumere
valori non negativi e poiché la funzione obiettivo è tale che
7𝑥1 + 𝑥2 + 5𝑥3 ≥ 𝑥1 − 𝑥2 + 3𝑥3 ≥ 10 (𝑑𝑎𝑙𝑙𝑎 75)
abbiamo sicuramente che la funzione obiettivo vale almeno 10 in corrispondenza ad ogni soluzione
inferiore a z* la si può ottenere considerando entrambi i vincoli del sistema di PL (74). Infatti possiamo
dedurre che 7𝑥1 + 𝑥2 + 5𝑥3 ≥ 𝑥1 − 𝑥2 + 3𝑥3 + (5𝑥1 + 2𝑥2 − 𝑥3) ≥ 10 + 6 𝑑𝑎𝑙𝑙𝑎 75 𝑒 76 .
Pertanto, per ogni soluzione ammissibile la funzione obiettivo vale almeno 16, e quindi possiamo affermare
che z*≥ 16. L’idea può ovviamente essere estesa. Per esempio, possiamo osservare che
7𝑥1 + 𝑥2 + 5𝑥3 ≥ 2 ∗ 𝑥1 − 𝑥2 + 3𝑥3 + (5𝑥1 + 2𝑥2 − 𝑥3) ≥ 2 ∗ 10 + 6
ed ottenere, per lo stesso ragionamento di prima, che z*≥26. Nulla ci impedisce di procedere ulteriormente
ed andare quindi alla ricerca di moltiplicatori y1 e y2, uno per ciascun vincolo del sistema (74), in modo tale
che
7𝑥1 + 𝑥2 + 5𝑥3 ≥ 𝑦1 ∗ 𝑥1 − 𝑥2 + 3𝑥3 + 𝑦2 ∗ (5𝑥1 + 2𝑥2 − 𝑥3) ≥ 𝑦1 ∗ 10 + 𝑦2 ∗ 6
Ovviamente, affinchè 𝑦1 ∗ 10 + 𝑦2 ∗ 6 sia una valida limitazione inferiore al valore della funzione obiettivo
7𝑥1 + 𝑥2 + 5𝑥3 occorre che i valori y1 e y2 soddisfano i vincoli
𝑦1 + 5𝑦2 ≤ 7
−𝑦1 + 2𝑦2 ≤ 1
3𝑦1 − 𝑦2 ≤ 5
Visto che vogliamo trovare la migliore limitazione inferiore al valore della funzione obiettivo 7x1+x2+5x3 , ci
troviamo di fronte al seguente problema
Algoritmi e Strutture Dati 2: Lezione 18 – Principio della dualità in programmazione lineare
69
𝑚𝑎𝑠𝑠𝑖𝑚𝑖𝑧𝑧𝑎𝑟𝑒 10𝑦1 + 6𝑦2 (78)
𝑠𝑜𝑔𝑔𝑒𝑡𝑡𝑜 𝑎 𝑦1 + 5𝑦2 ≤ 7 (79)
−𝑦1 + 2𝑦2 ≤ 1 (80)
3𝑦1 − 𝑦2 ≤ 5 81
𝑦1 , 𝑦2 ≥ 0 (82)
Ovvero, abbiamo un ulteriore sistema di PL, chiaramente collegato a (74). Chiamiamo il sistema (74) il
programma primale ed il sistema (78) il programma duale. Per costruzione, ogni soluzione ammissibile al
duale fornisce una limitazione inferiore al valore ottimo del primale. Ovviamente vale anche il viceversa:
ogni soluzione ammissibile al primale fornisce una limitazione superiore al valore ottimo del duale.
Pertanto, se potessimo trovare soluzioni ammissibili al duale ed al primale le cui funzioni obiettivo
coincidono di valore, allora entrambe le soluzioni devono essere ottime. Nel nostro esempio, x = (7/4, 0,
11/4), e y = (2,1) entrambe fanno assumere valore 26 alle relative funzioni obiettivo; pertanto sono
entrambe ottime. La figura di sotto esemplifica la situazione:
Le considerazioni appena svolte ovviamente non si applicano solo all’esempio discusso, ma valgono per
ogni sistema di PL, e costituiscono il teorema centrale della programmazione lineare: il teorema delle
dualità della programmazione lineare.
Per poterlo enunciare formalmente, consideriamo il seguente problema di minimo come un programma
primale (avremmo potuto equivalentemente partire con un programma di massimo come primale).
𝑚𝑖𝑛𝑖𝑚𝑖𝑧𝑧𝑎𝑟𝑒 𝑐𝑗 𝑥𝑗
𝑛
𝑗 =1
𝑠𝑜𝑔𝑔𝑒𝑡𝑡𝑜 𝑎 𝑎𝑖𝑗 𝑥𝑗
𝑛
𝑗 =1
≥ 𝑏𝑗 , 𝑖 = 1, … , 𝑚
𝑥𝑗 ≥ 0 , 𝑗 = 1, … , 𝑛
dove aij, bi, cj sono numeri. Introduciamo la variabile duale yi per ogni disequazione nel sistema di sopra.
Otteniamo quindi il seguente programma duale
𝑚𝑎𝑠𝑠𝑖𝑚𝑖𝑧𝑧𝑎𝑟𝑒 𝑏𝑖𝑦𝑖
𝑚
𝑖=1
𝑠𝑜𝑔𝑔𝑒𝑡𝑡𝑜 𝑎 𝑎𝑖𝑗 𝑦𝑖
𝑚
𝑖=1
≤ 𝑐𝑗 , 𝑗 = 1, … , 𝑛
𝑦𝑖 ≥ 0 , 𝑖 = 1, … , 𝑚
Teorema 5 (della dualità nella PL)
Il programma primale assume valore ottimo finito se e solo se il programma duale assume valore ottimo
finito. Se 𝑥∗ = (𝑥1∗, … , 𝑥𝑛
∗) 𝑒 𝑦∗ = (𝑦1∗, … , 𝑦𝑚
∗ ) sono soluzioni ottime per il primale e per il duale,
rispettivamente, allora
𝑐𝑗
𝑛
𝑗 =1
𝑥𝑗∗ = 𝑏𝑖
𝑚
𝑖=1
𝑦𝑖∗
Algoritmi e Strutture Dati 2: Lezione 18 – Principio della dualità in programmazione lineare
70
Ritornando all’esempio con cui abbiamo iniziato la lezione, abbiamo osservato che per costruzione valeva
che ogni soluzione ammissibile al programma duale fornisce una limitazione inferiore al valore ottimo del
primale. In effetti, ogni soluzione ammissibile al programma duale fornisce una limitazione inferiore al
valore assunto della funzione obiettivo in corrispondenza ad ogni soluzione ammissibile del primale.
Proviamolo formalmente ed in generale.
Teorema 6 (della dualità debole)
Se x = (x1,….,xn) e y = (y1,….,ym) sono soluzioni ammissibili al programma primale e duale, rispettivamente,
allora
𝑐𝑗
𝑛
𝑗 =1
𝑥𝑗 ≥ 𝑏𝑖𝑦𝑖
𝑚
𝑖=1
(83)
Dim. Poiché y è una soluzione ammissibile al duale, e le variabili xj sono non negative, abbiamo
𝑐𝑗𝑥𝑗
𝑛
𝑗 =1
≥ 𝑎𝑖𝑗 𝑦𝑖
𝑚
𝑖=1
𝑛
𝑗 =1
𝑥𝑗 (84)
Analogamente, poiché x è una soluzione ammissibile al primale, e le variabili yi sono non negative, abbiamo
𝑎𝑖𝑗 𝑥𝑗
𝑛
𝑗 =1
𝑦𝑖
𝑚
𝑖=1
≥ 𝑏𝑖𝑦𝑖
𝑚
𝑖=1
(85)
Il teorema è quindi dimostrato una volta che si osservi che
𝑎𝑖𝑗 𝑦𝑖
𝑚
𝑖=1
𝑥𝑗
𝑛
𝑗 =1
= 𝑎𝑖𝑗 𝑥𝑗
𝑛
𝑗=1
𝑦𝑖
𝑚
𝑖=1
Dal teorema della dualità della PL, x e y sono entrambe soluzioni ottime se e solo se (83) vale con il segno
della eguaglianza. Ciò accade se e solo se (84) e (85) valgono con il segno dell’eguaglianza. Pertanto,
otteniamo il seguente risultato circa la struttura delle soluzioni ottime:
Teorema 7 (Condizioni complementari di slackness)
Siano x = (x1,….,xn) e y = (y1,….,ym) soluzioni ammissibili al primale ed al duale, rispettivamente. Allora x e y
sono entrambe ottimali se e solo se entrambe le seguenti condizioni sono soddisfatte:
Condizioni complementari di slackness primali
𝑃𝑒𝑟 𝑜𝑔𝑛𝑖 1 ≤ 𝑖 ≤ 𝑚; 𝑜 𝑣𝑎𝑙𝑒 𝑐𝑒 𝑦𝑖 = 0 𝑜𝑝𝑝𝑢𝑟𝑒 𝑎𝑖𝑗 𝑥𝑗
𝑛
𝑗 =1
= 𝑏𝑖 ; 𝑒
Condizioni complementari di slackness duali
𝑃𝑒𝑟 𝑜𝑔𝑛𝑖 1 ≤ 𝑗 ≤ 𝑛; 𝑜 𝑣𝑎𝑙𝑒 𝑐𝑒 𝑥𝑗 = 0 𝑜𝑝𝑝𝑢𝑟𝑒 𝑎𝑗𝑖 𝑦𝑖
𝑚
𝑖=1
= 𝑐𝑗
Le condizioni complementari di slackness giocheranno un ruolo fondamentale nel progetto di algoritmi di
approssimazione basati su PL, come vedremo nella prossima lezione.
Set Cover greedy via duale Nel resto di questa lezione useremo le tecniche appena introdotte per presentare una analisi alternativa (e
leggermente migliorata) dell’algoritmo greedy per SET COVER visto nella lezione 12. Risulterà anche
maggiormente chiaro il procedimento mediante il quale veniva stimato il valore OPT della soluzione ottima
a SET COVER.
Il procedimento che seguiremo è il seguente. Dato un algoritmo per SET COVER cerchiamo di dedurre da
esso una assegnazione di valori alle variabili del sistema duale al sistema di PL che descrive SET COVER. Tale
assegnazione dovrà rendere il valore della funzione obiettivo del duale uguale al valore SOL prodotto
Algoritmi e Strutture Dati 2: Lezione 18 – Principio della dualità in programmazione lineare
71
dall’algoritmo greedy, ovvero pari al valore della funzione obiettivo del primale in corrispondenza al vettore
ammissibile ottenibile dalla soluzione prodotta da greedy. Ricordiamo che la relazione tra le quantità OPTR,
OPT e SOL è raffigurata nella figura sotto
La soluzione di valore SOL cosi ottenuta al duale non sarà in generale ammissibile (si trova infatti al di fuori
della regione di ammissibilità del duale). Il passo successivo consisterà nel dividere la soluzione del duale
per un fattore F in modo tale da diminuire il valore da SOL a SOL/F e renderla ammissibile
Avremo pertanto mostrato che per il valore SOL della soluzione a SET COVER prodotta dall’algoritmo
greedy vale che
𝑆𝑂𝐿 = 𝐹 ∙ 𝑆𝑂𝐿
𝐹 ≤ 𝐹𝑂𝑃𝑇𝑅 ≤ 𝐹𝑂𝑃𝑇
a causa del Teorema debole della dualità e del fatto che la soluzione al duale di valore SOL/F è adesso
ammissibile, e quindi il valore ≤ 𝑂𝑃𝑇𝑅 ≤ 𝑂𝑃𝑇. Mettendo tutto insieme, abbiamo di fatto provato che il
nostro procedimento è in effetti un algoritmo di approssimazione con fattore di approssimazione F.
Applichiamo ora quanto detto. Ricordiamo la formulazione di SET COVER via PL
𝑚𝑖𝑛𝑖𝑚𝑖𝑧𝑧𝑎𝑟𝑒 𝑥 𝑆 𝑐 𝑆
𝑆 ∈𝑺
𝑠𝑜𝑔𝑔𝑒𝑡𝑡𝑜 𝑎 𝑥 𝑆 ≥ 1
𝑆:𝑒 ∈𝑆
, ∀𝑒 ∈ 𝑈
𝑥 𝑆 ∈ 0,1 ∀𝑆 ∈ 𝑺
La versione rilassata del sistema di PL è
𝑚𝑖𝑛𝑖𝑚𝑖𝑧𝑧𝑎𝑟𝑒 𝑥 𝑆 𝑐 𝑆
𝑆 ∈𝑺
𝑠𝑜𝑔𝑔𝑒𝑡𝑡𝑜 𝑎 𝑥 𝑆 ≥ 1
𝑆:𝑒 ∈𝑆
, ∀𝑒 ∈ 𝑈
𝑥 𝑆 ≥ 0, ∀𝑆 ∈ 𝑺
Introducendo una variabile ye per ogni vincolo del problema otteniamo il programma duale
𝑚𝑎𝑠𝑠𝑖𝑚𝑖𝑧𝑧𝑎𝑟𝑒 𝑦𝑒
𝑒 ∈𝑈
(86)
𝑠𝑜𝑔𝑔𝑒𝑡𝑡𝑜 𝑎 𝑦𝑒 ≤ 𝑐(𝑆)
𝑒:𝑒 ∈𝑆
, ∀𝑆 ∈ 𝑺 (87)
𝑦𝑒 ≥ 0, ∀𝑒 ∈ 𝑈 (88)
Come possiamo interpretare il duale? Un modo intuitivo di pensare il sistema di PL(86) è quello di
immaginare che le variabili ye rappresentano “roba” che abbiamo “impacchettato” in ogni elemento
corrispondente e∈U, e stiamo cercando di massimizzare l’ammontare di roba impacchettata, sotto la
Algoritmi e Strutture Dati 2: Lezione 18 – Principio della dualità in programmazione lineare
72
condizione che l’ammontare di roba impacchettata in ogni S∈ S, data da 𝑦𝑒𝑒:𝑒∈𝑺 , non debba superare la
“capacità” dell’insieme S, qui rappresentata dal suo costo c(S).
L’interpretazione appena data al duale ci dovrebbe aiutare nel nostro primo obiettivo che, ricordiamo,
consiste nel dedurre dall’algoritmo greedy per SET COVER un’assegnazione di valori alle variabili del sistema
duale di PL, ovvero alle ye ∀𝑒 ∈ 𝑈 , tale che il valore SOL della soluzione prodotta dall’algoritmo greedy sia
esprimibile come
𝑆𝑂𝐿 = 𝑦𝑒
𝑒 ∈𝑈
E’ il momento di ricordare l’algoritmo greedy per SET COVER
Algoritmo Greedy per Set Cover
1. 𝐶 = ∅, 𝑆 ′ = ∅ // (S’ è il cover che vogliamo costruire, C è l’insieme degli elementi di U finora coperti
2. 𝑊𝑖𝑙𝑒 𝐶 ≠ 𝑈 𝑑𝑜
𝑇𝑟𝑜𝑣𝑎 𝑙’𝑖𝑛𝑠𝑖𝑒𝑚𝑒 𝑆 ∈ 𝑺 𝑐𝑜𝑛 𝑖𝑙 𝑣𝑎𝑙𝑜𝑟𝑒 𝛼 =𝑐 𝑆
𝑆−𝐶 𝑚𝑖𝑛𝑖𝑚𝑜
∀ 𝑒 ∈ 𝑆 − 𝐶 𝑝𝑜𝑛𝑖 𝑝𝑟𝑒𝑧𝑧𝑜 𝑒 = 𝛼 //prezzo(e)= quanto mi costa coprire l’arco e
𝑃𝑜𝑛𝑖 𝑆 ′ = 𝑆 ′ ∪ 𝑆 , 𝐶 = 𝐶 ∪ 𝑆 Output S’
Più importate ancora è ricordare che nella Lezione 12 abbiamo provato che
𝑆𝑂𝐿 = 𝑝𝑟𝑒𝑧𝑧𝑜(𝑒)
𝑒 ∈𝑈
Ecco quindi trovato l’assegnamento alle variabili ye che cercavamo: basterà porre 𝑦𝑒 = 𝑝𝑟𝑒𝑧𝑧𝑜 𝑒 ∀𝑒 ∈ 𝑈
ed avremo 𝑆𝑂𝐿 = 𝑦𝑒𝑒 ∈𝑈
Ovviamente, non è certo detto che tale assegnazione di valore alle variabili ye sia ammissibile, ovvero che
rispetti il vincolo (87). Infatti, dall’analisi dell’algoritmo greedy effettuate nella Lezione 12 ciò che sappiamo
valere è
𝑝𝑟𝑒𝑧𝑧𝑜(𝑒)
𝑒 𝑟𝑖𝑐𝑜𝑝𝑒𝑟𝑡𝑖 𝑝𝑒𝑟 𝑙𝑎 𝑝𝑟𝑖𝑚𝑎 𝑣𝑜𝑙𝑡𝑎 𝑑𝑎 𝑆
= 𝑦𝑒
𝑒 𝑟𝑖𝑐𝑜𝑝𝑒𝑟𝑡𝑖 𝑝𝑒𝑟 𝑙𝑎 𝑝𝑟𝑖𝑚𝑎 𝑣𝑜𝑙𝑡𝑎 𝑑𝑎 𝑆
= 𝑐 𝑆 ∀ 𝑆 ∈ 𝑺
il che implica che la disuguaglianza del vincolo del duale 𝑦𝑒 ≤ 𝑐 𝑆 𝑒:𝑒 ∈ 𝑆 (87) in generale non vale
(essendo il membro sinistro della disuguaglianza (87) una somma su di un numero di termini in generale
maggiore). Eseguiamo allora il secondo passo del procedimento che abbiamo prima descritto, ovvero
dividiamo i valori ye per un’opportuna quantità in modo da ottenere una soluzione ammissibile per il duale
(86). Poniamo
∀𝑒 ∈ 𝑈, 𝑧𝑒 =𝑦𝑒
𝐻𝑛=
𝑝𝑟𝑒𝑧𝑧𝑜(𝑒)
𝐻𝑛 (89)
dove 𝐻𝑛 = 1
𝑖𝑛𝑖=0 < log 𝑛 + 1. Proviamo ora che il vettore z definito dalla (89) è una soluzione ammissibile
al sistema di PL duale dato da (86). A tal fine occorre provare che
𝑧𝑒
𝑒 ∈𝑆
≤ 𝑐 𝑆 , ∀ 𝑆 ∈ 𝑺 (90)
La prova ricalca una analoga prova effettuata nella lezione 12. Consideriamo un generico S∈S e numeriamo
i suoi elementi nell’ordine in cui essi vengono coperti per la prima volta dall’algoritmo greedy. Sia quindi S =
{e1,….,ek-. Consideriamo l’istante in cui l’elemento ei viene ricoperto per la prima volta. Ciò vuol dire che in
questo passo dell’algoritmo l’insieme S contiene almeno K – i + 1 elementi non coperti. Pertanto, l’insieme
S stesso potrebbe coprire ei ad un costo medio ≤ 𝑐(𝑆)
𝑘−𝑖+1. Ciò implica anche che 𝑝𝑟𝑒𝑧𝑧𝑜(𝑒𝑖) ≤
𝑐(𝑆)
𝑘−𝑖+1, ovvero
𝑧𝑒𝑖≤
1
𝐻𝑛∙
𝑐(𝑆)
𝑘 − 𝑖 + 1
Algoritmi e Strutture Dati 2: Lezione 18 – Principio della dualità in programmazione lineare
73
Sommando su tutti gli elementi di S otteniamo
𝑧 = 𝑧𝑒𝑖
𝑘
𝑖=1
≤𝑐(𝑆)
𝐻𝑛∙
1
𝑘+
1
𝑘 − 1+ ⋯ + 1 =
𝑐(𝑆)
𝐻𝑛∙
1
𝑖
𝑘
𝑖=1
=𝐻𝑘
𝐻𝑛𝑐(𝑆) ≤ 𝑐(𝑆)
E quindi il vettore z è ammissibile per il duale.
A questo punto, ricordando dalla lezione 12 che il valore SOL della soluzione restituita dall’algoritmo
greedy è pari a 𝑝𝑟𝑒𝑧𝑧𝑜(𝑒)𝑒 ∈𝑈 otteniamo
𝑆𝑂𝐿 = 𝑝𝑟𝑒𝑧𝑧𝑜(𝑒)
𝑒 ∈𝑈
= 𝐻𝑛 𝑧𝑒
𝑒 ∈𝑈
≤ 𝐻𝑛𝑂𝑃𝑇𝑅 ≤ 𝐻𝑛𝑂𝑃𝑇
Abbiamo quindi (ri)provato che l’algoritmo greedy ha un fattore di approssimazione Hn.
Due osservazioni sono in ordine
1. Questo modo di procedere ci fà meglio capire qual è la limitazione inferiore di OPT che usammo a
suo tempo per valutare il fattore di approssimazione dell’algoritmo greedy per SET COVER. Infatti,
che 𝑝𝑟𝑒𝑧𝑧𝑜(𝑒)𝑒 ∈𝑈 𝐻𝑛 sia ≤ OPT discende ora immediatamente dal fatto che
𝑝𝑟𝑒𝑧𝑧𝑜(𝑒)𝑒 ∈𝑈 𝐻𝑛 è il valore della funzione obiettivo del duale in corrispondenza ad una
soluzione ammissibile di esso. Pertanto la disuguaglianza 𝑝𝑟𝑒𝑧𝑧𝑜(𝑒)𝑒 ∈𝑈 𝐻𝑛 ≤ 𝑂𝑃𝑇 è una
immediata conseguenza del Teorema della dualità debole.
2. Questo modo di procedere ci permette di ottenere in maniera semplice anche una analisi più
precisa dell’algoritmo greedy. Poniamo infatti
𝑡 = maxS ∈𝐒 𝑆 𝑒 𝐻𝑡 = 1
𝑖
𝑡
𝑖=1
E’ semplice verificare che il vettore z definito dalle componenti
𝑧𝑒 =𝑝𝑟𝑒𝑧𝑧𝑜(𝑒)
𝐻𝑡, ∀𝑒 ∈ 𝑈
È una soluzione ammissibile al duale(86). Da ciò segue che
𝑆𝑂𝐿 = 𝑝𝑟𝑒𝑧𝑧𝑜(𝑒)
𝑒 ∈𝑈
≤ 𝐻𝑡𝑂𝑃𝑇
che è in generale migliore della limitazione 𝑆𝑂𝐿 ≤ 𝐻𝑛𝑂𝑃𝑇
Algoritmi e Strutture Dati 2: Lezione 19 – Hitting Set via duale e Vertex Cover Primale-Duale
74
Lezione 19 – Hitting Set via duale e Vertex Cover Primale-Duale
In quel che segue illustreremo brevemente una tecnica per derivare un algoritmo di approssimazione direttamente dal duale del sistema di PL che descrive il problema in questione (invece di usare il duale solo come strumento nell'analisi di un algoritmo ottenuto a parte, come abbiamo appena fatto di sopra). Descriveremo la tecnica prendendo come esempio il problema dell' Hitting Set. Ricordiamo innanzitutto il problema dell'Hitting Set (in versione semplificata).
Hitting set Input:
Insieme 𝑈 = {𝑒1 , … , 𝑒𝑛 } , famiglia 𝑺 = {𝑆1 , … , 𝑆𝑚 } con 𝑆𝑖 ⊆ 𝑈per i=1….m Funzione di costo𝑐: 𝑒 ∈ 𝑈 → 𝑐 𝑒 ∈ 𝑅+ 𝑒 𝑐 𝑒 ≥ 0;
Output: sottoinsieme 𝐻 ⊆ 𝑈 di costo minimo 𝑐 𝐻 = 𝑐(𝑒)𝑒 ∈𝐻 minimo tale 𝐻 ∩ 𝑆 ≥ 1, ∀𝑆 ∈ 𝑺
La sua formulazione via PL è la seguente.
𝑚𝑖𝑛𝑖𝑚𝑖𝑧𝑧𝑎𝑟𝑒 𝑥 𝑒 𝑐 𝑒
𝑒 ∈𝑈
91
𝑠𝑜𝑔𝑔𝑒𝑡𝑡𝑜 𝑎 𝑥 𝑒 ≥ 1
𝑒 ∈𝑆
, ∀𝑆 ∈ 𝑺 (92)
𝑥 𝑒 ∈ 0,1 ∀𝑒 ∈ 𝑈 (93)
La versione rilassata del problema (91) sarà
𝑚𝑖𝑛𝑖𝑚𝑖𝑧𝑧𝑎𝑟𝑒 𝑥 𝑒 𝑐 𝑒
𝑒 ∈𝑈
94
𝑠𝑜𝑔𝑔𝑒𝑡𝑡𝑜 𝑎 𝑥 𝑒 ≥ 1
𝑒 ∈𝑆
, ∀𝑆 ∈ 𝑺 (95)
𝑥 𝑒 ≥ 0, ∀𝑒 ∈ 𝑈 (96)
Introducendo una variabile yS per ogni vincolo (95), otteniamo il seguente sistema di PL duale a (94)
𝑚𝑎𝑠𝑠𝑖𝑚𝑖𝑧𝑧𝑎𝑟𝑒 𝑦𝑆
𝑆∈𝑺
(97)
𝑠𝑜𝑔𝑔𝑒𝑡𝑡𝑜 𝑎 𝑦𝑆 ≤ 𝑐(𝑒)
𝑆:𝑒 ∈𝑆
, ∀𝑒 ∈ 𝑈 (98)
𝑦𝑆 ≥ 0, ∀𝑆 ∈ 𝑺 (99)
L'algoritmo che proponiamo per Hitting Set costruisce una soluzione H ⊆ U nel seguente modo: vengono messi in H tutti e solo quegli elementi 𝑒 ∈ 𝑈 per cui il corrispondente vincolo
𝑦𝑆
𝑆:𝑒 ∈𝑆
≤ 𝑐(𝑒)
del duale è soddisfatto con il segno di eguaglianza. Qual è la intuizione dietro questo modo di procedere? Ciò che stiamo in effetti facendo è la cosa seguente: stiamo costruendo una soluzione a Hitting Set (ovvero al sistema di PL che lo rappresenta) ponendo la variabile x(e) al valore 1 (ovvero ponendo e nella soluzione) se e solo se
𝑦𝑆
𝑆:𝑒 ∈𝑆
= 𝑐(𝑒)
In altri termini, stiamo costruendo una soluzione ai valori interi del primale imponendo inoltre che essa
soddisfi la condizione di slackness primale. Abbiamo quindi il seguente algoritmo:
Algoritmo per Hitting Set Via Duale
1. 𝑅𝑖𝑠𝑜𝑙𝑣𝑖 𝑖𝑙 𝑠𝑖𝑠𝑡𝑒𝑚𝑎 𝑃𝐿 𝑑𝑢𝑎𝑙𝑒 97 , 𝑒 𝑠𝑖𝑎 𝒚 𝑙𝑎 𝑠𝑜𝑙𝑢𝑧𝑖𝑜𝑛𝑒 𝑜𝑡𝑡𝑖𝑚𝑎 2. 𝐻 = ∅ 3. For 𝑒 ∈ 𝑈
If 𝑦𝑆𝑆:𝑒 ∈𝑆 = 𝑐(𝑒) Then 𝐻 = 𝐻 ∪ 𝑒
4. Return H
Algoritmi e Strutture Dati 2: Lezione 19 – Hitting Set via duale e Vertex Cover Primale-Duale
75
Mostriamo che l'insieme H restituito dall'algoritmo, ovvero l'insieme
𝐻 = 𝑒 ∈ 𝑈: 𝑦𝑆
𝑆:𝑒 ∈𝑆
= 𝑐 𝑒 (100)
è una soluzione per il problema dell'Hitting Set , ovvero vale che ∀𝑆 ∈ 𝑺 si ha 𝐻 ∩ 𝑆 ≠ ∅. Se infatti fosse 𝐻 ∩ 𝑇 = ∅ per qualche 𝑇 ∈ 𝑆, ciò vorrebbe dire che
∀ 𝑢 ∈ 𝑇, 𝑦𝑆
𝑆:𝑢 ∈𝑆
≤ 𝑐(𝑢)
Osserviamo ora che la variabile yT compare nei vincoli di sopra del sistema di PL duale e solo nei vincoli di sopra. Quindi, potremmo aumentare il valore della variabile yT , in modo tale che i corrispondenti vincoli del sistema (97) siano ancora soddisfatti. Ma ciò equivale a dire che possiamo trovare un'altra soluzione al sistema (97) migliore di y, contro la ipotizzata ottimalità della soluzione y. Stimiamo infine il fattore di approssimazione dell'algoritmo proposto. Abbiamo
𝑆𝑂𝐿 = 𝑐(𝑒)
𝑒∈𝐻
= 𝑦𝑆
𝑆:𝑒 ∈𝑆𝑒∈𝐻
𝑑𝑎𝑙𝑙𝑎 100 = |𝐻 ∩ 𝑆|𝑦𝑆
𝑆
L’ultima uguaglianza la si ottiene in quanto ogni yS compare nella somma una volta per ogni 𝑒 ∈ 𝐻 che appartiene anche a S. Se quindi sapessimo che esiste un α tale che ogni qualvolta ys >0 allora 𝐻 ∩ 𝑆 ≤ 𝛼, 𝑐𝑜𝑛 𝛼 = 𝑚𝑎𝑥𝑆 ∈𝑺 𝑆 , allora otterremo
𝑆𝑂𝐿 = |𝐻 ∩ 𝑆|𝑦𝑆
𝑆
≤ 𝛼 𝑦𝑆
𝑆
≤ 𝛼𝑂𝑃𝑇𝑅 (𝑖𝑛 𝑞𝑢𝑎𝑛𝑡𝑜 𝑦 è 𝑎𝑚𝑚𝑖𝑠𝑠𝑖𝑏𝑖𝑙𝑒 𝑝𝑒𝑟 𝑖𝑙 𝑑𝑢𝑎𝑙𝑒) ≤ 𝛼𝑂𝑃𝑇
Per esempio, detto 𝑘 = max 𝑆 ∶ 𝑆 ∈ 𝑺 , otteniamo banalmente che 𝛼 ≤ 𝑘,e quindi otterremo un altro algoritmo di approssimazione per Hitting Set con fattore di approssimazione k, diverso dall’algoritmo considerato nella lezione 16.
Algoritmi di approssimazione via Primale-Duale Ricordiamo ancora una volta il nostro “meta-algoritmo” per il progetto di algoritmi di approssimazione:
1. Formula il problema in questione come un problema di PL a vincoli interi
1. Rilassa il problema, sostituendo i vincoli di interezza con semplici vincoli di non negatività
2. Usa la soluzione al problema rilassato per ottenere una soluzione al problema a vincoli interi, di
valore prossimo all'ottimo
Nelle lezioni scorse abbiamo visto vari metodi per implementare il passo 3. In questa lezione ne vedremo
un ulteriore, abbastanza simile all'ultimo metodo visto ed applicato nella lezione scorsa. Intendiamo
riferirci all'uso diretto del duale e delle condizioni complementari di slackness, così come usate per
progettare un algoritmo di approssimazione per Hitting Set. La differenza con il metodo che vedremo oggi
consiste nel fatto che esso, invece di risolvere innanzitutto il sistema duale e poi usare la sua soluzione e le
condizioni complementari di slackness per costruire una soluzione intera al primale, costruisce passo passo
una soluzione al duale, imponendo che la condizione complementare di slackness duale sia sempre
soddisfatta. Il metodo risulta essere maggiormente flessibile di quello visto nella lezione scorsa, in quanto
nella costruzione della soluzione del duale (visto che la realizziamo noi) ci permette in linea teorica di tener
conto di addizionali informazioni che potremmo eventualmente avere sulla struttura del problema di
ottimizzazione sotto esame. Inoltre risulta essere più veloce in pratica, in quanto non richiede la soluzione
preliminare di un sistema di PL. Useremo la formulazione di PL del problema in questione solo come una
guida per il progetto e l'analisi dell'algoritmo. Il metodo generale (che va sotto il nome di Primale-Duale) lo
possiamo descrivere nella Figura 1 appresso presentata.
e1
e2
H e3
S
Algoritmi e Strutture Dati 2: Lezione 19 – Hitting Set via duale e Vertex Cover Primale-Duale
76
Per illustrare l'applicazione dello schema della Figura 1 ad algoritmi di approssimazione, applichiamo il
metodo al primo problema di ottimizzazione visto in questo corso: Vertex Cover. Ricordiamo il problema
Vertex Cover Input:
𝐺𝑟𝑎𝑓𝑜 𝐺 = (𝑉, 𝐸) Output: 𝑠𝑜𝑡𝑡𝑜𝑖𝑛𝑠𝑖𝑒𝑚𝑒 𝑆 ⊆ 𝑉 𝑑𝑖 𝑚𝑖𝑛𝑖𝑚𝑎 𝑐𝑎𝑟𝑑𝑖𝑛𝑎𝑡𝑙𝑖𝑡à 𝑆 , 𝑡𝑎𝑙𝑒 𝑐𝑒 ∀(𝑢, 𝑣) ∈ 𝐸, {𝑢, 𝑣} ∩ 𝑆 ≠ ∅
La sua formulazione via PL è:
𝑚𝑖𝑛𝑖𝑚𝑖𝑧𝑧𝑎𝑟𝑒 𝑥 𝑣
𝑣 ∈𝑉
101
𝑠𝑜𝑔𝑔𝑒𝑡𝑡𝑜 𝑎 𝑥 𝑢 + 𝑥 𝑣 ≥ 1, ∀ 𝑢, 𝑣 ∈ 𝐸 (102)
𝑥 𝑣 ∈ 0,1 ∀𝑢 ∈ 𝑉 (103)
Il corrispondente sistema rilassato
𝑚𝑖𝑛𝑖𝑚𝑖𝑧𝑧𝑎𝑟𝑒 𝑥 𝑣
𝑣 ∈𝑉
104
𝑠𝑜𝑔𝑔𝑒𝑡𝑡𝑜 𝑎 𝑥 𝑢 + 𝑥 𝑣 ≥ 1, ∀ 𝑢, 𝑣 ∈ 𝐸 (105)
𝑥 𝑣 ∈ [0,1] ∀𝑢 ∈ 𝑉 (106)
Per derivare il duale di (104) introduciamo una variabile duale ye per ogni vincolo (105), ottenendo il
sistema
𝑚𝑎𝑠𝑠𝑖𝑚𝑖𝑧𝑧𝑎𝑟𝑒 𝑦𝑒
𝑒∈𝐸
107
𝑠𝑜𝑔𝑔𝑒𝑡𝑡𝑜 𝑎 𝑦𝑒
𝑒:𝑣∈𝑒
≤ 1, ∀𝑣 ∈ 𝑉 (108)
𝑦𝑒 ∈ 0,1 ∀𝑒 ∈ 𝐸 (109)
E’ istruttivo, per un momento, osservare una particolare classe di soluzioni al sistema (107). Sia M un
matching del grafo G, ovvero una collezione di archi disgiunti di G. Definiamo il vettore 𝑧 = (𝑧𝑒1 , … . , 𝑧𝑒𝑚 )
come
𝑧𝑒𝑖=
1 𝑠𝑒 𝑒𝑖 ∈ 𝑀0 𝑠𝑒 𝑒𝑖 ∉ 𝑀
E’ semplice verificare che z è una soluzione ammissibile al sistema (107), in particolare che soddisfa i vincoli
(108), proprio perché , corrispondendo z ad un matching in G, su ogni vertice v ∈ V incide uno ed un solo
arco di M. Pertanto, dal Teorema debole della dualità abbiamo che
𝑀 = 𝑧𝑒
𝑒∈𝐸
≤ 𝑂𝑃𝑇
Algoritmi e Strutture Dati 2: Lezione 19 – Hitting Set via duale e Vertex Cover Primale-Duale
77
dove OPT è il valore della soluzione ottima al sistema di PL (101), ovvero OPT è la cardinalità di un Vertex
Cover per G di cardinalità minima. Ritroviamo quindi, come conseguenza del Teorema della dualità debole,
la limitazione inferiore alla cardinalità del VC di cardinalità minima derivato nella Lezione 11.
Vediamo ora come è possibile derivare un algoritmo di approssimazione per Vertex Cover usando lo
schema generale Primale-Duale illustrato nella Figura 1. Lo schema ci suggerisce di partire con una
soluzione y ammissibile per il duale (107), in cui tutte le componenti sono poste a 0, ed una soluzione non
ammissibile x al primale intero (101) in cui tutte le componenti sono poste a 0. Se x non è ammissibile (e fin
quando lo sarà), vuol dire che ∃ 𝑒 = (𝑢, 𝑣) ∈ 𝐸 tale che il relativo vincolo (102) non è soddisfatto, ovvero
vale
𝑥 𝑢 + 𝑥 𝑣 = 0 (110)
Allora, sempre in accordo allo schema generale Primale-Duale della Figura 1, incrementiamo la
corrispondente variabile duale ye il più possibile, mantenendo il rispetto dei vincoli del duale, ed in modo
tale che il vincolo (108) sia soddisfatto con l'uguaglianza. In altri termini, nel nostro caso specifico del
Vertex Cover , stiamo ponendo ye = 1. Poiché lo schema generale Primale-Duale ci impone che le condizioni
di slackness primali debbano essere sempre soddisfatte, dobbiamo porre anche 𝑥 𝑢 = 𝑥 𝑣 = 1 in
quanto adesso i vincoli duali 𝑦𝑒𝑒:𝑣∈𝑒 ≤ 1 sono soddisfatti con l'uguaglianza sia per il vertice u che per il
vertice v. In altre parole, stiamo mettendo sia il vertice u che il vertice v nella costruenda soluzione S per il
problema del Vertex Cover.
Iteriamo il procedimento: ogni qualvolta troviamo un vincolo nel primale intero che il vettore x non
soddisfa ancora (ovvero, troviamo un qualche 𝑒 = 𝑢, 𝑣 ∈ 𝐸 per cui 𝑥 𝑢 + 𝑥 𝑣 = 0), poniamo ye = 1
nella soluzione del duale, imponendo poi che le condizioni di slackness primali siano soddisfatte per x, cioè
incrementiamo le componenti xu e xv a 1.Prima o poi otterremo una soluzione intera x che soddisfa tutti i
vincoli del primale (101), con x che soddisfa anche
𝑥𝑣
𝑣∈𝑉
= 𝑦𝑒
𝑒:𝑣∈𝑒
𝑥𝑣
𝑣∈𝑉
111 = 𝑥𝑣
𝑣∈𝑒
𝑦𝑒
𝑒∈𝐸
112 ≤ 2 𝑦𝑒
𝑒∈𝐸
113 ≤ 2𝑂𝑃𝑇𝑅 ≤ 2𝑂𝑃𝑇 (114)
dove la uguaglianza (111) vale in quanto 𝑦𝑒𝑒:𝑣∈𝑒 = 1 per costruzione, per tutti i vertici v per cui xv = 1; la
uguaglianza (112) la si ottiene riorganizzando la somma; la diseguaglianza (113) vale in quanto il vettore x è
ammissibile per il primale e quindi soddisfa tutti i vincoli di (101). Abbiamo quindi (ri)ottenuto un algoritmo
di approssimazione con fattore 2 per il problema del Vertex Cover. Una analisi attenta di esso ci informa
che l'algoritmo appena ottenuto, mediante il metodo Primale-Duale, è perfettamente analogo a quello
presentato nella Lezione 11. Infatti, nell'algoritmo appena derivato noi inseriamo nella soluzione S, ad ogni
passo dell'algoritmo, entrambi i vertici u e v corrispondenti ad un arco e = (u,v) per cui abbiamo posto
𝑦𝑒 = 1 nel duale. D'altra parte, il vettore y è sempre costretto ad essere una soluzione ammissibile a (107),
ovvero deve rispettare i vincoli
𝑦𝑒
𝑒:𝑣∈𝑒
≤ 1, ∀𝑣 ∈ 𝑉
Questo implica che ∀ 𝑣 ∈ 𝑉 uno solo degli ye nella somma di sopra può assumere valore 1, cioè uno solo
degli ye corrispondenti ad archi e incidenti su v può essere posto ad 1. Di conseguenza, l'insieme
𝐴 = {𝑒 ∶ 𝑦𝑒 = 1} è una collezione di archi disgiunti (un matching), per ogni iterazione dell'algoritmo. Al
completamento dell'algoritmo l'insieme A è ovviamente un matching massimale, mentre la soluzione S
prodotta dall'algoritmo corrisponde evidentemente all'insieme dei vertici incidenti sugli archi del matching
massimale A.
Algoritmi e Strutture Dati 2: Lezione 20 – Set-Cover con PL Primale-Duale
78
Lezione 20 – Set-Cover con PL Primale-Duale
Applichiamo ora la tecnica Primale-Duale al problema del Set Cover . Ricordiamo la sua formulazione
Input: Insieme 𝑈 = {𝑢1 , … , 𝑢𝑛 } , famiglia 𝑺 = {𝑆1, … , 𝑆𝑘} con 𝑆𝑖 ⊆ 𝑈per i=1….k Funzione di costo𝑐: 𝑆 ∈ 𝑺 → 𝑐 𝑆 ∈ 𝑅+ 𝑒 𝑐 𝑠 ≥ 0;
Output: sottofamiglia 𝑺′ ⊆ 𝑺 di costo minimo 𝑐 𝑺′ = 𝑐(𝑆)𝑆 ∈𝑺′ minimo tale che 𝑆 ⊇ 𝑈𝑆 ∈𝑺′
la sua formulazione via PL a vincoli interi
𝑚𝑖𝑛𝑖𝑚𝑖𝑧𝑧𝑎𝑟𝑒 𝑥 𝑆 𝑐 𝑆
𝑆 ∈𝑺
𝑠𝑜𝑔𝑔𝑒𝑡𝑡𝑜 𝑎 𝑥 𝑆 ≥ 1
𝑆:𝑢 ∈𝑆
, ∀𝑢 ∈ 𝑈
𝑥 𝑆 ∈ 0,1 ∀𝑆 ∈ 𝑺
e la corrispondente versione rilassata del problema di PL
𝑚𝑖𝑛𝑖𝑚𝑖𝑧𝑧𝑎𝑟𝑒 𝑥 𝑆 𝑐 𝑆
𝑆 ∈𝑺
𝑠𝑜𝑔𝑔𝑒𝑡𝑡𝑜 𝑎 𝑥 𝑆 ≥ 1
𝑆:𝑢 ∈𝑆
, ∀𝑢 ∈ 𝑈
𝑥 𝑆 ∈ [0,1] ∀𝑆 ∈ 𝑺
Duale
𝑚𝑎𝑠𝑠𝑖𝑚𝑖𝑧𝑧𝑎𝑟𝑒 𝑦𝑢𝑢∈U
𝑠𝑜𝑔𝑔𝑒𝑡𝑡𝑜 𝑎 𝑦𝑢 ≤ 𝑐 𝑆 ∀ 𝑆 ∈ 𝐒𝑢 :𝑢 ∈𝑆
𝑦𝑢 ≥ 0 ∀ 𝑢 ∈ U
Il seguente algoritmo implementa la strategia Primale-Duale per il problema del Set Cover .
ALGORITMO
𝐼 ← ∅ //indice degli S inseriti nella soluzione
𝑦𝑢← ∅ ∀ 𝑢∈ 𝑈
𝑤𝑖𝑙𝑒 ∃ 𝑢 ∈ 𝑈 𝑡𝑎𝑙𝑒 𝑐𝑒 𝑢 ∉ 𝑆𝑗𝑗∈𝐼 do
Sia ℓ 𝑙′𝑖𝑛𝑑𝑖𝑐𝑒 𝑝𝑒𝑟 𝑐𝑢𝑖 𝑖𝑙 𝑚𝑖𝑛:𝑢 ∈ 𝑆 𝑐 𝑆 − 𝑦𝑎𝑎∈𝑆
è raggiunto
ℰℓ = 𝑐 𝑆ℓ − 𝑦𝑎𝑎∈𝑆ℓ
𝑦𝑢← yu + ℰℓ
𝐼 ← 𝐼 ∪ ℓ
Return 𝐼
N.B. I È un SET-COVER per le condizioni del while
𝑦 = yu1 + yu2 + … + yun è 𝑠𝑜𝑙𝑢𝑧𝑖𝑜𝑛𝑒 𝑎𝑚𝑚𝑖𝑠𝑠𝑖𝑏𝑖𝑙𝑒 𝑝𝑒𝑟 𝑖𝑙 𝑑𝑢𝑎𝑙𝑒
Procediamo per induzione sul numero di esecuzioni del ciclo while. Il caso base è ovvio in quanto all’inizio
vale ovviamente
yu𝑢 :𝑢∈𝑆
= 0 ≤ 𝑐 𝑆 ∀ = 1, … , 𝑚
Per il passo induttivo, assumiamo induttivamente che entrando in una iterazione del ciclo while abbiamo
yu𝑢 :𝑢∈𝑆
≤ 𝑐 𝑆 → 𝑜𝑡𝑡𝑒𝑛𝑔𝑜 2 𝑐𝑎𝑠𝑖 ⇉𝑢ℓ ∉𝑆 ⟹𝑛𝑜𝑛 𝑐𝑎𝑚𝑏𝑖𝑜 𝑖 𝑣𝑎𝑙𝑜𝑟𝑖 𝑛𝑒𝑙𝑙𝑎 𝑠𝑜𝑚𝑚𝑎𝑢ℓ ∈𝑆 ⟹𝑎𝑔𝑔𝑖𝑢𝑛𝑔𝑜 𝑦𝑢 ℓ 𝑎𝑙𝑙𝑎 𝑠𝑜𝑚𝑚𝑎
La sola variabile duale il cui valore è incrementato dall'esecuzione del ciclo While è la variabile 𝑦𝑢 (dove u è
un elemento per cui 𝑢 ∉ 𝑆𝑗𝑗∈𝐼 ), pertanto tutte le diseguaglianze
yu𝑢 :𝑢∈𝑆
≤ 𝑐 𝑆 ∀ = 1, … , 𝑚
yu
𝑢 :𝑢∈𝑆≤ 𝑐(𝑆)
Vincolo del Duale
È il minimo incremento
di costo
Algoritmi e Strutture Dati 2: Lezione 20 – Set-Cover con PL Primale-Duale
79
per gli insiemi Sh tali che 𝑢 ∉ Sh rimangono inalterate e quindi continuano a valere. Se invece u ∈ Sh, allora
per la nostra scelta dell'indice abbiamo che
𝑦𝑎
𝑎∈𝑆
+ 𝑐 𝑆ℓ − 𝑦𝑎
𝑎∈𝑆ℓ
≤ 𝑦𝑎
𝑎∈𝑆
+ 𝑐 𝑆 − 𝑦𝑎
𝑎∈𝑆
= 𝑐 𝑆
Pertanto, i vincoli del duale sono soddisfatti anche dopo l'esecuzione del ciclo While, e quindi, per il
principio di induzione, anche alla terminazione dell'algoritmo.
Lemma: 𝑠𝑒 𝑗 ∈ 𝐼 → yu𝑢∈𝑆𝑗= 𝑐 𝑆𝑗
Se in un qualche passo abbiamo aggiunto j a I, allora per come opera l'algoritmo, abbiamo anche
aumentato yu , per qualche u ∈ Sj, tale da rendere il vincolo yu𝑢∈𝑆𝑗= 𝑐 𝑆𝑗 soddisfatto dall’uguaglianza.
Teorema L'algoritmo Primale-Duale per Set Cover è un algoritmo di approssimazione con fattore di
approssimazione f, 𝑑𝑜𝑣𝑒 𝑓 = 𝑚𝑎𝑥𝑢 ∈𝑈 𝑓 𝑢 , 𝑒 𝑓 𝑢 = 𝑛𝑢𝑚𝑒𝑟𝑜 𝑑𝑖 𝑖𝑛𝑠𝑖𝑒𝑚𝑖 𝑆 ∈ 𝑺 che contengono u.
𝑓: max 𝑓 𝑢 ≤ 𝑓 𝑦 𝑢
𝑢
≤ 𝑓 · 𝑂𝑃𝑇𝑅 ≤ 𝑓 · 𝑂𝑃𝑇
Abbiamo
𝑆𝑂𝐿 = 𝑐(𝑆𝑗 )
𝑗∈𝐼
= 𝑦𝑢
𝑢 ∈ 𝑆𝑗𝑗∈𝐼
= 𝑦𝑢 {𝑗: 𝑢 ∈ 𝑆𝑗 }
𝑢 ∈ 𝑈
≤ 𝑓 ∙ 𝑦𝑢
𝑢 ∈ 𝑈
≤ 𝑓 ∙ 𝑂𝑃𝑇
dove la prima uguaglianza è per definizione, la seconda a causa del Lemma, la terza in quanto la variabile yu
compare nella somma tante volte quanti sono gli insiemi Sj che contengono il corrispondente u, la quarta
per definizione di f, e l'ultima per il Teorema della dualità debole.
Concludiamo la lezione affermando che la tecnica Primale-Duale sembra essere a tutt'oggi la metodologia
più efficace per il progetto di algoritmi di approssimazione. Si è visto in tempi recenti che vari algoritmi
derivati negli anni scorsi mediante procedimenti ad hoc, sono in realtà interpretabili come esempi di
algoritmi Primale-Duale. Inoltre, in molti casi, la tecnica Primale-Duale ha prodotto algoritmi di
approssimazione che risultano essere, a tutt'oggi, i migliori sia in termini di fattore di approssimazione, che
in termini di complessità computazionale.
yu
𝑢 :𝑢∈𝑆
= 𝑣𝑒𝑐𝑐𝑖 𝑣𝑎𝑙𝑜𝑟𝑖 + ℰℓ ≤ 𝑐 𝑆 − yu
𝑢 :𝑢∈𝑆
+ 𝑣𝑒𝑐𝑐𝑖 𝑣𝑎𝑙𝑜𝑟𝑖 = 𝑐 𝑆
yu𝑢∈𝑆
Somma delle istanze precedenti
Algoritmi e Strutture Dati 2: Lezione 21 – Algoritmi on-line e organizzazione della cache
80
Lezione 21 – Algoritmi on-line e organizzazione della cache
Finora abbiamo studiato algoritmi di approssimazione per problemi computazionalmente difficili, (ovvero
problemi di ottimizzazione la cui la versione decisionale è NP-HARD). Per questi problemi ad ogni possibile
istanza di input è associato un insieme di possibili soluzioni e la difficoltà consiste nel trovare per ogni
istanza di input una soluzione che abbia costo minimo, se il problema è un problema di minimizzazione, o
profitto massimo se il problema è un problema di massimizzazione. Per tali problemi di ottimizzazione
abbiamo studiato varie tecniche per produrre soluzioni che non si discostassero molto da quella ottima.
Tutta la teoria finora sviluppata si basa su una assunzione cruciale, e cioè che l'input al problema sia
interamente noto prima che l'algoritmo inizi le sua computazione. Tuttavia, in pratica non è sempre così,
ovvero in molte situazioni di interesse pratico l'input al problema ci viene data sequenzialmente, poco per
volta, ed ogni volta che riceviamo una nuova parte dell'input, ci viene anche richiesto di produrre una parte
dell' output, senza ovviamente conoscere il resto della sequenza input.
Algoritmo online – offline
ONLINE = Effettua le computazioni sequenzialmente. Non conosce a priori tutto l’input
OFFLINE = Conosce a priori tutto l’input e le richieste delle pagine future.
DIVERSA STIMA DELL’ALGORITMO
Per la prima volta ci troviamo ad operare con algoritmi che non hanno una conoscenza totale dell’input e
quindi dobbiamo utilizzare un nuovo strumento per la valutazione delle prestazioni.
Organizzazione della cache Il primo esempio di problemi siffatti che studieremo è il problema della gestione efficiente della
paginazione della memoria cache. Ricordiamo che i calcolatori sono dotati di memorie (secondaria, cache,
RAM) aventi caratteristiche diverse, sia per quanto riguarda la dimensione che i tempi di accesso. Inoltre,
dal punto di vista concettuale i diversi tipi di memoria possono essere organizzati in una gerarchia realizzata
in base al principio di localizzazione temporale e spaziale: le pagine (ovvero unità di memoria a dimensione
fissata) usate più spesso e quelle che si trovano in locazioni di memoria vicine, vengono caricate nella
memoria più veloce (la cache) in modo da garantirne un recupero immediato al momento in cui vengono
richieste. In particolare, quando la CPU richiede un dato, inizia la sua ricerca dalla memoria cache (la più
veloce ma anche la più piccola). Nel caso di esito negativo della ricerca (ciò avviene quando il dato non è
recuperato in quanto la pagina che lo contiene non è presente nella cache), la ricerca continua alla
memoria RAM, la quale si occupa di inviare alla cache la pagina contenente il dato richiesto. Una richiesta di
accesso ad un dato non presente in alcuna pagina nella cache (ed il conseguente spostamento della pagina
che contiene il dato dalla RAM alla cache) viene denominato page fault. La gestione di un page fault è
generalmente onerosa, in quanto richiede la esecuzione di svariate operazioni ausiliarie, e sarebbe quindi
opportuno avere politiche di gestione della memoria che minimizzino il numero di page fault. Il problema
della paginazione della cache entra in gioco proprio nella gestione di page faults, in quanto se la cache è
piena occorre eliminare qualche pagina da essa per far posto alla nuova pagina, contenente il dato
richiesto, che occorre spostare dalla RAM alla cache. Sarebbe desiderabile avere un metodo che ci dica,
all'occorrere di page faults, quale pagina espellere dalla cache in modo tale che il numero totale dei page
faults venga minimizzato.
Algoritmi e Strutture Dati 2: Lezione 21 – Algoritmi on-line e organizzazione della cache
81
PAGEFAULT = Richiesta di accesso ad un dato non presente nella cache, ed il conseguente spostamento
della pagina che contiene il dato dalla RAM alla cache.
Valutando il caso peggiore tutti gli algoritmi di caching sarebbero uguali. Non esiste, inoltre, una
distribuzione di probabilità tra le pagine da richiedere.
Per vedere come ciò possa essere realizzato, occorre precisare ulteriormente i termini del problema.
Abbiamo
una memoria RAM contenente n pagine P1,…, Pn
una memoria cache che può contenere ad ogni istante k pagine, dove si assume in generale che k
sia molto più piccolo di n
una sequenza di richieste 𝜎 = 𝜎 1 𝜎 2 … : 𝜎(𝑚), dove ogni 𝜎(𝑖), per i = 1,…,m, rappresenta una
richiesta ad una qualche pagina 𝑃 ∈ {P1, … , Pn}
un costo 𝑐𝑜𝑠𝑡𝑜(𝜎(𝑖)) per soddisfare la richiesta 𝜎(i), definito come
𝑐𝑜𝑠𝑡𝑜 𝜎 i = 1 𝑠𝑒 𝑙𝑎 𝑝𝑎𝑔𝑖𝑛𝑎 𝑟𝑖𝑐𝑖𝑒𝑠𝑡𝑎 ∉ 𝑔𝑖à 𝑎𝑙𝑙𝑎 𝑐𝑎𝑐𝑒0 𝑠𝑒 𝑙𝑎 𝑝𝑎𝑔𝑖𝑛𝑎 𝑟𝑖𝑐𝑖𝑒𝑠𝑡𝑎 ∈ 𝑔𝑖à 𝑎𝑙𝑙𝑎 𝑐𝑎𝑐𝑒
Il problema è progettare un algoritmo che decida, ad ogni page-fault, quale pagina espellere dalla memoria cache, al fine di minimizzare il numero totale di page-fault della sequenza delle pagine richieste. In altri termini, cerchiamo un algoritmo che minimizzi il costo
𝑐𝑜𝑠𝑡𝑜 𝜎 = 𝑐𝑜𝑠𝑡𝑜 𝜎 𝑖 (𝑁𝑢𝑚𝑒𝑟𝑜 𝑑𝑖 𝑝𝑎𝑔𝑒 𝑓𝑎𝑢𝑙𝑡)
𝑚
𝑖=1
per ogni possibile sequenza di richieste 𝜎.
Si presentano immediatamente due difficoltà di tipo pratico e concettuale:
1. Come progettare l'algoritmo?
Stiamo chiedendo di sviluppare un algoritmo che minimizzi il numero di page-fault senza però
conoscere quali sono le richieste future alla richiesta che ha creato il fault. Noi non conosciamo la
parte dell'input dell'algoritmo successiva alla richiesta corrente di pagina, quindi in base a quale
criterio l'algoritmo dovrà scegliere la pagina da espellere? Ciò che in altri termini stiamo dicendo, è
che in generale sembra difficile progettare algoritmi che operino bene sul futuro senza conoscerlo.
2. Come misurare la “bontà" dell'algoritmo, ovvero il costo in cui incorre?
Finora abbiamo sempre analizzato la complessità computazionale degli algoritmi sulla base del loro
comportamento nel caso peggiore. Ma nella situazione che stiamo ora studiando ciò non ha
ovviamente senso. Infatti, tutti gli algoritmi, anche il migliore, nel caso peggiore andranno
malissimo. Supponiamo infatti di avere un generico algoritmo A e supponiamo che in
corrispondenza di un dato page fault l'algoritmo A decida di espellere la pagina P dalla cache. Nel
caso peggiore potrebbe accadere che la stessa pagina P venga immediatamente richiesta, creando
quindi un nuovo page fault. Allora l'algoritmo A per poter portare di nuovo P nella memoria cache
dovrà espellere un'altra pagina, sia essa P’, che potrebbe essere ovviamente la nuova pagina
Siccome l’accesso alla memoria cache è molto più veloce, ogni volta
che richiedo un dato da una pagina in RAM, carico in memoria cache
tutta la pagina in modo da poter sfruttare i dati “intorno” a quello
interessato.
Algoritmi e Strutture Dati 2: Lezione 21 – Algoritmi on-line e organizzazione della cache
82
richiesta all'istante successivo, creando un nuovo page fault, e così via. In altri termini, qualunque
sia il comportamento dell'algoritmo A, è sempre vero che nel caso peggiore esiste una sequenza 𝜎
di m richieste a pagine che possono costringere A ad effettuare m page fault. Il succo di queste
considerazioni è che se adottassimo il comportamento dell'algoritmo nel caso peggiore come
misura della complessità dell'algoritmo, allora tutti gli algoritmi avrebbero la stessa complessità.
È chiaro che quanto appena detto (ovvero valutare gli algoritmi in questo scenario secondo il loro
comportamento nel caso peggiore) non ha alcun senso.
In pratica, inoltre, si vede che gli algoritmi di paging realmente usati dai sistemi operativi innanzitutto non
incorrono in numeri elevati di page fault, ed inoltre differenti algoritmi tendono ad esibire diverse
complessità. Possiamo quindi dire che nel caso di algoritmi che devono operare ed effettuare scelte sotto la
ipotesi di conoscenza parziale dell'input e di ignoranza dell'input futuro che si possa presentare, è errato
utilizzare il loro comportamento nel caso peggiore come misura della loro efficienza.
L'aspetto realmente nuovo di questo scenario risiede nel fatto che l'input all'algoritmo viene fornito passo-
passo, in maniera sequenziale. Pertanto, sarebbe sensato valutare quanto si perde, ovvero quanto costa,
passare dalla conoscenza totale dell'input a quella parziale o sequenziale. Introduciamo quindi un nuovo
strumento per l'analisi degli algoritmi, chiamata analisi competitiva degli algoritmi.
Analisi competitiva degli algoritmi
Un algoritmo on-line è un algoritmo A cui viene presentata una sequenza
𝜎 = 𝜎 1 𝜎 2 … 𝜎(𝑚)
di richieste, e l'algoritmo effettua una decisione in corrispondenza di ogni richiesta 𝜎 𝑖 , basandosi solo
sulla conoscenza delle richieste note finora 𝜎 𝑗 , 𝑗 ≤ 𝑖.
Sia 𝑐𝑜𝑠𝑡𝐴(𝜎) il costo dell'algoritmo on-line A sulla sequenza 𝜎 (il costo dipenderà dalla particolare
applicazione sotto esame, ad esempio nel caso del paging sarà il numero totale di page-fault cui l'algoritmo
A incorre quando la sequenza 𝜎 di richieste a pagine di memoria gli viene data in input). L'algoritmo on-line
A è detto un algoritmo c-competitivo se esistono delle costanti c ed 𝑎 tali che per ogni sequenza input 𝜎
vale che:
𝑐𝑜𝑠𝑡𝐴 𝜎 ≤ 𝑐 ∗ 𝑐𝑜𝑠𝑡𝑂𝑃𝑇 𝜎 + 𝑎
dove cost OPT è il costo del migliore algoritmo offline, ovvero del migliore algoritmo che opera conoscendo
tutta la sequenza input 𝜎 fin dall’inizio. La definizione appena data misura correttamente quanto costa
“l'ignoranza" del futuro, ovvero il passaggio da algoritmi off-line ad algoritmi on-line. Quindi se A è un
algoritmo on-line c-competitivo, allora esso, su ogni sequenza input, non costerà mai più di c volte
l'algoritmo ottimo off-line che conosce fin dall'inizio tutta la sequenza (che costituisce ovviamente la
situazione ideale ma irrealistica in pratica).
Torniamo al problema del paging. Il problema centrale dell'algoritmo è decidere ad ogni istante quale
pagina eventualmente espellere dalla memoria cache, senza conoscere le richieste future. Vari algoritmi
sono stati proposti per risolvere il problema, tra i più noti ed usati nella pratica vi sono i tre seguenti:
LRU (Least Recently Used) = Rimozione della pagina inutilizzata da più tempo.
FIFO (First in first out) = Rimozione della prima pagina inserita in cache.
LIFO (Last in first out ) = Rimozione dell’ultima pagina inserita in cache.
Vale il seguente risultato.
Teorema L'algoritmo LRU è k-competitivo (con k = dimensione della cache), ovvero vale che
𝑐𝑜𝑠𝑡𝐿𝑅𝑈(𝜎) ≤ 𝑘 ∗ 𝑐𝑜𝑠𝑡𝑂𝑃𝑇 (𝜎);
per ogni possibile sequenza di richieste 𝜎.
Tale teorema è valido anche per l'algoritmo FIFO. Per questi due algoritmi è dunque dimostrabile che i
rapporti 𝑐𝑜𝑠𝑡𝐿𝑅𝑈 𝜎 /𝑐𝑜𝑠𝑡𝑂𝑃𝑇 𝜎 e 𝑐𝑜𝑠𝑡𝐹𝐼𝐹𝑂 𝜎 /𝑐𝑜𝑠𝑡𝑂𝑃𝑇 𝜎 non divergono, ma sono limitati dal valore k
(la dimensione della memoria cache), qualunque sia la sequenza di richieste 𝜎, e comunque essa sia lunga.
Algoritmi e Strutture Dati 2: Lezione 21 – Algoritmi on-line e organizzazione della cache
83
È inoltre dimostrabile, invece, che l'algoritmo LIFO non è c-competitivo, per qualsiasi valore del parametro
c. In altri termini, l'algoritmo LIFO, su particolari sequenze di richieste 𝜎, può produrre un numero di page-
fault che non è limitato superiormente dal numero di page-fault dell'algoritmo ottimo moltiplicato per c,
qualunque sia il valore c.
Ovvero, il rapporto 𝑐𝑜𝑠𝑡𝐿𝐼𝐹𝑂 𝜎 /𝑐𝑜𝑠𝑡𝑂𝑃𝑇 𝜎 , per particolari sequenze di richieste 𝜎, cresce
indefinitamente, al crescere della lunghezza di 𝜎.
Passiamo ora alla dimostrazione del teorema.
Sia ς = ς (1), ς (2)… ς (m) una sequenza di richieste di input. Partizioniamo la sequenza di richieste in fasi
F(0), F(1),….F(i),...
La definizione di FASE è la seguente. Ogni fase F(i) è composta da una sottosequenza di richieste
consecutive di ς su cui LRU ha esattamente k Pagefault e ciò è vero ∀ 𝑖 ≥ 1 mentre nella fase F(0)
l’algoritmo ha al più k Pagefault (k è la dimensione della cache). La suddivisione in fasi è effettuabile nel
seguente modo: esaminiamo la sequenza 𝜎 dalla fine e, in base alle richieste, contiamo il numero di
pagefault in cui LRU è in corso. Appena ne abbiamo esattamente k allora raggruppiamo le richieste in una
fase, e continuiamo in questo modo con ulteriori raggruppamenti. Alla fine otterremo una ultima fase,
F(0), corrispondente ad un numero di pagefault ≤ k; (infatti se ciò non fosse potremmo dividere le richieste
in due fasi diverse). Abbiamo quindi: F(0), F(1), …, F(s) t.c. |F|=s+1.
Mostriamo innanzitutto la seguente asserzione circa il comportamento dell'algoritmo off-line ottimo
(qualunque esso sia) sulle fasi sopra definite.
𝐼𝑛 𝑜𝑔𝑛𝑖 𝑓𝑎𝑠𝑒 𝐹 𝑖 , 𝑖 ≥ 0; 𝑙′𝑎𝑙𝑔𝑜𝑟𝑖𝑡𝑚𝑜 𝑜𝑡𝑡𝑖𝑚𝑜 𝑎 𝑎𝑙𝑚𝑒𝑛𝑜 𝑢𝑛 𝑝𝑎𝑔𝑒𝑓𝑎𝑢𝑙𝑡. (125)
Prima di provare la asserzione (125) esaminiamone una sua immediata ed importante conseguenza.
Calcoliamo 𝑐𝑜𝑠𝑡𝐿𝑅𝑈 𝜎 . Avremo
𝑐𝑜𝑠𝑡𝐿𝑅𝑈 𝜎 = 𝑛𝑢𝑚𝑒𝑟𝑜 𝑑𝑖 𝑝𝑎𝑔𝑒 𝑓𝑎𝑢𝑙𝑡 𝑐𝑒 𝐿𝑅𝑈 𝑐𝑜𝑚𝑚𝑒𝑡𝑡𝑒 𝑠𝑢 𝜎 =
𝑘 ∙ 𝑛𝑢𝑚𝑒𝑟𝑜 𝑑𝑖 𝑓𝑎𝑠𝑖 = 𝑘 ∙ (𝑠 + 1)
D'altra parte la (125) implica che l'algoritmo ottimo ha almeno s+1 faults in totale quando gli viene
sottoposta la sequenza di richieste ς (infatti l'algoritmo ottimo avrà almeno un pagefault per ognuna delle
(s + 1) fasi F(i)), pertanto
𝑐𝑜𝑠𝑡𝑂𝑃𝑇 𝜎 ≥ (𝑠 + 1)
Mettendo insieme le due diseguaglianze di sopra otteniamo:
𝑐𝑜𝑠𝑡𝐿𝑅𝑈 𝜎 ≤ 𝑘 ∙ 𝑠 + 1 ≤ 𝑘 ∙ 𝑐𝑜𝑠𝑡𝑂𝑃𝑇 𝜎
che è esattamente l'enunciato del Teorema che vogliamo dimostrare. Ci resta quindi da provare la (125).
A tal fine supporremo, senza perdita di generalità che sia LRU che l'algoritmo off-line ottimo partano con lo
stesso contenuto nella memoria cache. Quindi appena una richiesta in 𝜎 provocherà il primo page fault per
LRU (ed ovviamente ciò avverrà in corrispondenza ad una richiesta nella fase F(0)), tale richiesta provocherà
anche il primo page fault per l'algoritmo off-line ottimo. Ci resta quindi da provare la (125) solo per 𝑖 ≥ 1.
Più precisamente, proveremo che in corrispondenza alle richieste della fase F(i), un qualunque algoritmo, e
quindi in particolare anche quello ottimo, avrà almeno un page fault.
Consideriamo la generica fase F(i) con i ≥ 1. Essa corrisponderà alle richieste che vanno da 𝜎 𝑡𝑖 a
𝜎 𝑡𝑖+1 − 1 , per qualche coppia di indici 𝑡𝑖 𝑒 𝑡𝑖+1 .
Sia P l’ultima pagina richiesta nella fase F(i-1), quindi la pagina P sicuramente risiede nella memoria cache
all’inizio della fase F(i). Proviamo che
𝑎𝑙𝑙’𝑖𝑛𝑡𝑒𝑟𝑛𝑜 𝑑𝑒𝑙𝑙𝑎 𝑓𝑎𝑠𝑒 𝐹 𝑖 𝑠𝑖𝑐𝑢𝑟𝑎𝑚𝑒𝑛𝑡𝑒 𝑐𝑖 𝑠𝑜𝑛𝑜 𝑠𝑡𝑎𝑡𝑒 𝑘 𝑟𝑖𝑐𝑖𝑒𝑠𝑡𝑒 𝑎 𝑝𝑎𝑔𝑖𝑛𝑒 𝑃1 … . . 𝑃𝑛
𝑑𝑖𝑣𝑒𝑟𝑠𝑒 𝑡𝑟𝑎 𝑙𝑜𝑟𝑜 𝑒 𝑑𝑖𝑣𝑒𝑟𝑠𝑒 𝑑𝑎 𝑃 (126)
Di nuovo, prima di provare la (126) discutiamo una sua immediata conseguenza. Se vale la (126), allora un
qualunque algoritmo avrà necessariamente un pagefault nella fase F(i). Infatti, all'inizio della fase F(i) la
pagina P è presente nella cache, e quindi le altre k pagine distinte e diverse da P che sono richieste in F(i)
non potranno essere tutte presenti, almeno una di esse non lo sarà , e quindi almeno un page fault avverrà
Algoritmi e Strutture Dati 2: Lezione 21 – Algoritmi on-line e organizzazione della cache
84
appena la corrispondente richiesta a tale pagina si presenta nella fase F(i). Pertanto, la (126) implica la
(125), e conseguentemente il Teorema.
Dimostriamo quindi la (126) al fine di completare la dimostrazione del Teorema.
Ricordiamo che nella fase F(i) sono avvenute k pagefault per l'algoritmo LRU. Ciò vuol dire che ci sono state
k richieste a pagine che non risiedevano nella memoria cache di LRU. Se tali pagine richieste sono tutte
distinte tra loro e tutte diverse da P, allora la (126) è ovviamente dimostrata. Altrimenti si può verificare
uno dei seguenti due casi.
1. 𝐿𝑒 𝑘 𝑟𝑖𝑐𝑖𝑒𝑠𝑡𝑒 𝑐𝑒 𝑎𝑛𝑛𝑜 𝑝𝑟𝑜𝑣𝑜𝑐𝑎𝑡𝑜 𝑖 𝑘 𝑝𝑎𝑔𝑒𝑓𝑎𝑢𝑙𝑡 𝑑𝑖 𝐿𝑅𝑈 𝑛𝑒𝑙𝑙𝑎 𝑓𝑎𝑠𝑒 𝐹 𝑖 𝑠𝑜𝑛𝑜 𝑡𝑢𝑡𝑡𝑒 𝑑𝑖𝑣𝑒𝑟𝑠𝑒
𝑑𝑎 𝑃 𝑚𝑎 𝑛𝑜𝑛 𝑠𝑜𝑛𝑜 𝑡𝑢𝑡𝑡𝑒 𝑑𝑖𝑠𝑡𝑖𝑛𝑡𝑒 𝑡𝑟𝑎 𝑙𝑜𝑟𝑜. 𝐼𝑛 𝑎𝑙𝑡𝑟𝑖 𝑡𝑒𝑟𝑚𝑖𝑛𝑖, 𝑙′𝑎𝑙𝑔𝑜𝑟𝑖𝑡𝑚𝑜 𝐿𝑅𝑈 𝑡𝑟𝑎 𝑖 𝑠𝑢𝑜𝑖 𝑘
𝑝𝑎𝑔𝑒𝑓𝑎𝑢𝑙𝑡 𝑛𝑒 𝑎 𝑑𝑢𝑒 𝑠𝑢 𝑢𝑛𝑎 𝑠𝑡𝑒𝑠𝑠𝑎 𝑝𝑎𝑔𝑖𝑛𝑎 𝑄. (𝑅𝑖𝑐𝑖𝑒𝑠𝑡𝑒 𝑄𝑖 𝑑𝑖𝑣𝑒𝑟𝑠𝑒 𝑑𝑎 𝑃 𝑚𝑎 𝑒𝑠𝑖𝑠𝑡𝑒 𝑢𝑛𝑎
𝑐𝑜𝑝𝑝𝑖𝑎 (𝑖, 𝑗) 𝑡𝑎𝑙𝑒 𝑐𝑒 𝑄𝑖 = 𝑄𝑗)
Ragioniamo allora nel seguente modo. Nella sequenza di richieste in F(i) ad un certo punto ci sarà il primo pagefault sulla pagina Q, e quindi la pagina Q verrà portata nella memoria cache. Dopodiché avremo il secondo pagefault sulla stessa pagina Q . Ciò vuol evidentemente dire che la pagina Q era stata precedentemente espulsa dalla memoria cache. Come era potuto accadere ciò? Era ovviamente accaduto che ad un certo momento tra tutte le k pagine residenti nella memoria cache, la pagina Q era diventata la pagina acceduta più lontanamente (ciò perché stiamo usando l'algoritmo LRU). Detto in altre parole, ciò che è accaduto è che dopo aver portato Q in memoria cache per la prima volta in conseguenza di una richiesta alla pagina Q, vi sono state k-1 richieste a pagine distinte da Q e tra di loro (che hanno fatto diventare Q la pagina acceduta più lontanamente nel passato tra tutte le k residenti nella cache) poi vi è stata l'espulsione di Q in conseguenza di un'altra richiesta distinta ad una pagina non risiedente in memoria. In totale, dal momento dell'inserimento di Q per la prima volta in memoria cache fino alla sua espulsione vi sono state almeno 1 + (k - 1) + 1 = k + 1 richieste a pagine distinte. Tra tali k + 1 richieste a pagine tutte distinte tra di loro, una sola può essere per la pagina P, ovvero ve ne sono sicuramente almeno k distinte tra di loro e distinte dalla pagina P, provando la (126)
2. 𝐿𝑒 𝑘 𝑟𝑖𝑐𝑖𝑒𝑠𝑡𝑒 𝑐𝑒 𝑎𝑛𝑛𝑜 𝑝𝑟𝑜𝑣𝑜𝑐𝑎𝑡𝑜 𝑙𝑒 𝑘 𝑝𝑎𝑔𝑒 𝑓𝑎𝑢𝑙𝑡 𝑑𝑖 𝐿𝑅𝑈 𝑛𝑒𝑙𝑙𝑎 𝑓𝑎𝑠𝑒 𝐹 𝑖 𝑠𝑜𝑛𝑜 𝑡𝑢𝑡𝑡𝑒
𝑑𝑖𝑠𝑡𝑖𝑛𝑡𝑒 𝑡𝑟𝑎 𝑑𝑖 𝑙𝑜𝑟𝑜 𝑚𝑎 𝑛𝑜𝑛 𝑠𝑜𝑛𝑜 𝑡𝑢𝑡𝑡𝑒 𝑑𝑖𝑣𝑒𝑟𝑠𝑒 𝑑𝑎 𝑃. 𝐼𝑛 𝑎𝑙𝑡𝑟𝑖 𝑡𝑒𝑟𝑚𝑖𝑛𝑖, 𝑙′𝑎𝑙𝑔𝑜𝑟𝑖𝑡𝑚𝑜 𝐿𝑅𝑈 𝑛𝑒𝑙𝑙𝑎
𝑓𝑎𝑠𝑒 𝐹 𝑖 𝑛𝑜𝑛 𝑓𝑎𝑙𝑙𝑖𝑠𝑐𝑒 𝑚𝑎𝑖 𝑑𝑢𝑒 𝑣𝑜𝑙𝑡𝑒 𝑠𝑢𝑙𝑙𝑎 𝑠𝑡𝑒𝑠𝑠𝑎 𝑝𝑎𝑔𝑖𝑛𝑎, 𝑚𝑎 𝑡𝑟𝑎 𝑖 𝑠𝑢𝑜𝑖 𝑘 𝑝𝑎𝑔𝑒 𝑓𝑎𝑢𝑙𝑡 è
𝑖𝑛𝑐𝑙𝑢𝑠𝑜 𝑎𝑛𝑐𝑒 𝑢𝑛𝑜 𝑐𝑎𝑢𝑠𝑎𝑡𝑜 𝑑𝑎 𝑢𝑛𝑎 𝑟𝑖𝑐𝑖𝑒𝑠𝑡𝑎 𝑎𝑙𝑙𝑎 𝑝𝑎𝑔𝑖𝑛𝑎 𝑃 (𝑅𝑖𝑐𝑖𝑒𝑠𝑡𝑒 𝑡𝑢𝑡𝑡𝑒 𝑑𝑖𝑣𝑒𝑟𝑠𝑒 𝑡𝑟𝑎 𝑙𝑜𝑟𝑜,
𝑚𝑎 𝑢𝑛𝑎 𝑟𝑖𝑐𝑖𝑒𝑠𝑡𝑎 è 𝑢𝑔𝑢𝑎𝑙𝑒 𝑎 𝑃)
Il ragionamento è analogo a prima. Abbiamo che all'inizio della fase F(i) la pagina P è in memoria cache, per ipotesi. Poi vi è un pagefault causato da una richiesta alla pagina P. Ciò vuol evidentemente dire che P era stata nel frattempo espulsa dalla cache. Ovvero, in accordo alla regola LRU, era accaduto che dopo l'inserimento di P nella memoria cache alla fine della fase F(i - 1), vi erano state k - 1 richieste a pagine distinte da P e tra di loro (che hanno fatto diventare P la pagina acceduta più lontanamente nel passato tra tutte le k residenti nella cache) poi vi è stata l'espulsione di P in conseguenza di un'altra richiesta distinta da P ad una pagina non risiedente in memoria. La cosa importante è che la pagina P alla fine della fase F(i - 1) è in memoria cache, e poi durante la fase F(i) vi sono state almeno k richieste a pagine non risiedenti in memoria e distinte da P, provando la (126) in tutti i casi possibili.
Si può dimostrare che anche l'algoritmo FIFO è k-competitivo, procedendo in maniera perfettamente analoga a quanto fatto nel teorema appena dimostrato. Un altro risultato interessante è il seguente, che mostra la ottimalità di LRU e FIFO tra gli algoritmi competitivi per il problema del paging.
Teorema: Non esistono algoritmi per il problema del paging che siano k’-competitivi, per un qualsiasi k’< k. Proof. Definiamo il seguente algoritmo off-line per il problema del paging:
𝐿𝐹𝐷: 𝑎𝑑 𝑜𝑔𝑛𝑖 𝑝𝑎𝑔𝑒 − 𝑓𝑎𝑢𝑙𝑡 𝑒𝑠𝑝𝑒𝑙𝑙𝑖 𝑙𝑎 𝑝𝑎𝑔𝑖𝑛𝑎 𝑙𝑎 𝑐𝑢𝑖 𝑝𝑟𝑜𝑠𝑠𝑖𝑚𝑎 𝑟𝑖𝑐𝑖𝑒𝑠𝑡𝑎 è 𝑝𝑖ù 𝑙𝑜𝑛𝑡𝑎𝑛𝑎 𝑛𝑒𝑙 𝑓𝑢𝑡𝑢𝑟𝑜. In particolare, si può dimostrare che questo è il miglior algoritmo off-line, ma ciò non è necessario ai fini della dimostrazione del teorema. Proviamo invece che per ogni sequenza 𝜎 di richieste a pagine nell'insieme {𝑃1, … , 𝑃𝑘, 𝑃𝑘 + 1} vale che:
Algoritmi e Strutture Dati 2: Lezione 21 – Algoritmi on-line e organizzazione della cache
85
𝑐𝑜𝑠𝑡𝐿𝐹𝐷 𝜎 ≤ 𝜎
𝑘 (127)
dove |𝜎| è il numero delle richieste nella sequenza 𝜎.
Dimostriamo la (127). A tal fine, notiamo innanzitutto che ogni richiesta 𝜎 (𝑖) si riferisce o ad una pagina già nella memoria cache o all'unica pagina correntemente al di fuori della memoria cache. Ciò a causa della ipotesi che 𝜎 è una sequenza di richieste a pagine nell'insieme {𝑃1, … , 𝑃𝑘, 𝑃𝑘 + 1}. Supponiamo ora che ad un certo istante, in corrispondenza alla richiesta 𝜎 (i), l'algoritmo LFD espella P. Ricordiamo che l'algoritmo LFD espelle sempre la pagina che verrà richiesta più lontanamente nel tempo futuro, tra tutte le pagine attualmente risiedenti nella memoria cache. Quindi, se P viene espulsa da LFD in conseguenza della richiesta 𝜎 (i), ciò implica che vi saranno, dopo la richiesta 𝜎 (i), necessariamente almeno k-1 successive richieste alle altre pagine diverse da P, che per ipotesi stanno già in memoria, e quindi non creano alcun page fault. In altri termini, per ogni k richieste consecutive della sequenza 𝜎, possiamo avere al più un page
fault. Ovvero, il numero di page fault di LFD è ≤ 𝜎
𝑘 e quindi la (127) è dimostrata. Possiamo ora
completare la dimostrazione del teorema. Supponiamo di avere una generica sequenza ς = ς (1), ς (2)… ς (m).Considero un arbitrario algoritmo Online ALG. Specifichiamo le ς (i) passo passo, a seconda delle decisioni su quali pagine da espellere dalla cache abbia preso l’algoritmo ALG. Supponiamo che la richiesta ς (i) alla pagina Pk+1 l'algoritmo ALG abbia deciso di espellere dalla cache la pagina Pi. Assumiamo che ς (i +1) corrisponda ad una richiesta alla pagine appena espulsa Pi. Vi sarà ovviamente un pagefault, con conseguente espulsione di una qualche pagina Pj . Possiamo allora assumere che ς (i + 2) corrisponda ad una richiesta a Pj , e così via, nel senso che in ς ogni successiva richiesta ad un pagefault si riferisce alla pagina precedentemente espulsa. Su una tale sequenza di richieste ς l'algoritmo ALG avrà n - k pagefault (per le prime k richieste non ci sono pagefault con 𝑛 =|𝜎|) e quindi
𝑐𝑜𝑠𝑡𝐴𝐿𝐺 𝜎 = 𝑛 − 𝑘 se per assurdo l’algoritmo online ALG fosse k’-competitivo, per qualche valore k’<k, allora avremmo
𝑐𝑜𝑠𝑡𝐴𝐿𝐺 𝜎 ≤ 𝑘 ′ 𝑐𝑜𝑠𝑡𝑂𝑃𝑇 𝜎 + 𝑎 (128) per qualche costante a e per ogni sequenza di richieste 𝜎. D'altra parte, abbiamo appena mostrato che per una particolare sequenza di richieste 𝜎 di lunghezza n vale che
𝑐𝑜𝑠𝑡𝐴𝐿𝐺 𝜎 = 𝑛 − 𝑘 mentre per l'algoritmo LFD, in virtù della (127), per la stessa sequenza 𝜎 vale che
𝑐𝑜𝑠𝑡𝐿𝐹𝐷 𝜎 ≤𝑛
𝑘 .
La diseguaglianza di sopra implica anche che
𝑐𝑜𝑠𝑡𝑂𝑃𝑇 𝜎 ≤ 𝑐𝑜𝑠𝑡𝐿𝐹𝐷 𝜎 ≤𝑛
𝑘 .
Pertanto, se fosse vera la (128) avremmo anche
𝑛 − 𝑘 = 𝑐𝑜𝑠𝑡𝐴𝐿𝐺 𝜎 ≤ 𝑘 ′ 𝑐𝑜𝑠𝑡𝑂𝑃𝑇 𝜎 + 𝑎 ≤ 𝑘 ′ 𝑛
𝑘 + 𝑎
Il che implica la disuguaglianza
𝑛 − 𝑘 ≤𝑘 ′ 𝑛
𝑘+ 𝑎
Ciò è ovviamente assurdo per valori di n sufficientemente grandi, visto che il rapporto k’/k è strettamente minore di 1. Possiamo quindi rigettare la ipotesi assurda, e concludere che non esistono algoritmi k’-competitivi per il problema del paging, qualunque sia il valore k’< k.
Algoritmi e Strutture Dati 2: Lezione 22 – Accesso e gestione di liste dinamiche
86
Lezione 22 – Accesso e gestione di liste dinamiche
Il problema dell'aggiornamento di liste consiste nel mantenere una struttura dati dizionario mediante una lista non ordinata. Dato un insieme di elementi rappresentati da una lista lineare, assumiamo di ricevere una sequenza σ = σ(1) … σ(m) di richieste, dove ogni richiesta σ(i) è una delle tre possibili operazioni:
1. accesso ad un elemento della lista, 2. inserimento di un nuovo elemento nella lista, 3. cancellazione di un elemento dalla lista.
Stimiamo i costi di ciascuna delle tre operazioni sopra descritte.
Per accedere ad un elemento, un algoritmo generico inizia la ricerca dalla testa della lista e procede sequenzialmente fin quando l'elemento desiderato non viene trovato. Pertanto, se l'elemento da accedere si trova nella posizione i all'interno della lista, possiamo assumere che il costo per servire una richiesta di accesso è pari a 𝜃(𝑖).
Per inserire un nuovo elemento nella lista, l'algoritmo prima scandisce l'intera lista per verificare che l'elemento non è già presente, e quindi inserisce l'elemento in questione alla fine della lista. Pertanto, se il numero di elementi nella lista prima dell'inserzione é pari ad n, possiamo assumere che il costo per servire una richiesta di inserimento é pari a n + 1.
Per cancellare un elemento dalla lista l'algoritmo prima effettua una ricerca per trovare l'elemento, poi lo cancella. Pertanto, se l'elemento da cancellare si trova nella posizione i all'interno della lista, possiamo assumere che il costo per servire una richiesta di cancellazione é pari a 𝜃(𝑖).
Mentre l'algoritmo effettua le operazioni necessarie per soddisfare una richiesta, esso può anche scambiare di posizione gli elementi all'interno della lista, al fine di ridurre il costo per soddisfare eventuali richieste future. Ad esempio, immediatamente dopo aver eseguito una operazione di accesso o di inserzione di un elemento, l'algoritmo potrebbe voler spostare lo stesso elemento in una nuova posizione più vicina alla testa della lista. Assumiamo che questa operazione non ci costi nulla, e chiameremo questo tipo di operazioni scambi gratis. Usando scambi gratis l'algoritmo può in linea di principio ridurre il costo per soddisfare successive richieste. Il motivo per cui assumiamo che gli scambi gratis non costino nulla all'algoritmo risiede nel fatto che il “grosso” del lavoro é stato già effettuato con l'accesso o l'inserimento dell'elemento, e quindi il suo eventuale spostamento verso la testa della lista non rappresenta un onere ulteriore significativo. Un altro tipo di modifica all'ordine degli elementi della lista può essere effettuato mediante scambi di due specifici elementi adiacenti nella lista. Il costo di ciascuno di questi scambi è posto ad 1, e chiameremo questo tipo di operazioni scambi pagati. Il nostro obiettivo è quello di progettare un algoritmo che, in corrispondenza ad una sequenza di richieste σ = σ(1) … σ(m), il cui costo individuale di servizio è stato prima definito, riorganizzi la lista in modo da minimizzare il costo totale costo(σ) = costo(𝜎(𝑖))𝑚
𝑖=0 . L'idea intuitiva è di riorganizzare la lista spostando gli elementi più frequentemente acceduti verso la testa della lista. Anche in questo caso una analisi dell'algoritmo basata sul suo comportamento nel caso peggiore non ha senso, in quanto è sempre possibile avere una sequenza di richieste σ costantemente all'ultimo elemento della lista. Su tali sequenze, ogni algoritmo avrebbe costo pari a m volte la lunghezza della lista. Di nuovo, quindi, ha senso effettuare l'analisi del comportamento di algoritmi per il problema dell'aggiornamento delle lista mediante il concetto di competitività. Tra gli algoritmi per l'aggiornamento di liste, probabilmente i più noti sono i seguenti
Move-to-Front (MTF): Muovi l'elemento richiesto alla testa della lista.
Transpose: Scambia l'elemento richiesto con quello immediatamente precedente nella lista.
Frequency-Count: Mantieni un contatore delle frequenza di accesso per ciascun elemento della lista. Ogni qualvolta un elemento è acceduto incrementa il suo contatore di 1. Mantieni la lista in modo tale che gli elementi appaiono sempre nell'ordine di frequenze di accesso non crescente.
Proveremo il seguente risultato. Teorema 11 L'algoritmo MTF è 2-competitivo, ovvero per ogni sequenza di richieste σ vale che
Algoritmi e Strutture Dati 2: Lezione 22 – Accesso e gestione di liste dinamiche
87
costoMTF(σ) ≤ 2 ∙ costoOPT (σ),
dove costoOPT (σ) è il costo dell'algoritmo ottimo off-line che conosce tutta la sequenza σ fin dall'inizio. Proof. Consideriamo una arbitraria sequenza di richieste di accesso σ = σ(1) … σ(m). Confronteremo il comportamento di MTF e dell'algoritmo ottimo (chiamiamolo OPT) offline su ciascuna richiesta σ(i) della sequenza σ usando una funzione ausiliaria φ che definiamo di sotto. Diremo che una coppia di elementi x e y formano una inversione se x occorre prima di y nella lista di MTF, mentre x occorre dopo di y nella lista di OPT (insomma vengono posizionati in ordine inverso). Assumeremo che gli algoritmi MTF e OPT partano con la stessa lista.
Per ogni valore di t, 1 ≤ t ≤ m (m numero di richieste), sia costoMTF (t) il costo in cui incorre l'algoritmo MTF
nel servire la richiesta σ(t), e sia analogamente costoOPT (t) il costo in cui incorre l'algoritmo OPT nel servire
la richiesta σ(t). Inoltre, sia φ(t) il numero di inversioni che si hanno dopo che la richiesta σ(t) è stata servita. In virtù del fatto che gli algoritmi MTF e OPT partono con la stessa identica lista, possiamo senz'altro assumere per convenzione che φ(0) = 0 (non ci sono inversioni). Mostreremo innanzitutto che
∀ 𝑡, 𝑐𝑜𝑠𝑡𝑜𝑴𝑻𝑭 𝑡 + 𝜙 𝑡 − 𝜙 𝑡 − 1 ≤ 2𝑐𝑜𝑠𝑡𝑜𝑶𝑷𝑻 𝑡 − 1 (129)
Prima di provare la validità della formula (129), esaminiamone una sua importante conseguenza. Abbiamo
𝑐𝑜𝑠𝑡𝑜𝑴𝑻𝑭 𝜎 = 𝑐𝑜𝑠𝑡𝑜𝑴𝑻𝑭 𝑡
𝑚
𝑡=1
130 ≤ 2 𝑐𝑜𝑠𝑡𝑜𝑶𝑷𝑻 𝑡 − 1 − 𝜙 𝑡 + 𝜙 𝑡 − 1
𝑚
𝑡=1
131
= 2𝑐𝑜𝑠𝑡𝑜𝑶𝑷𝑻 𝜎 − 𝑚 − 𝜙 𝑚 + 𝜙 0 132 ≤ 2𝑐𝑜𝑠𝑡𝑜𝑶𝑷𝑻 𝜎 (133) dove l'ultima diseguaglianza la si ottiene in quanto φ (0) = 0 e φ (m) ≥ 0. Pertanto, visto che la (129) implica
l'enunciato del Teorema, concentriamoci sulla prova della (129).
Supponiamo per il momento che σ(i) sia una richiesta di accesso ad un elemento ki della lista. Sia ti la
posizione dell'elemento ki nella lista di MTF prima che la richiesta σ(i) venga esaminata, ed analogamente
sia si la posizione dell'elemento ki nella lista di OPT prima che la richiesta σ(i) venga esaminata. Sia inoltre Pi
il numero di scambi pagati che l'algoritmo OPT decide di usare nell'eseguire la richiesta σ(i) (si ricordi che
l'algoritmo MTF non usa scambi pagati). Abbiamo quindi
𝑐𝑜𝑠𝑡𝑜𝑴𝑻𝑭 𝑖 = 𝑡𝑖 , 𝑐𝑜𝑠𝑡𝑜𝑶𝑷𝑻 𝑖 = 𝑠𝑖 + 𝑃𝑖 (134)
Per provare la (129) distinguiamo due casi.
1° Caso: ti > si: Supponiamo per il momento che l'algoritmo OPT non esegua scambi pagati, ovvero Pi = 0. Quindi solo l'elemento acceduto ki può cambiare posizione, e pertanto solo il numero di inversioni che coinvolgono ki può cambiare. Prima che ki cambi posizione, vi sono almeno ti - si inversioni del tipo (x; ki), ovvero ci sono almeno ti - si elementi che sono posizionati prima di ki nella lista di MTF, ma che vengono dopo di ki nella lista di OPT, e quindi il numero di inversioni che coinvolgono l'elemento ki è almeno pari a ti - si. Sia X il numero di inversioni rimanenti, ovvero il numero di inversioni che non coinvolgono l'elemento ki. Abbiamo quindi che
φ (t - 1) ≥ ti - si + X Per definizione, l'algoritmo MTF porta ki alla testa della lista, mentre OPT porterà ki in una qualunque delle posizioni 1, 2, … , si. Pertanto, dopo la esecuzione della richiesta σ(i) ci saranno al più si - 1 inversioni che coinvolgono l'elemento ki, cioè ci saranno al più si - 1 elementi che sono posizionati prima di ki nella lista di OPT ma che vengono dopo ki nella lista di MTF. Il numero X di inversioni nella lista che non coinvolgevano ki è ovviamente rimasto immutato, visto che abbiamo spostato di posizione solo l'elemento ki (si veda la figura di sotto).
Variazione dell’inversione
Algoritmi e Strutture Dati 2: Lezione 22 – Accesso e gestione di liste dinamiche
88
Quindi
φ (t) ≤ si - 1 + X: In altri termini, abbiamo osservato che
φ (t) - φ (t - 1) ≤ (si - 1) - (ti - si). Dalla (134), e ricordando che Pi = 0, otteniamo
𝑐𝑜𝑠𝑡𝑜𝑴𝑻𝑭 𝑡 + 𝜙 𝑡 − 𝜙 𝑡 − 1 = 𝑡𝑖 + 𝜙 𝑡 − 𝜙 𝑡 − 1 ≤ 𝑡𝑖 + 𝑠𝑖 − 1 − 𝑡𝑖 − 𝑠𝑖 = 2𝑠𝑖 − 1= 2𝑐𝑜𝑠𝑡𝑜𝑶𝑷𝑻 𝑡 − 1
e quindi la (129) è provata nel caso in cui Pi = 0. Se invece Pi > 0, osserviamo che ognuno dei Pi scambi pagati può far aumentare la differenza φ (t) - φ (t - 1) al più 1, in quanto uno scambio pagato può creare una sola inversione che prima non c'era. Pertanto, abbiamo che in generale vale
φ (t) - φ (t - 1) ≤ (si - 1) - (ti - si) + Pi. Dalla (134) otteniamo 𝑐𝑜𝑠𝑡𝑜𝑴𝑻𝑭 𝑡 + 𝜙 𝑡 − 𝜙 𝑡 − 1 = 𝑡𝑖 + 𝜙 𝑡 − 𝜙 𝑡 − 1 ≤ 𝑡𝑖 + 𝑠𝑖 − 1 − 𝑡𝑖 − 𝑠𝑖 + 𝑃𝑖 = 2𝑠𝑖 − 1 + 𝑃𝑖
≤ 2𝑠𝑖 + 2𝑃𝑖 − 1 = 2𝑐𝑜𝑠𝑡𝑜𝑶𝑷𝑻 𝑡 − 1 e quindi la (129) è provata in generale.
2° Caso: ti ≤ si. Ragionando come prima possiamo concludere che: 1) prima di eseguire la richiesta σ (i) ci sono almeno ti - si inversioni del tipo (x, ki) (cioè φ (t - 1) ≤ (si - ti) + X, dove X ha lo stesso significato di prima, ovvero conta il numero di inversioni che non coinvolgono ki), 2) dopo che MTF ha portato ki alla testa della lista e che OPT ha spostato ki in qualche posizione compresa tra 1, … , si, ci saranno al più si - 1 inversioni della forma (x, ki) (cioè φ (t) ≤ (si - 1) + X), 3) dopo che OPT ha eseguito i suoi Pi scambi pagati, possiamo avere al più altre Pi inversioni. Di conseguenza
𝑐𝑜𝑠𝑡𝑜𝑴𝑻𝑭 𝑡 + 𝜙 𝑡 − 𝜙 𝑡 − 1 = 𝑡𝑖 + 𝜙 𝑡 − 𝜙 𝑡 − 1 ≤ 𝑡𝑖 + 𝑠𝑖 − 1 − 𝑠𝑖 − 𝑡𝑖 + 𝑃𝑖 = 2𝑡𝑖 − 1 + 𝑃𝑖
≤ 2𝑠𝑖 − 1 + 𝑃𝑖 ≤ 2𝑠𝑖 + 2𝑃𝑖 − 1 = 2𝑐𝑜𝑠𝑡𝑜𝑶𝑷𝑻 𝑡 − 1 e quindi la (129) è provata anche in questo caso. Ci resta da considerare il caso in cui la richiesta σ (i) possa essere una richiesta di inserzione o di cancellazione. Nel caso in cui σ (i) è una richiesta di inserzione, allora abbiamo
costoMTF(t) = n + 1 e costoOPT (t) = n + 1;
dove n è la lunghezza della lista prima della inserzione. Inoltre, è semplice osservare che nessuna nuova inversione viene creata dalla inserzione, pertanto
φ (t) - φ (t - 1) = 0 Le due ultime uguaglianze provano la (129) anche nel caso in cui la richiesta σ(i) è una richiesta di inserzione. La prova della (129) nel caso in cui la richiesta σ(i) sia di una cancellazione è molto simile alla corrispondente prova nel caso in cui a richiesta σ(i) sia di accesso. Basta solo osservare che la cancellazione di un elemento non crea nuove inversioni, ed elimina tutte quelle che coinvolgevano l'elemento cancellato. Pertanto, se ad esempio la richiesta σ (i) di cancellazione fosse relativa ad un elemento ki che si trova nella posizione ti della lista di MTF e nella posizione si della lista di OPT, allora per quanto osservato prima, ci
Algoritmi e Strutture Dati 2: Lezione 22 – Accesso e gestione di liste dinamiche
89
sono almeno ti - si inversioni del tipo (x, ki) che saranno tutte eliminate a causa della cancellazione di ki, se ti > si, (ce ne saranno invece almeno si - ti eliminate se ti ≤ si). Pertanto, sotto l'ipotesi che Pi = 0, avremo che
φ (t) - φ (t - 1) ≤ - (ti - si); se ti > si, mentre
φ (t) - φ (t - 1) ≤ - (si - ti); se ti ≤ si, e procedendo come prima proveremmo la (129). Se Pi > 0, entrambe le espressioni si sopra possono crescere al più di Pi, ma anche il costo costoOPT (t) crescerebbe della stessa quantità, quindi come prima possiamo dedurre che la (129) vale. Avendo quindi provato la (129) in tutti i casi possibili, possiamo concludere che MTF è 2-competitivo. Possiamo provare che il fattore di competitività 2 non è essenzialmente migliorabile. Consideriamo un generico algoritmo on-line A, e costruiamo una sequenza σ di m richieste di accesso, ciascuna richiedente l'elemento posizionato alla coda della lista mantenuta da A. E’ chiaro che il costo di un tale algoritmo su di una tale sequenza σ soddisfa la relazione
costoA(σ) = n ∙ m,
dove n è il numero di elementi della lista. In altre parole, abbiamo osservato che per ogni algoritmo on-line A esiste una particolare sequenza di m richieste che lo forza ad avere un costo di n ∙ m. Consideriamo ora l'algoritmo B off-line che, conoscendo σ per intera fin dall'inizio si calcola la frequenza di accesso di ciascun elemento, ovvero per ciascun elemento della lista si calcola il numero di volte in cui esso verrebbe richiesto in σ. Ciò fatto, usando gli scambi pagati, può ordinare la lista nell'ordine dettato dalle frequenze decrescenti (cioè mette nella testa l'elemento maggiormente acceduto, e via via fin quando non mette nell'ultima posizione l'elemento che verrebbe richiesto il minor numero di volte). Questa operazione costa a B al più n(n - 1)/2 (per esempio, l'algoritmo B potrebbe usare BubbleSort per ordinare la lista in accordo alle frequenze decrescenti). Avendo adesso la lista ordinata, gli m accessi richiesti da σ costeranno all'algoritmo B una quantità pari a
𝑖 𝑓𝑖
𝑛
𝑖=1
dove 𝑓𝑖 è il numero di volte che l'elemento posizionato nella posizione i della lista di B deve essere acceduto. Poichè B ha disposto i suoi elementi nella lista in modo tale che 𝑓1 ≥ 𝑓2 ≥ ⋯ ≥ 𝑓𝑛 , si può dimostrare che
𝑖 𝑓𝑖
𝑛
𝑖=1
≤𝑚
𝑛 𝑖
𝑛
𝑖=1
=𝑚(𝑛 + 1)
2
Da ciò otteniamo che per ogni sequenza di richieste σ, per l'algoritmo OPT off-line vale che
𝑐𝑜𝑠𝑡𝑜𝑶𝑷𝑻 𝜎 ≤ 𝑐𝑜𝑠𝑡𝑜𝑩 𝜎 ≤𝑚(𝑛 + 1)
2+
𝑛(𝑛 − 1)
2
Ovvero
𝑐𝑜𝑠𝑡𝑜𝑶𝑷𝑻 𝜎 −𝑛(𝑛 − 1)
2≤
𝑚(𝑛 + 1)
2
Di conseguenza, in corrispondenza alla particolare sequenza di richieste σ sopra definita, vale che
𝑐𝑜𝑠𝑡𝑜𝑨 𝜎 = 𝑚𝑛 =𝑚(𝑛 + 1)
2∙
2𝑛
(𝑛 + 1)≥
2𝑛
(𝑛 + 1)∙ 𝑐𝑜𝑠𝑡𝑜𝑶𝑷𝑻 𝜎 −
𝑛 𝑛 − 1
2
= 2 −2
𝑛 + 1 𝑐𝑜𝑠𝑡𝑜𝑶𝑷𝑻 𝜎 −
𝑛
(𝑛 + 1)𝑛 𝑛 − 1 ≥ 2 −
2
𝑛 + 1 𝑐𝑜𝑠𝑡𝑜𝑶𝑷𝑻 𝜎 − 𝑛 𝑛 − 1
I termini in n sono negligibili rispetto a costoA(σ) e costoOPT (σ) (in quanto possiamo considerare una
sequenza di richieste σ molto lunga), inoltre se la lista contiene un numero di elementi n sufficientemente grande anche il termine 2/(n+1) diventa non significativo. Pertanto, possiamo concludere che il fattore di competitività 2 raggiunto dall'algoritmo MTF è essenzialmente ottimo. Ci resterebbe da provare che
Algoritmi e Strutture Dati 2: Lezione 22 – Accesso e gestione di liste dinamiche
90
𝑖 𝑓𝑖
𝑛
𝑖=1
≤𝑚
𝑛 𝑖
𝑛
𝑖=1
sotto l'ipotesi che 𝑓1 ≥ 𝑓2 ≥ ⋯ ≥ 𝑓𝑛 . Se 𝑓1 = 𝑓2 = ⋯ = 𝑓𝑛 , allora necessariamente vale che 𝑓𝑖 = m/n per ogni i = 1,…,n e quindi la formula è provata. Supponiamo quindi che non tutti gli 𝑓𝑖 sono uguali tra di loro. Ad esempio, esistono indici k e j, con k < j tali che fk > fj. Definiamo nuovi 𝑓′𝑖 nel seguente modo
𝑓𝑖′ =
𝑓𝑘 − 1 𝑠𝑒 𝑖 = 𝑘𝑓𝑗 + 1 𝑠𝑒 𝑖 = 𝑗
𝑓𝑖 𝑎𝑙𝑡𝑟𝑖𝑚𝑒𝑛𝑡𝑖
Calcoliamo
𝑖 𝑓𝑖
𝑛
𝑖=1
− 𝑖 𝑓𝑖′
𝑛
𝑖=1
= 𝑘𝑓𝑘 + 𝑗𝑓𝑗 − 𝑘𝑓𝑘′ − 𝑗𝑓𝑗
′ = 𝑘𝑓𝑘 + 𝑗𝑓𝑗 − 𝑘 𝑓𝑘 − 1 − 𝑗 𝑓𝑗 + 1 = 𝑘 − 𝑗 < 0
Pertanto,
𝑖 𝑓𝑖
𝑛
𝑖=1
< 𝑓𝑖′
𝑛
𝑖=1
La morale della storia di sopra è la seguente: se esistono fk e fj tali che fk ≠ fj, allora possiamo definire nuovi 𝑓′𝑖 in cui la differenza tra 𝑓′𝑘 e 𝑓′𝑗 è “diminuita”, e la somma 𝑖𝑓′𝑖
𝑛𝑖=1 è aumentata. Possiamo effettuare
questo procedimento, e quindi aumentare sempre la somma, fin quando non ci saranno più differenze tra gli fi, ovvero fi = m/n, per ogni i. In corrispondenza a tali valori di fi avremo raggiunto il valore massimo della somma. Il che equivale a dire che
𝑖 𝑓𝑖
𝑛
𝑖=1
≤𝑚
𝑛 𝑖
𝑛
𝑖=1
Algoritmi e Strutture Dati 2: Lezione 23 – Algoritmi on line
91
Lezione 23 – Algoritmi on line
Scheduling di Job Input: 𝑚 𝑚𝑎𝑐𝑐𝑖𝑛𝑒 𝑀1 , … , 𝑀𝑚 𝑢𝑛𝑎 𝑠𝑒𝑞𝑢𝑒𝑛𝑧𝑎 𝜎 = 𝐽1, … , 𝐽𝑛 𝑑𝑖 𝑑𝑢𝑟𝑎𝑡𝑎 𝑝 𝐽1 , … , 𝑝 𝐽𝑛 𝑟𝑖𝑠𝑝𝑒𝑡𝑡𝑖𝑣𝑎𝑚𝑒𝑛𝑡𝑒
Output: un’assegnazione di job a macchine in modo tale che sia minimizzato il tempo entro il quale tutti i job vengono eseguiti
Più precisamente, assumiamo che i job costituenti la sequenza ς si presentino in input all'algoritmo A in
successione. In corrispondenza ad ogni job Js, s = 1,..,n, l'algoritmo dovrà immediatamente decidere a quale
delle macchine Mk, k = 1..m assegnarlo. Sia 𝑆𝑘𝑖 l'insieme dei job assegnati dall'algoritmo A alla macchina Mk,
in corrispondenza alla sottosequenza J1..Ji dei job. Il carico della generica macchina Mk dopo che l'algoritmo
A ha processato la sottosequenza J1..Ji dei job sarà quindi:
𝐿𝑘𝑖 𝐴 = 𝑝(𝐽)
𝐽∈𝑆𝑘𝑖
ed il makespan dell'algoritmo A sarà:
𝐿 𝐴 = 𝑚𝑎𝑥𝑘=1,…,𝑚𝐿𝑘𝑛 𝐴
Cerchiamo un algoritmo on-line A che abbia L(A) minimo. La tecnica greedy ci suggerisce immediatamente il seguente algoritmo:
Assegna il job 𝐽𝑠, s=1,…,n dalla macchina 𝑀𝑘 per cui
𝐿𝑘𝑠−1 = min{𝐿1
𝑠−1 , … , 𝐿𝑚𝑠−1}
Ovvero alla macchina correntemente con il minor carico.
Vogliamo provare che:
∀𝜎, 𝑐𝑜𝑠𝑡𝑜𝒈𝒓𝒆𝒆𝒅𝒚 𝜎 ≤ 2𝑐𝑜𝑠𝑡𝑜𝑶𝑷𝑻 𝜎 , (135)
dove costogreedy(ς) è il makespan dell'algoritmo greedy in corrispondenza di ς, e costoOPT (ς) è il corrispondente costo dell'algoritmo ottimo offline. Osserviamo innanzitutto le seguenti due limitazioni inferiori a costoOPT (ς) Vale:
∀𝜎, 𝑐𝑜𝑠𝑡𝑜𝑶𝑷𝑻 𝜎 ≥ 𝑚𝑎𝑥𝑠=1,…,𝑛 𝑝 𝐽𝑠 𝑒 ∀𝜎, 𝑐𝑜𝑠𝑡𝑜𝑶𝑷𝑻 𝜎 ≥1
𝑚 𝑝 𝐽𝑠
𝑛
𝑠=1
La prima è ovvia. La seconda la si ottiene una volta che si osserva che (1 𝑚 ) 𝑝 𝐽𝑠 𝑛𝑠=1 rappresenta il
tempo necessario per eseguire tutti i job. Visto che abbiamo a disposizione m macchine, almeno una di esse dovrà lavorare per un tempo pari a (1 𝑚 ) 𝑝 𝐽𝑠
𝑛𝑠=1 .
Supponiamo ora che l'algoritmo greedy abbia effettuato una certa assegnazione di job alle macchine, risultante in un dato carico 𝐿1
𝑛 . . 𝐿𝑚𝑛 . Sia Mh la macchina con il carico massimo, e sia Jt l'ultimo job ad essa
assegnato dall'algoritmo greedy. In altri termini, stiamo assumendo che: 𝑐𝑜𝑠𝑡𝑜𝒈𝒓𝒆𝒆𝒅𝒚 𝜎 = 𝐿
𝑛
Sosteniamo che per il valore 𝐿𝑛 vale che:
∀ 𝑖 , 𝐿𝑖𝑛 ≥ 𝐿
𝑛 − 𝑝 𝐽𝑡 (138) Infatti, al momento in cui viene assegnato il job Jt alla macchina Mh, essa risulta essere la meno carica (per come opera l'algoritmo greedy). Quindi otteniamo:
𝑊 = 𝐿𝑖𝑛
𝑚
𝑖=1
≥ 𝐿𝑛 − 𝑝 𝐽𝑡 = 𝑚 𝐿
𝑛 − 𝑝 𝐽𝑡
𝑚
𝑖=1
Da cui:
𝐿𝑛 − 𝑝 𝐽𝑡 ≤
𝑊
𝑚
Osserviamo ora che
Algoritmi e Strutture Dati 2: Lezione 23 – Algoritmi on line
92
𝑝 𝐽𝑖
𝑛
𝑖=1
= 𝐿𝑘𝑛
𝑚
𝑖=1
Pertanto:
𝑐𝑜𝑠𝑡𝑜𝒈𝒓𝒆𝒆𝒅𝒚 𝜎 = 𝐿𝑛 ≤
𝑊
𝑚+ 𝑝 𝐽𝑡 =
1
𝑚 𝑝 𝐽𝑠
𝑛
𝑠=1
+ 𝑝 𝐽𝑡 ≤ 𝑐𝑜𝑠𝑡𝑜𝑶𝑷𝑻 𝜎 + 𝑐𝑜𝑠𝑡𝑜𝑶𝑷𝑻 𝜎
Il che completa la dimostrazione di (135).
Bin packing on-line Esaminiamo ora il seguente problema, risolvibile anch'esso attraverso la tecnica greedy.
Input: 𝑢𝑛𝑎 𝑠𝑒𝑞𝑢𝑒𝑛𝑧𝑎 𝜎 = 𝜎 1 , … , 𝜎 𝑚 𝑑𝑜𝑣𝑒 𝑜𝑔𝑛𝑖 𝜎 𝑖 𝑟𝑎𝑝𝑝𝑟𝑒𝑠𝑒𝑛𝑡𝑎 𝑢𝑛 𝑜𝑔𝑔𝑒𝑡𝑡𝑜 𝑑𝑖 𝑡𝑎𝑔𝑙𝑖𝑎 𝑎𝑖 ,
𝑐𝑜𝑛 0 < 𝑎𝑖 ≤ 1 𝑢𝑛 𝑖𝑛𝑠𝑖𝑒𝑚𝑒 𝑑𝑖 𝑐𝑜𝑛𝑡𝑒𝑛𝑖𝑡𝑜𝑟𝑖 𝐵1 , … , 𝐵𝑏 , 𝑏 ≥ 𝑚, 𝑐𝑖𝑎𝑠𝑐𝑢𝑜𝑛𝑜 𝑑𝑖 𝑐𝑎𝑝𝑎𝑐𝑖𝑡à 𝑝𝑎𝑟𝑖 𝑎 1
Output: un’assegnazione di tutti gli oggetti 𝜎 a contenitori, con la condizione che la somma delle taglie degli oggetti assegnati a ciascun contenitore non superi 1, e che minimizzi il numero totale di contenitori usati.
Un possibile algoritmo on-line per questo problema può essere il seguente:
Algoritmo next-fit
j=1 for i=1 to m do
aggiungi l’oggetto 𝜎 𝑖 in 𝐵𝑗 se ci va,
else poni j=j+1 e inserisci 𝜎 𝑖 in 𝐵𝑗
Sia costoNEXT-FIT(ς) il numero di contenitori usati dall'algoritmo greedy NEXT-FIT per impacchettare tutti gli
oggetti in ς, e sia costoOPT (ς) il corrispondente numero di contenitori usato dall'algoritmo ottimo offline
che conosce tutta la sequenza di richieste fin dall'inizio. Vogliamo provare che:
𝑐𝑜𝑠𝑡𝑜𝑵𝑬𝑿𝑻−𝑭𝑰𝑻 𝜎 ≤ 2𝑐𝑜𝑠𝑡𝑜𝑶𝑷𝑻 𝜎 + 1
Osserviamo innanzitutto che:
𝑐𝑜𝑠𝑡𝑜𝑶𝑷𝑻 𝜎 ≥ 𝑎𝑖
𝑚
𝑖=1
in quanto occorre sicuramente usare un numero di contenitori superiore alla somma totale delle
dimensioni degli oggetti in ς. Consideriamo la soluzione prodotta dall'algoritmo greedy, e supponiamo che
esso abbia usato i contenitori
𝐵1, . . , 𝐵𝑠
e quindi costoNEXT-FIT(ς) = s. L'osservazione chiave è che:
𝑎𝑖
𝜎 𝑎𝑖 ∈ 𝐵𝑗
+ 𝑎𝑖
𝜎 𝑎𝑖 ∈ 𝐵𝑗+1
≥ 1 ∀𝑗 = 1, … , 𝑠 − 1 (141)
Infatti, se ciò non fosse, non avremmo usato il nuovo contenitore Bj+1 ma avremmo messo tutti gli oggetti
in Bj . Di conseguenza:
𝑎𝑘
𝑚
𝑘=1
= 𝑎𝑖
𝜎 𝑎𝑖 ∈ 𝐵1
+ 𝑎𝑖
𝜎 𝑎𝑖 ∈ 𝐵2
+ ⋯ + 𝑎𝑖
𝜎 𝑎𝑖 ∈ 𝐵𝑠
≥ 1 + ⋯ + 1 (𝑟𝑖𝑝𝑒𝑡𝑢𝑡𝑜𝑠 − 1
2 𝑣𝑜𝑙𝑡𝑒 𝑝𝑜𝑖𝑐è 𝑟𝑎𝑔𝑔𝑟𝑢𝑝𝑝𝑖𝑎𝑚𝑜 𝑙𝑒 𝑠𝑜𝑚𝑚𝑒 𝑎 𝑑𝑢𝑒 𝑎 𝑑𝑢𝑒 𝑐𝑜𝑛𝑠𝑒𝑐𝑢𝑡𝑖𝑣𝑎𝑚𝑒𝑛𝑡𝑒
=𝑠 − 1
2
Da cui:
Algoritmi e Strutture Dati 2: Lezione 23 – Algoritmi on line
93
𝑐𝑜𝑠𝑡𝑜𝑵𝑬𝑿𝑻−𝑭𝑰𝑻 𝜎 = 𝑠 ≤ 2 𝑎𝑘
𝑚
𝑘=1
+ 1 ≤ 2𝑐𝑜𝑠𝑡𝑜𝑶𝑷𝑻 𝜎 + 1
L'approccio suggerito dall'analisi degli algoritmi on-line può essere utile anche in altri contesti. Uno di
questi riguarda classici problemi della Teoria delle Decisioni. Ci limitiamo, in questa lezione, a presentare ed
analizzare due semplici esempi.
Affitto sci Il problema può essere descritto come segue. Sia N > 1 un intero. Una persona deve usare un
equipaggiamento (sci) per un qualche numero T di giorni, 1 ≤T≤N. Assumiamo che il valore N sia noto alla
persona, ma che T non lo sia (esso può infatti dipendere da ovvi fattori non dipendenti dalla volontà della
persona).
All'inizio di ogni giorno, è noto alla persona in questione se gli occorrono o meno gli sci per la giornata.
Pertanto, la persona deve effettuare una scelta tra le seguenti due opzioni:
1. Affittare gli sci per la giornata, ad un costo assumiamo pari ad 1;
2. Comprare gli sci, ad un costo pari ad un certo valore B>>1.
Ovviamente, una volta che la persona abbia acquistato gli sci, non incorrerà in ulteriori spese nei giorni
successivi in cui deciderà ancora di sciare. Potrebbe, però, decidere di non voler più sciare (tutto dipende
dal valore incognito di T). Il costo totale in cui la persona incorre e ovviamente pari all'eventuale numero di
giorni in cui ha affittato gli sci, più il costo dell'acquisto degli stessi. Si pone, pertanto, il problema di
stabilire una strategia che minimizzi il costo, senza però conoscere il futuro (ovvero, il valore T dei giorni in
cui effettivamente si scierà).
In questo caso, l'algoritmica on-line può essere di aiuto. Consideriamo un generico algoritmo Ai che
effettua la seguente decisione: stabilisce un intero i ≥ 0, affitta gli sci per i giorni e, se ha ancora voglia di
sciare dopo tale periodo, li acquista. Abbiamo ovviamente
𝑐𝑜𝑠𝑡𝐴𝑖=
𝑇 𝑠𝑒 𝑇 ≤ 𝑖𝑖 + 𝐵 𝑠𝑒 𝑇 > 1
(142)
La strategia ottima che conosce il futuro, ovvero T, deciderà ovviamente di comprare gli sci se il periodo
effettivo T in cui si scierà è > B, deciderà di affittarli giorno per giorno, in caso contrario. Pertanto
𝑐𝑜𝑠𝑡𝑂𝑃𝑇 = min{𝐵, 𝑇}
Vogliamo provare che il miglior algoritmo consiste nello scegliere i = B - 1. In tal caso abbiamo
𝑐𝑜𝑠𝑡𝐴𝐵−1=
𝑇 𝑠𝑒 𝑇 ≤ 𝑖 = 𝐵 − 1 𝐵 − 1 + 𝐵 = 2𝐵 − 1 𝑠𝑒 𝑇 > 𝑖 = 𝐵 − 1
(142)
Inoltre:
𝑐𝑜𝑠𝑡𝑂𝑃𝑇 = min 𝐵, 𝑇 = 𝑇 𝑠𝑒 𝑇 ≤ 𝐵 − 1𝐵 𝑠𝑒 𝑇 > 𝐵 − 1
Abbiamo pertanto che qualunque sia il valore incognito di T, vale che:
𝑐𝑜𝑠𝑡𝐴𝐵−1≤
2𝐵 − 1
𝐵𝑐𝑜𝑠𝑡𝑂𝑃𝑇 = 2 −
1
𝐵 𝑐𝑜𝑠𝑡𝑂𝑃𝑇
Proviamo ora che nessun altra scelta del valore di i può portare a coefficienti di competitività migliori di
quello appena trovato. Distinguiamo due casi.
Caso 1: i ≤ B - 1. Nell'ipotesi che T = i + 1, abbiamo 𝑐𝑜𝑠𝑡𝐴𝑖
𝑐𝑜𝑠𝑡𝑂𝑃𝑇=
𝑖 + 𝐵
min 𝐵, 𝑇 =
𝑖 + 𝐵
min 𝑖 + 1, 𝑇 =
𝑖 + 𝐵
i + 1≥
𝐵 − 1 + 𝐵
𝐵 − 1 + 1=
2𝐵 − 1
𝐵= 2 −
1
B
Quindi il coefficiente di competitività non è migliorato.
Caso 2: i > B - 1. Nell'ipotesi che T = i + 1, abbiamo 𝑐𝑜𝑠𝑡𝐴𝑖
𝑐𝑜𝑠𝑡𝑂𝑃𝑇=
𝑖 + 𝐵
min 𝐵, 𝑇 =
𝑖 + 𝐵
min 𝑖 + 1, 𝑇 =
𝑖 + 𝐵
B= 1 +
𝑖
𝐵≥ 2
Algoritmi e Strutture Dati 2: Lezione 23 – Algoritmi on line
94
Anche in questo caso il coefficiente di competitività non è migliorato. Deduciamo quindi che la scelta
ottima consiste nello scegliere i = B - 1.
Compravendita di azioni Supponiamo di avere un'azione, il cui prezzo è noto poter variare tra due valori m e M, con 0 < m < M
entrambi noti a priori. All'inizio di ogni giornata i-esima i = 1,2,…. veniamo a conoscenza del valore vi ϵ [m,
M] giornaliero dell'azione, e dobbiamo decidere se vendere l'azione, e quindi realizzare un profitto vi,
oppure mantenere il possesso dell'azione. Qual è la strategia migliore, ovvero quella che ci massimizza il
profitto? Anche in questo caso ci troviamo di fronte ad un problema suscettibile di analisi mediante
l'algoritmica on-line.
Una generica strategia potrebbe essere la seguente: si stabilisca a priori un valore p ϵ [m, M], si venda
l'azione il primo giorno in cui vi ≥ p, altrimenti si mantenga l'azione. Come scegliere il valore p in modo da
massimizzare il nostro profitto? Sia 𝑝𝑚𝑎𝑥 il valore massimo assunto da vi durante tutto il periodo in
considerazione. Ovviamente, noi non conosciamo tale valore 𝑝𝑚𝑎𝑥 . Possono capitare due casi, a seconda
della relazione sussistente tra il valore p che abbiamo noi scelto ed il valore incognito 𝑝𝑚𝑎𝑥 .
Caso 1: p ≤ 𝑝𝑚𝑎𝑥 .
In tal caso, ci sarà un giorno in cui vi ≥ p, e pertanto realizzeremo un profitto p. Considerando
invece l’algoritmo off-line, potrebbe accadere che il valore dell'azione continui a crescere ed arrivi
al valore massimo M. L'algoritmo ottimo on-line A venderà l'azione esattamente quando essa varrà
p. Quindi, il rapporto è: 𝑐𝑜𝑠𝑡 𝐴
𝑐𝑜𝑠𝑡 𝑂𝑃𝑇=
𝑝
𝑀.
Caso 2: p > 𝑝𝑚𝑎𝑥 .
In tal caso, non ci sarà mai un giorno in cui vi ≥p, quindi non venderemmo mai per tutta la durata
del periodo in questione. Potrebbe accadere, pertanto, che alla fine del periodo l'azione valga m,
quindi questo è il profitto che realizzeremo.
L'algoritmo ottimo off-line, invece, venderà appena l'azione vale 𝑝𝑚𝑎𝑥 , realizzando un profitto
appunto pari a 𝑝𝑚𝑎𝑥 . Il rapporto tra il profitto dell'algoritmo on-line A e dell'algoritmo ottimo
off-line è in questo caso 𝑐𝑜𝑠𝑡 𝐴
𝑐𝑜𝑠𝑡 𝑂𝑃𝑇=
𝑚
𝑝𝑚𝑎𝑥 che può ovviamente essere arbitrariamente prossimo a
m/p.
Il miglior algoritmo on-line è sicuramente quello che sceglierà p in modo tale che vi sia bilanciamento tra le
due possibili situazioni, ovvero per cui valga: 𝑝
𝑀=
𝑚
𝑝⟹ 𝑝2 = 𝑚𝑀 ⟹ 𝑝 = 𝑚𝑀
ovvero sceglierà il valore p pari a 𝑝 = 𝑚𝑀
Detto in altri termini, l'algoritmo on-line ottimo è quello che decide, giorno per giorno, di vendere l'azione
se il suo valore vi ≥ 𝑚𝑀 e che decide di mantenere il possesso dell'azione in caso contrario. Il fattore di
competitività di un tale algoritmo è pari a: 𝑀/𝑚.