PROGRAMMAZIONE LINEARE A cura di Gerardo Catena In questo

PROGRAMMAZIONE LINEARE
A cura di Gerardo Catena
In questo paragrafo studieremo come approssimare le soluzioni ai problemi difficili
da trattare(NP-Hard) utilizzando il metodo della programmazione lineare.
I problemi che studieremo sono due:
1- Minimum Vertex Cover
2- Set Cover
SCHEMA:
Lo schema logico che adotta l’approssimazione via programmazione lineare
è il seguente:
1) Ad ogni soluzione ammissibile S associamo un vettore binario distinto
X= <x1,x2,x3…,xn>
Dove
xi  0,1
1 se xi є S
xi=
0 altrimenti
Ad ogni Si è assegnato un costo C(Si) e vogliamo minimizzare(o massimizzare)
 c(Si)  X
Si
SiS
In pratica si prende il problema originale e lo si formula come problema di
programmazione lineare intero.
Tale problema è, però, ancora difficile da trattare. Tale difficoltà deriva dal vincolo di
interezza xi  0,1;
2) Prendere il problema intero e rilassare i vincoli facendo in modo che 0≤xi ≤1
anziché xi  0,1;
3) Trovare la soluzione ottima al problema rilassato.
4) Adottare un criterio per riconvertire in soluzione al problema intero quella del
problema rilassato.
Esempio:
se X = (1/2,2/5,1/2,3/10) è il vettore della soluzione ottima al problema rilassato si
potrebbe pensare di includere nella soluzione tutti quegli elementi i che hanno
xi ≥1/2; dopo il passo 4 è come se avessimo selezionato la soluzione ammissibile del
problema intero con vettore associato X=<1,0,1,0> visto che abbiamo messo ad 1
solo quelle xi che avevano valore maggiore o uguale di ½.
In pratica dopo il passo 4 otteniamo un vettore intero che è una soluzione
ammissibile per il problema intero. Ci resta da capire in che modo la soluzione ottima
è stata approssimata dopo la selezione fatta al passo 4. Ciò dipende dal particolare
problema che vogliamo approssimare.
ALGORITMI
Set-Cover
Il problema è il seguente:
abbiamo un insieme U={e1, e2, …,en} di n elementi ed una famiglia F  U di m elementi:
F={S1, S2, …,Sm}
Ad ogni insieme Si è associato un costo tramite la funzione c: Si F  c(Si)  R+.
Ci interessa un sottoinsieme F’ di F che copra U, cioè  S  U , e che minimizzi il
S F '
costo della copertura (dato F’  F definiamo il costo di F’ come c(F’)=
 c(S) ).
S F '
Cerchiamo F’ t.c minimizzi c(F’).
Il problema è NPC e quello che possiamo fare è approssimarlo. Per fare ciò
utilizziamo lo schema della programmazione lineare.
Associamo ad ogni possibile sottofamiglia F’un vettore binario distinto
XF’ =< Xs1, Xs2,…., Xsm>
Con:
1 se Si  F’
Xsi =
1 se Si  F’
0 se Si  F’
dove Xsi  0,1.
Ora possiamo scrivere c(F’) in funzione di questo vettore:
c(F’)=  c(S) *xs
SF '
Abbiamo detto che F’ è una copertura e l’abbiamo espresso con  S  U .
S F '
Sfruttando il vettore XF’ ,possiamo esprimere questo risultato insiemistico come
vincolo:

S  U
XS  1  e  U
S:eS
S F '
Stiamo dicendo che se l’elemento è contenuto, ad esempio, negli insiemi S1, S2 ,S3
S4 allora, per definizione di copertura, almeno uno degli insiemi appena elencati deve
fare parte di F’, quindi almeno uno tra Xs1 ,Xs2 ,Xs3 ed Xs4 deve valere 1 quindi
Xs1 +Xs2 +Xs3 +Xs4  1.
Riassumendo la formulazione del problema Set-Cover via programmazione lineare è
la seguente:
minimizzare
 c(S)  X
