Ricerca Operativa e Logistica Dott. F.Carrabs e Dott.ssa M.Gentili A.A. 2011/2012 Lezione 7: Analisi di Sensitività con AMPL
Esempio : Il caseificio Un caseificio vuole pianificare la produzione giornaliera di burro, ricotta e mozzarella avendo a disposizione 7 operai e 120 litri di latte. La massima domanda di ciascun prodotto è di 9, 23 e 18 Kg rispettivamente. La quantità di latte richiesta per ogni Kg di prodotto è rispettivamente di 20, 2 e 5 litri. Ciascuno operaio può produrre ognuno dei 3 prodotti e la massima quantità che produrrebbe se si occupasse solamente di uno di essi è rispettivamente di 2, 7 e 3 Kg. Infine il prezzo di vendita per ogni Kg di prodotto è di 2.5, 1.1 e 2 euro. Rispondere alle seguenti domande: 1. Formulare un modello AMPL per determinare il piano di produzione che massimizza il guadagno totale. 2. Quali vincoli di domanda sono attivi? 3. Conoscendo i valori delle variabili di slack dei vincoli di domanda che cosa si può dire sui prezzi ombra? 4. Quali sono le risorse scarse e quali quelle abbondanti? 5. Su quale risorsa mi conviene investire? Perché? 6. Di quanto aumenta il profitto: Ø se portiamo a 130 i litri di latte disponibili? Ø se portiamo la domanda massima della ricotta a 28? Ø se riduciamo a 6 gli operai? 9. Di quanto dovrebbe aumentare il guadagno unitario del burro per iniziare a produrlo? 10. Il caseificio vuole valutare la possibilità di produrre panna. Sapendo che la produzione di 1Kg di panna richiede 15 litri e che ogni operaio può produrre al massimo una quota di 4 Kg di panna, a partire da quale prezzo conviene iniziare a produrla? Si assuma che non ci siano limiti di domanda. 11. Quali sono i range di variabilità dei coefficienti di costo entro i quali la base ottima non cambia? 12. Quali sono i range di variabilità dei termini noti entro i quali la base ottima non cambia?
Caseificio: modello matematico max2.5x B +1.1x R + 2x M s.t. 20x B + 2x R + 5x M!120 1 2 x B + 1 7 x R + 1 3 x M! 7 x B! 9 x R! 23 x M!18 x i " 0 Latte disponibile Vincolo sugli operai Vincoli di domanda Risorse disponibili
Caseificio: file.mod set PRODOTTI; var x{prodotti} >=0; param prezzo_vendita{prodotti}; param b_max_domanda{prodotti}; param A_richiesta_latte{PRODOTTI}; param A_richiesta_operai{PRODOTTI}; param b_latte_disp; param b_operai_disp; max2.5x B +1.1x R + 2x M s.t. 20x B + 2x R + 5x M!120 1 2 x B + 1 7 x R + 1 3 x M! 7 x B! 9 x R! 23 x M!18 x i " 0 Latte disponibile Vincolo sugli operai Vincoli di domanda maximize profitto: sum{i in PRODOTTI} prezzo_vendita[i]*x[i]; s.t. latte_disponibile: sum{i in PRODOTTI} A_richiesta_latte[i]*x[i]<=b_latte_disp; s.t. vinc_max_domanda {i in PRODOTTI}: x[i] <=b_max_domanda[i]; s.t. operai_disponibili: sum{i in PRODOTTI} A_richiesta_operai[i]*x[i] <=b_operai_disp;
Caseificio: file.dat set PRODOTTI:= BURRO RICOTTA MOZZARELLA; param prezzo_vendita:= BURRO 2.5 RICOTTA 1.1 MOZZARELLA 2; param b_max_domanda:= BURRO 9 RICOTTA 23 MOZZARELLA 18; param A_richiesta_latte:= BURRO 20 RICOTTA 2 MOZZARELLA 5; param A_richiesta_operai:= BURRO 0.5 RICOTTA 0.1428 MOZZARELLA 0.3333; param b_latte_disp:=120; param b_operai_disp:=7; (.run) max2.5x B +1.1x R + 2x M s.t. 20x B + 2x R + 5x M!120 1 2 x B + 1 7 x R + 1 3 x M! 7 x B! 9 x R! 23 x M!18 x i " 0 Latte disponibile Vincolo sugli operai Vincoli di domanda reset; option solver cplex; option cplex_options 'sensitivity timing=1'; options presolve 0; model./example/caseificio.mod; data./example/caseificio.dat; solve; display solve_result; display x;
Caseificio: risultati del solver ampl: include./example/caseificio.run; CPLEX 11.2.0: sensitivity timing=1 Times (seconds): Input = 0 Solve = 0 Output = 0.046 Tempo impiegato per risolvere il problema CPLEX 11.2.0: optimal solution; obective 47.59582958 1 dual simplex iterations (0 in phase I) Valore ottimo suffix up OUT; suffix down OUT; suffix current OUT; solve_result = solved Risultato del solver x [*] := BURRO 0 MOZZARELLA 11.1479 RICOTTA 23; Soluzione ottima
. solve_result = solved Caseificio: risultati del solver option solve_result_table '\ 0 solved\ 100 solved?\ 200 infeasible\ 300 unbounded\ 400 limit\ 500 failure\ '; number string interpretation 0-99 solved optimal solution found 100-199 solved? optimal solution indicated, but error likely 200-299 infeasible constraints cannot be satisfied 300-399 unbounded obective can be improved without limit 400-499 limit stopped by a limit that you set (such as on iterations) 500-599 failure stopped by an error condition in the solver routines
Caseificio: risultati del solver (.run) reset; option solver cplex; option cplex_options 'sensitivity timing=1 timelimit=0 iterations=100'; options presolve 0; model./example/caseificio.mod; data./example/caseificio.dat; solve; display solve_result; display x;
Richiami di Ricerca Operativa Se il problema ammette ottimo finito allora: l Il punto di ottimo coincide con un vertice della regione ammissibile, i.e. 1 esiste una soluzione di base ammissibile x B = A b e x B N = 0 in cui la funzione obiettivo assume valore ottimo. l Il valore della funzione obiettivo è pari a: con z = c B A 1 B a 1 B * z = c A b + ( c z ) x B N l Condizione di ottimalità di una sol. di base ammissibile: Problema di minimo: c z 0 N Problema di massimo: c z 0 N T T 1 l Dal teorema della dualità forte si ha che w = c e quindi: B AB * T T z = w b + ( c z ) x e z = w a N
Caseificio: vincoli attivi set PRODOTTI; var x{prodotti} >=0; param prezzo_vendita{prodotti}; param b_max_domanda{prodotti}; param A_richiesta_latte{PRODOTTI}; param A_richiesta_operai{PRODOTTI}; param b_latte_disp; param b_operai_disp; maximize profitto: sum{i in PRODOTTI} prezzo_vendita[i]*x[i]; s.t. latte_disponibile: sum{i in PRODOTTI} A_richiesta_latte[i]*x[i]<=b_latte_disp; s.t. vinc_max_domanda {i in PRODOTTI}: x[i] <=b_max_domanda[i]; s.t. operai_disponibili: sum{i in PRODOTTI} A_richiesta_operai[i]*x[i] <=b_operai_disp; Quali vincoli di domanda sono attivi? ampl: display vinc_max_domanda.slack; vinc_max_domanda.slack [*] := BURRO 9 MOZZARELLA 6.85209 RICOTTA 0; Solo il vincolo associato alla ricotta. Conoscendo i valori delle variabili di slack dei vincoli di domanda che cosa si può dire sui prezzi ombra?
Caseificio: prezzi ombra set PRODOTTI; var x{prodotti} >=0; param prezzo_vendita{prodotti}; param b_max_domanda{prodotti}; param A_richiesta_latte{PRODOTTI}; param A_richiesta_operai{PRODOTTI}; param b_latte_disp; param b_operai_disp; maximize profitto: sum{i in PRODOTTI} prezzo_vendita[i]*x[i]; s.t. latte_disponibile: sum{i in PRODOTTI} A_richiesta_latte[i]*x[i]<=b_latte_disp; s.t. vinc_max_domanda {i in PRODOTTI}: x[i] <=b_max_domanda[i]; s.t. operai_disponibili: sum{i in PRODOTTI} A_richiesta_operai[i]*x[i] <=b_operai_disp; Conoscendo i valori delle variabili di slack dei vincoli di domanda che cosa si può dire sui prezzi ombra? ampl: display vinc_max_domanda; vinc_max_domanda [*] := BURRO 0 MOZZARELLA 0 RICOTTA 0.243114; Il prezzo ombra sia del burro che della mozzarella sono nulli mentre quello della ricotta è diverso da zero.
Caseificio: risorse scarse ed abbondanti set PRODOTTI; var x{prodotti} >=0; param prezzo_vendita{prodotti}; param b_max_domanda{prodotti}; param A_richiesta_latte{PRODOTTI}; param A_richiesta_operai{PRODOTTI}; param b_latte_disp; param b_operai_disp; maximize profitto: sum{i in PRODOTTI} prezzo_vendita[i]*x[i]; s.t. latte_disponibile: sum{i in PRODOTTI} A_richiesta_latte[i]*x[i]<=b_latte_disp; s.t. vinc_max_domanda {i in PRODOTTI}: x[i] <=b_max_domanda[i]; s.t. operai_disponibili: sum{i in PRODOTTI} A_richiesta_operai[i]*x[i] <=b_operai_disp; Quali sono le risorse scarse e quali quelle abbondanti? ampl: display latte_disponibile.slack,operai_disponibili.slack; latte_disponibile.slack = 18.2604 operai_disponibili.slack = 0 Il latte è una risorsa abbondante mentre gli operai sono una risorsa scarsa
Caseificio: prezzi ombra set PRODOTTI; var x{prodotti} >=0; param prezzo_vendita{prodotti}; param b_max_domanda{prodotti}; param A_richiesta_latte{PRODOTTI}; param A_richiesta_operai{PRODOTTI}; param b_latte_disp; param b_operai_disp; maximize profitto: sum{i in PRODOTTI} prezzo_vendita[i]*x[i]; s.t. latte_disponibile: sum{i in PRODOTTI} A_richiesta_latte[i]*x[i]<=b_latte_disp; s.t. vinc_max_domanda {i in PRODOTTI}: x[i] <=b_max_domanda[i]; s.t. operai_disponibili: sum{i in PRODOTTI} A_richiesta_operai[i]*x[i] <=b_operai_disp; Su quale risorsa mi conviene investire? Perché? ampl: display latte_disponibile,operai_disponibili latte_disponibile = 0 operai_disponibili = 6.0006
Caseificio: prezzi ombra set PRODOTTI; var x{prodotti} >=0; param prezzo_vendita{prodotti}; param b_max_domanda{prodotti}; param A_richiesta_latte{PRODOTTI}; param A_richiesta_operai{PRODOTTI}; param b_latte_disp; param b_operai_disp; maximize profitto: sum{i in PRODOTTI} prezzo_vendita[i]*x[i]; s.t. latte_disponibile: sum{i in PRODOTTI} A_richiesta_latte[i]*x[i]<=b_latte_disp; s.t. vinc_max_domanda {i in PRODOTTI}: x[i] <=b_max_domanda[i]; s.t. operai_disponibili: sum{i in PRODOTTI} A_richiesta_operai[i]*x[i] <=b_operai_disp; Di quanto aumenta il profitto: Ø se portiamo a 130 i litri di latte disponibili? Ø se portiamo la domanda massima della ricotta a 28? Ø se riduciamo a 6 gli operai? ampl: display latte_disponibile,vinc_max_domanda,operai_disponibili; latte_disponibile = 0 vinc_max_domanda [*] := BURRO 0 MOZZARELLA 0 RICOTTA 0.243114 ; operai_disponibili = 6.0006
Caseificio: variazione coefficienti di costo set PRODOTTI; var x{prodotti} >=0; param prezzo_vendita{prodotti}; param b_max_domanda{prodotti}; param A_richiesta_latte{PRODOTTI}; param A_richiesta_operai{PRODOTTI}; param b_latte_disp; param b_operai_disp; maximize profitto: sum{i in PRODOTTI} prezzo_vendita[i]*x[i]; s.t. latte_disponibile: sum{i in PRODOTTI} A_richiesta_latte[i]*x[i]<=b_latte_disp; s.t. vinc_max_domanda {i in PRODOTTI}: x[i] <=b_max_domanda[i]; s.t. operai_disponibili: sum{i in PRODOTTI} A_richiesta_operai[i]*x[i] <=b_operai_disp; Di quanto dovrebbe aumentare il guadagno unitario del burro per iniziare a produrlo? T * z = w b + ( c z ) x N ampl: display x['burro'].rc; x['burro'].rc = -0.5003
Caseificio: introduzione nuovo prodotto set PRODOTTI; var x{prodotti} >=0; param prezzo_vendita{prodotti}; param b_max_domanda{prodotti}; param A_richiesta_latte{PRODOTTI}; param A_richiesta_operai{PRODOTTI}; param b_latte_disp; param b_operai_disp; maximize profitto: sum{i in PRODOTTI} prezzo_vendita[i]*x[i]; s.t. latte_disponibile: sum{i in PRODOTTI} A_richiesta_latte[i]*x[i]<=b_latte_disp; s.t. vinc_max_domanda {i in PRODOTTI}: x[i] <=b_max_domanda[i]; s.t. operai_disponibili: sum{i in PRODOTTI} A_richiesta_operai[i]*x[i] <=b_operai_disp; Il caseificio vuole valutare la possibilità di produrre panna. Sapendo che la produzione di 1Kg di panna richiede 15 litri di latte e che ogni operaio può produrre al massimo una quota di 4 Kg di panna, qual è il prezzo minimo a cui bisogna vendere la panna affinchè sia conveniente produrla? Si assuma che non ci siano vincoli di domanda. T * z = w b + ( c z ) x N z = w T a ampl: display latte_disponibile,operai_disponibili; latte_disponibile = 0 operai_disponibili = 6.0006 Basta imporre c p >wa p = 0*15+6.006*1/4=1,5015
Caseificio: range coefficienti di costo set PRODOTTI; var x{prodotti} >=0; param prezzo_vendita{prodotti}; param b_max_domanda{prodotti}; param A_richiesta_latte{PRODOTTI}; param A_richiesta_operai{PRODOTTI}; param b_latte_disp; param b_operai_disp; maximize profitto: sum{i in PRODOTTI} prezzo_vendita[i]*x[i]; s.t. latte_disponibile: sum{i in PRODOTTI} A_richiesta_latte[i]*x[i]<=b_latte_disp; s.t. vinc_max_domanda {i in PRODOTTI}: x[i] <=b_max_domanda[i]; s.t. operai_disponibili: sum{i in PRODOTTI} A_richiesta_operai[i]*x[i] <=b_operai_disp; Quali sono i range di variabilità dei coefficienti di costo entro i quali la base ottima non cambia? ampl: display x.up, x.down; : x.up x.down := BURRO 3.0003-1e+20 MOZZARELLA 2.56744 1.6665 RICOTTA 1e+20 0.856886; Se porto il prezzo di vendita del burro ad un valore superiore ai 3.0003 euro cambia la base ottima. Invece il prezzo può essere decrementato all infinito senza mai cambiare la base ottima. VERIFICHIAMOLO!!!
Caseificio: variabili in e fuori base Lo stato delle variabili al termine della risoluzione può essere mostrato tramite il suffisso.sstatus. La seguente tabella mostra quali possono essere i vari stati di una variabile: ampl: option sstatus_table; option sstatus_table '\ 0 none no status assigned\ 1 bas basic\ 2 sup superbasic\ 3 low nonbasic <= (normally =) lower bound\ 4 upp nonbasic >= (normally =) upper bound\ 5 equ nonbasic at equal lower and upper bounds\ 6 btw nonbasic between bounds\ ';
Caseificio: variabili in e fuori base Per prima cosa stampiamo quali sono le variabili nella base ottima individuate dal solver con il seguente comando: ampl: display x.sstatus; x.sstatus [*] := BURRO low MOZZARELLA bas RICOTTA bas; Le variabili associate alla mozzarella e alla ricotta sono in base. ampl: display latte_disponibile.sstatus, vinc_max_domanda.sstatus,operai_disponibili.sstatus; latte_disponibile.sstatus = bas vinc_max_domanda.sstatus [*] := BURRO bas MOZZARELLA bas RICOTTA upp; Le variabili di slack associate al vincolo del latte e ai vincoli di domanda del burro e della mozzarella sono in base. operai_disponibili.sstatus = upp Portiamo il prezzo di vendita del burro a 3.1 euro e risolviamo nuovamente il problema.
Caseificio: variabili in e fuori base Il risultato del problema modificato è il seguente: ampl: display x; x [*] := BURRO 1.46092 MOZZARELLA 8.95631 RICOTTA 23; ampl: display x.sstatus; x.sstatus [*] := BURRO bas MOZZARELLA bas RICOTTA bas; Le variabili associate ai tre prodotti sono in base. ampl: display latte_disponibile.sstatus, vinc_max_domanda.sstatus,operai_disponibili.sstatus; latte_disponibile.sstatus = upp vinc_max_domanda.sstatus [*] := BURRO bas MOZZARELLA bas RICOTTA upp; Le variabili di slack associate ai vincoli di domanda del burro e della mozzarella sono in base. operai_disponibili.sstatus = upp
Caseificio: range dei termini noti Quali sono i range di variabilità dei termini noti entro i quali la base ottima non cambia? ampl: display latte_disponibile.up, vinc_max_domanda.up,operai_disponibili.up; latte_disponibile.up = 1e+20 vinc_max_domanda.up [*] := BURRO 1e+20 MOZZARELLA 1e+20 RICOTTA 49.0196; operai_disponibili.up = 8.21724 ampl: display latte_disponibile.down, vinc_max_domanda.down,operai_disponibili.down; latte_disponibile.down = 101.74 vinc_max_domanda.down [*] := BURRO 0 MOZZARELLA 11.1479 RICOTTA 7.007; operai_disponibili.down = 3.2844
max 14x 1 +19x 2 + 27x 3 + 36x 4! (0.4 + 4*0.7) x 1! (0.2 + 4*0.5+ 2 * 0.5)x 2! s.t.! (0.1+ 4*0.1+ 2 * 0.3+ 9 * 0.4)x 3! (0.3+ 4*0.2 + 6 * 0.7)x 4! 6000 0.4x 1 + 0.2x 2 + 0.1x 3 + 0.3x 4 " 700 0.7x 1 + 0.5x 2 + 0.1x 3 + 0.2x 4 "1200 0.5x 2 + 0.3x 3 " 500 0.4x 3 " 200 0.7x 4 " 500 x 1 #15 x 2 #11 x 3 # 20 x 4 # 5 0.4x 1 + 0.7x 2 +1.1x 3 +1.3x 4 " 960 x # 0 Azienda dolciaria: Confetti zucchero mandorla latte cioccolato limone classico prod.min. doppio latte prod.min. al cioccolato prod.min. delizia al limone prod.min. Ore di lavorazione
Azienda dolciaria: Confetti
Azienda dolciaria: Confetti Il direttore dell azienda dolciaria ha chiesto il nostro aiuto per definire il piano di produzione che massimizza il profitto mensile ma anche per avere risposte alle seguenti domande: 1. Quali sono le risorse scarse e quali quelle abbondanti? 2. Di quanto aumenta il profitto dell azienda se si incrementa di 20kg la mandorla? E se invece si aumenta di 20kg la cioccolata? Ed infine di 20 kg lo zucchero? 3. Quale risorsa garantisce un tasso di aumento del profitto maggiore? 4. L azienda vuole valutare la possibilità di produrre un confetto quasi completamente fatto di mandorla. Sapendo che la produzione di 1Kg di questi confetti richiede 0.3 kg di zucchero e 0.9 kg di mandorla e che richieste 1 ora di lavorazione, qual è il prezzo di vendita che rende conveniente produrre questo nuovo confetto? 5. Quali sono i range di variabilità dei coefficienti di costo della funzione obiettivo entro i quali la base ottima non cambia? 6. Quali sono i range di variabilità dei termini noti entro i quali la base ottima non cambia?
Azienda dolciaria: Confetti Times (seconds): Input = 0.001211 Solve = 0.002279 Output = 0.000333 CPLEX 12.2.0.0: optimal solution; obective 18706.1 4 dual simplex iterations (1 in phase I) suffix up OUT; suffix down OUT; suffix current OUT; solve_result = solved ##################################### ############ Variables: ########### x [*] := ALCIOCCOLATO 20 CLASSICO 1563.62 DLATTE 11 DLIMONE 234.5; ########################################### ############ Slack Variables: ########### ingredienti_disponibili.slack [*] := CIOCCOLATO 192 LATTE 488.5 LIMONE 335.85 MANDORLA 51.0625 ZUCCHERO 0; vinc_min_domanda.slack [*] := ALCIOCCOLATO 0 CLASSICO 1548.62 DLATTE 0 DLIMONE 229.5; ore_disponibili.slack = 0 1 2 3 ##################################### ############ Dual Variables: ########### ingredienti_disponibili [*] := CIOCCOLATO 0 LATTE 0 LIMONE 0 MANDORLA 0 ZUCCHERO 4.4 ; vinc_min_domanda [*] := ALCIOCCOLATO -3 CLASSICO 0 DLATTE -0.9 DLIMONE 0 ; ore_disponibili = 22.6 ######################################### ############ Ranges Coefficienti: ########### x.up [*] := ALCIOCCOLATO 25.3 CLASSICO 16.8 DLATTE 16.7 DLIMONE 35.1 ; x.down [*] := ALCIOCCOLATO -1e+20 CLASSICO 9.44615 DLATTE -1e+20 DLIMONE 28.9; ########################## ####### Ranges termini noti: ########## ingredienti_disponibili.up [*] := CIOCCOLATO 1e+20 LATTE 1e+20 LIMONE 1e+20 MANDORLA 1e+20 ZUCCHERO 724.608; ingredienti_disponibili.down [*] := CIOCCOLATO 8 LATTE 11.5 LIMONE 164.15 MANDORLA 1148.94 ZUCCHERO 223.5; vinc_min_domanda.up [*] := ALCIOCCOLATO 224.25 CLASSICO 1563.62 DLATTE 174.4 DLIMONE 234.5; vinc_min_domanda.down [*] := ALCIOCCOLATO 0 CLASSICO -1e+20 DLATTE 0 DLIMONE -1e+20; ore_disponibili.up = 1439.79 ore_disponibili.down = 802.885