Sei sulla pagina 1di 60

Appunti sul linguaggio di

programmazione MPL

Lorenzo Brunetta1, Michele DAmico2 e Ivan Luzzi3

Milano, Agosto 2000

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

2 Programmazione con il linguaggio MPL 3


2.1 Scrivere e risolvere un Modello con MPL . . . . . . . . . . . 3
2.1.1 La Prima Sessione in MPL . . . . . . . . . . . . . . . 3
2.1.2 Utilizzare il Sistema di Aiuto in MPL . . . . . . . . . 6
2.2 Caratteristiche generali . . . . . . . . . . . . . . . . . . . . . 6
2.3 Struttura di un programma MPL . . . . . . . . . . . . . . . 8
2.3.1 TITLE . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.3.2 INDEX . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.3.3 DATA . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.3.4 DECISION . . . . . . . . . . . . . . . . . . . . . . . . 11
2.3.5 MACROS . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.3.6 MODEL . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.3.7 SUBJECT TO . . . . . . . . . . . . . . . . . . . . . . 13
2.3.8 BOUNDS . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.3.9 FREE . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.3.10 INTEGER e BINARY . . . . . . . . . . . . . . . . . 15

3 Un modello di bilanciamento della produzione 16


3.1 Formulazione del Modello . . . . . . . . . . . . . . . . . . . . 16
3.2 Vedere e Analizzare la Soluzione . . . . . . . . . . . . . . . . 17

4 Esempi di risoluzione di problemi classici della Programma-


zione Lineare 21
4.1 Un problema di assegnamento . . . . . . . . . . . . . . . . . . 21
4.2 Un primo problema dei trasporti . . . . . . . . . . . . . . . . 23
4.3 Un problema della dieta . . . . . . . . . . . . . . . . . . . . . 25
4.4 Un problema di produzione pi complesso . . . . . . . . . . . 28

5 Un Modello di Pianicazione della Produzione a Multi-Pe-


riodo 32
5.1 Formulazione del Modello . . . . . . . . . . . . . . . . . . . . 33
5.2 Risolvere il Modello e Analizzare la Soluzione . . . . . . . . . 34

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

8 Un Modello con Pi Macchinari 51


8.1 Formulazione del Modello . . . . . . . . . . . . . . . . . . . . 52
8.2 Risolvere il Modello e Analizzare la Soluzione . . . . . . . . . 53

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

Ai sostanziali progressi ottenuti nella programmazione matematica dagli an-


ni 50 agli anni 70 non corrisposto un adeguato utilizzo applicativo degli
stumenti matematici sviluppati. Questo dovuto, in gran parte, alle diffi-
colt computazionali ed informatiche insite nella stesura del modello, nella
raccolta ed organizzazione dei dati, nella programmazione degli algoritmi
solutori e nellanalisi dei risultati ottenuti. Quindi, gli sforzi ottenuti in
campo matematico, risultavano inutilizzabili a livello applicativo poich lef-
fettivo incremento nella velocit e potenza dei solutori si scontrava con la
necessit di creare software che interrogasse questi solutori e che gestisse
modelli e dati appartenenti al modo reale. MPL (e in generale i programmi
detti generatori algebrici di modelli) nasce proprio per ovviare a questa
difficolt e si pongono come obiettivi:

 fornire un linguaggio di programmazione ad alto livello che permetta


di descrivere in modo semplice modelli reali anche molto complessi;

 creare modelli indipendenti dal solutore utilizzato, in modo da poter


sfruttare sempre i solutori pi potenti presenti sul mercato;

 descrivere modelli nei quali la struttura logica del problema e i dati


utilizzati possano essere considerati come entit diverse.

Uno schema formale per la situazione descritta pu essere il seguente:


utente programma (es.MPL) solutore (es.CP LEX )

dati

database
Utilizzando MPL lutente non deve pi occuparsi direttamente dellinter-
rogazione del solutore, ma pu concentrarsi sulla stesura del modello pro-
grammando in un linguaggio di alto livello con il quale pu descrivere molto

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:

 il linguaggio di programmazione utilizzato semplice da imparare (


composto da poche parole chiave);

 i codici che si realizzano sono essi stessi una rappresentazione concisa


ed elegante del modello;

 possibile inserire commenti o denizioni linguistiche che rendono


sia linput che loutput comprensibili anche da non-programmatori;

 la maggior parte dei programmi creati sta in un unico documento il


che facilita il controllo e la creazione dei modelli;

 nelloutput vengono rappresentate, in modo comprensibile, tutte le


operazioni svolte dal solutore;

 i programmi vengono scritti con un semplice editor di testo e sono


indipendenti dalla piattaforma sulla quale vengono eseguiti sia il pro-
gramma, sia il solutore (anche se Windows la piattaforma su cui
pi usato);

 MPL ha circa 5 anni possiede una piccola libreria di esempi di modelli


che comprende sia problemi lineari, che problemi non lineari, e un
tutorial.

2
Capitolo 2

Programmazione con il
linguaggio MPL

MPL lacronimo di Model Development Environment, cio Ambiente


di Sviluppo di Modelli; si tratta di un linguaggio di programmazione ad alto
livello che permette di descrivere in modo semplice e intuitivo dei modelli di
Programmazione Lineare.
Si possono denire modelli specici con dati assegnati, oppure modelli
pi generali, che vengono associati di volta in volta con i dati letti da un le
esterno.
In questo capitolo, dopo una prima introduzione generale, verranno
analizzate le diverse sezione che compongono un programma MPL.

2.1 Scrivere e risolvere un Modello con MPL


In questa sezione impareremo, attraverso una serie di passi elementari,
come scrivere e risolvere un modello con MPL. Alla ne della sezione,
saremo in grado di far partire MPL, caricare e risolvere il modello, vedere la
soluzione. A questo punto, impareremo come si possano cambiare le opzioni
di settaggio di MPL attraverso le nestre di dialogo. Inoltre, nellultima
parte di questa sezione, forniremo una breve descrizione del sistema di aiuto
di MPL.

2.1.1 La Prima Sessione in MPL


Ci sono quattro semplici passi che devono diventarci familiari se inten-
diamo risolvere modelli usando MPL:

Eseguire lapplicazione MPL. Eseguire MPL in Windows 95 molto


semplice. Quando abbiamo installato MPL, il programma di installazione
ha creato una voce in Programmi nel men di Avvio dal nome Mpl for

3
Windows. Per eseguire MPL, se non lo abbiamo ancora fatto, sufficiente
cliccare sul men Avvio e selezionare Programmi Mpl for Windows

Caricare il le del modello nellambiente MPL. Dopo che si avviato