S
SF
soggetto ai vincoli

XS  1  e  U
S:eS
XS  0,1
Abbiamo appena terminato il passo 1) dello schema ottenendo la formulazione del
problema sotto forma di programmazione intera.
Tale riformulazione non rende il problema più facile da risolvere a causa del vincolo
di interezza.
Andiamo perciò a riformulare ulteriormente il problema, rilassando il vincolo di
interezza:
minimizzare
 c(S)  X
S
SF
soggetto ai vincoli

XS  1  e  U
S:eS
XS  1  S  F
XS  0  S  F
Così riformulato il Set-Cover diventa risolvibile in tempo polinomiale in quanto si
tratta di minimizzare una funzione lineare soggetta a dei vincoli lineari.
Vediamo in che relazione sta il problema intero con quello rilassato.
Nel problema intero i pesi degli elementi di F o vengono considerati per intero o per
niente in quanto la Xs o è 0 oppure è 1.
Nel problema rilassato invece possiamo anche considerare frazioni dei pesi degli
elementi di F in quanto Xs può assumere un valore che è compreso tra 0 ed 1.
Per questo motivo se OPT è la soluzione ottima la problema intero e OPTR è la
soluzione al problema rilassato abbiamo che
OPTR  OPT
In pratica nel problema rilassato consideriamo uno spazio delle soluzioni ammissibili
più ampio, quindi sicuramente troviamo una soluzione migliore.
Una volta calcolato OPTR abbiamo concluso il passo 3) dello schema. Ci resta da
individuare un criterio che ci permetta di selezionare, all’interno di tale soluzione,
la nostra soluzione approssimata al problema intero. Se considerassimo banalmente
ogni Xs  0 otterremmo sicuramente una copertura di U, e quindi una soluzione
ammissibile al problema intero, ma che si discosta di molto da quella ottima.
Per individuare un arrotondamento intelligente passiamo a definire la seguente
quantità:
 e  U definiamo f(e) = numero di insiemi S  F
