Example Models from the AMPL Book
Enhance your education with real world modeling examples.
For your convenience, you can copy and download all of the model, data and script files that appear as examples in the AMPL Book (second edition).
Preview & Download Options
Individual file downloads
Download a single file with all model, data and script files from the AMPL book (second edition).
Individual file downloads
Preview and download individual model, data and script files from either of the tables below.
Additional script files
Use the following links to see basic examples of programs written in the AMPL scripting language.Â
File (in alphabetical order)
Figure number
data; set ORIG := Coullard Daskin Hazen Hopp Iravani Linetsky Mehrotra Nelson Smilowitz Tamhane White ; set DEST := C118 C138 C140 C246 C250 C251 D237 D239 D241 M233 M239; param supply default 1 ; param demand default 1 ; param cost: C118 C138 C140 C246 C250 C251 D237 D239 D241 M233 M239 := Coullard 6 9 8 7 11 10 4 5 3 2 1 Daskin 11 8 7 6 9 10 1 5 4 2 3 Hazen 9 10 11 1 5 6 2 7 8 3 4 Hopp 11 9 8 10 6 5 1 7 4 2 3 Iravani 3 2 8 9 10 11 1 5 4 6 7 Linetsky 11 9 10 5 3 4 6 7 8 1 2 Mehrotra 6 11 10 9 8 7 1 2 5 4 3 Nelson 11 5 4 6 7 8 1 9 10 2 3 Smilowitz 11 9 10 8 6 5 7 3 4 1 2 Tamhane 5 6 9 8 4 3 7 10 11 2 1 White 11 9 8 4 6 5 3 10 7 2 1 ;
Figure: 3-2
set INPUT; # inputs set OUTPUT; # outputs param cost {INPUT} > 0; param in_min {INPUT} >= 0; param in_max {j in INPUT} >= in_min[j]; param out_min {OUTPUT} >= 0; param out_max {i in OUTPUT} >= out_min[i]; param io {OUTPUT,INPUT} >= 0; var X {j in INPUT} >= in_min[j], <= in_max[j]; minimize Total_Cost: sum {j in INPUT} cost[j] * X[j]; subject to Outputs {i in OUTPUT}: out_min[i] <= sum {j in INPUT} io[i,j] * X[j] <= out_max[i];
Figure: 2-4
# ---------------------------------------- # CUTTING STOCK USING PATTERNS # ---------------------------------------- param roll_width > 0; # width of raw rolls set WIDTHS; # set of widths to be cut param orders {WIDTHS} > 0; # number of each width to be cut param nPAT integer >= 0; # number of patterns set PATTERNS = 1..nPAT; # set of patterns param nbr {WIDTHS,PATTERNS} integer >= 0; check {j in PATTERNS}: sum {i in WIDTHS} i * nbr[i,j] <= roll_width; # defn of patterns: nbr[i,j] = number # of rolls of width i in pattern j var Cut {PATTERNS} integer >= 0; # rolls cut using each pattern minimize Number: # minimize total raw rolls cut sum {j in PATTERNS} Cut[j]; subject to Fill {i in WIDTHS}: sum {j in PATTERNS} nbr[i,j] * Cut[j] >= orders[i]; # for each width, total # rolls cut meets total orders # ---------------------------------------- # KNAPSACK SUBPROBLEM FOR CUTTING STOCK # ---------------------------------------- param price {WIDTHS} default 0.0; var Use {WIDTHS} integer >= 0; minimize Reduced_Cost: 1 - sum {i in WIDTHS} price[i] * Use[i]; subject to Width_Limit: sum {i in WIDTHS} i * Use[i] <= roll_width;
Figure: 14-2
data; param roll_width := 110 ; param: WIDTHS: orders := 20 48 45 35 50 24 55 10 75 8 ;
Figure: 14-4
model cut.mod; data cut.dat; option solver cplex, solution_round 6; option display_1col 0, display_transpose -10; problem Cutting_Opt: Cut, Number, Fill; option relax_integrality 1; problem Pattern_Gen: Use, Reduced_Cost, Width_Limit; option relax_integrality 0; let nPAT := 0; for {i in WIDTHS} { let nPAT := nPAT + 1; let nbr[i,nPAT] := floor (roll_width/i); let {i2 in WIDTHS: i2 <> i} nbr[i2,nPAT] := 0; } repeat { solve Cutting_Opt; let {i in WIDTHS} price[i] := Fill[i].dual; solve Pattern_Gen; if Reduced_Cost < -0.00001 then { let nPAT := nPAT + 1; let {i in WIDTHS} nbr[i,nPAT] := Use[i]; } else break; } display nbr, Cut; option Cutting_Opt.relax_integrality 0; solve Cutting_Opt; display Cut;
Figure: 14-3
problem Cutting_Opt; # ---------------------------------------- param nPAT integer >= 0, default 0; param roll_width; set PATTERNS = 1..nPAT; set WIDTHS; param orders {WIDTHS} > 0; param nbr {WIDTHS,PATTERNS} integer >= 0; check {j in PATTERNS}: sum {i in WIDTHS} i * nbr[i,j] <= roll_width; var Cut {PATTERNS} integer >= 0; minimize Number: sum {j in PATTERNS} Cut[j]; subject to Fill {i in WIDTHS}: sum {j in PATTERNS} nbr[i,j] * Cut[j] >= orders[i]; problem Pattern_Gen; # ---------------------------------------- param price {WIDTHS} default 0; var Use {WIDTHS} integer >= 0; minimize Reduced_Cost: 1 - sum {i in WIDTHS} price[i] * Use[i]; subject to Width_Limit: sum {i in WIDTHS} i * Use[i] <= roll_width;
Figure: 14-6
# ---------------------------------------- # GILMORE-GOMORY METHOD FOR # CUTTING STOCK PROBLEM # ---------------------------------------- option solver cplex; option solution_round 6; model cut2.mod; data cut.dat; problem Cutting_Opt; option relax_integrality 1; option presolve 0; problem Pattern_Gen; option relax_integrality 0; option presolve 1; let nPAT := 0; for {i in WIDTHS} { let nPAT := nPAT + 1; let nbr[i,nPAT] := floor (roll_width/i); let {i2 in WIDTHS: i2 <> i} nbr[i2,nPAT] := 0; }; repeat { solve Cutting_Opt; let {i in WIDTHS} price[i] := Fill[i].dual; solve Pattern_Gen; if Reduced_Cost < -0.00001 then { let nPAT := nPAT + 1; let {i in WIDTHS} nbr[i,nPAT] := Use[i]; } else break; }; display nbr; display Cut; option Cutting_Opt.relax_integrality 0; option Cutting_Opt.presolve 10; solve Cutting_Opt; display Cut;
set NUTR; set FOOD; param cost {FOOD} > 0; param f_min {FOOD} >= 0; param f_max {j in FOOD} >= f_min[j]; param n_min {NUTR} >= 0; param n_max {i in NUTR} >= n_min[i]; param amt {NUTR,FOOD} >= 0; var Buy {j in FOOD} >= f_min[j], <= f_max[j]; minimize Total_Cost: sum {j in FOOD} cost[j] * Buy[j]; subject to Diet {i in NUTR}: n_min[i] <= sum {j in FOOD} amt[i,j] * Buy[j] <= n_max[i];
Figure: 2-1
data; set NUTR := A B1 B2 C ; set FOOD := BEEF CHK FISH HAM MCH MTL SPG TUR ; param: cost f_min f_max := BEEF 3.19 0 100 CHK 2.59 0 100 FISH 2.29 0 100 HAM 2.89 0 100 MCH 1.89 0 100 MTL 1.99 0 100 SPG 1.99 0 100 TUR 2.49 0 100 ; param: n_min n_max := A 700 10000 C 700 10000 B1 700 10000 B2 700 10000 ; param amt (tr): A C B1 B2 := BEEF 60 20 10 15 CHK 8 0 20 20 FISH 8 10 15 10 HAM 40 40 35 10 MCH 15 35 15 15 MTL 70 30 15 15 SPG 25 50 25 15 TUR 60 20 15 10 ;
Figure: 2-2
data; set NUTR := A B1 B2 C NA CAL ; set FOOD := BEEF CHK FISH HAM MCH MTL SPG TUR ; param: cost f_min f_max := BEEF 3.19 2 10 CHK 2.59 2 10 FISH 2.29 2 10 HAM 2.89 2 10 MCH 1.89 2 10 MTL 1.99 2 10 SPG 1.99 2 10 TUR 2.49 2 10 ; param: n_min n_max := A 700 20000 C 700 20000 B1 700 20000 B2 700 20000 NA 0 40000 CAL 16000 24000 ; param amt (tr): A C B1 B2 NA CAL := BEEF 60 20 10 15 938 295 CHK 8 0 20 20 2180 770 FISH 8 10 15 10 945 440 HAM 40 40 35 10 278 430 MCH 15 35 15 15 1182 315 MTL 70 30 15 15 896 400 SPG 25 50 25 15 1329 370 TUR 60 20 15 10 1397 450 ;
Figure: 2-3
data; set NUTR := A B1 B2 C NA CAL ; set FOOD := BEEF CHK FISH HAM MCH MTL SPG TUR ; param: cost f_min f_max := BEEF 3.19 2 10 CHK 2.59 2 10 FISH 2.29 2 10 HAM 2.89 2 10 MCH 1.89 2 10 MTL 1.99 2 10 SPG 1.99 2 10 TUR 2.49 2 10 ; param: n_min n_max := A 700 20000 C 700 20000 B1 700 20000 B2 700 20000 NA 0 50000 CAL 16000 24000 ; param amt (tr): A C B1 B2 NA CAL := BEEF 60 20 10 15 938 295 CHK 8 0 20 20 2180 770 FISH 8 10 15 10 945 440 HAM 40 40 35 10 278 430 MCH 15 35 15 15 1182 315 MTL 70 30 15 15 896 400 SPG 25 50 25 15 1329 370 TUR 60 20 15 10 1397 450 ;
Figure: 2-3
set MINREQ; # nutrients with minimum requirements set MAXREQ; # nutrients with maximum requirements set NUTR = MINREQ union MAXREQ; # nutrients set FOOD; # foods param cost {FOOD} > 0; param f_min {FOOD} >= 0; param f_max {j in FOOD} >= f_min[j]; param n_min {MINREQ} >= 0; param n_max {MAXREQ} >= 0; param amt {NUTR,FOOD} >= 0; var Buy {j in FOOD} >= f_min[j], <= f_max[j]; minimize Total_Cost: sum {j in FOOD} cost[j] * Buy[j]; subject to Diet_Min {i in MINREQ}: sum {j in FOOD} amt[i,j] * Buy[j] >= n_min[i]; subject to Diet_Max {i in MAXREQ}: sum {j in FOOD} amt[i,j] * Buy[j] <= n_max[i];
Figure: 5-1
data; set MINREQ := A B1 B2 C CAL ; set MAXREQ := A NA CAL ; set FOOD := BEEF CHK FISH HAM MCH MTL SPG TUR ; param: cost f_min f_max := BEEF 3.19 2 10 CHK 2.59 2 10 FISH 2.29 2 10 HAM 2.89 2 10 MCH 1.89 2 10 MTL 1.99 2 10 SPG 1.99 2 10 TUR 2.49 2 10 ; param: n_min n_max := A 700 20000 C 700 . B1 0 . B2 0 . NA . 50000 CAL 16000 24000 ; param amt (tr): A C B1 B2 NA CAL := BEEF 60 20 10 15 938 295 CHK 8 0 20 20 2180 770 FISH 8 10 15 10 945 440 HAM 40 40 35 10 278 430 MCH 15 35 15 15 1182 315 MTL 70 30 15 15 896 400 SPG 25 50 25 15 1329 370 TUR 60 20 15 10 1397 450 ;
Figure: 5-2
set PROD; # products set ACT; # activities param cost {ACT} > 0; # cost per unit of each activity param demand {PROD} >= 0; # units of demand for each product param io {PROD,ACT} >= 0; # units of each product from # 1 unit of each activity var Price {i in PROD}; var Level {j in ACT}; subject to Pri_Compl {i in PROD}: Price[i] >= 0 complements sum {j in ACT} io[i,j] * Level[j] >= demand[i]; subject to Lev_Compl {j in ACT}: Level[j] >= 0 complements sum {i in PROD} Price[i] * io[i,j] <= cost[j];
Figure: 19-3
data; param: ACT: cost := P1 2450 P1a 1290 P2 1850 P2a 3700 P2b 2150 P3 2200 P3c 2370 P4 2170 ; param: PROD: demand := AA1 70000 AC1 80000 BC1 90000 BC2 70000 NA2 400000 NA3 800000 ; param io (tr): AA1 AC1 BC1 BC2 NA2 NA3 := P1 60 20 10 15 938 295 P1a 8 0 20 20 1180 770 P2 8 10 15 10 945 440 P2a 40 40 35 10 278 430 P2b 15 35 15 15 1182 315 P3 70 30 15 15 896 400 P3c 25 40 30 30 1029 370 P4 60 20 15 10 1397 450 ;
Figure: 19-2
set PROD; # products set ACT; # activities param cost {ACT} > 0; # cost per unit of each activity param demand {PROD} >= 0; # units of demand for each product param io {PROD,ACT} >= 0; # units of each product from # 1 unit of each activity var Level {j in ACT} >= 0; minimize Total_Cost: sum {j in ACT} cost[j] * Level[j]; subject to Demand {i in PROD}: sum {j in ACT} io[i,j] * Level[j] >= demand[i];
Figure: 19-1
set PROD; # products set ACT; # activities param cost {ACT} > 0; # cost per unit of each activity param demand {PROD} >= 0; # units of demand for each product param io {PROD,ACT} >= 0; # units of each product from # 1 unit of each activity param level_min {ACT} > 0; # min allowed level for each activity param level_max {ACT} > 0; # max allowed level for each activity var Price {i in PROD}; var Level {j in ACT}; subject to Pri_Compl {i in PROD}: Price[i] >= 0 complements sum {j in ACT} io[i,j] * Level[j] >= demand[i]; subject to Lev_Compl {j in ACT}: level_min[j] <= Level[j] <= level_max[j] complements cost[j] - sum {i in PROD} Price[i] * io[i,j];
Figure: 19-4
data; param: ACT: cost level_min level_max := P1 2450 240 1000 P1a 1290 270 1000 P2 1850 220 1000 P2a 3700 260 1000 P2b 2150 200 1000 P3 2200 260 1000 P3c 2370 220 1000 P4 2170 240 1000 ; param: PROD: demand := AA1 70000 AC1 80000 BC1 90000 BC2 70000 NA2 400000 NA3 800000 ; param io (tr): AA1 AC1 BC1 BC2 NA2 NA3 := P1 60 20 10 15 938 295 P1a 8 0 20 20 1180 770 P2 8 10 15 10 945 440 P2a 40 40 35 10 278 430 P2b 15 35 15 15 1182 315 P3 70 30 15 15 896 400 P3c 25 40 30 30 1029 370 P4 60 20 15 10 1397 450 ;
set PROD; # products set ACT; # activities param cost {ACT} > 0; # cost per unit of each activity param demand {PROD} >= 0; # units of demand for each product param io {PROD,ACT} >= 0; # units of each product from 1 unit of each activity param level_min {ACT} > 0; # max allowed level for each activity param level_max {ACT} > 0; # max allowed level for each activity var Level {j in ACT} >= level_min[j], <= level_max[j]; minimize Total_Cost: sum {j in ACT} cost[j] * Level[j]; subject to Demand {i in PROD}: sum {j in ACT} io[i,j] * Level[j] >= demand[i];
set PROD; # products set ACT; # activities param cost {ACT} > 0; # cost per unit of each activity param io {PROD,ACT} >= 0; # units of each product from # 1 unit of each activity param demzero {PROD} > 0; # intercept and slope of the demand param demrate {PROD} >= 0; # as a function of price var Price {i in PROD}; var Level {j in ACT}; subject to Pri_Compl {i in PROD}: Price[i] >= 0 complements sum {j in ACT} io[i,j] * Level[j] >= demzero[i] - demrate[i] * Price[i]; subject to Lev_Compl {j in ACT}: Level[j] >= 0 complements sum {i in PROD} Price[i] * io[i,j] <= cost[j];
Figure: 19-5
data; param: ACT: cost := P1 2450 P1a 1290 P2 1850 P2a 3700 P2b 2150 P3 2200 P3c 2370 P4 2170 ; param: PROD: demzero demrate := AA1 70000 500 AC1 80000 500 BC1 90000 500 BC2 70000 500 NA2 400000 500 NA3 800000 500 ; param io (tr): AA1 AC1 BC1 BC2 NA2 NA3 := P1 60 20 10 15 938 295 P1a 8 0 20 20 1180 770 P2 8 10 15 10 945 440 P2a 40 40 35 10 278 430 P2b 15 35 15 15 1182 315 P3 70 30 15 15 896 400 P3c 25 40 30 30 1029 370 P4 60 20 15 10 1397 450 ;
set MAT; # materials set ACT; # activities param io {MAT,ACT}; # input-output coefficients param revenue {ACT}; param act_min {ACT} >= 0; param act_max {j in ACT} >= act_min[j]; maximize Net_Profit; subject to Balance {i in MAT}: to_come = 0; var Run {j in ACT} >= act_min[j], <= act_max[j], obj Net_Profit revenue[j], coeff {i in MAT} Balance[i] io[i,j];
Figure: 16-2
set MAT; # materials set ACT; # activities param io {MAT,ACT}; # input-output coefficients set MATF within MAT; # finished materials param revenue {MATF} >= 0; param sell_min {MATF} >= 0; param sell_max {i in MATF} >= sell_min[i]; param cost {ACT} >= 0; param act_min {ACT} >= 0; param act_max {j in ACT} >= act_min[j]; maximize Net_Profit; subject to Balance {i in MAT}: to_come = 0; var Run {j in ACT} >= act_min[j], <= act_max[j], obj Net_Profit -cost[j], coeff {i in MAT} Balance[i] io[i,j]; var Sell {i in MATF} >= sell_min[i], <= sell_max[i], obj Net_Profit revenue[i], coeff Balance[i] -1;
Figure: 16-3
set MAT; # materials set ACT; # activities param io {MAT,ACT}; # input-output coefficients param revenue {ACT}; param act_min {ACT} >= 0; param act_max {j in ACT} >= act_min[j]; var Run {j in ACT} >= act_min[j], <= act_max[j]; maximize Net_Profit: sum {j in ACT} revenue[j] * Run[j]; subject to Balance {i in MAT}: sum {j in ACT} io[i,j] * Run[j] = 0;
Figure: 16-1
set PEOPLE; set PROJECTS; param supply {PEOPLE} >= 0; # hours each person is available param demand {PROJECTS} >= 0; # hours each project requires check: sum {i in PEOPLE} supply[i] = sum {j in PROJECTS} demand[j]; param cost {PEOPLE,PROJECTS} >= 0; # cost per hour of work param limit {PEOPLE,PROJECTS} >= 0; # maximum contributions # to projects var M; var Assign {i in PEOPLE, j in PROJECTS} >= 0, <= limit[i,j]; minimize Max_Cost: M; subject to M_def {i in PEOPLE}: M >= sum {j in PROJECTS} cost[i,j] * Assign[i,j]; subject to Supply {i in PEOPLE}: sum {j in PROJECTS} Assign[i,j] = supply[i]; subject to Demand {j in PROJECTS}: sum {i in PEOPLE} Assign[i,j] = demand[j];
Figure: 17-9
set ORIG; # origins set DEST; # destinations set PROD; # products param supply {ORIG,PROD} >= 0; # amounts available at origins param demand {DEST,PROD} >= 0; # amounts required at destinations check {p in PROD}: sum {i in ORIG} supply[i,p] = sum {j in DEST} demand[j,p]; param limit {ORIG,DEST} >= 0; param cost {ORIG,DEST,PROD} >= 0; # shipment costs per unit var Trans {ORIG,DEST,PROD} >= 0; # units to be shipped minimize Total_Cost: sum {i in ORIG, j in DEST, p in PROD} cost[i,j,p] * Trans[i,j,p]; subject to Supply {i in ORIG, p in PROD}: sum {j in DEST} Trans[i,j,p] = supply[i,p]; subject to Demand {j in DEST, p in PROD}: sum {i in ORIG} Trans[i,j,p] = demand[j,p]; subject to Multi {i in ORIG, j in DEST}: sum {p in PROD} Trans[i,j,p] <= limit[i,j];
Figure: 4-1
data; set ORIG := GARY CLEV PITT ; set DEST := FRA DET LAN WIN STL FRE LAF ; set PROD := bands coils plate ; param supply (tr): GARY CLEV PITT := bands 400 700 800 coils 800 1600 1800 plate 200 300 300 ; param demand (tr): FRA DET LAN WIN STL FRE LAF := bands 300 300 100 75 650 225 250 coils 500 750 400 250 950 850 500 plate 100 100 0 50 200 100 250 ; param limit default 625 ; param cost := [*,*,bands]: FRA DET LAN WIN STL FRE LAF := GARY 30 10 8 10 11 71 6 CLEV 22 7 10 7 21 82 13 PITT 19 11 12 10 25 83 15 [*,*,coils]: FRA DET LAN WIN STL FRE LAF := GARY 39 14 11 14 16 82 8 CLEV 27 9 12 9 26 95 17 PITT 24 14 17 13 28 99 20 [*,*,plate]: FRA DET LAN WIN STL FRE LAF := GARY 41 15 12 16 17 86 8 CLEV 29 9 13 9 28 99 18 PITT 26 14 17 13 31 104 20 ;
Figure: 4-2
set ORIG; # origins set DEST; # destinations set PROD; # products set orig {PROD} within ORIG; set dest {PROD} within DEST; set links {p in PROD} = orig[p] cross dest[p]; param supply {p in PROD, orig[p]} >= 0; # available at origins param demand {p in PROD, dest[p]} >= 0; # required at destinations check {p in PROD}: sum {i in orig[p]} supply[p,i] = sum {j in dest[p]} demand[p,j]; param limit {ORIG,DEST} >= 0; param cost {p in PROD, links[p]} >= 0; # shipment costs per unit var Trans {p in PROD, links[p]} >= 0; # units to be shipped minimize Total_Cost: sum {p in PROD, (i,j) in links[p]} cost[p,i,j] * Trans[p,i,j]; subject to Supply {p in PROD, i in orig[p]}: sum {j in dest[p]} Trans[p,i,j] = supply[p,i]; subject to Demand {p in PROD, j in dest[p]}: sum {i in orig[p]} Trans[p,i,j] = demand[p,j]; subject to Multi {i in ORIG, j in DEST}: sum {p in PROD: (i,j) in links[p]} Trans[p,i,j] <= limit[i,j];
Figure: 6-5
set ORIG; # origins set DEST; # destinations set PROD; # products param supply {ORIG,PROD} >= 0; # amounts available at origins param demand {DEST,PROD} >= 0; # amounts required at destinations check {p in PROD}: sum {i in ORIG} supply[i,p] = sum {j in DEST} demand[j,p]; param limit {ORIG,DEST} >= 0; # maximum shipments on routes param vcost {ORIG,DEST,PROD} >= 0; # variable shipment cost on routes var Trans {ORIG,DEST,PROD} >= 0; # units to be shipped param fcost {ORIG,DEST} >= 0; # fixed cost for using a route var Use {ORIG,DEST} binary; # = 1 only for routes used minimize Total_Cost: sum {i in ORIG, j in DEST, p in PROD} vcost[i,j,p] * Trans[i,j,p] + sum {i in ORIG, j in DEST} fcost[i,j] * Use[i,j]; subject to Supply {i in ORIG, p in PROD}: sum {j in DEST} Trans[i,j,p] = supply[i,p]; subject to Demand {j in DEST, p in PROD}: sum {i in ORIG} Trans[i,j,p] = demand[j,p]; subject to Multi {i in ORIG, j in DEST}: sum {p in PROD} Trans[i,j,p] <= limit[i,j] * Use[i,j];
Figure: 20-1a
data; set ORIG := GARY CLEV PITT ; set DEST := FRA DET LAN WIN STL FRE LAF ; set PROD := bands coils plate ; param supply (tr): GARY CLEV PITT := bands 400 700 800 coils 800 1600 1800 plate 200 300 300 ; param demand (tr): FRA DET LAN WIN STL FRE LAF := bands 300 300 100 75 650 225 250 coils 500 750 400 250 950 850 500 plate 100 100 0 50 200 100 250 ; param limit default 625 ; param vcost := [*,*,bands]: FRA DET LAN WIN STL FRE LAF := GARY 30 10 8 10 11 71 6 CLEV 22 7 10 7 21 82 13 PITT 19 11 12 10 25 83 15 [*,*,coils]: FRA DET LAN WIN STL FRE LAF := GARY 39 14 11 14 16 82 8 CLEV 27 9 12 9 26 95 17 PITT 24 14 17 13 28 99 20 [*,*,plate]: FRA DET LAN WIN STL FRE LAF := GARY 41 15 12 16 17 86 8 CLEV 29 9 13 9 28 99 18 PITT 26 14 17 13 31 104 20 ; param fcost: FRA DET LAN WIN STL FRE LAF := GARY 3000 1200 1200 1200 2500 3500 2500 CLEV 2000 1000 1500 1200 2500 3000 2200 PITT 2000 1200 1500 1500 2500 3500 2200 ;
Figure: 20-1b
set ORIG; # origins set DEST; # destinations set PROD; # products param supply {ORIG,PROD} >= 0; # amounts available at origins param demand {DEST,PROD} >= 0; # amounts required at destinations check {p in PROD}: sum {i in ORIG} supply[i,p] = sum {j in DEST} demand[j,p]; param limit {ORIG,DEST} >= 0; # maximum shipments on routes param minload >= 0; # minimum nonzero shipment param vcost {ORIG,DEST,PROD} >= 0; # variable shipment cost on routes var Trans {ORIG,DEST,PROD} >= 0; # units to be shipped param fcost {ORIG,DEST} >= 0; # fixed cost for using a route var Use {ORIG,DEST} binary; # = 1 only for routes used minimize Total_Cost: sum {i in ORIG, j in DEST, p in PROD} vcost[i,j,p] * Trans[i,j,p] + sum {i in ORIG, j in DEST} fcost[i,j] * Use[i,j]; subject to Supply {i in ORIG, p in PROD}: sum {j in DEST} Trans[i,j,p] = supply[i,p]; subject to Demand {j in DEST, p in PROD}: sum {i in ORIG} Trans[i,j,p] = demand[j,p]; subject to Multi {i in ORIG, j in DEST}: sum {p in PROD} Trans[i,j,p] <= limit[i,j] * Use[i,j]; subject to Min_Ship {i in ORIG, j in DEST}: sum {p in PROD} Trans[i,j,p] >= minload * Use[i,j];
data; set ORIG := GARY CLEV PITT ; set DEST := FRA DET LAN WIN STL FRE LAF ; set PROD := bands coils plate ; param supply (tr): GARY CLEV PITT := bands 400 700 800 coils 800 1600 1800 plate 200 300 300 ; param demand (tr): FRA DET LAN WIN STL FRE LAF := bands 300 300 100 75 650 225 250 coils 500 750 400 250 950 850 500 plate 100 100 0 50 200 100 250 ; param limit default 625 ; param minload := 375 ; param fcost: FRA DET LAN WIN STL FRE LAF := GARY 3000 1200 1200 1200 2500 3500 2500 CLEV 2000 1000 1500 1200 2500 3000 2200 PITT 2000 1200 1500 1500 2500 3500 2200 ; param vcost := [*,*,bands]: FRA DET LAN WIN STL FRE LAF := GARY 30 10 8 10 11 71 6 CLEV 22 7 10 7 21 82 13 PITT 19 11 12 10 25 83 15 [*,*,coils]: FRA DET LAN WIN STL FRE LAF := GARY 39 14 11 14 16 82 8 CLEV 27 9 12 9 26 95 17 PITT 24 14 17 13 28 99 20 [*,*,plate]: FRA DET LAN WIN STL FRE LAF := GARY 41 15 12 16 17 86 8 CLEV 29 9 13 9 28 99 18 PITT 26 14 17 13 31 104 20 ;
data; set ORIG := GARY CLEV PITT ; set DEST := FRA DET LAN WIN STL FRE LAF ; set PROD := bands coils plate ; param supply (tr): GARY CLEV PITT := bands 400 700 800 coils 800 1600 1800 plate 200 300 300 ; param demand (tr): FRA DET LAN WIN STL FRE LAF := bands 300 300 100 75 650 225 250 coils 500 750 400 250 950 850 500 plate 100 100 0 50 200 100 250 ; param limit default 625 ; param minload := 375 ; param fcost: FRA DET LAN WIN STL FRE LAF := GARY 3000 1200 1200 1200 2500 3500 2500 CLEV 2000 1000 1500 1200 2500 3000 2200 PITT 2000 1200 1500 1500 2500 3500 2200 ; param vcost := [*,*,bands]: FRA DET LAN WIN STL FRE LAF := GARY 30 10 8 10 11 71 6 CLEV 22 7 10 7 21 82 13 PITT 19 11 12 10 25 83 15 [*,*,coils]: FRA DET LAN WIN STL FRE LAF := GARY 39 14 11 14 16 82 8 CLEV 27 9 12 9 26 95 17 PITT 24 14 17 13 28 99 20 [*,*,plate]: FRA DET LAN WIN STL FRE LAF := GARY 41 15 12 16 17 86 8 CLEV 29 9 13 9 28 99 18 PITT 26 14 17 13 31 104 20 ;
set ORIG; # origins set DEST; # destinations set PROD; # products param supply {ORIG,PROD} >= 0; # amounts available at origins param demand {DEST,PROD} >= 0; # amounts required at destinations check {p in PROD}: sum {i in ORIG} supply[i,p] = sum {j in DEST} demand[j,p]; param limit {ORIG,DEST} >= 0; # maximum shipments on routes param minload >= 0; # minimum nonzero shipment param maxserve integer > 0; # maximum destinations served param vcost {ORIG,DEST,PROD} >= 0; # variable shipment cost on routes var Trans {ORIG,DEST,PROD} >= 0; # units to be shipped param fcost {ORIG,DEST} >= 0; # fixed cost for using a route var Use {ORIG,DEST} binary; # = 1 only for routes used minimize Total_Cost: sum {i in ORIG, j in DEST, p in PROD} vcost[i,j,p] * Trans[i,j,p] + sum {i in ORIG, j in DEST} fcost[i,j] * Use[i,j]; subject to Supply {i in ORIG, p in PROD}: sum {j in DEST} Trans[i,j,p] = supply[i,p]; subject to Max_Serve {i in ORIG}: sum {j in DEST} Use[i,j] <= maxserve; subject to Demand {j in DEST, p in PROD}: sum {i in ORIG} Trans[i,j,p] = demand[j,p]; subject to Multi {i in ORIG, j in DEST}: sum {p in PROD} Trans[i,j,p] <= limit[i,j] * Use[i,j]; subject to Min_Ship {i in ORIG, j in DEST}: sum {p in PROD} Trans[i,j,p] >= minload * Use[i,j];
Figure: 20-2a
data; set ORIG := GARY CLEV PITT ; set DEST := FRA DET LAN WIN STL FRE LAF ; set PROD := bands coils plate ; param supply (tr): GARY CLEV PITT := bands 400 700 800 coils 800 1600 1800 plate 200 300 300 ; param demand (tr): FRA DET LAN WIN STL FRE LAF := bands 300 300 100 75 650 225 250 coils 500 750 400 250 950 850 500 plate 100 100 0 50 200 100 250 ; param limit default 625 ; param vcost := [*,*,bands]: FRA DET LAN WIN STL FRE LAF := GARY 30 10 8 10 11 71 6 CLEV 22 7 10 7 21 82 13 PITT 19 11 12 10 25 83 15 [*,*,coils]: FRA DET LAN WIN STL FRE LAF := GARY 39 14 11 14 16 82 8 CLEV 27 9 12 9 26 95 17 PITT 24 14 17 13 28 99 20 [*,*,plate]: FRA DET LAN WIN STL FRE LAF := GARY 41 15 12 16 17 86 8 CLEV 29 9 13 9 28 99 18 PITT 26 14 17 13 31 104 20 ; param fcost: FRA DET LAN WIN STL FRE LAF := GARY 3000 1200 1200 1200 2500 3500 2500 CLEV 2000 1000 1500 1200 2500 3000 2200 PITT 2000 1200 1500 1500 2500 3500 2200 ; param minload := 375 ; param maxserve := 5 ;
Figure: 20-2b
set CITIES; set LINKS within (CITIES cross CITIES); param supply {CITIES} >= 0; # amounts available at cities param demand {CITIES} >= 0; # amounts required at cities check: sum {i in CITIES} supply[i] = sum {j in CITIES} demand[j]; param cost {LINKS} >= 0; # shipment costs/1000 packages param capacity {LINKS} >= 0; # max packages that can be shipped var Ship {(i,j) in LINKS} >= 0, <= capacity[i,j]; # packages to be shipped minimize Total_Cost: sum {(i,j) in LINKS} cost[i,j] * Ship[i,j]; subject to Balance {k in CITIES}: supply[k] + sum {(i,k) in LINKS} Ship[i,k] = demand[k] + sum {(k,j) in LINKS} Ship[k,j];
Figure: 15-2a
data; set CITIES := PITT NE SE BOS EWR BWI ATL MCO ; set LINKS := (PITT,NE) (PITT,SE) (NE,BOS) (NE,EWR) (NE,BWI) (SE,EWR) (SE,BWI) (SE,ATL) (SE,MCO); param supply default 0 := PITT 450 ; param demand default 0 := BOS 90, EWR 120, BWI 120, ATL 70, MCO 50; param: cost capacity := PITT NE 2.5 250 PITT SE 3.5 250 NE BOS 1.7 100 NE EWR 0.7 100 NE BWI 1.3 100 SE EWR 1.3 100 SE BWI 0.8 100 SE ATL 0.2 100 SE MCO 2.1 100 ;
Figure: 15-2b
set CITIES; set LINKS within (CITIES cross CITIES); param supply {CITIES} >= 0; # amounts available at cities param demand {CITIES} >= 0; # amounts required at cities check: sum {i in CITIES} supply[i] = sum {j in CITIES} demand[j]; param cost {LINKS} >= 0; # shipment costs/1000 packages param capacity {LINKS} >= 0; # max packages that can be shipped minimize Total_Cost; node Balance {k in CITIES}: net_in = demand[k] - supply[k]; arc Ship {(i,j) in LINKS} >= 0, <= capacity[i,j], from Balance[i], to Balance[j], obj Total_Cost cost[i,j];
Figure: 15-10
param p_city symbolic; set D_CITY; set W_CITY; set DW_LINKS within (D_CITY cross W_CITY); param p_supply >= 0; # amount available at plant param w_demand {W_CITY} >= 0; # amounts required at warehouses check: p_supply = sum {k in W_CITY} w_demand[k]; set CITIES = {p_city} union D_CITY union W_CITY; set LINKS = ({p_city} cross D_CITY) union DW_LINKS; param supply {k in CITIES} = if k = p_city then p_supply else 0; param demand {k in CITIES} = if k in W_CITY then w_demand[k] else 0; ### Remainder same as general transshipment model ### param cost {LINKS} >= 0; # shipment costs/1000 packages param capacity {LINKS} >= 0; # max packages that can be shipped var Ship {(i,j) in LINKS} >= 0, <= capacity[i,j]; # packages to be shipped minimize Total_Cost: sum {(i,j) in LINKS} cost[i,j] * Ship[i,j]; subject to Balance {k in CITIES}: supply[k] + sum {(i,k) in LINKS} Ship[i,k] = demand[k] + sum {(k,j) in LINKS} Ship[k,j];
Figure: 15-3a
data; param p_city := PITT ; set D_CITY := NE SE ; set W_CITY := BOS EWR BWI ATL MCO ; set DW_LINKS := (NE,BOS) (NE,EWR) (NE,BWI) (SE,EWR) (SE,BWI) (SE,ATL) (SE,MCO); param p_supply := 450 ; param w_demand := BOS 90, EWR 120, BWI 120, ATL 70, MCO 50; param: cost capacity := PITT NE 2.5 250 PITT SE 3.5 250 NE BOS 1.7 100 NE EWR 0.7 100 NE BWI 1.3 100 SE EWR 1.3 100 SE BWI 0.8 100 SE ATL 0.2 100 SE MCO 2.1 100 ;
Figure: 15-3b
set D_CITY; set W_CITY; set DW_LINKS within (D_CITY cross W_CITY); param p_supply >= 0; # amount available at plant param w_demand {W_CITY} >= 0; # amounts required at warehouses check: p_supply = sum {j in W_CITY} w_demand[j]; param pd_cost {D_CITY} >= 0; # shipment costs/1000 packages param dw_cost {DW_LINKS} >= 0; param pd_cap {D_CITY} >= 0; # max packages that can be shipped param dw_cap {DW_LINKS} >= 0; var PD_Ship {i in D_CITY} >= 0, <= pd_cap[i]; var DW_Ship {(i,j) in DW_LINKS} >= 0, <= dw_cap[i,j]; # packages to be shipped minimize Total_Cost: sum {i in D_CITY} pd_cost[i] * PD_Ship[i] + sum {(i,j) in DW_LINKS} dw_cost[i,j] * DW_Ship[i,j]; subject to P_Bal: sum {i in D_CITY} PD_Ship[i] = p_supply; subject to D_Bal {i in D_CITY}: PD_Ship[i] = sum {(i,j) in DW_LINKS} DW_Ship[i,j]; subject to W_Bal {j in W_CITY}: sum {(i,j) in DW_LINKS} DW_Ship[i,j] = w_demand[j];
Figure: 15-4a
data; set D_CITY := NE SE ; set W_CITY := BOS EWR BWI ATL MCO ; set DW_LINKS := (NE,BOS) (NE,EWR) (NE,BWI) (SE,EWR) (SE,BWI) (SE,ATL) (SE,MCO); param p_supply := 450 ; param w_demand := BOS 90, EWR 120, BWI 120, ATL 70, MCO 50; param: pd_cost pd_cap := NE 2.5 250 SE 3.5 250 ; param: dw_cost dw_cap := NE BOS 1.7 100 NE EWR 0.7 100 NE BWI 1.3 100 SE EWR 1.3 100 SE BWI 0.8 100 SE ATL 0.2 100 SE MCO 2.1 100 ;
Figure: 15-4b
set D_CITY; set W_CITY; set DW_LINKS within (D_CITY cross W_CITY); param p_supply >= 0; # amount available at plant param w_demand {W_CITY} >= 0; # amounts required at warehouses check: p_supply = sum {j in W_CITY} w_demand[j]; param pd_cost {D_CITY} >= 0; # shipment costs/1000 packages param dw_cost {DW_LINKS} >= 0; param pd_cap {D_CITY} >= 0; # max packages that can be shipped param dw_cap {DW_LINKS} >= 0; minimize Total_Cost; node Plant: net_out = p_supply; node Dist {i in D_CITY}; node Whse {j in W_CITY}: net_in = w_demand[j]; arc PD_Ship {i in D_CITY} >= 0, <= pd_cap[i], from Plant, to Dist[i], obj Total_Cost pd_cost[i]; arc DW_Ship {(i,j) in DW_LINKS} >= 0, <= dw_cap[i,j], from Dist[i], to Whse[j], obj Total_Cost dw_cost[i,j];
Figure: 15-11
set PEOPLE; set PROJECTS; set ABILITIES within (PEOPLE cross PROJECTS); param supply {PEOPLE} >= 0; # hours each person is available param demand {PROJECTS} >= 0; # hours each project requires check: sum {i in PEOPLE} supply[i] = sum {j in PROJECTS} demand[j]; param cost {ABILITIES} >= 0; # cost per hour of work param limit {ABILITIES} >= 0; # maximum contributions to projects var Assign {(i,j) in ABILITIES} >= 0, <= limit[i,j]; minimize Total_Cost: sum {(i,j) in ABILITIES} cost[i,j] * Assign[i,j]; subject to Supply {i in PEOPLE}: sum {(i,j) in ABILITIES} Assign[i,j] = supply[i]; subject to Demand {j in PROJECTS}: sum {(i,j) in ABILITIES} Assign[i,j] = demand[j];
Figure: 15-9
set CITIES; set LINKS within (CITIES cross CITIES); set PRODS; param supply {PRODS,CITIES} >= 0; # amounts available at cities param demand {PRODS,CITIES} >= 0; # amounts required at cities check {p in PRODS}: sum {i in CITIES} supply[p,i] = sum {j in CITIES} demand[p,j]; param cost {PRODS,LINKS} >= 0; # shipment costs/1000 packages param capacity {PRODS,LINKS} >= 0; # max packages shipped of product set FEEDS; param yield {PRODS,FEEDS} >= 0; # amounts derived from feedstocks param limit {FEEDS,CITIES} >= 0; # feedstocks available at cities minimize Total_Cost; var Feed {f in FEEDS, k in CITIES} >= 0, <= limit[f,k]; node Balance {p in PRODS, k in CITIES}: net_out = supply[p,k] - demand[p,k] + sum {f in FEEDS} yield[p,f] * Feed[f,k]; arc Ship {p in PRODS, (i,j) in LINKS} >= 0, <= capacity[p,i,j], from Balance[p,i], to Balance[p,j], obj Total_Cost cost[p,i,j];
Figure: 15-14
set INTER; # intersections param entr symbolic in INTER; # entrance to road network param exit symbolic in INTER, <> entr; # exit from road network set ROADS within (INTER diff {exit}) cross (INTER diff {entr}); param cap {ROADS} >= 0; # capacities var Traff {(i,j) in ROADS} >= 0, <= cap[i,j]; # traffic loads maximize Entering_Traff: sum {(entr,j) in ROADS} Traff[entr,j]; subject to Balance {k in INTER diff {entr,exit}}: sum {(i,k) in ROADS} Traff[i,k] = sum {(k,j) in ROADS} Traff[k,j]; data; set INTER := a b c d e f g ; param entr := a ; param exit := g ; param: ROADS: cap := a b 50, a c 100 b d 40, b e 20 c d 60, c f 20 d e 50, d f 60 e g 70, f g 70 ;
Figure: 15-6
set INTER; # intersections param entr symbolic in INTER; # entrance to road network param exit symbolic in INTER, <> entr; # exit from road network set ROADS within (INTER diff {exit}) cross (INTER diff {entr}); param cap {ROADS} >= 0; # capacities of roads node Intersection {k in INTER}; arc Traff_In >= 0, to Intersection[entr]; arc Traff_Out >= 0, from Intersection[exit]; arc Traff {(i,j) in ROADS} >= 0, <= cap[i,j], from Intersection[i], to Intersection[j]; maximize Entering_Traff: Traff_In; data; set INTER := a b c d e f g ; param entr := a ; param exit := g ; param: ROADS: cap := a b 50, a c 100 b d 40, b e 20 c d 60, c f 20 d e 50, d f 60 e g 70, f g 70 ;
Figure: 15-12
set CITIES; set LINKS within (CITIES cross CITIES); set PRODS; param supply {CITIES,PRODS} >= 0; # amounts available at cities param demand {CITIES,PRODS} >= 0; # amounts required at cities check {p in PRODS}: sum {i in CITIES} supply[i,p] = sum {j in CITIES} demand[j,p]; param cost {LINKS,PRODS} >= 0; # shipment costs/1000 packages param capacity {LINKS,PRODS} >= 0; # max packages shipped param cap_joint {LINKS} >= 0; # max total packages shipped/link minimize Total_Cost; node Balance {k in CITIES, p in PRODS}: net_in = demand[k,p] - supply[k,p]; subject to Multi {(i,j) in LINKS}: to_come <= cap_joint[i,j]; arc Ship {(i,j) in LINKS, p in PRODS} >= 0, <= capacity[i,j,p], from Balance[i,p], to Balance[j,p], coeff Multi[i,j] 1.0, obj Total_Cost cost[i,j,p];
Figure: 16-6
set CITIES; set LINKS within (CITIES cross CITIES); set PRODS; param supply {CITIES,PRODS} >= 0; # amounts available at cities param demand {CITIES,PRODS} >= 0; # amounts required at cities check {p in PRODS}: sum {i in CITIES} supply[i,p] = sum {j in CITIES} demand[j,p]; param cost {LINKS,PRODS} >= 0; # shipment costs/1000 packages param capacity {LINKS,PRODS} >= 0; # max packages shipped param cap_joint {LINKS} >= 0; # max total packages shipped/link minimize Total_Cost; node Balance {k in CITIES, p in PRODS}: net_in = demand[k,p] - supply[k,p]; arc Ship {(i,j) in LINKS, p in PRODS} >= 0, <= capacity[i,j,p], from Balance[i,p], to Balance[j,p], obj Total_Cost cost[i,j,p]; subject to Multi {(i,j) in LINKS}: sum {p in PRODS} Ship[i,j,p] <= cap_joint[i,j];
Figure: 15-13
set INTER; # intersections param entr symbolic in INTER; # entrance to road network param exit symbolic in INTER, <> entr; # exit from road network set ROADS within (INTER diff {exit}) cross (INTER diff {entr}); param time {ROADS} >= 0; # times to travel roads var Use {(i,j) in ROADS} >= 0; # 1 iff (i,j) in shortest path minimize Total_Time: sum {(i,j) in ROADS} time[i,j] * Use[i,j]; subject to Start: sum {(entr,j) in ROADS} Use[entr,j] = 1; subject to Balance {k in INTER diff {entr,exit}}: sum {(i,k) in ROADS} Use[i,k] = sum {(k,j) in ROADS} Use[k,j]; data; set INTER := a b c d e f g ; param entr := a ; param exit := g ; param: ROADS: time := a b 50, a c 100 b d 40, b e 20 c d 60, c f 20 d e 50, d f 60 e g 70, f g 70 ;
Figure: 15-7
set CITIES; set LINKS within (CITIES cross CITIES); param supply {CITIES} >= 0; # amounts available at cities param demand {CITIES} >= 0; # amounts required at cities check: sum {i in CITIES} supply[i] = sum {j in CITIES} demand[j]; param cost {LINKS} >= 0; # shipment costs per ton param city_cap {CITIES} >= 0; # max throughput at cities param link_cap {LINKS} >= 0; # max shipment over links minimize Total_Cost; node Supply {k in CITIES}: net_out = supply[k]; node Demand {k in CITIES}: net_in = demand[k]; arc Ship {(i,j) in LINKS} >= 0, <= link_cap[i,j], from Demand[i], to Supply[j], obj Total_Cost cost[i,j]; arc Through {k in CITIES} >= 0, <= city_cap[k], from Supply[k], to Demand[k];
Figure: 15-15
set ORIG; # origins set DEST; # destinations param supply {ORIG} >= 0; # amounts available at origins param demand {DEST} >= 0; # amounts required at destinations check: sum {i in ORIG} supply[i] = sum {j in DEST} demand[j]; param rate {ORIG,DEST} >= 0; # base shipment costs per unit param limit {ORIG,DEST} > 0; # limit on units shipped var Trans {i in ORIG, j in DEST} >= 0; # units to ship minimize Total_Cost: sum {i in ORIG, j in DEST} rate[i,j] * Trans[i,j] / (1 - Trans[i,j]/limit[i,j]); subject to Supply {i in ORIG}: sum {j in DEST} Trans[i,j] = supply[i]; subject to Demand {j in DEST}: sum {i in ORIG} Trans[i,j] = demand[j];
Figure: 18-4
data; param: ORIG: supply := GARY 1400 CLEV 2600 PITT 2900 ; param: DEST: demand := FRA 900 DET 1200 LAN 600 WIN 400 STL 1700 FRE 1100 LAF 1000 ; param rate : FRA DET LAN WIN STL FRE LAF := GARY 39 14 11 14 16 82 8 CLEV 27 9 12 9 26 95 17 PITT 24 14 17 13 28 99 20 ; param limit : FRA DET LAN WIN STL FRE LAF := GARY 500 1000 1000 1000 800 500 1000 CLEV 500 800 800 800 500 500 1000 PITT 800 600 600 600 500 500 900 ;
Figure: 18-5
set ORIG; # origins set DEST; # destinations param supply {ORIG} >= 0; # amounts available at origins param demand {DEST} >= 0; # amounts required at destinations check: sum {i in ORIG} supply[i] = sum {j in DEST} demand[j]; param rate {ORIG,DEST} >= 0; # base shipment costs per unit param limit {ORIG,DEST} > 0; # limit on units shipped var Trans {i in ORIG, j in DEST} >= 0, <= .9999 * limit[i,j]; # units to ship minimize Total_Cost: sum {i in ORIG, j in DEST} rate[i,j] * Trans[i,j] / (1 - Trans[i,j]/limit[i,j]); subject to Supply {i in ORIG}: sum {j in DEST} Trans[i,j] = supply[i]; subject to Demand {j in DEST}: sum {i in ORIG} Trans[i,j] = demand[j];
set ORIG; # origins set DEST; # destinations param supply {ORIG} >= 0; # amounts available at origins param demand {DEST} >= 0; # amounts required at destinations check: sum {i in ORIG} supply[i] = sum {j in DEST} demand[j]; param rate {ORIG,DEST} >= 0; # base shipment costs per unit param limit {ORIG,DEST} > 0; # limit on units shipped var Trans {i in ORIG, j in DEST} >= 0, := 0; # actual units to be shipped minimize Total_Cost: sum {i in ORIG, j in DEST} rate[i,j] * Trans[i,j]^0.8 / (1 - Trans[i,j]/limit[i,j]); subject to Supply {i in ORIG}: sum {j in DEST} Trans[i,j] = supply[i]; subject to Demand {j in DEST}: sum {i in ORIG} Trans[i,j] = demand[j];
set ORIG; # origins set DEST; # destinations param supply {ORIG} >= 0; # amounts available at origins param demand {DEST} >= 0; # amounts required at destinations check: sum {i in ORIG} supply[i] = sum {j in DEST} demand[j]; param rate {ORIG,DEST} >= 0; # base shipment costs per unit param limit {ORIG,DEST} > 0; # limit on units shipped var Trans {i in ORIG, j in DEST} >= 1e-10, <= .9999 * limit[i,j], := 0; # actual units to be shipped minimize Total_Cost: sum {i in ORIG, j in DEST} rate[i,j] * Trans[i,j]^0.8 / (1 - Trans[i,j]/limit[i,j]); subject to Supply {i in ORIG}: sum {j in DEST} Trans[i,j] = supply[i]; subject to Demand {j in DEST}: sum {i in ORIG} Trans[i,j] = demand[j];
var XB; var XC; maximize Profit: 25 * XB + 30 * XC; subject to Time: (1/200) * XB + (1/140) * XC <= 40; subject to B_limit: 0 <= XB <= 6000; subject to C_limit: 0 <= XC <= 4000;
set P; param a {j in P}; param b; param c {j in P}; param u {j in P}; var X {j in P}; maximize Total_Profit: sum {j in P} c[j] * X[j]; subject to Time: sum {j in P} (1/a[j]) * X[j] <= b; subject to Limit {j in P}: 0 <= X[j] <= u[j];
Figure: 1-2
data; set P := bands coils; param: a c u := bands 200 25 6000 coils 140 30 4000 ; param b := 40;
Figure: 1-3
set SHIFTS; # shifts param Nsched; # number of schedules; set SCHEDS = 1..Nsched; # set of schedules set SHIFT_LIST {SCHEDS} within SHIFTS; param rate {SCHEDS} >= 0; param required {SHIFTS} >= 0; minimize Total_Cost; subject to Shift_Needs {i in SHIFTS}: to_come >= required[i]; var Work {j in SCHEDS} >= 0, obj Total_Cost rate[j], coeff {i in SHIFT_LIST[j]} Shift_Needs[i] 1;
Figure: 16-4
data; set SHIFTS := Mon1 Tue1 Wed1 Thu1 Fri1 Sat1 Mon2 Tue2 Wed2 Thu2 Fri2 Sat2 Mon3 Tue3 Wed3 Thu3 Fri3 ; param Nsched := 126 ; set SHIFT_LIST[ 1] := Mon1 Tue1 Wed1 Thu1 Fri1 ; set SHIFT_LIST[ 2] := Mon1 Tue1 Wed1 Thu1 Fri2 ; set SHIFT_LIST[ 3] := Mon1 Tue1 Wed1 Thu1 Fri3 ; set SHIFT_LIST[ 4] := Mon1 Tue1 Wed1 Thu1 Sat1 ; set SHIFT_LIST[ 5] := Mon1 Tue1 Wed1 Thu1 Sat2 ; set SHIFT_LIST[ 6] := Mon1 Tue1 Wed1 Thu2 Fri2 ; set SHIFT_LIST[ 7] := Mon1 Tue1 Wed1 Thu2 Fri3 ; set SHIFT_LIST[ 8] := Mon1 Tue1 Wed1 Thu2 Sat1 ; set SHIFT_LIST[ 9] := Mon1 Tue1 Wed1 Thu2 Sat2 ; set SHIFT_LIST[ 10] := Mon1 Tue1 Wed1 Thu3 Fri3 ; set SHIFT_LIST[ 11] := Mon1 Tue1 Wed1 Thu3 Sat1 ; set SHIFT_LIST[ 12] := Mon1 Tue1 Wed1 Thu3 Sat2 ; set SHIFT_LIST[ 13] := Mon1 Tue1 Wed1 Fri1 Sat1 ; set SHIFT_LIST[ 14] := Mon1 Tue1 Wed1 Fri1 Sat2 ; set SHIFT_LIST[ 15] := Mon1 Tue1 Wed1 Fri2 Sat2 ; set SHIFT_LIST[ 16] := Mon1 Tue1 Wed2 Thu2 Fri2 ; set SHIFT_LIST[ 17] := Mon1 Tue1 Wed2 Thu2 Fri3 ; set SHIFT_LIST[ 18] := Mon1 Tue1 Wed2 Thu2 Sat1 ; set SHIFT_LIST[ 19] := Mon1 Tue1 Wed2 Thu2 Sat2 ; set SHIFT_LIST[ 20] := Mon1 Tue1 Wed2 Thu3 Fri3 ; set SHIFT_LIST[ 21] := Mon1 Tue1 Wed2 Thu3 Sat1 ; set SHIFT_LIST[ 22] := Mon1 Tue1 Wed2 Thu3 Sat2 ; set SHIFT_LIST[ 23] := Mon1 Tue1 Wed2 Fri1 Sat1 ; set SHIFT_LIST[ 24] := Mon1 Tue1 Wed2 Fri1 Sat2 ; set SHIFT_LIST[ 25] := Mon1 Tue1 Wed2 Fri2 Sat2 ; set SHIFT_LIST[ 26] := Mon1 Tue1 Wed3 Thu3 Fri3 ; set SHIFT_LIST[ 27] := Mon1 Tue1 Wed3 Thu3 Sat1 ; set SHIFT_LIST[ 28] := Mon1 Tue1 Wed3 Thu3 Sat2 ; set SHIFT_LIST[ 29] := Mon1 Tue1 Wed3 Fri1 Sat1 ; set SHIFT_LIST[ 30] := Mon1 Tue1 Wed3 Fri1 Sat2 ; set SHIFT_LIST[ 31] := Mon1 Tue1 Wed3 Fri2 Sat2 ; set SHIFT_LIST[ 32] := Mon1 Tue1 Thu1 Fri1 Sat1 ; set SHIFT_LIST[ 33] := Mon1 Tue1 Thu1 Fri1 Sat2 ; set SHIFT_LIST[ 34] := Mon1 Tue1 Thu1 Fri2 Sat2 ; set SHIFT_LIST[ 35] := Mon1 Tue1 Thu2 Fri2 Sat2 ; set SHIFT_LIST[ 36] := Mon1 Tue2 Wed2 Thu2 Fri2 ; set SHIFT_LIST[ 37] := Mon1 Tue2 Wed2 Thu2 Fri3 ; set SHIFT_LIST[ 38] := Mon1 Tue2 Wed2 Thu2 Sat1 ; set SHIFT_LIST[ 39] := Mon1 Tue2 Wed2 Thu2 Sat2 ; set SHIFT_LIST[ 40] := Mon1 Tue2 Wed2 Thu3 Fri3 ; set SHIFT_LIST[ 41] := Mon1 Tue2 Wed2 Thu3 Sat1 ; set SHIFT_LIST[ 42] := Mon1 Tue2 Wed2 Thu3 Sat2 ; set SHIFT_LIST[ 43] := Mon1 Tue2 Wed2 Fri1 Sat1 ; set SHIFT_LIST[ 44] := Mon1 Tue2 Wed2 Fri1 Sat2 ; set SHIFT_LIST[ 45] := Mon1 Tue2 Wed2 Fri2 Sat2 ; set SHIFT_LIST[ 46] := Mon1 Tue2 Wed3 Thu3 Fri3 ; set SHIFT_LIST[ 47] := Mon1 Tue2 Wed3 Thu3 Sat1 ; set SHIFT_LIST[ 48] := Mon1 Tue2 Wed3 Thu3 Sat2 ; set SHIFT_LIST[ 49] := Mon1 Tue2 Wed3 Fri1 Sat1 ; set SHIFT_LIST[ 50] := Mon1 Tue2 Wed3 Fri1 Sat2 ; set SHIFT_LIST[ 51] := Mon1 Tue2 Wed3 Fri2 Sat2 ; set SHIFT_LIST[ 52] := Mon1 Tue2 Thu1 Fri1 Sat1 ; set SHIFT_LIST[ 53] := Mon1 Tue2 Thu1 Fri1 Sat2 ; set SHIFT_LIST[ 54] := Mon1 Tue2 Thu1 Fri2 Sat2 ; set SHIFT_LIST[ 55] := Mon1 Tue2 Thu2 Fri2 Sat2 ; set SHIFT_LIST[ 56] := Mon1 Tue3 Wed3 Thu3 Fri3 ; set SHIFT_LIST[ 57] := Mon1 Tue3 Wed3 Thu3 Sat1 ; set SHIFT_LIST[ 58] := Mon1 Tue3 Wed3 Thu3 Sat2 ; set SHIFT_LIST[ 59] := Mon1 Tue3 Wed3 Fri1 Sat1 ; set SHIFT_LIST[ 60] := Mon1 Tue3 Wed3 Fri1 Sat2 ; set SHIFT_LIST[ 61] := Mon1 Tue3 Wed3 Fri2 Sat2 ; set SHIFT_LIST[ 62] := Mon1 Tue3 Thu1 Fri1 Sat1 ; set SHIFT_LIST[ 63] := Mon1 Tue3 Thu1 Fri1 Sat2 ; set SHIFT_LIST[ 64] := Mon1 Tue3 Thu1 Fri2 Sat2 ; set SHIFT_LIST[ 65] := Mon1 Tue3 Thu2 Fri2 Sat2 ; set SHIFT_LIST[ 66] := Mon1 Wed1 Thu1 Fri1 Sat1 ; set SHIFT_LIST[ 67] := Mon1 Wed1 Thu1 Fri1 Sat2 ; set SHIFT_LIST[ 68] := Mon1 Wed1 Thu1 Fri2 Sat2 ; set SHIFT_LIST[ 69] := Mon1 Wed1 Thu2 Fri2 Sat2 ; set SHIFT_LIST[ 70] := Mon1 Wed2 Thu2 Fri2 Sat2 ; set SHIFT_LIST[ 71] := Mon2 Tue2 Wed2 Thu2 Fri2 ; set SHIFT_LIST[ 72] := Mon2 Tue2 Wed2 Thu2 Fri3 ; set SHIFT_LIST[ 73] := Mon2 Tue2 Wed2 Thu2 Sat1 ; set SHIFT_LIST[ 74] := Mon2 Tue2 Wed2 Thu2 Sat2 ; set SHIFT_LIST[ 75] := Mon2 Tue2 Wed2 Thu3 Fri3 ; set SHIFT_LIST[ 76] := Mon2 Tue2 Wed2 Thu3 Sat1 ; set SHIFT_LIST[ 77] := Mon2 Tue2 Wed2 Thu3 Sat2 ; set SHIFT_LIST[ 78] := Mon2 Tue2 Wed2 Fri1 Sat1 ; set SHIFT_LIST[ 79] := Mon2 Tue2 Wed2 Fri1 Sat2 ; set SHIFT_LIST[ 80] := Mon2 Tue2 Wed2 Fri2 Sat2 ; set SHIFT_LIST[ 81] := Mon2 Tue2 Wed3 Thu3 Fri3 ; set SHIFT_LIST[ 82] := Mon2 Tue2 Wed3 Thu3 Sat1 ; set SHIFT_LIST[ 83] := Mon2 Tue2 Wed3 Thu3 Sat2 ; set SHIFT_LIST[ 84] := Mon2 Tue2 Wed3 Fri1 Sat1 ; set SHIFT_LIST[ 85] := Mon2 Tue2 Wed3 Fri1 Sat2 ; set SHIFT_LIST[ 86] := Mon2 Tue2 Wed3 Fri2 Sat2 ; set SHIFT_LIST[ 87] := Mon2 Tue2 Thu1 Fri1 Sat1 ; set SHIFT_LIST[ 88] := Mon2 Tue2 Thu1 Fri1 Sat2 ; set SHIFT_LIST[ 89] := Mon2 Tue2 Thu1 Fri2 Sat2 ; set SHIFT_LIST[ 90] := Mon2 Tue2 Thu2 Fri2 Sat2 ; set SHIFT_LIST[ 91] := Mon2 Tue3 Wed3 Thu3 Fri3 ; set SHIFT_LIST[ 92] := Mon2 Tue3 Wed3 Thu3 Sat1 ; set SHIFT_LIST[ 93] := Mon2 Tue3 Wed3 Thu3 Sat2 ; set SHIFT_LIST[ 94] := Mon2 Tue3 Wed3 Fri1 Sat1 ; set SHIFT_LIST[ 95] := Mon2 Tue3 Wed3 Fri1 Sat2 ; set SHIFT_LIST[ 96] := Mon2 Tue3 Wed3 Fri2 Sat2 ; set SHIFT_LIST[ 97] := Mon2 Tue3 Thu1 Fri1 Sat1 ; set SHIFT_LIST[ 98] := Mon2 Tue3 Thu1 Fri1 Sat2 ; set SHIFT_LIST[ 99] := Mon2 Tue3 Thu1 Fri2 Sat2 ; set SHIFT_LIST[100] := Mon2 Tue3 Thu2 Fri2 Sat2 ; set SHIFT_LIST[101] := Mon2 Wed1 Thu1 Fri1 Sat1 ; set SHIFT_LIST[102] := Mon2 Wed1 Thu1 Fri1 Sat2 ; set SHIFT_LIST[103] := Mon2 Wed1 Thu1 Fri2 Sat2 ; set SHIFT_LIST[104] := Mon2 Wed1 Thu2 Fri2 Sat2 ; set SHIFT_LIST[105] := Mon2 Wed2 Thu2 Fri2 Sat2 ; set SHIFT_LIST[106] := Mon3 Tue3 Wed3 Thu3 Fri3 ; set SHIFT_LIST[107] := Mon3 Tue3 Wed3 Thu3 Sat1 ; set SHIFT_LIST[108] := Mon3 Tue3 Wed3 Thu3 Sat2 ; set SHIFT_LIST[109] := Mon3 Tue3 Wed3 Fri1 Sat1 ; set SHIFT_LIST[110] := Mon3 Tue3 Wed3 Fri1 Sat2 ; set SHIFT_LIST[111] := Mon3 Tue3 Wed3 Fri2 Sat2 ; set SHIFT_LIST[112] := Mon3 Tue3 Thu1 Fri1 Sat1 ; set SHIFT_LIST[113] := Mon3 Tue3 Thu1 Fri1 Sat2 ; set SHIFT_LIST[114] := Mon3 Tue3 Thu1 Fri2 Sat2 ; set SHIFT_LIST[115] := Mon3 Tue3 Thu2 Fri2 Sat2 ; set SHIFT_LIST[116] := Mon3 Wed1 Thu1 Fri1 Sat1 ; set SHIFT_LIST[117] := Mon3 Wed1 Thu1 Fri1 Sat2 ; set SHIFT_LIST[118] := Mon3 Wed1 Thu1 Fri2 Sat2 ; set SHIFT_LIST[119] := Mon3 Wed1 Thu2 Fri2 Sat2 ; set SHIFT_LIST[120] := Mon3 Wed2 Thu2 Fri2 Sat2 ; set SHIFT_LIST[121] := Tue1 Wed1 Thu1 Fri1 Sat1 ; set SHIFT_LIST[122] := Tue1 Wed1 Thu1 Fri1 Sat2 ; set SHIFT_LIST[123] := Tue1 Wed1 Thu1 Fri2 Sat2 ; set SHIFT_LIST[124] := Tue1 Wed1 Thu2 Fri2 Sat2 ; set SHIFT_LIST[125] := Tue1 Wed2 Thu2 Fri2 Sat2 ; set SHIFT_LIST[126] := Tue2 Wed2 Thu2 Fri2 Sat2 ; param rate default 1 ; param required := Mon1 100 Mon2 78 Mon3 52 Tue1 100 Tue2 78 Tue3 52 Wed1 100 Wed2 78 Wed3 52 Thu1 100 Thu2 78 Thu3 52 Fri1 100 Fri2 78 Fri3 52 Sat1 100 Sat2 78 ;
Figure: 16-5
set PROD; # products param rate {PROD} > 0; # tons produced per hour param avail >= 0; # hours available in week param profit {PROD}; # profit per ton param market {PROD} >= 0; # limit on tons sold in week var Make {p in PROD} >= 0, <= market[p]; # tons produced maximize Total_Profit: sum {p in PROD} profit[p] * Make[p]; # Objective: total profits from all products subject to Time: sum {p in PROD} (1/rate[p]) * Make[p] <= avail; # Constraint: total of hours used by all # products may not exceed hours available
Figure: 1-4a
data; set PROD := bands coils; param: rate profit market := bands 200 25 6000 coils 140 30 4000 ; param avail := 40;
Figure: 1-4b
data; set PROD := bands coils plate; param: rate profit market := bands 200 25 6000 coils 140 30 4000 plate 160 29 3500 ; param avail := 40;
set PROD; # products param rate {PROD} > 0; # produced tons per hour param avail >= 0; # hours available in week param profit {PROD}; # profit per ton param commit {PROD} >= 0; # lower limit on tons sold in week param market {PROD} >= 0; # upper limit on tons sold in week var Make {p in PROD} >= commit[p], <= market[p]; # tons produced maximize Total_Profit: sum {p in PROD} profit[p] * Make[p]; # Objective: total profits from all products subject to Time: sum {p in PROD} (1/rate[p]) * Make[p] <= avail; # Constraint: total of hours used by all # products may not exceed hours available
Figure: 1-5a
data; set PROD := bands coils plate; param: rate profit commit market := bands 200 25 1000 6000 coils 140 30 500 4000 plate 160 29 750 3500 ; param avail := 40;
Figure: 1-5b
set PROD; # products set STAGE; # stages param rate {PROD,STAGE} > 0; # tons per hour in each stage param avail {STAGE} >= 0; # hours available/week in each stage param profit {PROD}; # profit per ton param commit {PROD} >= 0; # lower limit on tons sold in week param market {PROD} >= 0; # upper limit on tons sold in week var Make {p in PROD} >= commit[p], <= market[p]; # tons produced maximize Total_Profit: sum {p in PROD} profit[p] * Make[p]; # Objective: total profits from all products subject to Time {s in STAGE}: sum {p in PROD} (1/rate[p,s]) * Make[p] <= avail[s]; # In each stage: total of hours used by all # products may not exceed hours available
Figure: 1-6a
data; set PROD := bands coils plate; set STAGE := reheat roll; param rate: reheat roll := bands 200 200 coils 200 140 plate 200 160 ; param: profit commit market := bands 25 1000 6000 coils 30 500 4000 plate 29 750 3500 ; param avail := reheat 35 roll 40 ;
Figure: 1-6b
set PROD; # products set STAGE; # stages param rate {PROD,STAGE} > 0; # tons per hour in each stage param avail_mean {STAGE} > 0; param avail_variance {s in STAGE} > 0, < avail_mean[s] / 2; param avail {s in STAGE} = max(Normal(avail_mean[s], avail_variance[s]), 0); # hours available/week in each stage param profit {PROD}; # profit per ton param commit {PROD} >= 0; # lower limit on tons sold in week param market {PROD} >= 0; # upper limit on tons sold in week var Make {p in PROD} >= commit[p], <= market[p]; # tons produced maximize Total_Profit: sum {p in PROD} profit[p] * Make[p]; # Objective: total profits from all products subject to Time {s in STAGE}: sum {p in PROD} (1/rate[p,s]) * Make[p] <= avail[s]; # In each stage: total of hours used by all # products may not exceed hours available
data; set PROD := bands coils plate; set STAGE := reheat roll; param rate: reheat roll := bands 200 200 coils 200 140 plate 200 160 ; param: profit commit market := bands 25 1000 6000 coils 30 500 4000 plate 29 750 3500 ; # param avail := reheat 35 roll 40 ; param avail_mean := reheat 35 roll 40; param avail_variance := reheat 5 roll 2;
set ORIG; # origins (steel mills) set DEST; # destinations (factories) set PROD; # products param rate {ORIG,PROD} > 0; # tons per hour at origins param avail {ORIG} >= 0; # hours available at origins param demand {DEST,PROD} >= 0; # tons required at destinations param make_cost {ORIG,PROD} >= 0; # manufacturing cost/ton param trans_cost {ORIG,DEST,PROD} >= 0; # shipping cost/ton var Make {ORIG,PROD} >= 0; # tons produced at origins var Trans {ORIG,DEST,PROD} >= 0; # tons shipped minimize Total_Cost: sum {i in ORIG, p in PROD} make_cost[i,p] * Make[i,p] + sum {i in ORIG, j in DEST, p in PROD} trans_cost[i,j,p] * Trans[i,j,p]; subject to Time {i in ORIG}: sum {p in PROD} (1/rate[i,p]) * Make[i,p] <= avail[i]; subject to Supply {i in ORIG, p in PROD}: sum {j in DEST} Trans[i,j,p] = Make[i,p]; subject to Demand {j in DEST, p in PROD}: sum {i in ORIG} Trans[i,j,p] = demand[j,p];
Figure: 4-6
data; set ORIG := GARY CLEV PITT ; set DEST := FRA DET LAN WIN STL FRE LAF ; set PROD := bands coils plate ; param avail := GARY 20 CLEV 15 PITT 20 ; param demand (tr): FRA DET LAN WIN STL FRE LAF := bands 300 300 100 75 650 225 250 coils 500 750 400 250 950 850 500 plate 100 100 0 50 200 100 250 ; param rate (tr): GARY CLEV PITT := bands 200 190 230 coils 140 130 160 plate 160 160 170 ; param make_cost (tr): GARY CLEV PITT := bands 180 190 190 coils 170 170 180 plate 180 185 185 ; param trans_cost := [*,*,bands]: FRA DET LAN WIN STL FRE LAF := GARY 30 10 8 10 11 71 6 CLEV 22 7 10 7 21 82 13 PITT 19 11 12 10 25 83 15 [*,*,coils]: FRA DET LAN WIN STL FRE LAF := GARY 39 14 11 14 16 82 8 CLEV 27 9 12 9 26 95 17 PITT 24 14 17 13 28 99 20 [*,*,plate]: FRA DET LAN WIN STL FRE LAF := GARY 41 15 12 16 17 86 8 CLEV 29 9 13 9 28 99 18 PITT 26 14 17 13 31 104 20 ;
Figure: 4-7
set PROD; # products param T > 0; # number of weeks param rate {PROD} > 0; # tons per hour produced param inv0 {PROD} >= 0; # initial inventory param commit {PROD,1..T} >= 0; # minimum tons sold in week param market {PROD,1..T} >= 0; # limit on tons sold in week param avail_min {1..T} >= 0; # unpenalized hours available param avail_max {t in 1..T} >= avail_min[t]; # total hours avail param time_penalty {1..T} > 0; param prodcost {PROD} >= 0; # cost/ton produced param invcost {PROD} >= 0; # carrying cost/ton of inventory param revenue {PROD,1..T} >= 0; # revenue/ton sold var Make {PROD,1..T} >= 0; # tons produced var Inv {PROD,0..T} >= 0; # tons inventoried var Sell {p in PROD, t in 1..T} >= commit[p,t], <= market[p,t]; # tons sold var Use {t in 1..T} >= 0, <= avail_max[t]; # hours used maximize Total_Profit: sum {p in PROD, t in 1..T} (revenue[p,t]*Sell[p,t] - prodcost[p]*Make[p,t] - invcost[p]*Inv[p,t]) - sum {t in 1..T} <<avail_min[t]; 0,time_penalty[t]>> Use[t]; # Objective: total revenue less costs in all weeks subject to Time {t in 1..T}: sum {p in PROD} (1/rate[p]) * Make[p,t] = Use[t]; # Total of hours used by all products # may not exceed hours available, in each week subject to Init_Inv {p in PROD}: Inv[p,0] = inv0[p]; # Initial inventory must equal given value subject to Balance {p in PROD, t in 1..T}: Make[p,t] + Inv[p,t-1] = Sell[p,t] + Inv[p,t]; # Tons produced and taken from inventory # must equal tons sold and put into inventory
Figure: 17-5a
data; param T := 4; set PROD := bands coils; param: rate inv0 prodcost invcost := bands 200 10 10 2.5 coils 140 0 11 3 ; param: avail_min avail_max time_penalty := 1 35 42 3100 2 35 42 3000 3 30 40 3700 4 35 42 3100 ; param revenue: 1 2 3 4 := bands 25 26 27 27 coils 30 35 37 39 ; param commit: 1 2 3 4 := bands 3000 3000 3000 3000 coils 2000 2000 2000 2000 ; param market: 1 2 3 4 := bands 6000 6000 4000 6500 coils 4000 2500 3500 4200 ;
Figure: 17-5b
set PROD; # products param T > 0; # number of weeks param rate {PROD} > 0; # tons per hour produced param inv0 {PROD} >= 0; # initial inventory param commit {PROD,1..T} >= 0; # minimum tons sold in week param market {PROD,1..T} >= 0; # limit on tons sold in week param avail_min {1..T} >= 0; # unpenalized hours available param avail_max {t in 1..T} >= avail_min[t]; # total hours available param time_penalty {1..T} > 0; param prodcost {PROD} >= 0; # cost per ton produced param invcost {PROD} >= 0; # carrying cost per ton of inventory param revenue {PROD,1..T} >= 0; # revenue per ton sold var Make {PROD,1..T} >= 0; # tons produced var Inv {PROD,0..T} >= 0; # tons inventoried var Sell {p in PROD, t in 1..T} >= commit[p,t], <= market[p,t]; # tons sold var Use {t in 1..T} >= 0; # hours used maximize Total_Profit: sum {p in PROD, t in 1..T} (revenue[p,t]*Sell[p,t] - prodcost[p]*Make[p,t] - invcost[p]*Inv[p,t]) - sum {t in 1..T} <<avail_min[t],avail_max[t]; 0,time_penalty[t],100000>> Use[t]; # Objective: total revenue less costs in all weeks subject to Time {t in 1..T}: sum {p in PROD} (1/rate[p]) * Make[p,t] = Use[t]; # Total of hours used by all products # may not exceed hours available, in each week subject to Init_Inv {p in PROD}: Inv[p,0] = inv0[p]; # Initial inventory must equal given value subject to Balance {p in PROD, t in 1..T}: Make[p,t] + Inv[p,t-1] = Sell[p,t] + Inv[p,t]; # Tons produced and taken from inventory # must equal tons sold and put into inventory
data; param T := 4; set PROD := bands coils; param: rate inv0 prodcost invcost := bands 200 10 10 2.5 coils 140 0 11 3 ; param: avail_min avail_max time_penalty := 1 35 42 3100 2 35 42 3000 3 30 40 3700 4 35 42 3100 ; param revenue: 1 2 3 4 := bands 25 26 27 27 coils 30 35 37 39 ; param commit: 1 2 3 4 := bands 3500 5900 3900 6400 coils 2500 2400 3400 4100 ; param market: 1 2 3 4 := bands 6000 6000 4000 6500 coils 4000 2500 3500 4200 ;
set PROD; # products param T > 0; # number of weeks param rate {PROD} > 0; # tons per hour produced param inv0 {PROD} >= 0; # initial inventory param commit {PROD,1..T} >= 0; # minimum tons sold in week param market {PROD,1..T} >= 0; # limit on tons sold in week param avail_min {1..T} >= 0; # unpenalized hours available param avail_max {t in 1..T} >= avail_min[t]; # total hours available param time_penalty {1..T} > 0; param prodcost {PROD} >= 0; # cost per ton produced param invcost {PROD} >= 0; # carrying cost per ton of inventory param revenue {PROD,1..T} >= 0; # revenue per ton sold var Make {PROD,1..T} >= 0; # tons produced var Inv {PROD,0..T} >= 0; # tons inventoried var Sell {p in PROD, t in 1..T} >= 0, <= market[p,t]; # tons sold var Use {t in 1..T} >= 0, <= avail_max[t]; # hours used maximize Total_Profit: sum {p in PROD, t in 1..T} (revenue[p,t]*Sell[p,t] - prodcost[p]*Make[p,t] - invcost[p]*Inv[p,t]) - sum {t in 1..T} <<avail_min[t]; 0,time_penalty[t]>> Use[t] - sum {p in PROD, t in 1..T} <<commit[p,t]; -100000,0>> (Sell[p,t],commit[p,t]); # Objective: total revenue less costs in all weeks subject to Time {t in 1..T}: sum {p in PROD} (1/rate[p]) * Make[p,t] = Use[t]; # Total of hours used by all products # may not exceed hours available, in each week subject to Init_Inv {p in PROD}: Inv[p,0] = inv0[p]; # Initial inventory must equal given value subject to Balance {p in PROD, t in 1..T}: Make[p,t] + Inv[p,t-1] = Sell[p,t] + Inv[p,t]; # Tons produced and taken from inventory # must equal tons sold and put into inventory
set PROD; # products param T > 0; # number of weeks param rate {PROD} > 0; # tons per hour produced param inv0 {PROD} >= 0; # initial inventory param commit {PROD,1..T} >= 0; # minimum tons sold in week param market {PROD,1..T} >= 0; # limit on tons sold in week param avail_min {1..T} >= 0; # unpenalized hours available param avail_max {t in 1..T} >= avail_min[t]; # total hours available param time_penalty {1..T} > 0; param prodcost {PROD} >= 0; # cost per ton produced param invcost {PROD} >= 0; # carrying cost per ton of inventory param revenue {PROD,1..T} >= 0; # revenue per ton sold var Make {PROD,1..T} >= 0; # tons produced var Inv {PROD,0..T}; # tons inventoried var Sell {p in PROD, t in 1..T} >= commit[p,t], <= market[p,t]; # tons sold var Use {t in 1..T} >= 0, <= avail_max[t]; # hours used maximize Total_Profit: sum {p in PROD, t in 1..T} (revenue[p,t]*Sell[p,t] - prodcost[p]*Make[p,t] - invcost[p]*Inv[p,t]) - sum {t in 1..T} <<avail_min[t]; 0,time_penalty[t]>> Use[t]; # Objective: total revenue less costs in all weeks subject to Time {t in 1..T}: sum {p in PROD} (1/rate[p]) * Make[p,t] = Use[t]; # Total of hours used by all products # may not exceed hours available, in each week subject to Init_Inv {p in PROD}: Inv[p,0] = inv0[p]; # Initial inventory must equal given value subject to Balance {p in PROD, t in 1..T}: Make[p,t] + Inv[p,t-1] = Sell[p,t] + Inv[p,t]; # Tons produced and taken from inventory # must equal tons sold and put into inventory
data; param T := 4; set PROD := bands coils; param: rate inv0 prodcost invcost := bands 200 10 10 2.5 coils 140 0 11 3.0 ; param: avail_min avail_max time_penalty := 1 35 42 3100 2 35 42 3000 3 30 40 3700 4 35 42 3100 ; param revenue: 1 2 3 4 := bands 25 26 23 20 coils 30 35 31 25 ; param commit: 1 2 3 4 := bands 3000 3000 3000 3000 coils 2000 2000 2000 2000 ; param market: 1 2 3 4 := bands 6000 6000 4000 6500 coils 4000 2500 3500 4200 ;
set PROD; # products param T > 0; # number of weeks param rate {PROD} > 0; # tons per hour produced param inv0 {PROD} >= 0; # initial inventory param commit {PROD,1..T} >= 0; # minimum tons sold in week param market {PROD,1..T} >= 0; # limit on tons sold in week param avail_min {1..T} >= 0; # unpenalized hours available param avail_max {t in 1..T} >= avail_min[t]; # total hours available param time_penalty {1..T} > 0; param prodcost {PROD} >= 0; # cost per ton produced param invcost {PROD} >= 0; # carrying cost per ton of inventory param backcost {PROD} >= 0; # penalty cost per ton of backorders param revenue {PROD,1..T} >= 0; # revenue per ton sold var Make {PROD,1..T} >= 0; # tons produced var Inv {PROD,0..T}; # tons inventoried var Sell {p in PROD, t in 1..T} >= commit[p,t], <= market[p,t]; # tons sold var Use {t in 1..T} >= 0, <= avail_max[t]; # hours used maximize Total_Profit: sum {p in PROD, t in 1..T} (revenue[p,t]*Sell[p,t] - prodcost[p]*Make[p,t] - <<0; -backcost[p],invcost[p]>> Inv[p,t]) - sum {t in 1..T} <<avail_min[t]; 0,time_penalty[t]>> Use[t]; # Objective: total revenue less costs in all weeks subject to Time {t in 1..T}: sum {p in PROD} (1/rate[p]) * Make[p,t] = Use[t]; # Total of hours used by all products # may not exceed hours available, in each week subject to Init_Inv {p in PROD}: Inv[p,0] = inv0[p]; # Initial inventory must equal given value subject to Balance {p in PROD, t in 1..T}: Make[p,t] + Inv[p,t-1] = Sell[p,t] + Inv[p,t]; # Tons produced and taken from inventory # must equal tons sold and put into inventory subject to Final {p in PROD}: Inv[p,T] >= 0; # All backorders must be cleared by the last period
data; param T := 4; set PROD := bands coils; param: rate inv0 prodcost invcost backcost := bands 200 10 10 2.5 1.5 coils 140 0 11 3.0 2.0 ; param: avail_min avail_max time_penalty := 1 35 42 3100 2 35 42 3000 3 30 40 3700 4 35 42 3100 ; param revenue: 1 2 3 4 := bands 25 26 23 20 coils 30 35 31 25 ; param commit: 1 2 3 4 := bands 3000 3000 3000 3000 coils 2000 2000 2000 2000 ; param market: 1 2 3 4 := bands 6000 6000 4000 6500 coils 4000 2500 3500 4200 ;
set PROD; # products param T > 0; # number of weeks param rate {PROD} > 0; # tons per hour produced param avail {1..T} >= 0; # hours available in week param profit {PROD,1..T}; # profit per ton param market {PROD,1..T} >= 0; # limit on tons sold in week var Make {p in PROD, t in 1..T} >= 0, <= market[p,t]; # tons produced maximize Total_Profit: sum {p in PROD, t in 1..T} profit[p,t] * Make[p,t]; # total profits from all products in all weeks subject to Time {t in 1..T}: sum {p in PROD} (1/rate[p]) * Make[p,t] <= avail[t]; # total of hours used by all products # may not exceed hours available, in each week
Figure: 4-3
solve; display Total_Profit >steelT.sens; option display_1col 0; option omit_zero_rows 0; display Make >steelT.sens; display Sell >steelT.sens; option display_1col 20; option omit_zero_rows 1; display Inv >steelT.sens; let avail[3] := avail[3] + 5;
model steelT.mod; data steelT.dat; for {1..4} { solve; display Total_Profit >steelT.sens; option display_1col 0; option omit_zero_rows 0; display Make >steelT.sens; display Sell >steelT.sens; option display_1col 20; option omit_zero_rows 1; display Inv >steelT.sens; let avail[3] := avail[3] + 5; }
set PROD; # products param T > 0; # number of weeks param rate {PROD} > 0; # tons per hour produced param inv0 {PROD} >= 0; # initial inventory param avail {1..T} >= 0; # hours available in week param market {PROD,1..T} >= 0; # limit on tons sold in week param prodcost {PROD} >= 0; # cost per ton produced param invcost {PROD} >= 0; # carrying cost/ton of inventory param revenue {PROD,1..T} >= 0; # revenue per ton sold var Make {PROD,1..T} >= 0; # tons produced var Inv {PROD,0..T} >= 0; # tons inventoried var Sell {p in PROD, t in 1..T} >= 0, <= market[p,t]; # tons sold maximize Total_Profit: sum {p in PROD, t in 1..T} (revenue[p,t]*Sell[p,t] - prodcost[p]*Make[p,t] - invcost[p]*Inv[p,t]); # Total revenue less costs in all weeks subject to Time {t in 1..T}: sum {p in PROD} (1/rate[p]) * Make[p,t] <= avail[t]; # Total of hours used by all products # may not exceed hours available, in each week subject to Init_Inv {p in PROD}: Inv[p,0] = inv0[p]; # Initial inventory must equal given value subject to Balance {p in PROD, t in 1..T}: Make[p,t] + Inv[p,t-1] = Sell[p,t] + Inv[p,t]; # Tons produced and taken from inventory # must equal tons sold and put into inventory
Figure: 4-4
data; param T := 4; set PROD := bands coils; param avail := 1 40 2 40 3 32 4 40 ; param rate := bands 200 coils 140 ; param inv0 := bands 10 coils 0 ; param prodcost := bands 10 coils 11 ; param invcost := bands 2.5 coils 3 ; param revenue: 1 2 3 4 := bands 25 26 27 27 coils 30 35 37 39 ; param market: 1 2 3 4 := bands 6000 6000 4000 6500 coils 4000 2500 3500 4200 ;
Figure: 4-5
model steelT.mod; data steelT.dat; option solver_msg 0; set AVAIL3; param avail3_obj {AVAIL3}; param avail3_dual {AVAIL3}; let AVAIL3 := avail[3] .. avail[3] + 15 by 5; for {a in AVAIL3} { let avail[3] := a; solve; let avail3_obj[a] := Total_Profit; let avail3_dual[a] := Time[3].dual; } display avail3_obj, avail3_dual;
Figure: 13-1
model steelT.mod; data steelT.dat; option solution_precision 10; option solver_msg 0; set AVAIL3 default {}; param avail3_obj {AVAIL3}; param avail3_dual {AVAIL3}; param avail3_step := 5; repeat { solve; let AVAIL3 := AVAIL3 union {avail[3]}; let avail3_obj[avail[3]] := Total_Profit; let avail3_dual[avail[3]] := Time[3].dual; let avail[3] := avail[3] + avail3_step; } until Time[3].dual = 0; display avail3_obj, avail3_dual;
Figure: 13-3
model steelT.mod; data steelT.dat; option solution_precision 10; option solver_msg 0; set AVAIL3 default {}; param avail3_obj {AVAIL3}; param avail3_dual {AVAIL3}; let avail[3] := 1; param avail3_step := 1; param previous_dual default Infinity; repeat while previous_dual > 0 { solve; if Time[3].dual < previous_dual then { let AVAIL3 := AVAIL3 union {avail[3]}; let avail3_obj[avail[3]] := Total_Profit; let avail3_dual[avail[3]] := Time[3].dual; let previous_dual := Time[3].dual; } let avail[3] := avail[3] + avail3_step; } display avail3_obj, avail3_dual;
Figure: 13-4
model steelT.mod; data steelT.dat; option solution_precision 10; option solver_msg 0; set AVAIL3 default {}; param avail3_obj {AVAIL3}; param avail3_dual {AVAIL3}; let avail[3] := 0; param previous_dual default Infinity; repeat { let avail[3] := avail[3] + 1; solve; if Time[3].dual = previous_dual then continue; let AVAIL3 := AVAIL3 union {avail[3]}; let avail3_obj[avail[3]] := Total_Profit; let avail3_dual[avail[3]] := Time[3].dual; if Time[3].dual = 0 then break; let previous_dual := Time[3].dual; } display avail3_obj, avail3_dual;
Figure: 13-5
printf "\nSALES"; printf {p in PROD}: "%14s ", p; printf "\n"; for {t in 1..T} { printf "week %d", t; for {p in PROD} { printf "%9d", Sell[p,t]; printf "%7.1f%%", 100 * Sell[p,t]/market[p,t]; } printf "\n"; }
Figure: 13-2
set PROD; # products set WEEKS ordered; # number of weeks param rate {PROD} > 0; # tons per hour produced param inv0 {PROD} >= 0; # initial inventory param avail {WEEKS} >= 0; # hours available in week param market {PROD,WEEKS} >= 0; # limit on tons sold in week param prodcost {PROD} >= 0; # cost per ton produced param invcost {PROD} >= 0; # carrying cost/ton of inventory param revenue {PROD,WEEKS} >= 0; # revenue/ton sold var Make {PROD,WEEKS} >= 0; # tons produced var Inv {PROD,WEEKS} >= 0; # tons inventoried var Sell {p in PROD, t in WEEKS} >= 0, <= market[p,t]; # tons sold maximize Total_Profit: sum {p in PROD, t in WEEKS} (revenue[p,t]*Sell[p,t] - prodcost[p]*Make[p,t] - invcost[p]*Inv[p,t]); # Objective: total revenue less costs in all weeks subject to Time {t in WEEKS}: sum {p in PROD} (1/rate[p]) * Make[p,t] <= avail[t]; # Total of hours used by all products # may not exceed hours available, in each week subject to Balance0 {p in PROD}: Make[p,first(WEEKS)] + inv0[p] = Sell[p,first(WEEKS)] + Inv[p,first(WEEKS)]; subject to Balance {p in PROD, t in WEEKS: ord(t) > 1}: Make[p,t] + Inv[p,prev(t)] = Sell[p,t] + Inv[p,t]; # Tons produced and taken from inventory # must equal tons sold and put into inventory
Figure: 5-3
data; set PROD := bands coils ; set WEEKS := 27sep 04oct 11oct 18oct ; param avail := 27sep 40 04oct 40 11oct 32 18oct 40 ; param rate := bands 200 coils 140 ; param inv0 := bands 10 coils 0 ; param prodcost := bands 10 coils 11 ; param invcost := bands 2.5 coils 3 ; param revenue: 27sep 04oct 11oct 18oct := bands 25 26 27 27 coils 30 35 37 39 ; param market: 27sep 04oct 11oct 18oct := bands 6000 6000 4000 6500 coils 4000 2500 3500 4200 ;
Figure: 5-4
set PROD; # products set AREA {PROD}; # market areas for each product param T > 0; # number of weeks param rate {PROD} > 0; # tons per hour produced param inv0 {PROD} >= 0; # initial inventory param avail {1..T} >= 0; # hours available in week param market {p in PROD, AREA[p], 1..T} >= 0; # limit on tons sold in week param prodcost {PROD} >= 0; # cost per ton produced param invcost {PROD} >= 0; # carrying cost/ton of inventory param revenue {p in PROD, AREA[p], 1..T} >= 0; # revenue per ton sold var Make {PROD,1..T} >= 0; # tons produced var Inv {PROD,0..T} >= 0; # tons inventoried var Sell {p in PROD, a in AREA[p], t in 1..T} # tons sold >= 0, <= market[p,a,t]; maximize Total_Profit: sum {p in PROD, t in 1..T} (sum {a in AREA[p]} revenue[p,a,t]*Sell[p,a,t] - prodcost[p]*Make[p,t] - invcost[p]*Inv[p,t]); # Total revenue less costs for all products in all weeks subject to Time {t in 1..T}: sum {p in PROD} (1/rate[p]) * Make[p,t] <= avail[t]; # Total of hours used by all products # may not exceed hours available, in each week subject to Init_Inv {p in PROD}: Inv[p,0] = inv0[p]; # Initial inventory must equal given value subject to Balance {p in PROD, t in 1..T}: Make[p,t] + Inv[p,t-1] = sum {a in AREA[p]} Sell[p,a,t] + Inv[p,t]; # Tons produced and taken from inventory # must equal tons sold and put into inventory
Figure: 6-3
data; param T := 4; set PROD := bands coils; set AREA[bands] := east north ; set AREA[coils] := east west export ; param avail := 1 40 2 40 3 32 4 40 ; param rate := bands 200 coils 140 ; param inv0 := bands 10 coils 0 ; param prodcost := bands 10 coils 11 ; param invcost := bands 2.5 coils 3 ; param revenue := [bands,*,*]: 1 2 3 4 := east 25.0 26.0 27.0 27.0 north 26.5 27.5 28.0 28.5 [coils,*,*]: 1 2 3 4 := east 30 35 37 39 west 29 32 33 35 export 25 25 25 28 ; param market := [bands,*,*]: 1 2 3 4 := east 2000 2000 1500 2000 north 4000 4000 2500 4500 [coils,*,*]: 1 2 3 4 := east 1000 800 1000 1100 west 2000 1200 2000 2300 export 1000 500 500 800 ;
Figure: 6-4
set ORIG; # origins set DEST; # destinations param supply {ORIG} >= 0; # amounts available at origins param demand {DEST} >= 0; # amounts required at destinations check: sum {i in ORIG} supply[i] = sum {j in DEST} demand[j]; param cost {ORIG,DEST} >= 0; # shipment costs per unit var Trans {ORIG,DEST} >= 0; # units to be shipped minimize Total_Cost: sum {i in ORIG, j in DEST} cost[i,j] * Trans[i,j]; subject to Supply {i in ORIG}: sum {j in DEST} Trans[i,j] = supply[i]; subject to Demand {j in DEST}: sum {i in ORIG} Trans[i,j] = demand[j];
Figure: 3-1a
data; param: ORIG: supply := # defines set "ORIG" and param "supply" GARY 1400 CLEV 2600 PITT 2900 ; param: DEST: demand := # defines "DEST" and "demand" FRA 900 DET 1200 LAN 600 WIN 400 STL 1700 FRE 1100 LAF 1000 ; param cost: FRA DET LAN WIN STL FRE LAF := GARY 39 14 11 14 16 82 8 CLEV 27 9 12 9 26 95 17 PITT 24 14 17 13 28 99 20 ;
Figure: 3-1b
set ORIG; # origins set DEST; # destinations set LINKS = {ORIG,DEST}; param supply {ORIG} >= 0; # amounts available at origins param demand {DEST} >= 0; # amounts required at destinations check: sum {i in ORIG} supply[i] = sum {j in DEST} demand[j]; param cost {LINKS} >= 0; # shipment costs per unit var Trans {LINKS} >= 0; # units to be shipped minimize Total_Cost: sum {(i,j) in LINKS} cost[i,j] * Trans[i,j]; subject to Supply {i in ORIG}: sum {j in DEST} Trans[i,j] = supply[i]; subject to Demand {j in DEST}: sum {i in ORIG} Trans[i,j] = demand[j];
Figure: 6-1
set ORIG; # origins set DEST; # destinations set LINKS within {ORIG,DEST}; param supply {ORIG} >= 0; # amounts available at origins param demand {DEST} >= 0; # amounts required at destinations check: sum {i in ORIG} supply[i] = sum {j in DEST} demand[j]; param cost {LINKS} >= 0; # shipment costs per unit var Trans {LINKS} >= 0; # units to be shipped minimize Total_Cost: sum {(i,j) in LINKS} cost[i,j] * Trans[i,j]; subject to Supply {i in ORIG}: sum {(i,j) in LINKS} Trans[i,j] = supply[i]; subject to Demand {j in DEST}: sum {(i,j) in LINKS} Trans[i,j] = demand[j];
Figure: 6-2a
data; param: ORIG: supply := GARY 1400 CLEV 2600 PITT 2900 ; param: DEST: demand := FRA 900 DET 1200 LAN 600 WIN 400 STL 1700 FRE 1100 LAF 1000 ; param: LINKS: cost := GARY DET 14 GARY LAN 11 GARY STL 16 GARY LAF 8 CLEV FRA 27 CLEV DET 9 CLEV LAN 12 CLEV WIN 9 CLEV STL 26 CLEV LAF 17 PITT FRA 24 PITT WIN 13 PITT STL 28 PITT FRE 99 ;
Figure: 6-2b
set ORIG; # origins set DEST; # destinations param supply {ORIG} >= 0; # amounts available at origins param demand {DEST} >= 0; # amounts required at destinations check: sum {i in ORIG} supply[i] = sum {j in DEST} demand[j]; param rate1 {i in ORIG, j in DEST} >= 0; param rate2 {i in ORIG, j in DEST} >= rate1[i,j]; param rate3 {i in ORIG, j in DEST} >= rate2[i,j]; param limit1 {i in ORIG, j in DEST} > 0; param limit2 {i in ORIG, j in DEST} > limit1[i,j]; var Trans {ORIG,DEST} >= 0; # units to be shipped minimize Total_Cost: sum {i in ORIG, j in DEST} <<limit1[i,j], limit2[i,j]; rate1[i,j], rate2[i,j], rate3[i,j]>> Trans[i,j]; subject to Supply {i in ORIG}: sum {j in DEST} Trans[i,j] = supply[i]; subject to Demand {j in DEST}: sum {i in ORIG} Trans[i,j] = demand[j];
Figure: 17-2
set ORIG; # origins set DEST; # destinations param supply {ORIG} >= 0; # amounts available at origins param demand {DEST} >= 0; # amounts required at destinations check: sum {i in ORIG} supply[i] = sum {j in DEST} demand[j]; param npiece {ORIG,DEST} integer >= 1; param rate {i in ORIG, j in DEST, p in 1..npiece[i,j]} >= if p = 1 then 0 else rate[i,j,p-1]; param limit {i in ORIG, j in DEST, p in 1..npiece[i,j]-1} > if p = 1 then 0 else limit[i,j,p-1]; var Trans {ORIG,DEST} >= 0; # units to be shipped minimize Total_Cost: sum {i in ORIG, j in DEST} <<{p in 1..npiece[i,j]-1} limit[i,j,p]; {p in 1..npiece[i,j]} rate[i,j,p]>> Trans[i,j]; subject to Supply {i in ORIG}: sum {j in DEST} Trans[i,j] = supply[i]; subject to Demand {j in DEST}: sum {i in ORIG} Trans[i,j] = demand[j];
Figure: 17-3a
data;
param: ORIG: supply :=
GARY 1400 CLEV 2600 PITT 2900 ;
param: DEST: demand :=
FRA 900 DET 1200 LAN 600 WIN 400
STL 1700 FRE 1100 LAF 1000 ;
param npiece: FRA DET LAN WIN STL FRE LAF :=
GARY 3 3 3 2 3 2 3
CLEV 3 3 3 3 3 3 3
PITT 2 2 2 2 1 2 1 ;
param rate :=
[GARY,FRA,*] 1 39 2 50 3 70 [GARY,DET,*] 1 14 2 17 3 33
[GARY,LAN,*] 1 11 2 12 3 23 [GARY,WIN,*] 1 14 2 17
[GARY,STL,*] 1 16 2 23 3 40 [GARY,FRE,*] 1 82 2 98
[GARY,LAF,*] 1 8 2 16 3 24
[CLEV,FRA,*] 1 27 2 37 3 47 [CLEV,DET,*] 1 9 2 19 3 24
[CLEV,LAN,*] 1 12 2 32 3 39 [CLEV,WIN,*] 1 9 2 14 3 21
[CLEV,STL,*] 1 26 2 36 3 47 [CLEV,FRE,*] 1 95 2 105 3 129
[CLEV,LAF,*] 1 8 2 16 3 24
[PITT,FRA,*] 1 24 2 34 [PITT,DET,*] 1 14 2 24
[PITT,LAN,*] 1 17 2 27 [PITT,WIN,*] 1 13 2 23
[PITT,STL,*] 1 28 [PITT,FRE,*] 1 99 2 140
[PITT,LAF,*] 1 20 ;
param limit :=
[GARY,*,*] FRA 1 500 FRA 2 1000 DET 1 500 DET 2 1000
LAN 1 500 LAN 2 1000 WIN 1 1000
STL 1 500 STL 2 1000 FRE 1 1000
LAF 1 500 LAF 2 1000
[CLEV,*,*] FRA 1 500 FRA 2 1000 DET 1 500 DET 2 1000
LAN 1 500 LAN 2 1000 WIN 1 500 WIN 2 1000
STL 1 500 STL 2 1000 FRE 1 500 FRE 2 1000
LAF 1 500 LAF 2 1000
[PITT,*,*] FRA 1 1000 DET 1 1000 LAN 1 1000 WIN 1 1000
FRE 1 1000 ;
Figure: 17-3b
Figure number
File (by figure number)
Figure: 1-2
set P; param a {j in P}; param b; param c {j in P}; param u {j in P}; var X {j in P}; maximize Total_Profit: sum {j in P} c[j] * X[j]; subject to Time: sum {j in P} (1/a[j]) * X[j] <= b; subject to Limit {j in P}: 0 <= X[j] <= u[j];
Figure: 1-3
data; set P := bands coils; param: a c u := bands 200 25 6000 coils 140 30 4000 ; param b := 40;
Figure: 1-4a
set PROD; # products param rate {PROD} > 0; # tons produced per hour param avail >= 0; # hours available in week param profit {PROD}; # profit per ton param market {PROD} >= 0; # limit on tons sold in week var Make {p in PROD} >= 0, <= market[p]; # tons produced maximize Total_Profit: sum {p in PROD} profit[p] * Make[p]; # Objective: total profits from all products subject to Time: sum {p in PROD} (1/rate[p]) * Make[p] <= avail; # Constraint: total of hours used by all # products may not exceed hours available
Figure: 1-4b
data; set PROD := bands coils; param: rate profit market := bands 200 25 6000 coils 140 30 4000 ; param avail := 40;
Figure: 1-5a
set PROD; # products param rate {PROD} > 0; # produced tons per hour param avail >= 0; # hours available in week param profit {PROD}; # profit per ton param commit {PROD} >= 0; # lower limit on tons sold in week param market {PROD} >= 0; # upper limit on tons sold in week var Make {p in PROD} >= commit[p], <= market[p]; # tons produced maximize Total_Profit: sum {p in PROD} profit[p] * Make[p]; # Objective: total profits from all products subject to Time: sum {p in PROD} (1/rate[p]) * Make[p] <= avail; # Constraint: total of hours used by all # products may not exceed hours available
Figure: 1-5b
data; set PROD := bands coils plate; param: rate profit commit market := bands 200 25 1000 6000 coils 140 30 500 4000 plate 160 29 750 3500 ; param avail := 40;
Figure: 1-6a
set PROD; # products set STAGE; # stages param rate {PROD,STAGE} > 0; # tons per hour in each stage param avail {STAGE} >= 0; # hours available/week in each stage param profit {PROD}; # profit per ton param commit {PROD} >= 0; # lower limit on tons sold in week param market {PROD} >= 0; # upper limit on tons sold in week var Make {p in PROD} >= commit[p], <= market[p]; # tons produced maximize Total_Profit: sum {p in PROD} profit[p] * Make[p]; # Objective: total profits from all products subject to Time {s in STAGE}: sum {p in PROD} (1/rate[p,s]) * Make[p] <= avail[s]; # In each stage: total of hours used by all # products may not exceed hours available
Figure: 1-6b
data; set PROD := bands coils plate; set STAGE := reheat roll; param rate: reheat roll := bands 200 200 coils 200 140 plate 200 160 ; param: profit commit market := bands 25 1000 6000 coils 30 500 4000 plate 29 750 3500 ; param avail := reheat 35 roll 40 ;
Figure: 2-1
set NUTR; set FOOD; param cost {FOOD} > 0; param f_min {FOOD} >= 0; param f_max {j in FOOD} >= f_min[j]; param n_min {NUTR} >= 0; param n_max {i in NUTR} >= n_min[i]; param amt {NUTR,FOOD} >= 0; var Buy {j in FOOD} >= f_min[j], <= f_max[j]; minimize Total_Cost: sum {j in FOOD} cost[j] * Buy[j]; subject to Diet {i in NUTR}: n_min[i] <= sum {j in FOOD} amt[i,j] * Buy[j] <= n_max[i];
Figure: 2-2
data; set NUTR := A B1 B2 C ; set FOOD := BEEF CHK FISH HAM MCH MTL SPG TUR ; param: cost f_min f_max := BEEF 3.19 0 100 CHK 2.59 0 100 FISH 2.29 0 100 HAM 2.89 0 100 MCH 1.89 0 100 MTL 1.99 0 100 SPG 1.99 0 100 TUR 2.49 0 100 ; param: n_min n_max := A 700 10000 C 700 10000 B1 700 10000 B2 700 10000 ; param amt (tr): A C B1 B2 := BEEF 60 20 10 15 CHK 8 0 20 20 FISH 8 10 15 10 HAM 40 40 35 10 MCH 15 35 15 15 MTL 70 30 15 15 SPG 25 50 25 15 TUR 60 20 15 10 ;
Figure: 2-3
data; set NUTR := A B1 B2 C NA CAL ; set FOOD := BEEF CHK FISH HAM MCH MTL SPG TUR ; param: cost f_min f_max := BEEF 3.19 2 10 CHK 2.59 2 10 FISH 2.29 2 10 HAM 2.89 2 10 MCH 1.89 2 10 MTL 1.99 2 10 SPG 1.99 2 10 TUR 2.49 2 10 ; param: n_min n_max := A 700 20000 C 700 20000 B1 700 20000 B2 700 20000 NA 0 40000 CAL 16000 24000 ; param amt (tr): A C B1 B2 NA CAL := BEEF 60 20 10 15 938 295 CHK 8 0 20 20 2180 770 FISH 8 10 15 10 945 440 HAM 40 40 35 10 278 430 MCH 15 35 15 15 1182 315 MTL 70 30 15 15 896 400 SPG 25 50 25 15 1329 370 TUR 60 20 15 10 1397 450 ;
Figure: 2-4
set INPUT; # inputs set OUTPUT; # outputs param cost {INPUT} > 0; param in_min {INPUT} >= 0; param in_max {j in INPUT} >= in_min[j]; param out_min {OUTPUT} >= 0; param out_max {i in OUTPUT} >= out_min[i]; param io {OUTPUT,INPUT} >= 0; var X {j in INPUT} >= in_min[j], <= in_max[j]; minimize Total_Cost: sum {j in INPUT} cost[j] * X[j]; subject to Outputs {i in OUTPUT}: out_min[i] <= sum {j in INPUT} io[i,j] * X[j] <= out_max[i];
Figure: 3-1a
set ORIG; # origins set DEST; # destinations param supply {ORIG} >= 0; # amounts available at origins param demand {DEST} >= 0; # amounts required at destinations check: sum {i in ORIG} supply[i] = sum {j in DEST} demand[j]; param cost {ORIG,DEST} >= 0; # shipment costs per unit var Trans {ORIG,DEST} >= 0; # units to be shipped minimize Total_Cost: sum {i in ORIG, j in DEST} cost[i,j] * Trans[i,j]; subject to Supply {i in ORIG}: sum {j in DEST} Trans[i,j] = supply[i]; subject to Demand {j in DEST}: sum {i in ORIG} Trans[i,j] = demand[j];
Figure: 3-1b
data; param: ORIG: supply := # defines set "ORIG" and param "supply" GARY 1400 CLEV 2600 PITT 2900 ; param: DEST: demand := # defines "DEST" and "demand" FRA 900 DET 1200 LAN 600 WIN 400 STL 1700 FRE 1100 LAF 1000 ; param cost: FRA DET LAN WIN STL FRE LAF := GARY 39 14 11 14 16 82 8 CLEV 27 9 12 9 26 95 17 PITT 24 14 17 13 28 99 20 ;
Figure: 3-2
data; set ORIG := Coullard Daskin Hazen Hopp Iravani Linetsky Mehrotra Nelson Smilowitz Tamhane White ; set DEST := C118 C138 C140 C246 C250 C251 D237 D239 D241 M233 M239; param supply default 1 ; param demand default 1 ; param cost: C118 C138 C140 C246 C250 C251 D237 D239 D241 M233 M239 := Coullard 6 9 8 7 11 10 4 5 3 2 1 Daskin 11 8 7 6 9 10 1 5 4 2 3 Hazen 9 10 11 1 5 6 2 7 8 3 4 Hopp 11 9 8 10 6 5 1 7 4 2 3 Iravani 3 2 8 9 10 11 1 5 4 6 7 Linetsky 11 9 10 5 3 4 6 7 8 1 2 Mehrotra 6 11 10 9 8 7 1 2 5 4 3 Nelson 11 5 4 6 7 8 1 9 10 2 3 Smilowitz 11 9 10 8 6 5 7 3 4 1 2 Tamhane 5 6 9 8 4 3 7 10 11 2 1 White 11 9 8 4 6 5 3 10 7 2 1 ;
Figure: 4-1
set ORIG; # origins set DEST; # destinations set PROD; # products param supply {ORIG,PROD} >= 0; # amounts available at origins param demand {DEST,PROD} >= 0; # amounts required at destinations check {p in PROD}: sum {i in ORIG} supply[i,p] = sum {j in DEST} demand[j,p]; param limit {ORIG,DEST} >= 0; param cost {ORIG,DEST,PROD} >= 0; # shipment costs per unit var Trans {ORIG,DEST,PROD} >= 0; # units to be shipped minimize Total_Cost: sum {i in ORIG, j in DEST, p in PROD} cost[i,j,p] * Trans[i,j,p]; subject to Supply {i in ORIG, p in PROD}: sum {j in DEST} Trans[i,j,p] = supply[i,p]; subject to Demand {j in DEST, p in PROD}: sum {i in ORIG} Trans[i,j,p] = demand[j,p]; subject to Multi {i in ORIG, j in DEST}: sum {p in PROD} Trans[i,j,p] <= limit[i,j];
Figure: 4-2
data; set ORIG := GARY CLEV PITT ; set DEST := FRA DET LAN WIN STL FRE LAF ; set PROD := bands coils plate ; param supply (tr): GARY CLEV PITT := bands 400 700 800 coils 800 1600 1800 plate 200 300 300 ; param demand (tr): FRA DET LAN WIN STL FRE LAF := bands 300 300 100 75 650 225 250 coils 500 750 400 250 950 850 500 plate 100 100 0 50 200 100 250 ; param limit default 625 ; param cost := [*,*,bands]: FRA DET LAN WIN STL FRE LAF := GARY 30 10 8 10 11 71 6 CLEV 22 7 10 7 21 82 13 PITT 19 11 12 10 25 83 15 [*,*,coils]: FRA DET LAN WIN STL FRE LAF := GARY 39 14 11 14 16 82 8 CLEV 27 9 12 9 26 95 17 PITT 24 14 17 13 28 99 20 [*,*,plate]: FRA DET LAN WIN STL FRE LAF := GARY 41 15 12 16 17 86 8 CLEV 29 9 13 9 28 99 18 PITT 26 14 17 13 31 104 20 ;
Figure: 4-3
set PROD; # products param T > 0; # number of weeks param rate {PROD} > 0; # tons per hour produced param avail {1..T} >= 0; # hours available in week param profit {PROD,1..T}; # profit per ton param market {PROD,1..T} >= 0; # limit on tons sold in week var Make {p in PROD, t in 1..T} >= 0, <= market[p,t]; # tons produced maximize Total_Profit: sum {p in PROD, t in 1..T} profit[p,t] * Make[p,t]; # total profits from all products in all weeks subject to Time {t in 1..T}: sum {p in PROD} (1/rate[p]) * Make[p,t] <= avail[t]; # total of hours used by all products # may not exceed hours available, in each week
Figure: 4-4
set PROD; # products param T > 0; # number of weeks param rate {PROD} > 0; # tons per hour produced param inv0 {PROD} >= 0; # initial inventory param avail {1..T} >= 0; # hours available in week param market {PROD,1..T} >= 0; # limit on tons sold in week param prodcost {PROD} >= 0; # cost per ton produced param invcost {PROD} >= 0; # carrying cost/ton of inventory param revenue {PROD,1..T} >= 0; # revenue per ton sold var Make {PROD,1..T} >= 0; # tons produced var Inv {PROD,0..T} >= 0; # tons inventoried var Sell {p in PROD, t in 1..T} >= 0, <= market[p,t]; # tons sold maximize Total_Profit: sum {p in PROD, t in 1..T} (revenue[p,t]*Sell[p,t] - prodcost[p]*Make[p,t] - invcost[p]*Inv[p,t]); # Total revenue less costs in all weeks subject to Time {t in 1..T}: sum {p in PROD} (1/rate[p]) * Make[p,t] <= avail[t]; # Total of hours used by all products # may not exceed hours available, in each week subject to Init_Inv {p in PROD}: Inv[p,0] = inv0[p]; # Initial inventory must equal given value subject to Balance {p in PROD, t in 1..T}: Make[p,t] + Inv[p,t-1] = Sell[p,t] + Inv[p,t]; # Tons produced and taken from inventory # must equal tons sold and put into inventory
Figure: 4-5
data; param T := 4; set PROD := bands coils; param avail := 1 40 2 40 3 32 4 40 ; param rate := bands 200 coils 140 ; param inv0 := bands 10 coils 0 ; param prodcost := bands 10 coils 11 ; param invcost := bands 2.5 coils 3 ; param revenue: 1 2 3 4 := bands 25 26 27 27 coils 30 35 37 39 ; param market: 1 2 3 4 := bands 6000 6000 4000 6500 coils 4000 2500 3500 4200 ;
Figure: 4-6
set ORIG; # origins (steel mills) set DEST; # destinations (factories) set PROD; # products param rate {ORIG,PROD} > 0; # tons per hour at origins param avail {ORIG} >= 0; # hours available at origins param demand {DEST,PROD} >= 0; # tons required at destinations param make_cost {ORIG,PROD} >= 0; # manufacturing cost/ton param trans_cost {ORIG,DEST,PROD} >= 0; # shipping cost/ton var Make {ORIG,PROD} >= 0; # tons produced at origins var Trans {ORIG,DEST,PROD} >= 0; # tons shipped minimize Total_Cost: sum {i in ORIG, p in PROD} make_cost[i,p] * Make[i,p] + sum {i in ORIG, j in DEST, p in PROD} trans_cost[i,j,p] * Trans[i,j,p]; subject to Time {i in ORIG}: sum {p in PROD} (1/rate[i,p]) * Make[i,p] <= avail[i]; subject to Supply {i in ORIG, p in PROD}: sum {j in DEST} Trans[i,j,p] = Make[i,p]; subject to Demand {j in DEST, p in PROD}: sum {i in ORIG} Trans[i,j,p] = demand[j,p];
Figure: 4-7
data; set ORIG := GARY CLEV PITT ; set DEST := FRA DET LAN WIN STL FRE LAF ; set PROD := bands coils plate ; param avail := GARY 20 CLEV 15 PITT 20 ; param demand (tr): FRA DET LAN WIN STL FRE LAF := bands 300 300 100 75 650 225 250 coils 500 750 400 250 950 850 500 plate 100 100 0 50 200 100 250 ; param rate (tr): GARY CLEV PITT := bands 200 190 230 coils 140 130 160 plate 160 160 170 ; param make_cost (tr): GARY CLEV PITT := bands 180 190 190 coils 170 170 180 plate 180 185 185 ; param trans_cost := [*,*,bands]: FRA DET LAN WIN STL FRE LAF := GARY 30 10 8 10 11 71 6 CLEV 22 7 10 7 21 82 13 PITT 19 11 12 10 25 83 15 [*,*,coils]: FRA DET LAN WIN STL FRE LAF := GARY 39 14 11 14 16 82 8 CLEV 27 9 12 9 26 95 17 PITT 24 14 17 13 28 99 20 [*,*,plate]: FRA DET LAN WIN STL FRE LAF := GARY 41 15 12 16 17 86 8 CLEV 29 9 13 9 28 99 18 PITT 26 14 17 13 31 104 20 ;
Figure: 5-1
set MINREQ; # nutrients with minimum requirements set MAXREQ; # nutrients with maximum requirements set NUTR = MINREQ union MAXREQ; # nutrients set FOOD; # foods param cost {FOOD} > 0; param f_min {FOOD} >= 0; param f_max {j in FOOD} >= f_min[j]; param n_min {MINREQ} >= 0; param n_max {MAXREQ} >= 0; param amt {NUTR,FOOD} >= 0; var Buy {j in FOOD} >= f_min[j], <= f_max[j]; minimize Total_Cost: sum {j in FOOD} cost[j] * Buy[j]; subject to Diet_Min {i in MINREQ}: sum {j in FOOD} amt[i,j] * Buy[j] >= n_min[i]; subject to Diet_Max {i in MAXREQ}: sum {j in FOOD} amt[i,j] * Buy[j] <= n_max[i];
Figure: 5-2
data; set MINREQ := A B1 B2 C CAL ; set MAXREQ := A NA CAL ; set FOOD := BEEF CHK FISH HAM MCH MTL SPG TUR ; param: cost f_min f_max := BEEF 3.19 2 10 CHK 2.59 2 10 FISH 2.29 2 10 HAM 2.89 2 10 MCH 1.89 2 10 MTL 1.99 2 10 SPG 1.99 2 10 TUR 2.49 2 10 ; param: n_min n_max := A 700 20000 C 700 . B1 0 . B2 0 . NA . 50000 CAL 16000 24000 ; param amt (tr): A C B1 B2 NA CAL := BEEF 60 20 10 15 938 295 CHK 8 0 20 20 2180 770 FISH 8 10 15 10 945 440 HAM 40 40 35 10 278 430 MCH 15 35 15 15 1182 315 MTL 70 30 15 15 896 400 SPG 25 50 25 15 1329 370 TUR 60 20 15 10 1397 450 ;
Figure: 5-3
set PROD; # products
set WEEKS ordered; # number of weeks
param rate {PROD} > 0; # tons per hour produced
param inv0 {PROD} >= 0; # initial inventory
param avail {WEEKS} >= 0; # hours available in week
param market {PROD,WEEKS} >= 0; # limit on tons sold in week
param prodcost {PROD} >= 0; # cost per ton produced
param invcost {PROD} >= 0; # carrying cost/ton of inventory
param revenue {PROD,WEEKS} >= 0; # revenue/ton sold
var Make {PROD,WEEKS} >= 0; # tons produced
var Inv {PROD,WEEKS} >= 0; # tons inventoried
var Sell {p in PROD, t in WEEKS} >= 0, <= market[p,t]; # tons sold
maximize Total_Profit:
sum {p in PROD, t in WEEKS} (revenue[p,t]*Sell[p,t] -
prodcost[p]*Make[p,t] - invcost[p]*Inv[p,t]);
# Objective: total revenue less costs in all weeks
subject to Time {t in WEEKS}:
sum {p in PROD} (1/rate[p]) * Make[p,t] <= avail[t]; # Total of hours used by all products # may not exceed hours available, in each week subject to Balance0 {p in PROD}:
Make[p,first(WEEKS)] + inv0[p] = Sell[p,first(WEEKS)] + Inv[p,first(WEEKS)]; subject to Balance {p in PROD, t in WEEKS: ord(t) > 1}: Make[p,t] + Inv[p,prev(t)] = Sell[p,t] + Inv[p,t];
# Tons produced and taken from inventory
# must equal tons sold and put into inventory ;
Figure: 5-4
data; set PROD := bands coils ; set WEEKS := 27sep 04oct 11oct 18oct ; param avail := 27sep 40 04oct 40 11oct 32 18oct 40 ; param rate := bands 200 coils 140 ; param inv0 := bands 10 coils 0 ; param prodcost := bands 10 coils 11 ; param invcost := bands 2.5 coils 3 ; param revenue: 27sep 04oct 11oct 18oct := bands 25 26 27 27 coils 30 35 37 39 ; param market: 27sep 04oct 11oct 18oct := bands 6000 6000 4000 6500 coils 4000 2500 3500 4200 ;
Figure: 6-1
set ORIG; # origins set DEST; # destinations set LINKS = {ORIG,DEST}; param supply {ORIG} >= 0; # amounts available at origins param demand {DEST} >= 0; # amounts required at destinations check: sum {i in ORIG} supply[i] = sum {j in DEST} demand[j]; param cost {LINKS} >= 0; # shipment costs per unit var Trans {LINKS} >= 0; # units to be shipped minimize Total_Cost: sum {(i,j) in LINKS} cost[i,j] * Trans[i,j]; subject to Supply {i in ORIG}: sum {j in DEST} Trans[i,j] = supply[i]; subject to Demand {j in DEST}: sum {i in ORIG} Trans[i,j] = demand[j];
Figure: 6-2a
set ORIG; # origins set DEST; # destinations set LINKS within {ORIG,DEST}; param supply {ORIG} >= 0; # amounts available at origins param demand {DEST} >= 0; # amounts required at destinations check: sum {i in ORIG} supply[i] = sum {j in DEST} demand[j]; param cost {LINKS} >= 0; # shipment costs per unit var Trans {LINKS} >= 0; # units to be shipped minimize Total_Cost: sum {(i,j) in LINKS} cost[i,j] * Trans[i,j]; subject to Supply {i in ORIG}: sum {(i,j) in LINKS} Trans[i,j] = supply[i]; subject to Demand {j in DEST}: sum {(i,j) in LINKS} Trans[i,j] = demand[j];
Figure: 6-2b
data; param: ORIG: supply := GARY 1400 CLEV 2600 PITT 2900 ; param: DEST: demand := FRA 900 DET 1200 LAN 600 WIN 400 STL 1700 FRE 1100 LAF 1000 ; param: LINKS: cost := GARY DET 14 GARY LAN 11 GARY STL 16 GARY LAF 8 CLEV FRA 27 CLEV DET 9 CLEV LAN 12 CLEV WIN 9 CLEV STL 26 CLEV LAF 17 PITT FRA 24 PITT WIN 13 PITT STL 28 PITT FRE 99 ;
Figure: 6-3
set PROD; # products set AREA {PROD}; # market areas for each product param T > 0; # number of weeks param rate {PROD} > 0; # tons per hour produced param inv0 {PROD} >= 0; # initial inventory param avail {1..T} >= 0; # hours available in week param market {p in PROD, AREA[p], 1..T} >= 0; # limit on tons sold in week param prodcost {PROD} >= 0; # cost per ton produced param invcost {PROD} >= 0; # carrying cost/ton of inventory param revenue {p in PROD, AREA[p], 1..T} >= 0; # revenue per ton sold var Make {PROD,1..T} >= 0; # tons produced var Inv {PROD,0..T} >= 0; # tons inventoried var Sell {p in PROD, a in AREA[p], t in 1..T} # tons sold >= 0, <= market[p,a,t]; maximize Total_Profit: sum {p in PROD, t in 1..T} (sum {a in AREA[p]} revenue[p,a,t]*Sell[p,a,t] - prodcost[p]*Make[p,t] - invcost[p]*Inv[p,t]); # Total revenue less costs for all products in all weeks subject to Time {t in 1..T}: sum {p in PROD} (1/rate[p]) * Make[p,t] <= avail[t]; # Total of hours used by all products # may not exceed hours available, in each week subject to Init_Inv {p in PROD}: Inv[p,0] = inv0[p]; # Initial inventory must equal given value subject to Balance {p in PROD, t in 1..T}: Make[p,t] + Inv[p,t-1] = sum {a in AREA[p]} Sell[p,a,t] + Inv[p,t]; # Tons produced and taken from inventory # must equal tons sold and put into inventory
Figure: 6-4
data; param T := 4; set PROD := bands coils; set AREA[bands] := east north ; set AREA[coils] := east west export ; param avail := 1 40 2 40 3 32 4 40 ; param rate := bands 200 coils 140 ; param inv0 := bands 10 coils 0 ; param prodcost := bands 10 coils 11 ; param invcost := bands 2.5 coils 3 ; param revenue := [bands,*,*]: 1 2 3 4 := east 25.0 26.0 27.0 27.0 north 26.5 27.5 28.0 28.5 [coils,*,*]: 1 2 3 4 := east 30 35 37 39 west 29 32 33 35 export 25 25 25 28 ; param market := [bands,*,*]: 1 2 3 4 := east 2000 2000 1500 2000 north 4000 4000 2500 4500 [coils,*,*]: 1 2 3 4 := east 1000 800 1000 1100 west 2000 1200 2000 2300 export 1000 500 500 800 ;
Figure: 6-5
set ORIG; # origins set DEST; # destinations set PROD; # products set orig {PROD} within ORIG; set dest {PROD} within DEST; set links {p in PROD} = orig[p] cross dest[p]; param supply {p in PROD, orig[p]} >= 0; # available at origins param demand {p in PROD, dest[p]} >= 0; # required at destinations check {p in PROD}: sum {i in orig[p]} supply[p,i] = sum {j in dest[p]} demand[p,j]; param limit {ORIG,DEST} >= 0; param cost {p in PROD, links[p]} >= 0; # shipment costs per unit var Trans {p in PROD, links[p]} >= 0; # units to be shipped minimize Total_Cost: sum {p in PROD, (i,j) in links[p]} cost[p,i,j] * Trans[p,i,j]; subject to Supply {p in PROD, i in orig[p]}: sum {j in dest[p]} Trans[p,i,j] = supply[p,i]; subject to Demand {p in PROD, j in dest[p]}: sum {i in orig[p]} Trans[p,i,j] = demand[p,j]; subject to Multi {i in ORIG, j in DEST}: sum {p in PROD: (i,j) in links[p]} Trans[p,i,j] <= limit[i,j];
Figure: 13-1
model steelT.mod; data steelT.dat; option solver_msg 0; set AVAIL3; param avail3_obj {AVAIL3}; param avail3_dual {AVAIL3}; let AVAIL3 := avail[3] .. avail[3] + 15 by 5; for {a in AVAIL3} { let avail[3] := a; solve; let avail3_obj[a] := Total_Profit; let avail3_dual[a] := Time[3].dual; } display avail3_obj, avail3_dual;
Figure: 13-2
printf "\nSALES"; printf {p in PROD}: "%14s ", p; printf "\n"; for {t in 1..T} { printf "week %d", t; for {p in PROD} { printf "%9d", Sell[p,t]; printf "%7.1f%%", 100 * Sell[p,t]/market[p,t]; } printf "\n"; }
Figure: 13-3
model steelT.mod; data steelT.dat; option solution_precision 10; option solver_msg 0; set AVAIL3 default {}; param avail3_obj {AVAIL3}; param avail3_dual {AVAIL3}; param avail3_step := 5; repeat { solve; let AVAIL3 := AVAIL3 union {avail[3]}; let avail3_obj[avail[3]] := Total_Profit; let avail3_dual[avail[3]] := Time[3].dual; let avail[3] := avail[3] + avail3_step; } until Time[3].dual = 0; display avail3_obj, avail3_dual;
Figure: 13-4
model steelT.mod; data steelT.dat; option solution_precision 10; option solver_msg 0; set AVAIL3 default {}; param avail3_obj {AVAIL3}; param avail3_dual {AVAIL3}; let avail[3] := 1; param avail3_step := 1; param previous_dual default Infinity; repeat while previous_dual > 0 { solve; if Time[3].dual < previous_dual then { let AVAIL3 := AVAIL3 union {avail[3]}; let avail3_obj[avail[3]] := Total_Profit; let avail3_dual[avail[3]] := Time[3].dual; let previous_dual := Time[3].dual; } let avail[3] := avail[3] + avail3_step; } display avail3_obj, avail3_dual;
Figure: 13-5
model steelT.mod; data steelT.dat; option solution_precision 10; option solver_msg 0; set AVAIL3 default {}; param avail3_obj {AVAIL3}; param avail3_dual {AVAIL3}; let avail[3] := 0; param previous_dual default Infinity; repeat { let avail[3] := avail[3] + 1; solve; if Time[3].dual = previous_dual then continue; let AVAIL3 := AVAIL3 union {avail[3]}; let avail3_obj[avail[3]] := Total_Profit; let avail3_dual[avail[3]] := Time[3].dual; if Time[3].dual = 0 then break; let previous_dual := Time[3].dual; } display avail3_obj, avail3_dual;
Figure: 14-2
# ---------------------------------------- # CUTTING STOCK USING PATTERNS # ---------------------------------------- param roll_width > 0; # width of raw rolls set WIDTHS; # set of widths to be cut param orders {WIDTHS} > 0; # number of each width to be cut param nPAT integer >= 0; # number of patterns set PATTERNS = 1..nPAT; # set of patterns param nbr {WIDTHS,PATTERNS} integer >= 0; check {j in PATTERNS}: sum {i in WIDTHS} i * nbr[i,j] <= roll_width; # defn of patterns: nbr[i,j] = number # of rolls of width i in pattern j var Cut {PATTERNS} integer >= 0; # rolls cut using each pattern minimize Number: # minimize total raw rolls cut sum {j in PATTERNS} Cut[j]; subject to Fill {i in WIDTHS}: sum {j in PATTERNS} nbr[i,j] * Cut[j] >= orders[i]; # for each width, total # rolls cut meets total orders # ---------------------------------------- # KNAPSACK SUBPROBLEM FOR CUTTING STOCK # ---------------------------------------- param price {WIDTHS} default 0.0; var Use {WIDTHS} integer >= 0; minimize Reduced_Cost: 1 - sum {i in WIDTHS} price[i] * Use[i]; subject to Width_Limit: sum {i in WIDTHS} i * Use[i] <= roll_width;
Figure: 14-3
model cut.mod; data cut.dat; option solver cplex, solution_round 6; option display_1col 0, display_transpose -10; problem Cutting_Opt: Cut, Number, Fill; option relax_integrality 1; problem Pattern_Gen: Use, Reduced_Cost, Width_Limit; option relax_integrality 0; let nPAT := 0; for {i in WIDTHS} { let nPAT := nPAT + 1; let nbr[i,nPAT] := floor (roll_width/i); let {i2 in WIDTHS: i2 <> i} nbr[i2,nPAT] := 0; } repeat { solve Cutting_Opt; let {i in WIDTHS} price[i] := Fill[i].dual; solve Pattern_Gen; if Reduced_Cost < -0.00001 then { let nPAT := nPAT + 1; let {i in WIDTHS} nbr[i,nPAT] := Use[i]; } else break; } display nbr, Cut; option Cutting_Opt.relax_integrality 0; solve Cutting_Opt; display Cut;
Figure: 14-4
data; param roll_width := 110 ; param: WIDTHS: orders := 20 48 45 35 50 24 55 10 75 8 ;
Figure: 14-6
problem Cutting_Opt; # ---------------------------------------- param nPAT integer >= 0, default 0; param roll_width; set PATTERNS = 1..nPAT; set WIDTHS; param orders {WIDTHS} > 0; param nbr {WIDTHS,PATTERNS} integer >= 0; check {j in PATTERNS}: sum {i in WIDTHS} i * nbr[i,j] <= roll_width; var Cut {PATTERNS} integer >= 0; minimize Number: sum {j in PATTERNS} Cut[j]; subject to Fill {i in WIDTHS}: sum {j in PATTERNS} nbr[i,j] * Cut[j] >= orders[i]; problem Pattern_Gen; # ---------------------------------------- param price {WIDTHS} default 0; var Use {WIDTHS} integer >= 0; minimize Reduced_Cost: 1 - sum {i in WIDTHS} price[i] * Use[i]; subject to Width_Limit: sum {i in WIDTHS} i * Use[i] <= roll_width;
Figure: 15-2a
set CITIES; set LINKS within (CITIES cross CITIES); param supply {CITIES} >= 0; # amounts available at cities param demand {CITIES} >= 0; # amounts required at cities check: sum {i in CITIES} supply[i] = sum {j in CITIES} demand[j]; param cost {LINKS} >= 0; # shipment costs/1000 packages param capacity {LINKS} >= 0; # max packages that can be shipped var Ship {(i,j) in LINKS} >= 0, <= capacity[i,j]; # packages to be shipped minimize Total_Cost: sum {(i,j) in LINKS} cost[i,j] * Ship[i,j]; subject to Balance {k in CITIES}: supply[k] + sum {(i,k) in LINKS} Ship[i,k] = demand[k] + sum {(k,j) in LINKS} Ship[k,j];
Figure: 15-2b
data; set CITIES := PITT NE SE BOS EWR BWI ATL MCO ; set LINKS := (PITT,NE) (PITT,SE) (NE,BOS) (NE,EWR) (NE,BWI) (SE,EWR) (SE,BWI) (SE,ATL) (SE,MCO); param supply default 0 := PITT 450 ; param demand default 0 := BOS 90, EWR 120, BWI 120, ATL 70, MCO 50; param: cost capacity := PITT NE 2.5 250 PITT SE 3.5 250 NE BOS 1.7 100 NE EWR 0.7 100 NE BWI 1.3 100 SE EWR 1.3 100 SE BWI 0.8 100 SE ATL 0.2 100 SE MCO 2.1 100 ;
Figure: 15-3a
param p_city symbolic; set D_CITY; set W_CITY; set DW_LINKS within (D_CITY cross W_CITY); param p_supply >= 0; # amount available at plant param w_demand {W_CITY} >= 0; # amounts required at warehouses check: p_supply = sum {k in W_CITY} w_demand[k]; set CITIES = {p_city} union D_CITY union W_CITY; set LINKS = ({p_city} cross D_CITY) union DW_LINKS; param supply {k in CITIES} = if k = p_city then p_supply else 0; param demand {k in CITIES} = if k in W_CITY then w_demand[k] else 0; ### Remainder same as general transshipment model ### param cost {LINKS} >= 0; # shipment costs/1000 packages param capacity {LINKS} >= 0; # max packages that can be shipped var Ship {(i,j) in LINKS} >= 0, <= capacity[i,j]; # packages to be shipped minimize Total_Cost: sum {(i,j) in LINKS} cost[i,j] * Ship[i,j]; subject to Balance {k in CITIES}: supply[k] + sum {(i,k) in LINKS} Ship[i,k] = demand[k] + sum {(k,j) in LINKS} Ship[k,j];
Figure: 15-3b
data; param p_city := PITT ; set D_CITY := NE SE ; set W_CITY := BOS EWR BWI ATL MCO ; set DW_LINKS := (NE,BOS) (NE,EWR) (NE,BWI) (SE,EWR) (SE,BWI) (SE,ATL) (SE,MCO); param p_supply := 450 ; param w_demand := BOS 90, EWR 120, BWI 120, ATL 70, MCO 50; param: cost capacity := PITT NE 2.5 250 PITT SE 3.5 250 NE BOS 1.7 100 NE EWR 0.7 100 NE BWI 1.3 100 SE EWR 1.3 100 SE BWI 0.8 100 SE ATL 0.2 100 SE MCO 2.1 100 ;
Figure: 15-4a
set D_CITY; set W_CITY; set DW_LINKS within (D_CITY cross W_CITY); param p_supply >= 0; # amount available at plant param w_demand {W_CITY} >= 0; # amounts required at warehouses check: p_supply = sum {j in W_CITY} w_demand[j]; param pd_cost {D_CITY} >= 0; # shipment costs/1000 packages param dw_cost {DW_LINKS} >= 0; param pd_cap {D_CITY} >= 0; # max packages that can be shipped param dw_cap {DW_LINKS} >= 0; var PD_Ship {i in D_CITY} >= 0, <= pd_cap[i]; var DW_Ship {(i,j) in DW_LINKS} >= 0, <= dw_cap[i,j]; # packages to be shipped minimize Total_Cost: sum {i in D_CITY} pd_cost[i] * PD_Ship[i] + sum {(i,j) in DW_LINKS} dw_cost[i,j] * DW_Ship[i,j]; subject to P_Bal: sum {i in D_CITY} PD_Ship[i] = p_supply; subject to D_Bal {i in D_CITY}: PD_Ship[i] = sum {(i,j) in DW_LINKS} DW_Ship[i,j]; subject to W_Bal {j in W_CITY}: sum {(i,j) in DW_LINKS} DW_Ship[i,j] = w_demand[j];
Figure: 15-4b
data; set D_CITY := NE SE ; set W_CITY := BOS EWR BWI ATL MCO ; set DW_LINKS := (NE,BOS) (NE,EWR) (NE,BWI) (SE,EWR) (SE,BWI) (SE,ATL) (SE,MCO); param p_supply := 450 ; param w_demand := BOS 90, EWR 120, BWI 120, ATL 70, MCO 50; param: pd_cost pd_cap := NE 2.5 250 SE 3.5 250 ; param: dw_cost dw_cap := NE BOS 1.7 100 NE EWR 0.7 100 NE BWI 1.3 100 SE EWR 1.3 100 SE BWI 0.8 100 SE ATL 0.2 100 SE MCO 2.1 100 ;
Figure: 15-6
set INTER; # intersections param entr symbolic in INTER; # entrance to road network param exit symbolic in INTER, <> entr; # exit from road network set ROADS within (INTER diff {exit}) cross (INTER diff {entr}); param cap {ROADS} >= 0; # capacities var Traff {(i,j) in ROADS} >= 0, <= cap[i,j]; # traffic loads maximize Entering_Traff: sum {(entr,j) in ROADS} Traff[entr,j]; subject to Balance {k in INTER diff {entr,exit}}: sum {(i,k) in ROADS} Traff[i,k] = sum {(k,j) in ROADS} Traff[k,j]; data; set INTER := a b c d e f g ; param entr := a ; param exit := g ; param: ROADS: cap := a b 50, a c 100 b d 40, b e 20 c d 60, c f 20 d e 50, d f 60 e g 70, f g 70 ;
Figure: 15-7
set INTER; # intersections param entr symbolic in INTER; # entrance to road network param exit symbolic in INTER, <> entr; # exit from road network set ROADS within (INTER diff {exit}) cross (INTER diff {entr}); param time {ROADS} >= 0; # times to travel roads var Use {(i,j) in ROADS} >= 0; # 1 iff (i,j) in shortest path minimize Total_Time: sum {(i,j) in ROADS} time[i,j] * Use[i,j]; subject to Start: sum {(entr,j) in ROADS} Use[entr,j] = 1; subject to Balance {k in INTER diff {entr,exit}}: sum {(i,k) in ROADS} Use[i,k] = sum {(k,j) in ROADS} Use[k,j]; data; set INTER := a b c d e f g ; param entr := a ; param exit := g ; param: ROADS: time := a b 50, a c 100 b d 40, b e 20 c d 60, c f 20 d e 50, d f 60 e g 70, f g 70 ;
Figure: 15-9
set PEOPLE; set PROJECTS; set ABILITIES within (PEOPLE cross PROJECTS); param supply {PEOPLE} >= 0; # hours each person is available param demand {PROJECTS} >= 0; # hours each project requires check: sum {i in PEOPLE} supply[i] = sum {j in PROJECTS} demand[j]; param cost {ABILITIES} >= 0; # cost per hour of work param limit {ABILITIES} >= 0; # maximum contributions to projects var Assign {(i,j) in ABILITIES} >= 0, <= limit[i,j]; minimize Total_Cost: sum {(i,j) in ABILITIES} cost[i,j] * Assign[i,j]; subject to Supply {i in PEOPLE}: sum {(i,j) in ABILITIES} Assign[i,j] = supply[i]; subject to Demand {j in PROJECTS}: sum {(i,j) in ABILITIES} Assign[i,j] = demand[j];
Figure: 15-10
set CITIES; set LINKS within (CITIES cross CITIES); param supply {CITIES} >= 0; # amounts available at cities param demand {CITIES} >= 0; # amounts required at cities check: sum {i in CITIES} supply[i] = sum {j in CITIES} demand[j]; param cost {LINKS} >= 0; # shipment costs/1000 packages param capacity {LINKS} >= 0; # max packages that can be shipped minimize Total_Cost; node Balance {k in CITIES}: net_in = demand[k] - supply[k]; arc Ship {(i,j) in LINKS} >= 0, <= capacity[i,j], from Balance[i], to Balance[j], obj Total_Cost cost[i,j];
Figure: 15-11
set D_CITY; set W_CITY; set DW_LINKS within (D_CITY cross W_CITY); param p_supply >= 0; # amount available at plant param w_demand {W_CITY} >= 0; # amounts required at warehouses check: p_supply = sum {j in W_CITY} w_demand[j]; param pd_cost {D_CITY} >= 0; # shipment costs/1000 packages param dw_cost {DW_LINKS} >= 0; param pd_cap {D_CITY} >= 0; # max packages that can be shipped param dw_cap {DW_LINKS} >= 0; minimize Total_Cost; node Plant: net_out = p_supply; node Dist {i in D_CITY}; node Whse {j in W_CITY}: net_in = w_demand[j]; arc PD_Ship {i in D_CITY} >= 0, <= pd_cap[i], from Plant, to Dist[i], obj Total_Cost pd_cost[i]; arc DW_Ship {(i,j) in DW_LINKS} >= 0, <= dw_cap[i,j], from Dist[i], to Whse[j], obj Total_Cost dw_cost[i,j];
Figure: 15-12
set INTER; # intersections param entr symbolic in INTER; # entrance to road network param exit symbolic in INTER, <> entr; # exit from road network set ROADS within (INTER diff {exit}) cross (INTER diff {entr}); param cap {ROADS} >= 0; # capacities of roads node Intersection {k in INTER}; arc Traff_In >= 0, to Intersection[entr]; arc Traff_Out >= 0, from Intersection[exit]; arc Traff {(i,j) in ROADS} >= 0, <= cap[i,j], from Intersection[i], to Intersection[j]; maximize Entering_Traff: Traff_In; data; set INTER := a b c d e f g ; param entr := a ; param exit := g ; param: ROADS: cap := a b 50, a c 100 b d 40, b e 20 c d 60, c f 20 d e 50, d f 60 e g 70, f g 70 ;
Figure: 15-13
set CITIES; set LINKS within (CITIES cross CITIES); set PRODS; param supply {CITIES,PRODS} >= 0; # amounts available at cities param demand {CITIES,PRODS} >= 0; # amounts required at cities check {p in PRODS}: sum {i in CITIES} supply[i,p] = sum {j in CITIES} demand[j,p]; param cost {LINKS,PRODS} >= 0; # shipment costs/1000 packages param capacity {LINKS,PRODS} >= 0; # max packages shipped param cap_joint {LINKS} >= 0; # max total packages shipped/link minimize Total_Cost; node Balance {k in CITIES, p in PRODS}: net_in = demand[k,p] - supply[k,p]; arc Ship {(i,j) in LINKS, p in PRODS} >= 0, <= capacity[i,j,p], from Balance[i,p], to Balance[j,p], obj Total_Cost cost[i,j,p]; subject to Multi {(i,j) in LINKS}: sum {p in PRODS} Ship[i,j,p] <= cap_joint[i,j];
Figure: 15-14
set CITIES; set LINKS within (CITIES cross CITIES); set PRODS; param supply {PRODS,CITIES} >= 0; # amounts available at cities param demand {PRODS,CITIES} >= 0; # amounts required at cities check {p in PRODS}: sum {i in CITIES} supply[p,i] = sum {j in CITIES} demand[p,j]; param cost {PRODS,LINKS} >= 0; # shipment costs/1000 packages param capacity {PRODS,LINKS} >= 0; # max packages shipped of product set FEEDS; param yield {PRODS,FEEDS} >= 0; # amounts derived from feedstocks param limit {FEEDS,CITIES} >= 0; # feedstocks available at cities minimize Total_Cost; var Feed {f in FEEDS, k in CITIES} >= 0, <= limit[f,k]; node Balance {p in PRODS, k in CITIES}: net_out = supply[p,k] - demand[p,k] + sum {f in FEEDS} yield[p,f] * Feed[f,k]; arc Ship {p in PRODS, (i,j) in LINKS} >= 0, <= capacity[p,i,j], from Balance[p,i], to Balance[p,j], obj Total_Cost cost[p,i,j];
Figure: 15-15
set CITIES; set LINKS within (CITIES cross CITIES); param supply {CITIES} >= 0; # amounts available at cities param demand {CITIES} >= 0; # amounts required at cities check: sum {i in CITIES} supply[i] = sum {j in CITIES} demand[j]; param cost {LINKS} >= 0; # shipment costs per ton param city_cap {CITIES} >= 0; # max throughput at cities param link_cap {LINKS} >= 0; # max shipment over links minimize Total_Cost; node Supply {k in CITIES}: net_out = supply[k]; node Demand {k in CITIES}: net_in = demand[k]; arc Ship {(i,j) in LINKS} >= 0, <= link_cap[i,j], from Demand[i], to Supply[j], obj Total_Cost cost[i,j]; arc Through {k in CITIES} >= 0, <= city_cap[k], from Supply[k], to Demand[k];
Figure: 16-1
set MAT; # materials set ACT; # activities param io {MAT,ACT}; # input-output coefficients param revenue {ACT}; param act_min {ACT} >= 0; param act_max {j in ACT} >= act_min[j]; var Run {j in ACT} >= act_min[j], <= act_max[j]; maximize Net_Profit: sum {j in ACT} revenue[j] * Run[j]; subject to Balance {i in MAT}: sum {j in ACT} io[i,j] * Run[j] = 0;
Figure: 16-2
set MAT; # materials set ACT; # activities param io {MAT,ACT}; # input-output coefficients param revenue {ACT}; param act_min {ACT} >= 0; param act_max {j in ACT} >= act_min[j]; maximize Net_Profit; subject to Balance {i in MAT}: to_come = 0; var Run {j in ACT} >= act_min[j], <= act_max[j], obj Net_Profit revenue[j], coeff {i in MAT} Balance[i] io[i,j];
Figure: 16-3
set MAT; # materials set ACT; # activities param io {MAT,ACT}; # input-output coefficients set MATF within MAT; # finished materials param revenue {MATF} >= 0; param sell_min {MATF} >= 0; param sell_max {i in MATF} >= sell_min[i]; param cost {ACT} >= 0; param act_min {ACT} >= 0; param act_max {j in ACT} >= act_min[j]; maximize Net_Profit; subject to Balance {i in MAT}: to_come = 0; var Run {j in ACT} >= act_min[j], <= act_max[j], obj Net_Profit -cost[j], coeff {i in MAT} Balance[i] io[i,j]; var Sell {i in MATF} >= sell_min[i], <= sell_max[i], obj Net_Profit revenue[i], coeff Balance[i] -1;
Figure: 16-4
set SHIFTS; # shifts param Nsched; # number of schedules; set SCHEDS = 1..Nsched; # set of schedules set SHIFT_LIST {SCHEDS} within SHIFTS; param rate {SCHEDS} >= 0; param required {SHIFTS} >= 0; minimize Total_Cost; subject to Shift_Needs {i in SHIFTS}: to_come >= required[i]; var Work {j in SCHEDS} >= 0, obj Total_Cost rate[j], coeff {i in SHIFT_LIST[j]} Shift_Needs[i] 1;
Figure: 16-5
data; set SHIFTS := Mon1 Tue1 Wed1 Thu1 Fri1 Sat1 Mon2 Tue2 Wed2 Thu2 Fri2 Sat2 Mon3 Tue3 Wed3 Thu3 Fri3 ; param Nsched := 126 ; set SHIFT_LIST[ 1] := Mon1 Tue1 Wed1 Thu1 Fri1 ; set SHIFT_LIST[ 2] := Mon1 Tue1 Wed1 Thu1 Fri2 ; set SHIFT_LIST[ 3] := Mon1 Tue1 Wed1 Thu1 Fri3 ; set SHIFT_LIST[ 4] := Mon1 Tue1 Wed1 Thu1 Sat1 ; set SHIFT_LIST[ 5] := Mon1 Tue1 Wed1 Thu1 Sat2 ; set SHIFT_LIST[ 6] := Mon1 Tue1 Wed1 Thu2 Fri2 ; set SHIFT_LIST[ 7] := Mon1 Tue1 Wed1 Thu2 Fri3 ; set SHIFT_LIST[ 8] := Mon1 Tue1 Wed1 Thu2 Sat1 ; set SHIFT_LIST[ 9] := Mon1 Tue1 Wed1 Thu2 Sat2 ; set SHIFT_LIST[ 10] := Mon1 Tue1 Wed1 Thu3 Fri3 ; set SHIFT_LIST[ 11] := Mon1 Tue1 Wed1 Thu3 Sat1 ; set SHIFT_LIST[ 12] := Mon1 Tue1 Wed1 Thu3 Sat2 ; set SHIFT_LIST[ 13] := Mon1 Tue1 Wed1 Fri1 Sat1 ; set SHIFT_LIST[ 14] := Mon1 Tue1 Wed1 Fri1 Sat2 ; set SHIFT_LIST[ 15] := Mon1 Tue1 Wed1 Fri2 Sat2 ; set SHIFT_LIST[ 16] := Mon1 Tue1 Wed2 Thu2 Fri2 ; set SHIFT_LIST[ 17] := Mon1 Tue1 Wed2 Thu2 Fri3 ; set SHIFT_LIST[ 18] := Mon1 Tue1 Wed2 Thu2 Sat1 ; set SHIFT_LIST[ 19] := Mon1 Tue1 Wed2 Thu2 Sat2 ; set SHIFT_LIST[ 20] := Mon1 Tue1 Wed2 Thu3 Fri3 ; set SHIFT_LIST[ 21] := Mon1 Tue1 Wed2 Thu3 Sat1 ; set SHIFT_LIST[ 22] := Mon1 Tue1 Wed2 Thu3 Sat2 ; set SHIFT_LIST[ 23] := Mon1 Tue1 Wed2 Fri1 Sat1 ; set SHIFT_LIST[ 24] := Mon1 Tue1 Wed2 Fri1 Sat2 ; set SHIFT_LIST[ 25] := Mon1 Tue1 Wed2 Fri2 Sat2 ; set SHIFT_LIST[ 26] := Mon1 Tue1 Wed3 Thu3 Fri3 ; set SHIFT_LIST[ 27] := Mon1 Tue1 Wed3 Thu3 Sat1 ; set SHIFT_LIST[ 28] := Mon1 Tue1 Wed3 Thu3 Sat2 ; set SHIFT_LIST[ 29] := Mon1 Tue1 Wed3 Fri1 Sat1 ; set SHIFT_LIST[ 30] := Mon1 Tue1 Wed3 Fri1 Sat2 ; set SHIFT_LIST[ 31] := Mon1 Tue1 Wed3 Fri2 Sat2 ; set SHIFT_LIST[ 32] := Mon1 Tue1 Thu1 Fri1 Sat1 ; set SHIFT_LIST[ 33] := Mon1 Tue1 Thu1 Fri1 Sat2 ; set SHIFT_LIST[ 34] := Mon1 Tue1 Thu1 Fri2 Sat2 ; set SHIFT_LIST[ 35] := Mon1 Tue1 Thu2 Fri2 Sat2 ; set SHIFT_LIST[ 36] := Mon1 Tue2 Wed2 Thu2 Fri2 ; set SHIFT_LIST[ 37] := Mon1 Tue2 Wed2 Thu2 Fri3 ; set SHIFT_LIST[ 38] := Mon1 Tue2 Wed2 Thu2 Sat1 ; set SHIFT_LIST[ 39] := Mon1 Tue2 Wed2 Thu2 Sat2 ; set SHIFT_LIST[ 40] := Mon1 Tue2 Wed2 Thu3 Fri3 ; set SHIFT_LIST[ 41] := Mon1 Tue2 Wed2 Thu3 Sat1 ; set SHIFT_LIST[ 42] := Mon1 Tue2 Wed2 Thu3 Sat2 ; set SHIFT_LIST[ 43] := Mon1 Tue2 Wed2 Fri1 Sat1 ; set SHIFT_LIST[ 44] := Mon1 Tue2 Wed2 Fri1 Sat2 ; set SHIFT_LIST[ 45] := Mon1 Tue2 Wed2 Fri2 Sat2 ; set SHIFT_LIST[ 46] := Mon1 Tue2 Wed3 Thu3 Fri3 ; set SHIFT_LIST[ 47] := Mon1 Tue2 Wed3 Thu3 Sat1 ; set SHIFT_LIST[ 48] := Mon1 Tue2 Wed3 Thu3 Sat2 ; set SHIFT_LIST[ 49] := Mon1 Tue2 Wed3 Fri1 Sat1 ; set SHIFT_LIST[ 50] := Mon1 Tue2 Wed3 Fri1 Sat2 ; set SHIFT_LIST[ 51] := Mon1 Tue2 Wed3 Fri2 Sat2 ; set SHIFT_LIST[ 52] := Mon1 Tue2 Thu1 Fri1 Sat1 ; set SHIFT_LIST[ 53] := Mon1 Tue2 Thu1 Fri1 Sat2 ; set SHIFT_LIST[ 54] := Mon1 Tue2 Thu1 Fri2 Sat2 ; set SHIFT_LIST[ 55] := Mon1 Tue2 Thu2 Fri2 Sat2 ; set SHIFT_LIST[ 56] := Mon1 Tue3 Wed3 Thu3 Fri3 ; set SHIFT_LIST[ 57] := Mon1 Tue3 Wed3 Thu3 Sat1 ; set SHIFT_LIST[ 58] := Mon1 Tue3 Wed3 Thu3 Sat2 ; set SHIFT_LIST[ 59] := Mon1 Tue3 Wed3 Fri1 Sat1 ; set SHIFT_LIST[ 60] := Mon1 Tue3 Wed3 Fri1 Sat2 ; set SHIFT_LIST[ 61] := Mon1 Tue3 Wed3 Fri2 Sat2 ; set SHIFT_LIST[ 62] := Mon1 Tue3 Thu1 Fri1 Sat1 ; set SHIFT_LIST[ 63] := Mon1 Tue3 Thu1 Fri1 Sat2 ; set SHIFT_LIST[ 64] := Mon1 Tue3 Thu1 Fri2 Sat2 ; set SHIFT_LIST[ 65] := Mon1 Tue3 Thu2 Fri2 Sat2 ; set SHIFT_LIST[ 66] := Mon1 Wed1 Thu1 Fri1 Sat1 ; set SHIFT_LIST[ 67] := Mon1 Wed1 Thu1 Fri1 Sat2 ; set SHIFT_LIST[ 68] := Mon1 Wed1 Thu1 Fri2 Sat2 ; set SHIFT_LIST[ 69] := Mon1 Wed1 Thu2 Fri2 Sat2 ; set SHIFT_LIST[ 70] := Mon1 Wed2 Thu2 Fri2 Sat2 ; set SHIFT_LIST[ 71] := Mon2 Tue2 Wed2 Thu2 Fri2 ; set SHIFT_LIST[ 72] := Mon2 Tue2 Wed2 Thu2 Fri3 ; set SHIFT_LIST[ 73] := Mon2 Tue2 Wed2 Thu2 Sat1 ; set SHIFT_LIST[ 74] := Mon2 Tue2 Wed2 Thu2 Sat2 ; set SHIFT_LIST[ 75] := Mon2 Tue2 Wed2 Thu3 Fri3 ; set SHIFT_LIST[ 76] := Mon2 Tue2 Wed2 Thu3 Sat1 ; set SHIFT_LIST[ 77] := Mon2 Tue2 Wed2 Thu3 Sat2 ; set SHIFT_LIST[ 78] := Mon2 Tue2 Wed2 Fri1 Sat1 ; set SHIFT_LIST[ 79] := Mon2 Tue2 Wed2 Fri1 Sat2 ; set SHIFT_LIST[ 80] := Mon2 Tue2 Wed2 Fri2 Sat2 ; set SHIFT_LIST[ 81] := Mon2 Tue2 Wed3 Thu3 Fri3 ; set SHIFT_LIST[ 82] := Mon2 Tue2 Wed3 Thu3 Sat1 ; set SHIFT_LIST[ 83] := Mon2 Tue2 Wed3 Thu3 Sat2 ; set SHIFT_LIST[ 84] := Mon2 Tue2 Wed3 Fri1 Sat1 ; set SHIFT_LIST[ 85] := Mon2 Tue2 Wed3 Fri1 Sat2 ; set SHIFT_LIST[ 86] := Mon2 Tue2 Wed3 Fri2 Sat2 ; set SHIFT_LIST[ 87] := Mon2 Tue2 Thu1 Fri1 Sat1 ; set SHIFT_LIST[ 88] := Mon2 Tue2 Thu1 Fri1 Sat2 ; set SHIFT_LIST[ 89] := Mon2 Tue2 Thu1 Fri2 Sat2 ; set SHIFT_LIST[ 90] := Mon2 Tue2 Thu2 Fri2 Sat2 ; set SHIFT_LIST[ 91] := Mon2 Tue3 Wed3 Thu3 Fri3 ; set SHIFT_LIST[ 92] := Mon2 Tue3 Wed3 Thu3 Sat1 ; set SHIFT_LIST[ 93] := Mon2 Tue3 Wed3 Thu3 Sat2 ; set SHIFT_LIST[ 94] := Mon2 Tue3 Wed3 Fri1 Sat1 ; set SHIFT_LIST[ 95] := Mon2 Tue3 Wed3 Fri1 Sat2 ; set SHIFT_LIST[ 96] := Mon2 Tue3 Wed3 Fri2 Sat2 ; set SHIFT_LIST[ 97] := Mon2 Tue3 Thu1 Fri1 Sat1 ; set SHIFT_LIST[ 98] := Mon2 Tue3 Thu1 Fri1 Sat2 ; set SHIFT_LIST[ 99] := Mon2 Tue3 Thu1 Fri2 Sat2 ; set SHIFT_LIST[100] := Mon2 Tue3 Thu2 Fri2 Sat2 ; set SHIFT_LIST[101] := Mon2 Wed1 Thu1 Fri1 Sat1 ; set SHIFT_LIST[102] := Mon2 Wed1 Thu1 Fri1 Sat2 ; set SHIFT_LIST[103] := Mon2 Wed1 Thu1 Fri2 Sat2 ; set SHIFT_LIST[104] := Mon2 Wed1 Thu2 Fri2 Sat2 ; set SHIFT_LIST[105] := Mon2 Wed2 Thu2 Fri2 Sat2 ; set SHIFT_LIST[106] := Mon3 Tue3 Wed3 Thu3 Fri3 ; set SHIFT_LIST[107] := Mon3 Tue3 Wed3 Thu3 Sat1 ; set SHIFT_LIST[108] := Mon3 Tue3 Wed3 Thu3 Sat2 ; set SHIFT_LIST[109] := Mon3 Tue3 Wed3 Fri1 Sat1 ; set SHIFT_LIST[110] := Mon3 Tue3 Wed3 Fri1 Sat2 ; set SHIFT_LIST[111] := Mon3 Tue3 Wed3 Fri2 Sat2 ; set SHIFT_LIST[112] := Mon3 Tue3 Thu1 Fri1 Sat1 ; set SHIFT_LIST[113] := Mon3 Tue3 Thu1 Fri1 Sat2 ; set SHIFT_LIST[114] := Mon3 Tue3 Thu1 Fri2 Sat2 ; set SHIFT_LIST[115] := Mon3 Tue3 Thu2 Fri2 Sat2 ; set SHIFT_LIST[116] := Mon3 Wed1 Thu1 Fri1 Sat1 ; set SHIFT_LIST[117] := Mon3 Wed1 Thu1 Fri1 Sat2 ; set SHIFT_LIST[118] := Mon3 Wed1 Thu1 Fri2 Sat2 ; set SHIFT_LIST[119] := Mon3 Wed1 Thu2 Fri2 Sat2 ; set SHIFT_LIST[120] := Mon3 Wed2 Thu2 Fri2 Sat2 ; set SHIFT_LIST[121] := Tue1 Wed1 Thu1 Fri1 Sat1 ; set SHIFT_LIST[122] := Tue1 Wed1 Thu1 Fri1 Sat2 ; set SHIFT_LIST[123] := Tue1 Wed1 Thu1 Fri2 Sat2 ; set SHIFT_LIST[124] := Tue1 Wed1 Thu2 Fri2 Sat2 ; set SHIFT_LIST[125] := Tue1 Wed2 Thu2 Fri2 Sat2 ; set SHIFT_LIST[126] := Tue2 Wed2 Thu2 Fri2 Sat2 ; param rate default 1 ; param required := Mon1 100 Mon2 78 Mon3 52 Tue1 100 Tue2 78 Tue3 52 Wed1 100 Wed2 78 Wed3 52 Thu1 100 Thu2 78 Thu3 52 Fri1 100 Fri2 78 Fri3 52 Sat1 100 Sat2 78 ;
Figure: 16-6
set CITIES; set LINKS within (CITIES cross CITIES); set PRODS; param supply {CITIES,PRODS} >= 0; # amounts available at cities param demand {CITIES,PRODS} >= 0; # amounts required at cities check {p in PRODS}: sum {i in CITIES} supply[i,p] = sum {j in CITIES} demand[j,p]; param cost {LINKS,PRODS} >= 0; # shipment costs/1000 packages param capacity {LINKS,PRODS} >= 0; # max packages shipped param cap_joint {LINKS} >= 0; # max total packages shipped/link minimize Total_Cost; node Balance {k in CITIES, p in PRODS}: net_in = demand[k,p] - supply[k,p]; subject to Multi {(i,j) in LINKS}: to_come <= cap_joint[i,j]; arc Ship {(i,j) in LINKS, p in PRODS} >= 0, <= capacity[i,j,p], from Balance[i,p], to Balance[j,p], coeff Multi[i,j] 1.0, obj Total_Cost cost[i,j,p];
Figure: 17-2
set ORIG; # origins set DEST; # destinations param supply {ORIG} >= 0; # amounts available at origins param demand {DEST} >= 0; # amounts required at destinations check: sum {i in ORIG} supply[i] = sum {j in DEST} demand[j]; param rate1 {i in ORIG, j in DEST} >= 0; param rate2 {i in ORIG, j in DEST} >= rate1[i,j]; param rate3 {i in ORIG, j in DEST} >= rate2[i,j]; param limit1 {i in ORIG, j in DEST} > 0; param limit2 {i in ORIG, j in DEST} > limit1[i,j]; var Trans {ORIG,DEST} >= 0; # units to be shipped minimize Total_Cost: sum {i in ORIG, j in DEST} <<limit1[i,j], limit2[i,j]; rate1[i,j], rate2[i,j], rate3[i,j]>> Trans[i,j]; subject to Supply {i in ORIG}: sum {j in DEST} Trans[i,j] = supply[i]; subject to Demand {j in DEST}: sum {i in ORIG} Trans[i,j] = demand[j];
Figure: 17-3a
set ORIG; # origins set DEST; # destinations param supply {ORIG} >= 0; # amounts available at origins param demand {DEST} >= 0; # amounts required at destinations check: sum {i in ORIG} supply[i] = sum {j in DEST} demand[j]; param npiece {ORIG,DEST} integer >= 1; param rate {i in ORIG, j in DEST, p in 1..npiece[i,j]} >= if p = 1 then 0 else rate[i,j,p-1]; param limit {i in ORIG, j in DEST, p in 1..npiece[i,j]-1} > if p = 1 then 0 else limit[i,j,p-1]; var Trans {ORIG,DEST} >= 0; # units to be shipped minimize Total_Cost: sum {i in ORIG, j in DEST} <<{p in 1..npiece[i,j]-1} limit[i,j,p]; {p in 1..npiece[i,j]} rate[i,j,p]>> Trans[i,j]; subject to Supply {i in ORIG}: sum {j in DEST} Trans[i,j] = supply[i]; subject to Demand {j in DEST}: sum {i in ORIG} Trans[i,j] = demand[j];
Figure: 17-3b
data;
param: ORIG: supply :=
GARY 1400 CLEV 2600 PITT 2900 ;
param: DEST: demand :=
FRA 900 DET 1200 LAN 600 WIN 400
STL 1700 FRE 1100 LAF 1000 ;
param npiece: FRA DET LAN WIN STL FRE LAF :=
GARY 3 3 3 2 3 2 3
CLEV 3 3 3 3 3 3 3
PITT 2 2 2 2 1 2 1 ;
param rate :=
[GARY,FRA,*] 1 39 2 50 3 70 [GARY,DET,*] 1 14 2 17 3 33
[GARY,LAN,*] 1 11 2 12 3 23 [GARY,WIN,*] 1 14 2 17
[GARY,STL,*] 1 16 2 23 3 40 [GARY,FRE,*] 1 82 2 98
[GARY,LAF,*] 1 8 2 16 3 24
[CLEV,FRA,*] 1 27 2 37 3 47 [CLEV,DET,*] 1 9 2 19 3 24
[CLEV,LAN,*] 1 12 2 32 3 39 [CLEV,WIN,*] 1 9 2 14 3 21
[CLEV,STL,*] 1 26 2 36 3 47 [CLEV,FRE,*] 1 95 2 105 3 129
[CLEV,LAF,*] 1 8 2 16 3 24
[PITT,FRA,*] 1 24 2 34 [PITT,DET,*] 1 14 2 24
[PITT,LAN,*] 1 17 2 27 [PITT,WIN,*] 1 13 2 23
[PITT,STL,*] 1 28 [PITT,FRE,*] 1 99 2 140
[PITT,LAF,*] 1 20 ;
param limit :=
[GARY,*,*] FRA 1 500 FRA 2 1000 DET 1 500 DET 2 1000
LAN 1 500 LAN 2 1000 WIN 1 1000
STL 1 500 STL 2 1000 FRE 1 1000
LAF 1 500 LAF 2 1000
[CLEV,*,*] FRA 1 500 FRA 2 1000 DET 1 500 DET 2 1000
LAN 1 500 LAN 2 1000 WIN 1 500 WIN 2 1000
STL 1 500 STL 2 1000 FRE 1 500 FRE 2 1000
LAF 1 500 LAF 2 1000
[PITT,*,*] FRA 1 1000 DET 1 1000 LAN 1 1000 WIN 1 1000
FRE 1 1000 ;
Figure: 17-5a
set PROD; # products param T > 0; # number of weeks param rate {PROD} > 0; # tons per hour produced param inv0 {PROD} >= 0; # initial inventory param commit {PROD,1..T} >= 0; # minimum tons sold in week param market {PROD,1..T} >= 0; # limit on tons sold in week param avail_min {1..T} >= 0; # unpenalized hours available param avail_max {t in 1..T} >= avail_min[t]; # total hours avail param time_penalty {1..T} > 0; param prodcost {PROD} >= 0; # cost/ton produced param invcost {PROD} >= 0; # carrying cost/ton of inventory param revenue {PROD,1..T} >= 0; # revenue/ton sold var Make {PROD,1..T} >= 0; # tons produced var Inv {PROD,0..T} >= 0; # tons inventoried var Sell {p in PROD, t in 1..T} >= commit[p,t], <= market[p,t]; # tons sold var Use {t in 1..T} >= 0, <= avail_max[t]; # hours used maximize Total_Profit: sum {p in PROD, t in 1..T} (revenue[p,t]*Sell[p,t] - prodcost[p]*Make[p,t] - invcost[p]*Inv[p,t]) - sum {t in 1..T} <<avail_min[t]; 0,time_penalty[t]>> Use[t]; # Objective: total revenue less costs in all weeks subject to Time {t in 1..T}: sum {p in PROD} (1/rate[p]) * Make[p,t] = Use[t]; # Total of hours used by all products # may not exceed hours available, in each week subject to Init_Inv {p in PROD}: Inv[p,0] = inv0[p]; # Initial inventory must equal given value subject to Balance {p in PROD, t in 1..T}: Make[p,t] + Inv[p,t-1] = Sell[p,t] + Inv[p,t]; # Tons produced and taken from inventory # must equal tons sold and put into inventory
Figure: 17-5b
data; param T := 4; set PROD := bands coils; param: rate inv0 prodcost invcost := bands 200 10 10 2.5 coils 140 0 11 3 ; param: avail_min avail_max time_penalty := 1 35 42 3100 2 35 42 3000 3 30 40 3700 4 35 42 3100 ; param revenue: 1 2 3 4 := bands 25 26 27 27 coils 30 35 37 39 ; param commit: 1 2 3 4 := bands 3000 3000 3000 3000 coils 2000 2000 2000 2000 ; param market: 1 2 3 4 := bands 6000 6000 4000 6500 coils 4000 2500 3500 4200 ;
Figure: 17-9
set PEOPLE; set PROJECTS; param supply {PEOPLE} >= 0; # hours each person is available param demand {PROJECTS} >= 0; # hours each project requires check: sum {i in PEOPLE} supply[i] = sum {j in PROJECTS} demand[j]; param cost {PEOPLE,PROJECTS} >= 0; # cost per hour of work param limit {PEOPLE,PROJECTS} >= 0; # maximum contributions # to projects var M; var Assign {i in PEOPLE, j in PROJECTS} >= 0, <= limit[i,j]; minimize Max_Cost: M; subject to M_def {i in PEOPLE}: M >= sum {j in PROJECTS} cost[i,j] * Assign[i,j]; subject to Supply {i in PEOPLE}: sum {j in PROJECTS} Assign[i,j] = supply[i]; subject to Demand {j in PROJECTS}: sum {i in PEOPLE} Assign[i,j] = demand[j];
Figure: 18-4
set ORIG; # origins set DEST; # destinations param supply {ORIG} >= 0; # amounts available at origins param demand {DEST} >= 0; # amounts required at destinations check: sum {i in ORIG} supply[i] = sum {j in DEST} demand[j]; param rate {ORIG,DEST} >= 0; # base shipment costs per unit param limit {ORIG,DEST} > 0; # limit on units shipped var Trans {i in ORIG, j in DEST} >= 0; # units to ship minimize Total_Cost: sum {i in ORIG, j in DEST} rate[i,j] * Trans[i,j] / (1 - Trans[i,j]/limit[i,j]); subject to Supply {i in ORIG}: sum {j in DEST} Trans[i,j] = supply[i]; subject to Demand {j in DEST}: sum {i in ORIG} Trans[i,j] = demand[j];
Figure: 18-5
data; param: ORIG: supply := GARY 1400 CLEV 2600 PITT 2900 ; param: DEST: demand := FRA 900 DET 1200 LAN 600 WIN 400 STL 1700 FRE 1100 LAF 1000 ; param rate : FRA DET LAN WIN STL FRE LAF := GARY 39 14 11 14 16 82 8 CLEV 27 9 12 9 26 95 17 PITT 24 14 17 13 28 99 20 ; param limit : FRA DET LAN WIN STL FRE LAF := GARY 500 1000 1000 1000 800 500 1000 CLEV 500 800 800 800 500 500 1000 PITT 800 600 600 600 500 500 900 ;
Figure: 19-1
set PROD; # products set ACT; # activities param cost {ACT} > 0; # cost per unit of each activity param demand {PROD} >= 0; # units of demand for each product param io {PROD,ACT} >= 0; # units of each product from # 1 unit of each activity var Level {j in ACT} >= 0; minimize Total_Cost: sum {j in ACT} cost[j] * Level[j]; subject to Demand {i in PROD}: sum {j in ACT} io[i,j] * Level[j] >= demand[i];
Figure: 19-2