MPL e ci si trova nellambiente di sviluppo di modelli, il prossimo passo
quello di caricare il le del modello nelleditor di modelli. Lapplicazione
MPL viene fornita con diversi modelli di esempio che sono collocati nella
cartella (directory) Mplwin4. I les con i modelli di MPL sono registrati
come dei le di testo standard e, tipicamente, hanno lestensione .mpl.
Il modello che useremo in questa sezione si chiama Model1.mpl e si trova,
insieme a tutti i modelli utilizzati in questo tutorial, in una cartella separata
dal nome Tutorial.

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.

3. La nestra di dialogo Open ora mostrer una lista di les di modelli


MPL che sono conservati nella cartella Tutorial. Clicchiamo sul le
dal nome Model1.mpl per selezionarlo e premete il tasto Open per
aprire il le. Alternativamente, possiamo aprirlo semplicemente con
un doppio click sul le stesso nella lista.

Queste semplici operazioni ci permetteranno di aprire una nuova nestra di


editor dei modelli che contiene la formulazione del modello.

Risolvere il modello. In questo tutorial usiamo CPLEX300 come ri-


solutore (solver); ma, se siamo in possesso di altri risolutori supportati da
MPL, possiamo usarli.
Quando eseguiamo MPL per la prima volta dopo averlo installato, MPL
prover automaticamente a localizzare tutti i risolutori che abbiamo a di-
sposizione. Potremo controllare quali risolutori sono stati trovati da MPL
andando nel men Run. Ogni risolutore trovato verr indicizato nel men
preceduto dalla parola Solve.
Se non disponiamo di nessun risolutore verr visualizzato No Solvers nel
men Run. In questo caso, possiamo consultare il Capitolo 2.4: Setting
up Solvers for MPL per trovare le informazioni su come aggiungere riso-
lutori a MPL. D ora in poi assumeremo che CPLEX sia stato installato
con successo, oppure che qualsiasi altro risolutore sia stato correttamente
installato.
Il prossimo passo sar quello di risolvere il modello che stato caricato
nelleditor di modelli. Per risolvere il modello basta seguire i seguenti passi:

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.

La Status Window fornisce informazioni come il numero di linee lette,


il numero delle variabi e dei vincoli del modello, quanta memoria stata
usata. Mentre lottimizatore risolve il modello, vengono inoltre mostrati il
numero delle iterazioni e il valore corrente della funzione obbiettivo.

Vedere la soluzione. MPL registra automaticamente la soluzione in un


le con lo stesso nome del le del modello, ma con lestensione .sol. Usiamo
i seguenti passi per visualizzare il le di soluzione Model1.sol che stato
generato per il modello che abbiamo gi risolto.

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.

2. Possiamo scorrere il le della soluzione semplicemente utilizzando le


barre di scorrimento posizionate sulla destra. Notiamo che i detta-
gli della soluzione includono il valore ottimale della soluzione per la
funzione obbiettivo, i valori delle variabili decisionali e dei vincoli.

3. Quando abbiamo nito di vedere il le di soluzione, possiamo chiudere


la nestra semplicemente premendo il tasto (X) che si trova nellangolo
in alto a destra della nestra stessa.

Usare la nestra dellalbero delle denizioni del modello (Model


Denition Window). MPL ci permette inoltre di vedere tutti gli oggetti
deniti nella formulazione del modello in una nestra con una struttura ad
albero chiamata Model Denitions Windows. Ogni ramo corrisponde ad una
sezione del modello.
Se la nestra non visibile, possiamo aprirla scegliendo Model Deni-
tions nel men View. Normalmente una buona idea lavorare con MPL
mantenendo la Model Denitions Windows sempre aperta. MPL provvede-
r automaticamente a mantenere aggiornato il contenuto di questa nestra
tutte le volte che risolveremo i vostro modello.
La Model Denitions Windows provvede ad un facile accesso a differenti
parti del modello e ci permette di selezionare e vedere velocemente le parti
della soluzione del modello che ci interessano. Per utilizzare lalbero basta
eseguire:

1. Accertiamoci che la nestra con lalbero sia aperta scegliendo Model


Denitions dal men View.

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.

3. Ora selezioniamo la variabile Produce e premiamo il tasto View che si


trova sul fondo della nestra. Verr aperta una nuova View Window
con il valore della soluzione per la sola variabile Produce.

2.1.2 Utilizzare il Sistema di Aiuto in MPL


MPL offre agli utenti un sistema di aiuto che contiene informazioni utili
su come usare questo software.

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.

 Il bottone Contents mostra tutti gli argomenti disponibili in una strut-


tura ad albero.

 Il bottone Index ci permette di accedere alla lista di tutte le parole


chiave contenute nel le di aiuto, oppure ci permette di eseguire delle
ricerche per speciche parole chiave.

 Il bottone Find ci permette di ricercare negli argomenti di aiuto parole


speciche o frasi nel testo. Il database di ricerca viene costruito au-
tomaticamente dal Find Setup Wizard la prima volta che selezionate
Find.

2.2 Caratteristiche generali


Vengono qui spiegate alcune caratterisctiche generali del linguaggio MPL.

Lunghezza delle righe


Ogni riga non pu superare i 255 caratteri. I rimanenti verranno ignorati
da MPL.

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...
}

il punto esclamativo ! delimita invece linizio di un commento che


termina a ne riga

x[foods] ! dollars of food to be purchased daily

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:

[indice = min .. max]


[indice > val]

oppure selezionare un singolo indice di valore specicato

["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:

Cost = SUM(foods: x);

2.3 Struttura di un programma MPL


La struttura di un le MPL divisa in due parti fondamentali, ognuna
delle quali a sua volta suddivisa in diverse sezioni.
La prima parte di denizione e comprende:

TITLE - Il nome del modello


INDEX - Gli indici del problema
DATA - I dati (scalari, vettori e matrici multidimensionali)
DECISION - Le variabili del problema
MACRO - Macro riutilizzabili nelle varie espressioni

La seconda parte invece descrive il modello ed formata dalle seguenti


sezioni:

MODEL - Descrizione del problema


MAX o MIN - Funzione obiettivo
SUBJECT TO - Vincoli
BOUNDS - Estremi superiori ed inferiori delle variabili
FREE - Variabili libere
INTEGER - Variabili intere
BINARY - Variabili binarie (0/1)
END - Fine del modello

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.

day := (mon, tue, wed, thu, fri, sat, sun) CIRCULAR;


month := 1..12 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:

holiday[day] := (sat, sun);


summer[month] := (7..9);

dove tra parentesi quadre viene specicato linsieme di origine.


Si possono anche eseguire le normali operazioni sugli insiemi:

 Differenza con il simbolo: -

 Negazione con il simbolo: NOT

 Unione con uno dei simboli: +, OR, UNION

 Intersezione con uno dei simboli: AND, INTERSECTION

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.

product := INDEXFILE("product.dat", 1);

NB: Se i dati sono su un foglio elettronico o un database esterno si pu


accedere anche direttamente ai dati con opportuni comandi.

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?;

In questo caso allutente viene chiesto di confermare o modicare il valore


predenito dello scalare NumberOfYears.

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.

Required[nutrients] = ( 3, 70, 0.8, 12, 5, 2.7, 18, 75 );


A[foods,nutrients] = DATAFILE(nutri.dat)
! Nutritive values of foods per dollar expenditure.

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.

A[i] := (2, -4+3, 2*SQR(3)+2, 1/(2+1), last(i))

Se si utilizzano vettori e matrici sparse, si possono inserire solo i valori


non nulli; basta sostituire alle normali parentesi tonde quelle quadrate e far
precedere ai singoli valori i relativi indici.

A[i] := [2: 4.0, 5: 3.0, 6: -4.0] ;

ProdCost[plant, machine, product] := [


p1, m11, A1, 73.30,
p1, m11, A2, 52.90,
p1, m12, A3, 65.40,
p1, m13, A3, 47.60,

p2, m21, A1, 79.00,


p2, m21, A3, 66.80,
p2, m22, A2, 52.00,

p3, m31, A1, 75.80,


p3, m31, A3, 50.90,
p3, m32, A1, 79.90,
p3, m32, A2, 52.10,

p4, m41, A1, 82.70,


p4, m41, A2, 63.30,
p4, m41, A3, 53.80];

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]

