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 SiS 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 SF ' 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:eS 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 SF soggetto ai vincoli XS 1 e U S:eS 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 SF soggetto ai vincoli XS 1 e U S:eS 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). eU 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:eS 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 . SF 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: EC(F' ) = c(S) Probabilità di prendere S = c(S) X S SF ' per definizione di media probabilistica . SF ' = 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 : EC(F' ) = c(S) Probabilità di prendere S = c(S) X S SF ' = OPTR SF ' 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.