Professional Documents
Culture Documents
Prefazione
Il presente lavoro di tesi nato con l'intento di sviluppare idee interessanti per la progettazione di un algoritmo in grado di risolvere il Multidimensional Knapsack
Problem, uno dei problemi di tipo NP-Hard in forma Strong pi noti e complessi in
letteratura. Al momento della stesura di questa tesi non esistono algoritmi in grado di risolvere in modo esatto istanze particolarmente complesse del Multidimensional Knapsack
Indice
7
7 9 10
Applicazioni pratiche . . . . . . . . . . . . . . . . . . . . . . . . . . .
2 Stato dell'arte
2.1 2.2 Generazione di istanze . . . . . . . . . . . . . . . . . . . . . . . . . . Algoritmi esatti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2.1 2.2.2 2.2.3 2.3 Algoritmi Branch and Bound . . . . . . . . . . . . . . . . . .
12
13 14 15 18 21 22 23 25 30 31
2.4
ILOG CPLEX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3 Il nostro algoritmo
3.1 3.2 Il concetto di Core del Multidimensional Knapsack Problem Creazione ed espansione del Core 3.2.1 3.2.2 3.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
33
33 41 42 47 48 49
Risoluzione del problema Core . . . . . . . . . . . . . . . . . . . . . . 3.3.1 AAR: Analisi degli Alberi di Ricerca . . . . . . . . . . . . . .
INDICE
Cardinalit
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
50 53 55 64 68 68 74 75 76 76 77 81 84 85 87 87 88
. . . . . . . . . . . . . . . . . . . . . . . .
RR: Riduzione ricorsiva del problema . . . . . . . . . . . . . . 3.3.2.1 3.3.2.2 3.3.2.3 3.3.2.4 3.3.2.5 3.3.2.6 3.3.2.7 Inizializzazione di RR . . . . . . . . . . . . . . . . .
Fixing diretto delle variabili . . . . . . . . . . . . . . Fixing indiretto delle variabili . . . . . . . . . . . . . Schema generale di xing delle variabili . . . . . . .
3.4
Core, EC, AAR e RR: calcolo della soluzione ottima di un MKP . . . 3.4.1 3.4.2 Approccio senza distinzione di cardinalit Approccio con distinzione di cardinalit . . . . . . . . . . . . . . . . . . . . . . .
4 Prove computazionali
4.1 4.2 Java 5.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Applicazione dell'algoritmo esatto . . . . . . . . . . . . . . . . . . . . 4.2.1 4.2.2 4.2.3 4.2.4 Istanze di P.C. Chu e J.E. Beasley 100.5 , 250.5 e 500.5 . . . . Istanze di P.C. Chu e J.E. Beasley 100.10 e 250.10 . . . . . . . Analisi separata delle cardinalit
90
91 93 93 95
. . . . . . . . . . . . . . . . 102
4.3
Algoritmo euristico . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111 4.3.1 4.3.2 4.3.3 4.3.4 4.3.5 Valutazione dei problemi ridotti . . . . . . . . . . . . . . . . . 111 Istanze di P.C. Chu e J.E. Beasley 500.10 . . . . . . . . . . . . 112 Istanze di P.C. Chu e J.E. Beasley 500.30 . . . . . . . . . . . . 114 Confronto con le migliori euristiche . . . . . . . . . . . . . . . 114
Risultati per le istanze P.C. Chu e J.E. Beasley 250.10, 100.30, 250.30 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
INDICE
122
. . . . . . . . . . . . . . . . . . . . . . . 125 . . . . . . . . . . . . . . . . . . . 128
Risoluzione del problema con Core minimale . . . . . . . . . . 134 Espansione del Core . . . . . . . . . . . . . . . . . . . . . . . 136
Risoluzione del problema con Core espanso . . . . . . . . . . . 136 Applicazione dell'algoritmo RR Applicazione dell'algoritmo AAR Altre note implementative . . . . . . . . . . . . . . . . . 140 . . . . . . . . . . . . . . . . 151
. . . . . . . . . . . . . . . . . . . . 155
6 Conclusione
6.1 6.2
166
Capitolo
1.1
max
j=1 n
pj xj
wij xj ci i = 1, .., m
j=1
(1.1)
xj {0, 1} j = 1, .., n
Si tratta di un problema di massimizzazione denito su a
problema suggerisce, il MKP una generalizzazione del noto problema dello zaino unidimensionale, meglio conosciuto come 0-1 Knapsack Problem con la seguente
Multiple Knapsack Problem Multidimensional Knapsack Problem, descritto nel nostro lavoro
7
CAPITOLO 1.
formulazione:
max
j=1 n
pj xj
wj xj c
j=1
(1.2)
xj {0, 1} j = 1, .., n
Le variabili peso
xj
rappresentano gli
e un
wj .
Il meccanismo risolutivo del problema denito in (1.2) consiste nell'inserire un sottoinsieme di oggetti
in modo che venga massimizzato il prezzo totale degli stessi senza violare il vincolo di capacit dello zaino. Il MKP un problema dello zaino m-dimensionale nel senso che soggetto con-
m vincoli di capacit distinti. Ogni oggetto j caratterizzato da un prezzo pj e da m pesi wij che variano in relazione allo zaino in cui vengono inseriti. Selezionare un oggetto j (quindi porre xj = 1) corrisponde a doverlo inserire in tutti gli m zaini del problema. L'obiettivo della risoluzione del MKP sempre quello
temporaneamente a di massimizzare il prezzo totale del set di oggetti selezionati con l'unica dierenza che tale sottoinsieme di oggetti deve poter essere inserito in ogni zaino senza che ne venga ecceduta la relativa capacit. Di fatto la notazione utilizzata nel modello (1.1) assume il seguente signicato:
il valore di
xj
j esimo:
se
xj = 1,
l'oggetto
selezionato e viene inserito in tutti gli zaini del problema; in caso contrario si ha che
xj = 0. j
caratterizzato da un proprio prezzo
ogni item
pj
qualora un item venga selezionato, deve essere inserito in tutti gli zaini. Il peso dell'oggetto varia a seconda dello zaino in cui inserito. Il valore di tale peso contenuto nei parametri l'oggetto inserito.
wij ,
con
l'oggetto selezionato e
lo zaino in cui
ogni zaino
contenuti nello zaino non pu eccedere la relativa capacit. Questo deve valere contemporaneamente per tutti gli zaini su cui il problema denito.
CAPITOLO 1.
Inoltre, per evitare riformulazioni banali del problema di partenza in un problema di dimensioni ridotte, vengono fatte le seguenti assunzioni:
non pu essere
mai inserito in uno zaino senza violare il vincolo di capacit e si pone subito
i esimo
diventa
diverso
aventi primo membro uguale e secondo membro dierente. Di fatto il vincolo con capacit maggiore diventa ridontante e viene scartato dalla denizione del problema.
1.2
NP
Hard Strong
. Un problema
mo polinomiale che lo risolve. Un algoritmo si dice polinomiale se nel caso peggiore richiede un tempo di calcolo e
f (n) = O nk
se esiste un algo-
NP
qualora
venga risolto in un numero di passi polinomiale solo nel caso in cui si possa disporre di un numero indeterminato di macchine. Di fatto tutti gli algoritmi in grado di risolvere un problema tempo esponenziale
N P Hard
Strong se anche limitando con un polinomio i dati in ingresso il problema ancora N P Hard. Attualmente, pur sapendo che P N P , non si ancora riuscito a dimostrare se P = N P oppure P N P . Inoltre, secondo la teoria della complessit, un problema N P Hard se N P log , ossia che un qualunque algoritmo in grado di risolvere pu essere ridotto in spazio logaritmico in un algoritmo in grado di risolvere un qualunque problema appartenente a N P . Di fatto, se si riuscisse a trovare un algoritmo polinomiale per un problema N P Hard, ogni
CAPITOLO 1.
10
problema in
NP
NP.
Da queste considerazioni risulta chiaro che il Multidimensional Knapsack Problem
1.3
Applicazioni pratiche
Il Multidimensional Knapsack Problem tanto complesso quanto utile, in quanto il suo modello pu essere utilizzato per formalizzare una moltitudine di problemi reali. Tra le sue applicazioni pratiche spiccano sicuramente le aste combinatorie a tal punto che molti autori, per semplicare la spiegazione delle proprie metodologie risolutive, identicano gli elementi del modello del MKP con gli elementi caratteristici del contesto delle aste. In un'asta combinatoria, un venditore (il banditore d'asta) mette in vendita un insieme di beni ed i partecipanti all'asta possono formulare oerte per una qualsiasi combinazione dei beni stessi. In un'asta combinatoria sono in vendita una o, nel
caso generale, pi copie dello stesso bene. Il modello del MKP pu essere descritto tramite gli elementi del dominio dell'asta combinatoria e in particolare si ha che:
il numero di vincoli del problema corrisponde al numero di tipologie di beni distinti che vengono messi all'asta dal banditore;
la capacit
ci
del vincolo
i esimo
della tipologia
messi all'asta;
il numero di variabili del problema corrisponde al numero di oerte che sono state fatte dai partecipanti all'asta. La variabile associata
xj
il coeciente
pj
della variabile
xj
ogni oerta viene fatta su tutti i tipi di beni, richiedendo per ognuno di essi una determinata quantita. Il numero di beni del tipo valorizzato in
richiesto dall'oerta
wij ;
CAPITOLO 1.
11
il banditore d'asta deve selezionare, tra tutti i set di oerte tali che la somma dei beni totali richiesti per ogni tipo sia minore di quella da lui messa a disposizione, quello che gli consente di massimizzare i protti.
Data l'estrema semplicit nel descrivere il modello del MKP tramite concetti quali oerte, beni, prezzi ecc, tali notazioni saranno pi volte utilizzate anche nel seguito della trattazione. Ma il Multidimensional Knapsack Problem trova applicazioni in tanti altri casi reali. Tra i pi importanti ricordiamo i problemi di capital budgeting, project
selection, cutting stock e problemi di allocazione di risorse. Inne, molti problemi di programmazione intera necessitano la risoluzione di un sottoproblema che pu essere ricondotto a qualche forma particolare del MKP (numero pressato di vincoli, capacit dei vincoli unitaria, capacit dei vincoli tutte uguali ecc.).
Capitolo
Stato dell'arte
Il Multidimensional Knapsack Problem stato uno dei problemi maggiormente studiati in letteratura sin dalla ne degli anni 60, sia per l'eterogeneit delle sue applicazioni pratiche, sia perch l'estrema dicolt nel trovare un metodo risolutivo eciente ha stimolato i ricercatori a sviluppare idee su svariati fronti. Molti autori hanno proposto e stanno tuttora proponendo soluzioni volte a trovare un compromesso tra l'ecacia (la ricerca della soluzione ottima) e l'ecienza (il tempo impiegato per trovarla) e i risultati migliori in quest'ottica sono stati ottenuti proprio in questi anni. La ricerca ha spaziato nelle direzioni pi variegate: da metodi per ridurre la dimensione del problema ad algoritmi in grado di trovare buone soluzioni in tempi accettabili, dalla generazione di tagli ecaci per ridurre lo spazio di ricerca delle soluzioni a metauristiche complesse per la ricerca di un buon lower bound al problema da cui eventualmente far partire algoritmi esatti di tipo branch and cut. Nonostante l'enorme impiego di risorse ed energie nella ricerca di una metodologia risolutiva denitiva per questa classe di problemi, la realt dei fatti che si ancora ben lontani dal raggiungere questa meta. Attualmente non esiste alcun algoritmo
> 250,
m > 5)
ridurre ragionevolmente lo spazio di ricerca della soluzione ottima ha scoraggiato la ricerca di una metodologia esatta per questo tipo di problemi. Di conseguenza, data l'incapacit di risolvere in modo polinomiale problemi di tipo
N P Hard,
gli sforzi
maggiori sono concentrati tuttora nel raorzare metodi euristici complessi volti a trovare soluzioni ammissibili sempre migliori e in tempi sempre pi brevi. In questo capitolo cercheremo di presentare una sintetica panoramica dei metodi
12
CAPITOLO 2.
STATO DELL'ARTE
13
risolutivi che a nostro avviso sono da considerarsi i pi ecaci tra tutti quelli proposti in pi di 40 anni di ricerca. I risultati computazionali di alcuni di essi verranno
presentati nel capitolo 4, quando sar necessario confrontare i risultati ottenuti dal nostro algoritmo con quanto di meglio c' in letteratura.
2.1
Generazione di istanze
Prima di entrare nel merito degli algoritmi risolutivi per il MKP, opportuno aprire una breve parentesi per quanto concerne le istanze su cui questi algoritmi possono essere testati per valutarne l'ecacia e l'ecienza. In letteratura non esistono istanze su problemi reali sulle quali basare i test di valutazione degli algoritmi progettati. L'unico set di istanze estrapolate da casi reali consta di 56 problemi di dimensione variabile da
n = 6
a 105 oerte e da
m = 2
a 30 beni.
sono molto facili da risolvere e la soluzione ottima allo stato dell'arte attuale pu essere determinata in una frazione di secondo. Di fatto nata l'esigenza di trovare un meccanismo che permettesse di generare delle istanze benchmark con lo scopo di valutare oggettivamente la qualit delle varie metodologie risolutive senza che i risultati potessero essere inuenzati dall'estrema semplicit dei problemi formulati. Le istanze utilizzate per testare l'algoritmo descritto in questo lavoro di tesi sono state generate da P.C. Chu e J.E. Beasley utilizzando una procedura da loro stessi suggerita in [9]. Queste istanze, disponibili al sito internet [45], nonostante
siano state proposte ormai da 10 anni, rappresentano tuttora una sda per chiunque intenda valutare la bont del proprio algoritmo, in quanto la loro complessit tale che per la maggior parte di esse non ancora nota la soluzione ottima. Il numero dei vincoli ssato a
m = 5, 10, 30
Sono I
wij
delle oerte nei vincoli sono numeri interi ottenuti da un generatore discreto
uniforme
U (0, 1000).
le capacit
ci
ci =
n j=1
wij
dove
per le prime dieci istanze, 0.50 per le seconde dieci e 0.75 per le ultime dieci. coecienti della funzione obiettivo sono correlati ai pesi
wij
pj =
m i=1
wij
+ 500qj
CAPITOLO 2.
STATO DELL'ARTE
14
dove
qj
U (0, 1).
La complessit delle istanze dipende da diversi parametri: il numero di item, il numero di vincoli, i pesi nei vincoli, i termini noti dei vincoli, il numero di item presenti nella soluzione ottima e la correlazione fra essi. Le istanze di P.C. Chu e J.E. Beasley sono complesse proprio perch il peso dei vincoli e i loro termini noti, il numero di item presenti nella soluzione ottima e la correlazione tra gli stessi sono elevati. Per una esauriente trattazione sulla complessit dei problemi correlati si
rimanda a [16] e [31]. Le istanze di P.C. Chu e J.E. Beasley sono quelle pi note in letteratura e la progettazione di un metodo risolutivo per il Multidimensional Knapsack Problem non pu prescindere dal testare l'algoritmo su questo set di problemi, anche per ottenere un valido raronto con i risultati forniti da altri autori. Per completezza, bene segnalare che recentemente sono stati proposti set di istanze complesse, ottenute aumentando la dimensione del problema e utilizzando diversi meccanismi di generazione per aumentare la correlazione tra le variabili. Tra i pi importanti si cita il meccanismo di generazione di istanze proposto da Bertsimas e Demir [7] adottato per i problemi di test per l'algoritmo da loro sviluppato, le 7 istanze proposte da Glover e Kochenberger [17] nel 1996 e le 11 istanze pubblicate sempre da Glover e Kochenberger [46] nel 2001 di elevate dimensioni sino a
n = 2500
m = 100.
2.2
Algoritmi esatti
Allo stato dell'arte attuale, non esiste alcun algoritmo esatto in grado di risolvere in modo soddisfacente il Multidimensional Knapsack Problem. Sebbene sia possibile calcolare la soluzione ottima di istanze molto semplici anche con un risolutore generico per problemi di Programmazione Lineare Intera, al crescere della dimensione del problema nessun algoritmo presente in letteratura risulta scalabile in termini di tempo speso per la determinazione dell'ottimo. Chiaramente sono stati sviluppati diversi approcci per poter risolvere in modo esatto questa categoria di problemi. Considerata l'inecienza dei vari approcci su istanze complesse, la ricerca si spesso focalizzata nell'integrare ai vari metodi esatti alcune procedure euristiche per velocizzare la scansione dello spazio di ricerca delle soluzioni. In questo modo lo stesso algoritmo pu essere utilizzato sia come algoritmo esatto per istanze di dimensioni ridotte, sia come euristica per istanze pi complesse altrimenti risolvibili all'ottimo
CAPITOLO 2.
STATO DELL'ARTE
15
in tempi non accettabili. Gli algoritmi esatti per la risoluzione del Multidimensional Knapsack Problem fanno riferimento a:
algoritmi basati su analisi Branch and Bound; algoritmi basati su analisi Branch and Cut; algoritmi basati sulla programmazione dinamica; algoritmi basati sulla generazione di alberi binari.
Di seguito viene presentata un'introduzione sintetica ai primi tre approcci. Per quanto riguarda l'ultimo approccio, verr dato ampio spazio nel capitolo 3 costituendo esso una parte fondamentale alla base dell'algoritmo sviluppato durante questo lavoro di tesi.
P 0 = (z, F (P 0 )) dove z
la funzione
F (P ) la regione ammissibile. La miglior soluzione ottima 0 best sar z = z (P ) = {z (x) : x F (P )} mentre z rappresenta la miglior soluzione 0 1 2 k ammissibile nota. Suddividiamo il problema P in K sottoproblemi P , P , ...,P K i 0 i j i j tali che i=1 F (P ) = F (P ) e F (P ) F (P ) = , P , P : i = j . Questo processo
0
di ramicazione (branching) viene solitamente rappresentato mediante un albero decisionale dove ogni nodo rappresenta un sottoproblema. Risolvere il problema quindi equivalente a risolvere la totalit dei suoi che
P0
z = min z (P 1 ) , z (P 2 ) , ..., z P K
Un sottoproblema
Pi
pu considerarsi
1 Il discorso del tutto analogo al caso di problemi di minimizzazione. Aver scelto un problema
di massimizzazione in linea con l'analisi del
CAPITOLO 2.
STATO DELL'ARTE
16
Pi
F (P i )
z (P i ) < z best
Se non si riesce a risolvere un nodo (in quanto operazione troppo complessa) necessario suddividerlo in altri sottoproblemi. possibile determinare un upper bound Inoltre per ogni sottoproblema
Pi
U B (P )
U B (P i ) < z best
il nodo
pu essere escluso visto che la miglior soluzione che si pu sperare di ottenere comunque peggiore della migliore soluzione ammissibile sinora nota del problema originale. Gli algoritmi Branch and Bound dieriscono sostanzialmente da come
viene portata avanti la scomposizione del problema, dal tipo di discesa dell'albero per esplorare i nodi da risolvere e dalle tecniche per determinare lower bound e upper bound ai problemi. Applicato al MKP, le cui variabili possono assumere solo valore 1 o 0, l'albero decisionale di branching binario e i due gli sono ottenuti partendo dal problema padre e settando rispettivamente una variabile
xj
dimensioni non possibile risolvere all'ottimo un sottoproblema n tanto che non sono state ssate un numero sucientemente elevato di variabili. Questo, tradotto in termini di Branch and Bound, signica scendere a fondo nell'esplorazione dell'albero decisionale il cui numero di nodi cresce esponenzialmente. L'handicap di questo
approccio l'elevato consumo di memoria richiesto dai sottoproblemi che devono ancora essere valutati e di fatto si cercato di perfezionare le tecniche di potatura (fathoming) dell'albero per evitare di creare nodi superui in termini di residenza della soluzione ottima. Molti autori hanno proposto dei miglioramenti al metodo classico di Branch and Bound applicato alla risoluzione del MKP, quasi tutti volti a determinare un valore di un upper bound che potesse escludere l'analisi dei vari nodi ai pi alti livelli possibili dell'albero decisionale. Shin [37] ha presentato un metodo che sfrutta un upper bound cos formulato: dati
(KP )i
problemi con
siano
zi
CAPITOLO 2.
STATO DELL'ARTE
17
max
j=1 n
pj xj
wij xj ci
j=1
(2.1)
xj {0, 1} j = 1, .., n
segue che:
(2.2)
(2.3)
I migliori risultati in termini di qualit dell'upper bound relativo ai sottoproblemi sono stati ottenuti dagli studi svolti da Gavish e Pirkul pubblicati in [31] e [30]. Sono stati paragonati diversi tipi di rilassamento oltre a quello continuo, tra cui il lagrangiano, il surrogato e il composito. I risultati sperimentali evidenziano
che il rilassamento composito trova il miglior upper bound anche se con un tempo computazionale maggiore rispetto agli altri rilassamenti. K. L. Brown [8] ha sviluppato l'algoritmo CAMUS (Combinatorial Auctions Multi-Unit Search) che rappresenta il primo tentativo di risoluzione del Multidimen-
sional Knapsack Problem nel contesto delle aste combinatorie multi-unit. Il metodo
risolutivo garantisce la soluzione ottima attraverso una tecnica Branch and Bound di tipo depth-rst
che cerca un'allocazione full assegnando tutti i beni a disposizione I risultati presentati sono relativi a
problemi generati dagli autori stessi con un metodo spiegato nell'articolo che prevede che per ogni oerta i beni richiesti siano comunque pochi.
CAPITOLO 2.
STATO DELL'ARTE
18
L'algoritmo di Gonen-Lehmann [20] si basa anch'esso su un'approccio di tipo Branch and Bound in cui l'analisi dell'albero di ricerca viene velocizzata disponendo di lower bound e upper bound vicini all'ottimo. Entrambi gli algoritmi di GonenLehmann e CAMUS risolvono facilmente istanze scarsamente correlate di grandi dimensioni. Tuttavia il set di problemi preso in considerazione poco realistico e si dimostrano inecaci per istanze benchmark pi complesse come quelle proposte da P.C. Chu e J.E. Beasley.
(lower bound), anche se ottenuto attraverso sosticate tecniche di rilassamento, ha comunque un valore tale da consentire l'eliminazione del nodo analizzato solo in profondit elevate dell'albero, quando cio il numero di nodi generati gi esploso.
CAPITOLO 2.
STATO DELL'ARTE
19
L'utilizzo di disuguaglianze valide al rilassato continuo dei vari sottoproblemi consente di migliorare notevolmente il bound ottenuto vericando prima la condizione di potatura del ramo e tagliando il nodo stesso evitando di procedere con ulteriori quanto inutili operazioni di branching. Di fatto i pi sosticati algoritmi esatti per problemi di Programmazione Intera si sviluppano tutti a partire direttamente da un framework Branch and Cut anzich Branch and Bound, ivi inclusi gli algoritmi specici per il Multidimensional Knapsack Problem. Le dierenze sostanziali tra questi algoritmi, oltre che includere le diverse scelte implementative tipiche di un approccio Branch and Bound, includono anche il tipo di disuguaglianze valide generate, se sono valide localmente (solo per il nodo analizzato e i relativi gli) o globalmente (per tutti i nodi dell'albero) e i criteri in base ai quali si decide se relativamente ad un nodo opportuno applicare un taglio piuttosto che un operazione di branching. Sebbene in letteratura siano noti molti tagli nel contesto generico della Programmazione Linera Intera, la maggior parte di essi risulta del tutto inecace se applicata specicatamente al caso del Multidimensional Knapsack Problem. La semplicit e l'assenza di informazioni signicative estrapolate dal modello del MKP evidenzia l'inutilit di disuguaglianze che per altre tipologie di problemi risultano valide. L'unico approccio di tipo Cutting Planes che sembra aver contribuito a ottenere risultati positivi in termini di miglioramento dell'upper bound basato sulle lifted
cover inequalities (LCIs ), introdotte separatamente da Balas [3] e Wolsey [40] nel
1975, e ampliate successivamente da Gu et al. [21].
Q := conv x {0, 1}n : aT x b .L'insieme C N = {1, ..., n} si denisce cover se soddisfa la relazione jC aj > b. Data una cover C , la cover inequality jC xj |C| 1 sicuramente valida per Q. Inoltre, le disuguaglianze di copertura pi forti si ottengono se la cover C minimale, vale a dire se nessun sottoinsieme di C a sua volta una cover. In generale per ogni vincolo del problema possibile
Sia generare pi tagli di copertura minimale. Osorio et al. [28] hanno proposto un semplice algoritmo per la generazione di tutte le cover minimali associate ad un
MKP e hanno denito, partendo da esse, una nuova classe di disuguaglianze da loro
denite contiguous cuts. Le lifted cover inequalities sono ottenute applicando tecniche di lifting delle variabili ai tagli di copertura minimali generati. Come noto dalla programmazione lineare, se fosse possibile generare dei tagli in grado di ridurre il poliedro del problema continuo nel suo convex hull, il problema intero verrebbe risolto all'ottimo in tempi polinomiali attraverso l'algoritmo del simplesso. Tuttavia la determinazione di tutti i
CAPITOLO 2.
STATO DELL'ARTE
20
tagli cosidetti facet-inducin g a sua volta un problema dicile quanto la risoluzione del MKP. Le tecniche di lifting permettono di generare dei tagli facet-inducing su una porzione ridotta del poliedro del problema. In particolare, una lifted cover inequality assume la forma seguente:
xj +
jC
dove i coecienti di lifting
j xj |C| 1
jN \C
(2.4)
soddisfano la relazione
0 j |C| 1. C.
L'operazione
di lifting consiste dunque nel raorzare il taglio di copertura minimale portando al suo interno tutte le variabili non contenute nella cover per computare i coecienti di lifting. Esistono diverse tecniche
molto veloce basato sulla programmazione dinamica proposto da Zemel in [41]. I migliori risultati sono stati ottenuti da Kaparis et al. [24] che hanno ulteriormente raorzato le LCIs attraverso dei coecienti di down-lifting. Pi precisamente hanno osservato che per ogni vincolo la disuguaglianza
i,
e un sottoinsieme
D C,
(2.5)
xj |C \ D| 1
jC\D
valida per il poliedro ristretto
conv x {0, 1}
|N \D|
:
jN \D
aj x j b i
jD
aj
(2.6)
N \C
e un down-lifting
xj +
jC\D jN \C
j xj +
jD
j xj |C \ D| +
jD
j 1
(2.7)
che facet-inducing per il poliedro (2.6). Kaparis et al. spiegano nel dettaglio come procedere nelle operazioni di lifting per ottenere dei tagli pi ecaci per il problema MKP di partenza. Inoltre introducono una nuova classe di disuguaglianze, chiamate global lifted cover inequalities (GLCIs ), ottenute semplicemente creando i tagli di copertura considerando contemporaneamente tutti i vincoli del problema. I risultati computazionali del loro
CAPITOLO 2.
STATO DELL'ARTE
21
dimensioni mentre si osservato come per le istanze pi complesse di P.C. Chu e J.E. Beasley (n
= 500, m 10)
restrizione del bound si ha con le GLCIs, che necessitano tuttavia di un tempo di calcolo maggiore. Gupta, Buln e Smith [22] hanno sviluppato un metodo per determinare LCIs con coecienti di lifting frazionari. Sebbene questa classe di disuguaglianze risulti essere pi ecace delle LCIs a coecienti interi, la tecnica per calcolare i migliori coecienti frazionari possibili si basa su un problema di separazione
N P Completo
e non trovano applicazioni pratiche nelle istanze di grandi dimensioni. In generale l'applicazione di questi tagli nell'ambito di un framework Branch and Cut commerciale velocizza la navigazione dell'albero decisionale ma non sucientemente ecace da evidenziare sostanziali miglioramenti per quanto riguarda la risoluzione di istanze medio-complesse. La realt dei fatti che non esiste tuttora alcun metodo che applicato al Branch and Cut lo renda adatto a risolvere all'ottimo problemi correlati di grandi dimensioni. Di conseguenza, allo stato attuale, molti
algoritmi che si basano su questo approccio prevedono diversi rilassamenti delle condizioni di fathoming dei nodi, l'utilizzo delle quali, pur velocizzando di molto la navigazione dell'albero, non garantisce la determinazione della soluzione ottima.
z (j, g1 , ..., gm ) la soluzione ottima variabili {1, ..., j} e con le capacit dei
, sia
CAPITOLO 2.
STATO DELL'ARTE
22
vincoli pari a
g1 , ..., gm :
j
max
k=1 j
pk xk
wik xk gi i = 1, ..., m
k=1
(2.8)
xk {0, 1} k = 1, ..., j
Per il calcolo del valore
z (j, g1 , ..., gm )
gi wij
per alcuni
i {1, ..., m}
z (j, g1 , ..., gm ) = max {z (j 1, g1 , ..., gm ) , pj + z (j 1, g1 w1j , ..., gm wmj )} se gi wij per tutti gli i {1, ..., m}
La soluzione ottima
n c1 ... cm
z (n, c1 , ..., cm ) pu essere trovata con una tabella di dimensioni m m approsimabile a O (ncmax ) dove cmax = max {c1 , ..., cm } che richiede = 100 e m = 5) hanno ci 10000:
alti tempi di computazione e grande spazio di memoria. Tanto per rendere l'idea, le istanze pi semplici di P.C. Chu e J.E. Beasley (n questo implica circa
10
22
Problem.
Un primo tentativo di sviluppare un algoritmo dinamico competivo dovuto al lavoro svolto da Balev, Yanev, Freville e Andonov [4] grazie a tecniche di riformulazione per ridurre la dimensione del problema di partenza. Bertsimas e Demir [7] hanno proposto un approccio alla programmazione dinamica approssimata basata su una metodologia parametrica per semplicare la valutazione dei sottoproblemi. L'algoritmo sviluppato, denominato ADP (Adaptive
2.3
Algoritmi euristici
Gli algoritmi euristici si pongono come obiettivo quello di determinare una buona soluzione ammissibile in tempi accettabili senza che vi sia comunque la garanzia che
CAPITOLO 2.
STATO DELL'ARTE
23
la soluzione trovata coincida con quella ottima. Si tratta di un compromesso tra ecienza ed ecacia del meccanismo risolutivo utile in quei contesti in cui la soluzione ottima non pu essere determinata in tempi ragionevoli. L'aspetto che accomuna i vari algoritmi euristici il tentativo di ridurre nel modo migliore possibile lo spazio di ricerca delle soluzioni del problema, evitando di analizzare a priori un insieme di soluzioni all'interno del quale non presente quella ottima. La bont di un algoritmo dipende sostanzialmente da come la navigazione dello spazio di ricerca viene portata avanti. Esistono diverse tecniche consolidate per una scansione euristica dello spazio di ricerca, a prescindere dalla classe di problemi che si sta cercando di risolvere. Nell'ambito del MKP, si cercato di fatto di adattare queste tecniche generali nel contesto del problema di riferimento integrandole con le informazioni contenute nel suo modello. Non lo scopo di questa sede procedere in una trattazione esaustiva di tutti gli algoritmi euristici sviluppati per risolvere il MKP. Si tenga presente infatti che la dicolt nel risolvere in modo esatto questa categoria di problemi ha spinto la ricerca degli ultimi decenni nella direzione euristica e di fatto gli approcci risolutivi proposti in quest'ottica sono molti, ognuno con i propri pregi e i propri difetti. Di seguito verranno descritti sinteticamente quelli che a nostro avviso sono gli algoritmi di maggior portata, sia per la qualit dei risultati ottenuti sia per le idee introdotte, che hanno contribuito o possono contribuire a nuove strade di ricerca. In particolare ci soermeremo sulle seguenti classi di algoritmi euristici:
algoritmi di tipo greedy; metaeuristiche; algoritmi euristici basati sul rilassamento continuo.
CAPITOLO 2.
STATO DELL'ARTE
24
un'ecace funzione di ordinamento delle oerte, attivit questa non banale considerando i diversi parametri in gioco (prezzi delle oerte nella funzione obiettivo e costi delle stesse per ogni vincolo del problema). Dobson [12] ha proposto un ordinamento secondo la funzione:
ej =
pj m i=1 wij
(2.9)
Senju e Toyoda [36] propongono invece un ordinamento che tiene in considerazione anche delle capacit dei vincoli:
ej =
pj
m i=1
wij
n j=1
wij ci
(2.10)
Kellerer et al.
ej =
I coecienti
ri
possono essere visti come una sorta di moltiplicatori surrogati, come Si noti che ponendo
ri =
n j=1
wij ci
si
ottiene la relazione ( 2.10 ). Freville e Plateau [15] suggeriscono i seguenti valori dei coecienti
ri : ri =
n j=1 wij ci n j=1 wij
(2.12)
Gli algoritmi greedy, a prescindere dalla funzione di ordinamento delle oerte su cui si basano, sono molto inecaci in quanto la soluzione trovata con essi ben lontana da essere quella ottima, soprattutto per istanze complesse. Tuttavia, considerando l'ecienza del meccanismo risolutivo che permette di determinare una soluzione ammissibile in tempi polinomiali, gli algoritmi greedy vengono generalmente utilizzati come punto di partenza di approcci pi complessi che necessitano di un lower bound iniziale e di un sistema ecace di ordinamento delle variabili.
CAPITOLO 2.
STATO DELL'ARTE
25
2.3.2 Metaeuristiche
Per metaeuristica si intende una qualunque tecnica basata sulla Ricerca Locale in grado di partire da una soluzione ammissibile non vuota e di migliorarla iterativamente eettuando semplici modiche (o mosse) della soluzione corrente. L'algoritmo termina quando non esistono pi modiche in grado di migliorare la soluzione corrente. A dierenza dei semplici algoritmi di Local Search, le tecnice metaeuristiche utilizzano speciali meccanismi per uscire dai minimi locali incontrati e per evitare il vericarsi di cicli nell'evoluzione dell'algoritmo. In letteratura esistono molte tecniche metaeuristiche consolidate. Nell'ambito
del Multidimensional Knapsack Problem molti autori hanno adattato algoritmi gi esistenti introducendo nuovi aspetti per l'analisi del vicinato delle soluzioni in modo da tagliare buona parte dello spazio di ammissibilit del problema.
Algoritmi genetici
Gli algoritmi genetici prendono spunto dal processo evoluDurante il corso dell'evoluzione le
popolazioni evolvono secondo dei principi di selezione naturale in cui gli individui che meglio si adattano al loro ambiente hanno maggiori possibilit di sopravvivere e riprodursi rispetto agli altri. Nel contesto di un problema di ottimizzazione, gli
individui di una popolazione vengono codicati in una stringa di cromosomi che rappresenta una possibile soluzione del problema. Vengono poi utilizzate delle funzioni per valutare la robustezza genetica dei vari individui secondo dierenti criteri. Agli individui ritenuti pi forti geneticamente vengono applicate delle procedure di
crossover attraverso le quali pezzi di cromosomi vengono alterati creando nuovi individui che possono integrarsi o sostituirsi alla popolazione attuale. Questo processo di valutazione-selezione-riproduzione viene iterato no a quando non viene trovata una soluzione che soddisfa opportuni criteri. genetico sono qui di seguito elencati: 1. Generazione di una popolazione iniziale; 2. Valutazione della robustezza genetica degli individui nella popolazione; 3. Selezione di due o pi genitori dalla popolazione; 4. Ricombinazione delle informazioni genetiche dei genitori per generare i gli; 5. Valutazione della robustezza genetica dei gli; I passi principali di un algoritmo
CAPITOLO 2.
STATO DELL'ARTE
26
6. Sostituzione della popolazione ( tutta o una sua parte ) con i gli generati; 7. Se non si ottiene una soluzione che soddisfa opportuni criteri, tornare al passo 3. P.C. Chu e J.E. Beasley[9] hanno sviluppato un algoritmo genetico per il Multidimen-
sional Knapsack Problem basandosi sul meccanismo risolutivo descritto in precedenza e denendo nel dettaglio le strategie di valutazione, selezione e riproduzione degli individui utilizzando le informazioni contenute nel modello del problema. Il generico individuo viene rappresentato come un vettore in
S [j]
tenuta o meno nella soluzione. Gli individui vengono valutati secondo una funzione
f (S) =
n j=1
pj S [j]
gli vengono generati sia attraverso processi di mutazione in cui vengono alterati i bits di un unico genitore, sia attraverso operatori di crossover che combinano i bits di due genitori per generare un unico glio. I gli generati attraverso le procedure di mutazione e di crossover possono corrispondere a soluzioni che non soddisfano tutti i vincoli del problema. Per garantirne l'ammissibilit, i gli vengono sottoposti a Un algoritmo
greedy viene utilizzato anche per generare la popolazione iniziale costituita da 100 unit suddivise in due gruppi. Il processo di selezione dei genitori per la creazione dei nuovi individui viene attivato su entrambi i gruppi in base alla funzione di valutazione della robustezza genetica
f (S) .
f (S))
in modo che
ogni popolazione non ecceda mai le 100 unit. Per una pi approfondita trattazione dell'algoritmo proposto da P.C. Chu e J.E. Beasley si rimanda a [9]. L'algoritmo proposto da P.C. Chu e J.E. Beasley stato testato sulle 270 istanze da loro generate, ottenendo risultati di elevata qualit. Allo stato dell'arte attuale, nonostante in 10 anni siano stati evidenziati progessi nella ricerca nell'ambito del
MKP, l'algoritmo genetico da loro progettato ancora uno di quelli che permette di
ottenere le soluzioni migliori anche in relazione al tempo necessario per ottenerle. Recentemente Puchinger, Raild e Gruber [34] hanno sviluppato un approccio ibrido in cui un algoritmo genetico e un risolutore general purpouse per problemi lineari interi basato su Branch and Cut vengono eseguiti in parallelo scambiandosi continuamente informazioni in modo sincrono e bidirezionale. L'algoritmo consta di due parti fondamentali: la procedura genetica vera e propria (AG ) e il framework
CAPITOLO 2.
STATO DELL'ARTE
27
Branch and Cut (B&C ). AG non si discosta molto dal lavoro svolto da P.C. Chu e J.E. Beasley seppur con dei miglioramenti per quanto riguarda la generazione della popolazione iniziale e la valutazione della robustezza genetica degli individui. Il
framework B&C utilizza CPLEX come risolutore per problemi di programmazione lineare intera a cui vengono aggiunti ulteriori tagli per ridurre lo spazio di ricerca della soluzione ottima. Puchinger et al. hanno osservato, analizzando le istanze di P.C. Chu e J.E. Beasley per le quali era nota la soluzione ottima, che la distanza di
e la soluzione
con
xLP
soluzione del rilassato continuo, quasi sempre pi piccola del 10% del numero
totale di variabili del problema. Alla luce di questa considerazione empirica stato generato un nuovo taglio da applicare al framework B&C del tipo:
x, xRLP =
jS LP
(1 xj ) +
j S LP /
xj k
con
S LP = j = 1, ..., n |xLP = 1 j
I due algoritmi vengono eseguiti in parallelo in modo che possano scambiarsi le informazioni che serviranno poi per orientare la ricerca in opportune direzioni dello spazio delle soluzioni. In particolare se AG trova una soluzione migliore di quella attuale, questa viene utilizzata per incrementare il valore del lower bound utilizzato nel framework B&C. Nel caso sia il framework B&C a determinare una soluzione migliore questa viene aggiunta nella popolazione analizzata da AG e i valori della soluzione duale vengono utilizzati nella funzione di ordinamento delle variabili su cui si basa la riparazione delle soluzioni glie generate non ammissibili. I risultati ottenuti da Puchinger et al. sono stati ricavati applicando diverse
strategie di combinazione dei due algoritmi, a seconda di quante informazioni venivano scambiate nell'esecuzione parallela dei due processi. In generale si osserva un miglioramento complessivo della qualit delle soluzioni che rendono questo approccio ibrido una delle migliori strategie risolutive, ottenendo soluzioni di alta qualit in tempi molto brevi sulle istanze complesse di P.C. Chu e J.E. Beasley.
Tabu Search
[19] nel 1989 per far fronte al problema principale dei classici metodi di ricerca locale relativo all'arresto dell'algoritmo qualora nel vicinato della soluzione corrente non esista una soluzione migliore, cadendo appunto in quelli che comunemente vengono
CAPITOLO 2.
STATO DELL'ARTE
28
deniti minimi (o massimi) locali. L'idea principale su cui si basa il Tabu Search quella di consentire delle mosse peggioranti proibendo le ultime mosse eseguite (tabu ) nel cammino di ricerca, in modo che l'algoritmo non ricada subito nel minimo locale. Caratteristica basilare
di ogni algoritmo di Tabu Search quindi il sistematico utilizzo della memoria nel senso che, per aumentare l'ecacia del processo di ricerca, viene tenuta traccia nella
tabu list non solo delle informazioni locali (come il valore corrente della funzione
obiettivo) ma anche di informazioni aggiuntive relative all'itinerario percorso. Tali informazioni vengono impiegate per guidare la mossa dalla soluzione corrente alla soluzione successiva, da scegliersi all'interno del vicinato. Esiste una vastissima letteratura dedicata all'argomento, in quanto il Tabu Search rappresenta la procedura euristica pi diusa per risolvere una moltitudine di problemi, sia per l'ecacia dei risultati trovati, sia per la semplicit di implementazione della tecnica. La ricerca nel campo del Tabu Search per risolvere il Multidimensional Knapsack
Problem inizia con il lavoro di Dammayer e Voss [10] in cui sono state comparate diverse strategie statiche e dinamiche per gestire la tabu list. In particolare sono stati ottenuti interessanti risultati utilizzando una versione dinamica del Tabu Search, chiamato Reverse Elimination Method [11]. Recenti estensioni al metodo introdotto da Dammeyer e Voss sono state presentate da Hana e Freville [23] che hanno proposto nuove regole dinamiche di intensicazione e diversicazione nell'applicazione delle mosse. Indubbiamente i migliori risultati sono stati ottenuti combinando il Tabu Search classico con la programmazione lineare intera. Per esempio, Glover e Kochenberger [46] hanno proposto una schema oscillatorio di navigazione del vicinato della soluzione corrente alternando fasi costruttive e distruttive nell'alterazione della soluzione, il tutto guidato da informazioni ottenute dai vincoli surrogati e dalle variabili duali del problema. Il loro lavoro stato testato sia sulle istanze di P.C. Chu e J.E. Beasley, sia su un set di problemi complessi da loro generati (no a
n = 500
m = 25)
ottenendo risultati di alta qualit. Nel 2001 Vasquez e Hao [38] hanno pre-
sentato un'altra tecnica ibrida costruendo un set di soluzioni ammissibili partendo dal rilassato continuo risolto con un vincolo addizionale di cardinalit
n j=1
xj = k .
Lo stesso vincolo viene utilizzato anche per ridurre il vicinato della soluzione corrente, visitato attraverso una versione modicata della Reactive Tabu Search proposta da Battiti e Tecchiolli [5] che utilizza due tipologie distinte di tabu list.
CAPITOLO 2.
STATO DELL'ARTE
29
Nel 2005 Vasquez [39], in collaborazione con Vimont, ha ripreso il lavoro iniziato con Hao introducendo dei miglioramenti nella gestione della tabu list e risolvendo le istanze di test proposte da P.C. Chu e J.E. Beasley e da Glover e Kochenberger, applicando l'algoritmo per un numero molto elevato di iterazioni. Al tempo di stesura di questo lavoro di tesi, le migliori soluzioni note per i principali problemi di benchmark in letteratura sono state trovate con i metodi di Vasquez e Hao [38] e di Vasquez e Vimont [39]. L'aspetto negativo di tutti i metodi basati su Tabu Search, come evidenziato anche dagli stessi Vasquez, Hao e Vimont nelle loro ricerche, l'inecienza nella risoluzione di problemi con un numero di variabili elevato (n
> 500)
in quanto il
vicinato delle soluzioni cresce esponenzialmente ed estremamente dicile poterlo valutare completamente in tempi accettabili.
euristiche che sono state studiate nell'ambito del Multidimensional Knapsack Prob-
per il simulated annealing necessario scegliere se, a partire da uno stato corrente
s,
s1
piuttosto che
s2 .
correggere le transazioni tra gli stati attraverso opportune procedure di backtracking. Il primo tentativo di utilizzo del simulated annealing nell'ambito del MKP lo si deve a Drexl [13] che ha introdotto uno speciale movimento casuale tra stati in modo da garantire l'ammissibilit di tutte le soluzioni generate durante il processo. Battiti
e Tecchiolli [6] hanno introdotto una funzione di penalit per trasformare il MKP in un problema non vincolato, ottenendo risultati comunque peggiori rispetto ad approcci basati su Tabu Search. Dueck e Scheuer [14] hanno invece proposto una
versione deterministica del simulated annealing, chiamata threshold accepting, che ha migliorato i risultati ottenuti da Drexl. Le reti neurali si basano principalmente sulla simulazione di neuroni articiali opportunamente collegati, i quali ricevono in ingresso dei segnali e li elaborano. Solitamente le reti neurali vengono progettate per approssimare algoritmi molto complessi ottenendo risultati simili ma in tempi di elaborazione molto inferiori. La ricerca
CAPITOLO 2.
STATO DELL'ARTE
30
sulle reti neurali nell'ambito del MKP si limita ai tentativi proposti da Battiti e Tecchiolli in [6] e Ohlssen et al. in [26], incontrando enormi dicolt nel mantenere ammissibile la soluzione in uscita dalla rete neurale. Gli studi volti a determinare l'ecacia delle tecniche di simulated annealing e reti neurali nel contesto del Multidimensional Knapsack Problem sono molto datati rispetto a Tabu Search e algoritmi genetici. Uno studio invece molto recente e
di grande impatto per la ricerca dei prossimi anni stato pubblicato nel 2006 da Puchinger e Raidl [33]. L'idea quella di studiare una porzione ridotta ma signicativa del problema di partenza denendone un Core a cui applicare una procedura
RGVNS (Relaxation Guided Variable Neighborhood Search ) per modicarlo dinamicamente. Nonostante la ricerca in questa direzione sia ancora agli albori, Puchinger e Raild hanno dimostrato che si possono ottenere risultati interessanti che possono competere con le pi consolidate tecniche metaeuristiche basate su Tabu Search.
xH .
xH j
dove
1 = 0
se se
(2.13)
xLP
La seconda parte invece risolve il rilassamento continuo del sottoproblema composto dalle variabili
xH j
non denite nella prima parte, vale a dire quelle per cui
xLP < 1. j
In particolare si pone:
(2.14)
CAPITOLO 2.
STATO DELL'ARTE
31
L'ultima assegnazione garantisce che almeno una variabile sia posta a 0 (quella con il valore frazionario minore nella soluzione del rilassamento continuo). Questa seconda parte iterata no a quando le variabili sono tutte poste a 0 o a 1. Pi basso il valore di
, migliore la soluzione e maggiore il tempo di computazione. Gli autori propongono = 0.25. Si noti che = 1 equivalente al calcolo del rilassamento
continuo arrotondato al numero intero inferiore. Questa euristica migliore di tutti gli algoritmi greedy. Un'euristica molto citata in letteratura quella dovuta a Balas e Martin [2]. L'idea principale si basa sul fatto che in ogni soluzione ammissibile di base del rilassamento continuo ci sono variabili originali
x1 , ..., xn
1 xj
la
soluzione intera. Quindi una buona soluzione pu essere trovata mettendo in base pi variabili di slack possibili. In generale le euristiche basate sul rilassamento continuo, pur essendo estremamente veloci, non permettono di ottenere soluzioni di buona qualit quanto quelle ottenute dalle tecniche metaeuristiche precedentemente descritte. Solitamente un
euristica di base come quelle presentate in questo paragrafo determina un set di soluzioni ammissibili di buona qualit da cui partire per esplorare lo spazio adiacente attraverso strategie di ricerca locale avanzata.
2.4
ILOG CPLEX
La versione 10.0 del software (commercializzata nel 2005) in grado di risolvere in tempi ragionevoli istanze generate in qualunque modo del Multidimensional Knap-
sack Problem. ILOG CPLEX si appoggia su un potente framework Branch and Cut
altamente personalizzabile in cui sono implementati ecientemente pi di 50 tipologie di tagli. Sebbene ILOG CPLEX non sia nato per risolvere alcuna specica classe di problemi, rappresenta attualmente la metodologia pi eciente per risolvere in
CAPITOLO 2.
STATO DELL'ARTE
32
modo esatto le istanze del MKP, fornendo soluzioni ottime anche per problemi di medie dimensioni in tempi anche migliori delle pi sosticate euristiche. Per le istanze complesse (n
> 250
m > 5)
ineciente ed preferibile utilizzare un'altro strumento che adotta un'approccio di tipo euristico alla loro risoluzione. Per una trattazione completa del software CPLEX 10.0 si rimanda alla guida [42].
Capitolo
3
1
Il nostro algoritmo
Nel presente capitolo verr descritto l'algoritmo sviluppato per risolvere il Multidi-
mensional Knapsack Problem. Tale algoritmo stato pensato per risolvere in modo
esatto il problema . Nonostante questo, sono state apportate delle semplici varianti per poter utilizzare il software come una vera e propria euristica in grado di fornire delle soluzioni molto buone per istanze particolarmente complesse, non risolvibili all'ottimo in tempi accettabili. L'idea sui cui basa il nostro algoritmo molto semplice e pu essere riassunta nella risoluzione iterativa di problemi di dimensioni sempre maggiori ma pi facili da riformulare. In altre parole, anche se il numero delle variabili presenti nel problema cresce, aumenta anche la facilit con cui queste possono essere ssate al loro valore binario (0 piuttosto che 1).
3.1
Prima di descrivere in modo dettagliato il funzionamento dell'algoritmo doveroso denire il concetto di Core del Multidimensional Knapsack Problem poich una sua variante costituir una parte saliente di tutto il meccanismo di risoluzione del problema. Il concetto di Core stato presentato inizialmente nel contesto dello 0/1
Knapsack Problem a singolo bene da Balas e Zemel [1] e ampliato da Pisinger [32]. L'obiettivo principale quello di ridurre il problema originale considerando solo
1 Un algoritmo si denisce esatto se in grado di trovare la soluzione ottima al problema che sta
risolvendo.
33
CAPITOLO 3.
IL NOSTRO ALGORITMO
34
un nucleo di oerte per le quali sia dicile valutare la loro presenza all'interno di una soluzione ottima, mentre tutte le altre oerte non presenti nel Core sono state opportunamente ssate a 1 o a 0. La costruzione del Core dipende dalla scelta di una funzione di valutazione dell'ecacia delle oerte che permette di decidere se una data variabile possa essere ssata a 1, a 0 o in alternativa entrar a far parte delle oerte non valorizzate (ossia facenti parte del Core). Il Core rappresenta di
conseguenza un vero e proprio mini-problema che pu essere risolto molto facilmente grazie alla sua dimensione notevolmente ridotta rispetto al problema di partenza. Puchinger et al. [33] hanno esteso il concetto di Knapsack Core al caso multidimensionale valutando i risultati ottenuti utilizzando dierenti funzioni per determinare l'ecacia delle oerte, tra cui quelle di Senju e Toyoda (2.10) , Kellerer at al. (2.11) , Freville e Plateau (2.12). Hanno inoltre proposto una metodologia basata su dierenti metaeuristiche per modicare la dimensione del Core, aumentando la essibilit del meccanismo che altrimenti non avrebbe permesso ad alcuna variabile esterna al Core di assumere un valore diverso da quello a cui stata ssata. Per una maggiore trattazione sulle tecniche utilizzate da Puchinger et al. e i relativi risultati su istanze benchmark si rimanda a [33]. Il nostro algoritmo riprende l'idea del Core dierenziandosi tuttavia dagli autori precedenti per diversi aspetti. Senza perdere di generalit deniamo ecacia,
la funzione di
ej
xj
assume valore 1 e
3 sottoinsiemi:
N1
N0
2 Per garantire maggiore essibilit nell'utilizzo delle notazioni seguenti si scelto di inserire
all'interno di
gli indici
j = 1, ..., n.
gli items ) del problema . Ogni volta che si fa riferimento ad un'oerta sottointende un'oerta la cui variabile
settata a 1 ( o a 0 ) si
xj
assume valore 1 ( o 0 ).
CAPITOLO 3.
IL NOSTRO ALGORITMO
35
quelle contenute in
Ncore
notare in precedenza, al Core associato un Multidimensional Knapsack Problem di ridotte dimensioni, con la seguente formulazione:
max
jNcore
pj xj
wij xj ci
jNcore jN1
wij i = 1, ..., m
(3.2)
xj {0, 1} j Ncore
Sia ora noto un algoritmo in grado di risolvere il problema denito in (3.2). Il valore della funzione obiettivo (z ) del problema di partenza ottenuto semplicemente sommando i prezzi delle oerte contenute in a 1 dopo la risoluzione del problema core:
N1
Ncore
settate
z=
jN1
pj +
jNcore
pj x j
(3.3)
Supponiamo che nella soluzione ottima del problema ci sia un'oerta settata a 0 ma che appartiene a
Risulta piut-
tosto evidente che il valore della funzione obiettivo cos come calcolato in (3.3) non sar mai uguale all'ottimo. E' necessario di conseguenza pensare ad un meccanismo che permetta di modicare il valore delle variabili associate alle oerte contenute nel Core. Infatti la funzione di ecacia rappresenta solamente una stima della probabilit che una variabile possa essere settata ad un certo valore ma, per quanto buona possa essere, non vi alcuna garanzia che tale valore sia proprio quello assunto dalla variabile nella soluzione ottima. Si prenda l'oerta appartenente a nel Core e la si identichi con
N1
o a
N0
. j
0 (j) = |emin ej |. Sia j1 tale che 0 (j0 ) = min {0 (j) | j N0 }. Pi il valore dell'ecacia ej di un'oerta j
N1
si discosta da
emax
maggiore la probabilit che tale oerta sia eettivamente settata a 1 anche nella
CAPITOLO 3.
IL NOSTRO ALGORITMO
36
ej
emax
xj
viene settata a 1 con probabilit alquanto bassa a tal punto che, scegliendo un
emax , j
e
passarebbe dall'insieme
N1
all'insieme
Considerazioni analoghe possono essere applicate anche alle oerte contenute Di conseguenza le funzioni
Ncore . in N0 .
un'oerta, rispettivamente appartente inizialmente a entrare a far parte del Core. Per denizione,
N1
e a
N0 ,
probabilit di entrare nel Core. Tra le due, viene scelta ovviamente l'oerta con il valore di
, la partizione j = j1 ): j
delle oerte
Ncore
rispetto al problema (3.2). Il valore della funzione obiettivo del problema di partenza sar data da:
z =
jN1
Se
pj +
jNcore
pj x j j
(3.5)
z > z
doveva
essere esclusa dal Core risulta errata in quanto inserendo tale oerta all'interno del Core si ottiene una soluzione del problema originale migliore di quella ottenuta con un core ridotto. La dicolt principale resta nel capire quali oerte debbano essere inserite nel Core. Iterare il procedimento che porta di volta in volta a scegliere un'oerta da
includere nel Core non una soluzione fattibile in quanto prima o poi il Core avrebbe una dimensione tale da rendere il problema ad esso associato troppo dicile da risolvere. Il nostro algoritmo utilizza un approccio leggermente diverso che evita la creazione della partizione riportata in (3.4). Supponiamo che inserire
= j1 N 1 . j
Anzich
in
Ncore ,
si setta il valore di
x j
CAPITOLO 3.
IL NOSTRO ALGORITMO
37
Ncore .
= Ncore ),
N1 = N1
della funzione obiettivo del problema originale come descritto in (3.5). A seconda di tale valore, ci si imbatte in uno dei seguenti casi:
1.
z < z:
con
ssando il valore di
x = 1 perch la partizione delle variabili coinciderebbe con (3.1) e il valore j risultante sarebbe appunto pari a z .
2.
z z:
ssando il valore di
x j
blema originale aumenta o al pi rimane uguale. priori se, nella soluzione ottima,
x j
N1
N0
che non aatto dimostrata. Il risultato tuttavia non da scartare in quanto contribuisce ad aumentare (nel caso
z > z)
=z
), altrimenti si ha che
LB = z .
Iteriamo ora il processo di scelta dell'oerta pi promettente ad entrare nel Core come descritto in precedenza. Identichiamo tale oerta come notare che, prima di procedere con questo passaggio, senza tuttavia risolvere alcun problema associato.
j2 .
j1
j1 = j2 .
Supponiamo che
j 2 N0
e che il valore di
xj2
CAPITOLO 3.
IL NOSTRO ALGORITMO
38
N1 N0
= N1 {j2 } = N0 \ {j1 , j2 }
(3.7)
N1
N0
deniti in (3.6).
L'oerta
j1
propria dimensione rispetto al Core di partenza. Come nel caso precedente, l'oerta
j2
non entra a far parte subito del Core ma viene cambiato semplicemente il valore
della variabile
xj2
max
jNcore
pj xj
wij xj ci
jNcore jN1
wij i = 1, ..., m
(3.8)
xj {0, 1}
Si calcola il valore della funzione obiettivo del problema originale nell'ormai solito modo:
z =
jN1
con le seguenti considerazioni:
pj +
jNcore
pj x j
(3.9)
1.
z < LB
: ssando il valore di
xj2
problema originale diminuisce. Non necessario valutare come si comporta il problema con
xj2 = 0
N1 N0
= N1 = N0 \ {j1 }
(3.10)
N1
N0
LB
in quanto
CAPITOLO 3.
IL NOSTRO ALGORITMO
39
xj1 = 1, la funzione obiettivo del problema originale assume il valore z mentre se xj1 = 0 assume il valore z , il massimo dei quali coincide con il lower bound attuale. z LB
: ssando il valore di
2.
xj2
problema originale aumenta. Anche in questo caso possiamo solo constatare che il lower bound del problema aumenta.
LB
settate a 0, con
N1
N0
deniti in (3.7).
Si noti come il numero di oerte libere (ossia non settate) sia maggiore di un'unit della dimensione del problema Core in quanto
j2
semplica la risoluzione dello stesso e che non contemplato in un approccio simile a quello di (3.4). Risulta ora intuitivo come l'algoritmo prosegua andando di volta in volta a selezionare un'oerta da togliere da
N0
o da
N1
sulla nuova partizione delle oerte ottenuta. Ad ogni iterazione sar suciente inserire nel Core l'oerta il cui valore stato cambiato nell'iterazione precedente e cambiare il valore dell'oerta pi promettente ad entrare nel Core (spostandola da
N0
N1
N0
o da
N1
giungersi al core che di conseguenza cresce rendendo il problema di dicile soluzione. Questo vero sino ad un certo punto. Fermo e restando che l'algoritmo atto a risolvere il problema core non stato ancora descritto, una semplicazione nella risoluzione stata indirettamente apportata nel momento in cui un'oerta viene ssata al valore opposto a quello che la funzione di ecacia la porterebbe ad avere. E' infatti vero che, anche se le oerte contenute in
N0
e in
N1
N1
le capacit dei vincoli del problema diminuiscono di un valore pari al costo di tali oerte nel vincolo). Qualora si forzasse un'oerta a spostarsi da o viceversa, il problema core diventa pi facile da risolvere.
N0
N1
Per valorizzare
l'importanza di questa aermazione prendiamo in considerazione il problema core ottenuto dopo un numero
CAPITOLO 3.
IL NOSTRO ALGORITMO
40
stesso. Sia e
LB k
k k N 1 , N0
k Ncore
k LBcore
il lower
k LBcore = LB k
k jN1
pj
(3.11)
L'algoritmo in grado di risolvere il problema core non ha come obiettivo quello di fornire la soluzione ottima (come allocazione di oerte) del suddetto problema ma esclusivamente quello di dire se la funzione obiettivo del problema core all'ottimo abbia un valore maggiore di va, questo valore (che indichiamo con
k LBcore .
Se la risposta aermati-
migliorare il lower bound del problema di partenza che sar logicamente uguale a:
LB k = z k + core
k jN1
pj
(3.12)
Di fatto la risoluzione del problema core non ne a se stessa ma al problema originale. Calcolare sempre e comunque l'allocazione ottima delle oerte per il problema core e solo in seguito vericare che tali oerte, unite a quelle presenti in
k N1
LB k
un'oper-
contenuta in
k N1
k LBcore .
spazio di ricerca della soluzione ottima del problema core venga tagliato in quanto non in grado di fornire un valore maggiore di
k LBcore
riducendo pertan-
to il tempo di risoluzione del problema stesso. Questo approccio dipendente dal lower bound di partenza verr sicuramente compreso meglio quando verr
Ph
LBh
denizione classica. In questo contesto si intende infatti un valore al di sotto del quale l'ottimo di sia superiore a
Ph
non dovrebbe mai stare ma senza alcuna garanzia che questo accada realmente. Nel caso l'ottimo
LBh ,
necessit di trovarlo, che l'ottimo sia invece inferiore a upper bound. Alla quantit sia un lower bound di
LBh ,
associata al problema
LBh , quest'ultimo diverrebbe di fatto un P h , si dato il nome improprio di lower originale P migliori, necessario che LBh
P h.
CAPITOLO 3.
IL NOSTRO ALGORITMO
41
L'approccio sin qui descritto molto utile per calcolare un lower bound sempre migliore che, terminato l'algoritmo, coincide con l'ottimo del problema originale. Risulta evidente che la costruzione del core non casuale e che pertanto, all'ottimo, la maggior parte delle oerte inizialmente inserite in 1 e la maggior parte di quelle collocate in
N1 abbia valore
N0
gi il lower bound calcolato alla prima iterazione (quando cio il core non stato ancora espanso) risulta di qualit molto buona e, a seconda dell'istanza da risolvere, persino coincidente con l'ottimo. Supponiamo che esista un
N1 = , N0 = e Ncore = N . In particolare sia elim il valore tale per cui se 1 (j) > elim e j N1 allora nella soluzione ottima del problema di partenza si ha (con certezza) che xj = 1, mentre se 0 (j) > elim e j N0 allora si ha che xj = 0. Sia k l'iterazione per cui la variabile xh il cui valore deve essere k permutato abbia un valore di ecienza tale per cui 1 (h) > elim se h N1 k o 0 (h) > elim se h N0 . E' inutile proseguire nella permutazione del suo valore in quanto il valore di xh all'ottimo gi noto alla luce del criterio sopra k k enunciato ( sar 0 o 1 a seconda che h N0 o che h N1 ). Allora si pu facilk mente dimostrare come LB coincida con l'ottimo del problema di partenza. k Infatti LB il miglior valore della funzione obiettivo del problema originale k supponendo che tutte le oerte contenute in N1 siano settate a 1 e tutte quelle k contenute in N0 siano settate a 0. Indichiamo con (j) il valore di 1 (j) se k k j N1 o di 0 (j) se j N0 . Considerando che le oerte vengono di volta in k k volta tolte da N1 e da N0 in ordine crescente rispetto a , se (h) > elim k k allora vero anche che (j) > elim , j N1 N0 . Quindi all'ottimo xj = 1 k k k se j N1 e xj = 0 se j N0 . Ne consegue che LB = z , valore ottimo del
problema originale.
3.2
Nel paragrafo 3.1 si introdotto il meccanismo che sta alla base del funzionamento del nostro algoritmo senza minimamente entrare in dettaglio nei suoi aspetti principali. In questo paragrafo verr ampiamente descritto tutto ci che in precedenza stato introdotto in modo molto generale, vale a dire la funzione di valutazione dell'ecacia
CAPITOLO 3.
IL NOSTRO ALGORITMO
42
L'algoritmo
iterativo che ne deriva verr denominato con la sigla EC (acronimo che sta per Espansione del Core).
e rilassa-
mento surrogato per ssare alcune variabili a zero e generare dei tagli logici in grado di ridurre lo spazio di ricerca della soluzione ottima a qualunque livello dell'albero in un algoritmo esatto di tipo branch and bound. Oliva et al [27] vanno oltre generando un taglio logico da loro denominato Reduced
4 Il Constraint Pairing una tecnica che permette di generare nuovi vincoli a partire da due o
pi vincoli agendo opportunamente sui membri delle disuguaglianze. seguenti vincoli di un problema Per esempio, partendo dai
P
n
cj xj
j=1 n
<
(3.13)
sj xj
j=1
>
(3.14)
(sj cj ) xj
j=1
che risulta essere ancora valida per
>
BA
P.
CAPITOLO 3.
IL NOSTRO ALGORITMO
43
max
j=1 n
pj xj
wij xj ci i = 1, ..., m
j=1
(3.15)
xj {0, 1} j = 1, ..., n
e
Pl
variabili:
max
j=1
pj xj
wij xj ci i = 1, ..., m
j=1
(3.16)
0 xj 1 j = 1, ..., n
Siano che
le variabili slack di
Pl
e siano
(b, u)
(x, s).
E' noto
Pl
max U B +
jN
bj x j
jN +
bj (1 xj ) +
i=0
u i si
W x + Ss = c
(3.17)
0 xj 1 j = 1, ..., n si 0 i = 1, ..., m
con
(x, s), U B
l'upper bound di
ottenuto
risolvendo
Pl
e:
CAPITOLO 3.
IL NOSTRO ALGORITMO
44
N = {j N | xj N + = {j N | xj
una variabile non in base al suo lower bound} una variabile non in base al suo upper bound}
non in base al suo upper bound, se assume valore 1 e ha un coeciente di costo ridotto positivo;
non in base al suo lower bound, se assume valore 0 e ha un coeciente di costo ridotto negativo;
in base, se assume valore frazionario compreso tra 0 e 1 ha un coeciente di costo ridotto nullo.
lem, i coecienti di costo ridotto positivi corrispondono alle oerte contenute interamente nella soluzione continua, i coecienti nulli corrispondono alle oerte contenute parzialmente nella soluzione continua mentre i coecienti negativi corrispondono alle oerte non contenute nella soluzione continua. La relazione (3.17) ancora valida se vengono aggiunti i vincoli di interezza:
xj {0, 1} , j = 1, ..., n.
LB .
UB +
jN
equivalente a
bj x j
jN +
bj (1 xj ) +
i=0
ui si LB
(3.18)
jN
bj x j +
jN +
bj (1 xj )
i=0
ui si U B LB
(3.19)
CAPITOLO 3.
IL NOSTRO ALGORITMO
45
se
j N
allora
bj < 0
massimizzazione, quindi
u0
essendo
s0
u 0,
si ha che
m i=0
ui si 0,
|bj | xj +
jN jN +
bj (1 xj ) U B LB
(3.20)
La disuguaglianza (3.20) una semplice riformulazione del risultato ottenuto da Oliva et al. (3.19) ma che assume un ruolo fondamentale in molteplici aspetti del nostro algoritmo. Tale disuguaglianza a tutti gli eetti un taglio logico in quanto, non essendo violato dalla soluzione ottima del rilassato continuo
Pl ,
miglioramento dell'upper bound se utilizzato in un algoritmo di Cutting Planes. Pu tuttavia fornire interessanti informazioni sul comportamento relativo delle variabili per quanto riguarda i valori assunti all'ottimo intero nonch permettere di ssare direttamente alcune variabili a 0 piuttosto che a 1 riducendo le dimensioni del problema. Per comodit si far riferimento alla disuguaglianza (3.20) nel corso della
trattazione con la sigla RCC (acronimo che sta per Reduced Cost Constraint ). Ora che si hanno a disposizione gli strumenti matematici necessari, possibile continuare nella presentazione di quello che sar il metodo di ordinamento delle variabili che verr utilizzato nel nostro algoritmo. Sia il suo rilassamento continuo e di
Pl
Pl .
Le variabili di
del proprio coeciente di costo ridotto in modo che, senza perdere di generalit, sia:
(3.21)
Questo permetter una prima discriminazione delle oerte: quelle che vengono inserite inizialmente nel Core e quelle che invece ne sono escluse, indipendentemente dal fatto che queste ultime vengano poi ssate a 0 o a 1.
CAPITOLO 3.
IL NOSTRO ALGORITMO
46
Anzich utilizzare opportuni valori di degli indici delle variabili (3.1), l'insieme sione prestabilita pari a
emax Ncore
emin
DIMcore
DIMcore
oerte generando la
(3.22)
N1
N0
in
N1 = {j Nf ix | bj > 0} N0 = {j Nf ix | bj < 0}
Viene in seguito risolto il problema core denito su timo con il prezzo delle oerte contenute in
(3.23)
Ncore (3.22)
e sommandone l'ot-
N1
problema di partenza e, come gi descritto in precedenza, lo si migliora permutando il valore delle variabili i cui indici sono contenuti in della variabile
N1
N0 .
x j
x j
e, se
con
b = min {|bj | | j Nf ix } j N0 j
(3.24)
N1 j
portato a 1. In entrambi i casi si ottiene un nuovo problema core che deve essere risolto. Il procedimento di espansione del Core non si discosta dal meccanismo
generale illustrato nel paragrafo (3.1). Si tenga presente che attribuire ai costi ridotti il metro di valutazione dell'ecacia di una variabile del tutto lecito alla luce del RCC. Tenendo presente che questo vincolo non pu essere violato da
modulo di una variabile e pi alta la propabilit che questa variabile venga ssata a 0, se il suo costo ridotto fortemente negativo, o a 1, se il suo costo ridotto
CAPITOLO 3.
IL NOSTRO ALGORITMO
47
fortemente positivo.
Nf ix
N.
ecacia delle variabili garantisce in modo certo che una data oerta in
Nf ix
assuma
nella soluzione ottima lo stesso valore a cui stata ssata. Nessuna funzione di tipo greedy proposta da Puchinger et al. [34] possiede questa caratteristica. Al contrario, il valore del coeciente di costo ridotto, unitamente al fatto che il RCC non deve essere violato e al modo con cui viene selezionata la successiva oerta da inserire nel Core, fornisce in modo sicuro un criterio di terminazione di espansione del Core. Prendiamo come esempio un semplice problema MKP caratterizzato dal seguente
RCC :
39.31(1 x12 ) + 22.44(1 x13 ) + 5.11 + 10.62x14 + 10.65x5 +20.47x4 + 24.36x1 + 24.41x15 + 35.73x10 + 40.89xx8 + 43.21x7 34.62
Non stata riportata la formulazione del problema perch ritenuta superua ai nostri ni. Quello che interessante evidenziare sono le importanti informazioni fornite dal
x7 , x8
x10
vengono poste
x12
viene posta a 1.
34.62 mentre l'unica variabile settata a 1 ha un coeciente di costo ridotto positivo maggiore di 34.62. Risulta ora chiaro che se la variabile da permutare x10 il meccanismo di espansione del Core termina e il lower bound trovato a quella iterazione coincide con l'ottimo del problema originale. Infatti
x10
modo con cui queste oerte vengono selezionate, facile intuire che tutte le variabili associate alle oerte contenute in
Nf ix
CAPITOLO 3.
IL NOSTRO ALGORITMO
48
34.62
non venga violato. Il risultato importante e permette di comprendere il perch il RCC non venga utilizzato subito per settare alcune variabili a 0 e a 1 e ridurre di conseguenza la dimensione del problema, proprio come proposto da Oliva et al. [27]. Come sap-
piamo, la formulazione del RCC non univoca ma dipende dal valore del lower bound trovato per il problema: maggiore il valore di
LB ,
il vincolo dei costi ridotti in quanto il secondo membro della disuguaglianza diventa pi piccolo. Anzich utilizzare un approccio euristico per determinare un buon lower bound e applicare il RCC per ssare opportunatamente alcune variabili, si deciso di procedere in un modo conforme all'algoritmo e rinforzare nel tempo tale vincolo ogni qual volta ci si imbatte in valori del lower bound migliori. Infatti, una volta creato il Core, si risolve un problema di bound per il problema originale (3.3).
DIMcore
una parte il lower bound tende a migliorare no al raggiungimento del valore ottimo (rinforzando di fatto il RCC ), dall'altro la variabile
xh
, con
h Nf ix ,
il cui valore
deve essere cambiato cresce nel suo coeciente di costo ridotto (in modulo). Alla
k esima iterazione tale per cui la variabile xh da permutare abbia un costo ridotto |bh | > U B LB k , l'algoritmo si arresta avendo trovato l'ottimo z = LB k . Il criterio di terminazione perde di ecacia solo se |bj | U B z j N con z valore ottimo del problema intero P . In altre parole, anche conoscendo il miglior
lower bound possibile (coincidente con l'ottimo) il RCC non permette di ssare nessuna variabile a 0 o a 1. In questa situazione tutte le oerte contenute in
Nf ix
devono essere permutate e l'algoritmo di espansione del Core termina solo quando
Nf ix = .
3.3
In questa sezione ci occuperemo di descrivere in dettaglio l'algoritmo in grado di risolvere il problema Core. E' bene ricordare che il ne di questo algoritmo quello di vericare l'esistenza di un valore della funzione obiettivo migliore di
LBcore
fornito
in ingresso. Se tale valore esiste, viene fornito come output insieme all'allocazione delle oerte ad esso associato, quest'ultima necessaria per aggiornare la soluzione temporaneamente ottima del problema di partenza. Di fatto, l'algoritmo non pu
CAPITOLO 3.
IL NOSTRO ALGORITMO
49
LBcore
poniamo che tale valore sia noto. Risulta ormai evidente che la bont dell'algoritmo in termini di ecienza computazionale dipende molto dal valore di
LBcore .
In realt sono stati deniti due approcci risolutivi per il problema Core:
1. un approccio basato sull'analisi di alberi di ricerca attraverso la generazione di disuaguaglianze valide (che indichiamo con AAR = Analisi Alberi Ricerca ), utilizzato per risolvere problemi di ridotte dimensioni (con numero di variabili minore o uguale a
V ARmax ).
2. un approccio basato sulla riduzione ricorsiva di problemi di grandi dimensioni (che indichiamo con RR = Riduzione Ricorsiva ) che termina con una risoluzione di tipo AAR quando il problema ridotto ha un numero di variabili al pi uguale a
V ARmax .
E' utile premettere che entrambi gli algoritmi risolvono problemi di tipo MKP a patto che sia fornito un lower bound iniziale (o presunto tale) al problema. Di
fatto possibile utilizzare AAR o RR per risolvere direttamente il problema di partenza il cui lower bound pu essere ottenuto da una qualsiasi euristica. Sebbene questo sia possibile, AAR e RR sono pensati per risolvere in modo eciente problemi di tipo MKP sotto particolari condizioni e, come verr fatto presente pi avanti quando verranno illustrati i risultati computazionali, conviene utilizzarli entrambi nel contesto dell'algoritmo di espansione del Core che, tra l'altro, non necessita di alcuna particolare funzione euristica per poter funzionare. Maggiori dettagli sull'utilizzo
CAPITOLO 3.
IL NOSTRO ALGORITMO
50
3.3.1.1 Cardinalit
Per cardinalit di un insieme di oerte si intende il numero di oerte contenute nell'insieme stesso. A dierenza dei classici algoritmi branch and cut che analizzano un solo albero delle soluzioni, il nostro algoritmo scompone il problema in sottoproblemi ognuno caratterizzato da una propria cardinalit, analizzando le soluzioni che contengono un numero di oerte pari alla cardinalit considerata e rendendo i tagli pi ecaci. E' necessario determinare la cardinalit minima e la cardinalit massima del problema, che rispettivamente indichiamo con che, denito sia:
CARDmin
e con
CARDmax
in modo
CARDmin k CARDmax
Sono stati implementati due distinti metodi per calcolare il valore di
(3.25)
CARDmin
CARDmax :
le variabili del problema, il secondo invece consiste nella risoluzione di un problema lineare di supporto. rispettivi pregi e i difetti. Verranno presentati entrambi gli approcci, unitamente ai
1. La cardinalit minima viene calcolata utilizzando il valore del lower bound del problema. L'idea quella di creare un vettore
Vp
le oerte ordinate per prezzo in modo decrescente no a quando la somma complessiva dei prezzi delle oerte contenute nel vettore bound. Sia
Vp
il vettore dei prezzi delle oerte tale per cui, senza perdere di
generalit:
(3.26)
Vp
pj LB
jVp
(3.27)
CARDmin
CAPITOLO 3.
IL NOSTRO ALGORITMO
51
CARDmin 1 oerte.
ritmo, anch (3.27) rimanga valido possibile che si debbano aggiungere ulteriori oerte in
Vp
to riguarda la cardinalit massima, questa dipende dal numero complessivo dei beni messi a disposizione (le capacit dei vincoli del problema). Anche in questo caso viene generato un vettore in cui le oerte sono inserite in ordine crescente rispetto alla somma dei loro pesi nei vari vincoli. In particolare, sia
benij =
m i=1
wij
con
j = 1, ..., n
(3.28)
benitot =
m i=1 ci .
Si sommano i valori di
benij
secondo l'ordinamento (
(3.29)
In generale
ogni oerta viene fatta su tutti i beni, richiesti in una certa quantit. La quantit totale dei beni (senza distinzione) richiesti da un'oerta e salvata in viene calcolata
benij .
Si ha che
CARDmax = h 1
oerte con il valore totale di beni minore, la somma complessiva dei beni
ottenuta dalla loro somma eccede il numero totale di beni messi a disposizione (3.29) e, pertanto, ogni altra combinazione di
In
questo caso, non dipendendo dal lower bound, la cardinalit massima salvata in
CARDmax
calcolo. 2. Le cardinalit minima e massima vengono calcolate risolvendo due problemi lineari molto simili fra loro. Sia
m vincoli.
aggiungendo ai vincoli del problema originale il fatto che la funzione obiettivo di quest'ultimo debba essere almeno pari a
LB .
CAPITOLO 3.
IL NOSTRO ALGORITMO
52
Sia
Pmax
il seguente problema:
kmax = max
jN
xj
wij xj ci i = 1, ..., m
jN
(3.30)
pj xj LB
jN
0 xj 1 j N
e sia
Pmin
kmin = min
jN
xj
(3.31)
wij xj ci i = 1, ..., m
jN
pj xj LB
jN
0 xj 1 j N
Entrambi i problemi sono lineari e possono essere risolti in tempi polinomiali da un risolutore come CPLEX. Ne risulta semplicemente che:
CARDmin = CARDmax =
kmin + 1 kmax
(3.32)
Sebbene il primo approccio possa risultare pi eciente rispetto al secondo, che prevede la formulazione e la risoluzione di due ulteriori problemi, anche meno ecace in quanto i valori di
CARDmax
CARDmin
informazioni parziali del problema (rispettivamente beni totali e prezzi delle oerte).
Pmin e Pmax xj .
soddisfano la relazione (3.25) anche aggiungendo i vincoli di interezza sulle variabili Di fatto i valori di
CARDmin
CARDmax
sono molto pi stringenti di quelli forniti dal primo approccio, evitando quindi di analizzare un numero considerevole di alberi di ricerca.
CAPITOLO 3.
IL NOSTRO ALGORITMO
53
n = 5
k = 3
la cardinalit considerata.
Le possibili
1, 2, 3 1, 2, 4 1, 2, 5 1, 3, 4 1, 3, 5 1, 4, 5 2, 3, 4 2, 3, 5 2, 4, 5 3, 4, 5
Il metodo di enumerazione si basa sull'incremento dell'ultima oerta dell'allocazione sino al raggiungimento della cardinalit dell'ultima oerta inserita no a sizione
k.
n.
k)
uguale a
cardinalit non pu essere raggiunta perch le oerte sono esaurite (si inserisce l'oer-
k ),
oerta inserita, la prima oerta tale per cui, inserendo nelle posizioni successive le oerte a lei consecutive, possibile il raggiungimento della cardinalit
k.
Questo tipo
di analisi pu essere visualizzata attraverso un albero di ricerca binario. Riportiamo un esempio graco di albero binario con
n=4
k=3
1, 2, 3 1, 2, 4 1, 3, 4 2, 3, 4
CAPITOLO 3.
IL NOSTRO ALGORITMO
54
L'aver ridotto il numero di oerte dettato esclusivamente da ragioni estetiche, per non avere un albero binario troppo grande da rappresentare: Ogni livello dell'albero rappresenta un'oerta che viene inserita o esclusa nell'allocazione a seconda che si percorra il ramo di sinistra o quello di destra. L'albero riportato in gura non completo in quanto non tutti i sottoalberi vengono analizzati: per esempio, il nodo A non viene espanso ulteriormente in quanto gi stata raggiunta un'allocazione di 3 oerte, mentre il nodo B non ha il sottoalbero destro in quanto non includere l'oerta numero 3, unitamente al fatto che gi stata esclusa la numero 2, non consente di ottenere un allocazione di cardinalit 3 (rimanendo a disposizione solo l'oerta 1, gi inclusa, e l'oerta 4). In generale, se
sono le oerte e
elementi di classe k :
Cn,k
n n! = = k! (n k)! k
(3.33)
k:
l'introduzione dei tagli serve appunto per ridurre lo spazio di ricerca delle
soluzioni semplicemente rendendo superua la visita di alcuni nodi dell'albero. Prima di discutere in dettaglio i tipi di tagli utilizzati, bene capire come l'algoritmo
CAPITOLO 3.
IL NOSTRO ALGORITMO
55
alla
quale si applicano i tagli secondo un determinato ordine e, selezionando il taglio pi profondo, si risale l'albero tramite back-tracking. A questo punto si costruisce nuovamente un'allocazione full secondo il criterio di enumerazione incrementale delle oerte descritto in precedenza. Ogni volta che viene generata un'allocazione full si verica la sua ammissibilit e se risulta essere migliore della soluzione ottima attuale quest'ultima viene aggiornata. Il procedimento termina quando l'albero binario
stato completamente navigato. Il nostro algoritmo utilizza un approccio dierente attraverso il quale si ottiene un'allocazione full delle oerte solo nel caso in cui tale allocazione sia ammissibile e dia un valore della funzione obiettivo migliore del lower bound noto. Nella maggior parte dei casi il nostro algoritmo tratta allocazioni parziali in cui sono inserite oerte in numero minore rispetto alla cardinalit analizzata. A questo punto seleziona secondo opportuni criteri la prossima oerta da inserire e successivamente vengono applicati i tagli in un determinato ordine. Il primo di essi che viene applicato con successo determina la nuova allocazione parziale che dipender proprio dal tipo di taglio utilizzato. Il procedimento viene iterato no al raggiungimento di un'allocazione full (ammissibile) che in ogni caso avr un valore migliore o al pi uguale al lower bound attuale (altrimenti l'allocazione full non verrebbe mai generata). Inne si verica se dall'allocazione full trovata possa essere derivata una nuova allocazione parziale da cui far ripartire il procedimento, altrimenti l'algoritmo termina. Una descrizione rigorosa dell'algoritmo fornita nei paragra 3.3.1.4 e 3.3.1.5.
taglio sui prezzi : consente di eliminare allocazioni parziali che danno origine
esclusivamente ad allocazioni full il cui valore minore del lower bound;
taglio sui beni : verica che non vengano assegnati pi beni di quelli complessivamente a disposizione;
taglio sui coecienti : utilizza il Reduced Cost Constraint per eliminare alcune
allocazioni;
5 Un'allocazione di
oerte si dice
CAPITOLO 3.
IL NOSTRO ALGORITMO
56
L'enumerazione delle soluzioni avviene considerando le oerte ordinate per prezzi in modo decrescente.
per prezzi. Si costruisca un vettore bidimensionale alla somma dei prezzi delle prime
a.
a+b
Sp (a, b) =
i=a+1
Sia
(3.34)
ztemp
j1
p pj1 j
> j1 j
). Il
(3.35)
combinazioni di
il prezzo massimo tra tutti quelli delle allocazioni full che posso ottenere partendo dall'allocazione parziale considerata e aggiungendo piccolo di Se tale prezzo rimane pi
LB
inutile inserire
del sottoalbero equivalente non condurr al miglioramento (o al raggiungimento) del lower bound. Una situazione particolare si ha quando
card = ktemp + 1,
vale a dire
quando deve essere inserita solamente un'oerta per ottenere un'allocazione full. In questo caso il taglio applicabile se vale semplicemente che:
ztemp + p < LB j
(3.36)
CAPITOLO 3.
IL NOSTRO ALGORITMO
57
direttamente legato al fatto che le oerte vengono inserite nell'allocazione ordinate per prezzi decrescenti. Riportiamo dei semplici esempi per capire la profondit del taglio sui prezzi e del modo con cui, applicato con successo, possa determinare la prossima allocazione parziale da valutare nonch la prima oerta da inserire in questa nuova allocazione.
7 in quanto se un'allocazione
[1, 2, 3, 6, , ] non dar mai un'allocazione full con valore maggiore o uguale a LB , sicuramente non lo dar mai neppure un'allocazione del tipo [1, 2, 3, 7, , ] essendo p7 p6 . La prossima allocazione parziale diventa quindi [1, 2, , , , ] con 4 la prossima oerta da inserire. E' importante far notare come l'allocazione parziale da valutare non sia [1, 2, 4, , , ] come invece ci si potrebbe attendere
conoscendo il meccanismo di enumerazione incrementale delle oerte gi presentato in precedenza. Infatti la costruzione dell'allocazione full verte sul fatto che non si possa mai passare per un'allocazione parziale errata. garanzia che In eetti non si ha alcuna
[1, 2, 4, , , ] sia un'allocazione parziale valida, in quanto non detto che l'inserimento dell'oerta 4 venga consentito da uno dei tagli da applicare. Si supponga ora n = 14 e k = 7 e si analizzi la seguente allocazione parziale: [1, 2, 3, 7, 10, , ] con 11 la prossima oerta da aggiungere. Se il taglio sui prezzi ecace la prossima oerta da inserire non sicuramente la 12 per quanto visto
nell'esempio precedente. La prossima allocazione parziale dovrebbe quindi essere In realt l'analisi di que-
non migliora il lower bound, non lo far neppure una qualunque allocazione ottenuta partendo da
[1, 2, 3, 7, 11, , ].
sempio precedente, dato che in questo caso il taglio applicato con successo quando cerco di inserire l'oerta consecutiva all'ultima presente nell'allocazione. Pertanto la prossima allocazione parziale da valutare da aggiungere. Si vada oltre e si consideri lo stesso esempio appena mostrato considerando tuttavia la seguente allocazione parziale:
[1, 2, 3, , , , ]
con
la prima oerta
[1, 2, 3, 8, 10, , ]. 11
la prossima oer-
CAPITOLO 3.
IL NOSTRO ALGORITMO
58
[1, 2, 3, , , , ] con 9 la prima oerta da inserire poich se partendo da [1, 2, 3, 8, 10, , ] non miglioro il lower bound, questo non verr migliorato neppure partendo da [1, 2, 3, 9, 10, , ] (essendo p9 p8 ) e quindi nemmeno da [1, 2, 3, 9, , , ]. Di conseguenza la nuova allocazione parziale da valutare risulta essere [1, 2, , , , , ] con 4 la prossima oerta da includere. Per un ragionamento analogo se l'allocazione [1, 2, 7, 8, 10, , ], con 11 la prossima oerta da inserire, viene tagliata, la nuova allocazione parziale diventa
[1, , , , , , ]
3.
Sia
Come si evince dagli esempi, il taglio risulta tanto pi profondo quanto pi sono
j l'oerta da inserire nell'allocazione, h il numero di oerte sinora inserite e getX (i) una funzione che restituisce l'oerta presente nell'allocazione nella posizione i con i h. Se il taglio viene applicato con successo si esegua il seguente algoritmo:
contigue le oerte nell'allocazione parziale a partire dall'ultima posizione. 1. 2.
3. se 4. se 5. se
dif f erenza = 1
6. torna al punto 2 7.
hnew h, new + 1 j j
Il semplice algoritmo proposto in grado di determinare la migliore allocazione parziale (che anche quella pi piccola) da cui far ripartire AAR. Si noti la condizione nel punto 3: l'allocazione parziale di partenza stata ridotta no al primo elemento; questo signica che AAR non ha trovato (prima) e non trover (poi) nessuna allocazione full ottimale che contenga l'oerta presente nella prima posizione. Al termine di questo semplice algoritmo la nuova allocazione parziale ottenuta prendendo le prime
hnew
hnew + 1)
new . j
CAPITOLO 3.
IL NOSTRO ALGORITMO
59
Il ragionamento che sta alla base del taglio sui beni molto
semplice: non si possono assegnare pi beni di quelli che si hanno a disposizione. Per applicare con ecienza questo taglio necessario precalcolare alcune quantit prima che la navigazione dell'albero delle soluzioni venga avviata. Sia complessiva dei beni associati all'oerta
benij
la somma
wij . Si costruisca un vettore So (a, b) il cui elemento equivale alla delle b oerte con benij pi piccolo, selezionate tra tutte le oerte che hanno prezzo minore di quello di a( vale a dire, ricordando l'ordinamento delle oerte per prezzi decrescenti, a+1, a+2, ..., a+b ). Per evitare inutili calcoli, anche qui si ipotizzi che a + b card con card la j
tale che
m i=1
cardinalit analizzata.
Esempio:
n = 10, a = 3, b = 4. Si devono considerare solo le oerte con prezzo minore di p3 che sono semplicemente 4, 5, 6, 7, 8, 9 e 10. Siano tali oerte incluse in un insieme che per comodit chiamiamo Ntemp . Si ordinano le oerte contenute in Ntemp in modo crescente rispetto al loro valore di benij e si selezionano le prime 4 oerte. La somma dei valori di benij di quelle 4 oerte viene salvato in So (3, 4).
sia il numero complessivo di beni associato alle
Sia
objtemp
ktemp
locazione parziale,
la prossima oerta da aggiungere nell'allocazione e benitot = m i=1 ci il numero di beni a disposizione. Il taglio sui beni ecace se valida la
seguente disuaguaglianza:
(3.37)
Al primo membro si considera l'allocazione full ottenuta partendo da quella parziale analizzata che, tra tutte, richiede il minor numero di beni complessivi. Se questo
valore supera il numero totale di beni a disposizione, inutile proseguire nell'analisi del sottoalbero associato a tale allocazione parziale in quanto non verranno generate mai allocazioni full ammissibili.
n = 10 e k = 6 e si analizzi la seguente allocazione parziale [1, 2, 3, , , ] con 4 la prossima oerta da inserire. Se il taglio sui beni applicato con successo l'allocazione da valutare rimane sempre [1, 2, 3, , , ] ma cercando di includere l'oerta 5 (incrementale rispetto all'ultima come stabilito nel criterio di
Si supponga enumerazione delle oerte). Tuttavia pu essere fatto di meglio, valutando il numero di beni associati all'oerta
beni5 beni4
CAPITOLO 3.
IL NOSTRO ALGORITMO
60
beni6 beni4 si passa all'oerta 7 e via dicendo. La motivazione molto semplice. Partendo dall'allocazione [1, 2, 3, , , ] con 4 l'oerta da inserire, le oerte restanti sono 5, 6, 7, 8, 9 e 10 (stato A). Ne vengono scelte le due con il numero di beni minore (la cui somma salvata in So (4, 2)). Indichiamole con j1 e j2 . Applicato con successo il taglio sui beni, si cerca di inserire l'oerta 5, pertanto le oerte ancora disponibili sono 6, 7, 8, 9 e 10 (stato B).
care ulteriormente il taglio 3.37) . Se Si presentano due casi: 1. Se
j1 = 5 j2 = 5,
quanto per entrambi gli stati ci sono le stesse oerte tranne appunto la numero
5.
stata inserita la
5.
Ma
beni5 beni4 ,
quindi se l'allocazione full ottenuta da A non soddisfa il vincolo sui beni, a maggior ragione tale vincolo verr violato anche dall'allocazione full generata da B. 2. Se
j1 = 5 j2 = 5,
(in quanto gi inserita di suo nell'allocazione). Ne verr selezionata una terza che chiamiamo
j3 .
Sicuramente
benij3 benij1
benij3 benij2
altrimenti in
j3 .
da aggiungere hanno complessivamente un numero di beni maggiori rispetto ad A. Se a questo si aggiunge anche che la
in B sostituisce la
in A e che
beni5 beni4 ,
vincolo sui beni se questo non soddisfatto dall'allocazione full generata da A. Alla luce dell'esempio proposto, sia
Se
il taglio sui beni applicato con successo si determina la nuova allocazione parziale nonch la prossima oerta da aggiungere tramite il seguente algoritmo: 1.
2. se 3. se
+1 j j
vai al passo 5
4. torna al passo 2
CAPITOLO 3.
IL NOSTRO ALGORITMO
61
5. con
new j j
la nuova oerta da aggiungere nell'allocazione parziale alla prossima iter-
new j
azione di AAR.
sere solo ammissibile in relazione ai vincoli del problema, ma deve anche fornire un valore della funzione obiettivo migliore del lower bound. Di conseguenza lecito
utilizzare le informazioni contenute nel RCC (3.20) per tagliare porzioni dell'albero che sicuramente non lo soddisfano. I costi ridotti associati alle variabili costituiscono un input dell'algoritmo proprio come il valore di
LB
e di
UB
Tali coecienti sono computati semplicemente risolvendo il rilassamento continuo del MKP considerato. Per semplicit si assume che:
|bj | U B LB j N
(3.38)
Se cos non fosse alcune variabili possono essere ssate a 0 e a 1 e l'algoritmo AAR verrebbe quindi applicato al problema riformulato non considerando tali variabili. Come vedremo in seguito, AAR verr utilizzato in un contesto in cui la condizione (3.38) sempre vera.
[1, 2, , ] con 3 la prossima oerta da aggiungere. Siano b1 = 30.00, b2 = 10.23 e b3 = 20.31 i coecienti di costo ridotto associati alle tre variabili di interesse e sia 32.12 il termine noto di RCC. L'allocazione successiva diventa [1, 2, , ] con 4 la nuova oerta da inserire poich i coecienti 30.00 e 20.31 (che si ricorda devono essere presi in modulo) sommati violano il vincolo (|30.00 20.31| > 32.12). Si supponga di analizzare l'allocazione [1, 2, , ..., ] e di voler aggiungere l'oerta 5. Siano b1 = 0.00, b2 = 5.23, b3 = 10.12, b4 = 0.00 e b5 = 20.13 i coecienti di costo ridotto rispettivamente delle oerte 1, 2, 3, 4 e 5, e sia 35.34 il termine noto di RCC. Si osservi come il voler aggiungere l'oerta 5 presuppone che nell'eventuale
Si supponga
n = 10
k=4
allocazione full non ci saranno le oerte 3 e 4 in quanto, se ci fossero, comparirebbero in posizioni precedenti a quella occupata dall'oerta 5 a causa del loro prezzo maggiore. Si osservi inoltre che la presenza delle oerte 2 e 5 unitamente all'assenza dell'oerta 3 portano a violare il vincolo. Infatti, le oerte 2 e 5 forniscono un contributo al primo membro di (3.20) pari a
come visto
CAPITOLO 3.
IL NOSTRO ALGORITMO
62
x3 = 0,
il suo contributo
b3 (1 x3 )
di 35.48 che maggiore di 35.34, violando di conseguenza il vincolo. Per applicare questo taglio in modo eciente, sia
giungere nell'allocazione parziale. Le oerte gi valutate, che possono essere quindi presenti in tale allocazione, sono
1, 2, ..., 1. j
Sia
C+
range = (U B LB) j
jC
Il valore di violato.
|bj |
range j
Chiaramente
range1 = U B LB
alcuna variabile (l'oerta 1 non ancora stata allocata) e il bonus corrisponde interamente al termine noto del RCC. Man mano che vengono inserite oerte con costo ridotto negativo il valore di
range
del costo ridotto stesso. Una prima applicazione del taglio viene provata quando ha costo ridotto negativo. Se:
range b < 0 j j
(3.39)
il taglio ecace perch il RCC viene violato. Se l'esito negativo si applica una condizione pi stringente che tiene in considerazione anche le oerte contenute in
C +.
La disuguaglianza diventa:
range b j j
jC +
bj < 0
(3.40)
e se valida il taglio sui costi ridotti diventa ecace. Si potrebbe applicare direttamente il taglio (3.40) ma richiede un calcolo aggiuntivo ( che, di conseguenza, viene valutato per primo. Qualora
jC + bj ) rispetto a (3.39)
range j
jC +
bj < 0
(3.41)
che, se vero, porta ad un taglio ecace delle soluzioni. In tutti i casi in cui il taglio
CAPITOLO 3.
IL NOSTRO ALGORITMO
63
applicato con successo, si mantiene l'allocazione parziale valutata e si incrementa semplicemente di un'unit l'oerta che si vuole aggiungere.
Taglio di ammissibilit
particolare sia
l'insieme delle oerte gi contenute in tale allocazione. Si valutino poi le seguenti disuguaglianze:
(3.42)
non j
+ 1. j
In realt l'algoritmo AAR adotta una strategia dierente, del tutto simile a quella utilizzata nell'applicazione del taglio sui beni. Le disuguaglianze in (3.42) valutano l'ammisibilit attuale dell'allocazione parziale con l'aggiunta dell'oerta
. j
In al-
tre parole sono valide se i costi delle oerte presenti nell'allocazione, compresa
, j
violano uno dei vincoli del problema. Il nuovo approccio orientato alla valutazione dell'ammissibilit futura, cio di quella dell'allocazione full ottenuta partendo dall'allocazione parziale considerata. Chiaramente a partire da un'allocazione parziale possibile ottenere un elevato numero di allocazioni full a seconda di come vengono scelte le rimanenti oerte da aggiungere. Analogamente al ragionamento che sta
dietro il funzionamento dei tagli dei prezzi e dei beni, in questo caso si considera l'allocazione full costruita aggiungendo le oerte con costo minore all'interno del vincolo.
1 i m. Si costruisca un vettore Vi (a, b) il cui elemento corrisponde alla somma dei costi wij delle b oerte con costo wij pi piccolo tra tutte quelle con prezzo minore dell'oerta a (vale a dire, ricordando l'ordinamento decrescente per prezzi delle oerte, a + 1 , a + 2, ..., a + b). Per evitare inutili calcoli temp si ponga a + b card, dove card la cardinalit analizzata. Sia costoi il costo complessivo delle ktemp oerte nore allocate relativamente al vincolo i. Sia la j
Si consideri il vincolo
con
CAPITOLO 3.
IL NOSTRO ALGORITMO
64
vincolo
(3.43)
j
di
card ktemp 1
della capacit del vincolo, non possibile costruire un'allocazione full ammissibile a partire da quella allocazione parziale. Il taglio espresso da (3.43) guarda molto pi avanti rispetto a (3.42) e permette di potare rami nell'albero delle soluzioni senza valutare sottorami e foglie ad essi associati. E' chiaro che le considerazioni fatte in precedenza sul singolo vincolo sono replicate per tutti gli ,
V2 (a, b),
....,
m vincoli. E' suciente costruire diversi vettori del tipo V1 (a, b) Vm (a, b) e vericare che almeno una delle m disuguaglianze sia valida + 1 come prossima j
per poter applicare il taglio. Anche in questo caso, se il taglio ha successo, la nuova allocazione parziale da valutare non cambia mentre si considera oerta da aggiungere.
la
k.
Si identichi con
cont
la po-
sizione in cui inserire la prossima oerta nell'allocazione parziale. Sia Di fatto se l'allocazione costituita da 3 variabili si valuter posizione
cont = 4.
Chiaramente il valore di
cont
k.
h dell'algoritmo di ricerca lavora su un valore qualunque di cont e di j , determinati al passo h 1. Rimaniamo nell'ipotesi in cui si sta eseguendo il generico passo h di AAR. Si
quella con prezzo maggiore. Il generico passo vericano nell'ordine il taglio sui prezzi, sui beni, sui coecienti di costo ridotto e per ultimo quello di ammissibilit. Il primo taglio applicato con successo determi-
7 Si ricordi che la soluzione pu non essere trovata qualora l'ottimo del problema non sia superiore
al lower bound fornito in ingresso.
CAPITOLO 3.
IL NOSTRO ALGORITMO
65
na la nuova allocazione parziale e la prossima oerta da valutare secondo le regole denite quando sono stati descritti i vari tagli. Il valore di
nato in base alla dimensione della nuova allocazione parziale. Qualora nessuno dei tagli risulti essere ecace l'oerta viene aggiunta all'allocazione,
un'unit il suo valore e la prossima oerta che si cercher di aggiungere la prima nell'ordinamento tra tutte le oerte rimaste (vale a dire quella seguente a oerta inserita). Il procedimento viene iterato (passo
, j
l'ultima
h + 1)
cont
1.
e termina quando si incorre in una della seguenti situazioni: stata costruita un'allocazione full valida. Viene salvata la soluzione
cont = k :
ottima temporanea ottenuta settando a 1 le oerte presenti nell'allocazione e inoltre la somma dei prezzi delle oerte presenti diventa il nuovo lower bound (il che implica un raorzamento del taglio sui prezzi e di quello sui costi ridotti per i passaggi successivi). 2.
cont < k ma non ci sono pi oerte da allocare. Nel caso generale signica che, se u l'ultima oerta aggiunta e n quella con prezzo pi piccolo, si ha che u+1, u+2,....,n sono state tutte escluse dall'allocazione in virt dell'ecacia di
qualche taglio. E' importante capire la valenza di questo risultato. Per come strutturato l'algoritmo, non possibile raggiungere un'allocazione parziale se le oerte in essa presenti non soddisfano le condizioni esplicitate nei tagli. Di conseguenza ogni allocazione parziale sempre ammissibile e pertanto lo anche l'allocazione parziale nale (quando le oerte disponibili sono esaurite). Pu succedere che le oerte presenti in tale allocazione abbiano un prezzo tale che, sommati fra loro, eccedono il lower bound attuale, anche se l'allocazione non full. Se questo si verica, l'algoritmo si limita ad aggiornare il lower
bound come nella condizione 1., senza tuttavia salvare la soluzione temporanea. Questo possibile se si pensa che si sta analizzando una cardinalit che non detto che sia quella ottima. Di fatto non da escludere che nell'analisi di una cardinalit
k ci si imbatta in un'allocazione parziale (con k > CARDmin ) che pu coincidere con l'ottimo.
trovata con l'analisi della cardinalit
di cardinalit
Si evita di salvare la
k 8
8 Questo vero se l'analisi delle cardinalit avviene in ordine decrescente. Nel caso contrario la
soluzione ottima gi stata trovata avendo analizzato la cardinalit algoritmo.
prima di
k.
In seguito
verr comunque descritto come scegliere l'ordine di analisi degli alberi di ricerca adottato nel nostro
CAPITOLO 3.
IL NOSTRO ALGORITMO
66
La funzione appena descritta, che permette di allocare opportunatamente tutte le oerte disponibili a partire da un'allocazione parziale iniziale, viene denita per comodit alloca() e costituisce un pilastro portante di tutto l'algoritmo AAR. L'uscita da alloca() non implica la terminazione di AAR. Una volta aggiornato eventualmente il lower bound, necessario continuare nella navigazione dell'albero. Anche qualora avessimo trovato un'allocazione full, non aatto escluso che non ce ne possano essere altre migliori a partire da dierenti allocazioni parziali. Essendo
k.
oerta dell'allocazione parziale sia tale da non poter raggiungere un'allocazione full anche bypassando tutti i tagli implementati. Sia La condizione di terminazione si traduce in:
j1
cont = 1.
n j1 < k 1
In pratica inserita nella prima posizione l'oerta
(3.44)
j1 ,
lutare sono quelle successive nell'ordinamento decrescente per prezzi, vale a dire
j1 + 1, j1 + 2,...,n , in numero pari a n j1 . Se le n j1 oerte disponibili, sommate a j1 gi inserita, non danno un'allocazione di k elementi, inutile continuare a considerare l'allocazione parziale [j1 , , , ....., ]. D'altra parte la prossima allocazione parziale da valutare sarebbe [j1 + 1, , , ...., ] che tuttavia darebbe origine
ad un'allocazione full ancora pi piccola della precedente avendo meno oerte a disposizione. Lo stesso discorso valido per tutte le allocazioni del tipo con
[f, , , ...., ]
j1 f n .
Arrivati all'allocazione
[n, , , ..., ],
non pi espandibile, lo
sia trovata un'allocazione full valida, questa andata a sostituire la soluzione ottima temporanea. Se la condizione (3.44) non soddisfatta, l'albero delle soluzioni di cardinalit
ha ancora dei rami che non sono stati visitati. L'idea quella di prendere
l'ultima allocazione calcolata (full o parziale, in uscita da alloca() ) e di generarne una nuova da inviare alla funzione alloca(). Verr generata una nuova allocazione nale, ottenuta esplorando altri rami dell'albero delle soluzioni, dalla quale generare ancora un'allocazione parziale da far computare da alloca(). Il procedimento termina solo quando la condizione (3.44) soddisfatta. Il meccanismo in grado di generare una nuova allocazione parziale a partire dal-
CAPITOLO 3.
IL NOSTRO ALGORITMO
67
l'allocazione in uscita da alloca() molto semplice e si basa sulla possibilit di creare l'allocazione parziale pi grande possibile, dalla quale ottenere almeno un'allocazione full anche non ammissibile. Il fatto che l'allocazione full possa non essere ammissibile implica che l'unica condizione per la sua determinazione che ci sia un numero suciente di oerte non ancora valutate da inserire nell'allocazione parziale per raggiungere la cardinalit
k,
oerte causa tagli applicati con esito positivo. Sia ferta allocata,
cont
getX(i) una funzione che restituisce l'oerta inserita nella posizione i dell'allocazione e sia n il numero complessivo di oerte. Si ricordi inoltre che le oerte
vengono aggiunte (o sostituite) secondo un criterio incrementale rispetto all'oerta allocata nella posizione precedente. La nuova allocazione viene generata applicando il seguente algoritmo:
1.
2. se 3.
4. torna al passo 2 5.
Si memorizza in
e si
passa a
+ 1. j
Se il numero
n ( + 1)) j
almeno pari a
dif f
l'allocazione ottenuta
soddisfatta, si elimina l'ultima oerta allocata e si itera il procedimento. Di fatto il numero delle oerte da allocare incrementa di uno mentre la posizione dell'ultima oerta allocata diminuisce di uno. Vengono proposti alcuni esempi per mostrare con maggior chiarezza l'algoritmo descritto. Sia
n = 10
k =5
e sia
[1, 2, 5, 7, 8]
[1, 2, 5, 7, ] con 9 la prossima oerta da inserire. Se l'allocazione invece [1, 2, 5, 7, ] la nuova allocazione parziale diventa [1, 2, 5, , ] con 8 la prossima oerta da aggiungere. Inne se l'allocazione [1, 2, 7, 8, 9] la nuova allocazione [1, , , , ]
con 3 come nuova oerta da inserire.
CAPITOLO 3.
IL NOSTRO ALGORITMO
68
CARDmin
e quella massima
CARDmax .
Se al problema si fornisce un
lower bound pi grande del suo ottimo, nessuna soluzione verr trovata. Se il lower bound invece pi piccolo, l'ottimo (e l'allocazione di oerte ad esso associato) viene trovato in modo certo durante l'analisi di una delle cardinalit consentite. Di fatto l'algoritmo per il calcolo della soluzione ottima ad alto livello prevede i seguenti passaggi:
1. Determinazione di
CARDmax
CARDmin ;
2. Calcolo di una serie di valori memorizzati in vettori e utilizzati durante l'applicazione dei tagli per incrementarne l'ecienza; 3. Applicazione dell'algoritmo AAR per ogni cardinalit e
CARDmax ,
selezionabile liberamente. 4. Se l'ottimo esiste, stato salvato insieme all'allocazione di oerte durante l'esecuzione di AAR con cardinalit ottima
k.
Se il lower bound pi piccolo dell'ottimo del problema, quest'ultimo viene prima o poi determinato dall'analisi di una delle cardinalit possibili. Di fatto l'ordine con cui queste cardinalit vengono analizzate non dovrebbe essere rilevante. Questo non propriamente vero e la motivazione piuttosto evidente da quanto visto in (3.3.1.4). Si detto che, navigando l'albero di cardinalit
ci si pu imbattere in allocazioni ammissibili di cardinalit minore e di prezzo complessivo maggiore del lower bound. Allocazioni di questo genere, se trovate, permettono di aggiornare il lower bound e di rinforzare i tagli che dipendono da esso (il taglio sui prezzi e quello sui costi ridotti), rendendo l'analisi delle
CAPITOLO 3.
IL NOSTRO ALGORITMO
69
altre cardinalit (e l'analisi rimanente della cardinalit seguenza un'analisi delle cardinalit da rispetto a quella di ordine inverso.
CARDmax
L'applicazione dei tagli prevede, oltre all'utilizzo di quantit statiche precalcolate, anche di valutare lo stato dell'allocazione parziale. Per fare un esempio, nel taglio sui prezzi, necessario calcolare il prezzo totale delle oerte allocate cos come in quello sui beni si deve conoscere il numero complessivo dei beni associati alle oerte presenti nell'allocazione. Chiaramente, per
questioni di ecienza, lo stato non viene valutato nuovamente per ogni allocazione parziale ma si predilige calcolare lo stato attuale partendo da quello precedente a cui si applica una transizione specica per il taglio analizzato. Si supponga che dall'allocazione A
si passi ad un'allocazione
Sia
pA
pB
pB =
jB
pj
(3.45)
jA
pj + p11
jA
pj = pA .
to dell'allocazione precedente e quindi gi calcolato. In questo modo non viene eseguito un numero di somme pari al numero di oerte presenti in A diminuito di 1. Per ottenere questo risultato suciente memorizzare lo stato dell'allocazione e aggiornarlo continuamente. In realt l'approccio adottato nel nostro algoritmo leggermente dierente e ne migliora ancor pi fortemente l'ecienza. Supponiamo che dall'allocazione B si arrivi ad un'allocazione C siatta Se volessimo calcolare
[1, 4, 7, , ..., ].
pC in funzione dello stato precedente, pB p6 p10 p11 + p7 . Il numero delle somme alQuesto dovuto al fatto che le due
gebriche svolte superiore alle oerte presenti in C e di fatto un'approccio di calcolo del tipo (3.45) preferibile.
ptemp delle oerte contenute nell'allocazione [1, 4, , ..., ] avremmo che pC = ptemp +p7 . In pratica ci che si
naturale che se potessimo conoscere il prezzo totale desidera ottenere il valore dello stato attuale in funzione di uno stato passato
CAPITOLO 3.
IL NOSTRO ALGORITMO
70
(non prettamente quello precedente) e dell'ultima oerta aggiunta. Dopotutto se stiamo analizzando l'allocazione
considerando che le
oerte vengono aggiunte una a una, evidente che in qualche iterazione passata l'algoritmo abbia valutato anche l'allocazione con
ptemp .
Quello che viene fatto costruire una struttura dati che contenga
tutti gli stati passati non in funzione dell'allocazione parziale ma dell'ultima oerta inserita. Viene ora proposto un esempio per spiegare meglio il concetto. Si supponga che iterazioni consecutive all'interno della stessa funzione alloca() determino le seguenti allocazioni:
Statop (a)
a.
Se
a = 0
ovviamente anche
Statop (0) = 0.
gionamento non dierisce aatto qualora vengano considerate altre grandezze, quali la somma dei beni totali (taglio sui beni) o locali (taglio sui vincoli) associati alle oerte. seconda alla Alla prima iterazione si ha che
Statop (2) = Statop (1) + p2 , alla terza quarta Statop (4) = Statop (3) + p6 . Con la quinta
parziale cambia radicalmente riducendosi a due sole variabili. Di fatto si ha una riscrittura dello stato in riferimento all'ultima oerta inserita in modo che
Statop (2) = Statop (1) + p3 . Continuando con lo stesso ragionamento alla sesta iterazione si ha che Statop (3) = Statop (2) + p5 , anche qui una riscrittura
dello stato nella posizione 3. In generale, dunque, lo stato di un'allocazione parziale non viene determinato dallo stato dell'allocazione precedente ma dell'allocazione ottenuta eliminando da quella attuale l'ultima oerta inserita (e che sicuramente gi stato valutato in precedenza).
CAPITOLO 3.
IL NOSTRO ALGORITMO
71
Figura
3.2:
Ordinamento
delle
oerte
per
prezzi
decrescenti.
Si
noti
la
Il funzionamento di AAR implica un'ordinamento delle oerte per prezzi decrescenti in modo che valga (3.26). Le oerte sono numerate rispettando questo criterio. Di fatto nel contesto dell'algoritmo la relazione esistente tra le oerte
j1
j2
che il prezzo di
j1
maggiore di quello di
j2 .
abile che le oerte del problema siano numerate conformemente al criterio di ordinamento. Quello che viene fatto ordinarle e rinominarle in modo che un oerta di indice
j + 1.
E'
necessario pertanto tener traccia del legame che intercorre tra i nuovi indici (quelli ottenuti dopo l'ordinamento) e i vecchi indici (quelli che identicano la variabile nella formulazione originale del problema). Ci che importante sottolineare che l'ordinamento delle oerte per prezzi decrescenti solamente una delle possibili scelte a disposizione e, tra l'altro, non risulta nemmeno la sola adottata nella progettazione del nostro algoritmo. La seconda tipologia di ordinamento delle oerte quella per numero totale di beni dal pi piccolo al pi grande in modo che:
CAPITOLO 3.
IL NOSTRO ALGORITMO
72
La modalit di applicazione dei tagli sostanzialmente non dierisce dal caso precedente. signicativi: Si devono tuttavia tenere in considerazione un paio di aspetti
Le quantit precalcolate necessarie per applicare i tagli vengono computate in modo dierente a seconda dell'ordinamento delle oerte. esempio, per calcolare Per
prezzo maggiore tra tutte quelle rimaste da allocare. Se le oerte sono ordinate per prezzi decrescenti, quelle rimaste hanno tutte un prezzo minore dell'oerta
a.
a + 1, a + 2,
... ,
a + b.
Se le oerte sono ordinate per beni crescenti questo non aatto vero ed necessario prima determinare tutte le oerte rimaste, ossia quelle aventi un numero di beni totali maggiore dell'oerta
a,
e successivamente ordi-
b.
Un discorso analogo
Vm (a, b)).
Se il taglio viene applicato con successo, cambia la modalit di determinazione della nuova allocazione parziale e della prossima eventuale oerta da aggiungere. Si gi detto che il taglio dei prezzi in generale quello pi profondo. La profondit del taglio tuttavia dovuta esclusivamente al tipo di ordinamento eettuato. Sia
[1, 2, 4, 6, , ]
l'allocazione valutata
con 7 la prossima oerta da inserire. Se il taglio dei prezzi ecace avevamo gi osservato che la nuova allocazione diventa
[1, , , , , ]
con 3
la prossima oerta da aggiungere. Se le oerte sono ordinate per beni crescenti questo non pi vero. Infatti l'allocazione rimane
[1, 2, 4, 6, , ]
e l'oerta da inserire passa a 8. La motivazione semplice: non c' alcuna garanzia che
p 7 > p8
all'oerta 7 implica solamente che ai ni del taglio sui prezzi. prezzo maggiore la
[1, 2, 4, 6, 8, 11]
che,
11, da se p8 > p7 ,
beni8 < beni7 il che non rilevante Di fatto se da [1, 2, 4, 6, 7, ] l' oerta con [1, 2, 4, 6, 8, ] posso arrivare all'allocazione
ha un prezzo maggiore della migliore allo-
[1, 2, 4, 6, 7, ]. L'unico controllo che non richiede troppo tempo per essere eseguito appunto p8 > p7 : se questo non vero, anche da [1, 2, 4, 6, 8, ] non verr mai generata un'allocazione
cazione full ottenuta partendo da full di valore maggiore del lower bound e di conseguenza l'allocazione da
CAPITOLO 3.
IL NOSTRO ALGORITMO
73
valutare diventerebbe
gere. In denitiva, se le variabili sono ordinate per beni totali crescenti e il taglio sui prezzi ecace, si determinano nuova allocazione parziale e nuova oerta da aggiungere attraverso il seguente algoritmo: 1.
2. se 3. se
4. torna al passo 2 5.
new j j j
l'oerta che si cercato di aggiungere nell'allo-
new j
Per
quanto riguarda il taglio sui beni, esso tanto profondo quanto lo era il taglio sui prezzi quando le oerte erano ordinate per prezzi decrescenti e di fatto l'algoritmo per determinare la nuova allocazione parziale esattamente identico. Dopotutto questo algoritmo si basa sull'idea che se da un'allocazione non posso ottenere un'allocazione full di prezzo maggiore del lower bound, un'allocazione del genere non pu essere ottenuta nemmeno se dall'allocazione parziale iniziale sostituisco oerte con altre a loro incrementali, cio con prezzo pi piccolo. In questo caso invece, se da un'allocazione non posso ottenere un'allocazione full con un numero di beni minore di quello a disposizione, un'allocazione siatta non potr essere ottenuta nemmeno se dall'allocazione iniziale sostituisco oerte con altre a loro incrementali, cio con un numero di beni totale associato maggiore. Il taglio sui coecienti di costo ridotto e il taglio di ammissibilit sono invece indipendenti dall'ordinamento delle oerte e di conseguenza non subiscono variazioni nella metodologia di computazione della nuova allocazione parziale da valutare.
L'aver introdotto nella trattazione un secondo tipo di ordinamento dovuto al fatto che entrambi gli ordinamenti sono stati utilizzati per implementare l'algoritmo AAR. In particolare abbiamo osservato, alla luce di un suciente numero di istanze benchmark, che i risultati migliori in termini di prestazioni si ottengono analizzando le cardinalit alte mediante un ordinamento per beni
CAPITOLO 3.
IL NOSTRO ALGORITMO
74
crescenti e le cardinalit basse tramite un ordinamento per prezzi decrescenti. E' bene far presente anche che solitamente la cardinalit ottima ben lontana dagli estremi del range di cardinalit valide e in particolare si aggira in un intorno del valor medio tra
CARDmin e CARDmax .
puramente empiriche. Tuttavia, considerando che apportano un miglioramento delle prestazioni dell'algoritmo e che, in ogni caso, un peggioramento (sia in termini di ecacia che di ecienza) non fattibile, si ritenuto opportuno tenerle in considerazione nella strategia di analisi degli alberi che diventa:
1.
CARDmedia =
CARDmax +CARDmin ; 2
CARDmedia + 1
no a
CARDmax
con le
oerte ordinate per beni totali crescenti; 3. analisi degli alberi a partire da
CARDmedia
no a
CARDmin
con le oerte
CARDmedia k
(con
permette di determinare l'ottimo (se esiste) molto pi velocemente, perch pi probabile che sia ottima la cardinalit che la cardinalit
k + 1.
Qualora la cardinalit
la soluzione ottima pu essere trovata anche analizzando cardinalit superiori, che infatti vengono valutate per prima. Se invece la soluzione ottima
CARDmedia ,
sicura-
CARDmedia
set di variabili anch il problema riformulato abbia una dimensione tale da poter essere risolto attraverso AAR. Si tenga presente che il xing delle variabili sempre
CAPITOLO 3.
IL NOSTRO ALGORITMO
75
possibile a prescindere dalla durata dell'operazione in quanto nella soluzione ottima necessariamente una variabile
xj
strategie per determinare a quale dei due valori deve essere ssata all'ottimo. Il nome di Riduzione Ricorsiva sta a sottolineare come la ricorsione sia una delle principali strategie per ottenere questo risultato.
3.3.2.1 Inizializzazione di RR
Anche per RR la risoluzione del problema equivale a vericare che, dato un lower bound
LB ,
migliore o al limite uguale al lower bound stesso. Come vedremo in seguito le strategie di xing delle variabili si basano sulla risoluzione di sottoproblemi aventi dimensioni ridotte. Essendo l'obiettivo di queste strategie quello di ssare variabili nel problema di partenza, la risoluzione del sottoproblema non nalizzata alla ricerca dell'ottimo e anche qualora la soluzione ottima esista e abbia un valore complessivo migliore di
LB ,
bound. In altre parole RR ssa una serie di variabili tenendo traccia dei miglioramenti del lower bound senza tuttavia interessarsi dell'allocazione di oerte associata al miglior lower bound trovato. Sar compito dell'algoritmo AAR che risolve il problema ridotto a memorizzare la soluzione ottima (se esiste), esattamente nel modo esposto in (3.3.1.5). Sia
V ARmax
il numero massimo di
variabili che un problema deve avere per poter essere risolto tramite AAR. Il compito dell'algoritmo RR quello di ssare un numero di oerte almeno pari a
nV ARmax in
modo da ottenere un problema ridotto di dimensioni gestibili anche da un approccio di tipo AAR. Lo strumento principale utilizzato da RR il RCC denito in (3.20). E' suciente dunque risolvere il rilassamento continuo del problema e utilizzare i costi ridotti e il valore della funzione obiettivo, unitamente al lower bound in input, per costruire tale vincolo logico. Fatto questo, le variabili del problema vengono ordinate per costi ridotti
bj
(3.46)
CAPITOLO 3.
IL NOSTRO ALGORITMO
76
|bj | xj +
jN jN +
bj (1 xj ) U B LB
(3.47)
1. se 2. se
bj > U B LB
allora
xj 1 xj 0
bj < (U B LB)
allora
Questo permette di ottenere una prima sostanziale riduzione della dimensione del problema.
val
e vericare che, cosi facendo, non si possa ottenere un valore Se la verica va a buon ne, la variabile viene settata
1 val, questa volta in modo denitivo. In generale il xing temporaneo della variabile xj in funzione del segno del proprio costo ridotto: se bj > 0 , xj viene ssata temporaneamente a 0 mentre se bj < 0 , xj viene ssata a 1. In questo modo
avremo sempre un raorzamento del RCC dovuto ad una diminuzione del termine noto di una quantit pari a casi possibili:
|bj |.
Sia
xj
1.
bj > 0: xj
di (3.47) pari a
bj ,
U B LB .
xj
xj
a 0, possibile che
altre variabili debbano essere ssate a 0 o a 1 onde evitare la violazione del RCC.
CAPITOLO 3.
IL NOSTRO ALGORITMO
77
Il xing temporaneo di
xj ,
del problema di un numero maggiore o al pi uguale a uno (visto che almeno una variabile, ossia
xj ,
viene ssata).
Esempio:
23.13 (1 x12 ) + 22.44 (1 x13 ) + 5.11x6 + 10.62x14 +10.65x5 + 20.47x4 + 24.36x1 + 24.41x15 34.62 x12 venisse ssata a 0 si avrebbero ancora a disposizione 34.62 23.13 = 11.49 unit perch la disuguaglianza sia corretta. Da questa considerazione si pu aermare che x13 deve essere posta a 1 e che x4 , x1 e x15 devono essere poste a 0.
Se la variabile 2.
bj < 0 : x j
di (3.47) pari a
|bj |,
U B LB .
A questo
xj
xj
variabili debbano essere ssate a 0 o a 1 onde evitare la violazione del RCC. Il problema viene quindi ridotto di un numero di variabili maggiore o al pi uguale a 1 (visto che almeno
xj
viene ssata).
Esempio:
23.13 (1 x12 ) + 22.44 (1 x13 ) + 5.11x6 + 10.62x14 +10.65x5 + 20.47x4 + 24.36x1 + 24.41x15 34.62 x15 viene ssata a 1 34.62 24.41 = 10.21 unit perch
Se la variabile a 1 mentre si avrebbero a disposizione ancora la disuguaglianza sia corretta. Da
x12
x13
x14 , x5 , x4
x1
x j
val
(con
val
uguale a 0 o
Si denisca
Ndirf ix
l'insieme degli
Nindf ix
CAPITOLO 3.
IL NOSTRO ALGORITMO
78
Nf ix+
Nnotf ix = N/ (Ndirf ix Nindf ix { e j}) = {j (Ndirf ix Nindf ix { | xj = 1}. Si formula ora il seguente problema: j}) max
jNnotf ix
pj xj
wij xj ci
jNnotf ix jNf ix+
wij i = 1, ..., m
(3.48)
j {0, 1} j Nnotf ix
Se
LB
il lower bound del problema di partenza, il lower bound del problema (3.48)
corrisponde a:
LBrif ormulato = LB
jNf ix+
Si risolva il problema (3.48) e si valuti il valore ottimo
pj
zrif ormulato :
(3.49)
1.
LBrif ormulato , LB
che a sua
volta il minimo valore che sommato ai prezzi delle oerte gi ssate a 1 (appartenenti a
Nf ix+ )
del problema
pj < LB . x, j
Considerando che
< LBrif ormulato si ha che zrif ormulato + le oerte in Ndirf ix sono ssate al loro
Nindf ix
x = val j
equivale a trovare
come miglior soluzione ammissibile un'allocazione di oerte il cui prezzo totale non raggiunge il lower bound del problema originale. all'ottimo necessario che 2. Di fatto
x = val, j
xj = 1 val.
se sommo il valore ottimo del problema riformulato
Nf ix+ )
si ottiene un
valore pi grande del lower bound del problema di partenza. In altre parole l'allocazione (ammissibile) ottenuta considerando le oerte di
Nf ix+
e quelle
valorizzate a 1 nel problema riformulato (3.48) migliore della soluzione ottima attuale. Questo risultato permette di aggiornare il lower bound del problema che diventa quindi
LB =
xi Nf ix+
pi + zrif ormulato .
CAPITOLO 3.
IL NOSTRO ALGORITMO
79
x j
val
xj = 1 val,
xj = val
ha
un valore identico al lower bound del problema originale. E' l'unico caso in cui n il lower bound viene aggiornato n la variabile
xj
viene ssata a
1 val.
Si osservi, come descritto in (3.3.2.3), che una variabile viene posta temporaneamente ad un valore tale per cui il RCC si raorzi. E' inutile osservare il comportamento del problema ottenuto ssando tale variabile al valore opposto in quanto non verrebbe apportata alcuna semplicazione nella riformulazione del problema e la strategia di xing si ridurrebbe ad un puro approccio di tipo branch and bound. Come vedremo in seguito, la strategia di xing adottata permette di ottenere sottoproblemi (3.48) via via pi semplici da risolvere. Resta da capire come le variabili vengono selezionate per poi ssarne il valore. L'idea quella di indirizzare al xing le variabili che apportono una semplicazione maggiore possibile al RCC. Ci permette di risolvere un problema riformulato pi semplice e quindi di ottenere considerazioni del caso.
zrif ormulato
e maggiore la riduzione del termine noto del vincolo e pi variabili possono essere conseguentemente ssate ad un determinato valore tramite xing indiretto. Dopotutto abbiamo gi valutato come il costo ridotto di una variabile esprima una buona approsimazione di quanto questa variabile assuma il valore 0 piuttosto che 1 all'interno della soluzione ottima. Fissando la variabile al valore opposto di quello che avrebbe nella soluzione ottima, il problema riformulato viene risolto facilmente in quanto pi bassa la probabilit che il suo ottimo possa superare il valore del lower bound desiderato. Inoltre opportuno far notare un aspetto molto importante. Supponiamo che il meccanismo di xing sulla variabile
xj1
si concluda positivamente
e che di conseguenza sia noto il suo valore all'ottimo. processo di xing sulla variabile associato non contiene
Successivamente si itera il
xj2 .
xj1
Nf ix .
Di fatto pi si procede
a ssare variabili e pi i problemi riformulati avranno dimensioni ridotte e quindi pi semplici da risolvere. Tanto vale dunque tentare di ssare inizialmente le variabili
CAPITOLO 3.
IL NOSTRO ALGORITMO
80
pi facili in modo da poterle eliminare denitivamente dal problema allo stesso modo delle variabili contenute in
Nf ix 9 .
1.
2. se
3. Selezione di 4. se
tale che
bj > 0
allora
xj 0
xj 1
come descritto in (3.3.2.3)
5. determinazione di
Nindf ix
Nf ix+
zrif ormulato
zrif ormulato +
jNf ix+
,
pj LB
allora
LB zrif ormulato +
jNf ix+
pj
altrimenti 8. se 9.
xj 1 xj
Ndirf ix = Ndirf ix j
allora vai al passo 11 altrimenti vai al passo 9
Ntemp = Ntemp \ j
Chiaramente una volta ssate tutte le variabili necessarie, queste vengono eliminate dal problema (aggiornando opportunamente il lower bound e le capacit dei vincoli) che viene poi risolto tramite AAR.
P, a
Ndirf ix .
escluse in tutte le riformulazioni a venire in quanto il valore a cui sono poste non funzionale alla
x j
direttamente da
anzich da
P.
CAPITOLO 3.
IL NOSTRO ALGORITMO
81
il problema intero
Rlp . E' noto che, e zlp rispettivamente l'ottimo intero e l'ottimo continuo, vale che
zlp
Rlp pi piccolo di LBrif ormulato sicuramente impossibile che la soluzione ottima di R sia migliore di LBrif ormulato per la propriet transitiva ( z zlp LBrif ormulato ). Questo controllo molto veloce in
. Se il valore della soluzione ottima di termini di tempo ma solitamente poco ecace. E' necessario dunque utilizzare un metodo che navighi lo spazio delle soluzioni intere del problema vericando che ne esista almeno una migliore di quella cercata. Un approccio algoritmico siatto gi stato presentato nel corso di questa trattazione. Dopotutto il problema riformulato
non altro che un MKP e sono stati forniti gli strumenti per risolvere nel modo
desiderato questa tipologia di problemi: AAR e RR. Sussistono due possibilit. Si denisca
nR
R:
1.
nR V ARmax :
risolto tramite AAR. Se esiste un'allocazione ammissibile di oerte di valore complessivo maggiore di
LBrif ormulato
per aggiornare il lower bound del problema di partenza. In caso contrario viene restituituo un valore negativo. 2.
nR > V ARmax :
risolto tramite AAR. Di conseguenza necessario ssare qualche altra variabile in modo da ricadere nel caso 1. Il xing delle variabili viene eseguito applicando nuovamente l'algoritmo RR questa volta sul problema R. Cos facendo verranno generati altri problemi riformulati problemi ancora maggiore di
problemi e via dicendo. In altre parole RR viene applicato ricorsivamente no a quando non vengono generati sottoproblemi aventi una dimensione tale da poter essere risolti da AAR che, dunque, pu essere considerato come il piede della ricorsione. La terminazione della ricorsione garantita dal fatto che il
CAPITOLO 3.
IL NOSTRO ALGORITMO
82
problema riformulato ha un numero di variabili pi piccolo di almeno un'unit rispetto al proprio problema padre. Figura 3.3: Sia Si faccia un esempio, considerando la
R3 rispettivamente i problemi riformulati ottenuti ssando rispettivamente xj1 = val 1 , xj2 = val 2 e xj3 = val3 . R1 e R3 hanno una dimensione tale da poter essere risolti direttamente da AAR
il problema di partenza e e
R1 , R2
che tuttavia non riesce a determinare ad entrambi un valore migliore rispetto al loro lower bound. Di conseguenza le variabili vengono ssate, e
xj1 = 1 val1
e viene risolto
xj3 = 1 val3 . R2
V ARmax
R2
partendo dai costi ridotti del suo rilassato continuo e dal lower bound determinato a partire dal lower bound di descritto in precedenza.
LB R2
Alcune variabili di
R2
per non violare il suo RCC e ne rimangono da ssare altre due ( modo che ne restino da ssare un numero pari a e si ottiene il problema riformulato A
V ARmax . LBR2
Si
x1 e x2 ) in j j ssa x = val 1 j1
R1
1
R1
LBR
ottenuto da
R2 . R2
x1 j
viene settata a
1 val1 .
problema riformulato
con un lower
di variabili maggiore di
V ARmax
Si
CAPITOLO 3.
IL NOSTRO ALGORITMO
83
calcola un nuovo RCC, si ssano direttamente alcune variabili e si esegue il xing indiretto di altre tre variabili per poter raggiungere una dimensione tale da poter essere risolto da AAR. I tre problemi riformulati
R1 , R2
tutti risolti tramite AAR e in tutti e tre i casi la variabile viene ora un numero di variabili rimaste da ssare uguale a
R3 sono ssata. R2 ha
e
V ARmax e viene risolto tramite AAR. Il risultato tuttavia non migliore di LBR . Nel contesto del liv2 ello ricorsivo superiore, questo comporta che la variabile x deve essere ssata j2 2 . Una volta ssate x e x , la dimensione di R2 tale da poter essere a 1 val j1 j2
risolto tramite AAR. Anche in questo caso il valore trovato non migliore di
LBR2 e nell'ottica del livello ricorsivo superiore signica che xj2 viene ssata a 1 val 2 . A questo punto R si trova ad avere un numero di variabili uguale a V ARmax e viene risolto attraverso AAR. Se il risultato migliore di LBR la
soluzione viene salvata.
E' importante far notare come sebbene il problema da risolvere possa essere in realt il prodotto di un livello ricorsivo precedente, questa informazione del tutto irrilevante dal punto di vista dell'algoritmo risolutivo. L'obiettivo nale sempre
quello di vericare che il problema su cui applicato RR abbia una soluzione ottima migliore del lower bound fornito come input. E' compito di chi invoca l'esecuzione dell'algoritmo (che a sua volta potrebbe essere un'istanza di RR di livello superiore) interpretare correttamente i risultati pervenuti. C' tuttavia una dierenza sostanziale tra l'algoritmo RR applicato al problema radice (livello 0 della ricorsione) e l'algoritmo RR applicato ai livelli successivi. Si faccia riferimento sempre all'esempio di gura 3.3. Solitamente per care la soluzione ottima se questa ha un valore pi grande di della riduzione ricorsiva a
si vuole ricer-
LBR .
L'applicazione
R2
sivi successivi) non ha questo ne ma inserita in un contesto pi ampio, volto o a migliorare il lower bound di sola delle variabili di soluzione con valore se
o a ssare la variabile
xj2
1 val2 . R
Se anche una
R2
una
LBR2 . pj
Nel contesto di
xj2 = val2
LBR
e pi precisa-
jNf ix+
R2
la
in quanto l'obiettivo stato gi raggiunto, ossia che non possibile ssare in variabile
xj2
1 val2 .
R2
si possa trovare
LBR2 (andando
quindi a migliorare
CAPITOLO 3.
IL NOSTRO ALGORITMO
84
R)
questo viene prima o poi determinato. Il vantaggio, dunque, risiede nella capacit di spezzare prima la catena ricorsiva guadagnando in termini di prestazioni.
RR su un problema
LB :
Procedura RR
1. BEGIN 2. Costruzione di RCC e di 3.
Ndirf ix
4. se
5. selezione di 6. se
b > 0 j
allora
x 0 j
x 1 j
come descritto in (3.3.2.3)
7. determinazione di
Nindf ix
Nf ix+
tale problema e
nR
9. se
nR V ARmax applica AAR altrimenti applica Procedura su R. zrif ormulato l'output fornito da AAR o RR
RR (qui denita)
10. se
zrif ormulato + jNf ix+ pj LB allora LB zrif ormulato + altrimenti x 1 x , Ndirf ix = Ndirf ix { j} j j
jNf ix+
pj
11. se 12 12.
Ntemp = Ntemp \ ( j)
CAPITOLO 3.
IL NOSTRO ALGORITMO
85
Q denito su N q = N \ Ndirf ix .
Sia
q Nf ix+ =
max
jN q
pj xj wij i = 1, ..., m
jN q
f ix+
wij xj ci
jN q
(3.50)
xj {0, 1} j N q
con lower bound
LBq = LB jN q + pj . Se la migliore soluzione di Q ha un f ix valore LBq maggiore di LBq allora zrif ormulato LBq altrimenti zrif ormulato 1
15. END
la cardinalit d'ingresso e
LB
LB .
zrif ormulato
= 1
La variante di RR con cardinalit realizzata semplicemente modicando la formulazione del problema di partenza con l'aggiunta del suddetto vincolo di cardinalit:
xj = k
jN
Nel corso della trattazione questa variante di RR verr denita come cardinalit analizzata. Si possono ora fare alcune considerazioni:
(3.51)
RRk
con
la
il RCC si raorza notevolmente in quanto viene costruito partendo dal rilassato continuo del problema intero aggiungendo il vincolo (3.51). da un lato, l'abbassamento dell'upper bound Il risultato ,
UB
diminuzione del termine noto di RCC e, dall'altro, un incremento in modulo dei coecienti di costo ridotto associati alle variabili. La riduzione ricorsiva,
CAPITOLO 3.
IL NOSTRO ALGORITMO
86
la cui ecacia si basa sul RCC, migliora notevolmente in quanto ai vari livelli ricorsivi il numero di variabili che pu essere ssato in modo diretto e indiretto pi elevato.
l'algoritmo RR si basa sulla risoluzione di vari problemi riformulati che, a loro volta, vengono risolti tramite RR. E' necessario ogni qual volta viene formulato un nuovo sottoproblema, tener traccia del numero di variabili settate a 1 in modo da poter determinare correttamente la cardinalit ad esso associata. E' intuitivo infatti che se il problema radice viene risolto con
RRk
, anche
i sottoproblemi generati nei vari livelli ricorsivi devono essere risolti con tale variante di RR. Chiaramente la cardinalit associata ai vari problemi non pi uguale a
k = 20
la cardinalit di analisi
x = 1 j
indiretto che a sua volta ssa quattro variabili di cui due a 1. riformulato viene risolto tramite RR con analisi della cardinalit
krif ormulato =
20 3 1 2 = 14.
(3.52)
RRkrif ormulato .
RR
blema ottenuto eliminando tali variabili viene risolto tramite AAR. La prima operazione svolta da AAR quella di determinare
CARDmin
CARDmax
per
poi analizzare tutti gli alberi di cardinalit compresa tra questi valori. Come avvenuto per RR anche per AAR si denisce una sua variante con cardinalit,
AARk ,
cardinalit
k.
RRk ,
AARkridotto
con
esecuzione di
AARkridotto sia inferiore al tempo impiegato per analizzare l'albero di cardinalit kridotto utilizzando il tradizionale approccio AAR, in quanto
nel primo caso viene utilizzato un RCC pi forte, ottenuto grazie al vincolo di cardinalit (3.51), rendendo il taglio sui coecienti di costo ridotto pi
CAPITOLO 3.
IL NOSTRO ALGORITMO
87
ecace.
CARDmin
l'esecuzione di
AARkridotto
stesso risultato del caso in cui non si riesce a determinare una soluzione avente
LBridotto .
3.4
E' giunto il momento di mettere insieme tutti gli strumenti descritti dettagliamente nei paragra precedenti per poter denire un metodo rigoroso di risoluzione di un generico problema di tipo MKP.
DIMcore = V ARmax 10 in base ai costi ridotti ottenuti risolvendo il rilassato continuo di P . Si ssano le rimanenti variabili al loro valore di upper/lower bound e si calcola un primo LBcore P
un core di dimensione
attraverso una qualunque euristica di irrilevante peso computazionale solve il problema Core di lower bound
11
. Si riun
LBcore
LBcore
lower bound eettivo del problema Core, AAR restituisce sicuramente un'allocazione ottima di oerte che, unite a quelle settate a 1 tra le variabili gi ssate, costituisce la soluzione ammissibile di partenza che verr migliorata tramite l'espansione del Core. Questa soluzione viene salvata in il valore ottenuto sommando settate a 1 viene salvato in
soluzione
LBcore ottimo.
2. Tra tutte la variabili escluse dal Core si seleziona quella con costo ridotto in modulo pi grande. Se tale coeciente risulta pi grande del termine noto del
RCC associato a
l'algoritmo di risoluzione di
x j
tale variabile. Se
b > 0 j
allora
V ARmax
11 Nel nostro caso stata utilizzata l'euristica proposta da Bertsimas con il nome di Adaptive
CAPITOLO 3.
IL NOSTRO ALGORITMO
88
3. Si risolve il nuovo problema Core tramite RR a cui si fornisce in ingresso un nuovo lower bound
LBcore
ottimo
la somma
LBcore
In
cambiano a causa della dierente congurazione delle variabili esterne. uscita a RR viene fornito un valore
allocazione ammissibile di oerte avente prezzo complessivo maggiore di oppure un valore positivo che corrisponde all'ottimo del problema
LBcore Core (z
LBcore ).
z il prezzo totale delle oerte esterne al Core e settate a 1 e lo si salva in ottimo; inoltre, si aggiorna la soluzione ottima in soluzione. A prescindere dal risultato di RR la variabile xj viene aggiunta
Nel secondo caso si somma a al Core. 4. Tornare al passo 2.
applicando il procedimento
ottimo
e
e in
soluzione.
di
CARDmin k
CARDmax
P.
e
compresa tra
CARDmin
CARDmax
si costruisce un
V ARmax
12
Si riapplica il passo 1 descritto in (3.4.1) per ogni problema Core, aggiornando in caso di miglioramento il valore di
ottimo
e di
soluzione.
I problemi Core (e
cores.
4. Sia
Corek
cores con CARDmin k CARDmax . escluse da Corek quella con costo ridotto in k,
l'algoritmo risolutivo di
RCCk
associato a
12 Si osservi che i problemi Core, sebbene abbiano la stessa dimensione e siano ottenuti dallo stesso
problema di partenza, non sono aatto identici in quanto l'aggiunta del vincolo di cardinalit associa alle variabili costi ridotti dierenti.
CAPITOLO 3.
IL NOSTRO ALGORITMO
89
Corek
xj
tale variabile. Se
bj > 0
allora
cores. In xj 0 altrimenti xj 1.
5. Si applica il passo 3 della procedura descritta in (3.4.1). 6. Si iterano i passi 4 e 5 della procedura qui descritta per ogni cardinalit
con
CARDmin k CARDmax .
7. Se il vettore
cores
possibili. La soluzione ottima e il relativo valore della funzione obiettivo sono salvati rispettivamente in passo 4.
soluzione
ottimo.
Capitolo
Prove computazionali
In questo capitolo vengono riportate le prove compiute per testare l'algoritmo descritto comparando i risultati con i pi importanti lavori proposti in letteratura nell'ambito del Multidimensional Knapsack Problem. Abbiamo eseguito il nostro algoritmo su tutti i 270 problemi proposti da P.C. Chu e J.E. Beasley [9] adottando delle strategie risolutive dierenti a seconda della dimensione e della complessit del problema specico. seguito presentati possono essere classicati come segue: In particolare i risultati di
stata utilizzata per ottenere soluzioni di buona qualit per le istanze pi dicili tra quelle proposte da P.C. Chu e J.E. Beasley, comparando i risultati (bont della soluzione e tempo per ottenerla) con le migliori metaeuristiche attualmente sviluppate. Le prove sono state eseguite su un AMD Athlon 64
90
CAPITOLO 4.
PROVE COMPUTAZIONALI
91
X2 Dual Core 4800+ a 2.4 Ghz con 2 GB RAM e sistema operativo Windows XP Professional Service Pack 2.
Per tutte le prove abbiamo utilizzato la versione 8.1 di CPLEX come risolutore dei rilassamenti continui dei sottoproblemi all'interno del nostro algoritmo in quanto le migliorie introdotte nella versione 10.0 (di cui disponevamo solo di una licenza) riguardano essenzialmente la programmazione intera e non l'algoritmo del simplesso utilizzato per risolvere il rilassato.
4.1
Java 5.0
L'algoritmo stato sviluppato interamente in Java nella recente versione 5.0 [43]. La scelta di utilizzare Java anzich linguaggi come il C o il C++ pu considerarsi a primo impatto poco felice. Java infatti un linguaggio interpretato, cio il codice sorgente viene prima compilato in una sorta di linguaggio intermedio chiamato bytecode che, all'istanziazione del singolo processo, la Java Virtual Machine (JVM ) installata su calcolatore interpreta traducendolo in istruzioni macchina. Sebbene Java sia estremamente portabile in quanto suciente avere installata una JVM per eseguire qualunque programma java, esso risulta molto pi ineciente di un linguaggio compilato, che traduce solo in fase di compilazione il codice sorgente in istruzioni binarie direttamente eseguibili dal calcolatore. Il gap di ecienza tra le due tipologie di linguaggi, che agli albori di Java era di circa un ordine di grandezza, si notevolmente ridotto con il perfezionamento della
JVM. In particolare i risultati presentati in seguito sono stati ottenuti utilizzando la JVM rilasciata gratuitamente da BEA [44], una delle pi importanti software house
di application server in java. Questa JVM dispone di un sosticato compilatore
CAPITOLO 4.
PROVE COMPUTAZIONALI
92
La scelta di Java dovuta essenzialmente alla necessit di utilizzare un linguaggio potente e essibile per costruire un algoritmo robusto e facilmente modicabile in seguito a studi futuri. Avendo poca dimestichezza con l'utilizzo di C, ho optato per l'adozione di Java, che invece conosco e utilizzo nella pratica, per concentrare la maggior parte degli sforzi negli aspetti concettuali dell'algoritmo anzich in quelli puramente implementativi. Si tenga presente infatti che l'algoritmo descritto nel
capitolo 3 il risultato di un lavoro di parecchi mesi in cui la strategia risolutiva si anata ed evoluta nel tempo, necessitando di modicare dinamicamente il codice in seguito ai risultati delle prove intermedie di verica dell'ecacia ed ecienza della metodologia proposta. Volendo vericare nella pratica l'eettivo divario in termini di ecienza tra Java e C, si deciso di scrivere l'algoritmo AAR per la navigazione degli alberi di ricerca binaria in ANSI C ed eseguire delle prove su istanze realizzate ad hoc comparando i risultati con lo stesso algoritmo scritto in Java. Anch il test sia valido, abbiamo eseguito le prove sulla stessa macchina, un AMD Athlon 64 X2 Dual Core 4800+ a 2.4 Ghz e 2 GB RAM con sistema operativo Linux distribuzione Kubuntu. Per l'algoritmo in Java ci siamo avvalsi della JVM di BEA mentre per quello scritto in C abbiamo utilizzato il compilatore GCC 4.1.1. Le istanze di test sono state generate partendo dai problemi pi semplici tra quelli proposti da P.C. Chu e J.E. Beasley (n
= 100
m = 5)
variabili a 40, scelte tra quelle pi dicili da settare al relativo valore binario ottimo. La scelta di tradurre esclusivamente l'algoritmo AAR dovuta al fatto che una procedura che non necessita della collaborazione e dello scambio di messaggi con altre parti dell'algoritmo generale EC e pertanto la scrittura del codice si limitata quasi ad una semplice trasposizione dei costrutti Java in costrutti C. Ovviamente, essendo
CAPITOLO 4.
PROVE COMPUTAZIONALI
93
procedurale di basso livello meno leggibile ma pi eciente rispetto ai costrutti Java orientati agli oggetti, si pu ritenere realistico il dimezzamento dei tempi ottenuti traducendo l'algoritmo EC in C. Di fatto si pu valutare l'idea di avere una versione compilabile dell'algoritmo prima di procedere ad apportare modiche, in modo da valutare i risultati generati in tempi pi brevi soprattutto nell'ottica euristica, in cui i problemi di test sono complessi e necessitano comunque di tempi elevati prima che i risultati vengano prodotti. In conclusione le tempistiche che sono presentate nel seguito del capitolo si riferiscono all'esecuzione dell'algoritmo EC scritto in Java 5.0. In realt, seppur,
come vedremo, sono tempi gi di per s ottimi, possono essere abbassati di molto, anche per eettuare un confronto pi veritiero con i risultati ottenuti dagli algoritmi concorrenti comparati, tutti implementati in C.
4.2
Al momento della stesura di questo lavoro le uniche istanze di P.C. Chu e J.E. Beasley delle quali sono note le soluzioni ottime appartengono alle classi di dimensioni minori, pi precisamente:
= 100 = 250
e e
m = 5) m = 5)
e
Istanze CB 100.10 (n
= 100
m = 10)
Questo
signica che a dieci anni di distanza dalla loro pubblicazione, ben 180 problemi non sono ancora stati risolti.
CAPITOLO 4.
PROVE COMPUTAZIONALI
94
quanto riguarda il nostro algoritmo, abbiamo settato la dimensione del Core iniziale a
DIMcore = 30
V ARmax = 30.
V ARmax ,
per
V ARmax > 30
V ARmax =
variabili
30 + h,
ssare
V ARmax
tramite AAR.
per
V ARmax < 30 la dimensione del problema da risolvere con AAR diminuisce, necessitando di ssare tramite RR pi variabili. In pratica, se V ARmax = 30 h, il tempo necessario per risolvere un problema con 30 variabili tramite AAR generalmente pi basso del tempo impiegato per ssare h variabili con RR e risolvere il problema riformulato con V ARmax variabili tramite AAR.
Questo dovuto al fatto che la risoluzione con AAR di un problema con 30 variabili quasi sempre immediata e di fatto inutile abbassare la dimensione massima di risoluzione, in quanto il lieve l'incremento computazionale ottenuto viene cancellato dalla necessit di eettuare pi chiamate ricorsive per ssare un numero maggiore di variabili.
In tabella 4.1, 4.2 e 4.3 sono riportati i risultati relativi rispettivamente alle istanze 100.5, 250.5 e 500.5 di P.C. Chu e J.E. Beasley. Per ogni istanza viene indicato
dell'al-
locazione ottima e i tempi ottenuti dal nostro algoritmo EC e da CPLEX 10.0 in secondi. In tabella 4.4 sono riportati i tempi medi di risoluzione di ogni set di 10 istanze (dierenziate per
m, n
e il coeciente
CAPITOLO 4.
PROVE COMPUTAZIONALI
95
e non sono comparabili ad alcun'altra strategia di risoluzione di questa classe di problemi. Lo stesso CPLEX 10.0 che implementa un risolutore basato su un eciente branch and cut risolve gli stessi problemi in tempi maggiori quasi di un ordine di grandezza rispetto ai nostri. Per le istanze 100.5 i tempi sono dell'ordine del secondo e non si discostano troppo da quelli ottenuti con CPLEX 10.0. Aumentando la
dimensione del problema la dierenza tra i due approcci comincia a farsi pi evidente no a palesarsi nella risoluzione delle istanze 500.5 per le quali il nostro algoritmo impiega un tempo medio per istanza di poco meno di 5 minuti al contrario dei 75 minuti impiegati da CPLEX 10.0. Allo stato dell'arte attuale non esiste nessun
algoritmo (esatto ed euristico) in grado di trovare la soluzione ottima per i problemi della classe 500.5 in un tempo cos ridotto.
DIMcore = 30
V ARmax = 30.
In tabella 4.5 e 4.6 sono riportati i risultati relativi alle istanze rispettivamente delle classi 100.10 e 250.10. Per queste ultime, i tempi di elaborazione sono forniti in ore e minuti, secondo la notazione hh - mm.
CAPITOLO 4.
PROVE COMPUTAZIONALI
96
Tabella 4.1: Istanze 100.5 di P.C. Chu e J.E. Beasley Istanze Tempo elaborazione EC ( s ) Tempo elaborazione CPLEX 10.0 ( s ) 6.14 2.66 4.95 19.81 6.23 2.5 0.64 2.53 4.09 4.28 Tempo elaborazione CPLEX 10.0 ( s ) 1.28 1.83 35.39 6.23 4.03
( = 0.25)
100.5.00 100.5.01 100.5.02 100.5.03 100.5.04 100.5.05 100.5.06 100.5.07 100.5.08 100.5.09 Istanze
Ottimo 24381 24274 23551 23534 23991 24613 25591 23410 24216 24411 Ottimo 42757 42545 41968 45090 42218 42927 42009 45020 43441 44554 Ottimo 59822 62081 69802 60479 61091 58959 61538 61520 59453 59965
K
29 29 29 28 30 30 31 28 28 28
2.00 1.52 2.67 3.11 1.19 1.06 0.53 1.28 0.61 1.0 0.39 0.45 5.66 1.55 0.87 0.34 3.55 0.77 1.69
1.21
( = 0.5)
100.5.10 100.5.11 100.5.12 100.5.13 100.5.14 100.5.15 100.5.16 100.5.17 100.5.18 100.5.19 Istanze
K
52 50 53 52 54 54 55 53 52 53
Tempo elaborazione EC ( s )
0.37
8.59 1.16 3.05 Tempo elaborazione CPLEX 10.0 ( s ) 0.59 0.67 2.06 3.44 1.42 2.58 1.20 1.02 0.59 4.09
1.08
( = 0.75)
100.5.20 100.5.21 100.5.22 100.5.23 100.5.24 100.5.25 100.5.26 100.5.27 100.5.28 100.5.29
K
78 77 77 76 78 76 76 76 76 76
Tempo elaborazione EC ( s )
0.52 0.28 0.52 0.81 0.58 1.39 0.36 1.06 0.34 3.39
CAPITOLO 4.
PROVE COMPUTAZIONALI
97
Tabella 4.2: Istanze 250.5 di P.C. Chu e J.E. Beasley Istanze Tempo elaborazione EC ( s ) Tempo elaborazione CPLEX 10.0 ( s ) 64.48 167.53 14.20 943.37 448.09 428.61 242.22 222.55 60.36 21.37 Tempo elaborazione CPLEX 10.0 ( s ) 209.44 26.44 140.66 219.70 833.22 207.67 147.72 462.87 187.11 253.52 Tempo elaborazione CPLEX 10.0 ( s ) 116.02 80.02 154.92 88.06 134.43 9.13 7.20 140.36 36.16 101.00
( = 0.25)
250.5.00 250.5.01 250.5.02 250.5.03 250.5.04 250.5.05 250.5.06 250.5.07 250.5.08 250.5.09 Istanze
Ottimo 59312 61472 62130 59463 58951 60077 60414 61472 61885 58959 Ottimo 109109 109841 108508 109383 110720 110256 109040 109042 109971 107058 Ottimo 149665 155944 149334 152130 150353 150045 148607 149782 155075 154668
K
73 74 76 71 74 74 76 73 76 72
2.53 15.58 5.44 82.45 21.87 44.09 9.50 47.01 14.05 4.87 24.41 8.55 18.25 37.23 74.03 25.17 12.02 38.37 48.41 33.08 26.62 8.53 23.17 9.78 25.28 3.05 2.58 14.62 4.68 12.65
( = 0.5)
250.5.10 250.5.11 250.5.12 250.5.13 250.5.14 250.5.15 250.5.16 250.5.17 250.5.18 250.5.19 Istanze
K
132 135 130 134 130 132 133 132 130 131
Tempo elaborazione EC ( s )
( = 0.75)
250.5.20 250.5.21 250.5.22 250.5.23 250.5.24 250.5.25 250.5.26 250.5.27 250.5.28 250.5.29
K
191 190 191 193 191 191 192 193 190 191
Tempo elaborazione EC ( s )
CAPITOLO 4.
PROVE COMPUTAZIONALI
98
Tabella 4.3: Istanze 500.5 di P.C. Chu e J.E. Beasley Istanze Tempo elaborazione EC ( s ) Tempo elaborazione CPLEX 10.0 ( s ) 9495.08 2112.22 5188.23 6390.36 2860.30 3657.51 8498.31 3631.08 10424.12 6641.16 Tempo elaborazione CPLEX 10.0 ( s ) 4572.84 2981.42 11637.39 8425.27 648.89 5136.17 2447.30 2955.05 5886.83 5117.97 Tempo elaborazione CPLEX 10.0 ( s ) 218.31 3744.97 746.42 5467.58 2554.25 1218.58 837.47 804.24 2336.92 8301.98
( = 0.25)
500.5.00 500.5.01 500.5.02 500.5.03 500.5.04 500.5.05 500.5.06 500.5.07 500.5.08 500.5.09 Istanze
Ottimo 120148 117879 121131 120804 122319 122024 119127 120568 121586 120717 Ottimo 218428 221202 217542 223560 218966 220530 219989 218215 216976 219719 Ottimo 295828 308086 299796 306480 300342 302571 301339 306454 302828 299910
K
147 148 144 149 147 153 145 150 149 138
563.31 127.20 233.25 192.61 220.92 407.37 559.56 171.37 482.61 261.00
( = 0.5)
500.5.10 500.5.11 500.5.12 500.5.13 500.5.14 500.5.15 500.5.16 500.5.17 500.5.18 500.5.19 Istanze
K
267 265 264 264 267 262 266 249 262 267
Tempo elaborazione
409.47 97.97 1347.89 781.12 65.22 215.22 125.87 188.05 212.41 488.12
Tempo elaborazione EC ( s )
EC ( s )
( = 0.75)
500.5.20 500.5.21 500.5.22 500.5.23 500.5.24 500.5.25 500.5.26 500.5.27 500.5.28 500.5.29
K
371 384 385 384 369 385 385 383 369 378
43.76 247.83 86.64 143.33 203.70 82.34 47.02 39.75 150.20 554.53
CAPITOLO 4.
PROVE COMPUTAZIONALI
99
Tabella 4.4: Sintesi dei risultati per le istanze 100.5, 250.5 e 500.5 di P.C. Chu e J.E. Beasley Istanze 100.5 00-09 10-19 20-29 Tempo di elaborazione medio EC ( s ) Tempo di elaborazione medio CPLEX 10.0 ( s ) 5.38 6.30 1.76 Tempo di elaborazione medio CPLEX 10.0 ( s ) 261.28 268.85 83.86 Tempo di elaborazione medio CPLEX 10.0 ( s ) 5889.83 4980.93 2623.72
Istanze
Istanze
relativamente bassi, sono comunque di un ordine di grandezza pi elevato dei tempi relativi alle istanze 100.5. Si osserva, come era prevedibile, che la dicolt del problema cresce esponenzialmente all'aumentare del numero dei vincoli. A dimostrazione di ci, suciente comparare le tempistiche relative alle istanze 250.10, risolte all'ottimo mediamente in 10 ore rispetto alle istanze 250.5, risolte all'ottimo mediamente in meno di un minuto. Inoltre le istanze identicate in grassetto in tabella 4.6 hanno tempi di risoluzione non accettabili e la situazione non pu che peggiorare con l'aumentare dei vincoli e delle variabili. L'incremento del numero di vincoli del problema aumenta la correlazione tra le variabili, rendendo pi dicile stilare una graduatoria delle oerte con pi possibilit di entrare nell'allocazione ottima. In altre parole gi con istanze correlate da 250 variabili e 10 vincoli, il modello del problema non permette di ottenere informazioni signicative per una riformulazione adeguata. Questo uno dei motivi per cui il Multidimensional Knapsack Problem un problema di dicile trattazione e che ha spinto di fatto molti ricercatori a trovare strategie di tipo euristico per la sua risoluzione. Nel nostro caso specico, l'ecacia dell'algoritmo
dipende completamente dalla robustezza del taglio RCC , responsabile del xing delle
CAPITOLO 4.
PROVE COMPUTAZIONALI
100
Tabella 4.5: Istanze 100.10 di P.C. Chu e J.E. Beasley Istanze Tempo elaborazione EC ( s ) 90.26 83.11 24.14 175.56 19.06 89.84 30.34 7.76 13.42 63.23 Tempo elaborazione EC ( s ) 72.42 21.06 106.37 39.62 24.25 112.14 96.20 28.19 81.09 113.43 Tempo elaborazione EC ( s ) 3.13 36.14 30.28 5.87 5.04 21.25 45.37 6.29 13.09 7.78
( = 0.25)
100.10.00 100.10.01 100.10.02 100.10.03 100.10.04 100.10.05 100.10.06 100.10.07 100.10.08 100.10.09 Istanze
Ottimo 23064 22081 22131 22772 22751 22777 21875 22635 22511 22702 Ottimo 41395 42344 42401 45624 41884 42995 43574 42970 42212 41207 Ottimo 57375 58978 58391 61966 60803 61437 56377 59391 60205 60633
K
27 27 26 27 26 26 27 27 27 27
( = 0.5)
100.10.10 100.10.11 100.10.12 100.10.13 100.10.14 100.10.15 100.10.16 100.10.17 100.10.18 100.10.19 Istanze
K
51 51 51 54 51 52 52 52 52 53
( = 0.75)
100.10.20 100.10.21 100.10.22 100.10.23 100.10.24 100.10.25 100.10.26 100.10.27 100.10.28 100.10.29
K
77 75 75 75 74 76 76 75 76 76
CAPITOLO 4.
PROVE COMPUTAZIONALI
101
Tabella 4.6: Istanze 250.10 di P.C. Chu e J.E. Beasley Istanze Tempo elaborazione EC ( hh - mm ) 10h - 15m 8h - 7m 3h - 6m 35h - 24m 78h - 30m 3h - 39m 3h - 36m 75h - 43m 8h - 36m 14h - 21m Tempo elaborazione EC ( hh - mm ) 7h - 7m 15h - 32m 9h - 48m 38h - 22m 5h - 42m 21h - 30m 19h - 27m 12h - 53m 10h - 58m 2h - 55m Tempo elaborazione EC ( hh - mm ) 2h - 11m 6h - 51m 1h - 22m 1h - 48m 2h - 12m 1h - 37m 14m 10h - 54m 1h - 3m 1h - 8m
( = 0.25)
250.10.00 250.10.01
Ottimo 59187 58781 58097 61000 58092 58824 58704 58936 59387 59208 Ottimo 110913 108717 108932 110086 108485 110845 106077 106686 109829 106723 Ottimo 151809 148772 151909 151324 151966 152109 153131 153578 149160 149704
K
68 69 69 70 67 68 67 69 68 69
250.10.03 250.10.04
250.10.05
250.10.02
250.10.07
250.10.08 250.10.09 Istanze
250.10.06
( = 0.5)
K
129 127 128 131 128 130 129 128 127 131
250.10.10
( = 0.75)
250.10.20 250.10.21 250.10.22 250.10.23 250.10.24 250.10.25 250.10.26 250.10.27 250.10.28 250.10.29
K
187 188 189 189 191 189 189 187 187 190
CAPITOLO 4.
PROVE COMPUTAZIONALI
102
variabili e della riduzione del problema. Aumentare la correlazione tra le variabili comporta un avvicinamento dei loro costi ridotti i cui valori sono fondamentali per classicare le variabili prima e creare ed espandere il Core dopo. Inoltre, pi vincoli ha un problema, maggiore il numero della variabili in base. Ora, a meno che non entrino in base solo variabili di slack, una variabile
xj
ridotto nullo e di fatto non viene inserita nella formulazione del RCC . Se la funzione di valutazione delle variabili, basata sui costi ridotti, restituisce valori tra loro simili, il relativo vincolo RCC meno forte e di conseguenza tutto l'algoritmo diventa pi debole. Nonostante questo aspetto fosse noto a priori, abbiamo deciso comunque di risolvere all'ottimo le istanze 250-10 per due semplici motivi:
trovare il limite, in termini di dimensione del problema, dell'ecacia risolutiva del nostro algoritmo;
entrare in possesso di dati oggettivi (soluzione ottima e tempo necessario per calcolarla) da confrontare con i risultati ottenuti risolvendo le stesse istanze con un approccio di tipo euristico.
Con il secondo metodo sono stati risolti i problemi 250-5, 500-5 e 100-10.
Con il
primo metodo sono state risolte le istanze 100-5 e tutti i problemi appartenenti alle classi pi complesse di P.C. Chu e J.E. Beasley risolte in modo euristico. In tabella 4.7, 4.8, 4.9, 4.10 e 4.11 sono riportati i risultati relativi alle quattro classi di istanze risolte all'ottimo, comparando le tempistiche ottenute applicando entrambi i metodi risolutivi descritti. . Considerata la trascurabile dierenza di tempistiche tra i due metodi applicati alle istanze 100.5, dalle nostre prove emerso che per istanze con un numero ridotto
CAPITOLO 4.
PROVE COMPUTAZIONALI
103
Tabella 4.7: Istanze 100-5 di P.C. Chu e J.E. Beasley Istanza Tempo EC ( s ) card. distinte 2.31 1.95 2.87 4.51 1.83 1.16 0.59 1.89 1.17 1.47 Tempo EC ( s ) card. distinte 0.63 0.70 8.21 2.19 0.91 0.49 1.45 3.86 0.94 2.00 Tempo EC ( s ) card. distinte 0.56 0.29 0.61 1.17 0.59 2.05 0.47 1.19 Tempo EC ( s ) card. non distinte
( = 0.25)
100-5-00 100-5-01 100-5-02 100-5-03 100-5-04 100-5-05 100-5-06 100-5-07 100-5-08 100-5-09 Istanza
2.00 1.52 2.67 3.11 1.19 1.06 0.53 1.28 0.61 1.0
( = 0.5)
100-5-10 100-5-11 100-5-12 100-5-13 100-5-14 100-5-15 100-5-16 100-5-17 100-5-18 100-5-19 Istanza
0.39 0.45 5.66 1.55 0.87 0.34 1.21 3.55 0.77 1.69
( = 0.75)
100-5-20 100-5-21 100-5-22 100-5-23 100-5-24 100-5-25 100-5-26 100-5-27 100-5-28 100-5-29
2.41
0.42
CAPITOLO 4.
PROVE COMPUTAZIONALI
104
Tabella 4.8: Istanze 250-5 di P.C. Chu e J.E. Beasley Istanza Tempo EC ( s ) card. distinte Tempo EC ( s ) card. non distinte 8.39 19.41 6.51
( = 0.25)
250-5-00 250-5-01 250-5-02 250-5-03 250-5-04 250-5-05 250-5-06 250-5-07 250-5-08 250-5-09 Istanza
18.45
59.62 14.02
89.22
13.16 3.20
Tempo EC ( s ) card. non distinte 78.55
89.28
( = 0.5)
250-5-10 250-5-11 250-5-12 250-5-13 250-5-14 250-5-15 250-5-16 250-5-17 250-5-18 250-5-19 Istanza
24.41
8.55
7.64
33.08
Tempo EC ( s ) card. distinte
48.41
35.26 39.70
38.55 Tempo EC ( s ) card. non distinte 28.36
15.77
( = 0.75)
250-5-20 250-5-21 250-5-22 250-5-23 250-5-24 250-5-25 250-5-26 250-5-27 250-5-28 250-5-29
26.62 8.53
23.17
9.78
3.05 2.58
12.20
25.28
CAPITOLO 4.
PROVE COMPUTAZIONALI
105
Tabella 4.9: Istanze 500-5 di P.C. Chu e J.E. Beasley Istanza Tempo EC ( s ) card. distinte Tempo EC ( s ) card. non distinte 707.14 135.19 389.87
( = 0.25)
500-5-00 500-5-01 500-5-02 500-5-03 500-5-04 500-5-05 500-5-06 500-5-07 500-5-08 500-5-09 Istanza
197.48 480.87
244.56 632.34 458.39 Tempo EC ( s ) card. non distinte 547.67 106.12 1617.36 801.17 71.75 523.08
545.15
( = 0.5)
500-5-10 500-5-11 500-5-12 500-5-13 500-5-14 500-5-15 500-5-16 500-5-17 500-5-18 500-5-19 Istanza
340.61
( = 0.75)
500-5-20 500-5-21 500-5-22 500-5-23 500-5-24 500-5-25 500-5-26 500-5-27 500-5-28 500-5-29
81.86
47.75
150.20
554.53
38.45 428.78
187.28
CAPITOLO 4.
PROVE COMPUTAZIONALI
106
Tabella 4.10: Istanze 100-10 di P.C. Chu e J.E. Beasley Istanza Tempo EC ( s ) card. distinte Tempo EC ( s ) card. non distinte
( = 0.25)
100-10-00 100-10-01 100-10-02 100-10-03 100-10-04 100-10-05 100-10-06 100-10-07 100-10-08 100-10-09 Istanza
90.26
85.00
30.27
117.06
210.86
14.17
13.81 24.31 81.34
123.34
24.49
( = 0.5)
100-10-10 100-10-11 100-10-12 100-10-13 100-10-14 100-10-15 100-10-16 100-10-17 100-10-18 100-10-19 Istanza
72.42
21.06
106.37
39.62
24.25
82.66
( = 0.75)
100-10-20 100-10-21 100-10-22 100-10-23 100-10-24 100-10-25 100-10-26 100-10-27 100-10-28 100-10-29
36.14 30.28
5.87
2.95
45.45 30.91
21.25
45.37 6.29 13.09
5.04
4.58 4.03
7.78
21.97
CAPITOLO 4.
PROVE COMPUTAZIONALI
107
Tabella 4.11: Sintesi dei risultati per le istanze 100.5, 250.5, 500.5 e 100.10 di P.C. Chu e J.E. Beasley Istanze 100.5 00-09 10-19 20-29 Tempo medio EC card. distinte( s ) 1.97 2.14 0.98 Tempo medio EC card. distinte( s ) Tempo medio EC card. non distinte( s )
Istanze
Tempo medio EC card. non distinte( s ) 32.12 41.55 14.99 Tempo medio EC card. non distinte( s ) 431.41 442.69 189.55 Tempo medio EC card. non distinte( s ) 72.46 84.32 18.11
Istanze
CAPITOLO 4.
PROVE COMPUTAZIONALI
108
di vincoli la risoluzione di pi problemi distinti ognuno con il proprio vincolo di cardinalit permette in generale di ottenere delle prestazioni computazionali migliori. In pratica sia
un problema con
CARDmin
CARDmax
rispettivamente la cardi-
nalit minima e la cardinalit massima delle allocazioni da valutare. Sia inoltre l'algoritmo in grado di risolvere il problema in modo classico,
EC
ECk l'algoritmo che risolve il problema P applicando separatamente i CARDmax CARDmin + 1 vincoli di cardinalit e T una funzione per valutare il tempo di esecuzione degli algoritmi.
Per istanze con un numero di vincoli ridotto si ha, in generale, che:
CARDmax
T (EC (P )) >
k=CARDmin
T (ECk (P ))
(4.1)
Per problemi siatti il taglio sui costi ridotti estremamente ecace e permette di riformulare il problema in modo da ridurlo notevolmente in poche chiamate ricorsive. L'aggiunta di un ulteriore condizione stringente, quale il vincolo di cardinalit, al rilassato continuo, permette di generare costi ridotti in valore assoluto pi elevati parallelamente ad un upper bound (e di fatto al termine noto del vincolo RCC ) pi basso. Tutto questo raorza ulteriormente il vincolo RCC rendendo molto pi veloce l'applicazione dell'algoritmo ricorsivo per cardinalit prossime a quella ottima e quasi immediata per cardinalit distanti da essa. Questo spiega come sia possibile che la risoluzione di
risoluzione di un unico problema. Lo stesso discorso pu essere applicato anche per le istanze 100.10 in quanto, sebbene il numero di vincoli sia maggiore, la dimensione del problema in termini di numero di variabili ancora piccola, ottenendo dei vincoli
La situazione Per
questi problemi, l'aggiunta del vincolo di cardinalit non determina un raorzamento del taglio sui costi ridotti signicativo. Essendo questo taglio l'unica dierenza tra i vari problemi risolti da
ECk ,
CARDmax CARDmin + 1
CAPITOLO 4.
PROVE COMPUTAZIONALI
109
determinare a priori quali fattori entrano in gioco per determinare quale dei due ordinamenti preferibile applicare e di conseguenza ci siamo avvalsi di considerazioni empiriche. Abbiamo eseguito delle prove sulle istanze della classe 500.5 utilizzando diversi approcci e comparando i tempi ottenuti. Si deciso di ordinare le variabili a seconda del valore della cardinalit analizzata
kmedia
tra la cardinalit massima e quella minima. In tabella 4.12 sono riportati i tempi in secondi ottenuti utilizzando:
l'ordinamento per prezzi per tutte le cardinalit; l'ordinamento per beni per tutte le cardinalit; l'ordinamento per beni se l'ordinamento per beni se l'ordinamento per beni se l'ordinamento per beni se
altrimenti l'ordinamento per prezzi; altrimenti l'ordinamento per prezzi; altrimenti l'ordinamento per prezzi; altrimenti l'ordinamento per prezzi.
Dalle prove eettuate emerso che la strategia migliore quella di ordinare le variabili per beni crescenti qualora la cardinalit analizzata sia maggiore della cardinalit media, altrimenti le variabili devono essere ordinate per prezzi decrescenti. Tuttavia solo una considerazione empirica ottenuta mediando i tempi relativi esclusivamente a queste 30 istanze. Si consideri che, prendendo di volta in volta il tempo migliore in relazione alla singola istanza, si ottiene un tempo medio di risoluzione pari a 252 secondi, ossia del 15% pi basso del valore da noi trovato. Inoltre plausibile che un'ordinamento sia preferibile all'altro a prescindere dalla relazione tra la cardinalit analizzata e quella media ma in funzione di altri fattori. E' bene dunque eettuare
CAPITOLO 4.
PROVE COMPUTAZIONALI
110
Tabella 4.12: Tempi di risoluzione delle istanze 500.5 di P.C. Chu e J.E. Beasley per diversi ordinamenti delle variabili Istanza 500.5.00 500.5.01 500.5.02 500.5.03 500.5.04 500.5.05 500.5.06 500.5.07 500.5.08 500.5.09 500.5.10 500.5.11 500.5.12 500.5.13 500.5.14 500.5.15 500.5.16 500.5.17 500.5.18 500.5.19 500.5.20 500.5.21 500.5.22 500.5.23 500.5.24 500.5.25 500.5.26 500.5.27 500.5.28 500.5.29 media BENI 530 PREZZI 579 87 247 320 179
k < kmedia
559
k kmedia ,
535 98 159 304 185 371 369 181
k kmedia
140 178
230 399
141
86
523
135 165 183 220 391 582 151 448 243 582 96
k > kmedia
563 127 233 193 221 407 560 171 482 261 409 98 1348
220
149 441
235 606
573
356
206 553
367
170 362
362 201 544 254 411
312
387
61 1736
271
229
562 67 1548 840 73 308 123 178 191 496 40 356 74 198 231 113 30 37 125 650 306
505
1155
954 70 297 138 225 222 495 46 262 96 165 237 128 54 44 170 652 304
102
60
69
680
70 230
1697 685
1193 933 69 287 141 229 230 511 45 263 96 156 241 114 53 45 172 666 305
144 184
496 39 343 67 181 203
113
237
65 215
126 188 212 488
781
248
87 143 204 82 47 40 150
44
69
26 34
106 544
296
291
555
CAPITOLO 4.
PROVE COMPUTAZIONALI
111
ulteriori studi per stabilire se esiste una procedura che permetta di valutare di volta in volta la scelta di un ordinamento piuttosto che l'altro.
4.3
Algoritmo euristico
V ARmax )
viene risolto tramite AAR, altrimenti si procede ricorsivamente ad applicare RR. L'algoritmo esatto non prevede alcun'altra condizione di valutazione oltre a questa e in entrambi i casi il problema ridotto viene risolto. La versione euristica del nostro algoritmo prevede semplicemente di introdurre una nuova condizione per la risoluzione del problema ridotto. ridotto, Sia
il problema il il
UB P
un suo upper bound ottenuto risolvendo il rilassato continuo e E' ovvio che se
LB U B < LB
non viene risolto in quanto la soluzione ottima intera non sar mai uguale
LB .
UB
UB GAP
< LB
(4.2)
In pratica si decrementa l'upper bound di una quantit che dipende da esso. L'idea quella di non risolvere il problema se la dierenza tra
UB
LB
pi piccola di
una certa quantit ipotizzando che la soluzione ottima intera abbia un valore che si discosta da
UB
almeno di
UB . GAP
GAP
e pi
possibilit ci sono che la condizione (4.2) venga soddisfatta, evitando di risolvere il problema. Di fatto, per valori bassi di
GAP
CAPITOLO 4.
PROVE COMPUTAZIONALI
112
risolti e l'algoritmo molto prestante; tuttavia ci sono maggiori possibilit che venga tagliato parte dello spazio di ricerca in cui collocata la soluzione ottima. Aumentando il valore di
GAP ,
GAP
riferimento. Generalmente bene utilizzare valori bassi per problemi molto complessi per avere una prima buona soluzione in tempi comunque brevi. Successivamente possibile riapplicare l'algoritmo risolutivo con un
GAP
anche dal tempo limite che viene ssato per la risoluzione di un certo problema. Nelle nostre prove abbiamo utilizzato diversi approcci per capire come valorizzare il parametro
GAP
e ne verr fatta menzione quando saranno presentati i risultati Per tutte le istanze risolte
euristicamente, abbiamo utilizzato l'algoritmo EC senza distinzione delle cardinalit dei problemi durante la ricorsione.
GAP = 100.
Oltre al tempo di
elaborazione e alla miglior soluzione trovata, sono indicati anche la cardinalit della soluzione
Si osserva come il nostro algoritmo trova una soluzione decisamente migliore rispetto a quella di Chu e Beasley su tutte le 30 istanze risolte, in tempi relativamente brevi mediamente sotto l'ora. Inoltre bene precisare che l'algoritmo EC stato
condotto a termine no a che il Core non poteva pi essere espanso, nonostante la soluzione riportata in tabella sia stata ricavata generalmente molto prima. Per fare un esempio il valore 219984 relativo al problema 500.10.17 stato trovato dopo soli 1500 secondi contro i 10421 dell'intera elaborazione. Chiaramente possibile partire con
GAP
GAP = 50
ab-
biamo notato miglioramenti della soluzione in tempi dell'ordine dei minuti, anche se ovviamente non si raggiunge la qualit ottenuta con
GAP = 100.
Abbiamo di
seguito valutato il tempo impiegato per terminare l'algoritmo EC con per ripetere l'algoritmo con un nuovo valore di
GAP = 100
GAP .
il valore di poco quando il tempo di elaborazione gi piuttosto alto, mentre aumentarlo maggiormente sino a raddoppiarlo per istanze risolte in breve tempo. In tabella 4.14 sono riportati i nuovi valori della soluzione ottenuta con un
GAP
varia-
CAPITOLO 4.
PROVE COMPUTAZIONALI
113
Tabella 4.13: Risultati per le istanze 500.10 di P.C. Chu e J.E. Beasley con GAP = 100
Istanza 500.10.01 500.10.01 500.10.02 500.10.03 500.10.04 500.10.05 500.10.06 500.10.07 500.10.08 500.10.09 500.10.10 500.10.11 500.10.12 500.10.13 500.10.14 500.10.15 500.10.16 500.10.17 500.10.18 500.10.19 500.10.20 500.10.21 500.10.22 500.10.23 500.10.24 500.10.25 500.10.26 500.10.27 500.10.28 500.10.29
Risultato Chu e Beasley 117726 119139 119159 118802 116434 119454 119749 118288 117779 119125 217318 219022 217772 216802 213809 215013 217896 219949 214332 220833 304344 302332 302354 300743 304344 301730 304949 296437 301313 307014
Risultato
117790 119206 119215 118813 116509 119475 119790 118323 117781 119218 217377 219077 217797 216868 213846 215071 217931 219984 214382 220882 304387 302348 302416 300757 304357 301796 304952 296459 301357 307089
EC
K
134 136 136 137 135 137 139 135 136 137 256 259 256 259 256 256 260 257 257 254 379 380 380 378 380 376 377 379 379 378
GAP 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100
Tempo di elaborazione EC ( s ) 2445 1986 6744 2942 208 1343 9893 3786 201 1411 4243 1120 372 103 1543 964 213 10421 1032 3122 1534 524 1032 2653 4354 532 9321 3124 1033 212
CAPITOLO 4.
PROVE COMPUTAZIONALI
114
bile, dipendente dall'istanza. Come si osserva, in generale c' un incremento della soluzione rispetto al caso precedente, a scapito di un peggioramento computazionale considerato che il tempo medio di elaborazione passa da poco meno di un'ora a poco meno di tre ore.
GAP = 30
tempo medio per istanza pari a 1 ora. Abbiamo poi ristretto la condizione 4.2 con
GAP = 40
risultati delle prove eseguite sono riportati in tabella 4.15. Anche in questo caso si nota la dierenza tra la qualit delle soluzioni trovate dal nostro algoritmo con quelle dell'euristica di P.C. Chu e J.E. Beasley. Inoltre i valori calcolati con
GAP = 40,
in
molti casi, sono stati ottenuti molto prima delle 8 ore di tempo massimo pressato.
Per quanto riguarda il nostro algoritmo, abbiamo chiaramente utilizzato i risultati del metodo esatto per quanto riguarda le istanze 500.5, mentre per le 500.10 e 500.30 abbiamo considerato valore della soluzione e tempistiche relativi al metodo con pi elevato tra quelli proposti in precedenza. Come si pu notare, non c' assolutamente paragone per le istanze 500.5 per le
GAP
CAPITOLO 4.
PROVE COMPUTAZIONALI
115
Tabella 4.14: Risultati per le istanze 500.10 di P.C. Chu e J.E. Beasley con GAP variabile Risultato EC GAP = 100 117790 Risultato EC GAP = gap
Istanza 500.10.01 500.10.01 500.10.02 500.10.03 500.10.04 500.10.05 500.10.06 500.10.07 500.10.08 500.10.09 500.10.10 500.10.11 500.10.12 500.10.13 500.10.14 500.10.15 500.10.16 500.10.17 500.10.18 500.10.19 500.10.20 500.10.21 500.10.22 500.10.23 500.10.24 500.10.25 500.10.26 500.10.27 500.10.28 500.10.29
gap
110 120 100 110 150 120 100 110 150 120 110 120 200 150 120 150 150 100 150 150 200 200 120 150 150 150 100 150 150 150
K
136 135 136 137 135 137 139 135 136 137 256 259 256 259 256 257 260 257 257 255 379 380 380 379 380 376 377 380 379 378
119215
118813 116509
119206
119475
215071
304357
117809 119217 119215 118825 116524 119481 119790 118323 117781 119228 217377 219077 217847 216868 213861 215086 217931 219984 214382 220899 304387 302379 302416 300784 304374 301796 304952 296472 301357 307089
Tempo EC ( s ) GAP = gap 10220 4372 6744 5710 19324 11450 9893 5420 6128 6023 6421 2645 2846 3784 8621 4439 9432 10421 15694 23123 11712 9173 3542 13339 20701 15434 9321 14379 21347 8531
CAPITOLO 4.
PROVE COMPUTAZIONALI
116
Tabella 4.15: Risultati per le istanze 500.30 di P.C. Chu e J.E. Beasley con GAP = 30 e GAP = 40 Risultato Chu e Beasley 115868 114667 116661 115237 116353 115604 113952 114199 115247 116947 217995 214534 215854 217836 215566 215762 215772 216336 217290 214624 301627 299985 304995 301935 304404 296894 303233 306944 303057 300460 Risultato EC GAP = 40 Risultato EC GAP = 30
Istanza 500.30.01 500.30.01 500.30.02 500.30.03 500.30.04 500.30.05 500.30.06 500.30.07 500.30.08 500.30.09 500.30.10 500.30.11 500.30.12 500.30.13 500.30.14 500.30.15 500.30.16 500.30.17 500.30.18 500.30.19 500.30.20 500.30.21 500.30.22 500.30.23 500.30.24 500.30.25 500.30.26 500.30.27 500.30.28 500.30.29
K
GAP = 40 128 128 128 129 128 131 128 129 128 128 251 251 250 252 251 254 252 253 253 252 375 374 375 375 376 373 374 376 375 376
115947 114780 116699 115244 116449 115734 114107 114311 115419 117030 218056 214626 215896 217848 215613 215867 215883 216450 217340 214701 301648 300055 305069 302001 304413 296953 303322 306961 303168 300532
115947
114701
115244 115734
114058 116399
116682
115419
117023
114246
218033
302001 304413
296916 303299 306956
305045
300532
303162
CAPITOLO 4.
PROVE COMPUTAZIONALI
117
Tabella 4.16: Risultati comparativi per le istanze di P.C. Chu e J.E. Beasley 500.5, 500.10 e 500.30 [38] [39] EC
m
5
z
120 623 219 507 302 360 118 600 217 298 302 575 115 547 216 211 302 404
t [h]
5 5 5 9 9 9 12 12 12
z
120 628
t [h]
8.5 8.5 8.5 7.6 7.6 7.6 33 33 33
302 363 118 629 302 603 115 624 216 275 302 447
217 326
219 512
t [h]
0.1 0.1 0.1 2.5 2.5 3.5 8 8 8
10
30
quali neppure il metodo [39] in grado di trovare sempre l'ottimo pur con un tempo di elaborazione 100 volte superiore a quello impiegato dal nostro algoritmo. Per le istanze 500.10, i nostri risultati si avvicinano ai migliori noti ottenuti con [39] in un terzo del tempo. Inoltre per calcolata superiore. Per le istanze 500.30 la soluzione calcolata con [39] ha una qualit tale da non poter essere superata da quella ottenuta tramite il nostro algoritmo. Nonostante
questo la qualit delle soluzioni da noi trovate superiore a tutti gli altri metodi presenti in letteratura, tranne appunto [39], con tempi decisamente inferiori. Inoltre possibile ottenere soluzioni di qualit ancora migliore semplicemente aumentando il valore di
GAP .
un valore di 306999 al posto di 306961 con un tempo di elaborazione di 12 ore. Per concludere, bene far notare come l'approccio euristico da noi utilizzato sia molto semplice e pu essere notevolmente migliorato attraverso nuovi studi. Nel
CAPITOLO 4.
PROVE COMPUTAZIONALI
118
4.3.5 Risultati per le istanze P.C. Chu e J.E. Beasley 250.10, 100.30, 250.30
Per completezza riportiamo i risultati per le rimanenti istanze di P.C. Chu e J.E. Beasley. Per le istanze 100.30 abbiamo applicato l'algoritmo EC con un Per le istanze 250.30 siamo partiti con
GAP = 30
ad un tempo di elaborazione massimo per istanza di 2 ore. Per le istanze 250.10 stato usato un
GAP = 100.
il valore ottimo, calcolato con il nostro algoritmo esatto. Di fatto si pu procedere ad un confronto pi oggettivo tra la soluzione ottima e quella trovata dalla nostra euristica. Si osserva dai risultati riportati in tabella 4.17 che per 28 delle 30 istanze elaborate l'algoritmo euristico trova la soluzione ottima (calcolata con il metodo esatto mediamente in 10 ore) in un tempo medio pari a 15 minuti.
CAPITOLO 4.
PROVE COMPUTAZIONALI
119
Tabella 4.17: Istanze 250.10 di P.C. Chu e J.E. Beasley Istanze Risultato EC GAP = 100 Tempo elaborazione EC - GAP = 100 ( s) 1181 3370 780 1910 6254 149 35 2550 888 1085 Tempo elaborazione EC - GAP = 100 ( s) 882 931 870 250 798 223 2240 701 363 334 Tempo elaborazione EC - GAP = 100 ( s) 314 1833 205 353 427 122 157 445 465 312
( = 0.25)
250.10.00 250.10.01 250.10.02 250.10.03 250.10.04 250.10.05 250.10.06 250.10.07 250.10.08 250.10.09 Istanze
Ottimo
59187 58781 58097 61000 58092 58824 58704 58936 59387 59208
Ottimo
( = 0.5)
250.10.10 250.10.11 250.10.12 250.10.13 250.10.14 250.10.15 250.10.16 250.10.17 250.10.18 250.10.19 Istanze
110913 108717 108932 110086 108485 110845 106077 106686 109829 106723
Ottimo
110894
( = 0.75)
250.10.20 250.10.21 250.10.22 250.10.23 250.10.24 250.10.25 250.10.26 250.10.27 250.10.28 250.10.29
151809 148772 151909 151324 151966 152109 153131 153578 149160 149704
151809 148772 151909 151324 151966 152109 153131 153578 149160 149704
CAPITOLO 4.
PROVE COMPUTAZIONALI
120
Tabella 4.18: Risultati per le istanze 100.30 di P.C. Chu e J.E. Beasley con GAP = 30
Istanza 100.30.00 100.30.01 100.30.02 100.30.03 100.30.04 100.30.05 100.30.06 100.30.07 100.30.08 100.30.09 100.30.10 100.30.11 100.30.12 100.30.13 100.30.14 100.30.15 100.30.16 100.30.17 100.30.18 100.30.19 100.30.20 100.30.21 100.30.22 100.30.23 100.30.24 100.30.25 100.30.26 100.30.27 100.30.28 100.30.29
Risultato
41041 40872 41058 41062 42719 42230 41700 57494 60027 58025 60776 58884 60011 58132 59064 58975 60603
41560
21946 21716 20754 21464 21844 22176 21799 21397 22525 20983 40767 41308 41630 41041 40872 41062 42719 42230 41700 57494 60027 58052 60776 58884 60011 58132 59064 58975 60603
41028
EC
k
24 25 24 24 24 24 25 24 24 24 49 49 50 50 49 49 49 49 49 49 73 73 74 74 74 74 74 74 74 73
GAP 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30
Tempo di elaborazione EC ( s ) 61.1 171.4 63.9 97.4 229.0 179.9 353.5 360.2 481.7 49.6 150.0 294.4 95.0 91.2 104.5 102.6 66.8 80.7 25.6 60.5 34.4 42.8 57.7 32.8 41.9 41.8 44.1 54.5 65.9 39.8
CAPITOLO 4.
PROVE COMPUTAZIONALI
121
Tabella 4.19: Risultati per le istanze 250.30 di P.C. Chu e J.E. Beasley con GAP = 30
Istanza 250.30.00 250.30.01 250.30.02 250.30.03 250.30.04 250.30.05 250.30.06 250.30.07 250.30.08 250.30.09 250.30.10 250.30.11 250.30.12 250.30.13 250.30.14 250.30.15 250.30.16 250.30.17 250.30.18 250.30.19 250.30.20 250.30.21 250.30.22 250.30.23 250.30.24 250.30.25 250.30.26 250.30.27 250.30.28 250.30.29
Risultato Chu e Beasley 56693 58318 56553 56863 56629 57119 56292
Risultato
57442
56447 107689 108338 106385 106796 107398 107246 106308 103993
56403
56824 58520 56572 56930 56629 57189 56303 56457 56447 107746 108379 106415 106855 107414 107271 106365 104013 106835 150138 149907 153007 153234 150287 148559 146477 152877 149570 149601
105733 57429
EC
k
63 65 63 63 63 63 63 63 63 63 125 124 124 124 125 126 125 124 123 125 187 186 187 186 186 186 186 186 186 186
GAP 40 30 30 40 40 30 30 30 30 40 30 30 30 40 40 40 40 40 40 40 30 30 40 30 40 40 40 30 40 30
Tempo di elaborazione EC ( s ) 7200 5640 3544 2832 7200 2002 7200 444 5630 1213 825 528 292 7200 804 2132 3125 7200 3561 7200 240 293 1856 398 895 7200 807 308 1104 485
105751
150083 149907 152993 153169 150287 148544 147471 152841 149568 149572
106835
Capitolo
5.1
Il Packager mkp.*
I package java sono dei contenitori ttizi di classi, interfacce e altri packages, utili per rappresentare in modo gerarchico la struttura del software java. All'interno
di uno stesso package sono contenuti elementi con funzionalit ani, solitamente riconducibili al nome stesso del package. Per quanto concerne il nostro software ci siamo avvalsi della ripartizione delle classi schematizzata in gura 5.1. I packages sono rappresentati tramite dei rettangoli ombreggati. Ogni package contiene pi classi e in italico sono evidenziate le interfacce. La funzionalit di ogni package viene descritta in seguito:
122
CAPITOLO 5.
123
Figura 5.1: Struttura gerachica delle classi che costituiscono il nostro software
CAPITOLO 5.
124
mkp.solver.AAR : contiene le classi che implementano l'algoritmo AAR mkp.solver.RR : contiene le classi che implementano l'algoritmo RR mkp.problem : il package in cui sono inserite le classi che immagazzinano i
dati che descrivono il problema
mkp.euristic a:
mkp.util : contiene classi di utilit generale, in particolar modo per l'ordinamento dei vettori che contengono i dati del problema (prezzi, beni, costi ridotti ecc.)
mkp.relax :
mkp.cut : contiene i generatori di tagli da applicare ai vari rilassamenti mkp.cut.LCI : un package che fornisce le classi per implementare le Lifted Cover Inequalities, locali e globali
Sebbene, avendo denito l'algoritmo in modo rigoroso, sia possibile esplicitare concretamente gli elementi strutturali che lo compongono, si deciso di costruire una struttura dinamica facilmente estendibile per aumentare la essibilit e la robustezza del software, sopratutto in vista di modiche ed estensioni future. Le scelte
implementative adottate, ben supportate dall'utilizzo di un linguaggio orientato agli oggetti, sono indirizzate alla creazione di una struttura portante dell'algoritmo in cui l'inserimento di moduli aggiuntivi, implementati ad hoc dall'utente, sia semplicato il pi possibile. L'utilizzo di numerose interfacce permette ai vari componenti software
CAPITOLO 5.
125
di accedere a servizi generici, i cui risultati dipendono dalle singole implementazioni. In particolare possibile:
Generator. Essa fornisce i metodi per istanziare un oggetto della classe Cut
che pu essere aggiunto a qualunque rilassamento tramite lo specico metodo
addTaglio().
creare diversi tipi di rilassamento, oltre a quello continuo utilizzato nel nostro algoritmo, implementando l'interfaccia MKPRilassamento.
implementare dierenti sistemi di acquisizione dei dati del problema a seconda di come questi sono organizzati all'interno del le tramite l'interfaccia
MKPInput.
sviluppare nuove euristiche, implementando l'interfaccia MKPEuristica, per calcolare lower bound ecaci per il problema
implementare diversi algoritmi di ordinamento dei vettori in cui sono contenuti i dati relativi al problema implementando l'interfaccia Ordinamento
creare nuovi enumeratori delle soluzioni tramite albero di ricerca, completamenti diversi dall'algoritmo AAR, implementando l'interfaccia Enumerator
Qualora si voglia continuare la ricerca iniziata con questo lavoro di tesi, l'aver utilizzato un linguaggio come Java rende decisamente semplice l'aspetto pratico dell'applicazione delle estensioni, in quanto si riduce ad una comprensione della collaborazione tra le classi. Se si seguono le poche linee guida dettate dal rispetto dei metodi offerti dalle varie interfacce, la quasi totalit del lavoro di sviluppo si focalizza sulla creazione di nuovi moduli, senza doversi preoccupare di come interfacciare queste nuove funzionalit all'interno del software preesistente.
5.2
Pseudocodice dell'algoritmo
Il capitolo 3 ore una descrizione formale degli aspetti algoritmici della metodologia di risoluzione proposta. Di seguito ci occuperemo di sintetizzare attraverso uno
CAPITOLO 5.
126
CAPITOLO 5.
127
CAPITOLO 5.
128
nostro software interagiscono per risolvere un problema seguendo la strategia dettata dall'algoritmo da noi proposto. L'idea quella di presentare solo i metodi che permettono alle classi di collaborare fra loro, evitando di formalizzare funzionalit e servizi di utilit varia la cui comprensione del tutto intuitiva anche senza una precisa descrizione. Questo stato fatto per evitare di non perdere il focus sul cuore dell'algoritmo considerando l'alto numero di classi di cui il software costituito. Qualora si voglia entrare maggiormente in dettaglio sugli aspetti puramente implementativi, il codice sorgente sviluppato durante questo lavoro di tesi stato scritto seguendo i principi di leggibilit della programmazione e commentato in modo approfondito. Lo pseudocodice riportato in seguito stato scritto seguendo alcuni criteri in modo da poter essere facilmente leggibile nel contesto del paradigma a oggetti, in cui spesso si ha a che fare con variabili e altri oggetti contenuti nella classe del metodo analizzato e non passati come argomenti al metodo stesso. In particolare, per ogni metodo, vengono specicati gli elementi esterni ai quali il metodo pu referenziarsi tramite la keyword Require. Con la parola chiave Ensure, si indicano tutte le strutture dati (semplici o complesse) che in qualche modo vengono modicate dal metodo. Inoltre, prima di procedere con i costrutti implementativi del metodo, vengono elencati tutti gli oggetti creati all'interno dal metodo con la relativa classe di appartenenza. Inne, i metodi invocati su questi oggetti, sono scritti in modo
CAPITOLO 5.
129
5: 6: 7: 8: 9:
10)
and
10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
else
CAPITOLO 5.
130
SolverCardNonDistinte : viene istanziato un oggetto CoreManager che si occupa di creare il core del problema ed espanderlo. Per far questo vengono passati come argomenti il problema da risolvere, il lower bound (che inizialmente uguale a 0), la cardinalit dell'allocazione (in questo caso 0 signica che devono essere analizzate tutte le cardinalit) e la dimensione del Core. Il risolutore
SolverCardDistinte : si calcola un lower bound iniziale istanziando un CoreManager e risolvendo il problema riformulato con core minimale. Il lower bound
trovato, attraverso le classi MinCardProblemRelax e MaxCardProblemRelax, permette di determinare la cardinalit minima e massima dell'allocazione ottima delle oerte. Si costruisce in seguito un vettore di istanze di CoreMan-
ager, ognuno inizializzato con la propria cardinalit, compresa tra minCard e maxCard, e il proprio ordinamento delle oerte. Ogni CoreManager risolve il
problema riformulato con core minimale: qualora non sia possibile costruire un core minimale in quanto il vincolo RCC viene violato, l'istanza non viene salvata nella lista e la cardinalit relativa viene scartata in quanto sicuramente non ottima. Una volta costruito il vettore, si esegue il metodo continuaEse-
anager viene eliminato dal vettore in quanto il problema con cardinalit a lui
associato stato risolto. Il procedimento viene iterato no a quando non ci
init() per creare il Core. A sua volta questo metodo invoca il metodo interno create-
CAPITOLO 5.
131
DIM_CORE
3: 4: 5: 6: 7:
repeat
core.setLB(LB) if core.continuaEsecuzione() =
break esci dal ciclo se il core non pu essere pi espanso end if if core.getLB() > LB then
LB core.getLB()
aggiorno il lower bound
false then
17:
CAPITOLO 5.
132
Algorithm 3 SolverCardDistinte.solve( MKPProblem problema ) - PARTE 1 Require: DIM_CORE 1: int LB, ottimo 2: CoreManager core 3: MinCardProblemRelax minCardRelax 4: MaxCardProblemRelax maxCardRelax 5: int ordine
6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
LB 0 core new CoreM anager(problema, DIM _CORE, 0, LB) core.init() core.processa() LB core.getLB() minCardRelax new M inCardP roblemRelax(problema, LB) maxCardRelax new M axCardP roblemRelax(problema, LB) minCardRelax.solve() maxCardRelax.solve() int minCard minCardRelax.getValoreFunzioneObiettivo() int maxCard maxCardRelax.getValoreFunzioneObiettivo() int media (minCard + maxCard)/2 int card maxCard List solutori new List()
20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30:
repeat
ordine ORDIN AM EN T O_P REZZI if card > media then ordine ORDIN AM EN T O_BEN I
end if
core new CoreM anager(problema, DIM _CORE, card, LB, ordine) core.init() if core.isStop() = false then core.processa() if core.getLB() > LB then LB core.getLB() aggiorno il lower bound
CAPITOLO 5.
133
end if end if
solutori.aggiungi(core)
36: 37: 38: 39: 40: 41: 42: 43: 44: 45:
else
false then
46:
CAPITOLO 5.
134
OutCore() che accetta come parametri di ingresso il problema di partenza e la cardinalit. A livello implementativo viene creato un oggetto di tipo OutCore che contiene le strutture dati per le variabili esterne al Core. Si procede con la creazione di un oggetto MKPRilassamentoContinuo, implementazione dell'interfaccia MKPRilassa-
mento, a cui si aggiunge eventualmente il taglio di cardinalit attraverso il metodo addTaglio() qualora la cardinalit sia diversa da 0. Il metodo solve() di MKPRilassamento risolve il rilassato, il cui valore ottimo viene restituito tramite il metodo getValoreFunzioneObiettivo().
Quest'interfaccia dispone anche del metodo getCo-
stiRidotti() per avere il vettore dei costi ridotti delle variabili. I costi ridotti vengono
poi ordinati in ordine decrescente e vengono selezionati quelli pi alti in valore assoluto. Di quest'ultimi, vengono creati oggetti di tipo Variabile che memorizzano oltre all'indice della variabile, il prezzo e il costo ridotto. Tali oggetti vengono aggiunti ad
Enumerator. Di questa interfaccia sono fornite due implementazioni, AAREnumerator e AAROneCardEnumerator, entrambe basate sull'algoritmo AAR. La prima
risolve il problema considerando tutte le cardinalit possibili per l'allocazione ottima, la seconda solo per la cardinalit in ingresso. Si osservi che la cardinalit del problema riformulato ottenuta sottraendo alla cardinalit di partenza il numero delle variabili settate a 1 nell'OutCore. Entrambe le classi necessitano in ingresso, oltre al problema, del lower bound, del termine noto del vincolo RCC e dei costi ridotti, tutte informazioni necessarie per l'applicazione dei tagli. AAROneCardEnu-
CAPITOLO 5.
135
end if
ordinaCostiRidottiDecrescenti(costiRidotti,indiciVariabili)
outCore new OutCore() int cont1 1 int cont2 problema.getNumeroVariabili() int contV ar 0
18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28:
else
index cont2; cont2 cont2 1 p problema.getPrezzoVariabile(indiciV ariabili[index]) Variabile var newV ariabile(indiciV ariabili[index], p, costiRidotti[index]) outCore.addVarOutCore(var) contV ar contV ar + 1 until problema.getNumeroVariabili() DIM _CORE < contV ar
end if
CAPITOLO 5.
136
la risoluzione del problema e il metodo getOttimo() per ottenere l'ottimo trovato. Il lower bound iniziale LB del problema ottenuto sommando l'ottimo del problema riformulato con il prezzo delle variabili settate a 1 nell'OutCore, quest'ultimo calcolato grazie al suo metodo getPrezzo() (algoritmo 6).
OutCore che rimuove la variabile con costo ridotto in valore assoluto pi piccolo
tra tutte quelle escluse dal Core. Viene successivamente istanziato un oggetto di
tipo CoreRRManager passando come parametri di input il problema di partenza, l'OutCore, i costi ridotti, il lower bound, l'upper bound e l'eventuale cardinalit dell'allocazione ottima. La risoluzione del problema con il nuovo Core espanso,
viene eseguita invocando il metodo processa() di CoreRRManager. Il CoreManager valuta l'esito della risoluzione invocando il metodo getStato() del CoreRRManager. A seconda del valore restituito, il metodo continuaEsecuzione() aggiorna il lower bound e restituisce true, se al core si possono aggiungere ulteriori variabili, false se l'espansione del Core da considerarsi terminata (algoritmo 7).
varFissate che viene passata in ingresso, insieme al problema riformulato, al metodo isFixable(). Tale metodo restituisce true o false a seconda se la variabile pu essere
CAPITOLO 5.
137
MKPRilassamento relax Enumerator e MKPProblem rif ormulato int LB List varOutCore outCore.getVarOutCore()
rif ormulato problema.creaProblemaVariabiliNonFissate(varOutCore) if card <> 0 then Cut taglioCard generaTaglioCardinalita(problema, card) relax.addTaglio(taglioCard)
end if
relax.solve() LB 0 double U B relax.getValoreFunzioneObiettivo() double termineN otoRCC U B LB int nuovaCard card outCore.getVarCrPositivo()
16: 17:
if
18: 19:
else
card <> 0 then e new AAROneCardEnumerator(rif ormulato, LB, relax.getCostiRidotti(), range, nuovaCard, EN U M ERAZION E _BEN I) e new AAREnumerator(rif ormulato, relax.getCostiRidotti(), range) LB,
20:
end if
21: 22:
CAPITOLO 5.
138
1:
2: 3: 4: 5:
then
outCore.removeLastVar() problema.setLB(LB) rcc new CoreRRM anager(costiRidotti, indiciV ariabili, U B, LB, problema, card, ordine, outCore) rcc.processa()
espansione del core
6: 7:
8:
if
return true else if rcc.getStato() = ESP AN SION E _CORE _T ERM IN AT A then return false else return true end if
then
CAPITOLO 5.
139
MKPProblem rif ormulato double[] costiRidotti int[] indiciV ariabili int stato, var List varF issate
ordinaCostiRidottiDecrescenti(costiRidotti,indiciVariabili)
card backupCard if costiRidotti[1] > costiRidotti[problema.getNumeroVariabili()] if costiRidotti[1] > termineN otoRCC then stato ESP AN SION E _CORE _T ERM IN AT A
then
exit end if
var indiciV ariabili[cont1]
interrompi esecuzione
else if then
interrompi esecuzione
varF issate fixAltreVariabili(var, rif ormulato, costiRidotti, indiciV ariabili) if isFixable(varF issate, rif ormulato) = true then stato LB _N ON _M IGLIORAT O
else
end if
CAPITOLO 5.
140
ssata al valore opposto a quello a cui stata temporaneamente settata. Nel contesto del CoreRRManager, se la variabile viene ssata signica che il lower bound del problema non migliorato, e si ssa la variabile stato a LB_NON_MIGLIORATO. Viceversa, se la variabile pu essere ssata, il lower bound migliorato e di fatto la variabile stato viene valorizzata a LB_MIGLIORATO. La variabile stato viene restituita tramite il metodo getStato() che lo stesso invocato dal CoreManager per vericare l'esito dell'espansione del Core (algoritmo 8).
xDiretto() tiene traccia sia del numero di variabili settate (variabiliFissate ) sia della
nuova cardinalit di analisi del problema (backupCard ) (algoritmo 9). Successivamente viente invocato il metodo xIndiretto() la cui implementazione dierisce da quella della classe CoreRRManager. In questo caso, infatti, l'idea Di
quella di cercare di ssare pi variabili e non solo l'ultima inserita nel Core.
volta in volta viene selezionata la variabile con costo ridotto in valore assoluto pi elevato e salvata temporaneamente in var. Se non ci sono pi variabili con costo
ridotto positivo si setta neCrPos a true ; analogamente se non ci sono pi variabili con costo ridotto negativo si setta neCrNeg a true. Selezionata la variabile, viene chiamato il metodo xAltreVariabili() a cui si passano come argomenti la variabile stessa, il problema, i costi ridotti con i relativi indici delle variabili e i vettori xed,
varFissate e varFissateTemp.
CAPITOLO 5.
141
Algorithm 9 RRManager.xDiretto() Require: problema, costiRidotti, indiciV ariabili, backupCard, termineN otoRCC Ensure: variabiliF issate, backupCard
1:
int variabiliF issate 0 for i = 1, costiRidotti.size(), i i + 1 do if costiRidotti[i] > termineN otoRCC then
problema.fix(indiciV ariabili[i], 1) backupCard backupCard 1 variabiliF issate variabiliF issate + 1
2: 3: 4: 5: 6: 7: 8: 9: 10:
else break end if end for for i = costiRidotti.size(), 1, i i 1 do if costiRidotti[i] > termineN otoRCC then
problema.fix(indiciV ariabili[i], 1) variabiliF issate variabiliF issate + 1
CAPITOLO 5.
142
Algorithm 10 RRManager.xIndiretto() - PARTE 1 Require: problema, backupCard, termineN otoRCC, variabiliF issate Ensure: stato, LB, backupCard
1: 2: 3: 4: 5: 6:
MKPProblem rif ormulato double[] costiRidotti int[] indiciV ariabili int stato, var, card, cont List varF issate, varF issateT emp boolean f ineCrP os false f ineCrN eg false
ordinaCostiRidottiDecrescenti(costiRidotti,indiciVariabili)
int cont1 1 int cont2 problema.getNumeroVariabili() repeat
14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27:
card backupCard boolean esegui true if (costiRidotti[cont1] > costiRidotti[cont2] f ineCrN eg = true then cont cont1 var indiciV ariabili[cont1] if costiRidotti[cont1] <= 0 then esegui false f ineCrP os true
end if else
end if end if
cont cont2 var indiciV ariabili[cont2] if costiRidotti[cont2] >= 0 then esegui false f ineCrN eg true
CAPITOLO 5.
143
if
else
end if
variabiliF issate variabiliF issate + 1
= true) problema.getNumeroVariabili() M AX _V AR
else *gestione variabili non ssate* *aggiornamento lower bound* end if end if until (f ineCrP os = true and f ineCrN eg
or
for i = 1, varF issate.size() do ssa le variabili al problema padre int indiceP adre rif ormulato.getIndicePadre(varF issate[i].indice) end for
problema.fix(indiceP adre, varF issate[i].valore)
CAPITOLO 5.
144
Il metodo xAltreVariabili() restituisce la nuova cardinalit del problema dopo il settaggio temporaneo delle variabili. Per vericare se la variabile var pu essere ssata ad un certo valore, si invoca il metodo isFixable(), passando come argomento, oltre al problema, il vettore varFis-
sateTemp. Se l'esito positivo, la variabile var viene ssata a 1 qualora il suo costo
ridotto sia positivo, a 0 se il costo ridotto negativo. In entrambi i casi viene aggiunta nella lista varFissate, si aggiorna il vettore xed e si incrementa il valore di
xAltreVariabili:
costo ridotto negativo e a 0 se positivo, aggiungendola al vettore varFissateTemp e aggiornando il termineNotoRCC ora salvato in nuovoTermineNotoRCC. Viene eseguita una scansione intelligente del vettore costiRidotti e vengono ssate a 1 tutte le variabili con costo ridotto superiore a nuovoTermineNotoRCC e a 0 quella con costo ridotto inferiore a nuovoTermineNotoRCC cambiato di segno. In entrambi i casi il ssaggio viene eseguito per non violare il vincolo RCC e si realizza semplicemente aggiungendo le variabili interessate nel vettore varFissateTemp. Inne in questa lista vengono anche aggiunte tutte le variabili sicuramente ssate, contenute in varFissate (algoritmo 12).
isFixable:
della variabile var selezionata all'interno di xIndiretto(). Il prezzo complessivo delle variabili contenute in varFissateTemp e valorizzate a 1 viene salvato in valoreFissato. Si costruisce il problema ottenuto eliminando le variabili presenti in varFissateTemp dalla sua formulazione. Il lower bound del nuovo problema cos ottenuto uguale
CAPITOLO 5.
145
Algorithm 12
varFissateTemp )
double[] costiRidotti,
boolean[] xed,
3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25:
else
end if
f ixed[indiciV ariabili[var]] true while costiRidotti[cont1] > nuovoT ermineN otoRCC do if cont1 <> var and f ixed[indiciV ariabili[cont1]] = false then varF issateT emp.add(newV ariabile(indiciV ariabili[cont1], 1))
end if
cont1 cont1 + 1
end while while costiRidotti[cont2] < nuovoT ermineN otoRCC do if cont2 <> var and f ixed[indiciV ariabili[cont2]] = false then varF issateT emp.add(newV ariabile(indiciV ariabili[cont2], 0)) end if
cont2 cont2 1
26: 27:
end for
CAPITOLO 5.
146
Require:
1: 2: 3:
4:
5: 6: 7: 8: 9: 10:
for i = 0, varF issateT emp.size() do if varF issaT emp[i].valore = 1 then end if end for
valoreF issato valoreF issato + rif ormulato.getPrezzoVariabile(varF issateT emp[i].indice)
LB LB valoreF issato ridotto rif ormulato.creaProblemaVariabiliNonFissate(varF issateT emp) ridotto.setLB(LB) relax newM KP RilassamentoContinuo(ridotto)
if
end if
relax.solve()
CAPITOLO 5.
147
if
then
*aggiorno il lower bound* return false else return true end if end if
ridotto.getNumeroVariabili() <= M AX _V AR then esito risolviConAAR(relax, ridotto, LB, card) if esito = LB _M IGLIORAT O then
sso la variabile
sso la variabile
CAPITOLO 5.
148
al lower bound del problema di partenza diminuito di valoreFissato. Di questo problema si calcola il rilassamento continuo, con eventuale vincolo di cardinalit, nel consueto modo. Viene poi vericata la condizione di rilassamento per la valutazione del problema in cui entra in gioco il parametro GAP. Se la condizione non vericata il problema deve essere risolto. Qualora il numero di variabili sia minore
risolviConRR().
problema, il suo lower bound e l'eventuale cardinalit da analizzare. Se l'esito del metodo coincide con LB_MIGLIORATO, si aggiorna il lower bound e il metodo is-
Fixable() restituisce false. In caso contrario viene ritornato il valore true (algoritmi
13 e 14).
risolviConAAR:
tramite l'applicazione dell'algoritmo AAR. Per prima cosa in base al valore dell'upper bound e del lower bound viene calcolato il valore di nuovoTermineNotoRCC che, se negativo, evita di risolvere il problema. In seguito vengono fatte alcune valutazioni sulla cardinalit da analizzare. Se la variabile di classe cardDistinte, valorizzata in fase di istanziazione di RRManager, posta a true, signica che stato adottato un approccio che prevede la risoluzione di tanti problemi distinti, uno con la propria cardinalit. Questa cardinalit salvata in card, anch'essa input del metodo. Ovviamente il valore di card deve essere superiore al numero di variabili del problema. Si istanzia un oggetto Enumerator, in particolare AAREnumerator se cardDistinte uguale a false o AAROneCardEnumerator altrimenti. In quest'ultimo caso, necessario che il valore di card sia compreso tra la cardinalit minima e quella massima dell'allocazione ottima, ottenute invocando rispettivamente i metodi getCardMin() e getCardMax() dell'oggetto Enumerator. Si risolve il problema invocando il metodo solve() di Enumerator e si ottiene il valore ottimo tramite getOttimo(). Se quest'ultimo superiore al lower bound corrente, si aggiorna il valore di LB. In tutti i casi la risoluzione del problema non garantisce un ottimo superiore al lower bound, il metodo restituisce LB_NON_MIGLIORATO. (algoritmo 15).
risolviConRR:
l'applicazione dell'algoritmo RR e costituisce il punto in cui avviene di fatto l'esecuzione ricorsiva dell'algoritmo stesso. Quello che viene eseguito semplicemente
CAPITOLO 5.
149
Algorithm 15 Require:
1: 2:
cardDistinte, ordine
3: 4: 5: 6: 7: 8: 9: 10: 11:
end if if cardDistinte = true and card > ridotto.getNumeroVariabili() then return LB _N ON _M IGLIORAT O end if if cardDistinte = true then e new AAROneCardEnumerator(ridotto, LB,
relax.getCostiRidotti(), nuovoT ermineN otoRCC, card, ordine)
12: 13:
else
14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28:
end if if e.getCardMin() > e.getCardMax() then return LB _N ON _M IGLIORAT O end if if cardDistinte = true then if e.getCardMin()> card or e.getCardMax()< card then return LB _N ON _M IGLIORAT O end if end if
e.processa() if e.getOttimo() < LB then return LB _N ON _M IGLIORAT O
CAPITOLO 5.
150
Require:
1: 2: 3: 4:
cardDistinte, ordine
5: 6: 7: 8: 9:
end if
10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26:
rcc new RRM anager(relax.getCostiRidotti(), relax.getValoreFunzioneObiettivo(), LB, problema, card, ordine) rcc.processa() RCC ssa alcune variabili al problema ridotto problema.creaProblemaVariabiliNonFissate() ridottoRelax new M KP RilassamentoContino(ridotto) if cardDistinte = true then Cut taglioCard generaTaglioCardinalita(ridotto, card) ridottoRelax.addTaglio(taglioCard)
end if
ridottoRelax.solve() ridottoLB LB problema.getPrezzoVariabiliFissate() ridottoCard rcc.getCard() esito risolviConAAR(ridottoRelax, ridotto, ridottoLB, ridottoCard) if esito = LB _M IGLIORAT O then
sso la variabile
CAPITOLO 5.
151
istanziare un nuovo oggetto di tipo RRManager, relativo al problema ridotto dopo il settaggio, anche temporaneo, di alcune variabili. Se cardDistinte uguale a false, il valore di card viene posto a 0 in modo che anche nel livello ricorsivo pi basso il problema possa essere trattato in tutte le sue cardinalit. Invocando il metodo processa() del nuovo oggetto RRManager, il problema viene ridotto ulteriormente ad una dimensione massima di MAX_VAR variabili. Questo nuovo problema ora pu essere tranquillamente risolto con AAR tramite il metodo risolviConAAR() (algoritmo 16).
strutture dati necessarie per applicare i tagli tramiti i metodi initProcessaPrezzi() e initProcessaBeni() per poi iniziare con l'enumerazione vera e propria tramite i metodi processaPrezzi() e processaBeni(). Nel caso di AAROneCardEnumerator suciente scegliere una delle due modalit di enumerazione delle soluzioni in base alla variabile di classe ordine. Analizziamo ora come strutturato l'algoritmo di enumerazione delle soluzioni per ordinamento decrescenti dei prezzi delle variabili, tenendo presente che quello per beni crescenti del tutto analogo. un'allocazione x di card oerte. L'intero algoritmo ha il compito di creare
Il contenuto di
x [cont]
locata nella posizione cont. Si inizia con la chiamata del metodo iteraPrezzi() che accetta come parametri cont, card e inizio, corrispondente all'indice dell'oerta, nel vettore ordinato, che si vuole cercare di allocare (inizialmente sar la prima oerta, di indice 0). Questo metodo aggiorna il vettore x no ad ottenere un'allocazione, anche parziale, che soddisfa tutti i vincoli e che abbia un valore migliore del lower bound corrente. Inoltre restituisce la posizione della prossima oerta da allocare in
CAPITOLO 5.
152
Algorithm 17 AAREnumerator.processaPrezzi( int card ) Require: problema, LB, x Ensure: cardOttima, LB, ottimo
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30:
int cont iteraPrezzi(cont,card,0) int num problema.getNumeroVariabili()1 int tempCont cont repeat
ottimo storicoP rezzoP arziale[card] LB ottimo if card = cont then cardOttima card
*copia soluzione ottima* end if if x[0] > problema.getNumeroVariabili()card then break nessuna allocazione futura end if
cont cont 1; dif f card cont; dif f T emp 0 if cont = card 1 then dif f 0
end if while true do if num x[cont] >= dif f then break end if
dif f dif f + 1; cont cont 1
end while
xT emp x[cont] for i = cont, tempCont x[i] 0
do
end for
CAPITOLO 5.
153
Require:
1:
2: 3: 4: 5:
then
allocazione full
6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22:
if taglioPrezzi(card, cont, i) = true then int dif f erenza 2 while true do break end if if temp i > dif f erenza then break else if temp i = 2 then
dif f erenza 1
23:
24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34:
temp i while i < problema.getNumeroVariabili()1 do if beni[indiceP rezzi[i + 1] > beni[indiceP rezzi[temp] ii+1
then
CAPITOLO 5.
154
if
costiRidotti[indiceP rezzi[i]] <= 0 then temp rangeT ermineN otoRCC[cont] + costiRidotti[indiceP rezzi[i]] if temp < 0 then
*passa all'iterazione successiva* end if if taglioRCC(i, temp) = true then *passa all'iterazione successiva* end if
else
rangeT ermineN otoRCC[cont + 1] temp rangeT ermineN otoRCC[cont + 1] rangeT ermineN otoRCC[cont]
end if
50:
then
sommaV incoli[j][cont + 1] sommaV incoli[j][cont]+ problema.getPesoVariabileVincolo(j, indiceP rezzi[i]) if sommaV incoli[j][cont + 1] > problema.getCapacitaVincolo(j)
break end if end for if ok = false then *passa all'iterazione successiva* end if if taglioVincoli(card, cont, i) = true then *passa all'iterazione successiva* end if end for
x[cont] i; cont cont + 1
ok false
61: 62:
63:
return cont
CAPITOLO 5.
155
essere generata una nuova allocazione, altrimenti il metodo termina l'esecuzione in quanto tutte le allocazioni con quella cardinalit sono state analizzate. Viene in seguito calcolata la nuova allocazione parziale da cui partire aggiornando sia il valore di cont che il valore di inizio, coincidente con
x [cont] + 1.
Viene quindi
chiamato nuovamente il metodo iteraPrezzi(), questa volta sui nuovi valori aggiornati. L'intero procedimento viene iterato no a quando le allocazioni da analizzare sono terminate (algoritmo 17). Il metodo iteraPrezzi() costruisce l'allocazione vera e propria aggiornando il vettore x. All'interno di un ciclo con indici dinamici avviene al pi l'allocazione di una singola oerta per ogni iterazione, con il calcolo dei nuovi valori di cont e inizio. L'indice i del ciclo corrisponde all'indice dell'oerta che deve essere allocata. Se
tazione dei tagli non viene riportata in quanto descritta in dettaglio nel Capitolo 3. I metodi taglioPrezzi(), taglioBeni(), taglioRCC() e taglioVincoli() accettano come parametri card, cont e i e restituiscono true se il taglio risultato ecace. In questo caso vengono calcolati i nuovi valori di card e inizio terminando l'iterazione corrente (senza aggiungere l'oerta nell'allocazione) e passando a quella successiva. E' in questo punto che l'indice del ciclo viene modicato all'interno del suo corpo. Il metodo termina l'esecuzione o quando si raggiunta un'allocazione full o quando sono state valutate, per la posizione cont, tutte le oerte rimanenti, ossia quando l'indice del ciclo settato all'ultima variabile (algoritmi 18 e 19).
CAPITOLO 5.
156
In particolar modo vengono forniti i seguenti metodi, ognuno con i propri parametri di ingresso:
creaEnumerator() : Enumerator
creaInput() : crea l'istanza di una classe che implementa l'interfaccia MKPInput creaEuristica() : crea l'istanza di una classe che implementa l'interfaccia MKPEuristica
A seconda dell'implementazione di MKPFactory, i relativi metodi istanziano e restituiscono oggetti di classi dierenti, le quali rappresentano diverse implementazioni della stessa interfaccia. Per fare un esempio, nell'mplementazione utilizzata concretamente (MKPTesiFactory ) il metodo creaInput() restituisce un istanza di MKPIn-
putBeasley e il metodo creaAlgoritmoOrdinamento() un istanza di Heap. All'implementazione specica di MKPFactory, tutte le classi del software accedono tramite la classe statica MKPRepository che fornisce un metodo getFactory(). Ogni qualvolta uno degli oggetti sopra elencati deve essere istanziato, la creazione non avviene direttamente nella classe che lo utilizza ma viene demandata alla factory. La comunicazione avviene tramite dei servizi (i metodi dell'interfaccia) a prescindere dall'implementazione degli oggetti. Il vantaggio palese in quanto la modica del tipo di algoritmo di ordinamento utilizzato, o del gestore del le di input del problema, o ancora dell'algoritmo che enumera le soluzioni localizzata in un unico punto ed suciente creare una dierente implementazione di MKPFactory per fare in modo che vengano istanziati oggetti dierenti. Tutto ci rende il software essibile e robusto a cambiamenti, aspetto questo a cui si dato peso sin dalla sua progettazione. Tecnicamente sono stati utilizzati alcuni design pattern tipici della progettazione di software a oggetti, in particolare del Factory Pattern e del Singleton Pattern.
CAPITOLO 5.
157
n log (n)
rispetto a
n2
del pi classico
insertion sort. La relativa classe di supporto Heap, implementazione dell'interfaccia Ordinamento. L'ordinamento, indipendentemente dall'algoritmo specico utilizzato,
prevede di modicare sempre l'ordine degli elementi di due vettori distinti. Il primo vettore specico e contiene gli elementi veri e propri da ordinare (prezzi, beni, costi ridotti ecc.). Il secondo invece contiene gli indici delle variabili, i cui elementi vanno permutati in modo speculare a quelli contenuti nel primo vettore, in modo da non perdere mai il riferimento tra la quantit da ordinare e l'oerta ad essa associata.
cuzione ricorsiva del problema. Ogni problema da risolvere in realt ottenuto da una riformulazione di un problema padre a sua volta ottenuto dalla riformulazione del problema al livello ricorsivo precedente e via discorrendo. E' necessario di fatto mantenere le associazioni tra gli indici delle variabili di un problema delle relative variabili del problema padre
Pn
e gli indici
P n1 .
indiciP adre [3] = 11, signica che la variabile di indice 3 del problema P n la stessa n1 variabile che nel problema padre P ha indice 11. Il vettore nomi, sempre presente n in MKPProblem, lega invece le variabili del problema P con quelle del problema di partenza P, in modo del tutto analogo al caso di indiciPadre. Queste associazioni
sono importanti in quanto il miglioramento della soluzione ottima localizzato generalmente in livelli ricorsivi pi bassi della radice, quando il problema numero di variabili decisamente pi ridotto del problema di partenza queste variabili deve essere ssato nel problema padre
Pn
ha un
P.
Il valore di
n1
P n a P n1 ,
da
P n1
P n2
no ad arrivare
P.
e propria aggiornata.
azione ricorsiva a ritroso identica alla creazione della soluzione ottima. Quando un
P n ha un valore ottimo della funzione obiettivo maggiore del suo LBn , anche il problema P n1 avr un lower bound LBn1 migliore
lower e pi
CAPITOLO 5.
158
LBn
n1
LBn2
di
P n2
no
all'aggiornamento del lower bound del problema di partenza. Questa operazione di aggiornamento del valore del lower bound tra glio e padre avviene ogni volta che negli algoritmi di cui proposto lo pseudocodice si utilizzata l'istruzione *aggiorno
il lower bound*.
MKPRepository:
possono essere utilizzati da tutti gli oggetti istanziati durante l'esecuzione dell'interno algoritmo. Tra i pi signicativi si evidenziano:
DIM_CORE : indica la dimensione che deve avere il Core iniziale PERCENTUALE_VARIABILI_DA_VALUTARE : indica la percentuale, rispetto al numero di variabili del problema di partenza, delle variabili che si vogliono aggiungere nel Core. Si pu infatti pensare di non voler aggiungere nel Core le variabili con valore assoluto pi elevato in quanto euristicamente ritenute gi ssate al loro valore ottimo senza necessit di dimostrarlo tramite la risoluzione del nuovo Core espanso. E' un modo per velocizzare l'algoritmo euristico.
TEMPO_LIMITE : il tempo massimo, in secondi, di elaborazione dell'algoritmo. Se posto uguale a 0, non viene ssato alcun limite temporale di
esecuzione.
5.3
CAPITOLO 5.
159
CAPITOLO 5.
160
CAPITOLO 5.
161
CAPITOLO 5.
162
CAPITOLO 5.
163
CAPITOLO 5.
164
CAPITOLO 5.
165
Capitolo
Conclusione
6.1 Riepilogo del lavoro di tesi
Nel presente lavoro di tesi stato proposto un algoritmo in grado di risolvere sia in modo esatto che in modo euristico il Multidimensional Knapsack Problem, un problema noto essere NP-Hard Strong. Le maggiori dicolt nel risolvere questo tipo di problema sono dovute principalmente all'assenza di informazioni fornite dal modello le quali non sono sucientemente rilevanti per l'elaborazione di algoritmi ecienti ed ecaci. Lo studio da noi condotto ha permesso di sfrutture al massimo le potenzialit e le informazioni intrinseche nei coecienti di costo ridotto derivati dal rilassamento continuo del problema, permettendo di sviluppare tramite discesa ricorsiva un robusto sistema di determinazione del valore delle variabili. L'idea su cui si fonda l'intero algoritmo quella di focalizzare l'attenzione su un problema ridotto chiamato Core contenente le variabili che tra tutte risultano quelle pi dicili da settare al valore ottimo e valutarne il comportamento aggiungendo di volta in volta variabili secondo una precisa funzione di ecacia basata sui costi ridotti. La risoluzione del problema derivato dall'espansione dinamica del Core facilitata grazie all'utilizzo di un taglio che, se applicato in modo ricorsivo, in grado di ssare teoricamente tutte le variabili con costo ridotto non nullo in tempi dipendenti essenzialmente dal numero di vincoli del problema. I tempi di elaborazione ottenuti sono particolarmente incoraggianti. Allo stato dell'arte attuale nessun algoritmo presente in letteratura in grado di reggere il confronto con il nostro per quanto riguarda la risoluzione di problemi correlati con
166
CAPITOLO 6.
CONCLUSIONE
167
pochi vincoli e un numero elevato di variabili, sia dal punto di vista della qualit della soluzione trovata, da noi garantita ottima, sia dell'ecienza computazionale. Per le istanze pi complesse tra quelle proposte da P.C. Chu e J.E. Beasley [9] la variante euristica del nostro algoritmo consente di ottenere soluzioni molto buone in tempi ragionevoli, posizionandosi al secondo posto in assoluto per quanto riguarda la qualit delle soluzioni trovate. Rispetto alla metodologia che occupa la prima
posizione in questa particolare classica, il nostro approccio decisamente pi eciente, avendo dei tempi di elaborazione quattro volte inferiori. Inoltre la possibilit di applicare una serie di migliorie all'euristica sviluppata, unitamente al fatto che possibile procedere con l'esecuzione dell'algoritmo ben oltre il tempo limite da noi imposto, ci rende duciosi sul fatto che si possano trovare soluzioni almeno pari a quelle migliori note in tempi del tutto simili, se non inferiori, alla strategia risolutiva attualmente pi ecace.
6.2
Sviluppi futuri
Abbiamo deciso di concludere questa trattazione segnalando una serie di accorgimenti e migliorie che possono essere applicate all'algoritmo attuale in modo da incrementarne l'ecienza nella risoluzione delle istanze complesse di P.C. Chu e J.E. Beasley. In realt le possibilit di modicare il nostro algoritmo in modo euristico sono molte e solo la mancanza di tempo non ci ha permesso di vericarne gli eetti su tutte le istanze di prova a nostra disposizione. Tuttavia, essendo ora l'algoritmo ben denito nella sua struttura portante, non escluso che si possa iniziare uno studio mirato alla ricerca di nuove strade per rendere la variante euristica dell'algoritmo sempre pi eciente. Di seguito elenchiamo alcuni aspetti che secondo noi utile approfondire :
Come noto, uno dei tagli applicati durante l'analisi dell'albero di ricerca binario quello dei costi ridotti. Qualora il problema abbia un numero di
vincoli limitato, questo taglio decisamente ecace e accelera notevolmente l'esecuzione dell'algoritmo. Per problemi con un numero di vincoli elevato Si prendano in considerazione le istanze di Un problema per essere risolto tramite
m = 30.
1 nessuno dei suggerimenti e alternative qui proposte stato applicato all'algoritmo utilizzato
per produrre i risultati presentati nel Capitolo 4.
CAPITOLO 6.
CONCLUSIONE
168
V ARmax
base, la maggior parte delle 30 variabili del problema sono tutte in base e di conseguenza il costo ridotto ad esse associate nullo. Di fatto il taglio sui costi ridotti, essendo questi quasi tutti nulli, risulta essere completamente inecace e pu essere benissimo eliminato. Si osservato che l'eliminazione di questo taglio per istanze a 30 vincoli migliora le prestazioni dell'algoritmo di almeno il 20%.
Abbiamo osservato, analizzando la soluzione ottima calcolata per le istanze risolte in modo esatto, che i vincoli non sono mai soddisfatti all'uguaglianza. In altre parole, all'ottimo, non tutti i beni vengono assegnati; anzi, per alcune tipologie di beni, il numero di beni non assegnato rimane elevato. E' dunque possibile utilizzare questa informazione empirica per raorzare notevolmente il taglio sui beni che, ricordiamo, si appoggia sulla quantit totale dei beni messi a disposizione dal banditore d'astra. Questo pu essere fatto settando questa quantit alla somma delle capacit dei vincoli diminuita di una certa quantit dipendente anche dall'istanza considerata. Anche qui, diminuendo
di 10000 la quantit di beni totale per istanze a 30 vincoli si osservato un incremento di circa il 40% dei tempi computazionali senza che la soluzione migliore precedentemente trovata venga tagliata.
E' consigliabile procedere ad una traduzione rigorosa dell'algoritmo in un linguaggio compilabile come il C. Una versione ottimizzata dell'algoritmo in C pu portare ad un incremento delle prestazioni di almeno il 100% rispetto alla versione interpretata.
Si pu evitare di far entrare nel Core tutte le variabili del problema anche quando il criterio di terminazione dell'espansione del Core non soddisfatto. Dalle prove da noi condotte per una qualunque istanza 500.30 tale condizione non viene mai soddisfatta ed necessario valutare l'inserimento di tutte le variabili nel Core. In realt abbiamo notato che quasi sempre la miglior soluzione calcolata stata trovata prima dell'inserimento della variabile in posizione 150 nell'ordinamento basato sui costi ridotti. istanze 500.10 e 500.5. E tale valore scende ancora per le
CAPITOLO 6.
CONCLUSIONE
169
valore assoluto crescente dei costi ridotti, le ultime 350 variabili possono essere ssate a priori, evitando ulteriori calcoli.
Sarebbe opportuno condurre uno studio approfondito sul legame sussistente tra la struttura del problema e il tipo di ordinamento delle variabili da applicare nell'algoritmo AAR, in quanto abbiamo notato che la preferenza dell'ordinamento per beni rispetto a quella per prezzi del tutto relativa alla singola istanza presa in considerazione. Inoltre possibile valutare l'ecacia di al-
tre forme di ordinamento, come quella basata sui pesi delle oerte in uno dei vincoli del problema, magari quello che a priori pu risultare il pi violabile.
La variante euristica dell'algoritmo stata costruita rilassando la condizione di valutazione dei sottoproblemi in modo banale. E' consigliabile studiare sistemi alternativi per tagliare lo spazio di ricerca. Per esempio si possono ssare a
priori certe variabili in tutti i livelli ricorsivi, oppure su valutarne solo i primi
n sottoproblemi ridotti
pensare di valorizzare il parametro gap in modo dinamico, dipendentemente dal livello ricorsivo o dal sottoproblema analizzato.
Bibliograa
ORSA Journal on
170
BIBLIOGRAFIA
171
[10] F. Dammayer - S. Voss. Application of tabu search strategies for solving multiconstraint zero-one knapsack problems. Working paper, Technische Hochschule
Darmstadt, 1991
[11] F. Dammayer S. Voss. Dynamic tabu list management using Reverse
Elimination Method. Annals of Operations Research, 31-46, 1993 [12] G. Dobson: Worst-case analysis of greedy heuristics for integer programming with non-negative data. mathematics of operations research, 7:515-531, 1982. [13] A. Drexl. A simulated annealing approach to the multiconstraint zero-one knapsack problem, Computing, 40:1-8 [14] G. Dueck - T. Scheuer. Threshold accepting: a general purpose optimization algorithm. Journal of computational Physics, 90:161-175 [15] A. Freville - G. Plateau. An ecient preprocessing procedure for the multidimensional 0-1 knapsack problem. Discrete Applied Mathematics, 49:189-212, 1994. [16] B. Gavish - H. Pirkul. Ecient algorithms for solving multiconstraint zero-one knapsack problems to optimality. Mathematical Programming, 31:78-105, 1985 [17] F. Glover - G.A. Kochenberger. Critical event tabu search for multidimensional knapsack problems. Metaheuristics: The Theory and Applications, 407-427, 1996 [18] F. Glover - Tabu Search :Part I. ORSA Journal on Computing , 3:190-206,1989 [19] F. Glover - Tabu Search:Part II. ORSA Journal on Computing, 1:4-32,1990 [20] R. Gonen - D. Lehmann. Linear programming helps solving large multi-unit combinatorial auctions, Aprile 2001 [21] Z. Gu - G.L. Nemhauser - M.W.P. Savelsbergh. Cover inequalities for 0-1 linear programs: computation. INFORMS J. on Computing, 10:427-437, 1998 [22] S.R. Gupta - R.L. Buln - J.S. Smith. Lifting Cover Inequalities for the Binary Knapsack Polytope
BIBLIOGRAFIA
172
[23] S. Hana - A. Freville. Extension of reverse elimination method through a dyamic management of the tabu list, RAIRO Operations Research, 35:251-267, 2001 [24] K. Kaparis - A.N. Letchford. Local and Global Lifted Cover Inequalities for the 0-1 Multidimensional Knapsack Problem. Department of Management Science,
ceedings of the 5th International Conference in Electronic Commerce Research (ICECR-5), Montreal ( Canada ), 23-27 ottobre 2002
[30] H. Pirkul - S. Narasimhan. Ecient algorithms for the multiconstraint general knapsack problem. IEEE transactions, 18:195-203,1986. [31] H. Pirkul. A heuristic solution procedure for the multiconstraint zero-one knapsack problem. Naval Research Logistics, 34:161-172, 1987. [32] D. Pisinger. An expanding-core algorithm for the exact 0-1 knapsack problem.
BIBLIOGRAFIA
173
[34] J. Puchinger - G.R. Raidl - M. Gruber. Cooperating Memetic and Branch-andCut Algorithms for Solving the Multidimensional Knapsack Problem. The 6th