Condizioni sulle variabili


A volte necessario limitare le variabili al vericarsi di determinate con-
dizioni. La clausola WHERE seguita dalla condizione, permette di selezio-
nare solo alcune variabili.

Production[product,month] WHERE (Demand[product,month] > 0);

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.

TotalRevenue := SUM(product,month: price * Sales) ;

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.

MAX 3x1 + 5x2 ;

MIN Cost = SUM(products,months : InventoryCost) ;

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 ;

Limitare i vincoli vettoriali


Si pu limitare il range di un indice per un vincolo vettoriale direttamente
nella denizione stessa del vicnolo.

InventoryBalance[month=Jan..Nov] : ...
InventoryBalance[month<=Jun] : ...
InventoryBalance[month=Dec] : ...

Oppure si pu denire un vincolo al vericarsi di determinate condizioni

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:

limiteinf eriore < variabile < limitesuperiore

Come per i vincoli anche i bounds possono essere semplici o vettoriali


(indicizzati su uno o pi indici).
Il limite inferiore per denizione 0.

x < 4*12 ;
z_bounds : 2 < z < 8 ;
CloseInv : Inventory[December] = 20000 ;

MaxInv[month<=Nov] : Inventory <= 90000 ;


Inventory[month=Dec] = 90000 ;
Sales <= Demand ;

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] ;

2.3.10 INTEGER e BINARY


Allo stesso modo si possono forzare delle variabili ad assumere solamente
valori interi; basta anteporre la porola INTEGER alla lista di variabili e/o
vettori di variabili.

INTEGER
Production[month,product] ;

Si possono anche forzare alcune variabili ad assumere solamente i valori


interi 0 e 1.

BINARY
ShopOpen ;

In entrambi i casi questa forzatura ha effetto soltatno se il pacchetto


risolutore supporta questa caratteristica, ossia risolve problemi MIP (Mixed
Integer Programming).

15
Capitolo 3

Un modello di bilanciamento
della produzione

In questo capitolo costruiremo un modello di produzione con tre prodotti


che verranno chiamati A1, A2 e A3. Per questi prodotti creeremo un indice
e, quindi, deniremo un vettore di variabili che rappresenta la necessit di
produzione di ogni prodotto.
Data la denizione di questi nuovi termini, indici e vettori, ora dovremo
applicarla a un modello di prova. Il modello di bilanciamento della produ-
zione un problema di distribuzione della forza produttiva tra i prodotti,
con lo scopo di determinare il livello di produzione di ogni singolo prodotto
per soddisfare una data domanda.
Il prezzo di vendita di ogni prodotto ssato: $120.00 per A1, $100.00
per A2 e $115.00 per A3. Per ogni prodotto, esiste anche un limite massimo
di domanda: 4300 per A1, 4500 per A2 e 5400 per A3.
La quota di produzione di un prodotto misurata in quanti pezzi vengono
prodotti ogni giorno. In questo problema abbiamo un totale di 22 giorni di
produzione disponibili in un mese. Nella tabella seguente sono indicati la
quota e il costo di produzione di ogni prodotto.

Produzione A1 A2 A3
Costo di Produzione $73.30 $52.90 $65.40
Quota di Produzione 500 450 550

3.1 Formulazione del Modello


Il prossimo passo quello di prendere il problema appena descritto e
formularne un modello per MPL. Qui di seguito riportiamo il codice MPL
del modello (le Planning3.mpl ).

