programmazione MPL
1
Dipartimento di Elettronica e Informazione, Politecnico of Milano, Piazza L.
da Vinci 32, 20133 Milano, e-mail: brunetta@elet.polimi.it
2
Dipartimento di Matematica Pura e Applicata, Universit di Padova, Via
Belzoni 7, 35131 Padova ITALY, e-mail:damico@math.unipd.it
3
Dipartimento di Matematica Pura e Applicata, Universit di Padova, Via
Belzoni 7, 35131 Padova ITALY, e-mail:iluzzi@libero.it
Indice
1 Introduzione 1
I
6 Un Modello di Pianicazione con pi Impianti di Produzio-
ne 39
6.1 Formulazione del Modello . . . . . . . . . . . . . . . . . . . . 40
6.2 Risolvere il Modello e Analizzare la Soluzione . . . . . . . . . 41
7 Modelli di Trasporto 44
7.1 Usare la Condizione Where sui Vettori di Variabili . . . . . . 44
7.2 Vincoli di Bilanciamento degli Impianti . . . . . . . . . . . . 45
7.3 Un Modello di trasporto tra impianti di produzione . . . . . . 46
7.4 Formulazione del modello . . . . . . . . . . . . . . . . . . . . 47
7.5 Risolvere il Modello e Analizzare la Soluzione . . . . . . . . . 48
II
Lobiettivo di queste dispensa quello di fornire una guida in italiano uti-
le per apprendere le idee di base di uno dei software di ottimizzazione pi
diffusi. Gli argomenti trattati sono di livello elementare e, leggendo que-
ste pagine, chiunque abbia un minimo di dimestichezza con un qualsiasi
linguaggio di programmazione dovrebbe poter apprendere velocemente la
metodologia necessaria per creare e risolvere problemi di ottimizzazione li-
neare. Le pagine che seguono hanno quindi uno scopo puramente didattico
e speriamo possano essere uno strumento utile a chi si avvicina per la prima
volta a questo programma di ottimizzazione.
Nel primo capitolo viene spiegata la losoa di base sulla quale si fondano i
software detti generatori algebrici di modelli. Nel secondo capitolo viene
introdotta la forma di base di un modello in MPL. Si volutamente data
una struttura pi rigida di quella effettivamente necessaria per aiutare chi
si trova per la prima volta ad affrontare questo metodo di programmazione
a individuare i vari passi necessari per tradurre un problema di ottimiz-
zazione in un modello MPL. Nel terzo, quinto, sesto, settimo ed ottavo
capitolo sono discussi i modelli contenuti nel Tutorial di MPL. Nel quarto
capitolo sono discussi e tradotti in modelli MPL alcuni classici problemi di
programmazione lineare.
possibile ottenere la versione studenti del software MPL con licenza
duso semestrale al sito http://www.maximal-usa.com.
III
Capitolo 1
Introduzione
1
semplicemente problemi reali anche molto complessi. Inoltre il solutore pu
essere sostituito senza dover modicare la forma con la quale sono descritti
i modelli. Inne la possibilit di trattare in modo diverso i dati e struttu-
ra logica dei problemi fa si che piccole modiche nei dati o nella struttura
del modello siano gestibili senza dover riprogrammare completamente molte
righe di codice. Inne, la distinzione dati-modello permette di importare i
parametri che caratterizzano listanza di un problema da un database ester-
no lasciando libero lutente di occuparsi solo della formulazione logica del
modello.
Le principali caratteristiche di questi generatori algebrici di modelli sono le
seguenti:
2
Capitolo 2
Programmazione con il
linguaggio MPL
3
Windows. Per eseguire MPL, se non lo abbiamo ancora fatto, sufficiente
cliccare sul men Avvio e selezionare Programmi Mpl for Windows
1. Scegliamo Open nel men File per aprire la nestra di dialogo Open.
2. Doppio click sulla cartella dal nome Tutorial per entrare nella cartella
dove conservato il le del modello Model1.mpl.
1. Scegliere Solve CPLEX nel men Run per risolvere il modello Model1.
4
2. Durante la risoluzione del modello, viene mostrata la nestra di stato
(Status Window) che ci fornisce informazioni su come progredisce la
soluzione.
1. Premiamo il tasto View sul fondo della Status Window che apparsa
sul video durante il processo di risoluzione. Questa operazione aprir
una View Window che contiene il le di soluzione.
5
2. Sotto lintestazione VARIABLES nella nestra potremo osservare il
nome delle variabili in una lista: Produce, Inventory e Sales, che sono le
variabili del modello. Davanti allintestazione di ogni sezione, troviamo
un quadratino che contiene o un segno pi (+) o un segno meno (-).
Questo quadratino ci permette di espandere o comprimere velocemente
ogni ramo dellalbero.
Accesso agli argomenti di aiuto per MPL. Per aprire la nestra prin-
cipale di aiuto per MPL, andiamo nel men Help e scegliamo Topics. Ci
verr mostrata una nestra di aiuto, dove potremo selezionare largomento
che ci interessa.
La nestra di dialogo degli argomenti di aiuto di MPL (MPL Help
Topics dialog box) contiene tre bottoni; il bottone Contents , il bottone Index
e il bottone Find; fornendoci strade differenti per accedere agli aiuti.
6
Commenti
In MPL ci sono due tipi di commenti: le parentesi grafe { ...} rac-
chiudono commenti in blocco, cio che possono estendersi anche su pi
righe
{
Commento...
}
Separatori
I diversi statement allinterno di una sezione (indici, vincoli, etc...) de-
vono essere separati dal carattere ;
i = 1..5 ;
j = 1..12 ;
Gli elementi di una lista di valori devono essere separati dalla virgola ,
o da un a capo (questo permette di introdurre dei commenti esplicativi
accanto ad ogni valore).
nutrients = (Calorie,Protein,Calcium,Iron,Vitamin);
Required[nutrients] = ( 3 ! Calories
70 ! Protein
0.8 ! Calcium
12 ! Iron
75 ) ; ! Vitamin
Range di un insieme
Si pu esprimere un insieme di valori con luso di caratteri speciali:
["val"]
7
Formule
Si possono scrivere espressioni che comprendono le normali operazioni
aritmetiche +, -, *, / nonch diverse altre funzioni matematiche: sqr, sqrt,
sin, cos, log, ext, power ....
Esiste inoltre la funzione sommatoria che richiede come primo parametro
il nome dellindice su cui iterare e come secondo lespressione da valutare
con lindice specico:
2.3.1 TITLE
Il titolo del modello non obbligatiorio, ma buona norma assegnare
un titolo ad ogni problema e terminare la riga con il carattere ;
2.3.2 INDEX
Gli indici deniscono il dominio del problema e la sua dimensione. De-
vono essere dichiarati con il carattere := e possono essere sia numerici che
alfabetici. Per i primi sufficiente specicare i due valori estremi separati
dal carattere ...
8
month := 1..12;
Gli indici alfabetici invece, vengono dichiarati come lista di nomi, se-
parati dalla virgola e racchiusi tra parentesi tonde. Questo secondo tipo
preferibile a primo in quanto rende molto pi chiara la lettura di vincoli ed
altre espressioni in cui essi vengono usati.
nutrients := (Calorie,Protein,Calcium,Iron,Vitamin);
Indici alias
In MPL possibile assegnare un nuovo nome ad uno stesso indice senza
dover ripeterne la denizione:
i := 1..4;
j := i;
Indici circolari
Per alcuni tipi di indice, in particolare quelli temporali, si ha la neces-
sit di denire un offset sullindice, ad esempio Stock[month-1]. Se lindi-
ce esce dal range assegnato MPL ignora quel particolare valore. Si pu
invece forzarlo a ripartire dalla parte opposta del range rendendo la lista
circolare. Basta aggiungere alla dichiarazione dellindice la parola riservata
CIRCULAR.
Sottoinsiemi di indici
Se si vuole dichiarare un nuovo indice composto da un sottoinsieme di
valori di un altro basta usare la seguente sintassi:
9
INDEX
plants := (NewYork, Chicago, London, Paris);
OpenPlants[plants] := (NewYork, London);
EuropePlants[plants] := (London, Paris);
! Differenza
ClosedPlants[plants] := plants - OpenPlants;
! := (Chicago, Paris)
! Negazione
USPlants[plants] := NOT EuropePlants;
! := (NewYork, Chicago)
! Unione
OpenOrEurope[plants] := OpenPlants OR EuropePlants;
! := (NewYork, London, Paris)
! Intersezione
OpenAndEurope[plants] := OpenPlants AND EuropePlants;
! := (London)
Indici da le esterno
La lista di valori di un indice pu anche essere letta da un le esterno in
cui i dati sono separati dalla virgola o da uno spazio. Se poi oltre allindice
il le contiene anche altri dati, si pu specicare quale colonna contiene i
valori dellindice.
2.3.3 DATA
In questa sezione vengono specicati i valori dei dati da usare nel mo-
dello. Anche in questo caso essi possono essere dichiarati direttamente o
essere caricati da un le esterno, da un foglio elettronico o da un database,
con il comando DATAFILE. I dati possono essere scalari, vettori o matrici
multidimensionali.
Nel caso scalare il valore assegnato risulta una costante per tutta la
risoluzione del modello. Il carattere speciale ? serve per chiedere conferma
allutente del valore predenito.
NumberOfMonths = 12;
NumberOfYears = 4?;
10
Per i vettori e le matrici, gli indici sono racchiusi tra parentesi quadre,
e separati dalla virgola, mentre i relativi valori, sono racchiusi da parentesi
tonde e separati da virgola o a capo.
Nel caso di una matrice, la lista corrisponde alla scansione per riga della
matrice stessa. Lo stesso concetto si estende al caso di matrici multidimen-
sionali.
I dati possono essere valori semplici o il risultato di espressioni matema-
tiche.
2.3.4 DECISION
Nella sezione DECISION vengono dichiarate le variabili del problema
che possono essere scalari, vettori o matrici. Il nome completo della sezione
11
DECISION VARIABLES, ma MPL accetta indifferentemente uno delle
tre seguenti dichiarazioni:
DECISION VARIABLES
DECISION
VARIABLES
Nel caso di vettori o matrici, i relativi indici vanno racchiusi tra parentesi
quadre e separati dalla virgola.
Production[product,month]
2.3.5 MACROS
Le macro sono una caratteristica importante di MPL. Esse permettono
di denire delle espressioni a cui assegnare un nome specico da usare poi
nella denizione della funzione obiettivo e dei vincoli. In questo modo si
semplica il modello rendendolo allo stesso tempo pi leggibile.
La macro si denisce con un nome seguito dal simbolo := e dalla sua
espressione. Non si possono dichiarare macro indicizzate, ma si possono
usare vettori e formule nel calcolo della sua espressione.
2.3.6 MODEL
La parola chiave MODEL indica linizio della descrizione del modello
vero e proprio. La funzione obiettivo richiede come primo elemento il sen-
so di ottimizzazione: MAXIMIZE o MINIMIZE, che pu essere abbreviato
in MAX o MIN; segue il nome, il segno di uguaglianza = ed inne le-
spressione da valutare. Se non viene indicato alcun nome MPL assegna per
denizione il nome z alla funzione obietttivo.
12
2.3.7 SUBJECT TO
Questa la sezione che descrive i vincoli del problema. buona abitudine
assegnare un nome ad ogni vincolo, ed anteporlo alla sua denizione. Il
nome non pu contenere spazi vuoti ed altri caratteri riservati e deve essere
seguito dal simbolo :. Se non viene dichiarato alcun nome per il vincolo
i-esimo MPL assegna il generico nome ci. Unequazione composta da
due membri separati da uno dei seguenti segni di comparazione:
minore o uguale < <=
uguale =
maggiore o uguale > >=
I simboli < e > vengono interpretati come minore o uguale e maggiore o
uguale. Per comodit e facilit di lettura sia le variabili che le costanti
possono essere scritte in entrambi i lati della relazione. Le variabili possono
anche essere ripetute nella stessa formula o nei due lati dello stesso vincolo.
Ci pensa poi MPL ad accorpare i coefficienti e spostare tutte le variabili a
sinistra e a sommare le costanti in un unico valore da porre sul lato destra
della relazione.
Ogni vincolo pu estendersi anche su pi righe e deve essere terminato
con il simbolo ; per separarlo dal successivo.
Ci sono due tipi di vincoli: semplici e vettoriali.
Vincoli semplici
I vincoli semplici sono quelli deniti senza indici; sono formati dalla com-
binazione di variabili semplici, vettori costanti ed eventualmente sommatorie
su vettori di variabili purch tutte le variabili del vettore siano utilizzate.
3 (Sb1 + Co1 + So1) = 2 (Sb2 + Co2 + So2) ;
Overtime : Over < 50\% * 170 Workforce ;
Production : SUM(shifts: Prod[shifts]) < 3750 ;
Vincoli vettoriali
I vincoli vettoriali sono quelli indicizzati, cio vincoli che vengono ripe-
tuti cambiando il valore dellindice ogni volta. Si dichiarano aggiungendo
il nome dellindice racchiuso tra parentesi quadre subito dopo il nome del
vincolo e prima del simbolo :. Ovviamente lindice del vincolo deve essere
compatibile con quello dei vettori di variabili usati nella denizione del vin-
colo stesso. MPL poi espande questo singolo vincolo in una serie di vincoli
semplici basati sui relativi indici.
La denizione del vincolo avviene nello stesso modo dei vincoli semplici.
Si costruiscono equazioni composte da variabili, vettori di variabili, somma-
torie e costanti. Non occorre dichiarare lindice dopo ogni variabile, purch
questo sia compatibile con lindice principale del vincolo.
13
InventoryBalance[product,period]:
Inventory = Inventory[period-1] + Production - Sales ;
ProdCap[machine,time] :
SUM(tire: ProdRates * Prod) < ProdHours ;
InventoryBalance[month=Jan..Nov] : ...
InventoryBalance[month<=Jun] : ...
InventoryBalance[month=Dec] : ...
InventoryBalance[product,month]
WHERE (month > Jan)
2.3.8 BOUNDS
In questa sezione vengono deniti i limiti inferiori e superiori alle va-
riabili. La maggior parte dei risolutori LP prevede la possibilit di denire
bounds sulle variabili, migliorando lefficienza della loro gestione interna
rispetto alla dichiarazione di vincoli espliciti.
La denizione dei bounds riette esatamente quella dei vincoli. Il limite
pu andare sul lato sinistro o destro della relazione e si possono anche denire
vincoli composti del tipo:
x < 4*12 ;
z_bounds : 2 < z < 8 ;
CloseInv : Inventory[December] = 20000 ;
14
2.3.9 FREE
Questa e le due successive sezioni servono per denire il tipo di variabili
usate e possono essere poste in qualsiasi ordine purch dopo la sezione di
dichiarazione dei vincoli (SUBJECT TO).
MPL come la maggior parte dei risolutori LP, assume che le variabili
decisionali siano positive o nulle. Per permettere ad una variabile sempli-
ce o ad un vettore di variabili di assumere anche valori negativi bisogna
dichiararli come liberi.
FREE
Temperature ;
Inventory[month] ;
INTEGER
Production[month,product] ;
BINARY
ShopOpen ;
15
Capitolo 3
Un modello di bilanciamento
della produzione
Produzione A1 A2 A3
Costo di Produzione $73.30 $52.90 $65.40
Quota di Produzione 500 450 550
{ Planning3.mpl }
16
TITLE
Producton_Planning3;
INDEX
product := (A1, A2, A3);
DATA
Price[product] := (120.00, 100.00, 115.00);
Demand[product] := (4300, 4500, 5400);
ProdCost[product] := (73.30, 52.90, 65.40);
ProdRate[product] := (500, 450, 550);
ProdDaysAvail := 22;
VARIABLES
Produce[product] -> Prod;
MACROS
TotalRevenue := SUM(product: Price * Produce);
TotalCost := SUM(product: ProdCost * Produce);
MODEL
SUBJECT TO
ProdCapacity -> PCap:
SUM(product: Produce / ProdRate) <= ProdDaysAvail;
BOUNDS
Produce <= Demand;
END
17
Dopo aver risolto il modello possiamo visualizzare la soluzione in una
nestra cliccando il tasto View che si trova sul fondo della nestra di stato.
Questa operazione mostrer in una nestra (View Window) i dati che qui
riportiamo.
Filename: Planning3.mpl
Date: July 8, 2000
Time: 13:53
Parsing time: 0.33 sec
Constraints: 1
Variables: 3
Nonzeros: 3
Density: 100 %
SOLUTION RESULT
MACROS
18
TotalRevenue 1298181.8182
TotalCost 753615.1818
-----------------------------------------------
DECISION VARIABLES
VARIABLE Produce[product] :
CONSTRAINTS
PLAIN CONSTRAINTS
END
19
valore. Per esempio, nel nostro modello Planning3 le entrate totali sono di
1,298 milioni di dollari, mentre le spese sono circa 754.000 dollari. Questo
corrisponde ad un protto di circa $545.000, che il valore della funzione
obbiettivo.
Nella sezione DECISION VARIABLES possiamo trovare la lista di tutte
le variabili del modello: vettore di variabili e variabili semplici. Nel nostro
caso abbiamo un solo vettore di variabili produzione (Produce) denito su
lindice prodotti. Potremo osservare che per i prodotti A1 e A3 la soluzio-
ne suggerisce di produrre rispettivamente 4300 e 5400 pezzi. Questi valori
corrispondono alla domanda per questi prodotti. Daltro canto per A2 vie-
ne suggerito di produrre non pi di 1611 pezzi, questo corrisponde ad una
produzione inferiore alla domanda. Chiaramente non abbiamo la possibilit
di produrre abbastanza da coprire la domanda di tutti i prodotti e il mo-
dello scelto consiglia di scegliere la produzione di A1 e A3 no a coprirne la
domanda, sacricando la produzione di A2.
Nella sezione CONSTRAINTS contenuta la lista dei vincoli compresi
nel modello: vettori di vincoli e vincoli semplici. Nel nostro modello abbiamo
solo un vincolo di tipo semplice chiamato ProdCapacity. Siccome lo slack del
vincolo vale zero risulta che la nostra produzione funziona a pieno regime. I
costi nascosti ci informano a quanto ammonterebbe il mancato guadagno se
ci trovassimo nella necessit di ridurre i limiti dei vincoli di una unit. Dato
che la capacit di produzione espressa in giorni di produzione, la riduzione
dei giorni disponibili per la produzione diminuisce i protti di $21.195 al
giorno.
20
Capitolo 4
Esempi di risoluzione di
problemi classici della
Programmazione Lineare
21
soggetta ai vincoli che ogni persona pu svolgere esattamente un lavoro:
X
xij = 1 j = 1 .. N
i
TITLE
Problema_di_Assegnamento;
INDEX
persone = (Bianchi, Verdi, Rossi, Ferrari);
incarichi = (lavoroA, lavoroB, lavoroC, lavoroD);
DATA
! tempo impiegato dalla persona j a svolgere il lavoro i
tempi[persone, incarichi] = ( 12, 15, 9, 5,
13, 16, 11, 6,
6, 8, 5, 3,
5, 7, 4, 3 );
DECISION
x[incarichi, persone] ! persona che svolge lincarico
MODEL
MIN tempoTotale = Sum(persone, incarichi: tempi * x);
SUBJECT TO
vincolo_incarichi[persone] : Sum(incarichi: x) = 1;
vincolo_persone[incarichi] : Sum(persone: x) = 1;
BINARY
x[persone, incarichi];
END
22
lavoro B ==> Ferrari
lavoro C ==> Bianchi
lavoro D ==> Verdi
Verona 10 Genova 20
Perugia 12 Venezia 15
Roma 20 Ancona 25
Pescara 24 Napoli 33
Taranto 18 Bari 21
Lamezia 40
23
e che ogni porto di distinazione deve soddisfare la propria richiesta:
X
xij richj j = 1 .. 5
i
TITLE
Problema_di_Trasporto;
INDEX
magazzini = ( Verona, Perugia, Roma, Pescara, Taranto, Lamezia );
porti = ( Genova, Venezia, Ancona, Napoli, Bari );
DATA
disponibilita[magazzini] = ( 10, 12, 20, 24, 18, 40 );
richiesta[porti] = ( 20, 15, 25, 33, 21 );
DECISION
! numero di containter spediti dal magazzino i al porto j
x[magazzini, porti]
MODEL
! funzione obiettivo
MIN costoTotale = Sum(magazzini, porti: distanze * x * costo_unitario);
SUBJECT TO
vincolo_disponibilita[magazzini] : Sum(porti: x) <= disponibilita;
vincolo_richiesta[porti] : Sum(magazzini: x) >= richiesta;
INTEGER
x[magazzini, porti];
END
24
{ Datafile per TRASPORTI.MPL }
Nutrimento requisito
Calorie 200 cal
Proteine 50g
Calcio 700 mg
25
Dalle tabelle dietetiche si ricavano i seguenti contenuti di calorie, proteine
e calcio per ogni singola porzione di ciascun alimento.
TITLE
Dieta_ottima
INDEX
nutrimenti = (Calorie,Proteine,Calcio) : 10
DATA
richieste[nutrimenti] = ( 2000 ! Calorie []
50 ! Proteine [grammi]
700) ; ! Calcio [milligrammi]
costo[alimenti] = ( 2 ! Pane
3 ! Latte
4 ! Uova
26
19 ! Carne
20 ) ; ! Dolce
apporto[alimenti,nutrimenti] = DATAFILE(nutrimen.dat)
! Contenuti di nutrimenti nei diversi alimenti
DECISION
x[alimenti] -> "" ! porzioni di ogni alimento
MODEL
SUBJECT TO
BOUNDS
END
Segue il le Nutrimen.dat.
Pane 110 4 2
Latte 160 8 285
Uova 180 13 54
Carne 260 14 80
27
Dolce 420 4 22
Alimento quantit
Pane 4
Latte 8
Uova 1.5556
Carne 0
Dolce 0
INTEGER
x; ! variabili intere
28
Sapendo che i costi orari e la disponibilit di ogni macchina :
{ Produz.mpl }
{ Mix ottimale della produzione }
TITLE
Opt_Mix__Produzione;
INDEX
prodotto := (PVC1, PVC2, PVC3, Gomma1, Gomma2);
29
macchina := (macPVC, macGomma, Taglio, Pallets, Avvolgi);
DATA
Costo_mat[prodotto] = ( 30 ! PVC1 (in lire)
45 ! PVC2
20 ! PVC3
10 ! GOMMA1
25 ) ; ! GOMMA2
tempo[macchina,prodotto] = DATAFILE(mixprod.dat)
! tempi di ciascuna machina per ottenere ununita di prodotto
DECISION
x[prodotto] -> "" ! quantita di prodotti che conviene produrre
MACRO
Ricavi := SUM(prodotto: Ricavo * x - Costo_mat * x);
MODEL
SUBJECT TO
30
N[macchina] -> "" : SUM(prodotto: tempo * x) < Offerta[macchina];
END
Segue il le mixprod.dat .
macPVC 2 1 1 0 0
macGomma 0 0 0 3 4
Taglio 1 3 1 1 0.5
Pallets 0.5 1 1 0 0
Avvolgi 0 0 0 0.2 0.1
Prodotto quantit
PVC1 105.750
PVC2 110.250
PVC3 0
Gomma1 81.000
Gomma2 0
31
Capitolo 5
Un Modello di
Pianicazione della
Produzione a Multi-Periodo
32
5.1 Formulazione del Modello
Il listato seguente la formulazione del modello di Planning4. Come si
pu osservare il modello unestensione di quello presentato nel capitolo 3
a pag. 16.
{ Planning4.mpl }
TITLE
Production_Planning4;
INDEX
product := (A1, A2, A3);
month := (Jan, Feb, Mar, Apr);
DATA
Price[product] := (120.00, 100.00, 115.00);
Demand[product, month] := (4300, 4200, 6400, 5300,
4500, 5400, 6500, 7200,
5400, 6700, 7800, 8200);
ProdCost[product] := (73.30, 52.90, 65.40);
ProdRate[product] := (500, 450, 550);
ProdDaysAvail[month] := (23, 20, 23, 22);
InvtCost[product] := (3.50, 4.00, 3.00);
InvtCapacity := 800;
VARIABLES
Produce[product, month] -> Prod;
Inventory[product, month] -> Invt;
Sales[product, month] -> Sale;
MACROS
TotalRevenue := SUM(product, month: Price * Sales);
TotalProdCost := SUM(product, month: ProdCost * Produce);
TotalInvtCost := SUM(product, month: InvtCost * Inventory);
TotalCost := TotalProdCost + TotalInvtCost;
MODEL
SUBJECT TO
ProdCapacity[month] -> PCap:
SUM(product: Produce / ProdRate) <= ProdDaysAvail;
33
InvtBal[product, month] -> IBal:
Produce + Inventory[month-1] = Sales + Inventory;
BOUNDS
Sales <= Demand;
END
MODEL STATISTICS
Filename: Planning4.mpl
Date: July 8, 2000
Time: 20:13
Parsing time: 0.22 sec
34
Constraints: 20
Variables: 36
Nonzeros: 69
Density: 10 %
SOLUTION RESULT
MACROS
DECISION VARIABLES
VARIABLE Produce[product,month] :
35
A2 Feb 0.0000 -3.6667
A2 Mar 0.0000 -4.7889
A2 Apr 0.0000 -0.7889
A3 Jan 5720.0000 0.0000
A3 Feb 6380.0000 0.0000
A3 Mar 7800.0000 0.0000
A3 Apr 8200.0000 0.0000
----------------------------------------------------
VARIABLE Inventory[product,month] :
VARIABLE Sales[product,month] :
36
A3 Feb 6700.0000 8.0636
A3 Mar 7800.0000 7.1455
A3 Apr 8200.0000 7.1455
----------------------------------------------------
CONSTRAINTS
CONSTRAINT ProdCapacity[month] :
CONSTRAINT InvtBal[product,month] :
37
CONSTRAINT MaxInventory[month] :
END
38
Capitolo 6
Un Modello di
Pianicazione con pi
Impianti di Produzione
Costi di Produzione A1 A2 A3
impianto 1 73.30 52.90 65.40
impianto 2 79.00 52.00 66.80
impianto 3 75.80 52.10 50.90
impianto 4 82.70 63.30 53.80
39
Quota di Produzione A1 A2 A3
impianto 1 500 450 450
impianto 2 550 450 300
impianto 3 450 350 300
impianto 4 550 400 350
{ Planning5.mpl }
TITLE
Production_Planning5;
INDEX
product := (A1, A2, A3);
month := (Jan, Feb, Mar, Apr);
plant := (p1, p2, p3, p4);
DATA
Price[product] := (120.00, 100.00, 115.00);
Demand[product, month] := DATAFILE("Demand.dat");
ProdCost[plant, product] := DATAFILE("ProdCost.dat");
ProdRate[plant, product] := DATAFILE("ProdRate.dat");
ProdDaysAvail[month] := (23, 20, 23, 22);
InvtCost[product] := (3.50, 4.00, 3.00);
InvtCapacity := 800;
VARIABLES
Produce[plant, product, month] -> Prod;
Inventory[product, month] -> Invt;
Sales[product, month] -> Sale;
MACROS
TotalRevenue := SUM(product, month: Price * Sales);
TotalProdCost := SUM(plant, product, month: ProdCost * Produce);
TotalInvtCost := SUM(product, month: InvtCost * Inventory);
TotalCost := TotalProdCost + TotalInvtCost;
MODEL
40
SUBJECT TO
ProdCapacity[plant, month] -> PCap:
SUM(product: Produce / ProdRate) <= ProdDaysAvail;
BOUNDS
Sales <= Demand;
END
1. Nel men Options scegliere Solution File per aprire la nestra di dia-
logo (Options Dialog Box).
41
Dato che il modello su cui stiamo lavorando sta diventando piuttosto
grande ci occuperemo solo di guardare determinate parti della soluzione
invece che la soluzione completa. A questo punto, useremo lalbero delle
denizioni del modello per visualizzare solo le parti della soluzione alle quali
siamo interessati.
La nestra delle denizioni del modello (Model Denitions Windows) ci
permette di vedere tutte le istanze denite nella formulazione del modello in
una struttura ad albero dove ad ogni ramo corrisponde una sezione del mo-
dello. Nelluso di MPL normalmente una buona idea lasciare la nestra
con lalbero delle denizioni sempre visibile. MPL provvede allaggiorna-
mento automatico del contenuto della nestra delle denizioni ogni volta
che risolviamo un modello. Per visualizzare la nestra delle denizioni del
modello scegliamo Model Denitions nel men View.
Nella nestra con lalbero delle denizioni possiamo selezionare una qual-
siasi delle istanze denite nel modello per osservarne i valori. Per esem-
pio, per vedere il valore della variabile Produce basta un doppio click sulla
scritta Produce nellalbero, oppure, alternativamente, selezionando la scrit-
ta e premendo il tasto View. Questa operazione visualizzer in una nestra
contenente solo i valori della variabile Produce.
VARIABLE Produce[plant,product,month] :
42
Torniamo ora alla nestra con lalbero delle denizioni per visualizzare
una nestra contenente i vincoli ProdCapacity; avremo i seguenti valori per
la soluzione:
CONSTRAINT ProdCapacity[plant,month] :
Questi dati suggeriscono una grossa inefficienza di tutti gli impianti nei
vari mesi dovuto ai vincoli di capacit di produzione. Questo pu essere
interpretato con il fatto che possiamo produrre molto di pi di quello che
produciamo, ma non necessario dato che abbiamo gi soddisfatto tutta
la domanda. Dato che lunit di misura della capacit di produzione in
giorni di produzione, i valori di slack rappresentano quanti giorni al mese gli
impianti possono fermare la produzione.
43
Capitolo 7
Modelli di Trasporto
Si tratta di modelli nei quali sono previsti dei viaggi tra varie localit,
spesso tali modelli sono detti di trasporto o di distribuzione. Tipicamente,
in un modello del trasporto, si dispone di centri sorgente con determinate
disponibilit (risorse) e di destinazioni con determinate richieste, quindi si
ha la necessit di far viaggiare i prodotti dalle sorgenti alle destinazioni.
In alcuni casi si trattano modelli del trasporto a pi livelli. Per esempio, si
deve trasportare dagli impianti ai depositi e, successivamente, dai depositi ai
centri di vendita. Unaltro gruppo di modelli di distribuzione sono i modelli
di distribuzione (Transhipment Models). Questo tipo di modelli si adattano a
casi nei quali si hanno diversi centri nei quali sussiste sia la produzione che la
vendita. Quindi non ci sono degli specici centri di risorse e di destinazione,
si pu trasportare i prodotti tra tutti i centri.
VARIABLES
Ship[fromplant,toplant]
WHERE(fromplant<>toplant);
44
nazione. In alcuni casi le condizioni decisionali non sono basate sul valore
dellindice. Queste condizioni possono essere determinate dai vettori di dati
del modello. Tipicamente, si ha un vettore assegnato che contiene i costi
di trasporto tra gli impianti. Se il trasporto tra due impianti non pos-
sibile, si pu assegnare a questo trasporto un valore speciale, come zero, e
usarlo per identicarlo. Quindi, possiamo usare i valori dei vettori di dati
nella denizione delle variabili per escludere i percorsi che non hanno senso.
Riportiamo un esempio:
VARIABLES
Ship[fromplant,toplant]
WHERE(ShipCost[fromplant,toplant]>0);
PlantBal[plant,product,month]
Produce+Inventory[month-1] +
SUM(fromplant: Ship[fromplant,toplant:=plant])
=
Sales + Inventory +
SUM(fromplant: Ship[fromplant:=plant,toplant]);
45
7.3 Un Modello di trasporto tra impianti di pro-
duzione
In questa sezione dovremo creare un nuovo modello dove ogni impianto
ha una sua domanda interna di prodotti e, inoltre, dispone di un magaz-
zino. Useremo il modello creato nella precedente sezione con le opportune
modiche. Dato che ogni impianto pu vendere i prodotti, ma adesso la
domanda differenziata in ogni impianto, per ogni prodotto e per ogni
mese. Riportiamo qui di seguito la tabella con i dati della domanda:
Impianto Prodotto Gen Feb Mar Apr
A1 4300 4200 6400 5300
p1 A2 4500 5400 6500 7200
A3 5400 6700 7800 8200
A1 5100 6200 5400 7600
p2 A2 6300 7100 5200 6300
A3 4800 6500 5000 7200
A1 4100 6100 4700 5800
p3 A2 5300 5200 5700 4100
A3 4200 4100 5200 6300
A1 4300 4100 5300 4500
p4 A2 5300 6400 4200 6200
A3 5600 5200 3800 4100
Questi dati sono in tre dimensioni: impianti, prodotti e mesi. Nei modelli
di programmazione lineare abbastanza tipico avere dati multidimensiona-
li, a volte anche di dimensione maggiore di otto. Nella prossima sezione
aumenteremo ancora la dimensione dei dati includendo unaltra dimensio-
ne; inseriremo la dimensione dei macchinari creando un vettore a quattro
dimensioni.
La capacit del magazzino ora diversicata tra i vari impianti. Abbia-
mo quattro valori, uno per ogni impianto: 800, 400, 500 e 400. Inoltre, dato
che abbiamo diversi impianti, ognuno con il suo magazzino, avremo dei costi
diversi per ogni magazzino per ogni impianto e per ogni prodotto. I costi
del magazzino sono riportati nella seguente tabella:
Inne, dato che permettiamo il trasporto tra gli impianti dei prodotti, abbia-
mo dei costi legati a questo trasporto; la tabella seguente riporta il riassunto
dei costi di trasporto:
46
Costi di trasporto p1 p2 p3 p4
p1 - $15.00 $21.00 $13.00
p2 $16.00 - $12.00 $12.00
p3 $14.00 $17.00 - $15.00
p4 $21.00 $13.00 $10.00 -
Si noti come non sia associato nessun costo quando limpianto di partenza
uguale a quello di destinazione.
{ Planning6.mpl }
TITLE
Production_Planning6;
INDEX
product := (A1, A2, A3);
month := (Jan, Feb, Mar, Apr);
plant := (p1, p2, p3, p4);
toplant := plant;
fromplant := plant;
DATA
Price[product] := (120.00, 100.00, 115.00);
Demand[plant,product,month] := DATAFILE("Demand6.dat");
ProdCost[plant,product] := DATAFILE("ProdCost.dat");
ProdRate[plant,product] := DATAFILE("ProdRate.dat");
ProdDaysAvail[month] := (23, 20, 23, 22);
InvtCost[plant,product] := DATAFILE("InvtCost.dat");
InvtCapacity[plant] := (800, 400, 500, 400);
ShipCost[fromplant,toplant] := DATAFILE("ShipCost.dat");
VARIABLES
Produce[plant,product,month] -> Prod;
Inventory[plant, product,month] -> Invt;
Sales[plant, product, month] -> Sale;
Ship[product, month, fromplant, toplant]
WHERE (fromplant <> toplant);
47
MACROS
TotalRevenue := SUM(plant, product, month: Price * Sales);
TotalProdCost := SUM(plant, product, month: ProdCost * Produce);
TotalInvtCost := SUM(plant, product, month: InvtCost * Inventory);
TotalShipCost := SUM(product, month, fromplant, toplant: ShipCost * Ship);
TotalCost := TotalProdCost + TotalInvtCost + TotalShipCost;
MODEL
SUBJECT TO
ProdCapacity[plant, month] -> PCap:
SUM(product: Produce / ProdRate) <= ProdDaysAvail;
BOUNDS
Sales <= Demand;
END
48
il tasto View. Questo mostrer una nestra contenente solo i valori della
variabile Produce.
VARIABLE Produce[plant,product,month] :
plant product month Activity Reduced Cost
-----------------------------------------------------------
p1 A1 Jan 4300.0000 0.0000
p1 A1 Feb 4200.0000 0.0000
p1 A1 Mar 6400.0000 0.0000
p1 A1 Apr 5300.0000 0.0000
p1 A2 Jan 1080.0000 0.0000
p1 A3 Jan 5400.0000 0.0000
p1 A3 Feb 5220.0000 0.0000
p1 A3 Mar 4590.0000 0.0000
p1 A3 Apr 5130.0000 0.0000
p2 A1 Jan 5100.0000 0.0000
p2 A1 Feb 6200.0000 0.0000
p2 A1 Mar 5400.0000 0.0000
p2 A1 Apr 7600.0000 0.0000
p2 A2 Jan 6177.2727 0.0000
p2 A2 Feb 3927.2727 0.0000
p2 A2 Mar 5931.8182 0.0000
p2 A2 Apr 3681.8182 0.0000
p3 A1 Jan 4100.0000 0.0000
p3 A1 Feb 6100.0000 0.0000
p3 A1 Mar 4700.0000 0.0000
p3 A1 Apr 5800.0000 0.0000
p3 A3 Jan 4166.6667 0.0000
p3 A3 Feb 1933.3333 0.0000
p3 A3 Mar 3766.6667 0.0000
p3 A3 Apr 2733.3333 0.0000
p4 A1 Jan 3850.0000 0.0000
p4 A1 Feb 2828.5714 0.0000
p4 A1 Mar 5300.0000 0.0000
p4 A1 Apr 4500.0000 0.0000
p4 A3 Jan 5600.0000 0.0000
p4 A3 Feb 5200.0000 0.0000
p4 A3 Mar 4677.2727 0.0000
p4 A3 Apr 4836.3636 0.0000
-----------------------------------------------------------
49
spedizione. Per esempio, A1 prodotto negli impianti p1, p2 e p3, ma non
nellimpianto p4; A2 prodotto in p1 e p2, A3 prodotto in p1, p2 e p4.
Se ritorniamo nella nestra con lalbero e apriamo una nestra con la
variabile Ship avremo i seguenti valori per la soluzione:
VARIABLE Ship[product,month,fromplant,toplant] :
50
Capitolo 8
Un Modello con Pi
Macchinari
51
elementi non necessari; ad esempio: impianto p1, macchina m11 e prodotto
A3.
{ Planning7.mpl }
TITLE
Production_Planning7;
INDEX
product := (A1, A2, A3);
month := (Jan, Feb, Mar, Apr);
plant := (p1, p2, p3, p4);
toplant := plant;
fromplant := plant;
machine := (m11, m12, m13, m21, m22, m31, m32, m41);
DATA
Price[product] := (120.00, 100.00, 115.00);
Demand[plant, product, month] := DATAFILE("Demand6.dat");
ProdCost[plant, machine, product] := SPARSEFILE("Produce.dat", 4);
ProdRate[plant, machine, product] := SPARSEFILE("Produce.dat", 5);
ProdDaysAvail[month] := (23, 20, 23, 22);
InvtCost[plant, product] := DATAFILE("InvtCost.dat");
InvtCapacity[plant] := (800, 400, 500, 400);
ShipCost[fromplant, toplant] := DATAFILE("ShipCost.dat");
VARIABLES
Produce[plant, machine, product, month] -> Prod
WHERE (ProdCost > 0);
Inventory[plant, product, month] -> Invt;
Sales[plant, product, month] -> Sale;
Ship[product, month, fromplant, toplant]
WHERE (fromplant <> toplant);
MACROS
TotalRevenue := SUM(plant, product, month: Price * Sales);
TotalProdCost := SUM(plant, machine, product, month: ProdCost * Produce);
TotalInvtCost := SUM(plant, product, month: InvtCost * Inventory);
TotalShipCost := SUM(product, month, fromplant, toplant: ShipCost * Ship);
52
TotalCost := TotalProdCost + TotalInvtCost + TotalShipCost;
MODEL
SUBJECT TO
ProdCapacity[plant, machine, month] -> PCap:
SUM(product: Produce / ProdRate) <= ProdDaysAvail;
BOUNDS
Sales <= Demand;
END
VARIABLE Produce[plant,machine,product,month] :
53
plant machine product month Activity Reduced Cost
--------------------------------------------------------------------
p1 m11 A1 Jan 4300.0000 0.0000
p1 m11 A1 Feb 4200.0000 0.0000
p1 m11 A1 Mar 5487.5000 0.0000
p1 m11 A1 Apr 5300.0000 0.0000
p1 m11 A2 Jan 6480.0000 0.0000
p1 m11 A2 Feb 5220.0000 0.0000
p1 m11 A2 Mar 5411.2500 0.0000
p1 m11 A2 Apr 5130.0000 0.0000
p1 m12 A3 Feb 9049.3506 0.0000
p1 m12 A3 Mar 916.1616 0.0000
p1 m12 A3 Apr 10803.1169 0.0000
p1 m13 A3 Jan 8050.0000 0.0000
p1 m13 A3 Feb 7000.0000 0.0000
p1 m13 A3 Mar 8050.0000 0.0000
p1 m13 A3 Apr 7700.0000 0.0000
p2 m21 A1 Jan 5100.0000 0.0000
p2 m21 A1 Feb 6200.0000 0.0000
p2 m21 A1 Mar 6538.8889 0.0000
p2 m21 A1 Apr 7600.0000 0.0000
p2 m21 A3 Jan 4422.6136 0.0000
p2 m21 A3 Feb 3927.2727 0.0000
p2 m21 A3 Mar 5000.0000 0.0000
p2 m21 A3 Apr 3681.8182 0.0000
p2 m22 A2 Jan 6900.0000 0.0000
p2 m22 A2 Feb 6000.0000 0.0000
p2 m22 A2 Mar 6900.0000 0.0000
p2 m22 A2 Apr 6600.0000 0.0000
p3 m31 A1 Jan 3300.0000 0.0000
p3 m31 A1 Feb 5964.9351 0.0000
p3 m31 A1 Mar 2550.0000 0.0000
p3 m31 A1 Apr 4477.4026 0.0000
p3 m31 A3 Jan 4700.0000 0.0000
p3 m31 A3 Feb 2023.3766 0.0000
p3 m31 A3 Mar 5200.0000 0.0000
p3 m31 A3 Apr 3615.0649 0.0000
p3 m32 A1 Jan 800.0000 0.0000
p3 m32 A1 Feb 135.0649 0.0000
p3 m32 A1 Mar 2150.0000 0.0000
p3 m32 A1 Apr 1322.5974 0.0000
p3 m32 A2 Jan 7350.0000 0.0000
p3 m32 A2 Feb 6881.8182 0.0000
p3 m32 A2 Mar 6168.7500 0.0000
54
p3 m32 A2 Apr 6542.7273 0.0000
p4 m41 A1 Jan 4300.0000 0.0000
p4 m41 A1 Feb 4100.0000 0.0000
p4 m41 A1 Mar 5073.6111 0.0000
p4 m41 A1 Apr 4500.0000 0.0000
p4 m41 A2 Jan 2270.0000 0.0000
p4 m41 A2 Feb 5018.1818 0.0000
p4 m41 A2 Mar 2500.0000 0.0000
p4 m41 A2 Apr 5527.2727 0.0000
p4 m41 A3 Jan 3327.3864 0.0000
p4 m41 A3 Mar 2633.8384 0.0000
--------------------------------------------------------------------
La variabile Produce ora denita su quattro indici: impianto, macchinario,
prodotto e mese. Per ogni impianto il modello ha deciso quali macchinari so-
no pi efficienti per produrre un prodotto in un particolare impianto. Questa
tabella potr essere usata come per programmare la produzione dellintera
azienda.
Unaltra variabile interessante in questo modello Inventory (magazzi-
no). Se ritorniamo nellalbero delle denizioni e apriamo una nuova nestra
con i valori della soluzione per la variabile Inventory visualizzeremo i seguenti
valori:
VARIABLE Inventory[plant,product,month] :
CONSTRAINT ProdCapacity[plant,machine,month] :
55
p1 m12 Feb 3.5466 0.0000
p1 m12 Mar 21.3343 0.0000
p1 m12 Apr 2.3580 0.0000
p2 m21 Jan 3.8992 0.0000
-----------------------------------------------------------
56