ALGORITMI EURISTICI PER PROBLEMI DI TAGLIO BIDIMENSIONALE
|
|
|
- Guglielmo Carella
- 10 anni fa
- Просмотров:
Транскрипт
1 ALMA MATER STUDIORUM - UNIVERSITA DI BOLOGNA FACOLTA DI INGEGNERIA Corso di Laurea in INGEGNERIA INFORMATICA Insegnamento: OTTIMIZZAZIONE COMBINATORIA ALGORITMI EURISTICI PER PROBLEMI DI TAGLIO BIDIMENSIONALE Tesi di Laurea di: Fabio Ciani Relatore: Chiar.mo Prof. Paolo Toth Correlatori: Prof. Alberto Caprara Ing. Enrico Malaguti ANNO ACCADEMICO
2
3 Sommario Argomento di questa tesi è lo sviluppo e l implementazione di due algoritmi euristici per problemi vincolati di taglio bidimensionale, ortogonale, non a ghigliottina. Il problema consiste nel tagliare pezzi rettangolari da un rettangolo più grande in modo da massimizzare il valore totale dei pezzi tagliati. Il problema è classificabile, nell ambito della teoria della complessità computazionale, come N P Hard e non sono noti, per questo tipo di problemi, algoritmi in grado di ottenere una soluzione ottima in un tempo polinomiale per qualunque istanza del problema. Si è dunque progettato, e successivamente implementato sfruttando il linguaggio di programmazione C, prima un algoritmo euristico che utilizza la tecnica nota come GRASP (greedy randomized adaptive search procedure) e successivamente un altro algoritmo euristico che sfrutta la tecnica del Tabu Search, per ottenere buone soluzioni in tempi ragionevoli. Durante la realizzazione sono state tenute in considerazione diverse strategie per le fasi che costituiscono entrambi gli algoritmi e sono state effettuate diverse scelte per la ricerca di parametri critici. Infine sono stati eseguiti molti esperimenti computazionali su un gran numero di istanze di tipo eterogeneo, sia per selezionare le migliori alternative, sia per comparare l efficienza degli algoritmi con altri già esistenti. Parole chiave: taglio, bidimensionale, euristico, euristici, tabu search i
4
5 Indice Sommario i 1 Introduzione Origini, applicazioni e classificazioni del problema di taglio Formulazione del problema Esempi grafici di risoluzione Tecniche euristiche Sviluppo di un algoritmo costruttivo Inizializzazione di P, L e C Scelta del rettangolo Scelta del pezzo da tagliare Aggiornamento di P, L e C Esempio di applicazione dell algoritmo Tecniche metaeuristiche Ricerca Locale Genetic Search Simulated Annealing Ant Colony Optimization GRASP Tabu Search Sviluppo di un algoritmo GRASP Fase Costruttiva iii
6 4.1.1 Scelta del parametro δ Fase di Miglioramento Variazione dei vincoli dei pezzi Aumento dei lower bound P i Diminuzione degli upper bound Q i Scelta delle migliori strategie Sviluppo di un algoritmo Tabu Search Definizione delle mosse Riduzione di un blocco Inserimento di un blocco Mosse da esaminare Selezione della mossa Tabu list Intensificazione e diversificazione Variazione dei vincoli dei pezzi Path relinking Scelta delle migliori strategie Implementazione Strutture dati Lista dei pezzi P Lista dei rettangoli L Lista dei blocchi C Lista delle soluzioni d elite E Lista dei tabu T Lista delle frequenze dei pezzi F Caricamento dei dati iniziali Schema dell algoritmo GRASP Funzioni dell algoritmo GRASP Schema dell algoritmo Tabu Search Funzioni dell algoritmo Tabu Search iv
7 6.7 Funzioni comuni ai due algoritmi Test e risultati computazionali Tipi di test Risultati computazionali Confronto tra gli algoritmi GRASP Confronto tra gli algoritmi Tabu Search Confronto tra le due tecniche Conclusioni 105 Possibili sviluppi futuri 107 Bibliografia 109 v
8
9 Capitolo 1 Introduzione 1.1 Origini, applicazioni e classificazioni del problema di taglio Quando dei pezzi piccoli sono ricavati da pezzi più grandi, due problemi insorgono. Il primo riguarda la scelta della dimensione dei pezzi da tagliare (assortment problem). Il secondo riguarda come ricavare i pezzi piccoli da quelli grandi in modo da minimizzare il materiale scartato (trim loss problem) (Hinxman, 1979). I pezzi piccoli sono spesso chiamati order list, mentre i pezzi da tagliare, vengono chiamati stock material. La combinazione dei due problemi è conosciuta come problema di taglio (cutting stock problem). Il problema di taglio (CSP) insorge in molte grandi industrie dove fogli o lastre devono essere tagliati in pezzi più piccoli. Materiali tipici sono il vetro, il legno, l acciaio, la plastica e i prodotti tessili (Dyckhoff, 1990). La prima formulazione del CSP risale al 1939 e fu realizzata da Kantorovich, anche se venne pubblicata in Inghilterra solo nel 1960 (Kantorovich, 1960). La ricerca scientifica iniziò solo allora e, fin da subito, si diffusero un gran numero di metodi e risoluzioni. I problemi CSP possono essere classificati utilizzando lo schema proposto da Dyckhoff. Questa classificazione prevede quattro diverse categorie: 7
10 1. Dimensione N) Numero delle dimensioni 2. Tipo di assegnamento B) Utilizzo di tutto il pezzo grande e di una selezione dei pezzi piccoli V) Utilizzo di una parte del pezzo grande e di tutti i pezzi piccoli 3. Assortimento dei pezzi grandi da tagliare O) Un solo pezzo grande I) Molti pezzi grandi tutti della stessa dimensione D) Molti pezzi grandi di dimensioni diverse 4. Assortimento dei pezzi piccoli F) Pochi pezzi di dimensioni diverse M) Molti pezzi con molte dimensioni diverse R) Molti pezzi con poche dimensioni diverse C) Molti pezzi delle stesse dimensioni La caratteristica più importante è la dimensione. Dyckhoff suddivise i problemi in monodimensionali, bidimensionali, tridimensionali e multidimensionali. Nel caso monodimensionale, una sola dimensione è rilevante ai fini della soluzione. Nei problemi bidimensionali, invece, i pezzi piccoli possono essere posizionati in maniera libera all interno del pezzo da tagliare. Il caso più semplice si verifica quando i pezzi piccoli e il pezzo grande sono tutti di forma rettangolare. Se i pezzi possono essere tagliati solamente con i lati paralleli a quelli del pezzo grande, si parla di problema di tipo ortogonale (orthogonal). Infine, se il taglio deve avvenire lungo l intera lunghezza del 8
11 pezzo da tagliare (o di sue sottoparti formate da tagli precedenti), il problema è detto a ghigliottina (guillotine). Diversi tipi di taglio sono mostrati nella Figura 1, dove le parti in grigio rappresentano gli sprechi di materiale. In particolare la Figura 1(a) mostra il caso del problema monodimensionale, dove la lunghezza dei pezzi è prefissata, mentre le Figure 1(b) e 1(c) mostrano la differenza tra i problemi bidimensionali a ghigliottina e quelli non a ghigliottina. a) taglio monodimensionale b) taglio bidimensionale a ghigliottina c) taglio bidimensionale non a ghigliottina Figura 1 Diversi tipi di taglio 9
12 Un altra importante caratteristica, che influenza la complessità del problema, è il tipo di assegnamento. Per la classificazione dei vari CSP sono necessarie almeno due categorie. Nella prima, tutto il pezzo da tagliare è utilizzato, ma non tutti i pezzi piccoli possono essere ricavati. Nella seconda, tutti i pezzi sono ritagliati, ma soltanto una parte del pezzo grande viene utilizzata. La terza caratteristica può essere suddivisa in tre categorie a seconda dell assortimento dei pezzi grandi. Nel primo caso c è un unico pezzo da tagliare. Nel secondo, ci sono tanti pezzi grandi con le stesse dimensioni. Infine, nel terzo caso, ci sono molti pezzi da tagliare con dimensioni differenti. Per esempio, questo caso si verifica quando i pezzi da tagliare sono gli scarti di tagli precedentemente eseguiti. Una suddivisione simile può essere fatta anche per l assortimento dei pezzi piccoli. Nel primo caso ci sono pezzi piccoli di dimensioni diverse. Nel secondo, ci sono molti pezzi piccoli, di cui molti di essi con dimensioni differenti. Nel terzo, ci sono molti pezzi piccoli, di cui molti di essi hanno le stesse dimensioni. Infine, nell ultimo caso, tutti i pezzi hanno le stesse dimensioni. Poiché è stato dimostrato che anche i problemi di taglio più semplici sono N P Hard, anche quelli più complicati sono N P Hard (Blazewicz et al 1989; Fowler et al, 1981). Questo significa che è molto improbabile che esista un algoritmo che risolva il CSP, in maniera ottimale, in un tempo polinomiale. Per questo motivo, anziché cercare di trovare algoritmi esatti, sin dalla sua formulazione, il CSP è stato affrontato sviluppando algoritmi euristici per la sua risoluzione. Nelle prossime pagine verranno analizzati diversi tipi di metodi euristici cercando di individuare quello che meglio si adatta alla risoluzione del CSP. 1.2 Formulazione del problema Il problema trattato da questa tesi è un problema di taglio bidimensionale, ortogonale, non a ghigliottina, che consiste nel ricavare un insieme finito 10
13 di piccoli pezzi rettangolari a partire da un rettangolo base di dimensioni prefissate, in modo da massimizzare il profitto. Il rettangolo base R ha lunghezza L ed altezza W, mentre ogni pezzo i da tagliare ha dimensioni (l i,w i ) e un valore indicato con v i. Il problema consiste nel tagliare x i copie di ogni pezzo i in modo che 0 P i x i Q i, i = 1,.., m e che il valore totale i v i x i sia massimizzato. Il massimo numero di pezzi che possono essere tagliati è indicato con M = i Q i. I pezzi da tagliare sono soggetti a due ulteriori vincoli: I pezzi hanno un orientazione fissata, cioè pezzi di dimensione (a, b) e (b, a) non sono la stessa cosa. Ogni pezzo deve essere tagliato con i suoi lati paralleli a quelli del rettangolo base (tagli ortogonali). A seconda dei valori di P i e Q i, si possono distinguere tre tipi di problemi: 1. Unconstrained: i, P i = 0, Q i = L W/l i w i. 2. Constrained: i, P i = 0, i, Q i < L W/l i w i. 3. Doubly Constrained: i, P i > 0; j, Q j < L W/l j w j. Definiamo l efficienza di un pezzo i come e i = v i /(l i w i ); a seconda dell efficienza dei pezzi si possono distinguere altre categorie di problemi: 1. Unweighted: e i = 1, i. Il valore di ogni pezzo è uguale alla sua area. 2. Weighted: e i 1, almeno per un pezzo i. Alcuni pezzi hanno un valore che non corrisponde alla loro superficie, ma riflette altri aspetti come la loro forma o la loro relativa importanza per i clienti. E possibile ottenere un semplice upper bound per il problema risolvendo il seguente knapsack problem, dove la variabile x i rappresenta il numero di pezzi del tipo i che devono essere tagliati in più rispetto al suo lower bound P i : m m Max v i x i + v i P i (1.1) i=1 i=1 11
14 s.t. m m (l i w i )x i LW P i (l i w i ) (1.2) i=1 i=1 x i Q i P i, i = 1,...m (1.3) x i 0, integer, i = 1,...m (1.4) Alcuni autori hanno preso in considerazione il problema di tipo unconstrained: Tsai et al [3], Arenales e Morabito [4], Healy et al [5]. Tuttavia questo genere di problema è di scarso interesse applicativo e pertanto, in questa tesi, verranno sviluppati algoritmi euristici in grado di risolvere solamente problemi di tipo constrained e doubly constrained. 1.3 Esempi grafici di risoluzione Nella Figura 2 vediamo alcuni esempi grafici di risoluzione, con un rettangolo base di dimensione (10,10) e m = 10 pezzi da tagliare (Figura 2(a)). i l i w i P i Q i v i e i , , , , , , , , , La prima soluzione, di valore 268, è ottima per l unconstrained problem (Figura 2(b)), la seconda, che produce un risultato di 247, è ottima per il constrained problem (Figura 2(c)), mentre la terza, il cui valore è 220, è ottima per il doubly constrained problem (Figura 2(d)). 12
15 (a) pezzi da inserire (b) unconstrained, ottimo = 268 (c) constrained, ottimo = 247 (d) doubly constrained, ottimo = 220 Figura 2 Istanza 3 da Beasley [6] 13
16
17 Capitolo 2 Tecniche euristiche Nell affrontare un problema di ottimizzazione combinatoria possono essere utilizzati vari approcci a seconda sia della difficoltà specifica e delle dimensioni del problema in esame, sia degli obiettivi reali che si vogliono ottenere. Così, in quei casi in cui è necessario pervenire alla soluzione ottima di un certo problema, si cercherà di sviluppare un algoritmo esatto che utilizzi un approccio di enumerazione implicita delle istanze. Algoritmi esatti che risolvono il problema di taglio bidimensionale sono stati sviluppati da Beasley [6], Scheithauer e Terno [7], Hadjiconstantinou e Christofides [8], Fekete e Schepers [9] e Caprara e Monaci [10]. Tuttavia questi metodi, nel caso di istanze di grosse dimensioni, non sono in grado di fornire il risultato ottimo in un tempo accettabile. Per cui se non è necessario individuare il risultato ottimo a tutti i costi, ma è sufficiente avere una garanzia sul massimo errore commesso in termini relativi, si potrà far ricorso ad un algoritmo euristico che individui una soluzione il più vicino possibile a quella ottima, in un tempo accettabile. Un metodo euristico piuttosto semplice, in grado di risolvere il problema in questione, è conosciuto come algoritmo costruttivo. 15
18 2.1 Sviluppo di un algoritmo costruttivo Il problema di taglio bidimensionale può essere risolto sviluppando un algoritmo euristico costruttivo che consiste in un processo iterativo in cui si combinano tre elementi: una lista P di pezzi ancora da tagliare (inizialmente la lista completa dei pezzi), una lista L di rettangoli vuoti in cui un pezzo può essere tagliato (inizialmente contenente solo il rettangolo base R = (L, W )) e una lista C contenente i blocchi (ovvero l unione di uno o più pezzi) già tagliati ed inizialmente vuota. Ad ogni passo un rettangolo viene scelto da L e vi si inserisce un pezzo scelto da P che possa esservi contenuto. Questo produce, di solito, la rimozione del rettangolo di partenza e la creazione di nuovi rettangoli che si aggiungono a L. Il processo termina quando L = oppure nessuno dei pezzi rimanenti riesce a entrare in uno dei rettangoli di L. L algoritmo può essere così sintetizzato: 1. Inizializza L, P e C. 2. Se un pezzo che entra in uno dei rettangoli, prosegui, se no STOP. 3. Scegli un rettangolo di L. 4. Scegli un pezzo di P da tagliare. 5. Aggiorna L, P e C e ritorna al punto Inizializzazione di P, L e C Come già detto in precedenza, inizialmente, la lista dei rettangoli vuoti L contiene solo il rettangolo base, la lista dei blocchi C è vuota, mentre la lista dei pezzi P contiene l elenco completo dei pezzi da tagliare. Quest ultima deve essere ordinata per favorire l applicazione dell algoritmo costruttivo, seguendo tre criteri: 1. Pezzi ordinati per valori P i l i w i decrescenti, in modo da dare priorità ai pezzi che devono per forza essere tagliati (cioè quelli con P i > 0). 2. Se P i = 0 i, i pezzi devono essere ordinati per valori e i decrescenti. 16
19 3. Se e i = 1 i, i pezzi devono essere ordinati per valori l i w i decrescenti Scelta del rettangolo La scelta migliore è quella di selezionare il rettangolo R L con l area minore in modo da poter soddisfare le richieste dei pezzi più piccoli coi rettangoli più piccoli, lasciando i rettangoli più grandi per i pezzi più grandi. Se scegliessimo un rettangolo grande all inizio e lo usassimo per tagliare un pezzo piccolo, i nuovi rettangoli creati dall inserimento del pezzo potrebbero risultare inutili per i pezzi più grandi ancora da tagliare Scelta del pezzo da tagliare Scelta di un pezzo p i e di una quantità n i Q i in modo da formare il blocco b Una volta selezionato il rettangolo R, deve essere scelto il primo pezzo p i di P (ordinato come specificato in precedenza) che entra in R. Se il pezzo selezionato per essere tagliato ha un upper bound Q i > 1, può essere presa in considerazione l idea di tagliare un blocco, ovvero diverse copie del pezzo in questione disposte in righe e colonne, purché il numero di questi pezzi non superi Q i e il blocco continui ad avere una forma rettangolare. La Figura 3 mostra esempi di questa situazione. Figura 3 Varie scelte sulla composizione dei blocchi 17
20 Due criteri sono stati considerati per la selezione del pezzo: 1. Il primo pezzo nella lista ordinata P. Questo è il modo più ragionevole di scegliere il pezzo, in accordo con quanto detto prima. 2. Il pezzo che produce il maggiore incremento nella funzione obiettivo. Questo è un modo di agire molto più greedy. Posizionamento del blocco nel rettangolo R Poiché con molta probabilità il blocco b non riempirà completamente il rettangolo R, tale blocco deve essere posizionato in uno degli angoli del rettangolo, e più precisamente nell angolo che dista di meno da uno degli angoli del rettangolo di base. Posizionando i blocchi il più vicino possibile agli angoli del rettangolo base, si concentrano tutti i rettangoli vuoti al centro, facilitando così l operazione di fusione e recuperando spazio per i pezzi successivi Aggiornamento di P, L e C La lista C dei blocchi deve essere aggiornata con l indice i del pezzo inserito con il relativo numero di pezzi n i che formano il blocco. Inoltre sarà necessario indicare in qualche modo la posizione del blocco all interno del rettangolo selezionato. La lista P dei pezzi da tagliare deve essere aggiornata modificando l upper bound del pezzo inserito Q i = Q i n i ; se Q i = 0, il pezzo i deve essere rimosso dalla lista. La lista L dei rettangoli vuoti deve essere aggiornata eliminando il rettangolo appena utilizzato e, a meno che il blocco non occupi tutto lo spazio del rettangolo vuoto, inserendovi i nuovi rettangoli appena formati. Così facendo però si presenterebbero un sacco di piccoli rettangoli, impedendo a pezzi grandi di essere tagliati, anche se lo spazio libero totale lo permetterebbe. Occorre perciò fondere questi rettangolini. 18
21 Fusione dei rettangoli Quando si fondono due rettangoli, possono comparire al massimo tre nuovi rettangoli, di solito uno più grande e uno o due più piccoli, come da Figura 4. Figura 4 Fusione di due rettangoli Tra le varie alternative di fusione, la migliore è quella che favorisce l inserimento dei pezzi che si trovano nelle prime posizioni della lista P. Seguendo questo consiglio, le condizioni per una fusione tra due rettangoli sono le seguenti: 1. Se l ordine del miglior pezzo che entra nel più grande dei nuovi rettangoli è minore dell ordine dei pezzi che entrano nei vecchi rettangoli, deve avvenire la fusione. 2. Se l ordine del miglior pezzo che entra nel più grande dei nuovi rettangoli è maggiore dell ordine dei pezzi che entrano nei vecchi rettangoli, non deve avvenire la fusione. 3. Se l ordine del miglior pezzo che entra nel più grande dei nuovi rettangoli è uguale all ordine dei pezzi che entrano nei vecchi rettangoli, la fusione deve avvenire solo se l area del più grande tra i nuovi rettangoli è maggiore dell area di ognuno dei vecchi rettangoli. 19
22 2.2 Esempio di applicazione dell algoritmo Riprendendo l esempio di Figura 2, proviamo ad applicare l algoritmo costruttivo nel caso constrained ovvero con P i = 0 i. Denotiamo ogni rettangolo con la quadrupla (x 1, y 1, x 2, y 2 ) dove (x 1, y 1 ) sono le coordinate dell angolo in basso a sinistra, mentre (x 2, y 2 ) sono le coordinate dell angolo in alto a destra. Il processo può essere seguito attraverso la Figura 5. Figura 5 Applicazione dell algoritmo costruttivo Inizialmente L = {R} = {(0, 0, 10, 10)} e P = {10, 9, 6, 5, 7, 2, 8, 3, 1, 4} in ordine di efficienza. Consideriamo il primo pezzo della lista, il pezzo 10, con Q 10 = 2 e proviamo a tagliare un blocco formato da due pezzi nell angolo in basso a destra del primo (e unico) rettangolo di L. Aggiorniamo P = {9, 6, 5, 7, 2, 8, 3, 1, 4} e L = {(4, 0, 10, 10)}. Ora proviamo a tagliare il pezzo 9 con Q 9 = 3, ma solamente 2 copie possono entrare nel rettangolo. Tagliamo il blocco nell angolo in basso a destra e riaggiorniamo P = {9, 6, 5, 7, 2, 8, 3, 1, 4} (con Q 9 = 1) e L = {(4, 7, 10, 10)}. A questo 20
23 punto i pezzi 9, 6 e 5 non entrano nel rettangolo e quindi viene selezionato il pezzo 7 con Q 7 = 2. Il blocco, formato da due pezzi, viene posizionato nell angolo in alto a destra. Aggiorniamo ancora P = {9, 6, 5, 2, 8, 3, 1, 4} e L = {(4, 7, 6, 10), (6, 7, 10, 8)}, ma nessun altro pezzo può entrare in nessuno dei rettangoli restanti. Prima di finire il processo proviamo a fondere i due rettangoli ottenendo L = {(4, 7, 10, 8), (4, 8, 6, 10)}, ma anche in questo caso nessun pezzo può più essere tagliato. Il risultato finale trovato dall algoritmo costruttivo è di 242, contro il 247 che rappresenta la soluzione ottima. Considerando il fatto che questo problema è uno di quelli considerati più facili, il risultato può risultare inaccettabile. Per questo motivo l algoritmo costruttivo si presenta inadeguato perché cerca sempre di effettuare il passo più conveniente in quel momento (come un algoritmo di tipo greedy) e preclude così la strada verso altre soluzioni migliori. Per superare questo inconveniente è possibile sviluppare un algoritmo che si fondi su una tecnica di tipo metaeuristico. 21
24
25 Capitolo 3 Tecniche metaeuristiche Negli ultimi anni hanno acquisito importanza via via maggiore alcuni approcci euristici che, anziché essere progettati in maniera specifica per un dato problema, sono di tipo generale. Tali tecniche sono dette metaeuristiche. La struttura e l idea di fondo di ciascuna metaeuristica sono sostanzialmente fissate, ma la realizzazione delle varie componenti dell algoritmo dipende dai singoli problemi. Tra queste le più interessanti sono: genetic search simulated annealing ant colony optimization GRASP tabu search Gli approcci metaeuristici possono vedersi in realtà in modo omogeneo, come generalizzazioni di un unico approccio fondamentale, che è quello della ricerca locale. La ricerca locale si basa su quello che è, per certi versi, l approccio più semplice e istintivo all ottimizzazione: andare per tentativi. In effetti, l idea di funzionamento della ricerca locale (come del resto quella delle varie metaeuristiche) è talmente elementare che è sorprendente constatare la loro relativa efficacia. Va tuttavia detto fin da ora che a fronte di 23
26 questa relativa semplicità, l applicazione di una qualunque metaeuristica a un problema di ottimizzazione combinatoria richiede comunque una messa a punto accurata e talvolta laboriosa. Consideriamo un problema di minimizzazione, e una sua soluzione ammissibile x, con associato il valore della funzione obiettivo f(x). La ricerca locale consiste nel definire un intorno di x (detto, nella terminologia della ricerca locale, vicinato), e nell esplorarlo in cerca di soluzioni migliori, se ve ne sono. Se, in questo vicinato di x, si scopre una soluzione y per cui f(y) < f(x), allora ci si sposta da x a y e si riparte da y con l esplorazione del suo intorno. Se invece nel vicinato di x non si scopre nessuna soluzione migliore, allora vuol dire che x è un minimo locale. Nella ricerca locale classica, arrivati in un minimo locale, l algoritmo si ferma e restituisce questo minimo come valore di output. Ovviamente, non si ha nessuna garanzia in generale che tale valore costituisca una soluzione ottima del problema; anzi, tipicamente esso può essere anche molto distante dall ottimo globale. Le metaeuristiche, in effetti, sono state concepite proprio per cercare di ovviare al problema di rimanere intrappolati in un minimo locale. Vediamo dapprima più da vicino la ricerca locale, e poi esamineremo gli approcci metaeuristici. 3.1 Ricerca Locale In base a quanto detto sopra, possiamo riassumere schematicamente l algoritmo generale di ricerca locale come segue. Con x indichiamo una generica soluzione ammissibile del problema, con N(x) il suo vicinato, e con f(x) la funzione obiettivo. 1. Scegli una soluzione iniziale x. 2. Genera le soluzioni nel vicinato N(x). 3. Se in N(x) c è una soluzione y tale che f(y) < f(x), allora poni x := y e vai al punto 2, altrimenti STOP. 24
27 Lo spostamento da x a y al punto 3 viene spesso chiamato mossa. Nella ricerca locale, come si vede, si ha un miglioramento della funzione obiettivo in corrispondenza di una mossa. Per applicare l approccio della ricerca locale a un particolare problema, bisogna fare alcune scelte di fondo. Occorre avere a disposizione una soluzione iniziale ammissibile. Questa può essere generata da un euristica ad hoc per il particolare problema, o addirittura può essere generata casualmente. E possibile anche eseguire l algoritmo a partire da diverse soluzioni iniziali, ottenendo così diverse soluzioni euristiche, e scegliere poi la migliore. Bisogna definire in modo preciso e opportuno il vicinato di una soluzione. Definito il vicinato, occorre avere a disposizione un algoritmo efficiente per esplorarlo. E inutile definire il vicinato in un modo teoricamente potente per poi non essere in grado di esplorarlo in un tempo di calcolo ragionevole. A seconda di come vengono fatte queste scelte, l algoritmo risultante può essere più o meno efficiente, e la soluzione proposta dalla ricerca locale risultare più o meno buona. Benché ogni applicazione del concetto di ricerca locale a un problema abbia le sue peculiarità, alcuni aspetti sono abbastanza comuni a molte realizzazioni. La definizione del vicinato è in genere connessa al concetto di perturbazione di una soluzione ammissibile, nel senso che la ricerca avviene tra le soluzioni che si ottengono perturbando una soluzione iniziale. Spesso di parla di forza di un vicinato. Un vicinato definito in un certo modo è tanto più forte quanto più la qualità delle soluzioni prodotte dall algoritmo è indipendente dalla bontà della soluzione di partenza. 25
28 Per cui si può affrontare il problema senza perdere tempo a generare buone soluzioni iniziali. Anzi, conviene generare molte soluzioni iniziali casualmente, sperando così di avere un campionamento rappresentativo dell intera regione ammissibile. Un altro aspetto caratterizzante un approccio di ricerca locale è il modo in cui deve essere esplorato il vicinato di una soluzione. Due strategie antitetiche sono first improvement e steepest descent. Nel primo caso l esplorazione del vicinato termina non appena si trova una soluzione migliore di quella corrente. Nel secondo, invece, lo si esplora comunque tutto cercando il massimo miglioramento che quel vicinato consente di ottenere. In genere si preferisce il primo approccio, ma non è una regola fissa. Come già osservato, un grosso pregio della ricerca locale sta nella sua semplicità concettuale e realizzativa, pur consentendo tale metodo di ottenere risultati interessanti. Tuttavia, il criterio di arresto dell algoritmo di ricerca locale visto finora appare in generale troppo rigido. A parte alcuni casi particolari (e fortunati) in cui la funzione obiettivo ha determinate caratteristiche di convessità, nella grande maggioranza dei problemi reali la funzione obiettivo da minimizzare presenta un grande numero di minimi locali, talora anche molto lontani dal minimo globale. Per ovviare a questo problema, a partire dalla metà degli anni 80, la ricerca si è indirizzata verso approcci euristici che generalizzano la ricerca locale cercando di evitare i suoi principali difetti. 3.2 Genetic Search Con il termine weak methods si indicano quei metodi di risoluzione di problemi che si basano su poche assunzioni (o conoscenze) relative alle particolari strutture e caratteristiche dei problemi stessi, motivo per il quale tali metodi sono applicabili ad una vasta classe di problemi. Gli algoritmi genetici rientrano pienamente in questa categoria, dal momento che essi sono in grado 26
29 di compiere una efficiente ricerca anche quando tutta la conoscenza a priori è limitata alla sola procedura di valutazione che misura la qualità di ogni punto dello spazio di ricerca (misura data, ad esempio, dal valore della funzione obiettivo). Questa caratteristica conferisce a tali algoritmi una grande robustezza, ovvero una grande versatilità che li rende applicabili a diversi problemi, al contrario dei metodi convenzionali che, in genere, non trovano altra applicazione che quella relativa al problema per cui sono stati ideati. Gli algoritmi genetici integrano l abilità di semplici rappresentazioni nel codificare strutture molto complicate con la potenza esibita da semplici trasformazioni (che agiscono su tali rappresentazioni) nel migliorare queste strutture. Questo miglioramento è l obiettivo primario dell ottimizzazione. Infatti, sotto l azione di certe trasformazioni genetiche, si registrano miglioramenti o, se si vuole, evoluzioni delle rappresentazioni in modo da imitare il processo di evoluzione di popolazioni di organismi viventi. In natura, il problema che ciascuna specie deve affrontare è quello della sopravvivenza, che coincide con il trovare un adattamento vantaggioso ad un ambiente mutevole e talvolta ostile. Le trasformazioni genetiche che consentono una evoluzione in tal senso sono quelle che alterano il patrimonio genetico della specie contenuto nei cromosomi di ciascun individuo: esse sono il crossover di gruppi di geni parentali e la mutazione. I cromosomi codificano strutture biologiche molto complicate, mentre le trasformazioni genetiche costituiscono il mezzo attraverso il quale si generano nuove strutture biologiche più evolute delle precedenti. L idea di fondo degli algoritmi genetici è la seguente. Supponiamo di avere un certo insieme di soluzioni di un problema di ottimizzazione. Tra queste, ce ne saranno di migliori e di peggiori. La qualità di una soluzione è misurata da una funzione di merito, detta fitness function, che in genere coinciderà con la funzione obiettivo, ma non sempre. A questo punto, vogliamo generare nuove soluzioni, con la speranza ovviamente che fra queste ve ne siano sempre di migliori. L idea è allora quella di accoppiare le soluzioni tra di loro in modo che diano alla luce nuove soluzioni. Allora, da una certa popolazione di individui (soluzioni), se ne ricava un altra, che costituisce 27
30 una nuova generazione, ossia quella dei figli della popolazione di partenza. Questa nuova generazione potrebbe essere molto più numerosa della precedente, e allora quello che si fa è effettuare una selezione, cioè si escludono dalla popolazione tutte le soluzioni che hanno un valore di fitness function inferiore a una certa soglia. Con la popolazione così selezionata, si ricomincia, generando quindi i nipoti delle soluzioni di partenza e così via, per un numero prefissato di generazioni. Come si vede, in questo contesto così generale vi sono diverse scelte da fare. Anzitutto, negli algoritmi genetici gioca un ruolo fondamentale il modo in cui vengono rappresentate le soluzioni ammissibili. Tipicamente, una soluzione sarà rappresentata da un insieme di stringhe di interi o binarie, che sono i cromosomi. Ciascun cromosoma a sua volta è composto da geni (i singoli bit). Dalla combinazione di due individui (crossover) nascerà una nuova soluzione del problema. I geni nei cromosomi del nuovo individuo dovranno ovviamente provenire da quelli dei due genitori. Un semplice modo di realizzare questo è il seguente. Se indichiamo con x i e y i l i-esimo gene di un certo cromosoma dei due genitori, il corrispondente gene nel cromosoma-figlio può essere posto rispettivamente uguale all uno o all altro con probabilità p e 1 p. Si noti che in questo modo si introduce un elemento probabilistico nell algoritmo. Peraltro, reiterando più volte il processo aleatorio di crossover, diverse soluzioni possono essere ottenute dalla stessa coppia di genitori. E evidente che la scelta dell operatore di crossover è particolarmente importante; tuttavia non c è solo questa. Un altra scelta molto importante è quella relativa alla dimensione della popolazione: a ogni generazione, infatti, verranno escluse dall evoluzione dell algoritmo tutte le soluzioni con basso valore di funzione obiettivo. E una scelta comune quella di mantenere costante nei vari passi il numero di individui della popolazione. E implicito, in quanto detto finora, che l efficacia degli algoritmi genetici risiede nel fatto empirico che se si combinano soluzioni buone, si ottengono soluzioni ancora buone. Tuttavia, sperimentalmente, si è potuto osservare che anche gli algoritmi genetici, dopo un certo numero di iterazioni, tendono a produrre soluzioni che non migliorano più. Per diversificare la ricerca, allora, 28
31 si introduce un nuovo operatore, detto mutazione. Prima cioè di procedere alla successiva generazione, in alcuni degli individui della popolazione viene alterato un gene. Ovviamente, gli operatori di mutazione dipendono molto dal particolare problema in esame. Da quanto detto, un algoritmo genetico è fondamentalmente caratterizzato da cinque componenti: 1. una rappresentazione delle soluzioni generalmente sotto forma di stringhe di bit; 2. un criterio per generare la popolazione iniziale di soluzioni; 3. una funzione di valutazione che misura la qualità di ciascuna soluzione; 4. un insieme di operatori genetici che trasformano punti-soluzione in altri punti; 5. un insieme di valori per i parametri di controllo dell algoritmo. Lo schema di principio di un algoritmo genetico è quello che segue: 1. Genera la popolazione iniziale. 2. Seleziona i genitori. 3. Genera i figli. 4. Esegui il ricambio generazionale. 5. Se condizione d uscita, STOP, altrimenti torna al punto 2. L algoritmo inizia con la creazione di una popolazione iniziale di soluzioni, generata di solito in modo casuale. Quindi prosegue con un ciclo la cui condizione d uscita è determinata o dal raggiungimento di una soluzione soddisfacente, vale a dire caratterizzata da un valore di fitness giudicato buono, oppure dal raggiungimento di un numero prefissato di generazioni da elaborare. Il ciclo che realizza la generica iterazione di un algoritmo genetico determina il passaggio da una generazione ad un altra. Esso inizia con la selezione 29
32 dei genitori dalla popolazione corrente, ovvero degli individui che partecipano alla fase di riproduzione. Una possibile implementazione del test di sopravvivenza consiste nell assegnare a ciascun esemplare una probabilità di figurare nella lista dei genitori proporzionale al proprio valore di fitness. In questo modo, si seleziona il patrimonio genetico migliore di tutta la popolazione perché esso venga trasmesso alle generazioni successive. Alla fase di selezione dei genitori segue quella di riproduzione, mediante la quale avviene la generazione di nuovi punti dello spazio di ricerca: ciascuna coppia di individui prescelti genera, con probabilità p c (probabilità di crossover), una coppia di figli. Il processo di riproduzione simula il meccanismo biologico di crossover in cui si verifica uno scambio di gruppi di geni appartenenti ai due genitori. Nel caso più semplice viene selezionato casualmente un punto di rottura del cromosoma e quindi, in corrispondenza di questo taglio, si ha uno scambio delle parti omologhe. Tuttavia si possono adottare tecniche più sofisticate. L altro operatore genetico responsabile di variazioni nei parametri codificati dal cromosoma è la mutazione, che consiste nell effettuare, con una probabilità p m, una complementazione del valore assunto da un bit in corrispondenza ad una posizione scelta in modo casuale. Questo operatore interviene sui nuovi nati. La parte finale del ciclo comporta la fase di ricambio generazionale durante la quale si deve formare la popolazione da trasmettere alla generazione successiva, operando una selezione fra gli individui di cui si dispone (genitori e figli). Questa fase è necessaria per limitare la dimensione della popolazione di soluzioni che, altrimenti, crescerebbe esponenzialmente con l evolvere dell algoritmo. Esistono in merito diverse soluzioni. La prima costituisce il metodo di ricambio generazionale classico in cui i genitori lasciano il posto ai nuovi nati: alla popolazione dei genitori si sostituisce la popolazione dei figli. La seconda si basa ancora sul ricambio classico ma con l accorgimento di preservare dalla scomparsa l esemplare migliore in assoluto, qualora la nuova popolazione non dovesse contenere nessuna soluzione migliore di esso. La terza soluzione prevede una selezione naturale tra genitori e figli in base 30
33 alla qualità di ciascuno di essi, ossia sopravvivono solo gli esemplari migliori. Un ottimo algoritmo che risolve il problema di taglio bidimensionale con la tecnica del genetic search è quello realizzato da Beasley [15]. Questo algoritmo si fonda su una formulazione non lineare del problema. 3.3 Simulated Annealing Il simulated annealing è una tecnica stocastica che si ispira alla meccanica statistica per trovare soluzioni per problemi di ottimizzazione sia continua che discreta. Ricercare il minimo globale di una funzione di costo con molti gradi di libertà è un problema molto complesso, se questa funzione ammette un gran numero di minimi locali. Uno degli obiettivi principali dell ottimizzazione è proprio quello di evitare di rimanere intrappolati in un minimo locale. Questo è uno dei limiti più grandi delle tecniche di ricerca locale. I metodi basati sul simulated annealing applicano un meccanismo probabilistico che consente alla procedura di ricerca di fuggire da questi minimi locali. L idea è quella di accettare, in certi casi, oltre alle transizioni che corrispondono a miglioramenti nella funzione obiettivo, anche quelle transizioni che portano a peggioramenti nel valore di questa funzione di valutazione. La probabilità di accettare tali deterioramenti varia nel corso del processo di ricerca, e discende lentamente verso zero. Verso la fine della ricerca, quando vengono accettati solo miglioramenti, questo metodo diventa una semplice ricerca locale. Tuttavia, la possibilità di transire in punti dello spazio di ricerca che deteriorano la soluzione ottima corrente, consente di abbandonare i minimi locali ed esplorare meglio l insieme delle soluzioni ammissibili. La strategia che è alla base del simulated annealing si ispira al processo fisico di annealing (raffreddamento). Se il sistema si trova all equilibrio termico ad una data temperatura T, allora la probabilità n T (s) che esso sia in una data configurazione s dipende dall energia dello stato in questione E(s), e segue la distribuzione di Boltzmann: n T (s) = e E(s)/kT w e E(w)/kT (3.1) 31
34 dove k è la costante di Boltzmann e la sommatoria si estende a tutti gli stati possibili w. Fu per primo Metropolis nel 1953 a proporre un metodo per calcolare la distribuzione di un sistema di particelle all equilibrio termico usando un metodo di simulazione al computer. In questo metodo, supposto che il sistema si trovi in una configurazione q avente energia E(q), si genera un nuovo stato r, avente energia E(r), spostando una delle particelle dalla sua posizione: la nuova configurazione viene quindi confrontata con la vecchia. Se E(r) E(q) il nuovo stato viene accettato; se E(r) > E(q) esso non viene respinto, bensì viene accettato con una probabilità pari a: e (E(r) E(q))/kT (3.2) Secondo questo metodo, esiste dunque una probabilità non nulla di raggiungere stati di più alta energia, ossia di scavalcare le barriere di energia che separano i minimi globali dai minimi locali. Si noti che la funzione esponenziale esprime il rapporto tra la probabilità di trovarsi nella configurazione r e la probabilità di trovarsi in q. Kirkpatrick utilizzò lo schema del simulated annealing per problemi di ottimizzazione combinatoria. Per fare ciò, sostituì l energia con una funzione costo e gli stati di un sistema fisico di particelle con le soluzioni di un problema di minimizzazione. La perturbazione delle particelle con le soluzioni diventa allora equivalente ad uno spostamento nello spazio di ricerca verso un punto che si trova nelle vicinanze della soluzione corrente. La minimizzazione è raggiunta riscaldando dapprima il sistema, e poi raffreddandolo lentamente fino al raggiungimento della situazione di cristallizzazione in uno stato stabile. E da sottolineare il fatto che per raggiungere configurazioni di bassa energia non è sufficiente abbassare semplicemente la temperatura; è necessario, viceversa, attendere per ciascuna temperatura di transizione, un tempo sufficiente a raggiungere l equilibrio termico del sistema. Altrimenti, la probabilità di raggiungere stati di bassa energia è sensibilmente ridotta. La simulazione del processo di annealing, applicato a problemi di ottimizzazione, richiede diversi passi preparatori. Per prima cosa si devono identificare nel problema di ottimizzazione le analogie con i concetti fisici: l energia 32
35 diventa la funzione di costo, le configurazioni di particelle divengono le configurazioni di parametri (variabili decisionali) del problema da ottimizzare, ricercare uno stato di minima energia significa ricercare una soluzione che minimizza la funzione di costo, la temperatura diventa un parametro di controllo. Quindi, si deve scegliere un opportuno schema di annealing (cooling schedule), consistente nella regolazione dei parametri da cui dipende il processo di ottimizzazione: si tratta cioè di stabilire la legge di decadimento della temperatura e la durata del tempo necessario per il raggiungimento dell equilibrio termico a ciascuna temperatura. Infine si deve introdurre un metodo di perturbazione del sistema che consenta di esplorare lo spazio di ricerca generando nuove configurazioni. L algoritmo di annealing descritto da Kirkpatrick consiste nell esecuzione ripetuta dell algoritmo di Metropolis per ciascuna temperatura di transizione, fino al raggiungimento della configurazione ottima del sistema, ottenuta in prossimità della temperatura di cristallizzazione prefissata. L algoritmo di Metropolis, che accetta configurazioni che incrementano il costo, fornisce il meccanismo probabilistico che consente di evitare l intrappolamento nei minimi locali. Lo schema di principio di un algoritmo basato sul Simulated Annealing è riportato di seguito. 1. Inizializza C e X. 2. Poni i := Genera Y da X. 4. Se f(y ) f(x), poni X := Y. 5. Altrimenti se e (f(y ) f(x))/c > random(0, 1), poni X := Y. 6. Incrementa i di Se i == L prosegui, se no torna al punto Riduci il parametro C. 9. Se condizione d uscita, STOP, altrimenti torna al punto 2. L algoritmo parte con l inizializzazione di X, che rappresenta una possibi- 33
36 le soluzione, e di C che costituisce il parametro di controllo dell algoritmo stesso (equivale alla temperatura nel processo di annealing). Quindi si entra nel ciclo while da cui si esce solo quando risulterà vera la condizione di arresto: questa situazione si verifica quando si raggiunge una soluzione soddisfacente o in corrispondenza del raggiungimento della temperatura di congelamento prefissata per il sistema. Le fasi del ciclo while sono essenzialmente due; nella prima si entra in un ciclo for, durante la seconda si provvede a diminuire la temperatura del sistema secondo una legge prefissata che definisce lo schema di annealing. La prima fase corrisponde all esecuzione dell algoritmo di Metropolis e viene ripetuta L volte (questo è un altro parametro essenziale dello schema di annealing) per il raggiungimento dell equilibrio termico; la seconda fase determina la transizione da una temperatura ad un altra. Per quanto riguarda il problema della definizione dello schema di annealing, ovvero della definizione dei parametri di funzionamento, esistono in merito diverse soluzioni e una gran quantità di studi sono stati dedicati a questo problema. Per risolvere il problema di taglio bidimensionale, sono stati sviluppati alcuni algoritmi euristici che utilizzano una tecnica mista, fondendo simulated annealing e genetic search, tra questi meritano di essere citati quelli di Lai e Chan [11], [12] e di Leung et al [13], [14]. In questi algoritmi ogni soluzione è data da una lista ordinata di pezzi, la quale è trasformata in una sequenza di tagli da un placement algorithm. Questo algoritmo può essere, a seconda dei casi, un bottom-left algorithm o un difference algorithm. 3.4 Ant Colony Optimization La ant colony optimization (ACO) è una tecnica metaeuristica per problemi di ottimizzazione, ispirata al sistema di comunicazione delle formiche biologiche. Alcuni ricercatori hanno studiato, in laboratorio, il comportamento di una colonia di formiche alla quale era dato accesso ad una fonte di cibo (food), partendo dal loro nido (nest), attraverso due percorsi di diversa lunghezza (Figura 6). 34
37 Figura 6 Esperimento con vere formiche Inizialmente le formiche, giunte al bivio, si dividono equamente tra le due strade, mostrando quindi di fare questa scelta in modo casuale. Dopo un periodo di transizione di alcuni minuti però, la maggior parte di esse sceglierà sempre la via più breve verso il cibo. E stato osservato inoltre che, a regime, la probabilità di scegliere la strada più breve aumenta con l aumentare della differenza di lunghezza tra i due percorsi. Dorigo ha costruito un modello della funzione di probabilità con la quale avviene la scelta, al crescere del numero di formiche già passate. Questo fenomeno è stato spiegato supponendo che le formiche adottino un sistema di comunicazione indiretto basato su feromone, una sostanza odorosa che esse rilasciano sul terreno durante la marcia. Quando si trovano ad un bivio esse effettuano una scelta probabilistica della strada da prendere, assegnando una maggiore probabilità alla via con maggiore deposito di feromone. Questo porta ad un effetto autocatalizzante, per cui le strade più odorose verranno scelte con maggiore probabilità, ottenendo sempre più feromone e diventando quindi sempre più attrattive. Immaginiamo ora due formiche che partano allo stesso momento dal nido in una condizione di assenza di feromone sul percorso, e supponiamo anche che prendano due strade diverse al bivio. Quella che ha avuto la fortuna di scegliere la più breve farà ritorno al nido per prima, e quindi potrà ag- 35
38 giungere un secondo deposito di feromone sul suo percorso prima dell altra. Le successive formiche, quindi, saranno attratte dalla maggiore quantità di feromone del percorso effettivamente più breve e, con maggiore probabilità, sceglieranno quello. Lo stesso avviene se si considera il viaggio di ritorno, dal cibo verso il nido: raggiunto il bivio la scelta cadrà con maggiore probabilità sulla via che porta al nido, in quanto è stata percorsa da tutte le formiche indiscriminatamente. Questo semplice esempio potrebbe suggerire che, in presenza di feromone al bivio, una scelta deterministica sarebbe migliore, in quanto la soluzione ottima corrisponde sempre alla via più odorosa, fin dal passaggio della seconda formica. Purtroppo questo è vero solo se non siamo in presenza di minimi locali. Se invece la strada fosse costituita da un gran numero di passaggi intermedi, ed incroci con più di due direzioni possibili, si corre il rischio di fermarsi a soluzioni solo parzialmente ottime. Il giusto approccio invece è quello di utilizzare un gran numero di formiche in successione, guidate nella loro scelta da un algoritmo probabilistico, in modo che vengano esplorate anche soluzioni che apparentemente sono svantaggiose, ma che globalmente potrebbero rivelarsi quelle ottime. Questi concetti possono essere utilizzati nella soluzione di problemi di ottimizzazione, costruendo una colonia di formiche artificiali che, simulando l attività di ricerca del cibo, ottengano la soluzione ottima al problema. Queste formiche artificiali altro non saranno che degli agenti software, ognuno dei quali costruirà una soluzione parziale del problema (esattamente come ogni vera formica trova una soluzione parziale al problema del raggiungimento del cibo), basandosi sull informazione lasciata dagli agenti che hanno affrontato il problema in precedenza. Le informazioni generate da ogni agente, durante il suo cammino di ricerca di una soluzione, sono codificate in depositi di feromone artificiale associato ad ogni percorso attraversato. Questo feromone permane anche dopo il passaggio dell agente che lo ha depositato, e verrà percepito da quelli successivi. Lo schema di una procedura che utilizzi l ant colony optimization, può essere rappresentato così: 36
39 1. Inizializza i valori dei feromoni τ i. 2. Costruisci una soluzione s a per ogni formica a, utilizzando una tecnica euristica η e tenendo in considerazione il valore del feromeone τ, per un dato percorso. 3. Aggiorna i valori dei feromoni τ i. 4. Se condizione di termine, STOP, altrimenti torna al punto 2. Oltre all attività dei singoli agenti è possibile avere anche alcune funzionalità esterne: l evaporazione del feromone e le operazioni centralizzate. L evaporazione del feromone è un processo che fa diminuire il valore del deposito con il passare del tempo. Questo è necessario per evitare che il sistema converga troppo in fretta verso soluzioni che non sono ottime, non dando il tempo agli agenti di esplorare altre soluzioni. Per operazioni centralizzate si intendono tutti quegli interventi che non sono messi in atto direttamente dagli agenti, come per esempio l aggiunta di un deposito extra di feromone su un particolare percorso che, in un certo momento, sembra essere promettente, oppure la modifica di alcuni parametri di funzionamento degli agenti in particolari condizioni. Un problema chiave nella progettazione di algoritmi di tipo ACO è il bilanciamento tra esplorazione e sfruttamento. Quando gli agenti si muovono principalmente alla ricerca di zone già esplorate, quindi con elevati depositi di feromone, essi sfruttano le esperienze degli agenti precedenti, cercando di ottenere il miglior risultato finale. Al contrario un movimento principalmente casuale porterebbe all esplorazione di nuove zone. Se gli agenti si muovessero solo in funzione del feromone, dopo poco tutti percorrerebbero sempre la stessa strada, portandosi ad una condizione di stagnazione. D altra parte un comportamento troppo casuale porterebbe alla dispersione del feromone, rallentando o impedendo la messa in evidenza di una soluzione ottima. Per ottenere il giusto equilibrio tra questi comportamenti, normalmente si agisce sul deposito di feromone e sull influenza che esso ha sugli agenti. La sua distribuzione infatti determina la probabilità che una soluzione sia 37
40 visitata o meno. Una tecnica molto usata per evitare l eccessivo sfruttamento è quella di fare in modo che la quantità di feromone che un agente deposita sia proporzionale alla bontà del percorso effettuato. In questo modo si permette alle nuove strade, se sono migliori delle vecchie, di emergere più velocemente. Un algoritmo di tipo ACO che risolve il problema di taglio, è stato sviluppato da Ducatelle e Levine [26]. 3.5 GRASP La tecnica GRASP (Greedy Randomized Adaptive Search Procedure) è stata sviluppata da Feo e Resende [16] per risolvere Set Covering Problems ed è una procedura iterativa in cui ogni iterazione è caratterizzata da due fasi: fase costruttiva; fase di miglioramento (ricerca locale). La soluzione migliore trovata durante tutte le iterazioni viene mantenuta come risultato della procedura. Lo pseudocodice della procedura può essere rappresentato così: 1. Carica i dati iniziali del problema. 2. Inizializza la miglior soluzione trovata (BSF). 3. Poni S = ConstructivePhase(). 4. Poni S = ImprovementPhase(S). 5. Se S > SBF poni SBF = S. 6. Se condizione di termine, STOP, altrimenti torna al punto 3. Le condizioni di termine possono essere di diversa natura; la procedura può ad esempio terminare qualora sia stato raggiunto il numero massimo di iterazioni consentite, oppure sia stata trovata una soluzione il cui valore della funzione obbiettivo sia uguale all upper bound calcolato. 38
41 Durante la fase costruttiva della procedura, viene costruita una soluzione ammissibile in maniera iterativa aggiungendo un elemento alla volta; ad ogni iterazione di questa fase la scelta dell elemento che deve essere aggiunto è determinata ordinando, rispetto ad una funzione di tipo greedy, tutti gli elementi in una lista di candidati. Questa funzione misura il beneficio (miopico) associato alla scelta di ciascun elemento. L euristica è definita come adaptive (adattabile) perché i benefici associati ad ogni elemento sono aggiornati ad ogni iterazione della fase di costruzione per riflettere i cambiamenti avvenuti in seguito alla selezione dell elemento nell iterazione precedente. La componente probabilistica della procedura si manifesta nella scelta dell elemento che ad ogni iterazione deve essere aggiunto per formare la soluzione; esso è infatti scelto casualmente (randomized) tra i migliori candidati nella lista e non è detto quindi che sia il migliore in assoluto. La lista contenente i migliori candidati che possono essere scelti viene indicata col termine RCL (Restricted Candidate List) e può essere fissa oppure variare ad ogni iterazione seguendo l andamento di un parametro δ. Questa tecnica di scelta permette dunque di ottenere soluzioni diverse ad ogni iterazione della procedura GRASP. La fase di miglioramento, invece, parte dalla soluzione trovata durante la fase costruttiva e, attraverso una ricerca locale, esplora il vicinato finché non viene raggiunto un punto di minimo locale. Per quanto riguarda la risoluzione del problema di taglio bidimensionale con l utilizzo di una tecnica GRASP è da menzionare l algoritmo realizzato da Alvarez-Valdes et al [1]. 3.6 Tabu Search Nella ricerca locale classica, ogniqualvolta si esplora il vicinato di una soluzione, l unica informazione relativa alla storia dell algoritmo fino a quel momento è la migliore soluzione corrente e il corrispondente valore della funzione obiettivo. L idea della tecnica tabu search è invece quella di mantenere una me- 39
42 moria di alcune informazioni sulle ultime soluzioni visitate, orientando la ricerca in modo tale da permettere di uscire da eventuali minimi locali. Più precisamente, vedremo che la struttura del vicinato di una soluzione varia da iterazione a iterazione. Come in tutti gli algoritmi di ricerca locale, se, nell esplorazione del vicinato N(x) di una soluzione x, si scopre una soluzione migliore dell ottimo corrente, si ha una transizione su quella soluzione e si inizia a esplorare quel vicinato. Tuttavia, se la soluzione corrente è un minimo locale, l algoritmo di ricerca locale si fermerebbe. E chiaro allora che, per poter sfuggire ai minimi locali, è necessario accettare mosse che possano portare a un peggioramento della soluzione corrente, pur di spostarsi sufficientemente lontano dal minimo locale. Supponendo allora di trovarci in un minimo locale x, dobbiamo anzitutto scegliere su quale soluzione spostarci, dal momento che nessuna, in N(x), sarà migliore di x. Negli algoritmi di tabu search si fa in genere la scelta di spostarsi sulla soluzione y N(x) per la quale è minimo il peggioramento della funzione obiettivo. A questo punto però nasce il problema che sta alla base dell idea di tabu search. Se ci portiamo sulla soluzione y, ed esploriamo il suo vicinato, è assai probabile che la migliore soluzione in N(y) risulti essere proprio x, cioè quella da cui vogliamo viceversa sfuggire. Più in generale, dal momento che stiamo permettendo anche mosse che non migliorano la funzione obiettivo, può sempre presentarsi il pericolo, anche dopo un certo numero di mosse, di tornare su una soluzione già visitata. Ecco allora che entra in gioco l uso della memoria. L idea è quella di utilizzare le informazioni sulle ultime mosse effettuate per evitare il pericolo di ciclaggio. Precisamente, mantenendo memoria delle ultime mosse che hanno portato alla soluzione attuale, sarà possibile proibire quelle mosse per un certo tempo al fine appunto di prevenire ricadute in punti già visitati. Dunque, mentre nella ricerca locale si parla di vicinato N(x) di una soluzione x, nella tabu search possono essere escluse, dall esplorazione di N(x), alcune soluzioni, a seconda dell itinerario seguito per giungere in x. Diciamo allora che l insieme delle soluzioni da esplorare dipende, oltre che dalla soluzione x, anche dall iterazione k del metodo, ossia il vicinato diviene 40
43 N(x, k). Per realizzare questo concetto, si fa uso di uno strumento chiamato tabu list T. La tabu list è una coda in cui vengono memorizzate le ultime T mosse effettuate. Le mosse opposte a queste, che potrebbero dunque avere l effetto di riavvicinarsi a soluzioni già visitate, vengono proibite nella situazione attuale, cioè vengono escluse dal vicinato della soluzione corrente tutte le soluzioni ottenibili per mezzo di una mossa tabu. Si noti che si potrebbe pensare di memorizzare direttamente le ultime T soluzioni, ma questo può essere estremamente poco pratico per problemi di grandi dimensioni. Si preferisce allora memorizzare direttamente le mosse. La tabu list è una coda, nel senso che, a ogni passo, la mossa che era nella tabu list da maggior tempo viene cancellata, e torna a essere quindi ammessa. Anche se il ruolo della tabu list dovrebbe essere abbastanza chiaro, non è in generale ovvio stabilire quale debba essere la lunghezza più appropriata per la tabu list. Infatti, una tabu list troppo lunga potrebbe inutilmente vincolare il processo di ricerca anche quando la distanza percorsa da una determinata soluzione è già sufficientemente elevata da rendere improbabile un ritorno su tale soluzione. D altro canto, una tabu list troppo corta può presentare invece il problema opposto, cioè potrebbe rendere possibile il ciclaggio. Il valore ottimale della lunghezza della tabu list varia tipicamente da problema a problema anzi, talora addirittura da istanza a istanza, ma comunque raramente eccede il valore dieci. Rispetto a un algoritmo di ricerca locale, va definito il criterio di arresto, dal momento che esso non è più dato dall evento per cui la funzione obiettivo non migliora. In pratica si utilizzano i seguenti criteri di arresto: il numero di iterazioni raggiunge un valore k max prefissato; il numero di iterazioni dall ultimo miglioramento della funzione obiettivo raggiunge un valore k max prefissato; è possibile certificare che l ottimo corrente è l ottimo globale. Un ultimo ingrediente di un algoritmo di tabu search nasce dalla seguen- 41
44 te osservazione. A un generico passo dell algoritmo, si hanno un insieme di mosse tabu. Può però accadere che la soluzione in cui ci si porterebbe applicando una di queste mosse tabu abbia delle caratteristiche che la rendono in qualche modo interessante. In tal caso si esegue la mossa, nonostante fosse nella tabu list. Tali caratteristiche vengono chiamate criteri di aspirazione. Quello di gran lunga più utilizzato è quello per cui una mossa tabu può essere forzata (overruled) se la soluzione cui essa dà luogo ha un valore di funzione obiettivo migliore dell ottimo corrente (dunque tra l altro si tratta certamente di una soluzione mai visitata). Un approccio di tabu search può comprendere molti altri accessori, quali le tabu list di lunghezza variabile nel corso dell algoritmo, nonché strategie di diversificazione e di intensificazione della ricerca. A questo punto possiamo riassumere la struttura di un algoritmo di tabu search (che come è evidente generalizza la ricerca locale): 1. Scegli una soluzione iniziale x; k := 0 e inizializza la tabu list T =. 2. Incrementa il contatore k e genera le soluzioni nel vicinato N(x, k). 3. Trova la soluzione y per cui f(y) (o un altra funzione f (y)) è minima con y N(x, k), y x e che non viola nessun tabu oppure che soddifa un criterio di aspirazione. 4. Se f(y) < f(x), poni x := y. 5. Aggiorna T inserendo la mossa che fa passare da x a y e poni x := y. 6. Se condizione d uscita, STOP, altrimenti torna al punto 2. La tabu search è applicabile, in linea di principio, pressoché a qualsiasi problema di ottimizzazione combinatoria. Tuttavia, alla scelta progettuale relativa al vicinato (come del resto già nel caso della ricerca locale) va aggiunta ora quella relativa alla definizione della mossa tabu e alla lunghezza della tabu list. L esperienza computazionale mostra che l elemento più importante nell efficienza di un algoritmo di tabu search è la scelta del vicinato. Una caratteristica importante di un vicinato è la raggiungibilità della soluzione 42
45 ottima. Ci si chiede cioè se, data una qualunque soluzione iniziale, esiste un cammino di soluzioni che, passando da un vicinato all altro, consente di raggiungere l ottimo globale. Non si richiede che l algoritmo sia in grado effettivamente di trovarlo (questo dipenderà da come vengono scelte le mosse tabu, dal criterio di arresto etc.), ma solo che con una certa definizione di vicinato questo sia possibile, almeno in teoria. Un altro aspetto molto rilevante è la scelta della funzione obiettivo. La scelta più naturale ovviamente è quella di usare nell algoritmo di tabu search la funzione che si desidera minimizzare. Questa scelta però non necessariamente è quella più conveniente. In molti problemi, tipicamente il valore ottimo è un numero molto basso, e comunque non molto distante dal valore della soluzione iniziale, se questa è prodotta con una qualsiasi delle euristiche rapide presenti in letteratura. La conseguenza è che un numero enorme di soluzioni ammissibili hanno in realtà lo stesso valore, e dunque la funzione obiettivo assai raramente avrà dei miglioramenti nel corso dell algoritmo. La conseguenza è che l algoritmo seguirà un cammino abbastanza casuale nella regione ammissibile, dal momento che un numero elevatissimo di direzioni di ricerca apparirebbero altrettanto appetibili. Si può allora utilizzare una funzione obiettivo secondaria f (come indicato al passo 3) legata ovviamente a quella primaria, ma che consenta di ovviare a questo problema. Tra gli algoritmi che utilizzano la tecnica del tabu search per la risoluzione di problemi di taglio bidimensionale va citato quello sviluppato da Alvarez- Valdes et al [2]. 43
46
47 Capitolo 4 Sviluppo di un algoritmo GRASP Per migliorare i risultati prodotti dall algoritmo euristico costruttivo, ho deciso di sviluppare un algoritmo di tipo GRASP, per il problema di taglio bidimensionale, non a ghigliottina, seguendo il lavoro svolto da Alvarez-Valdes et al [1]. 4.1 Fase Costruttiva La fase costruttiva coincide con l algoritmo costruttivo presentato in precedenza, introducendo però delle procedure di scelta casuale dei pezzi e dei rettangoli. Definiamo s i lo score di un pezzo i (che può essere uguale a e i o a v i a seconda del criterio di ordinamento di P prescelto) e s max = max{s i i P}. A questo punto si può scegliere tra tre alternative: 1. Selezionare il pezzo i a caso nell insieme S = {j s j δs max } dove δ è un parametro da determinare (0 < δ < 1). S è chiamato anche Restricted Set of Candidates. 2. Selezionare il pezzo i a caso nell insieme formato dal 100(1 δ)% dei pezzi migliori. 45
48 3. Selezionare il pezzo i tra tutti quelli di P ma con una probabilità di essere scelto proporzionale allo score s i e pari a p i = s i sj Scelta del parametro δ Qualora si opti per l utilizzo della prima o della seconda alternativa, la scelta del parametro δ risulta fondamentale per ottenere una buona efficienza dell algoritmo. Un analisi preliminare dimostra che nessun valore di δ produce sempre il miglior risultato, perciò vengono prese in considerazione diverse strategie, le quali consistono nel far variare il parametro δ in maniera casuale o sistematica durante il processo iterativo. Queste strategie di scelta sono: 1. Ad ogni iterazione, scegliere δ a caso nell intervallo [0.4, 0.9]. 2. Ad ogni iterazione, scegliere δ a caso nell intervallo [0.25, 0.75]. 3. Ad ogni iterazione, δ assume a turno uno dei seguenti valori: 0.4, 0.5, 0.6, 0.7, 0.8, δ = Reactive GRASP Nel Reactive GRASP, proposto da Prais e Ribeiro [18], δ è inizialmente scelto a caso da un insieme di valori discreti, ma dopo un certo numero di iterazioni, la qualità delle soluzioni trovate con ogni valore di δ viene presa in considerazione e la probabilità associata ai valori di δ che producono le soluzioni migliori viene incrementata. La procedura è descritta in dettaglio nella Figura 7, seguendo le indicazioni espresse da Delorme et al [19]. Il valore di α è fissato a 10, come suggerito da Prais e Ribeiro [18]. 46
49 Inizializzazione: D = {0.1, 0.2,..., 0.9}, insieme dei possibili valori di δ S best = 0; S worst = n δ = 0, numero delle iterazioni con δ, δ D. Sum δ = 0, somma dei valori delle soluzioni ottenute con δ. P (δ = δ ) = p δ = 1/ D, δ D, con p δ probabilità associata a δ. numiter = 0 While (numiter < maxiter) { } Scegli δ da D con probabilità p δ n δ = n δ + 1 numiter = numiter + 1 Applica la Fase Costruttiva ottenendo la soluzione S Applica la Fase di Miglioramento ottenendo la soluzione S If S > S best then S best = S If S < S worst then S worst = S Sum δ = Sum δ + S If mod(numiter, 100) == 0 (ogni 100 iterazioni): ) α eval δ = δ D p δ = ( ( Sum δ /n δ S worst S best S worst eval δ δ D eval δ ) δ D Figura 7 Reactive GRASP 4.2 Fase di Miglioramento La fase di miglioramento parte dalla soluzione ottenuta nella fase costruttiva e consiste in un tentativo di migliorare la soluzione trovata facendo ricorso ad una procedura di ricerca locale. Sono possibili tre diverse alternative: 47
50 1. Si seleziona un blocco adiacente ad un rettangolo vuoto e si prende in considerazione il fatto di ridurne il numero di pezzi o di eliminarlo completamente. I pezzi rimanenti sono poi spostati verso gli angoli e i rettangoli vuoti vengono fusi. A questo punto si applica nuovamente la fase costruttiva alla nuova lista di rettangoli vuoti, inserendo però prima i pezzi a maggiore efficienza e i ed utilizzando per primi i rettangoli vuoti con area minore (Figura 8). Se la soluzione trovata migliora quella della fase precedente, il processo va avanti e si prende in considerazione un nuovo blocco. Selezione Riduzione Spostamento Riempimento Figura 8 Metodo I 2. Questa seconda procedura è una semplificazione di quella precedente in quanto i pezzi non vengono mossi verso gli angoli e i nuovi rettangoli vuoti sono fusi solamente con rettangoli vuoti adiacenti e già esistenti (Figura 9). Selezione Riduzione Riempimento Figura 9 Metodo II 3. Il terzo metodo consiste nell eliminare l ultimo k% dei blocchi inseriti (per esempio l ultimo 10%), spostare i pezzi rimanenti verso gli angoli, 48
51 fondere i rettangoli vuoti ed applicare ai nuovi spazi creati un algoritmo costruttivo deterministico come quello proposto da Beltrán et al [20] (vedi Figura 10, in cui i numeri nei pezzi riflettono l ordine in cui questi sono stati inseriti durante la fase costruttiva). Selezione Riduzione Riempimento Figura 10 Metodo III 4.3 Variazione dei vincoli dei pezzi Durante il processo iterativo si ottiene la miglior soluzione attuale conosciuta di valore v best. E possibile utilizzare questo valore per far variare il lower bound P i di alcuni pezzi, che devono comparire se si vuole migliorare la soluzione, e l upper bound Q i di alcuni pezzi, la cui inclusione non permetterebbe di migliorare la soluzione Aumento dei lower bound P i Definiamo total pieces = m i v i Q i, il valore totale di tutti i pezzi disponibili; se c è un pezzo i con P i < Q i e total pieces (Q i P i ) v i v best, una soluzione con il numero minimo di pezzi P i non può migliorare la soluzione v best. Ogni soluzione migliore deve includere più pezzi di i e il relativo P i deve essere aumentato. Se calcoliamo t come max t : total pieces t v i > v best (4.1) t 0, t Q i P i (4.2) 49
52 il nuovo valore di P i sarà P i = Q i t. Questo lower bound migliorato può essere utile nella fase costruttiva in cui i pezzi con P i > 0 sono tagliati per primi, e nella fase di miglioramento in cui i pezzi che raggiungono il loro lower bound non sono candidati alla rimozione Diminuzione degli upper bound Q i Definiamo R = P i >0 P i l i w i, l area totale dei pezzi che devono apparire per forza in ogni soluzione ammissibile, R v = P i >0 P i v i, il valore di questi pezzi e e max = max{e i, i = 1,..., m}, la massima efficienza dei pezzi. Se c è un pezzo i con Q i > P i e e i < e max che soddisfa la disequazione Q i l i w i (e max e i ) e max (L W R) + R v v best (4.3) ogni soluzione con Q i copie del pezzo i non può migliorare la soluzione v best. Quindi ogni soluzione migliore dovrà avere al massimo un numero di pezzi di i minore di Q i. Se calcoliamo t come max t : t l i w i (e max e i ) < e max (L W R) + R v v best (4.4) t 0, t Q i P i (4.5) il nuovo valore di Q i sarà Q i = P i + t. Questa diminuzione dell upper bound può essere utile in entrambe le fasi, soprattutto se Q i dovesse essere posto a 0, il pezzo i dovrebbe essere rimosso, favorendo un notevole risparmio computazionale nella scelta dei pezzi. 4.4 Scelta delle migliori strategie Prima di implementare l algoritmo GRASP, è bene sciogliere alcuni nodi rimasti in sospeso. Si tratta di scegliere le opzioni migliori tra quelle fornite nelle varie strategie sopra discusse. Per effettuare questa scelta, ho fatto tesoro dell esperienza computazionale svolta da Alvarez-Valdes et al [1]. Quindi l algoritmo GRASP completo dovrà utilizzare le seguenti strategie: 50
53 Selezione del pezzo: il pezzo che produce il maggior incremento nella funzione obiettivo. Selezione del rettangolo: casuale. Procedura di randomizzazione: Restricted Candidate List. Selezione del parametro δ: Reactive GRASP. Fase di miglioramento: metodo 3 con rimozione del 10% dei pezzi. Numero di iterazioni: L algoritmo deve arrestarsi quando ha raggiunto il limite massimo di iterazioni oppure quando la soluzione trovata risulti uguale al corrispondente upper bound. Stando sempre all esperienza di Alvarez-Valdes et al, l incremento dei lower bound P i dei pezzi non produce significativi vantaggi sulle performance dell algoritmo (e pertanto non verrà implementato), mentre l incremento degli upper bound Q i ha un effetto considerevole, specialmente nei problemi in cui ci sono differenze notevoli tra le efficienze dei pezzi. In media, più del 60% dei pezzi sono scartati non appena vengono trovate buone soluzioni. 51
54
55 Capitolo 5 Sviluppo di un algoritmo Tabu Search Per comparare i risultati ottenuti con l algoritmo GRASP e per cercare di migliorarli ulteriormente, ho deciso di sviluppare anche un algoritmo che utilizzi la tecnica metaeuristica del Tabu Search. Per far ciò ho seguito con attenzione il lavoro svolto da Alvarez-Valdes et al [2]. Gli elementi base dell algoritmo sono descritti nelle sezioni seguenti. 5.1 Definizione delle mosse Lo spazio delle soluzioni, in cui è possibile muoversi, è composto solo da soluzioni ammissibili. In questo spazio vengono definite diverse mosse per muoversi da una soluzione ad un altra. Una soluzione iniziale può essere ottenuta attraverso l applicazione del già citato algoritmo costruttivo. Distinguiamo tra due tipi di mosse: una riduzione di un blocco e un inserimento di un blocco. Nella riduzione viene ridotta la dimensione di un blocco esistente, eliminando alcune delle sue righe o colonne. Nell inserimento, un nuovo blocco è aggiunto alla soluzione. Per entrambe le mosse verrà presentato prima uno schema della procedura e poi un esempio dettagliato. 53
56 5.1.1 Riduzione di un blocco La riduzione delle dimensioni di un blocco avviene seguendo i seguenti passi elementari: 1. Inizializzazione L=lista dei rettangoli vuoti della soluzione corrente C=lista dei blocchi della soluzione corrente 2. Scelta del blocco da ridurre Per prima cosa bisogna scegliere b, uno dei blocchi di C, formato da k colonne e l righe del pezzo i. Poi va selezionato il numero di colonne (righe) da eliminare, 1 r k (1 r l), mantenendo il numero dei pezzi nella soluzione x i P i. Se P i = 0, il blocco può scomparire completamente. Il nuovo rettangolo vuoto R va aggiunto a L. 3. Spostamento dei blocchi rimanenti verso gli angoli più vicini La lista dei rettangoli vuoti L è aggiornata secondo questo criterio. 4. Riempimento dei rettangoli vuoti con nuovi blocchi A questo punto va applicato l algoritmo costruttivo partendo dalle composizioni attuali di L e C, e con P contenente i pezzi che possono ancora essere tagliati e aggiunti alla soluzione corrente. Prima di procedere con il processo costruttivo, i rettangoli vuoti di L devono essere fusi, per adattarsi in modo migliore alla lista dei pezzi P. Quando viene selezionato il nuovo pezzo da tagliare, non deve essere preso in considerazione il pezzo i del blocco ridotto, finché un altro pezzo non sia stato incluso nella soluzione modificata. 5. Fusione dei blocchi con la stessa struttura Infine è necessario provare a fondere blocchi dello stesso pezzo i con la stessa lunghezza o la stessa larghezza, se sono adiacenti e hanno un 54
57 lato in comune, oppure se uno di essi può essere spostato in modo da renderli adiacenti. a) selezione b) riduzione c) movimento agli angoli d) riempimento Figura 11 Riduzione di un blocco a) riduzione b) spostamento c) fusione d) riempimento Figura 12 Rettangoli vuoti nella mossa di riduzione Nella Figura 11 vediamo un esempio di mossa di riduzione su un istanza proposta da Jakobs [23] e usata in seguito da Leung et al [14]. Il rettangolo base è R = (120, 45), m = 22 e M = 25 pezzi che possono essere tagliati da esso, riempiendolo completamente. La Figura 11(a) mostra una soluzione con 23 pezzi nella quale non possono essere inseriti i due pezzi (6, 12). L è composta da R 1 = (60, 24, 72, 30) e R 2 = (72, 18, 84, 24) (in grigio chiaro). 55
58 Per prima cosa un blocco composto da un pezzo (12, 21) viene selezionato e ridotto, così facendo scompare dalla soluzione creando un nuovo rettangolo vuoto R 3 = (72, 24, 84, 45) che viene aggiunto a L (Figura 11(b)). A questo punto un blocco composto da un pezzo (12, 15) viene mosso verso l angolo in alto a destra. Quindi L = {R 1, R 2, R 4, R 5 } dove R 4 = (60, 30, 72, 45) e R 5 = (72, 24, 84, 30) (Figura 11(c)). In seguito l algoritmo costruttivo riempie i rettangoli vuoti. Per prima cosa vengono fusi R 1 e R 4 per formare R 6 = (60, 24, 72, 45), e R 2 e R 5 per formare R 7 = (72, 18, 84, 30). Poi R 7 viene selezionato e riempito completamente con due pezzi (6, 12). Infine R 6 viene riempito con il pezzo eliminato all inizio. La soluzione finale, che è anche quella ottima, è mostrata nella Figura 11(d) Inserimento di un blocco L inserimento di un nuovo blocco avviene eseguendo la sequenza di passi indicata qui sotto: 1. Inizializzazione L=lista dei rettangoli vuoti della soluzione corrente C=lista dei blocchi della soluzione corrente 2. Scelta del blocco da inserire Bisogna prendere un pezzo i con x i Q i, in modo tale da formare un blocco con k colonne e l righe (k l Q i x i ) di pezzi di tipo i. 3. Selezione della posizione in cui inserire il nuovo blocco Due strategie sono state prese in considerazione per scegliere la posizione del nuovo blocco. In entrambi i casi il blocco è posizionato in modo da ricoprire parzialmente o totalmente uno o più rettangoli vuoti. Per ogni rettangolo vuoto, si considerano le quattro alternative in cui un angolo del rettangolo è scelto per il corrispondente angolo del blocco. Se le dimensioni del blocco sono maggiori di quelle del rettangolo, il blocco può ricoprire altri blocchi oppure può occupare parte di altri rettangoli vuoti. 56
59 Si seleziona solo un rettangolo vuoto in modo che, posizionando il blocco con il suo angolo inferiore sinistro sopra l angolo inferiore sinistro del rettangolo, venga massimizzata l area ricoperta. Per questo rettangolo vengono considerate le quattro alternative viste sopra. 4. Rimozione dei pezzi della soluzione che si sovrappongono al blocco inserito Aggiornamento di C (alcuni blocchi vengono ridotti o eliminati) Aggiornamento di L (nuovi rettangoli vuoti possono comparire) 5. Riempimento dei rettangoli vuoti con nuovi blocchi 6. Fusione dei blocchi con la stessa struttura Questi ultimi due punti coincidono con gli ultimi due della riduzione dei blocchi. Nella Figura 13 vediamo un esempio della seconda strategia di inserimento dei blocchi nei rettangoli. Nella Figura 13(a) due rettangoli vuoti, in grigio, sono presi in considerazione per l inserimento del nuovo blocco, in bianco. Poiché l area occupata maggiore corrisponde al rettangolo 1, viene scelto quest ultimo. Nella Figura 13(b), vengono mostrate le quattro possibili alternative per inserire il nuovo blocco nei corrispondenti quattro angoli del rettangolo. a) Scelta del rettangolo b) Possibili posizioni Figura 13 Selezione della posizione del nuovo blocco 57
60 a) Soluzione iniziale b) Inserimento c) Eliminazione sovrapposizioni d) Fusione e riempimento Figura 14 Inserimento di un blocco Nella Figura 14 vediamo un esempio dell utilizzo della mossa di inserimento su un istanza proposta da Fekete e Schepers [9] e in seguito utilizzata da Beasley [6]. Il rettangolo base è R = (100, 100), m = 15 e M = 50 pezzi che possono essere tagliati da esso. La Figura 14(a) mostra una soluzione di valore z = La lista dei rettangoli vuoti L è formata da R 1 = (70, 41, 72, 81) e R 2 = (72, 80, 100, 81). Per prima cosa viene sele- 58
61 zionato il pezzo i = 5 di dimensioni (6, 40) con Q i = 5 e solo due copie nella soluzione attuale, e viene scelto un blocco b formato da un solo pezzo. In seguito viene posizionato tale blocco sopra R 1, sovrapponendo l angolo in alto a sinistra del blocco con l angolo in alto a sinistra del rettangolo. Il blocco b ricopre completamente R 1 e parzialmente R 2, il quale diventa R 3 = (76, 80, 100, 81). Il blocco ricopre in parte anche un blocco esistente (Figura 14(b)). Quindi vengono rimossi i pezzi della soluzione iniziale che si sovrappongono al nuovo blocco inserito, producendo due nuovi rettangoli R 4 = (76, 40, 78, 80) e R 5 = (72, 40, 76, 41) (Figura 14(c)). A questo punto la procedura di riempimento inizia con L = {R, R 4, R 5 }. Prima però R 3 e R 4 vengono fusi generando R 6 = (76, 40, 78, 81) e R 7 = (78, 80, 100, 81). Mentre nessuno dei pezzi poteva entrare in R 3 o R 4, ora invece un pezzo i = 13 di dimensione (2, 41) può essere inserito in R 6. La nuova soluzione è migliore di quella iniziale ed ha un valore z = 27718, ottima per il problema (Figura 14(d)). 5.2 Mosse da esaminare Ad ogni iterazione vengono esaminate tutte le possibili mosse di riduzione e inserimento che possono essere applicate alla soluzione corrente. Riduzione: 1. Bisogna prendere ogni blocco della soluzione, uno per volta, in ordine casuale. 2. Vanno considerate tutte le possibilità di riduzione nelle direzioni adiacenti ai rettangoli vuoti. Inserimento: 1. Bisogna selezionare un pezzo per cui il numero di copie x i nella soluzione è minore di Q i, uno per volta, in ordine casuale. 2. Vanno considerati tutti i blocchi che è possibile costruire con questo pezzo. 59
62 3. Vanno considerate tutte le alternative per posizionare il blocco all interno di un rettangolo vuoto. 5.3 Selezione della mossa La funzione obiettivo consiste solo nel massimizzare il valore dei pezzi tagliati f(x) = i v i x i. Tuttavia, se le mosse fossero valutate in accordo con questa funzione, potrebbero esserci della mosse con la stessa valutazione. Quindi, in caso di valori uguali della funzione obiettivo, è possibile valutare la mossa attraverso l utilizzo di una funzione obiettivo secondaria g(x) = k 1 S +k 2 L + k 3 C + k 4 F. S (Simmetria): è preferibile non esplorare soluzioni simmetriche, ma vengono preferite soluzioni in cui i rettangoli vuoti sono più concentrati nella parte destra e in quella in alto del rettangolo base. Se non esiste una soluzione simmetrica e se i rettangoli vuoti sono concentrati a destra e in alto, allora S = 1, altrimenti S = 0. L (Numero dei rettangoli vuoti): se è possibile, vengono preferite soluzioni in cui il numero di rettangoli vuoti è il più basso possibile. C (Rettangoli vuoti accentrati e concentrati): sono preferibili soluzioni in cui i rettangoli vuoti sono accentrati e concentrati il più possibile, perché in questo modo è più semplice eseguire fusioni ed ottenere spazi per nuovi pezzi. Dato ER il più piccolo rettangolo che contiene tutti i rettangoli vuoti, C = 1 (0.75 rd ra) dove rd è la distanza tra il centro di ER e il centro del rettangolo base, diviso la distanza tra il centro del rettangolo base e il suo angolo in basso a sinistra, e ra è l area di ER diviso l area del rettangolo base. F (Ammissibilità). Nei problemi di tipo doubly constrained, la soluzione iniziale può non essere ammissibile. In questo caso F = 1, altrimenti F = 0. 60
63 Questi criteri sono aggiunti alla funzione obiettivo secondaria con alcuni coefficienti che riflettono la loro relativa importanza, in accordo con i risultati preliminari ricavati da un sottoinsieme di problemi. In questa implementazione questi fattori assumono i seguenti valori: 5.4 Tabu list Criterio Coefficiente Valore Simmetria k Rettangoli vuoti k Rettangoli accentrati k 3 50 Ammissibilità k La tabu list contiene, per ogni soluzione, la seguente coppia di attributi: il valore della funzione obiettivo e il più piccolo dei rettangoli ER contenente tutti i rettangoli vuoti. Una mossa è quindi tabu se questi due attributi della nuova soluzione coincidono con una delle coppie della tabu list. La dimensione della tabu list varia in maniera dinamica. Dopo un certo numero di iterazioni senza migliorare la soluzione, le lunghezza è scelta a caso nell intervallo [0.25 M, 0.75 M], dove M = i Q i. Il criterio di aspirazione permette di muoversi verso una soluzione tabu se essa migliora la soluzione ottenuta finora. 5.5 Intensificazione e diversificazione Le mosse che sono state definite sopra consentono un alto livello di diversificazione. Tuttavia sono possibili due ulteriori strategie di diversificazione: Memoria a lungo termine Durante il processo di ricerca, viene mantenuta in memoria la frequenza di ogni pezzo che appare nelle soluzioni. Questa informazione è utilizzata sia per la diversificazione che per l intensificazione. 61
64 Quando viene usata la diversificazione, vengono favorite le mosse che coinvolgono pezzi che non appaiono molto frequentemente nelle soluzioni, in modo da favorire l apparizione di nuovi pezzi. Quando viene usata per l intensificazione, vengono considerati solo i pezzi che corrispondono a soluzioni di alta qualità, in modo da favorire questi pezzi e far sì che appaiano ancora in nuove soluzioni. Durante la fase di diversificazione, la funzione obiettivo è modificata sottraendo un termine che è la somma delle frequenze dei pezzi che appaiono nelle soluzioni: f(x) f(x) i freq(p i ) Durante una fase di intensificazione, la funzione obiettivo è modificata aggiungendo un termine che riflette la frequenza dei pezzi nell insieme delle soluzioni d elite E: f(x) f(x) + K freq(p i ) i E Ripartenza Stando a quanto detto prima a riguardo della funzione obiettivo secondaria, vengono preferite le soluzioni che soddisfano il criterio di simmetria. Dopo un certo numero di iterazioni senza migliorare la miglior soluzione trovata, la soluzione attuale viene sostituita da quella che si ottiene eseguendo una simmetria orizzontale e una verticale su di essa. La nuova soluzione ottenuta in questa maniera dovrebbe essere abbastanza diversa da quelle esaminate di recente ed è assunta come il nuovo punto di partenza per la ricerca. 5.6 Variazione dei vincoli dei pezzi La variazione dei lower bound P i e degli upper bound Q i dei pezzi, per aumentare l efficienza dell algoritmo, avviene in maniera del tutto identica a quanto specificato nell omonima sezione dell algoritmo GRASP. 62
65 5.7 Path relinking Il Path Relinking è un approccio per integrare diversificazione e intensificazione nel contesto del Tabu Search (Glover e Laguna [24]). Questo approccio genera nuove soluzioni esplorando traiettorie che collegano soluzioni di alta qualità. Partendo da una di queste soluzioni, chiamata soluzione iniziale, viene generato un percorso nello spazio delle soluzioni che conduca ad un altra soluzione, chiamata soluzione guida. Ciò è possibile selezionando mosse che introducano gli elementi della soluzione guida nelle nuove soluzioni. Durante tutto il processo di ricerca viene mantenuto un insieme di soluzioni d elite, cioè le migliori soluzioni trovate. Per prima cosa vengono prese queste soluzioni d elite a coppie: una della due, la soluzione A, viene considerata la soluzione iniziale, mentre l altra, la soluzione B, viene considerata la soluzione guida. Poiché l algoritmo tabu search favorisce le soluzioni con rettangoli vuoti preferibilmente nella parte in alto a destra del rettangolo base, entrambe le soluzioni tenderanno ad avere i rettangoli vuoti in questa zona. Quindi viene applicata una simmetria verticale alla soluzione iniziale prima di iniziare il processo di Path Relinking. Seguendo una strategia costruttiva, vengono inseriti i blocchi della soluzione B, uno per volta, nella soluzione A. La mossa di inserimento segue la procedura descritta in precedenza. I pezzi che si sovrappongono al blocco vengono eliminati, i rimanenti blocchi vengono mossi verso gli angoli del rettangolo base più vicini, e i rettangoli vuoti che si formano vengono riempiti. Alla fine del processo, si sarà riprodotta la soluzione B, ma durante il percorso saranno state generate nuove soluzioni. Quando vengono inseriti i blocchi della soluzione B, devono essere inseriti per primi i blocchi adiacenti ai lati del rettangolo base e solo in seguito i blocchi nel centro. Un esempio del primo passo del Path Relinking appare nella Figura 15. La soluzione A con il valore 5376, viene selezionata come soluzione iniziale (Figura 15(a)) mentre la soluzione B con il valore 5352, come soluzione guida (Figura 15(b)). La simmetria verticale applicata alla soluzione A produce la soluzione di Figura 15(c). A questo punto un blocco di B viene inserito in 63
66 essa (Figura 15(d)). I pezzi che si sovrappongono ad esso vengono cancellati così come un pezzo dello stesso tipo del pezzo appena inserito, in modo da non eccedere Q i. I blocchi rimanenti vengono spostati verso gli angoli più vicini, come indicato dalle frecce nella Figura 15(e). Infine gli spazi vuoti vengono fusi e riempiti con nuovi pezzi, producendo la soluzione di Figura 15(f). Questa soluzione è diversa dalle soluzioni A e B ed ha valore a) Soluzione A: 5376 b) Soluzione B: 5352 c) Simmetria su A d) Inserimento blocco di B e) Eliminazione sovrapposizioni f) Fusione e riempimento Figura 15 Path Relinking - Istanza 2 da Jaboks [23] 64
67 5.8 Scelta delle migliori strategie Anche in questo caso, prima di implementare l algoritmo Tabu Search è utile impostare le varie strategie in modo da ottenere i risultati migliori. Tenendo in considerazione il lavoro svolto da Alvarez-Valdes et al [2] ho deciso di utilizzare le seguenti strategie: Tabu list dinamica: variazione delle dimensioni dopo 100 iterazioni in cui non si migliora la soluzione. Diversificazione: si effettua dopo 100 iterazioni senza miglioramenti, e si esegue per le successive 100 iterazioni (o finché non si migliora la soluzione). Intensificazione: si effettua dopo 100 iterazioni senza miglioramenti, e si esegue per le successive 100 iterazioni (o finché non si migliora la soluzione), con K = 100 e considerando un elite composta dalle 10 migliori soluzioni. Ripartenza: se al termine delle fasi di diversificazione e intensificazione non si è migliorata la soluzione, si eseguono una simmetria verticale e, contemporaneamente, una orizzontale. Scelta del rettangolo nella mossa di inserimento: se il problema è unweighted si utilizza il metodo 1, altrimenti si ricorre al metodo 2. Numero di iterazioni: Anche in questo caso l algoritmo deve fermarsi non appena viene raggiunto il limite massimo di iterazioni, o quando la soluzione sia uguale al corrispondente upper bound. Per quanto riguarda la variazione dei vincoli dei pezzi, anche per l algoritmo Tabu Search si è scelto di implementare solo la procedura che permette la diminuzione degli upper bound Q i, poiché è l unica che garantisce significativi miglioramenti. 65
68 Così come si è deciso di non implementare la procedura di Path Relinking poiché anche quest ultima non riuscirebbe a migliorare le prestazioni dell algoritmo. 66
69 Capitolo 6 Implementazione Per l implementazione degli algoritmi euristici descritti in precedenza, mi sono avvalso del linguaggio di programmazione C che, grazie alle sue potenzialità e alla sua modularità, ben si adatta alla realizzazione degli algoritmi, rendendo possibile un ampio riutilizzo del codice. Dato che il C è un linguaggio compilato, è possibile ottenere ottimi risultati in termini di tempi computazionali. 6.1 Strutture dati Le strutture dati complesse, presenti nell algoritmo, sono principalmente tre: i pezzi da tagliare, i rettangoli vuoti e i blocchi inseriti. A queste tre poi se ne aggiungono altre secondarie utilizzate solo nell algoritmo Tabu Search e definite in dettaglio in seguito. Per tutte quante si è deciso di utilizzare una delle strutture dati del linguaggio C, ovvero la lista lineare. La lista lineare è una successione di elementi omogenei che occupano in memoria una posizione qualsiasi. Ciascun elemento contiene una o più informazioni e un puntatore all elemento successivo. L accesso alla lista avviene con il puntatore al primo elemento. Elemento = informazioni + puntatore 67
70 6.1.1 Lista dei pezzi P La lista dei pezzi P comprende, oltre all indice i che identifica il pezzo, anche la lunghezza l, la larghezza w, il lower bound P, l upper bound Q, il valore v e l efficienza e. Pertanto, la struttura che definisce tale lista è: 1 struct pezzo{ 2 int i; 3 int l; 4 int w; 5 int P; 6 int Q; 7 int v; 8 double e; 9 struct pezzo *pun; 10 }; E da notare come tutti i dati siano int, mentre l efficienza può assumere un valore non intero ed è pertanto stata rappresentata tramite un double Lista dei rettangoli L Un rettangolo vuoto è identificato dalle coordinate (x, y) rispettivamente dell angolo in basso a sinistra e dell angolo in alto a destra. Pertanto la lista dei rettangoli L è definita come: 1 struct rettangolo{ 2 int x1; 3 int y1; 4 int x2; 5 int y2; 6 struct rettangolo *pun; 7 }; 68
71 6.1.3 Lista dei blocchi C Un blocco, invece, è caratterizzato oltre che dalle coordinate degli angoli, come i rettangoli, anche dall indice i e dal valore v del pezzo che lo compone, nonché dal numero k dei pezzi per colonna e dal numero l dei pezzi per riga. Quindi, la lista dei blocchi C è così costituita: 1 struct blocco{ 2 int i; 3 int x1; 4 int y1; 5 int x2; 6 int y2; 7 int v; 8 int k; 9 int l; 10 struct blocco *pun; 11 }; Lista delle soluzioni d elite E Gli elementi che compongono la lista delle soluzioni d elite sono formati dal valore di una soluzione v e dalla lista dei blocchi b, generata da tale soluzione: 1 struct elite{ 2 int v; 3 struct blocco *b; 4 struct elite *pun; 5 }; 69
72 6.1.5 Lista dei tabu T La tabu list è composta da coppie formate dal valore di una soluzione v e dal più piccolo rettangolo ER in grado di contenere tutti i rettangoli vuoti generati da tale soluzione. Il rettangolo ER è identificato ovviamente dalla quadrupla (x1, y1, x2, y2): 1 struct tabu{ 2 int v; 3 int x1; 4 int y1; 5 int x2; 6 int y2; 7 struct tabu *pun; 8 }; Lista delle frequenze dei pezzi F La lista delle frequenze tiene conto di quante volte un pezzo entra a far parte di una soluzione. Quindi gli elementi di tale lista saranno formati dall indice i di un pezzo e dal numero di occorrenze n: 1 struct frequenza{ 2 int i; 3 int n; 4 struct frequenza *pun; 5 }; 6.2 Caricamento dei dati iniziali Il caricamento dei dati avviene attraverso l utilizzo di un file di testo. Tale file deve essere realizzato seguendo obbligatoriamente lo schema seguente: 70
73 N n 1 L 1 W 1 l 1 w 1 P 1 Q 1 v 1... l n w n P n Q n v n. n N L N W N l 1 w 1 P 1 Q 1 v 1... l n w n P n Q n v n dove N è il numero di problemi presenti nel file, n i, L i e W i sono rispettivamente il numero di pezzi dell istanza, la lunghezza e la larghezza del rettangolo base, e l j, w j, P j, Q j e v j sono la lunghezza, la larghezza, il lower bound, l upper bound e il valore di un singolo pezzo. 6.3 Schema dell algoritmo GRASP Per realizzare l algoritmo GRASP ho utilizzato una metodologia di tipo topdown: partendo dallo schema generale dell algoritmo, ho implementato man mano le varie funzioni, sintetizzando prima quelle principali e proseguendo poi con quelle secondarie. Tale schema è rappresentato qui di seguito: 1 void main() 2 { 3 aprifile(); 4 for (int index = 1; index <= problemi; index++){ 5 caricadatiproblema(); 6 inizializzaparametri(); 7 ub = upperbound(); 8 while (numiter < maxiter){ 9 numiter++; 10 S0 = randomconstructive(); 71
74 11 S1 = improvement(); 12 if (!isfeasible(p)) 13 continue; 14 if (S1 > Sbest){ 15 Sbest = S1; 16 salvasoluzionemigliore(p, L, C); 17 if (Sbest == ub) 18 break; 19 decreasingqi(p); 20 } 21 if (S1 < Sworst) 22 Sworst = S1; 23 ndelta[idelta]++; 24 sumdelta[idelta] = sumdelta[idelta] + S1; 25 if ((numiter % 100) == 0){ 26 denom = Sbest - Sworst; 27 totaleval = 0; 28 for (int j = 0; j < 9; j++){ 29 mean = sumdelta[j] / ndelta[j]; 30 numer = mean - Sworst; 31 evaldelta[j] = pow(numer / denom, alfa); 32 totaleval = totaleval + evaldelta[j]; 33 } 34 for (int j = 0; j < 9; j++) 35 probdelta[j] = evaldelta[j] / totaleval; 36 } 37 } 38 visualizzarisultati(); 39 eliminaliste(); 40 } 41 chiudifile(); 42 } 72
75 Dallo schema si evince che l algoritmo GRASP consiste nell esecuzione reiterata delle fasi costruttiva (nella sua versione randomconstructive) e di miglioramento (improvement). Al termine di queste fasi, se la soluzione è ammissibile (isfeasible), si confronta il risultato ottenuto con il migliore a disposizione; se questo è maggiore, la nuova soluzione trovata viene salvata (salvasoluzionemigliore) e, se quest ultima ha un valore uguale all upper bound, l algoritmo termina all istante. In questa parte dell algoritmo vengono aggiornati anche parametri come la somma delle soluzioni ottenute con un dato fattore δ (sumdelta) e il numero di iterazioni in cui si è fatto ricorso a tale valore di δ (ndelta). Infine, ogni 100 iterazioni, avviene l aggiornamento delle probabilità (probdelta) associate all utilizzo dei valori ammissibili di δ. 6.4 Funzioni dell algoritmo GRASP int randomconstructive() La funzione randomconstructive è la funzione cardine di tutto l algoritmo GRASP e coincide con la prima fase, quella costruttiva. Per prima cosa viene scelto il valore del parametro δ tenendo conto delle probabilità associate ai suoi possibili valori, poi si definisce la soglia tra i valori dei pezzi e viene costruita la Restricted Candidate List (crearcl). A questo punto, finché esiste un pezzo in grado di entrare in uno qualunque dei rettangoli vuoti si procede col selezionare in maniera casuale (rand) sia il pezzo da tagliare che il rettangolo vuoto. Se il pezzo non può essere inserito nel rettangolo (fill), vengono selezionati un pezzo e un rettangolo nuovi, sempre in maniera casuale. Se il pezzo, invece, è in grado di entrare nel rettangolo, si procede scegliendo, sempre in maniera casuale, sia il numero di colonne, che il numero di righe del pezzo che formeranno il blocco da tagliare, sempre però rispettando il limite Q i. Quindi, si prosegue scegliendo l angolo del rettangolo vuoto in cui inserire 73
76 il blocco, per la precisione si sceglie quello con distanza (distanza) minima dal corrispettivo angolo del rettangolo base (distanzamin). Fatto questo si procede con la rimozione del rettangolo utilizzato (rimuovirettangolo), con l inserimento del blocco nella lista dei blocchi (aggiungiblocco), con l inserimento di uno o più rettangoli vuoti (aggiungirettangolo) e con il modificare i parametri P i e Q i del pezzo (se Q i = 0, il pezzo viene rimosso con rimuovipezzo). Infine si procede con l eseguire tutte le fusioni che migliorano l inserimento dei pezzi (merge). Quando non ci sono più pezzi in grado di essere tagliati, la procedura termina restituendo il valore della soluzione trovata. int improvement() La funzione improvement realizza la fase di miglioramento discussa in precedenza. Per prima cosa vengono rimossi dalla lista dei blocchi il k% di essi (rimuoviblocco), poi viene aggiornata la lista dei pezzi, aggiungendo quelli appena ripristinati (aggiungipezzo), e poi vengono inseriti i rettangoli vuoti generati dalla rimozione dei blocchi. In seguito vengono ordinati i pezzi secondo i criteri espressi in precedenza (ordinapezzi) e vengono valutate tutte le fusioni tra i rettangoli. Infine viene eseguito l algoritmo costruttivo classico (constructive) che termina con la restituzione del nuovo valore della soluzione. struct pezzo *crearcl(double soglia, struct pezzo *p) Restituisce la lista dei pezzi composta solamente da quei pezzi con P i > 0 o con v i soglia (Restricted Candidate List). int vmax(struct pezzo *p) Restituisce il più grande tra tutti i valori v dei pezzi. 74
77 6.5 Schema dell algoritmo Tabu Search Anche nel caso dell algoritmo Tabu Search ho utilizzato una metodologia di tipo top-down in cui, partendo da uno schema generale, ho implementato di volta in volta le varie funzioni, partendo da quelle principali e proseguendo con quelle secondarie. Poiché le funzioni dell algoritmo GRASP sono state sviluppate sapientemente in maniera generale, è stato possibile riutilizzare un gran numero di queste funzioni, così com erano, anche nell algoritmo Tabu Search. Lo schema generale è così definito: 1 void main() 2 { 3 aprifile(); 4 for (int index = 1; index <= problemi; index++){ 5 caricadatiproblema(); 6 inizializzaparametri(); 7 ub = upperbound(); 8 S = constructive(); 9 Start = S; 10 Sbest = S; 11 salvasoluzioneiniziale(p, L, C); 12 salvasoluzionemigliore(p, L, C); 13 tabulist = aggiungitabu(s, creaer(l), tabulist); 14 frequenze = inizializzafrequenza(p); 15 while (numiter < maxiter){ 16 numiter++; 17 valutariduzione(); 18 valutainserimento(); 19 salvasoluzioneiniziale(p, L,C); 20 frequenze = aggiornafrequenza(c, frequenze); 21 if (numiter < numelite) 22 aggiungisoluzioneelite(c, S, E); 75
78 23 else 24 sostituiscisoluzioneelite(c, S, E); 25 if (ntabu < ntabumax){ 26 ntabu++; 27 tabulist = aggiungitabu(s, creaer(l), tabulist); 28 } 29 else{ 30 rimuovitabu(tabulist); 31 aggiungitabu(s, creaer(l), tabulist); 32 } 33 if (Sstart > Sbest){ 34 numiternotimpl = 0; 35 diversification = 0; 36 intensification = 0; 37 Sbest = Sstart; 38 salvasoluzionemigliore(p, L, C); 39 decreasingqi(p); 40 } 41 else{ 42 numiternotimpl++; 43 if ((numiternotimpl % 100) == 0) 44 tabulist = modificadimensionitabulist(tabulist); 45 if ((numiternotimpl % 400) == 0) 46 diversification = 1; 47 if ((numiternotimpl % 400) == 0) 48 intensification = 1; 49 if ((numiternotimpl % 500) == 0){ 50 diversification = 0; 51 intensification = 0; 52 restartingl(l); 53 restartingc(c); 54 } 76
79 55 } 56 } 57 visualizzarisultati(); 58 eliminaliste(); 59 } 60 chiudifile(); 61 } Dallo schema si vede come l algoritmo Tabu Search inizi con l applicazione dell algoritmo costruttivo (constructive) e con il salvataggio della soluzione trovata (salvasoluzionemigliore e salvasoluzioneiniziale). A questo punto inizia un processo iterativo in cui vengono valutate tutte le mosse che è possibile eseguire tra quelle di riduzione (valutariduzione) e di inserimento (valutainserimento). La mossa che è ritenuta la migliore viene eseguita e, dalla soluzione così trovata, si riparte per la prossima iterazione. Quindi viene inserita (nel rispetto delle dimensioni ntabumax della tabu list) la mossa effettuata, tra quelle tabu (aggiungitabu). Poi vengono aggiornate le frequenze dei pezzi (aggiornafrequenza) e viene valutato se la soluzione trovata è meritevole di entrare tra le soluzioni di elite (aggiungisoluzioneelite). Se la nuova soluzione iniziale è maggiore di quella attuale, quest ultima viene sostituita (se è uguale all upper bound, l algoritmo termina). Altrimenti, se non c è un miglioramento della soluzione, viene valutato il numero di iterazioni da cui non si ottiene un miglioramento (numiternotimpl) e, se questo numero è multiplo di 100, viene variata la dimensione della tabu list (modificadimensionitabulist). Se non si verificano miglioramenti da 400 iterazioni, vengono attivate le fasi di diversificazione e intensificazione che provvedono ad alterare il valore della funzione obiettivo. Qualora dopo ulteriori 100 iterazioni, la soluzione non dovesse essere ancora migliorata, vengono interrotte le fasi di diversificazione e intensificazione e viene eseguita un operazione di ripartenza sulla lista dei blocchi (restartingc) e sulla lista dei rettangoli vuoti (restartingl). 77
80 6.6 Funzioni dell algoritmo Tabu Search void valutariduzione() La funzione esegue tutte le possibili riduzioni dei blocchi esistenti. Per far questo, vengono selezionati a turno tutti i blocchi, finché non si giunge alla fine della lista, e se questo blocco è adiacente ad un rettangolo vuoto (isadjacent) si esegue la riduzione (reduction) valutando tutte le possibili combinazioni di righe e colonne, da entrambe le direzioni: sinistra e destra per le colonne, e alto e basso per le righe. Al termine della riduzione, si valuta la mossa eseguita (valutamossa) e si prosegue con quella successiva. void valutainserimento() La funzione esegue tutti i possibili inserimenti di blocchi. Per prima cosa vengono selezionati tutti i pezzi della lista, uno alla volta, finché non si raggiunge il termine. Di questo pezzo vengono valutate, a turno, tutte le sue possibili combinazioni di righe e colonne. Per ognuna di queste combinazioni si prova ad inserire il blocco (insertion) in tutti i rettangoli (nel caso di problemi di tipo unweighted), oppure solamente nel rettangolo con area comune massima (bestrettangolo), posizionandolo alternativamente, se possibile, in tutti e quattro gli angoli. Una volta eseguito l inserimento, viene valutata la mossa appena effettuata (valutamossa) e si passa a quella successiva. void reduction(int i, int k, int l) La funzione riduce di k colonne e l righe un blocco di indice i. Per far questo modifica i relativi indici del blocco (o lo rimuove totalmente nel caso fosse stato selezionato per intero per la riduzione) e aggiunge i pezzi rimossi e i rettangoli vuoti che si vengono a formare, alle relative liste. A questo punto vengono eseguiti un ordinamento dei pezzi e una fusione dei rettangoli. Infine, viene applicato l algoritmo costruttivo alla configurazione attuale dei blocchi, in seguito alla riduzione. 78
81 void insertion(int i, int k, int l, int x1, int y1, int x2, int y2) La funzione si occupa di inserire un blocco formato da pezzi di indice i e composto da k colonne e l righe nella posizione indicata. Per far ciò, oltre a inserire il nuovo blocco, vengono rimossi tutti i blocchi e i rettangoli esistenti che si sovrappongono al nuovo blocco e vengono inseriti anche i nuovi rettangoli che si formano di conseguenza. Alla termine di tutto ciò, vengono eseguiti un ordinamento sui pezzi e una fusione sui rettangoli. Per finire, si esegue l algoritmo costruttivo sulla nuova configurazione. void valutamossa() La funzione valuta la mossa appena effettuata prendendo in considerazione la funzione obiettivo primaria, quella secondaria, la tabu list, la diversificazione, l intensificazione e il criterio di aspirazione. Ovvero, viene valutata positivamente solo la mossa che presenta un valore più alto della funzione obiettivo primaria (in caso di parità, conta la funzione obiettivo secondaria) rispetto alle altre mosse, a meno che tale mossa non sia inserita nella tabu list, ma se la soluzione ha un valore maggiore della miglior soluzione fino a quel momento trovata, si ignora la tabu list. Se sono attive le fasi di intensificazione e diversificazione, la funzione obiettivo primaria è modificata dai relativi parametri. In caso di valutazione positiva, la soluzione trovata con l esecuzione della mossa è candidata ad essere la nuova soluzione di partenza a partire dall iterazione successiva. void salvasoluzioneiniziale(struct pezzo *p, struct rettangolo *r, struct blocco *b) Provvede a salvare la nuova soluzione iniziale, sostituendo le liste dei pezzi, dei rettangoli e dei blocchi della vecchia soluzione iniziale, con quelle nuove passate come parametro. 79
82 struct tabu *aggiungitabu(int v, struct rettangolo *r, struct tabu *t) Aggiunge un elemento (formato dal valore della soluzione e dal relativo rettangolo ER) in coda alla tabu list. struct tabu *rimuovitabu(struct tabu *t) Rimuove il primo elemento della tabu list in modo da gestirla come una coda e rispettare la politica di tipo FIFO. struct blocco *unisciblocchi(struct blocco *b) Provvede ad unire i blocchi formati da insiemi degli stessi pezzi se tali blocchi sono adiacenti e con un lato in comune, oppure se possono essere congiunti mediante un semplice spostamento. struct rettangolo *creaer(struct rettangolo *r) Restituisce il rettangolo di dimensioni minime, in grado di racchiudere al suo interno tutti i rettangoli vuoti presenti nella lista passata come parametro. struct elite *aggiungisoluzioneelite(struct blocco *b, int valore, struct elite *e) Aggiunge alle soluzioni di elite quella formata dalla lista di blocchi e dal relativo valore totale, passati come parametri. Le soluzioni di elite sono ordinate per valore della soluzione crescente. struct elite *sostituiscisoluzioneelite(struct blocco *b, int valore, struct elite *e) Se la soluzione passata come parametro è migliore di quella in testa alla lista delle soluzioni di elite (quella con valore minore), quest ultima viene sostituita. 80
83 void restartingl(struct rettangolo *r) Esegue una simmetria verticale e, contemporaneamente, una orizzontale sulla lista dei rettangoli vuoti. void restartingc(struct blocco *b) Esegue una simmetria verticale e, contemporaneamente, una orizzontale sulla lista dei blocchi. double secondaryobjective(struct pezzo *p, struct rettangolo *r) Calcola il valore della funzione obiettivo secondaria, a partire dalla lista dei pezzi ancora da tagliare e da quella dei rettangoli vuoti. int istabu(struct tabu *t, int valore, struct rettangolo *ER) Restituisce 1 se il valore della soluzione e il rettangolo ER passati come parametro coincidono con un elemento della tabu list, 0 altrimenti. int tabumax(struct pezzo *p) Calcola, in maniera casuale, la dimensione massima della tabu list in modo che risulti compresa tra il 25% e il 75% di M, dove M = i Q i. struct rettangolo *bestrettangolo(int l, int w, struct rettangolo *r) Restituisce il rettangolo che ha la più alta sovrapposizione, in termini di superficie, con il blocco da inserire di dimensioni (l, w). struct frequenza *inizializzafrequenza(struct pezzo *p) Crea una lista di frequenza con tanti elementi (tutti inizializzati a 0) quanti 81
84 quelli della lista di pezzi passata come parametro. struct frequenza *aggiornafrequenza(struct blocco *b, struct frequenza *f) Aggiorna le frequenze dei pezzi aggiungendo quante volte ogni singolo pezzo compare nella lista dei blocchi passata come parametro. double valorefrequenza(struct blocco *b, struct frequenza *f, int num) Calcola il valore totale delle frequenze dei pezzi che compaiono nella lista dei blocchi passata come parametro, diviso per il numero di occorrenze num. struct tabu *modificadimensionitabulist(struct tabu *t) Provvede a generare a caso la nuova dimensione della tabu list e, se questa è inferiore alla precedente, rimuove gli elementi in esubero. 6.7 Funzioni comuni ai due algoritmi int constructive() La funzione constructive è la funzione che realizza l algoritmo costruttivo. Per prima cosa viene ordinata la lista dei pezzi in base ai già citati criteri (ordinapezzi). A questo punto, finché esiste un pezzo in grado di entrare in uno qualunque dei rettangoli vuoti si procede selezionando il pezzo da tagliare, scandendo la lista ordinata, e scegliendo il rettangolo vuoto di area minima. Se il pezzo non può entrare nel rettangolo (fill), si procede selezionando il pezzo successivo. Se il pezzo, invece, può essere contenuto nel rettangolo, si procede individuando in maniera casuale, sia il numero di co- 82
85 lonne, che il numero di righe del pezzo che formeranno il blocco da tagliare, rispettando però il limite Q i. Quindi, si prosegue scegliendo l angolo del rettangolo vuoto in cui inserire il blocco, per la precisione si sceglie quello con distanza (distanza) minima dal corrispettivo angolo del rettangolo base (distanzamin). Fatto questo si procede con la rimozione del rettangolo utilizzato (rimuovirettangolo), con l inserimento del blocco nella lista dei blocchi (aggiungiblocco), con l inserimento di uno o più rettangoli vuoti (aggiungirettangolo) e con il modificare i parametri P i e Q i del pezzo (se Q i = 0, il pezzo viene rimosso con rimuovipezzo). Infine si procede con l eseguire tutte le fusioni che migliorano l inserimento dei pezzi (merge). Quando si giunge in coda alla lista dei pezzi, si seleziona il rettangolo successivo e ci si riposiziona in testa alla lista dei pezzi. Quando non ci sono più pezzi in grado di essere tagliati, la procedura termina restituendo il valore della soluzione trovata. void visualizzap(struct pezzo *p) Visualizza la lista dei pezzi P, passata come parametro, stampandola a video nella forma P = {i 1, i 2,..., i n }. void visualizzal(struct rettangolo *r) Visualizza la lista dei rettangoli L, passata come parametro, stampandola a video nella forma L = {(x1 1, y1 1, x2 1, y2 1 ),..., (x1 n, y1 n, x2 n, y2 n )}. void visualizzac(struct blocco *b) Visualizza la lista dei blocchi C, passata come parametro, stampandola a video nella forma C = {i 1 (x1 1, y1 1, x2 1, y2 1 ),..., i n (x1 n, y1 n, x2 n, y2 n )}. struct pezzo *ordinapezzi(struct pezzo *p) Restituisce la lista dei pezzi P, ordinandola secondo i tre criteri espressi nella 83
86 sezione Per far ciò utilizza le tre funzioni che seguono. struct pezzo *ordinapezziperpi(struct pezzo *p) Restituisce la lista dei pezzi P, ordinandola per P i l i w i decrescenti. struct pezzo *ordinapezziperei(struct pezzo *p) Restituisce la lista dei pezzi P, ordinandola per e i decrescenti. struct pezzo *ordinapezzipervi(struct pezzo *p) Restituisce la lista dei pezzi P, ordinandola per v i decrescenti. struct pezzo *aggiungipezzo(int i, int l, int w, int P, int Q, int v, struct pezzo *p) Aggiunge un pezzo in coda alla lista dei pezzi passata come parametro. Se l indice i del pezzo esiste già, vengono modificati solo il lower bound P i e l upper bound Q i. struct rettangolo *aggiungirettangolo(int x1, int y1, int x2, int y2, struct rettangolo *r) Aggiunge un rettangolo alla lista dei rettangoli passata come parametro, ordinata per area crescente, mantenendone l ordinamento. struct blocco *aggiungiblocco(int i, int x1, int y1, int x2, int y2, int k, int l, int v, struct blocco *b) Aggiunge un blocco in coda alla lista di blocchi passata come parametro. struct pezzo *rimuovipezzo(int i, struct pezzo *p) Rimuove, liberando la memoria, il pezzo (se esiste) di indice i presente nella 84
87 lista p. struct rettangolo *rimuovirettangolo(int x1, int y1, int x2, int y2, struct rettangolo *r) Rimuove, liberando la memoria, il rettangolo (se esiste) di coordinate (x1, y1) e (x2, y2), presente nella lista r. struct blocco *rimuoviblocco(int x1, int y1, int x2, int y2, struct blocco b*) Rimuove, liberando la memoria, il blocco (se esiste) di coordinate (x1, y1) e (x2, y2), presente nella lista b. void eliminapezzi(struct pezzo *p) Rimuove, liberando la memoria, tutti i pezzi presenti nella lista passata come parametro. void eliminarettangoli(struct rettangolo *r) Rimuove, liberando la memoria, tutti i rettangoli presenti nella lista passata come parametro. void eliminablocchi(struct blocco *b) Rimuove, liberando la memoria, tutti i blocchi presenti nella lista passata come parametro. int contapezzi(struct pezzo p*) Restituisce il numero di pezzi presenti nella lista p. int contarettangoli(struct rettangolo *r) 85
88 Restituisce il numero di rettangoli presenti nella lista r. int contablocchi(struct blocco *b) Restituisce il numero di blocchi presenti nella lista b. struct pezzo *selezionapezzo(int i, struct pezzo *p) Seleziona il pezzo di indice i e ne restituisce il riferimento. struct rettangolo *selezionarettangolo(int i, struct rettangolo *r) Seleziona il rettangolo di indice i e ne restituisce il riferimento. struct blocco *selezionablocco(int i, struct blocco *b) Seleziona il blocco di indice i e ne restituisce il riferimento. struct pezzo *copiapezzi(struct pezzo *p) Restituisce una copia dell intera lista dei pezzi passata come parametro. struct rettangolo *copiarettangoli(struct rettangolo *r) Restituisce una copia dell intera lista dei rettangoli passata come parametro. struct blocco *copiablocchi(struct blocco *b) Restituisce una copia dell intera lista dei blocchi passata come parametro. struct rettangolo *merge(struct rettangolo *r, struct pezzo *p) Valuta ed esegue tutte le fusioni tra i rettangoli vuoti adiacenti utilizzando i criteri espressi nella sezione 2.1.4, e per far ciò necessita, oltre che della lista dei rettangoli da fondere, anche di quella dei pezzi ancora da tagliare 86
89 ordinata secondo il criterio migliore. double distanza(double x1, double y1, double x2, double y2) Restituisce la distanza, in valore assoluto, tra due punti (x1, y1) e (x2, y2). double distanzamin(double bl, double br, double tl, double tr) Restituisce la distanza minima tra le quattro passate come parametro che corrispondono alle distanze tra i quattro angoli di un rettangolo vuoto e i corrispettivi angoli del rettangolo base (bottom-left, bottom-right, top-left e top-right). int isadjacent(struct blocco *b, struct rettangolo *r) Restituisce 1 se il blocco e il rettangolo passati come parametro sono adiacenti, 0 altrimenti. int upperbound(struct pezzo *p) Calcola l upper bound del problema a partire dalla lista dei pezzi da tagliare. int isunweighted(struct pezzo *p) Se per ogni pezzo i risulta e i = 1, restituisce 1 (problema di tipo unweighted), altrimenti restituisce 0. int isfeasible(struct pezzo *p) Se per ogni pezzo i ancora da tagliare risulta P i = 0, restituisce 1 (soluzione ammissibile), altrimenti restituisce 0 (soluzione non ammissibile). int fill(struct rettangolo *r, struct pezzo *p) Restituisce 1 se il pezzo è in grado di essere tagliato dal rettangolo vuo- 87
90 to, 0 altrimenti. double emax(struct pezzo *p) Restituisce la più grande tra tutte le efficienze e dei pezzi. void decreasingqi(struct pezzo *p) Decrementa gli upper bound Q i dei pezzi della lista passata come parametro, seguendo le formule indicate nella sezione Quindi, se un pezzo presenta un Q i = 0, questo viene rimosso dalla lista dei pezzi ancora da tagliare. void aprifile() Richiede il nome del file in cui sono contenuti i problemi da risolvere e provvede ad aprirlo in lettura. Inoltre apre in scrittura il file risultati.txt in cui verranno scritte le soluzioni dei problemi e i tempi computazionali. void chiudifile() Provvede a chiudere i file precedentemente aperti. void caricadatiproblema() Crea le tre liste P, L e C inizializzandole con i valori presenti sul file. void inizializzaparametri() Inizializza tutti i parametri fondamentali come il numero di iterazioni numiter, il numero massimo di iterazioni maxiter, ecc. void salvasoluzionemigliore(struct pezzo *p, struct rettangolo *r, struct blocco *b) Provvede a salvare le tre liste associate alla soluzione migliore trovata fino a 88
91 quel momento. void eliminaliste() Si occupa di eliminare tutte le liste precedentemente create in modo da liberare la memoria occupata. void visualizzarisultati() Stampa a video la soluzione trovata e salva il risultato e il tempo impiegato all interno del file risultati.txt. 89
92
93 Capitolo 7 Test e risultati computazionali 7.1 Tipi di test Per testare entrambi gli algoritmi sono stati utilizzati diversi insiemi di problemi: 1. Un insieme di 21 problemi estratti dalla letteratura: dodici da Beasley [6], due da Hadjiconstantinou e Christofides [8], uno da Wang [21], uno da Christofides e Whitlock [22], cinque da Fekete e Schepers [9]. Le soluzioni ottime sono tutte note. I problemi sono stati risolti anche da Beasley [15]. 2. Un insieme di 630 problemi di grosse dimensioni generati da Beasley [15], seguendo il lavoro di Fekete e Schepers [9]. Tutti i problemi hanno un rettangolo base di dimensioni (100, 100). Per ogni valore di m, il numero di tipi diversi di pezzi (m=40, 50, 100, 150, 250, 500, 1000), 10 problemi sono generati in maniera casuale con P i = 0, Q i = Q, i = 1,..., m, dove Q =1; 3; 4. Queste 630 istanze sono suddivise in tre tipi di problemi, a seconda della percentuale di tipi di pezzi di ogni classe: 91
94 Classe Descrizione Lunghezza Larghezza 1 Corti e larghi [1,50] [75,100] 2 Lunghi e stretti [75,100] [1,50] 3 Grandi [50,100] [50,100] 4 Piccoli [1,50] [1,50] Tipo % di classe 1 % di classe 2 % di classe 3 % di classe Il valore assegnato ad ogni pezzo è uguale alla sua area moltiplicata per un intero scelto a caso tra {1, 2, 3}. 3. I 21 problemi provenienti dalla letteratura sono stati trasformati da Beasley [15] in doubly constrained problems modificando alcuni lower bounds P i, in particolare per ogni tipo di pezzo da i = 1,..., m che soddisfi m j=1,j i (l j w j )P j + l i w i (LW )/3, il lower bound P i è posto uguale a 1. Questo insieme di problemi permette di verificare la bontà degli algoritmi nel caso generale di problemi di tipo doubly constrained. 4. Infine sono stati eseguiti i test utilizzando i problemi usati da Leung et al [14], che consistono in tre istanze da Lai e Chan [11], cinque da Jakobs [23] e due da Leung et al [14]. I test sono stati eseguiti anche su 21 istanze di grosse dimensioni create da Hopper e Turton [25]. Questi problemi sono tutti di tipo unweighted in cui il valore di ogni pezzo corrisponde alla sua area e l obbiettivo da raggiungere è ridurre al minimo lo scarto nel rettangolo base. Quest ultima classe di problemi ha caratteristiche complementari rispetto agli altri tipi. Infatti i primi tre tipi di problemi possono essere considerati una sorta di problemi di selezione perché ci sono molti pezzi disponibili e solo 92
95 una piccola parte di essi dovrà essere inclusa nella soluzione ottimale. Invece i problemi del quarto tipo possono essere definiti come problemi a incastro in cui tutti i pezzi disponibili devono far parte della soluzione ottima e la difficoltà sta nel trovare la loro corretta posizione per far sì che entrino tutti nel rettangolo base. Un algoritmo che funzioni bene con entrambi i tipi di problemi può essere considerato un buon general purpose algorithm. 7.2 Risultati computazionali I risultati computazionali completi appaiono nelle Tabelle dalla 1 alla 4, per quanto riguarda l algoritmo GRASP, e dalla 5 alla 8, per quanto riguarda l algoritmo Tabu Search. Nelle tabelle è stato fatto un confronto con l algoritmo GRASP sviluppato da Alvarez-Valdes et al [1] e con quello Tabu Search realizzato sempre da Alvarez-Valdes et al [2]. Il confronto avviene sia sui risultati ottenuti dalle due procedure, sia sui tempi impiegati a risolvere i problemi. I tempi di elaborazione, però, non possono essere direttamente confrontati in quanto entrambi i miei algoritmi sono stati sviluppati in C ed eseguiti su un AMD Athlon 2100+, mentre gli algoritmi di Alvarez-Valdes et al sono stati implementati utilizzando il linguaggio C++ ed eseguiti su un Pentium III 800 MHz. Tuttavia è possibile affermare, con un certo margine di approssimazione, che il PC usato da me per l esecuzione dei test è circa due volte più veloce rispetto a quello usato da Alvarez-Valdes et al Confronto tra gli algoritmi GRASP Confrontando il primo insieme di problemi (Tabella 1), quelli provenienti dalla letteratura, si nota come il mio algoritmo produca risultati identici a quelli di Alvarez-Valdes et al, sia in termini di numero di soluzioni ottime trovate, sia in termini di valore di tali soluzioni, risolvendo i problemi in circa metà tempo, in accordo con le differenti prestazioni dei processori. Per quanto riguarda il secondo insieme di problemi (Tabella 2), per i quali 93
96 esistono solo risultati aggregati, l algoritmo di Alvarez-Valdes et al produce risultati leggermente migliori in un tempo di poco superiore. Per questo tipo di problemi, non essendo disponibili le soluzioni ottime, il confronto è stato fatto prendendo in considerazione i relativi upper bound. Il terzo insieme è rappresentato dai problemi doubly constrained (Tabella 3) nei quali come soluzione ottima di riferimento è stata scelta la stessa dei problemi constrained, poiché quella reale non era disponibile. Per questi problemi i risultati del mio algoritmo sono migliori, sia dal punto di vista del valore delle soluzioni trovate, che dal punto di vista dei tempi (inferiori alla metà). Alcuni problemi sono non risolvibili (not feasible), ciononostante sono stati inseriti lo stesso nella tabella per dimostrare che l algoritmo è in grado di riconoscerli quando li incontra. Infine, confrontando i risultati prodotti sui problemi di tipo unweighted (Tabella 4) possiamo notare come il mio algoritmo fornisca risultati decisamente migliori, rispetto a quelli dell algoritmo di Alvarez-Valdes et al, sotto tutti i punti di vista, cioè del numero di soluzioni ottime trovate, dei valori delle soluzioni e dei tempi di esecuzione (inferiori a un terzo). La Figura 16 riassume il confronto tra i due algoritmi GRASP. Figura 16 Confronto tra gli algoritmi GRASP 94
97 Dimensioni CPU (s) I (L,W) m M Ciani Alvarez Ottimo Ciani Alvarez 1 (10,10) ,00 0,00 2 (10,10) ,00 0,00 3 (10,10) ,00 0,00 4 (15,10) ,00 0,00 5 (15,10) ,00 0,00 6 (15,10) ,00 0,00 7 (20,20) ,00 0,00 8 (20,20) ,06 0,77 9 (20,20) ,14 0,00 10 (30,30) ,04 0,00 11 (30,30) ,06 0,05 12 (30,30) ,10 0,05 13 (30,30) ,04 0,00 14 (30,30) ,05 0,00 15 (70,40) ,13 0,77 16 (40,70) ,11 0,39 17 (100,100) ,33 2,31 18 (100,100) ,11 4,17 19 (100,100) ,30 3,68 20 (100,100) ,90 0,00 21 (100,100) ,43 0,00 Deviazione media dall ottimo 0,19% 0,19% 0,23 0,58 Numero di soluzioni ottime Tabella 1 GRASP - Problemi dalla letteratura 95
98 Deviazione media percentuale dall UB CPU (s) m Q M Ciani Alvarez Ciani Alvarez ,01 6,97 1,83 2, ,39 2,22 5,40 6, ,98 1,81 3,33 4, ,91 4,80 3,20 4, ,79 1,50 5,48 7, ,37 1,18 4,38 5, ,59 1,51 4,11 5, ,74 0,47 7,43 9, ,45 0,26 5,26 6, ,93 0,89 4,90 5, ,27 0,14 9,76 11, ,26 0,11 4,77 6, ,51 0,51 4,78 5, ,16 0,04 10,76 13, ,10 0,03 9,91 6, ,12 0,05 3,02 3, ,02 0,00 8,33 12, ,02 0,00 4,32 1, ,01 0,00 4,76 1, ,00 0,00 5,92 6, ,00 0,00 4,39 0,29 Tipo 1 1,13 1,04 4,44 5,13 Tipo 2 1,23 1,14 5,42 5,90 Tipo 3 1,16 1,03 6,00 7,28 Tutti 1,17 1,07 5,29 6,02 Tabella 2 GRASP - Problemi random di grosse dimensioni 96
99 Dimensioni CPU (s) I (L,W) m M Ciani Alvarez Ottimo Ciani Alvarez 1 (10,10) ,04 0,00 2 (10,10) ,04 0,00 3 (10,10) ,04 0,00 4 (15,10) ,04 0,00 5 (15,10) ,04 0,00 6 (15,10) ,08 0,00 7 (20,20) ,00 0,00 8 (20,20) ,06 0,77 9 (20,20) ,14 0,00 10 (30,30) 5 13 n/f n/f n/f 0,04 0,00 11 (30,30) ,06 0,05 12 (30,30) ,10 0,05 13 (30,30) ,04 0,00 14 (30,30) ,05 0,00 15 (70,40) ,13 0,77 16 (40,70) ,11 0,39 17 (100,100) ,33 2,31 18 (100,100) ,11 4,17 19 (100,100) n/f n/f n/f 1,30 3,68 20 (100,100) ,90 0,00 21 (100,100) ,43 0,00 Deviazione media dall ottimo 7,02% 7,36% 0,50 1,29 n/f: Nessuna soluzione fattibile è stata trovata Tabella 3 GRASP - Problemi di tipo doubly constrained 97
100 Dimensioni CPU (s) I (L,W) m M Ciani Alvarez Ottimo Ciani Alvarez 1 (400,200) ,00 0,00 2 (400,200) ,00 0,00 3 (400,400) ,00 4,12 4 (70,80) ,06 10,16 5 (70,80) ,49 15,44 6 (120,45) ,94 12,57 7 (90,45) ,05 10,28 8 (65,45) ,72 14,94 9 (150,110) ,90 90,52 10 (160,120) ,50 132,26 11 (20,20) ,31 0,94 12 (20,20) ,92 9,28 13 (20,20) ,04 0,06 14 (40,15) ,43 19,44 15 (40,15) ,33 17,36 16 (40,15) ,88 0,71 17 (60,30) ,66 26,80 18 (60,30) ,12 37,35 19 (60,30) ,91 30,92 20 (60,60) ,56 102,05 21 (60,60) ,01 110,79 22 (60,60) ,72 94,41 23 (60,90) ,97 212,07 24 (60,90) ,48 231,56 25 (60,90) ,91 231,24 26 (80,120) ,40 480,44 27 (80,120) ,05 465,49 28 (80,120) ,54 478,02 29 (160,240) , ,14 30 (160,240) , ,96 31 (160,240) , ,99 Deviazione media dall ottimo 1,46% 1,68% 164,62 423,95 Numero di soluzioni ottime 7 5 Tabella 4 GRASP - Problemi di tipo unweighted 98
101 7.2.2 Confronto tra gli algoritmi Tabu Search Se si confrontano i 21 problemi provenienti dalla letteratura (Tabella 5), i due algoritmi Tabu Search producono esattamente gli stessi risultati, trovando tutte e 21 le soluzioni ottime; ma il mio algoritmo li risolve in metà tempo. I problemi di grosse dimensioni (Tabella 6), invece, presentano risultati aggregati pressoché identici, con qualche differenza solo da categoria a categoria. Anche i tempi computazionali sono paragonabili, tenendo in considerazione le diversità dei processori. Per quanto riguarda i problemi doubly constrained (Tabella 7), anche in questo caso i risultati sono identici e i tempi sono paragonabili. Probabilmente, anche se non vi è certezza, poiché le soluzioni ottime di questo tipo di problema non sono disponibili, entrambi gli algoritmi sono riusciti a individuare tutte le soluzioni ottime. Infine, i problemi di unweighted (Tabella 8) vengono risolti dai due algoritmi realizzando risultati totali molto simili, ma piuttosto diversi da istanza a istanza. Per quanto riguarda i tempi di esecuzione, anche questa volta, il mio algoritmo risolve i problemi in un tempo inferiore (circa un terzo). La Figura 17 mostra il paragone tra i due algoritmi Tabu Search. Figura 17 Confronto tra gli algoritmi Tabu Search 99
102 Dimensioni CPU (s) I (L,W) m M Ciani Alvarez Ottimo Ciani Alvarez 1 (10,10) ,00 0,06 2 (10,10) ,00 0,00 3 (10,10) ,00 0,00 4 (15,10) ,00 0,00 5 (15,10) ,00 0,00 6 (15,10) ,00 0,00 7 (20,20) ,00 0,00 8 (20,20) ,06 0,16 9 (20,20) ,00 0,05 10 (30,30) ,00 0,00 11 (30,30) ,00 0,00 12 (30,30) ,03 0,06 13 (30,30) ,00 0,00 14 (30,30) ,00 0,00 15 (70,40) ,04 0,11 16 (40,70) ,03 0,06 17 (100,100) ,00 0,05 18 (100,100) ,09 2,14 19 (100,100) ,51 3,40 20 (100,100) ,41 0,66 21 (100,100) ,00 0,00 Deviazione media dall ottimo 0,00% 0,00% 0,15 0,32 Numero di soluzioni ottime Tabella 5 Tabu Search - Problemi dalla letteratura 100
103 Deviazione media percentuale dall UB CPU (s) m Q M Ciani Alvarez Ciani Alvarez ,41 6,55 6,99 10, ,93 1,95 8,84 14, ,52 1,65 11,37 18, ,56 4,85 9,86 15, ,28 1,27 15,42 22, ,89 0,96 12,25 18, ,59 1,50 19,95 38, ,38 0,31 18,34 32, ,14 0,18 12,29 19, ,02 0,84 35,31 54, ,15 0,07 20,73 31, ,06 0,05 14,49 19, ,69 0,45 72,05 90, ,02 0,01 8,78 13, ,00 0,00 3,06 4, ,05 0,03 67,93 86, ,00 0,00 0,88 1, ,00 0,00 0,59 0, ,00 0,00 5,16 7, ,00 0,00 0,91 1, ,00 0,00 0,76 1,19 Tipo 1 0,96 0,95 12,75 19,61 Tipo 2 1,06 1,06 15,49 23,84 Tipo 3 0,95 0,94 21,17 32,56 Tutti 0,99 0,98 16,47 25,34 Tabella 6 Tabu Search - Problemi random di grosse dimensioni 101
104 Dimensioni CPU (s) I (L,W) m M Ciani Alvarez Ottimo Ciani Alvarez 1 (10,10) ,00 0,00 2 (10,10) ,81 1,70 3 (10,10) ,04 2,26 4 (15,10) ,00 0,00 5 (15,10) ,82 1,48 6 (15,10) ,78 1,59 7 (20,20) ,00 0,00 8 (20,20) ,96 1,76 9 (20,20) ,00 0,00 10 (30,30) 5 13 n/f n/f n/f 0,55 0,94 11 (30,30) ,06 2,52 12 (30,30) ,10 3,73 13 (30,30) ,00 0,00 14 (30,30) ,05 3,18 15 (70,40) ,18 6,16 16 (40,70) ,19 5,27 17 (100,100) ,32 25,27 18 (100,100) ,17 18,35 19 (100,100) n/f n/f n/f 7,37 12,41 20 (100,100) ,91 37,46 21 (100,100) ,63 61,90 Deviazione media dall ottimo 6,62% 6,62% 4,76 8,86 n/f: Nessuna soluzione fattibile è stata trovata Tabella 7 Tabu Search - Problemi di tipo doubly constrained 102
105 Dimensioni CPU (s) I (L,W) m M Ciani Alvarez Ottimo Ciani Alvarez 1 (400,200) ,00 0,00 2 (400,200) ,00 0,02 3 (400,400) ,04 0,38 4 (70,80) ,51 1,89 5 (70,80) ,42 16,88 6 (120,45) ,20 0,42 7 (90,45) ,04 1,97 8 (65,45) ,51 1,53 9 (150,110) ,91 52,36 10 (160,120) ,93 63,95 11 (20,20) ,13 0,42 12 (20,20) ,86 4,23 13 (20,20) ,19 0,95 14 (40,15) ,11 0,44 15 (40,15) ,95 4,16 16 (40,15) ,00 0,00 17 (60,30) ,03 4,91 18 (60,30) ,52 10,11 19 (60,30) ,47 5,52 20 (60,60) ,82 45,27 21 (60,60) ,93 68,59 22 (60,60) ,05 51,11 23 (60,90) ,88 135,97 24 (60,90) ,14 96,80 25 (60,90) ,23 82,06 26 (80,120) ,66 240,39 27 (80,120) ,73 399,86 28 (80,120) ,98 206,78 29 (160,240) , ,38 30 (160,240) , ,70 31 (160,240) , ,75 Deviazione media dall ottimo 0,46% 0,42% 107,96 392,19 Numero di soluzioni ottime Tabella 8 Tabu Search - Problemi di tipo unweighted 103
106 7.2.3 Confronto tra le due tecniche Sebbene la tecnica GRASP produca un algoritmo eccezionale sotto il profilo dei risultati, dimostrando di essere una delle euristiche che meglio si adatta al problema di taglio bidimensionale, la tecnica Tabu Search si rivela addirittura superiore permettendo di realizzare un algoritmo in grado di risolvere tutte le categorie di problemi presentate in precedenza, con risultati migliori ovunque (come si vede dalla Figura 18). Per quanto riguarda i tempi di esecuzione, invece, i due algoritmi presentano risultati diversi. I problemi provenienti dalla letteratura, sia nel caso constrained, sia nel caso doubly constrained, vengono risolti dai due algoritmi in tempi più o meno uguali (con una leggera preferenza per l algoritmo Tabu Search). I risultati dei problemi di grosse dimensioni e di quelli unweighted, invece, sono ottenuti dall algoritmo GRASP in tempi notevolmente inferiori. Per questo motivo è possibile concludere che, qualora il maggior tempo impiegato non sia un vincolo strettissimo, è preferibile impiegare sempre l algoritmo Tabu Search. Qualora invece, il tempo sia il vincolo fondamentale, per problemi complessi è meglio utilizzare l algoritmo GRASP, accontentandosi di risultati leggermente peggiori. Figura 18 Confronto tra le due tecniche 104
107 Conclusioni In questa tesi sono stati sviluppati due algoritmi euristici, uno basato sulla tecnica GRASP e uno basato sulla tecnica Tabu Search. Entrambi gli algoritmi risolvono problemi di taglio bidimensionale non a ghigliottina. L algoritmo GRASP è costituito da due fasi: una costruttiva e una di miglioramento. Nella prima fase l algoritmo seleziona i pezzi da tagliare, in maniera casuale, utilizzando una procedura di tipo greedy. Nella seconda fase, invece, vengono modificate alcune decisioni prese nella fase costruttiva, permettendo all intera procedura di migliorare la soluzione trovata. Durante le varie iterazioni vengono eseguite procedure per diminuire la complessità del problema e per adattare la scelta dei pezzi ai risultati fino a quel momento ottenuti. Per quanto riguarda l algoritmo Tabu Search, sono state proposte due mosse che si fondano sull inserimento e sulla riduzione di blocchi di pezzi. L efficienza delle mosse si basa su una strategia di tipo merge and fill che adatta i rettangoli vuoti ai pezzi ancora da tagliare. Inoltre sono state sviluppate anche strategie di tabu list dinamica, e di diversificazione e intensificazione, basate sulla memoria a lungo termine. I risultati computazionali dimostrano che gli algoritmi producono risultati ottimi per ogni categoria di problemi: di piccole e di grandi dimensioni, constrained e doubly constrained, weighted e unweighted. Per questo motivo, gli algoritmi dimostrano di essere totalmente general purpose e adatti ad ogni tipo di problema di taglio bidimensionale. 105
108
109 Possibili sviluppi futuri Entrambi gli algoritmi hanno dimostrato di essere altamente competitivi e pronti per essere utilizzati da una qualunque azienda, che necessiti di un programma in grado di risolvere il problema di taglio bidimensionale presentato in precedenza. Tuttavia, poiché gli algoritmi sono stati implementati in maniera totalmente modulare e con codice altamente riusabile, sarebbe possibile migliorare sia le prestazioni che l interfaccia in maniera relativamente semplice. Tra questi miglioramenti è possibile: 1. Utilizzare una tecnica più efficiente nella fase di miglioramento dell algoritmo GRASP (semplicemente sostituendo la vecchia funzione con quella nuova). 2. Introdurre nuove mosse nell algoritmo Tabu Search per giungere più velocemente alla soluzione migliore (semplicemente aggiungendole al corpo principale dell algoritmo). 3. Applicare una tecnica mista costituita da una prima fase costruttiva in cui pezzi e rettangoli vuoti vengono scelti in maniera casuale (GRASP), e da una seconda fase in cui si applicano mosse e strategie tipiche dell approccio Tabu Search. 4. Sviluppare un interfaccia più potente che permetta, per esempio, di introdurre i dati dei problemi in diversi modi (e non solo tramite file) o di visualizzare le soluzioni ottenute, magari con l utilizzo di componenti grafici. 107
110
111 Bibliografia [1] Alvarez-Valdes R, Parreño F e Tamarit JM (2005). A GRASP algorithm for constrained two-dimensional non-guillotine cutting problems. J Opl Res Soc 56: [2] Alvarez-Valdes R, Parreño F e Tamarit JM (2005). A tabu search algorithm for two-dimensional non-guillotine cutting problems. J Opl Res Soc: attualmente in stampa. [3] Tsai RD, Malstrom EM e Meeks HD (1988). A two-dimesional palletizing procedure for warehouse loading operations. IIE Trans 20: [4] Arenales M e Morabito R (1995). An AND/OR-graph approach to the solution ot two-dimensional non-guillotine cutting problems. Eur J Opl Res 84: [5] Healy P, Creavin M e Kuusik A (1999). An optimal algorithm for placement rectangle. Opns Res Lett 24: [6] Beasley JE (1985). An exact two-dimensional non-guillotine cutting tree search procedure. Opns Res 33: [7] Scheithauer G e Terno J (1993). Modeling of packing problems. Optimization 28: [8] Hadjiconstantinou E e Christofides N (1995). An exact algorithm for general, orthogonal, two-dimensional knapsack problems. Eur J Opl Res 83:
112 [9] Fekete SP e Schepers J (2004). An exact algorithm for higherdimensional orthogonal packing. Il materiale è disponibile all indirizzo fekete [10] Caprara A e Monaci M (2004). On the two-dimensional Knapsack problem. Opns Res Lett 32: [11] Lai KK e Chan JWM (1997). Developing a simulated annealing algorithm for the cutting stock problem. Comput Ind Eng 32: [12] Lai KK e Chan JWM (1997). A evolutionary algorithm for the rectangular cutting stock problem. Int J Ind Eng 4: [13] Leung TW, Yung CH e Troutt MD (2001). Applications of genetic search and simulated annealing to the two-dimensional non-guillotine cutting stock problem. Comput Ind Eng 40: [14] Leung TW, Chan CK e Troutt MD (2003). Application of a mixed simulated annealing-genetic algorithm heuristic for the two-dimensional orthogonal packing problem. Eur J Opl Res 145: [15] Beasley JE (2004). A population heuristic for constrained twodimensional non-guillotine cutting. Eur J Opl Res 156: [16] Feo T e Resende MGC (1989). A probabilistic heuristic for a computationally difficult set covering problem. Opns Res Lett 8: [17] Resende MGC e Ribeiro CC (2003). Greedy randomized adaptive search procedures. Handbook of Metaheuristics. Kluwer Academic Publishers, Dordrecht, MA, pp [18] Prais M e Ribeiro CC (2000). Reactive GRASP: an application to a matrix decomposition problem in TDMA traffic assignment. INFORMS J Comput 12: [19] Delorme X, Gandibleux X e Rodriguez J (2003). GRASP for set packing problems. Eur J Opl Res 153:
113 [20] Beltrán JC, Celderón JE, Cabrera RJ e Moreno JM (2002). Procedimientos constructivos adaptativos (GRASP) para el problema del empaquetado bidimensional. Rev Iberoam Intel Artif 15: [21] Wang PY (1983). Two algorithms for constrained two-dimensional cutting stock problems. Opns Res 31: [22] Christofides N e Whitlock C (1977). An algorithm for two-dimensional cutting problems. Opns Res 25: [23] Jakobs S (1996). On genetic algorithms for the packing of polygons. Eur J Opl Res 88: [24] Glover F e Laguna M (1997). Tabu Search. Kluver Academic Publishers, Boston. [25] Hopper E e Turton BCH (2001). An empirical investigation of metaheuristic and heuristic algorithms for a 2D packing problem. Eur J Opl Res 128: [26] Ducatelle F e Levine J (2001). Ant Colony Optimization for Bin Packing and Cutting Stock Problems. Proceedings of the UK Workshop on Computational Intelligence. 111
Introduzione agli Algoritmi Genetici Prof. Beatrice Lazzerini
Introduzione agli Algoritmi Genetici Prof. Beatrice Lazzerini Dipartimento di Ingegneria della Informazione Via Diotisalvi, 2 56122 PISA ALGORITMI GENETICI (GA) Sono usati per risolvere problemi di ricerca
Page 1. Evoluzione. Intelligenza Artificiale. Algoritmi Genetici. Evoluzione. Evoluzione: nomenclatura. Corrispondenze natura-calcolo
Evoluzione In ogni popolazione si verificano delle mutazioni. Intelligenza Artificiale In un ambiente che varia, le mutazioni possono generare individui che meglio si adattano alle nuove condizioni. Questi
Ottimizzazione Multi Obiettivo
Ottimizzazione Multi Obiettivo 1 Ottimizzazione Multi Obiettivo I problemi affrontati fino ad ora erano caratterizzati da una unica (e ben definita) funzione obiettivo. I problemi di ottimizzazione reali
Parte I. Prima Parte
Parte I Prima Parte Capitolo 1 Introduzione generale 1.1 Il problema dell assegnazione Corsi-Borsisti Il problema dell assegnazione delle borse dei corsi ai vari studenti può essere riassunto nei punti
Automazione Industriale (scheduling+mms) scheduling+mms. [email protected]
Automazione Industriale (scheduling+mms) scheduling+mms [email protected] Introduzione Sistemi e Modelli Lo studio e l analisi di sistemi tramite una rappresentazione astratta o una sua formalizzazione
Ricerca Operativa A.A. 2007/2008
Ricerca Operativa A.A. 2007/2008 9. Cenni su euristiche e metaeuristiche per ottimizzazione combinatoria Motivazioni L applicazione di metodi esatti non è sempre possibile a causa della complessità del
Appunti sulla Macchina di Turing. Macchina di Turing
Macchina di Turing Una macchina di Turing è costituita dai seguenti elementi (vedi fig. 1): a) una unità di memoria, detta memoria esterna, consistente in un nastro illimitato in entrambi i sensi e suddiviso
Algoritmi e strutture dati. Codici di Huffman
Algoritmi e strutture dati Codici di Huffman Memorizzazione dei dati Quando un file viene memorizzato, esso va memorizzato in qualche formato binario Modo più semplice: memorizzare il codice ASCII per
Dimensione di uno Spazio vettoriale
Capitolo 4 Dimensione di uno Spazio vettoriale 4.1 Introduzione Dedichiamo questo capitolo ad un concetto fondamentale in algebra lineare: la dimensione di uno spazio vettoriale. Daremo una definizione
Analisi e diagramma di Pareto
Analisi e diagramma di Pareto L'analisi di Pareto è una metodologia statistica utilizzata per individuare i problemi più rilevanti nella situazione in esame e quindi le priorità di intervento. L'obiettivo
Capitolo 13: L offerta dell impresa e il surplus del produttore
Capitolo 13: L offerta dell impresa e il surplus del produttore 13.1: Introduzione L analisi dei due capitoli precedenti ha fornito tutti i concetti necessari per affrontare l argomento di questo capitolo:
Siamo così arrivati all aritmetica modulare, ma anche a individuare alcuni aspetti di come funziona l aritmetica del calcolatore come vedremo.
DALLE PESATE ALL ARITMETICA FINITA IN BASE 2 Si è trovato, partendo da un problema concreto, che con la base 2, utilizzando alcune potenze della base, operando con solo addizioni, posso ottenere tutti
f(x) = 1 x. Il dominio di questa funzione è il sottoinsieme proprio di R dato da
Data una funzione reale f di variabile reale x, definita su un sottoinsieme proprio D f di R (con questo voglio dire che il dominio di f è un sottoinsieme di R che non coincide con tutto R), ci si chiede
Introduzione agli Algoritmi Genetici Prof. Beatrice Lazzerini
Introduzione agli Algoritmi Genetici Prof. Beatrice Lazzerini Dipartimento di Ingegneria della Informazione Via Diotisalvi, 2 56122 PISA ALGORITMI GENETICI (GA) Sono usati per risolvere problemi di ricerca
Il concetto di valore medio in generale
Il concetto di valore medio in generale Nella statistica descrittiva si distinguono solitamente due tipi di medie: - le medie analitiche, che soddisfano ad una condizione di invarianza e si calcolano tenendo
e-dva - eni-depth Velocity Analysis
Lo scopo dell Analisi di Velocità di Migrazione (MVA) è quello di ottenere un modello della velocità nel sottosuolo che abbia dei tempi di riflessione compatibili con quelli osservati nei dati. Ciò significa
Un gioco con tre dadi
Un gioco con tre dadi Livello scolare: biennio Abilità interessate Costruire lo spazio degli eventi in casi semplici e determinarne la cardinalità. Valutare la probabilità in diversi contesti problematici.
CAPITOLO 10 I SINDACATI
CAPITOLO 10 I SINDACATI 10-1. Fate l ipotesi che la curva di domanda di lavoro di una impresa sia data da: 20 0,01 E, dove è il salario orario e E il livello di occupazione. Ipotizzate inoltre che la funzione
La distribuzione Normale. La distribuzione Normale
La Distribuzione Normale o Gaussiana è la distribuzione più importante ed utilizzata in tutta la statistica La curva delle frequenze della distribuzione Normale ha una forma caratteristica, simile ad una
PROBABILITÀ - SCHEDA N. 2 LE VARIABILI ALEATORIE
Matematica e statistica: dai dati ai modelli alle scelte www.dima.unige/pls_statistica Responsabili scientifici M.P. Rogantin e E. Sasso (Dipartimento di Matematica Università di Genova) PROBABILITÀ -
1. Distribuzioni campionarie
Università degli Studi di Basilicata Facoltà di Economia Corso di Laurea in Economia Aziendale - a.a. 2012/2013 lezioni di statistica del 3 e 6 giugno 2013 - di Massimo Cristallo - 1. Distribuzioni campionarie
Intelligenza Artificiale
Intelligenza Artificiale Esercizi e Domande di Esame Tecniche di Ricerca e Pianificazione Esercizi Griglia Si consideri un ambiente costituito da una griglia n n in cui si muove un agente che può spostarsi
Riproduzione Crossover Mutazione
Algoritmi Genetici Sono algoritmi di ricerca basati sui principi evolutivi della selezione naturale e della genetica, che implicano la sopravvivenza degli elementi migliori e lo scambio di informazioni
Aprire WEKA Explorer Caricare il file circletrain.arff Selezionare random split al 66% come modalità di test Selezionare J48 come classificatore e
Alberi di decisione Aprire WEKA Explorer Caricare il file circletrain.arff Selezionare random split al 66% come modalità di test Selezionare J48 come classificatore e lanciarlo con i parametri di default.
Quadratic assignment Problem: The Hospital Layout
Università degli Studi di Modena e Reggio Emilia Corso di Laurea Magistrale in Ingegneria Gestionale Metodi di ottimizzazione per la logistica e la produzione Quadratic assignment Problem: The Hospital
APPUNTI DI MATEMATICA LE FRAZIONI ALGEBRICHE ALESSANDRO BOCCONI
APPUNTI DI MATEMATICA LE FRAZIONI ALGEBRICHE ALESSANDRO BOCCONI Indice 1 Le frazioni algebriche 1.1 Il minimo comune multiplo e il Massimo Comun Divisore fra polinomi........ 1. Le frazioni algebriche....................................
Indice generale. OOA Analisi Orientata agli Oggetti. Introduzione. Analisi
Indice generale OOA Analisi Orientata agli Oggetti Introduzione Analisi Metodi d' analisi Analisi funzionale Analisi del flusso dei dati Analisi delle informazioni Analisi Orientata agli Oggetti (OOA)
Funzioni funzione dominio codominio legge argomento variabile indipendente variabile dipendente
Funzioni In matematica, una funzione f da X in Y consiste in: 1. un insieme X detto dominio di f 2. un insieme Y detto codominio di f 3. una legge che ad ogni elemento x in X associa uno ed un solo elemento
B+Trees. Introduzione
B+Trees Introduzione B+Trees Il B+Trees e la variante maggiormente utilizzata dei BTrees BTrees e B+trees fanno parte della famiglia degli alberi di ricerca. Nel B+Trees i dati sono memorizzati solo nelle
RECUPERO DATI LIFO DA ARCHIVI ESTERNI
RECUPERO DATI LIFO DA ARCHIVI ESTERNI È possibile importare i dati relativi ai LIFO di esercizi non gestiti con Arca2000? La risposta è Sì. Esistono tre strade per recuperare i dati LIFO per gli articoli
Metodi e Modelli per l Ottimizzazione Combinatoria Il problema del flusso di costo minimo
Metodi e Modelli per l Ottimizzazione Combinatoria Il problema del flusso di costo minimo L. De Giovanni G. Zambelli 1 Problema del flusso a costo minimo Il problema del flusso a costo minimo é definito
Ricerca Operativa Esercizi sul metodo del simplesso. Luigi De Giovanni, Laura Brentegani
Ricerca Operativa Esercizi sul metodo del simplesso Luigi De Giovanni, Laura Brentegani 1 1) Risolvere il seguente problema di programmazione lineare. ma + + 3 s.t. 2 + + 2 + 2 + 3 5 2 + 2 + 6,, 0 Soluzione.
Sommario. Definizione di informatica. Definizione di un calcolatore come esecutore. Gli algoritmi.
Algoritmi 1 Sommario Definizione di informatica. Definizione di un calcolatore come esecutore. Gli algoritmi. 2 Informatica Nome Informatica=informazione+automatica. Definizione Scienza che si occupa dell
Il Metodo Branch and Bound
Il Laura Galli Dipartimento di Informatica Largo B. Pontecorvo 3, 56127 Pisa [email protected] http://www.di.unipi.it/~galli 4 Novembre 2014 Ricerca Operativa 2 Laurea Magistrale in Ingegneria Gestionale
Corso di Calcolo Numerico
Corso di Calcolo Numerico Dott.ssa M.C. De Bonis Università degli Studi della Basilicata, Potenza Facoltà di Ingegneria Corso di Laurea in Ingegneria Meccanica Sistemi di Numerazione Sistema decimale La
Corso di Informatica Generale (C. L. Economia e Commercio) Ing. Valerio Lacagnina Rappresentazione in virgola mobile
Problemi connessi all utilizzo di un numero di bit limitato Abbiamo visto quali sono i vantaggi dell utilizzo della rappresentazione in complemento alla base: corrispondenza biunivoca fra rappresentazione
LE FUNZIONI A DUE VARIABILI
Capitolo I LE FUNZIONI A DUE VARIABILI In questo primo capitolo introduciamo alcune definizioni di base delle funzioni reali a due variabili reali. Nel seguito R denoterà l insieme dei numeri reali mentre
Plate Locator Riconoscimento Automatico di Targhe
Progetto per Laboratorio di Informatica 3 - Rimotti Daniele, Santinelli Gabriele Plate Locator Riconoscimento Automatico di Targhe Il programma plate_locator.m prende come input: l immagine della targa
Il sapere tende oggi a caratterizzarsi non più come un insieme di contenuti ma come un insieme di metodi e di strategie per risolvere problemi.
E. Calabrese: Fondamenti di Informatica Problemi-1 Il sapere tende oggi a caratterizzarsi non più come un insieme di contenuti ma come un insieme di metodi e di strategie per risolvere problemi. L'informatica
Laboratorio di Pedagogia Sperimentale. Indice
INSEGNAMENTO DI LABORATORIO DI PEDAGOGIA SPERIMENTALE LEZIONE III INTRODUZIONE ALLA RICERCA SPERIMENTALE (PARTE III) PROF. VINCENZO BONAZZA Indice 1 L ipotesi -----------------------------------------------------------
STATISTICA IX lezione
Anno Accademico 013-014 STATISTICA IX lezione 1 Il problema della verifica di un ipotesi statistica In termini generali, si studia la distribuzione T(X) di un opportuna grandezza X legata ai parametri
Analisi sensitività. Strumenti per il supporto alle decisioni nel processo di Valutazione d azienda
Analisi sensitività. Strumenti per il supporto alle decisioni nel processo di Valutazione d azienda Premessa Con l analisi di sensitività il perito valutatore elabora un range di valori invece di un dato
Relazioni statistiche: regressione e correlazione
Relazioni statistiche: regressione e correlazione È detto studio della connessione lo studio si occupa della ricerca di relazioni fra due variabili statistiche o fra una mutabile e una variabile statistica
Statistica. Lezione 6
Università degli Studi del Piemonte Orientale Corso di Laurea in Infermieristica Corso integrato in Scienze della Prevenzione e dei Servizi sanitari Statistica Lezione 6 a.a 011-01 Dott.ssa Daniela Ferrante
Capitolo 4: Ottimizzazione non lineare non vincolata parte II. E. Amaldi DEIB, Politecnico di Milano
Capitolo 4: Ottimizzazione non lineare non vincolata parte II E. Amaldi DEIB, Politecnico di Milano 4.3 Algoritmi iterativi e convergenza Programma non lineare (PNL): min f(x) s.v. g i (x) 0 1 i m x S
LA TRASMISSIONE DELLE INFORMAZIONI QUARTA PARTE 1
LA TRASMISSIONE DELLE INFORMAZIONI QUARTA PARTE 1 I CODICI 1 IL CODICE BCD 1 Somma in BCD 2 Sottrazione BCD 5 IL CODICE ECCESSO 3 20 La trasmissione delle informazioni Quarta Parte I codici Il codice BCD
come nasce una ricerca
PSICOLOGIA SOCIALE lez. 2 RICERCA SCIENTIFICA O SENSO COMUNE? Paola Magnano [email protected] ricevimento: martedì ore 10-11 c/o Studio 16, piano -1 PSICOLOGIA SOCIALE COME SCIENZA EMPIRICA le sue
LE SUCCESSIONI 1. COS E UNA SUCCESSIONE
LE SUCCESSIONI 1. COS E UNA SUCCESSIONE La sequenza costituisce un esempio di SUCCESSIONE. Ecco un altro esempio di successione: Una successione è dunque una sequenza infinita di numeri reali (ma potrebbe
3 GRAFICI DI FUNZIONI
3 GRAFICI DI FUNZIONI Particolari sottoinsiemi di R che noi studieremo sono i grafici di funzioni. Il grafico di una funzione f (se non è specificato il dominio di definizione) è dato da {(x, y) : x dom
risulta (x) = 1 se x < 0.
Questo file si pone come obiettivo quello di mostrarvi come lo studio di una funzione reale di una variabile reale, nella cui espressione compare un qualche valore assoluto, possa essere svolto senza necessariamente
Slide Cerbara parte1 5. Le distribuzioni teoriche
Slide Cerbara parte1 5 Le distribuzioni teoriche I fenomeni biologici, demografici, sociali ed economici, che sono il principale oggetto della statistica, non sono retti da leggi matematiche. Però dalle
CALCOLO COMBINATORIO
CALCOLO COMBINATORIO 1 Modi di formare gruppi di k oggetti presi da n dati 11 disposizioni semplici, permutazioni Dati n oggetti distinti a 1,, a n si chiamano disposizioni semplici di questi oggetti,
Scheduling della CPU. Sistemi multiprocessori e real time Metodi di valutazione Esempi: Solaris 2 Windows 2000 Linux
Scheduling della CPU Sistemi multiprocessori e real time Metodi di valutazione Esempi: Solaris 2 Windows 2000 Linux Sistemi multiprocessori Fin qui si sono trattati i problemi di scheduling su singola
Corso di. Dott.ssa Donatella Cocca
Corso di Statistica medica e applicata Dott.ssa Donatella Cocca 1 a Lezione Cos'è la statistica? Come in tutta la ricerca scientifica sperimentale, anche nelle scienze mediche e biologiche è indispensabile
Testo alla base del Pitgame redatto dal prof. Yvan Lengwiler, Università di Basilea
Testo alla base del Pitgame redatto dal prof. Yvan Lengwiler, Università di Basilea Funzionamento di un mercato ben organizzato Nel Pitgame i giocatori che hanno poche informazioni private interagiscono
Effetto reddito ed effetto sostituzione.
. Indice.. 1 1. Effetto sostituzione di Slutsky. 3 2. Effetto reddito. 6 3. Effetto complessivo. 7 II . Si consideri un consumatore che può scegliere panieri (x 1 ; ) composti da due soli beni (il bene
Un po di statistica. Christian Ferrari. Laboratorio di Matematica
Un po di statistica Christian Ferrari Laboratorio di Matematica 1 Introduzione La statistica è una parte della matematica applicata che si occupa della raccolta, dell analisi e dell interpretazione di
TECNICHE DI SIMULAZIONE
TECNICHE DI SIMULAZIONE INTRODUZIONE Francesca Mazzia Dipartimento di Matematica Università di Bari a.a. 2004/2005 TECNICHE DI SIMULAZIONE p. 1 Introduzione alla simulazione Una simulazione è l imitazione
lo 2 2-1 - PERSONALIZZARE LA FINESTRA DI WORD 2000
Capittol lo 2 Visualizzazione 2-1 - PERSONALIZZARE LA FINESTRA DI WORD 2000 Nel primo capitolo sono state analizzate le diverse componenti della finestra di Word 2000: barra del titolo, barra dei menu,
Capitolo 2. Operazione di limite
Capitolo 2 Operazione di ite In questo capitolo vogliamo occuparci dell operazione di ite, strumento indispensabile per scoprire molte proprietà delle funzioni. D ora in avanti riguarderemo i domini A
GUIDA RAPIDA PER LA COMPILAZIONE DELLA SCHEDA CCNL GUIDA RAPIDA PER LA COMPILAZIONE DELLA SCHEDA CCNL
GUIDA RAPIDA BOZZA 23/07/2008 INDICE 1. PERCHÉ UNA NUOVA VERSIONE DEI MODULI DI RACCOLTA DATI... 3 2. INDICAZIONI GENERALI... 4 2.1. Non modificare la struttura dei fogli di lavoro... 4 2.2. Cosa significano
Probabilità discreta
Probabilità discreta Daniele A. Gewurz 1 Che probabilità c è che succeda...? Una delle applicazioni della combinatoria è nel calcolo di probabilità discrete. Quando abbiamo a che fare con un fenomeno che
L analisi dei rischi: l aspetto statistico Ing. Pier Giorgio DELLA ROLE Six Sigma Master Black Belt
L analisi dei rischi: l aspetto statistico Ing. Pier Giorgio DELL ROLE Six Sigma Master lack elt Dicembre, 009 Introduzione Nell esecuzione dei progetti Six Sigma è di fondamentale importanza sapere se
Mon Ami 3000 Varianti articolo Gestione di varianti articoli
Prerequisiti Mon Ami 3000 Varianti articolo Gestione di varianti articoli L opzione Varianti articolo è disponibile per le versioni Azienda Light e Azienda Pro e include tre funzionalità distinte: 1. Gestione
4 3 4 = 4 x 10 2 + 3 x 10 1 + 4 x 10 0 aaa 10 2 10 1 10 0
Rappresentazione dei numeri I numeri che siamo abituati ad utilizzare sono espressi utilizzando il sistema di numerazione decimale, che si chiama così perché utilizza 0 cifre (0,,2,3,4,5,6,7,8,9). Si dice
( x) ( x) 0. Equazioni irrazionali
Equazioni irrazionali Definizione: si definisce equazione irrazionale un equazione in cui compaiono uno o più radicali contenenti l incognita. Esempio 7 Ricordiamo quanto visto sulle condizioni di esistenza
Introduzione all analisi dei segnali digitali.
Introduzione all analisi dei segnali digitali. Lezioni per il corso di Laboratorio di Fisica IV Isidoro Ferrante A.A. 2001/2002 1 Segnali analogici Si dice segnale la variazione di una qualsiasi grandezza
Logica Numerica Approfondimento 1. Minimo Comune Multiplo e Massimo Comun Divisore. Il concetto di multiplo e di divisore. Il Minimo Comune Multiplo
Logica Numerica Approfondimento E. Barbuto Minimo Comune Multiplo e Massimo Comun Divisore Il concetto di multiplo e di divisore Considerato un numero intero n, se esso viene moltiplicato per un numero
Il mercato di monopolio
Il monopolio Il mercato di monopolio Il monopolio è una struttura di mercato caratterizzata da 1. Un unico venditore di un prodotto non sostituibile. Non ci sono altre imprese che possano competere con
Sistema operativo. Sommario. Sistema operativo...1 Browser...1. Convenzioni adottate
MODULO BASE Quanto segue deve essere rispettato se si vuole che le immagini presentate nei vari moduli corrispondano, con buona probabilità, a quanto apparirà nello schermo del proprio computer nel momento
Sequenziamento a minimo costo di commutazione in macchine o celle con costo lineare e posizione home (In generale il metodo di ottimizzazione
Sequenziamento a minimo costo di commutazione in macchine o celle con costo lineare e posizione home (In generale il metodo di ottimizzazione presentato in questo file trova la seq. a costo minimo per
Test d ipotesi. Statistica e biometria. D. Bertacchi. Test d ipotesi
In molte situazioni una raccolta di dati (=esiti di esperimenti aleatori) viene fatta per prendere delle decisioni sulla base di quei dati. Ad esempio sperimentazioni su un nuovo farmaco per decidere se
Transitori del primo ordine
Università di Ferrara Corso di Elettrotecnica Transitori del primo ordine Si consideri il circuito in figura, composto da un generatore ideale di tensione, una resistenza ed una capacità. I tre bipoli
Guida Compilazione Piani di Studio on-line
Guida Compilazione Piani di Studio on-line SIA (Sistemi Informativi d Ateneo) Visualizzazione e presentazione piani di studio ordinamento 509 e 270 Università della Calabria (Unità organizzativa complessa-
(liberamente interpretato da http://www2.unipr.it/~bottarel/epi/homepage.html) SCHEDA ALUNNI. Descrizione dell attività:
Pagina 1 di 11 (liberamente interpretato da http://www2.unipr.it/~bottarel/epi/homepage.html) SCHEDA ALUNNI Descrizione dell attività: Problema 1. Siamo nel 2060 ed ormai gli umani hanno colonizzato Marte.
COME SI FORMA E COME SI RICONOSCE UN ROSS HOOK
COME SI FORMA E COME SI RICONOSCE UN ROSS HOOK di Francesco Fabi Trader Professionista e Responsabile di Joe Ross Trading Educators Italia PREMESSA Il Ross Hook è una delle formazioni grafiche che sono
Capitolo 25: Lo scambio nel mercato delle assicurazioni
Capitolo 25: Lo scambio nel mercato delle assicurazioni 25.1: Introduzione In questo capitolo la teoria economica discussa nei capitoli 23 e 24 viene applicata all analisi dello scambio del rischio nel
Esercizi su. Funzioni
Esercizi su Funzioni ๒ Varie Tracce extra Sul sito del corso ๓ Esercizi funz_max.cc funz_fattoriale.cc ๔ Documentazione Il codice va documentato (commentato) Leggibilità Riduzione degli errori Manutenibilità
VALORE DELLE MERCI SEQUESTRATE
La contraffazione in cifre: NUOVA METODOLOGIA PER LA STIMA DEL VALORE DELLE MERCI SEQUESTRATE Roma, Giugno 2013 Giugno 2013-1 Il valore economico dei sequestri In questo Focus si approfondiscono alcune
Corso di Matematica per la Chimica
Dott.ssa Maria Carmela De Bonis a.a. 203-4 I sistemi lineari Generalità sui sistemi lineari Molti problemi dell ingegneria, della fisica, della chimica, dell informatica e dell economia, si modellizzano
1) Si consideri un esperimento che consiste nel lancio di 5 dadi. Lo spazio campionario:
Esempi di domande risposta multipla (Modulo II) 1) Si consideri un esperimento che consiste nel lancio di 5 dadi. Lo spazio campionario: 1) ha un numero di elementi pari a 5; 2) ha un numero di elementi
Più processori uguale più velocità?
Più processori uguale più velocità? e un processore impiega per eseguire un programma un tempo T, un sistema formato da P processori dello stesso tipo esegue lo stesso programma in un tempo TP T / P? In
I ricavi ed i costi di produzione
I ricavi ed i costi di produzione Supponiamo che le imprese cerchino di operare secondo comportamenti efficienti, cioè comportamenti che raggiungono i fini desiderati con mezzi minimi (o, che è la stessa
Corrispondenze e funzioni
Corrispondenze e funzioni L attività fondamentale della mente umana consiste nello stabilire corrispondenze e relazioni tra oggetti; è anche per questo motivo che il concetto di corrispondenza è uno dei
Esponenziali elogaritmi
Esponenziali elogaritmi Potenze ad esponente reale Ricordiamo che per un qualsiasi numero razionale m n prendere n>0) si pone a m n = n a m (in cui si può sempre a patto che a sia un numero reale positivo.
15. Antico gioco russo
15. Antico gioco russo In un antico gioco russo, attraverso i risultati casuali ottenuti dall allacciamento di cordicelle, i giovani cercavano una previsione sul tipo di legame che si sarebbe instaurata
REGOLAZIONE (E TASSAZIONE OTTIMALE) DI UN MONOPOLIO CON PIÙ LINEE DI PRODUZIONE
REGOLAZIONE (E TASSAZIONE OTTIMALE) DI UN MONOPOLIO CON PIÙ LINEE DI PRODUZIONE Nella Sezione 16.5 abbiamo visto come un regolatore che voglia fissare il prezzo del monopolista in modo da minimizzare la
www.andreatorinesi.it
La lunghezza focale Lunghezza focale Si definisce lunghezza focale la distanza tra il centro ottico dell'obiettivo (a infinito ) e il piano su cui si forma l'immagine (nel caso del digitale, il sensore).
SPC e distribuzione normale con Access
SPC e distribuzione normale con Access In questo articolo esamineremo una applicazione Access per il calcolo e la rappresentazione grafica della distribuzione normale, collegata con tabelle di Clienti,
Determinare la grandezza della sottorete
Determinare la grandezza della sottorete Ogni rete IP possiede due indirizzi non assegnabili direttamente agli host l indirizzo della rete a cui appartiene e l'indirizzo di broadcast. Quando si creano
Test statistici di verifica di ipotesi
Test e verifica di ipotesi Test e verifica di ipotesi Il test delle ipotesi consente di verificare se, e quanto, una determinata ipotesi (di carattere biologico, medico, economico,...) è supportata dall
Uso di base delle funzioni in Microsoft Excel
Uso di base delle funzioni in Microsoft Excel Le funzioni Una funzione è un operatore che applicato a uno o più argomenti (valori, siano essi numeri con virgola, numeri interi, stringhe di caratteri) restituisce
DIPARTIMENTO DI STUDI UMANISTICI
DIPARTIMENTO DI STUDI UMANISTICI Corso di Laurea Interdipartimentale in Scienze della Formazione Primaria( Ind.Primaria) A.A 2013/2014 REPORT SULL ELABORAZIONE DI UN AGENTE ARITIFICIALE TEORIA E METODOLOGIA
Computational Game Theory
Computational Game Theory Vincenzo Bonifaci 24 maggio 2012 5 Regret Minimization Consideriamo uno scenario in cui un agente deve selezionare, più volte nel tempo, una decisione tra un insieme di N disponibili:
A intervalli regolari ogni router manda la sua tabella a tutti i vicini, e riceve quelle dei vicini.
Algoritmi di routing dinamici (pag.89) UdA2_L5 Nelle moderne reti si usano algoritmi dinamici, che si adattano automaticamente ai cambiamenti della rete. Questi algoritmi non sono eseguiti solo all'avvio
Il principio di induzione e i numeri naturali.
Il principio di induzione e i numeri naturali. Il principio di induzione è un potente strumento di dimostrazione, al quale si ricorre ogni volta che si debba dimostrare una proprietà in un numero infinito
(Esercizi Tratti da Temi d esame degli ordinamenti precedenti)
(Esercizi Tratti da Temi d esame degli ordinamenti precedenti) Esercizio 1 L'agenzia viaggi GV - Grandi Viaggi vi commissiona l'implementazione della funzione AssegnaVolo. Tale funzione riceve due liste