{ 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

MAX Profit = TotalRevenue - TotalCost;

SUBJECT TO
ProdCapacity -> PCap:
SUM(product: Produce / ProdRate) <= ProdDaysAvail;

BOUNDS
Produce <= Demand;

END

3.2 Vedere e Analizzare la Soluzione


Dopo aver risolto il modello, MPL crea automaticamente un le che
contiene in un formato standard vari elementi della soluzione del modello.
Questo le include, tra le altre cose, il valore ottimo della funzione obbiet-
tivo, le attivit dei costi ridotti delle variabili, i valori di slack e i costi
nascosti (shadow price) per i vincoli. Il le della soluzione viene creato
con lo stesso nome del le del modello, ma con lestensione .sol. Nel nostro
caso il le si chiamer Planning3.sol .

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.

MPL Modeling System - Copyright (c) 1988-2000, Maximal Software, Inc.


-------------------------------------------------------------------------------
MODEL STATISTICS

Problem name: Producton_Planning3

Filename: Planning3.mpl
Date: July 8, 2000
Time: 13:53
Parsing time: 0.33 sec

Solver: CPLEX 300


Objective value: 544566.636364
Iterations: 3
Solution time: 0.60 sec

Constraints: 1
Variables: 3
Nonzeros: 3
Density: 100 %

SOLUTION RESULT

Optimal solution found

MAX Profit = 544566.6364

MACROS

Macro Name Values


-----------------------------------------------

18
TotalRevenue 1298181.8182
TotalCost 753615.1818
-----------------------------------------------

DECISION VARIABLES

VARIABLE Produce[product] :

product Activity Reduced Cost


---------------------------------------------
A1 4300.0000 4.3100
A2 1611.8182 0.0000
A3 5400.0000 11.0636
---------------------------------------------

CONSTRAINTS

PLAIN CONSTRAINTS

Constraint Name Slack Shadow Price


------------------------------------------------------
ProdCapacity 0.0000 21195.0000
------------------------------------------------------

END

La prima parte del le della soluzione contiene diversi dati statistici


del modello come il nome del le, la data e lora in cui il modello stato
risolto, quale risolutore stato usato, il valore della funzione obbiettivo
e la dimensione del modello. La parte successiva contiene i risultati della
soluzione. In questa parte possiamo vedere se la soluzione trovata ottimale,
illimitata oppure impossibile. Inoltre viene mostrato il nome e il valore
della funzione obbiettivo. Nella sezione MACROS del le della soluzione
possiamo avere la lista di tutte le macros del modello denite insieme al loro

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

In questo capitolo vengono analizzati alcuni problemi classici di Pro-


grammazione Lineare e ne viene fornita la descrizione del modello con il
linguaggio MPL.

4.1 Un problema di assegnamento


Unazienda deve eseguire N lavori diversi avendo a disposizione N per-
sone. Ognuna impiega un determinato tempo a svolgere un certo incarico
secondo la tabella riportata sotto. Sapendo che la ditta paga i suoi di-
pendenti ad un determinato prezzo orario, come devono essere assegnati gli
incarichi alle diverse persone per minimizzare il costo complessivo?
Lavoro Bianchi Verdi Rossi Ferrari
lavoro A 12 15 9 5
lavoro B 13 16 11 6
lavoro C 6 8 5 3
lavoro D 5 7 4 3
Poich il costo direttamente proporzionale al tempo impiegato, suffi-
ciente minimizzare il tempo totale.
Introduciamo le variabili binarie xij con il seguente signicato:

1 se il lavoro i-esimo viene assegnato alla j-esima persona
xij =
0 altrimenti
La funzione da minimizzare sar quindi:
X
tij xij
i,j

21
soggetta ai vincoli che ogni persona pu svolgere esattamente un lavoro:
X
xij = 1 j = 1 .. N
i

e che ogni lavoro pu essere assegnato solamente ad una persona:


X
xij = 1 i = 1 .. N
j

Vediamo ora come si traduce questo modello in MPL.

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

Se si risolve questo modello si avra il seguente assegnamento ottimo:

lavoro A ==> Rossi

22
lavoro B ==> Ferrari
lavoro C ==> Bianchi
lavoro D ==> Verdi

di tempo totale minimo = 28.

4.2 Un primo problema dei trasporti


Una ditta di trasporto deve trasferire container vuoti dai propri ma-
gazzini ai principali porti nazionali. Le disponibilit di container vuoti ai
magazzini e le richieste ai porti sono le seguenti:

Verona 10 Genova 20
Perugia 12 Venezia 15
Roma 20 Ancona 25
Pescara 24 Napoli 33
Taranto 18 Bari 21
Lamezia 40

I costi di trasporto sono proporzionali al numero di container ed ai


chilometri percorsi dai camion, secondo la seguente tabella:

Genova Venezia Ancona Napoli Bari


Verona 290 115 355 715 810
Perugia 380 340 165 380 610
Roma 505 530 285 220 450
Pescara 655 450 155 240 315
Taranto 1010 840 550 305 95
Lamezia 1072 1097 747 372 333

Si vuole determinare la politica di trasporto di costo complessivo minimo.


Cominciamo col denire le variabili intere xij come segue:
xij = numero di container trasferiti dal magazzino i al porto j
La funzione obiettivo da minimizzare il costo complessivo di trasporto:
X
distanzeij  xij  costo unitario
i,j

soggetta ai vincoli che ogni magazzino di partenza pu spedire tanti contai-


ner quant la sua disponibilit:
X
xij  dispi i = 1 .. 6
j

23
e che ogni porto di distinazione deve soddisfare la propria richiesta:
X
xij  richj j = 1 .. 5
i

Vediamo come tradurre questo modello in MPL

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 );

distanze[magazzini, porti] = DATAFILE ("Distanze.dat");

costo_unitario = 300; ! costo per chilometro

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

Per come abbiamo deniti gli INDEX, magazzini e porti, il le Distan-


ze.dat contiene la tabella dei chilometri percorsi esattamente cos come
riportata nella pagina precedente.

24
{ Datafile per TRASPORTI.MPL }

Genova Venezia Ancona Napoli Bari \\

Verona 290 115 355 715 810 \\


Perugia 380 340 165 380 610 \\
Roma 505 530 285 220 450 \\
Pescara 655 450 155 240 315 \\
Taranto 1010 840 550 305 95 \\
Lamezia 1072 1097 747 372 333 \\

Risolvendo questo modello con MPL si avr la seguente congurazione


di trasporto ottimo:

Genova Venezia Ancona Napoli Bari


Verona - 10 - - -
Perugia 7 5 - - -
Roma 13 - 1 6 -
Pescara - - 24 - -
Taranto - - - - 18
Lamezia - - - 27 3

di costo minimo = 9.045.900.

4.3 Un problema della dieta


Una mensa deve pianicare gli acquisti di alimenti per la sua attivit.
Nella formulazione della dieta deve obbedire a requisiti nutrizionali minimi,
nonch vincolare le porzioni massime di ogni elemento entro certi limiti.
Conoscendo i costi unitari dei vari alimenti, trovare la dieta ottima che
minimizzi il costo complessivo rispettando i vincoli imposti.

Alimento Costo unitario Quantit massima


Pane 2 4
Latte 3 8
Uova 4 3
Carne 19 2
Dolce 20 2

Requisiti nutrizionali minimi

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.

Calorie Proteine Calcio


Pane 110 4 2
Latte 160 8 285
Uova 180 13 54
Carne 260 14 80
Dolce 420 4 22

Le variabili di questo problema sono le quantit xi di ogni alimento da


inserire nella dieta.
La funzione obiettivo da minimizzare il costo complessivo:
X
costoi  xi
i

Un primo vincolo quello dellapporto nutrizionale:


X
apportoij  richiestej j nutrimenti
ialimenti

Esiste poi un limite massimo alle quantit dei singoli alimenti.

xi  maxP orzi i alimenti

Questo limite pu essere imposto introducendo dei nuovi vincoli oppure, in


modo pi efficiente, utilizzando degli upper bound.
Vediamo come convertire questo modello nel linguaggio MPL.

TITLE
Dieta_ottima

INDEX
nutrimenti = (Calorie,Proteine,Calcio) : 10

alimenti = (Pane, Latte, Uova, Carne, Dolce) : 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

maxPorz[alimenti] = ( 4 ! Pane Massimo numero di porzioni


8 ! Latte tollerato giornalmente
3 ! Uova
2 ! Carne
2 ) ; ! Dolce

apporto[alimenti,nutrimenti] = DATAFILE(nutrimen.dat)
! Contenuti di nutrimenti nei diversi alimenti

DECISION
x[alimenti] -> "" ! porzioni di ogni alimento

MODEL