dell’elemento e),
e sia
f = max
f(e).
eU
Andiamo a selezionare tutti gli S tali che Xs  1/f .
che contengono e (frequenza
ALGORITMO-SET-COVER
1-Risolvi X soluzione al problema rilassato
2-F’= 
3-For all S F do
4- If Xs  1/f
5- Then F’= F’   S 
6-return F’
Analisi dell’algoritmo
1) Complessità temporale.
L’algoritmo appena presentato è sicuramente polinomiale: la linea 1 risolve un
problema di programmazione lineare che richiede tempo polinomiale ed il ciclo
della linea 3 richiede tempo lineare in |F|.
2) Correttezza.
Dimostriamo che l’algoritmo restituisce una copertura di U. Per farlo dobbiamo
provare che  e  U  S  F’ tale che e S.
Consideriamo un elemento e U . La sommatoria  XS  1  e  U contiene
S:eS
proprio f(e) elementi per definizione di f(e) stesso: essa è definita su tutti gli S tali
che e S.
Se questa somma è almeno 1 ci deve essere almeno un elemento della somma
maggiore o uguale ad 1/f(e). Da ciò si deduce che  S : XS  1/f(e).
Poiché f(e)  f per definizione, si ha che  S : XS  1/f(e)  1/f.
In base all’algoritmo tale S viene incluso in F’. Quindi abbiamo coperto l’elemento
e di U. Ciò è vero per ogni e, quindi l’algoritmo restituisce una copertura di U.
3) Rapporto limite.
L’algoritmo ha rapporto limite f.
Infatti abbiamo arrotondato ogni XS  1/f ad 1. Ciò equivale a moltiplicare Xs per al
più f .
Sappiamo che OPTR =  c(S)  XS .
SF
Per ottenere F’ moltiplichiamo i vari c(S) di OPTR per al più f ottenendo una
soluzione di costo minore o uguale di f volte OPTR:
C(F’)  f* OPTR
Ma, come già discusso
OPTR  OPT allora f* OPTR  f* OPT.
Da questi due risultati si ricava che l’algoritmo ha rapporto limite f:
C(F’)  f* OPT.
[Vazirani par. 14.1]
Set-Cover randomizzato
Presentiamo ora un algoritmo di programmazione lineare per Set-Cover con fattore di
approssimazione logaritmico.
Partiamo ancora una volta dalla soluzione ottima al problema rilassato Xs, ma questa
volta interpretiamo le sue componenti come probabilità:
Xsi = probabilità che Si venga incluso nella soluzione F’.
In pratica è come se avessimo m=|F| bit a zero e scegliamo in maniera random i bit da
porre ad 1 (la nostra soluzione intera). L’i-esimo bit avrà probabilità Xsi di essere
posto ad 1. In pratica le Xsi è come se avessero il compito di pesare l’esito
dell’evento di un lancio di una moneta: se l’evento testa equivale all’evento “includo
il sottoinsieme nella soluzione” e l’evento croce equivale all’evento “non includo il
sottoinsieme nella soluzione”, allora per esempio P(T al terzo lancio)=Xs3 .
Dopo il primo lancio di queste monete avremo una certa probabilità che gli insiemi
posti nella soluzione (i bit messi ad uno nell’esempio precedente) siano una copertura
di U. Si può ripetere l’esperimento k volte ed unire i risultati dei lanci diminuendo
così la probabilità che un elemento di U resti scoperto.
Risulta perciò critica la scelta di k.
Presentiamo di seguito l’algoritmo ed analizziamolo, dando anche un valore a k.
ALGORITMO:
1-F’= 
2-C’= 
3-Xsi =soluzione al problema rilassato
4- for k=1 to dlogn
5- do for all i=1 to m
6do includi Si con probabilità Xsi nella soluzione F’
7- C’=C’  F’
8F’= 
8- return C’.
ANALISI
Dall’algoritmo si deduce che:
EC(F' ) =
 c(S)  Probabilità di prendere S =  c(S)  X
S
SF '
per definizione di media probabilistica .
SF '
= OPTR
A questo punto controlliamo se la famiglia scelta è o meno un cover per U.
Dato e U, supponiamo che sia coperto da k insiemi, diciamo S1 ,S2, …., Sk.
Sia A = “e è coperto da F’ ” ed Ā = ”e non è coperto da F’ ”; Ā è equivalente a dire
che nessuno dei k sottoinsiemi sono stati inclusi in F’.
Sia Bi=”Si non è stato inserito in F’ ”.
P(A)=1-P(Ā)
k
Ā=  Bi
i=1
K
P(A)=1- P(  Bi)
i=1
Poiché gli eventi Bi sono tra loro indipendenti la probabilità dell’intersezione degli
eventi è uguale al prodotto delle probabilità dei singoli eventi.
P(A)=1-(P(B1 ) P(B2)….P(Bk ))=1-((1-X1) (1-X2)… (1-Xk))  1-(1/k)k  1-1/e  k
Da qui otteniamo che
P(A)=1- P(Ā)  1/e
P(Ā)  1 /e  e  U
Dove ‘e’ è la base del logaritmo naturale.
Quindi abbiamo costruito un insieme F’ e la probabilità che esso non sia un cover è
minore o uguale ad 1/e. Vogliamo minimizzare ulteriormente questa probabilità.
Per ridurla possiamo reiterare il processo di scelta di F’ ed unire la soluzione a quella
precedentemente calcolata. Facendo così la probabilità di non ottenere un cover per U
si riduce.
Possiamo pensare di costruire in questo modo d*logn famiglie e di unirle di volta in
volta.
Poniamo C’= F’1  F’2  ….  F’dlogn
Il valore di d viene scelto in modo tale che : (1/e)dlogn  1 /4n.
A questo punto calcoliamo la probabilità che tutto C’ sia un cover.
A tale scopo sia A=”e è coperto da C’ ”  e  U ed Ā=”e non è coperto da C’ ”, sia
Bi=”e non è coperto F’i ”; calcoliamo P(Ā):
dlogn
P(Ā)= P(  Bi)
i=1
Poiché gli eventi sono indipendenti risulta:
dlogn
d log n
P(Ā)=P(  Bi) =

i 1
P(Bi ) 
d log n

i 1
 e
( 1 )= 1
e
d log n
1
4n
i=1
Questa appena calcolata è la probabilità che e non sia coperto da C’, allora, sia
 =”C’ è un cover per U” ed  =”C’ non è un cover per U” e  i= “ei non è coperto
da C’ “; calcoliamo P(  ):
n
n
n
i 1
i 1
P(  )= P(   i)   P(  i)   1 
4n
1
.
4
i=1
Da qui P(H)=1-P(  )=1-1/4 = ¾ =probabilità che C’ sia un cover.
Non è detto però che questo cover abbia un buon costo.
Come detto Prima in media ogni F’i ha un costo pari ad OPTR :
EC(F' ) =
 c(S)  Probabilità di prendere S =  c(S)  X
S
SF '
= OPTR
SF '
Poiché C’= F’1  F’2  ….  F’dlogn otteniamo
E[C(C’)]=d*lognOPTR.
A questo punto utilizziamo il seguente risultato per stabilire di quanto si sbaglia,
probabilisticamente, la nostra soluzione approssimata:
Disuguaglianza di Markov: data una variabile casuale X con valore medio E[X],
vale che
E  X 
Pr{X  t} 
.
t
Se consideriamo X=C(C’) e t=4dlognOPTR allora
P[C(C’)  4dlognOPTR ]  dlognOPTR / 4dlognOPTR =1/4
In pratica abbiamo garantito con probabilità alta che C’ sia un cover per U e che sia
anche un buon cover.
In pratica, con probabilità ¾ C’ è un cover e con probabilità ¾ ha un costo minore a
4dlognOPTR .
I due eventi si devono verificare insieme:
P[H  C(C’)< 4dlognOPTR]=1-P[   C(C’)  4dlognOPTR] 
 1- [P(  )+P(C(C’)  4dlognOPTR )]  ½
in quanto entrambe le quantità tra parentesi quadre sono minori o uguali ad ¼ .
A questo punto possiamo verificare in tempo polinomiale se C’ soddisfa entrambe le
condizioni. In caso non soddisfi entrambe le condizioni si può ripetere l’algoritmo. Il
numero medio di ripetizioni dell’algoritmo è al più due.
Per dimostrarlo consideriamo la variabile aleatoria G che conta il numero di volte in
cui ripetiamo l’algoritmo. G assume valore i con probabilità p(1-p)i-1.
G ci dice che la probabilità di ripetere l’algoritmo i volte è pari alla probabilità di non
scegliere un cover per U in i-1 tentativi per la probabilità di sceglierlo all’i-esimo.
Vediamo come usare tale variabile aleatoria per calcolare il numero medio di volte
che dobbiamo ripetere l’algoritmo. Sia p la probabilità che i due eventi H e C(C’)<
4dlognOPTR si verifichino contemporaneamente, ed i=1,2,….,k l’indice che ci dice a
che ripetizione si sono verificati.
G ha distribuzione ipergeometrica con media nota 1/p:
E[G]=1/p=1/ P[H  C(C’)< 4dlognOPTR]=1/1/2=2
In realtà P[H  C(C’)< 4dlognOPTR]  ½ , diciamo che è uguale a c+(½) per
qualche c>0, allora 1/1/2  [1/c+(1/2)] infatti 2  2/1+2c in quanto 1+2c è sempre
positivo, ciò implica che E[G]  2.
Come già detto per il Set-Cover vale la relazione OPTR  OPT , dove OPT è il costo
della soluzione al nostro problema intero. Allora, se SOL è il costo della nostra
soluzione approssimata, ripetendo in media due volte l’algoritmo abbiamo che:
SOL  4dlogn OPTR  4dlogn OPT
Allora
SOL  4dlogn OPT
Da cui si ricava che il rapporto limite è un O(logn) in quanto 4d è una costante.