Dispense del corso di Ottimizzazione Combinatoria (IN440) 5. Problemi di Ottimizzazione e Programmazione Matematica Marco Liverani Università degli Studi Roma Tre Dipartimento di Matematica e Fisica Corso di Laurea in Matematica E-mail [email protected] Aprile 2014 2 M. Liverani – IN440 Revisione del 13 aprile 2014. Problemi di Ottimizzazione e Programmazione Matematica 3 1 Generalità In queste pagine ci proponiamo di descrivere una particolare classe di problemi, quelli di ottimizzazione combinatoria, studiandone una formulazione più generale che si inquadra nel contesto più ampio di problemi di programmazione matematica. Per iniziare a circoscrivere la famiglia dei problemi di ottimizzazione combinatoria e le caratteristiche che la distinguono da altri insiemi di problemi, dobbiamo focalizzare l’attenzione sul tipo di soluzione che viene richiesta da ciascuna classe di problema: è proprio la tipologia della soluzione che si deve individuare per risolvere il problema che ci permette di costruire una prima classificazione che aggrega in famiglie omogenee problemi che per ambito, applicazioni, strumenti di risoluzione risultano altrimenti molto diversi fra loro. Nel costruire questa classificazione procederemo in modo “incrementale”, rendendo la richiesta posta dal problema stesso, via via sempre più “esigente”. La formulazione più essenziale in cui può essere posto un problema è quella in cui si chiede semplicemente di rispondere «sì o no», «vero o falso», «0 o 1». Esiste uno zero della funzione f (x) nell’intervallo (a, b)? Esiste un cammino di lunghezza inferiore a k tra i due vertici u e v del grafo G? È possibile trovare un cammino chiuso sul grafo per raggiungere ogni vertice senza passare mai due volte per lo stesso spigolo? È possibile vincere una determinata partita a scacchi in sole tre mosse partendo da una certa configurazione dei pezzi sulla scacchiera? Tutti problemi la cui soluzione è effettivamente un semplice «sì o no», «esiste o non esiste», «è possibile o non è possibile». Non si richiede infatti di costruire ed esibire uno zero della funzione f (x), un cammino sul grafo G, o la sequenza di mosse che mi permette di vincere la partita a scacchi, ma soltanto di dire se uno zero, un cammino o una sequenza di mosse vincenti esiste. Questo genere di problemi sono denominati problemi di decisione o di esistenza. È bene precisare che non solo non è richiesto di esibire una possibile configurazione delle variabili del problema a supporto della soluzione del problema stesso, ma spesso non è neanche necessario costruire la soluzione per poter formulare una risposta per una particolare istanza di un problema di decisione: è sufficiente articolare la risposta in modo tale che, al di là di ogni dubbio, questa risulti inconfutabile. Ad esempio, se la funzione f (x) è continua nell’intervallo (a, b) e risulta f (a) > 0 e f (b) < 0 allora certamente esiste un x˜ ∈ (a, b) tale che f (x) ˜ = 0. Al contrario se il grafo G non è connesso e i due vertici u e v appartengono a due componenti connesse distinte, allora certamente un cammino p : u v non esiste in G. Nei cosiddetti problemi di ricerca, invece, viene richiesto proprio di costruire una soluzione del problema, ossia si richiede di esibire esplicitamente una configurazione delle variabili del problema che diano luogo ad una soluzione. Rifacendoci agli esempi formulati in precedenza, si richiede di identificare un particolare valore di x ∈ (a, b) tale che f (x) = 0, oppure di costruire uno specifico cammino p : u v sul grafo G con meno di k spigoli, o un circuito su G che non passi mai due volte per lo stesso spigolo, o la sequenza di mosse che mi permetta di vincere la partita a scacchi a partire da una certa disposizione dei pezzi sulla scacchiera. È chiaro che una soluzione può essere esibita solo se esiste: in altre parole risolvere un’istanza di un problema nella sua formulazione come problema di ricerca, comporta implicitamente anche la soluzione dello stesso problema nella sua formulazione come problema di decisione. Se viene richiesto di calcolare ed esibire tutte le possibili soluzioni di una determinata istanza del problema, allora siamo di fronte ad una formulazione del problema come problema di enumerazione. Ad esempio si richiede di identificare tutti i valori x ∈ (a, b) tali che f (x) = 0; si richiede di costruire tutti i possibili cammini sul grafo G da u a v composti con meno di k spigoli; ecc. Anche in questo caso dovrebbe risultare chiaro che risolvere un problema di enumerazione significa, implicitamente, risolvere anche un problema di ricerca, in cui si chiede di esibire una sola soluzione ammissibile per il problema, ed anche risolvere il problema di decisione associato, in cui si chiedeva soltanto di stabilire 4 M. Liverani – IN440 Classe Problemi di decisione o di esistenza Problemi di ricerca Problemi di enumerazione Problemi di ottimizzazione Descrizione Si richiede di verificare se esiste o meno una certa soluzione per l’istanza del problema Si richiede di costruire ed esibire una soluzione per l’istanza del problema Si richiede di costruire ed esibire tutte le soluzioni per l’istanza del problema Si richiede di costruire le soluzioni ottimali in base ad un determinato criterio (funzione obiettivo o di costo) Tabella 1: Una classificazione dei problemi in base al tipo di soluzione richiesta se una soluzione esiste o meno per quella determinata istanza del problema. Risolvere problemi di enumerazione sarà quindi più laborioso che risolvere problemi di ricerca; risolvere problemi di ricerca sarà più laborioso che risolvere problemi di esistenza. Arriviamo così alla formulazione dei problemi di ottimizzazione: in questo caso non ci si accontenterà né di stabilire soltanto se una soluzione esiste, né di identificare una soluzione qualsiasi per l’istanza del problema e neanche di identificare tutte le soluzioni del problema stesso, indistintamente; si richiede, invece, di identificare una o tutte le soluzioni che risultano ottimali rispetto ad un qualche criterio di valutazione delle soluzioni ammissibili per una specifica istanza del problema. Ad esempio tra tutti gli zeri della funzione f (x) nell’intervallo (a, b) si chiederà di individuare quelli che rendono minima la funzione ϕ(x) nell’intervallo stesso; tra tutti i cammini che sul grafo G collegano i vertici u e v si chiederà di trovare quelli di lunghezza minima o che minimizzano il costo dato dalla somma dei pesi attribuiti a ciascuno spigolo del grafo, e così via. In un problema di ottimizzazione viene quindi fornita anche una funzione con cui valutare il costo di ciascuna soluzione del problema: questa funzione, detta funzione obiettivo, costituisce un criterio di scelta tra le possibili soluzioni del problema, ossia uno strumento, una bussola, con cui orientarsi nell’insieme delle soluzioni ammissibili con l’intento di selezionare solo le soluzioni migliori, quelle che “minimizzano” il costo o massimizzano il “profitto”. Nel seguito ci occuperemo quasi esclusivamente di problemi di ottimizzazione; in particolare, come vedremo tra breve, ci occuperemo di una particolare classe di problemi che va sotto il nome di problemi di ottimizzazione combinatoria. In generale per questi problemi l’insieme delle soluzioni ammissibili entro cui cercare il sottoinsieme di soluzioni ottimali è un insieme discreto, di cardinalità finita; tuttavia il numero di elementi di cui è costituito è di un ordine di grandezza molto superiore alla dimensione dell’istanza del problema che si intende risolvere. 2 Formulazione generale per i problemi di ottimizzazione In termini molto generali un’istanza di un problema di ottimizzazione è definita come una coppia (A, f ), dove A è l’insieme delle soluzioni ammissibili ed f : A → R è la funzione obiettivo che si deve ottimizzare (massimizzare o minimizzare). Il problema di ottimizzazione viene posto chiedendo di trovare i valori x ∈ A tali che f (x) ≤ f (y) per ogni y ∈ A (problema in forma di minimizzazione). Tali valori x costituiscono delle soluzioni ottime globali per il problema; nel caso in cui risulti invece f (x) ≤ f (y) soltanto per ogni y appartenente ad un intorno di x, allora la soluzione x si dice soluzione ottima locale. Problemi di Ottimizzazione e Programmazione Matematica y y S z 5 z x x S' Figura 1: Un insieme convesso S ed un insieme S0 non convesso (concavo): S0 è tale che, fissata una coppia di punti x, y ∈ S0 , esistono altri punti z = λx + (1 − λ)y che, per alcuni valori di λ ∈ [0, 1], non appartengono ad S0 L’insieme A delle soluzioni ammissibili è l’insieme entro il quale devono essere cercate le soluzioni che rendono minima o massima la funzione obiettivo: la definizione di A è una caratteristica specifica di ciascun problema e consente di escludere punti dello spazio su cui sono definite le variabili del problema su cui non è utile o non ha senso cercare la soluzione. Non si deve necessariamente pensare all’insieme A come ad un sottoinsieme o un intervallo della retta reale: spesso infatti l’insieme A è un sottoinsieme di Rn o un insieme discreto definito in modo più articolato, come ad esempio un sottografo con determinate caratteristiche. Ad esempio il problema della ricerca del cammino più breve tra due vertici u e v di un grafo G, può essere formulato come problema di ottimizzazione definendo l’insieme A delle soluzioni ammissibili come la collezione di tutti i cammini semplici in G dal vertice u al vertice v; la funzione obiettivo f : A → R viene definita come la funzione che associa ad ogni cammino p ∈ A la sua lunghezza. I cammini ottimi sono quelli che rendono minima la funzione obiettivo, ossia quei cammini da u a v con la lunghezza minima. Nella formulazione di un problema di ottimizzazione un aspetto assai critico e rilevante è costituito dalla corretta definizione dell’insieme delle soluzioni ammissibili; è necessario circoscrivere questo sottoinsieme dello “spazio delle soluzioni”, senza escludere punti dello spazio che possano corrispondere ad una soluzione ammissibile e dunque potenzialmente ottima e al tempo stesso cercando di ridurre al massimo l’insieme entro cui eseguire la ricerca delle soluzioni, per rendere più efficiente e meno oneroso in termini computazionali, il procedimento di calcolo adottato per individuare le soluzioni ottime. In generale quindi l’insieme A delle soluzioni ammissibili viene definito attraverso un insieme di vincoli che limitano e circoscrivono l’insieme entro cui possono assumere valori le variabili del problema. In particolare tra i problemi di ottimizzazione rivestono notevole importanza i problemi di programmazione matematica. In questo genere di problema i vincoli che circoscrivono l’insieme A delle soluzioni ammissibili sono costituiti da un certo numero, anche molto ampio, ma sempre finito, di equazioni e disequazioni; da qui il nome di questa classe di problemi. In generale quindi un problema di programmazione matematica viene definito come segue: minimizzare f (x) per x tale che gi (x) ≥ 0 i = 1, 2, . . . , m h j (x) = 0 (1) j = 1, 2, . . . , p Le funzioni gi e h j costituiscono i vincoli del problema. Dati due punti dello spazio x, y ∈ Rn una combinazione convessa di x e y è un punto z dello spazio definito come z = λx + (1 − λ)y, con λ ∈ R e 0 ≤ λ ≤ 1. Un insieme S ⊆ Rn è convesso se contiene qualsiasi combinazione convessa di ogni coppia di elementi distinti di S; in altri termini S è convesso 6 M. Liverani – IN440 f(y) λf(x) + (1-λ)f(y) f(x) f(λx + (1-λ)y) x y Figura 2: La funzione convessa calcolata nei punti di una combinazione convessa è minore o uguale alla combinazione convessa dei valori della funzione negli estremi se per ogni x, y ∈ S, x 6= y, risulta λx + (1 − λ)y ∈ S per ogni 0 ≤ λ ≤ 1. In Figura 1 è rappresentato un insieme S convesso ed un insieme S0 non convesso in R2 . Proposizione 1. Se S1 , S2 , . . . , Sk sono insiemi convessi, allora anche ∩ki=1 Si è un insieme convesso. Dimostrazione. Se x, y ∈ ∩ki=1 Si allora x, y ∈ Si , per ogni i = 1, . . . , k. Per cui, visto che per ipotesi ogni insieme Si è convesso, ogni combinazione convessa di x e y appartiene ad Si e dunque appartiene anche a ∩ki=1 Si . Sia S ⊆ Rn un insieme convesso. La funzione f : S → R è convessa in S se, per ogni x, y ∈ S, risulta f (λx + (1 − λ)y) ≤ λ f (x) + (1 − λ) f (y) (2) Se vale la disuguaglianza opposta, la funzione si dice concava. Evidentemente se f (x) è convessa, allora − f (x) è concava. In Figura 2 è rappresentato il grafico di una funzione convessa f definita a valori su R. Un esempio di funzione convessa su R2 è dato dal paraboloide f (x1 , x2 ) = x12 + x22 . Proposizione 2. Sia f (x) una funzione convessa sull’insieme convesso S. Allora, per ogni t ∈ R, l’insieme St = {x ∈ S : f (x) ≤ t} è convesso. Dimostrazione. Dobbiamo mostrare che ogni combinazione convessa di elementi di St è ancora in St , ossia che la funzione f (x), calcolata in ogni combinazione convessa di elementi di St , è minore o uguale a t. Siano x, y ∈ St per qualche t ∈ R. Per ipotesi (S è convesso) ogni combinazione convessa di x e y, λx + (1 − λ)y è in S. Inoltre, siccome f è una funzione convessa, risulta f (λx + (1 − λ)y) ≤ λ f (x) + (1 − λ) f (y) ≤ λt + (1 − λ)t = t Quindi effettivamente f (λx + (1 − λ)y) ≤ t e dunque λx + (1 − λ)y ∈ St . In conclusione, allora, St è un insieme convesso. Un problema di programmazione convessa è un problema di programmazione matematica espresso nella forma (1), in cui la funzione obiettivo f (x) sia convessa, le funzioni gi (x) siano concave e le h j (x) siano lineari. Perché è importante distinguere tra i generici problemi di programmazione matematica quelli che sono dotati di una funzione obiettivo convessa? La risposta è semplice: se la funzione obiettivo è convessa allora ogni soluzione ottima locale è anche una soluzione ottima globale. Problemi di Ottimizzazione e Programmazione Matematica 7 Proposizione 3. In un problema di programmazione convessa ogni soluzione ottima locale è anche una soluzione ottima globale. Dimostrazione. Supponiamo che per un determinato problema di programmazione convessa (A, f ) risulti f (x) ≤ f (y) per ogni y ∈ N(x) ⊆ A (indichiamo con N(x) un intorno del punto x) e che esista un punto z 6∈ N(x), z ∈ A, tale che f (x) 6≤ f (z). In questo caso x sarebbe una soluzione ottima locale, ma non globale. Dunque se così fosse, allora esisterebbe sicuramente un punto y ∈ N(x) tale che possa essere espresso come combinazione convessa di x e z: y = λx + (1 − λ)z. In questo caso si avrebbe f (z) < f (x) ≤ f (y) contraddicendo così la convessità di f . 3 Programmazione lineare Le funzioni lineari sono un caso molto particolare di funzioni convesse. Se la funzione obiettivo ed i vincoli del problema di ottimizzazioni sono funzioni lineari, allora il problema di programmazione matematica che si ottiene è un problema di programmazione lineare (LP). È facile osservare che se la funzione obiettivo è lineare, allora i suoi punti di minimo o di massimo si trovano sicuramente sulla frontiera dell’insieme A delle soluzioni ammissibili. Proprio su questo principio si basa il celebre metodo per la risoluzione di problemi di programmazione lineare proposto dal matematico americano George Dantzig nel 1947 e noto come algoritmo del simplesso. L’algoritmo proposto da Dantzig opera su un simplesso, ossia un politopo in n dimensioni con n + 1 vertici (ad esempio, in uno spazio di dimensione n = 3, un simplesso è un tetraedro, il poliedro con il minor numero di vertici). I vincoli del problema di ottimizzazione definiscono la regione ammissibile, cioè l’insieme dei punti che soddisfano tutti i vincoli del problema. Nel caso della programmazione lineare la regione ammissibile è un politopo (un poligono nel piano, un poliedro nello spazio), che può essere vuoto (nel caso in cui non esistono soluzioni al problema), limitato o illimitato. La funzione obiettivo che deve essere minimizzata o massimizzata esprime il “costo” di ogni soluzione tenendo conto dei vincoli (ossia calcolando la soluzione all’interno del poliedro). L’algoritmo del simplesso è in grado di determinare di che tipo di poliedro si tratta e di individuare la soluzione ottima, che è, sotto opportune ipotesi, un vertice del poliedro, nel caso in cui il problema abbia una soluzione ottimale finita. Tra i problemi di programmazione lineare è opportuno distinguere i problemi di programmazione lineare intera (PLI): in questo caso alcune delle variabili del problema sono vincolate ad assumere soltanto valori interi. Questo vincolo ulteriore riduce drasticamente il numero di punti presenti nella regione ammissibile. Il problema di programmazione lineare diventa un problema di ottimizzazione combinatoria se tutte le variabili sono vincolate ad assumere soltanto valori interi. Quando in un problema di programmazione lineare intera si eliminano i “vincoli di integrità”, ossia i vincoli che impongono x ∈ Zn , si ottiene un problema di programmazione lineare detto rilassamento continuo. Se, inoltre, accade che le soluzioni ottime del problema originario sono anche soluzioni ottime del suo rilassamento continuo, si dice che il problema gode della proprietà di integralità. In effetti la proprietà di integralità riguarda l’insieme ammissibile del problema più che il problema in sè. Infatti la funzione obiettivo del rilassamento continuo ha lo stesso valore di quella del problema originario sul suo insieme ammissibile e, inoltre, poiché è un problema di programmazione lineare, ha sempre una soluzione ottima di vertice. Per chiarire meglio questi concetti, vediamo di seguito alcuni problemi classici di ottimizzazione combinatoria che possono essere formulati come problemi di Programmazione Lineare e di Programmazione Lineare Intera. 8 M. Liverani – IN440 3.1 Problema della bisaccia Il problema della bisaccia binario (knapsack problem, in inglese) può essere posto come segue: abbiamo a disposizione un sacco, una bisaccia, in grado di sopportare un carico pari a P, con cui siamo intenzionati a trasportare un certo numero di oggetti di peso e di valore diverso, selezionandoli da una collezione di n elementi, in modo tale da massimizzare il valore complessivo degli oggetti selezionati, ma senza rompere la bisaccia riempiendola con un peso eccessivo, superiore a P. Naturalmente ogni oggetto ha un peso intero ben definito e non è possibile rompere gli oggetti in modo da costituire oggetti più piccoli di peso inferiore: ciascun oggetto può essere preso per intero oppure deve essere lasciato al suo posto, rinunciando a trasportarlo. Qual è il modo migliore con cui è possibile operare la scelta degli oggetti da inserire nella bisaccia? Il problema può essere formulato come un problema di programmazione lineare intera indicando con ci e pi rispettivamente il valore e il peso dell’i-esimo oggetto. Con la variabile binaria xi ∈ {0, 1} indicheremo se l’oggetto i-esimo è stato scelto (xi = 1) oppure se è stato scartato (xi = 0). In questo modo la soluzione ottima del problema è una sequenza x = (x1 , x2 , . . . , xn ) ∈ {0, 1}n con cui possiamo identificare il contenuto della bisaccia; il problema di ottimizzazione può essere posto nei seguenti termini: n massimizzare f (x) = ∑ ci xi i=1 n ∑ pi xi ≤ P (3) i=1 xi ∈ {0, 1} i = 1, 2, . . . , n Le variabili del problema, x1 , . . . , xn , non soltanto sono intere, ma addirittura sono vincolate ad assumere valori binari: xi = 0 oppure xi = 1. In questi casi si parla di problema di programmazione lineare intera “0-1”. Il problema è chiaramente di tipo combinatorio: le soluzioni ammissibili sono in numero finito e possono essere anche prodotte in modo esaustivo, costruendo tutte le sequenze binarie con n caratteri; tuttavia questo approccio conduce ad un algoritmo di complessità esponenziale nella dimensione n dell’istanza del problema, dal momento che il numero di stringhe binarie con n caratteri (o, come abbiamo visto in precedenza, l’insieme delle parti di un insieme di cardinalità n) sono 2n . 3.2 Problema dell’assegnazione di task Un problema classico di pianificazione riguarda l’assegnazione di task ai processori di un calcolatore parallelo, alle macchine di una rete di calcolatori che cooperano per la soluzione di uno stesso problema o ad un gruppo di persone. Supponiamo che n processori debbano svolgere m task. Ciascuno di essi deve essere svolto esattamente da un processore ed inoltre, ciascun processore può svolgere al al massimo un task. Indichiamo con ci j il costo dell’utilizzo del processore i per l’esecuzione del task j. Il problema chiede di assegnare i task alle varie risorse (processori, calcolatori o persone, a seconda del contesto applicativo) minimizzando il costo totale per la realizzazione di tutti gli m task previsti. Per formulare questo problema in termini di programmazione lineare intera, introduciamo le variabili binarie xi j , per i = 1, . . . , n e j = 1, . . . , m corrispondenti all’evento “i j” (esecuzione del task j da parte della risorsa i) definite come segue xi j = 1 se il task j viene eseguito dalla risorsa i e xi j = 0 altrimenti. Poiché esattamente una ed una sola risorsa deve essere assegnata al task j, avremo i seguenti vincoli: n ∑ xi j = 1, per ogni j = 1, 2, . . . , m i=1 Problemi di Ottimizzazione e Programmazione Matematica 9 Figura 3: George Bernard Dantzig (1914–2005) Al tempo stesso, visto che per ipotesi ogni risorsa non può svolgere più di un task, si avranno anche i seguenti vincoli: m ∑ xi j = 1, per ogni i = 1, 2, . . . , n j=1 È facile verificare che un vettore x ∈ {0, 1} che soddisfa tutti i vincoli appena descritti individua un assegnamento ammissibile di risorse ai task. La funzione obiettivo, che ovviamente deve essere minimizzata, è la seguente: n m ∑ ∑ ci j xi j i=1 j=1 4 Il metodo del simplesso Il metodo del simplesso è un algoritmo generale per la risoluzione di problemi di programmazione lineare proposto nel 1947 dal matematico americano George Dantzig.1 La sua rilevanza, oltre che storica, anche dal punto di vista applicativo, è fondata proprio sulla generalità dell’approccio, piuttosto che sulla sua efficienza: l’algoritmo del simplesso permette di risolvere qualsiasi problema di ottimizzazione formulato come problema di programmazione lineare, anche se computazionalmente è piuttosto pesante. Possiamo riformulare un problema di programmazione lineare partendo dall’espressione (1), formalizzandolo come segue: data una matrice A ∈ Rm×n e i vettori colonna b ∈ Rm , c ∈ Rn , si chiede di trovare un vettore colonna x ∈ Rn tale che Ax ≤ b e ct x sia minimo (problema in forma di minimizzazione). Naturalmente il vettore c rappresenta il “costo” associato a ciascuna variabile xi della soluzione del problema (o il “profitto”, nel caso di problemi in forma di massimizzazione) e la funzione obiettivo è espressa quindi come f (x) = ct x. La matrice A è la matrice dei coefficienti delle disequazioni lineari con cui viene definito l’insieme delle soluzioni ammissibili del problema. L’espressione (1) 1 Per una trattazione più completa dell’argomento, che in queste pagine viene solo tratteggiato nelle sue linee più generali, si rimanda ai testi citati tra i riferimenti bibliografici ed in particolare [3], [5] e [6]. 10 M. Liverani – IN440 può così essere riformulata come segue: minimizzare f (x) = ct x per x tale che Ax ≤ b A∈R m×n m (4) n ,b ∈ R ,c ∈ R L’insieme di disequazioni lineari Ax ≤ b definisce un poliedro P come intersezione dei semispazi definiti da ciascuna disequazione. È all’interno di P che sono da ricercare le soluzioni ottime del problema, tra tutte le soluzioni ammissibili. Esistono due casi degeneri per un problema di programmazione lineare: il caso in cui il problema / o il caso non ammette nessuna soluzione, quando cioè i vincoli producono un poliedro nullo, P = 0, in cui il problema ammette infinite soluzioni, quando il poliedro P è illimitato. Quando il problema di programmazione lineare è ben posto e dunque P non è né nullo, né illimitato, diremo che P è un politopo. Un simplesso, il termine che dà il nome all’algoritmo di Dantzig, è un politopo di n + 1 vertici in n dimensioni: un segmento in dimensione 1, un triangolo in dimensione 2 e un tetraedro in dimensione 3. Cerchiamo di formalizzare meglio questi concetti. Innanzi tutto chiamiamo vertice di un poliedro P un punto x ∈ P tale che non esistono altri due punti x0 , x00 ∈ P, con x 6= x0 , x00 e x ∈ [x0 , x00 ]. Non tutti i poliedri ottenuti come intersezioni di semispazi definiti mediante disequazioni lineari hanno almeno un vertice. Ad esempio se consideriamo un unico semispazio di R2 , questo non ha vertici. Dunque il poliedro P = {x ∈ Rn : Ax ≥ b} non ha vertici se la matrice A ha un numero di righe minore di n: in tal caso non è possibile trovare n vincoli linearmente indipendenti che circoscrivano un poliedro chiuso. Un poliedro P non ha vertici se contiene rette: diremo che un poliedro P contiene una retta se esiste un punto x˜ ∈ P e un vettore non nullo d ∈ Rn tale che x˜ + λd ∈ P per ogni λ ∈ R. Possiamo infine enunciare il seguente Teorema fondamentale della Programmazione Lineare: Teorema 1. Si consideri il problema di Programmazione Lineare min ct x Ax = b Supponiamo che il poliedro P = {x ∈ Rn tale che Ax = b} non contenga rette. Allora una e una sola delle seguenti tre affermazioni è vera: 1. il problema è inammissibile, ovvero il poliedro P è vuoto; 2. il problema è illimitato inferiormente; 3. il problema ammette soluzioni ottime e almeno una di queste è un vertice del poliedro P. L’algoritmo del simplesso non consiste altro che in una “visita intelligente” dei vertici di P; il teorema fondamentale della programmazione lineare garantisce infatti che la soluzione ottimale del problema, se esiste, è situata in uno di questi vertici. Muovendosi sugli spigoli del poliedro, da un vertice ad un altro, il metodo del simplesso cerca di individuare una soluzione ottima, che massimizzi o minimizzi la funzione obiettivo. Consideriamo la matrice A ∈ Rm×n ; se I è un insieme di indici di riga di A, indichiamo con AI la sottomarine di A composta con le sole righe in I ; analogamente se b è un vettore, indichiamo con bI il sottovettore composto dalle sole componenti di indice in I . Indichiamo con ai la riga A{i} e con Problemi di Ottimizzazione e Programmazione Matematica 11 Algoritmo 1 S IMPLESSO(A, b, c) Input: Una matrice di coefficienti A ∈ Rm×n , il vettore dei termini noti b ∈ Rm , il vettore dei costi ct ∈ Rn , un vertice x ∈ P = {x ∈ Rn : Ax ≤ b} Output: Un vertice x∗ ∈ P tale che ct x∗ = maxx∈P {ct x}, oppure un vettore w ∈ Rn con Aw ≤ 0 e ct w > 0 (il poliedro P è illimitato) 1: Scegli un insieme di n indici di riga I tali che AI è non singolare e AI x = bI 2: Calcola c (AI )−1 e aggiungi gli zeri necessari per ottenere un vettore y tale che c = yA e tutti gli elementi di y fuori da I siano nulli 3: se y ≥ 0 allora 4: return x e y; stop 5: fine-condizione 6: Sia i il minimo indice per cui risulta yi < 0 7: Sia w la colonna di −(AI )−1 con indice i, tale che AI \{i} w = 0 e ai w = −1 8: se Aw ≤ 0 allora 9: return w; stop 10: fine-condizione n o b j −a j x 11: Sia λ := min j=1,...,m a j w : a j w > 0 e sia j il più piccolo indice di riga con cui si ottiene questo minimo 12: Sia I := (I \ {i}) ∪ { j} e x := x + λw 13: Vai al passo 2 bi = b{i} . Utilizzando queste notazioni formalizziamo il Metodo del Simplesso con lo pseudo codice dell’Algoritmo 1. È possibile dimostrare che l’Algoritmo del Simplesso termina al massimo dopo mn iterazioni del ciclo 2–13. Se l’algoritmo restituisce x e y al passo 4, allora x e y sono i vettori che rappresentano le soluzioni ottime per i seguenti problemi di programmazione lineare, con c x = y b: max{c x : Ax ≤ b} t t min{y b : y A = c , y ≥ 0} (5) (6) Infine, se l’algoritmo restituisce il vettore w al passo 9, allora cw > 0 e il problema di programmazione lineare (5) è illimitato. Il problema di programmazione lineare espresso da (5) viene chiamato problema primale, mentre il problema di programmazione lineare (6), associato al precedente, viene chiamato problema duale. 5 Programmazione lineare per problemi di ottimizzazione su grafi Per concludere questa breve panoramica sui problemi di programmazione matematica e su quelli di programmazione lineare in particolare, vediamo alcune applicazioni della programmazione lineare alla teoria dei grafi. Una volta impostato il problema in termini di programmazione lineare è possibile calcolarne una soluzione con l’algoritmo del simplesso, che garantisce l’identificazione di una soluzione ottima, al costo di una complessità computazionale più elevata di un algoritmo specificamente progettato per risolvere un determinato problema (es.: il problema del cammino minimo tra due vertici di un grafo). Di seguito consideriamo alcuni problemi classici di ottimizzazione combinatoria con l’obiettivo di offrirne una formulazione in termini di programmazione lineare intera: 12 M. Liverani – IN440 1. minimo ricoprimento di vertici per gli spigoli di un grafo G; 2. massima clique di un grafo G; 3. cammino di costo minimo dal vertice s al vertice t su un grafo G; 4. albero ricoprente di costo minimo di un grafo G. I problemi saranno formulati come problemi di programmazione lineare intera “0 − 1”, ossia con variabili xi che assumono valori nell’insieme {0, 1}; infatti, nel caso di problemi di ottimizzazione combinatoria, la soluzione è data sempre da una “scelta” degli elementi che costituiscono l’istanza del problema: una scelta di alcuni vertici di un grafo, una scelta di alcuni degli spigoli di un grafo, in generale una scelta di alcuni elementi di un insieme discreto, per cui è comodo rappresentare con la variabile xi il fatto di aver scelto (xi = 1) oppure di aver scartato (xi = 0) l’elemento i-esimo dell’insieme. 5.1 Minimo insieme di copertura dei vertici Dato un grafo G = (V, E) un ricoprimento di vertici è un sottoinsieme C ⊆ V tale che ogni spigolo di G sia incidente almeno a un vertice di C. Il problema di ottimizzazione combinatoria che si intende risolvere chiede di calcolare un insieme C di copertura dei vertici di G, di cardinalità minima. Per modellizzare il problema introduciamo le seguenti variabili: 1 se vi è nel ricoprimento C ∀ vi ∈ V, xi = 0 altrimenti Si tratta dunque di minimizzare il numero di vertici nel ricoprimento, ovvero la funzione: ∑vi ∈V xi . La condizione che garantisce che C sia un ricoprimento è che per ogni spigolo (vi , v j ) ∈ E(G) almeno uno tra vi e v j sia nel ricoprimento C. Formalizzando si ha dunque il seguente vincolo: ∀(vi , v j ) ∈ E(G), xi + x j ≥ 1. Riassumendo, il problema del minimo ricoprimento può essere formalizzato nel modo seguente come problema di programmazione lineare intera: min ∑vi ∈V xi ∀ (vi , v j ) ∈ E, xi + x j ≥ 1 ∀ vi ∈ V xi ∈ {0, 1} 5.2 Clique massima Dato un grafo G = (V, E) una clique di G è un sottoinsieme C ⊆ V tale che ogni coppia di vertici in C sia collegata da uno spigolo in G (C induce un sottografo completo su G). Dato un grafo G si vuole quindi individuare una clique di dimensione massima su G. Per modellizzare il problema in termini di programmazione lineare introduciamo le seguenti variabili: 1 se vi è nella clique ∀ vi ∈ V, xi = 0 altrimenti Si tratta dunque di massimizzare il numero di vertici nella clique, ovvero la funzione: ∑vi ∈V xi . La condizione che garantisce che C sia una clique è che per ogni coppia (vi , v j ) che non sia uno spigolo di G almeno uno tra vi e v j non sia in C. In termini formali si ha dunque il seguente vincolo: ∀ (vi , v j ) ∈ / E(G), xi + x j ≤ 1. 13 Problemi di Ottimizzazione e Programmazione Matematica Riassumendo, il problema della massima clique può essere formulato come problema di programmazione lineare intera nel modo seguente: max ∑vi ∈V xi ∀ (vi , v j ) ∈ / E, xi + x j ≤ 1 ∀ vi ∈ V, xi ∈ {0, 1} 5.3 Cammino di costo minimo Sia G = (V, E) un grafo con dei pesi non negativi assegnati agli spigoli: per ogni (vi , v j ) ∈ E(G) di j ≥ 0 sia il peso corrispondente. Dati due vertici s,t ∈ V , si vuole trovare un cammino p da s a t per cui la somma dei pesi assegnati agli spigoli sia minima. Per formulare il problema in termini di programmazione lineare, si introducono le seguenti variabili, questa volta una per ogni spigolo: ∀ (vi , v j ) ∈ E(G) xi j = 1 se (vi , v j ) è nel cammino p : s 0 altrimenti t Per trovare una soluzione del problema dobbiamo quindi minimizzare la seguente funzione obiettivo: ∑(vi ,v j )∈E di j xi j . Affinché un insieme di spigoli del grafo G costituisca un cammino da s a t bisogna assicurarsi che esattamente uno spigolo del cammino esca da s e nessuno entri in esso, esattamente uno spigolo del cammino entri in t e nessuno esca da esso e che per tutti gli altri vertici il numero di spigoli del cammino uscenti sia pari a quello di spigoli entranti. Formalizzando si ottengono i seguenti vincoli: −1, vh = s ∑ xh j − ∑ xi j = 1, vh = t (vi ,vh )∈E (v j ,vi )∈E 0, ∀ vh ∈ V \ {s,t} Riassumendo, il problema del cammino minimo può essere formalizzato nel modo seguente come un problema di programmazione lineare intera: ∑(vi ,v j )∈E di j xi j ∑(vi ,vh )∈E xh j − ∑(v j ,vi )∈E xi j = −1, se vh = s ∑(vi ,vh )∈E xh j − ∑(v j ,vi )∈E xi j = 1, se vh = t ∑(vi ,vh )∈E xh j − ∑(v j ,vi )∈E xi j = 0, se vh ∈ V \ {s,t} ∀ (v , v ) ∈ E, x ∈ {0, 1} i j ij 5.4 Albero ricoprente di costo minimo Un albero ricoprente (spanning tree) di un grafo G = (V, E) è un albero T = (V, E 0 ), con E 0 ⊆ E, ossia un albero con gli stessi vertici di G e n − 1 spigoli di G, affinché T sia un grafo connesso e aciclico (un albero). Se associamo un peso non negativo w(u, v) ad ogni spigolo (u, v) ∈ E(G), è possibile definire il problema di ottimizzazione combinatoria che chiede di costruire l’albero ricoprente di G di peso minimo, ossia l’albero T ∗ tale che ∑ (u,v)∈E(T ∗ ) w(u, v) = min T che ricopre G ∑ (u,v)∈E(T ) w(u, v) 14 M. Liverani – IN440 x3 1 x’ = (1, 0, 1) v1 3)= e w( e 3 = (v 10 1,v 3) ) ,v2 v1 =( 20 e2 )= e w( 2 x’’’ = (0, 1, 1) 1 x1 1 e2 = (v2, v3) v3 w(e2) = 30 x2 v2 (a) x’’ = (1, 1, 0) (b) Figura 4: Un grafo pesato G = (V, E) e il politopo con la regione delle soluzioni ammissibili per il problema MST. Anche in questo caso, per formulare il problema in termini di programmazione lineare, si introducono le seguenti variabili associate agli spigoli del grafo: ∀ ei ∈ E(G) xi = 1 se ei ∈ E(T ) 0 altrimenti In questo modo possiamo formulare il problema del minimo albero ricoprente (MST – minimum spanning tree) come segue: min per x tale che f (x) = ∑m i=1 w(ei )xi x1 + x2 + · · · + xm = n − 1 xi ≥ 0 per i = 1, 2, . . . , m xi ≤ 1 per i = 1, 2, . . . , m Per aiutare a visualizzare il significato geometrico di questa formulazione, consideriamo il grafo G = (V, E) definito ponendo V = {v1 , v2 , v3 }, E = {e1 = (v1 , v2 ), e2 = (v2 , v3 ), e3 = (v1 , v3 )}; supponiamo anche che w(e1 ) = 20, w(e2 ) = 30 e w(e3 ) = 10. Il grafo è rappresentato in Figura 4(a). Effettuando un rilassamento continuo del problema, possiamo rappresentare l’insieme delle soluzioni ammissibili con il poliedro (triangolo) evidenziato in Figura 4(b), ossia il poliedro a 2 dimensioni collocato nello spazio a 3 dimensioni, con vertici nei punti x0 = (1, 0, 1), x00 = (1, 1, 0) e x000 = (0, 1, 1). Per il vincolo di integrità delle variabili del problema (dobbiamo scegliere uno spigolo o non sceglierlo per nulla, non possiamo prenderne solo un pezzo!), le soluzioni del problema si trovano proprio nei vertici del politopo costituito dal triangolo. In particolare, come si può osservare facilmente senza la necessità di applicare l’Algoritmo del Simplesso, la soluzione ottima è costituita dal punto x00 = (1, 0, 1): questo punto rappresenta l’albero ricoprente costruito scegliendo gli spigoli e1 ed e3 , con peso complessivo f (x00 ) = w(e1 ) + w(e3 ) = 20 + 10 = 30. Problemi di Ottimizzazione e Programmazione Matematica 15 Riferimenti bibliografici [1] Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein, Introduzione agli algoritmi e strutture dati, seconda edizione, McGraw-Hill, 2005. [2] Ottavio D’Antona, Introduzione alla Matematica Discreta, Apogeo, 1999. [3] Bernhard Korte, Jens Vygen, Ottimizzazione Combinatoria, Springer, 2011. [4] Marco Liverani, Qual è il problema? Metodi, strategie risolutive, algoritmi, Mimesis, 2005. [5] Christos H. Papadimitriou, Kenneth Steiglitz, Combinatorial Optimization – Algorithms and Complexity, Dover Publications Inc., 1998. [6] Antonio Sassano, Modelli e algoritmi della Ricerca Operativa, Franco Angeli, 1999. [7] Paolo Serafini, Ottimizzazione, Zanichelli, 2000.
© Copyright 2024 ExpyDoc