MIN Cost = SUM(alimenti: costo*x) ;

SUBJECT TO

NutrBal[nutrimenti] : SUM(alimenti: apporto*x) > richieste[nutrimenti];

BOUNDS

MaxPorzioni : x < maxPorz ;

END

Segue il le Nutrimen.dat.

{ Datafile per DIETA.MPL }

! Valori Nutritivi degli alimenti

Calorie Proteine Calcio


! (cal) (grams) (migrams)

Pane 110 4 2
Latte 160 8 285
Uova 180 13 54
Carne 260 14 80

27
Dolce 420 4 22

Risolvendo questo modello con MPL si avr la seguente dieta ottima:

Alimento quantit
Pane 4
Latte 8
Uova 1.5556
Carne 0
Dolce 0

di costo minimo = 38.222. Come si pu notare la soluzione ottima prevede


un valore non intero per lalimento Uova. Se vogliamo forzare la soluzione ad
assumere solo valori interi baster aggiungere il seguente vincolo di interezza
al modello subito dopo gli altri vincoli:

INTEGER
x; ! variabili intere

La nuova soluzione intera risulta essere ora:


Alimento quantit
Pane 4
Latte 8
Uova 2
Carne 0
Dolce 0

di costo minimo = 40. Il fatto che la soluzione intera sia semplicemente


quella lineare con lunica variabili non intera arrotondata per eccesso pu-
ramente casuale. Spesso la soluzione intera e la sua versione rilassata sono
assai diverse.

4.4 Un problema di produzione pi complesso


Unazienda produce 5 diversi tipi di gomma (PVC1, PVC2, PVC3, Gom-
ma1 e Gomma2) con i seguenti costi e ricavi unitari.

Prodotto Costo Ricavo


PVC1 30 130
PVC2 45 200
PVC3 20 120
Gomma1 10 115
Gomma2 25 165

28
Sapendo che i costi orari e la disponibilit di ogni macchina :

Macchina Costo orario Disponibilit


macPVC 90 60
macGomma 100 90
Tagliom 50 130
Pallets 40 70
Avvolgimento 30 40

e che i tempi di lavorazione in ore di ciascuna machina per ottenere ununit


di prodotto nita sono i seguenti:

macchina / prodotto PVC1 PVC2 PVC3 GOMMA1 GOMMA2


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

calcolare la quantit ottimale da produrre per ogni prodotto in modo da


massimizzare i guadagni.

Deniamo per prima cosa le variabili del problema: siano xi le quantit


da produrre di ogni prodotto.
La funzione obiettivo da massimizzare il guadagno netto, dato dalla diffe-
renza tra ricavi e costi unitari dei singoli prodotti e costi di produzione di
ogni macchina in base al loro utilizzo:
X X X
(Ricavoi Costoi )  xi ( Costo orarioj  tempoij  xi ) / 3600
i j i

Lunico vincolo che non si superi la disponibilit di utilizzo di ogni mac-


china: X
tempoij  xi < Of f ertaj j macchina
i

Vediamo come convertire questo modello nel linguaggio MPL.

{ 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

Ricavo[prodotto] = ( 130 ! PVC1 (in lire)


200 ! PVC2
120 ! PVC3
115 ! GOMMA1
165 ) ; ! GOMMA2

Offerta[macchina] = 3600 * ( 60 ! macPVC


90 ! macGomma
130 ! Taglio
70 ! Pallets
40 ) ; ! Avvolgimento

Costo_orario[macchina] = 1000 * ( 90 ! macPVC


100 ! macGomma
50 ! Taglio
40 ! Pallets
30 ) ; ! Avvolgimento

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);

TotaleCosto := SUM(prodotto, macchina : Costo_orario * tempo * x / 3600 );

MODEL

Max Guadagno = Ricavi - TotaleCosto ;

SUBJECT TO

30
N[macchina] -> "" : SUM(prodotto: tempo * x) < Offerta[macchina];

END

Segue il le mixprod.dat .

{ Datafile per Produz.MPL }

! Tempi di lavorazione in ore di ciascuna machina per ottenere


! una unit di prodotto finita

PVC1 PVC2 PVC3 GOMMA1 GOMMA2

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

La soluzione ottima per la produzione risulta:

Prodotto quantit
PVC1 105.750
PVC2 110.250
PVC3 0
Gomma1 81.000
Gomma2 0

per un guadagno complessivo di L. 15.388.750.

31
Capitolo 5

Un Modello di
Pianicazione della
Produzione a Multi-Periodo

In questo capitolo creeremo una formulazione di un modello di pianica-


zione della produzione a multi-periodo. Partiamo dal modello che abbiamo
creato nel capitolo 3 facendo le opportune modiche.
In questo nuovo problema abbiamo un periodo di quattro mesi da pia-
nicare, da Gennaio a Aprile. Per prima cosa dobbiamo creare un nuovo
indice che contiene i quattro mesi in esame, quindi aggiornare il resto del
modello aggiungendo gli indici ai vettori gi deniti.
Come nel problema del capitolo 3, il prezzo di vendita per i prodotti
ancora rispettivamente $120.00, $100.00 e $115.00. Ora, oltre ad avere una
domanda diversa per ogni prodotto, abbiamo una domanda differenziata per
ogni prodotto e ogni mese. Nella tabella seguente riportiamo i valori.

Domanda di Produzione Gen Feb Mar Apr


A1 4300 4200 6400 5300
A2 4500 5400 6500 7200
A3 5400 6700 7800 8200

Le quote di produzione e i costi di produzione resteranno gli stessi che sono


stati forniti nella tabella del capitolo 3 a pag. 16. Inoltre i giorni di produ-
zione disponibili in un mese varieranno ogni mese: 23 giorni a Gennaio, 20
a Febbraio, 23 a Marzo e 22 a Aprile.
Inoltre dovremo introdurre un magazzino nel modello; questo comporta
lintroduzione di un costo di magazzino per ogni prodotto: A1-$3.50/mese,
A2-$4.00/mese e A3-$3.00/mese. Ogni prodotto occupa lo stesso spazio, ma
lo spazio totale disponibile nel magazzino di 800 unit.

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

MAX Profit = TotalRevenue - TotalCost;

SUBJECT TO
ProdCapacity[month] -> PCap:
SUM(product: Produce / ProdRate) <= ProdDaysAvail;

33
InvtBal[product, month] -> IBal:
Produce + Inventory[month-1] = Sales + Inventory;

MaxInventory[month] -> MaxI:


SUM(product: Inventory) <= InvtCapacity;

BOUNDS
Sales <= Demand;

END

5.2 Risolvere il Modello e Analizzare la Soluzione


Il prossimo passo quello di risolvere il modello Planning4: basta sce-
gliere la voce Solve CPLEX nel men Run. Se i dati sono stati inseriti
correttamente, MPL moster il messaggio che la soluzione ottimale stata
trovata (Optimal Solution Found). Se si presenta un messaggio di errore in
una nestra, indicazione di un errore di sintassi, ricontrolliamo la formula-
zione del modello che abbiamo inserito confrontandola con quella fornita a
pag. 33.
Dopo aver risolto il modello, MPL crea automaticamente un le chia-
mato Planning4.sol nel formato standard contenente la soluzione. Possiamo
visualizzare il le della soluzione in una nestra con la pressione del tasto
View che si trova sul fondo della nestra di stato. Riportiamo qui il listato
completo del le della soluzione:

MPL Modeling System - Copyright (c) 1988-2000, Maximal Software, Inc.


-----------------------------------------------------------------------------

MODEL STATISTICS

Problem name: Production_Planning4

Filename: Planning4.mpl
Date: July 8, 2000
Time: 20:13
Parsing time: 0.22 sec

Solver: CPLEX 300


Objective value: 2246007.27273
Iterations: 0
Solution time: 0.06 sec

34
Constraints: 20
Variables: 36
Nonzeros: 69
Density: 10 %

SOLUTION RESULT

Optimal solution found

MAX Profit = 2246007.2727

MACROS

Macro Name Values


-----------------------------------------------
TotalRevenue 5386045.4545
TotalProdCost 3139078.1818
TotalInvtCost 960.0000
TotalCost 3140038.1818
-----------------------------------------------

DECISION VARIABLES

VARIABLE Produce[product,month] :

product month Activity Reduced Cost


----------------------------------------------------
A1 Jan 4300.0000 0.0000
A1 Feb 4200.0000 0.0000
A1 Mar 4409.0909 0.0000
A1 Apr 3545.4545 0.0000
A2 Jan 1800.0000 0.0000

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] :

product month Activity Reduced Cost


----------------------------------------------------
A1 Jan 0.0000 -0.2000
A1 Feb 0.0000 -2.4900
A1 Mar 0.0000 -3.5000
A1 Apr 0.0000 -123.5000
A2 Jan 0.0000 -4.0000
A2 Feb 0.0000 -4.0000
A2 Mar 0.0000 0.0000
A2 Apr 0.0000 -108.0000
A3 Jan 320.0000 0.0000
A3 Feb 0.0000 -2.0818
A3 Mar 0.0000 -3.0000
A3 Apr 0.0000 -110.8545
----------------------------------------------------

VARIABLE Sales[product,month] :

product month Activity Reduced Cost


----------------------------------------------------
A1 Jan 4300.0000 4.3100
A1 Feb 4200.0000 1.0100
A1 Mar 4409.0909 0.0000
A1 Apr 3545.4545 0.0000
A2 Jan 1800.0000 0.0000
A2 Feb 0.0000 0.0000
A2 Mar 0.0000 0.0000
A2 Apr 0.0000 -4.0000
A3 Jan 5400.0000 11.0636

36
A3 Feb 6700.0000 8.0636
A3 Mar 7800.0000 7.1455
A3 Apr 8200.0000 7.1455
----------------------------------------------------

CONSTRAINTS

CONSTRAINT ProdCapacity[month] :

month Slack Shadow Price


-------------------------------------------
Jan 0.0000 21195.0000
Feb 0.0000 22845.0000
Mar 0.0000 23350.0000
Apr 0.0000 23350.0000
-------------------------------------------

CONSTRAINT InvtBal[product,month] :

product month Slack Shadow Price


----------------------------------------------------
A1 Jan 0.0000 -115.6900
A1 Feb 0.0000 -118.9900
A1 Mar 0.0000 -120.0000
A1 Apr 0.0000 -120.0000
A2 Jan 0.0000 -100.0000
A2 Feb 0.0000 -100.0000
A2 Mar 0.0000 -100.0000
A2 Apr 0.0000 -104.0000
A3 Jan 0.0000 -103.9364
A3 Feb 0.0000 -106.9364
A3 Mar 0.0000 -107.8545
A3 Apr 0.0000 -107.8545
----------------------------------------------------

37
CONSTRAINT MaxInventory[month] :

month Slack Shadow Price


-------------------------------------------
Jan 480.0000 0.0000
Feb 800.0000 0.0000
Mar 800.0000 0.0000
Apr 800.0000 0.0000
-------------------------------------------

END

Il protto ora risulta di 2,2 milioni di dollari che considerevolmete pi


alto di quello calcolato per il modello Planning3; questo naturale dato che
ora lavoriamo su un periodo di quattro mesi. Il protto il risultato di un
introito pari a 5,4 milioni di dollari e un importo dei costi pari a 3,1 milioni
di dollari, la maggior parte dei quali dato dal costo di produzione, dato che
quello che viene conservato in magazzino poco gi a partire da Gennaio.
Se si osserva nella soluzione la variabile Produce (produzione) notiamo
che abbiamo prodotto A1 e A3 per lintero periodo pianicato, ma non
sempre stato possibile soddisfare la domanda. Daltro canto del prodotto
A2 sono stati prodotte solo 1800 unit in Gennaio, questo signica che non
abbiamo la capacit di produrre tutti e tre i prodotti.
In Gennaio il modello ha deciso di produrre, oltre alla domanda, 320
unit di A3, con lo scopo di immagazinarli per soddisfare la domanda di
Febbraio.

38
Capitolo 6

Un Modello di
Pianicazione con pi
Impianti di Produzione

In questo capitolo creeremo una nuovo modello per la pianicazione della


produzione che include la presenza di pi impianti oltre a considerare periodi
differenziati come nel capitolo 5. Quello che dobbiamo decidere quanto
bisogna produrre di ogni prodotto per ogni mese, in ogni impianto, cercando
di ottimizare, per ogni mese e per ogni impianto, la vendita e il deposito nel
magazzino.
In questo nuovo problema avremo quattro differenti impianti p1, p2, p3
e p4. Ognuno di questi impianti produce tutti e tre i prodotti. Creiamo un
indice chiamato plants (impianti) che contiene i quattro differenti impianti
e quindi aggiorniamo il modello con laggiunta dellindice ai vettori che ne
necessitano.
Come nelle sezioni precedenti, il prezzo di vendita per ogni prodotto
rispettivamente $120.00, $100.00 e $150.00. La domanda dei vari prodot-
ti rimane la stessa del capitolo precedente; ci riferiamo alla tabella della
domanda del capitolo 5 a pag. 32.
Ora abbiamo pi di un impianto di produzione e il costo di produzione
di ogni prodotto diverso per ogni impianto. Riportiamo questi dati nella
tabella seguente.

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

Anche la quota di produzione di ogni prodotto diversicata a seconda


dellimpianto come riportiamo nella seguente tabella.

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

6.1 Formulazione del Modello


Il listato seguente la formulazione del modello per Planning5.

{ 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

MAX Profit = TotalRevenue - TotalCost;

40
SUBJECT TO
ProdCapacity[plant, month] -> PCap:
SUM(product: Produce / ProdRate) <= ProdDaysAvail;

InvtBal[product, month] -> IBal:


SUM(plant: Produce) + Inventory[month-1] = Sales + Inventory;

MaxInventory[month] -> MaxI:


SUM(product: Inventory) <= InvtCapacity;

BOUNDS
Sales <= Demand;

END

6.2 Risolvere il Modello e Analizzare la Soluzione


Dato che abbiamo aggiunto diversi indici al modello, il numero delle va-
riabili cresciuto in maniera considerevole. Tipicamente, quando si lavora
con grandi modelli, il creatore del modello preferisce includere solo le varia-
bili diverse da zero. MPL ha diverse opzioni che possono essere impostate
tramite il men Options; mediante queste opzioni possiamo cambiare il com-
portamento del programma. Una delle possibilit nel men Options quella
di aprire la nestra di dialogo delle opzioni relative al le della soluzione; in
questa nestra di dialogo possiamo scegliere a vostro piacere cosa includere e
cosa escludere nel le della soluzione. Per cambiare i valori standard e quin-
di includere solo i valori diversi da zero nel le della soluzione, sufficiente
fare i seguenti passi:

1. Nel men Options scegliere Solution File per aprire la nestra di dia-
logo (Options Dialog Box).

2. Attivare lopzione Nonzero Values Only cliccando sul quadratino rela-


tivo.

3. Chiudere la nestra di dialogo premendo il tasto OK.

Dopo aver effettuato il cambiamento che permette di non scrivere i valo-


ri nulli, il prossimo passo quello di risolvere il modello scegliendo Solve
CPLEX nel men Run. Se tutto ha funzionato a dovere MPL mostrer il
messaggio Optimal solution Found. Se si presenta un messaggio di errore
in una nestra, indicazione di un errore di sintassi, ricontrolliamo la formu-
lazione del modello che abbiamo inserito confrontandola con quella fornita
a pag. 40.

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] :

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
p2 A2 Jan 4500.0000 0.0000
p2 A2 Feb 5400.0000 0.0000
p2 A2 Mar 6500.0000 0.0000
p2 A2 Apr 7200.0000 0.0000
p3 A3 Jan 5400.0000 0.0000
p3 A3 Feb 6000.0000 0.0000
p3 A3 Mar 6900.0000 0.0000
p3 A3 Apr 6600.0000 0.0000
p4 A3 Feb 700.0000 0.0000
p4 A3 Mar 900.0000 0.0000
p4 A3 Apr 1600.0000 0.0000
-----------------------------------------------------------
Se osserviamo i valori dellattivit per la variabile Produce ci accorgere che
ora siamo in grado di saturare completamente la domanda per ogni prodotto.
Per esempio, limpianto p1 usato per produrre A1, limpianto p2 usato
per produrre A2, gli impianti p3 e p4 sono usati per produrre A3.

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] :

plant month Slack Shadow Price


--------------------------------------------------
p1 Jan 14.4000 0.0000
p1 Feb 11.6000 0.0000
p1 Mar 10.2000 0.0000
p1 Apr 11.4000 0.0000
p2 Jan 13.0000 0.0000
p2 Feb 8.0000 0.0000
p2 Mar 8.5556 0.0000
p2 Apr 6.0000 0.0000
p3 Jan 5.0000 0.0000
p4 Jan 23.0000 0.0000
p4 Feb 18.0000 0.0000
p4 Mar 20.4286 0.0000
p4 Apr 17.4286 0.0000
--------------------------------------------------

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.

7.1 Usare la Condizione Where sui Vettori di


Variabili
Diverse volte, lavorando con vettori multi-dimensionali, ci troveremo a
non voler considerare tutti le variabili del vettore dato che alcuni casi posso-
no non essere validi oppure non aver signicato. Per esempio, in un modello
di distribuzione non ha senso trasportare i prodotti da un determinato im-
pianto allimpianto stesso. In questi casi possiamo usare la condizione where
sulle variabili per rimuovere gli elementi non necessari. Per esempio, nel mo-
dello di distribuzione possiamo eliminare la possibilit di trasportare da un
impianto in se stesso mediante la seguente dichiarazione:

VARIABLES
Ship[fromplant,toplant]
WHERE(fromplant<>toplant);

In questo caso, la condizione (fromplant<>toplant) rimuove tutti gli ele-


menti del vettore dove limpianto sorgente lo stesso dellimpianto di desti-

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);

7.2 Vincoli di Bilanciamento degli Impianti


Quando lavoriamo con un modello di distribuzione abbiamo la necessit
di garantire che la quantit di prodotti arrivati da altri impianti sommata
alla produzione e a quanto stato preso dal magazzino, deve essere uguale
a quanto stato trasportato fuori dallimpianto sommato a quello che
stato venduto e alla quantit immagazinata. In poche parole, quello che
entra nellimpianto deve essere uguale a quello che esce. Questo tipo di
vincolo tipicamente chiamato vincolo di bilanciamento dellimpianto. Qui
riportiamo un semplice esempio di vincolo di bilanciamento dellimpianto:

PlantBal[plant,product,month]
Produce+Inventory[month-1] +
SUM(fromplant: Ship[fromplant,toplant:=plant])
=
Sales + Inventory +
SUM(fromplant: Ship[fromplant:=plant,toplant]);

Si noti che questo vincolo simile al vincolo di bilanciamento del magazzino


che stato introdotto precedentemente. Lunica differenza che ora bisogna
considerare che trasportiamo in e da un impianto utilizzando un sommatoria
su ogni impianto per la variabile Ship.
Lassegnamento dellindice toplant:=plant nella prima sommatoria, ci
permette di specicare che limpianto di arrivo (toplant) utilizzato deve es-
sere limpianto per il quale stiamo denendo il vincolo PlantBal. In questa
vincolo sono sommati tutti i beni trasportati allimpianto al quale il vin-
colo stesso si riferisce da qualsiasi impianto. In maniera analoga lassegna-
mento fromplant:=plant nella seconda sommatoria specica che limpianto
di partenza (fromplant) deve essere limpianto (plant) per il quale stiamo
denendo il vincolo.

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:

Costi del magazzino A1 A2 A3


p1 $8.50 $7.00 $6.50
p2 $9.80 $9.80 $9.80
p3 $7.50 $7.50 $7.50
p4 $9.30 $8.00 $6.50

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.

7.4 Formulazione del modello


Quello che segue il codice della formulazione del modello Planning6.
Come vedremo una estensione del modello Planning5.

{ 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

MAX Profit = TotalRevenue - TotalCost;

SUBJECT TO
ProdCapacity[plant, month] -> PCap:
SUM(product: Produce / ProdRate) <= ProdDaysAvail;

PlantBal[plant, product, month] -> PBal:


Produce + Inventory[month-1]
+ SUM(fromplant: Ship[fromplant, toplant:=plant])
=
Sales + Inventory
+ SUM(toplant: Ship[fromplant:=plant, toplant]);

MaxInventory[plant, month] -> MaxI:


SUM(product: Inventory) <= InvtCapacity;

BOUNDS
Sales <= Demand;

END

7.5 Risolvere il Modello e Analizzare la Soluzione


Il prossimo passo quello di risolvere il modello Planning6 scegliendo Sol-
ve CPLEX nel men Run. Se tutto si svolto correttamente MPL mostrer
il messaggi Optimal Solution Found. Se viene visualizzato un messaggio
di errore ricontrolliamo il codice inserito confrontandolo con quello riportato
in precedenza in questa sezione. Ora useremo la nestra con la formulazione
del modello (Model Denition Windows) come nel capitolo 6 per vedere solo
le parti della soluzione che ci interessano. Per aprire la nestra con le de-
nizioni del modello per il modello Planning6 scegliamo Model Denitions
nel men View.
Per vedere i valori della variabile Produce, eseguire un doppio click sulla
scritta Produce nellalbero o, alternativamente, selezionatela e premiamo

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
-----------------------------------------------------------

Come possiamo vedere la produzione ora distribuita tra i vari impianti


con una gestione pi efficiente dei costi. chiaro che meglio produrre
determinati prodotti in determinati impianti e mettere in conto le spese di

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] :

product month fromplant toplant Activity Reduced Cost


------------------------------------------------------------------------
A2 Mar p2 p4 331.8182 0.0000
A3 Mar p4 p3 877.2727 0.0000
A3 Apr p4 p3 736.3636 0.0000
------------------------------------------------------------------------

Come possiamo vedere il modello propone di trasportare A2 dallim-


pianto p2 allimpianto p4. Analogamente A3 viene trasportato da p4 a p3.
Chiaramente perch gli impianti p2 e p4 hanno una capacit extra e un bas-
so costo di produzione e quindi possono essere usati per produrre quello di
cui necessitano p4 e p3 rispettivamente.

50
Capitolo 8

Un Modello con Pi
Macchinari

In questo capitolo dovremo aggiornare il precedente modello inserendo


dei macchinari distribuiti tra gli impianti. Baster apportare le opportune
modiche al modello creato nel capitolo 7 per aggiornarlo.
Dato che ora abbiamo dei macchinari differenti nei vari impianti, i costi
e le quote di produzione saranno ora diversi per ogni macchina. La seguen-
te tabella riassume i dati di produzione dove ogni riga corrisponde a una
macchina che produce un prodotto in un dato impianto.

Impianto Macchinario Prodotto Costo di Produzione Quota di Produzione


m11 A1 $73.30 500
p1 m11 A2 $52.90 450
m12 A3 $65.40 550
m13 A3 $47.60 350
m21 A1 $79.00 550
p2 m21 A3 $66.80 450
m22 A2 $52.00 300
m31 A1 $75.80 450
p3 m31 A3 $50.90 300
m32 A1 $79.90 400
m32 A2 $52.10 350
m41 A1 $82.70 550
p4 m41 A2 $63.30 400
m41 A3 $53.80 350

Il processo di valutazione della produzione, quanto dobbiamo produrre di


ciascuno prodotto, necessita di tenere in considerazione la presenza di diver-
se macchine. Perci, dovremo aggiornare la variabile Produce includendo
lindice delle macchine e, quindi, usare la condizione where per escludere gli

51
elementi non necessari; ad esempio: impianto p1, macchina m11 e prodotto
A3.

8.1 Formulazione del Modello


Il listato che segue il codice della formulazione di Planning7.

{ 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

MAX Profit = TotalRevenue - TotalCost;

SUBJECT TO
ProdCapacity[plant, machine, month] -> PCap:
SUM(product: Produce / ProdRate) <= ProdDaysAvail;

PlantBal[plant, product, month] -> PBal:


SUM(machine: Produce) + Inventory[month-1]
+ SUM(fromplant: Ship[fromplant, toplant:=plant])
=
Sales + Inventory[month]
+ SUM(toplant: Ship[fromplant:=plant, toplant]);

MaxInventory[plant, month] ->MaxI:


SUM(product: Inventory) <= InvtCapacity;

BOUNDS
Sales <= Demand;

END

8.2 Risolvere il Modello e Analizzare la Soluzione


Il prossimo passo quello di risolvere il modello scegliendo Solve CPLEX
nel men Run. Se tutto stato fatto correttamente verr visualizzato il mes-
saggio Optimal Solution Found. Altrimenti, se viene visualizzato un mes-
saggio di errore, controlliamo il codice che abbiamo scritto confrontandolo
con quello riportato in precedenza in questa sezione.
Useremo ancora la nestra delle denizioni del modello (Model Deni-
tions Model), come nel capitolo 7, per osservare solo le parti della soluzione
alle quali siamo interessati. Per aprire la nestra con le denizioni del mo-
dello per il modello Planning7 scegliendo Model Denitions nel men View.
Per vedere il valore della variabile Produce fare un doppio click sulla scrit-
ta Produce che si trova nellalbero delle denizioni oppure selezioniamo la
scritta e premiamo View. Questa operazioni visualizzeranno una nestra
con i valori della soluzione solo per la variabile Produce; riportiamo qui nel
seguito questi valori.

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] :

plant product month Activity Reduced Cost


-----------------------------------------------------------
p1 A2 Jan 800.0000 0.0000
p1 A2 Feb 620.0000 0.0000
p2 A2 Jan 400.0000 0.0000
p3 A3 Jan 500.0000 0.0000
p4 A2 Jan 400.0000 0.0000
-----------------------------------------------------------

Possiamo osservare che il modello ha deciso di produrre una eccedenza


dei prodotti A2 e A3 in Gennaio per aumentare la disponibilit in Febbraio.
La maggior parte degli impianti ora funzionano a pieno regime. Riutiliz-
zare la nestra con lalbero delle denizioni apriamo una nuova nestra con
il vincolo ProdCapacity per visualizzare i seguenti valori:

CONSTRAINT ProdCapacity[plant,machine,month] :

plant machine month Slack Shadow Price


-----------------------------------------------------------
p1 m12 Jan 23.0000 0.0000

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
-----------------------------------------------------------

Come possiamo vedere limpianti p1 e p2 hanno una capacit di produzione


non sfruttata per le machine m12 e m21 rispettivamente. Del resto tutte
le altre macchine degli altri impianti lavorano a pieno regime per coprire
completamente la domanda.

56