License Portal

Search
Close this search box.

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;

Figure:

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: 19-3

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: 5-1

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 ;

Figure:

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

Figure:

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 ;

Figure:

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

Figure:

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 ;

Figure:

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

Figure:

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

Figure:

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

Figure:

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;

Figure:

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;

Figure:

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

Figure:

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;

Figure:

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

Figure:

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 ;

Figure:

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

Figure:

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

Figure:

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 ;

Figure:

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

Figure:

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 ;

Figure:

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;

Figure:

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

Figure:

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

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

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

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

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: 20-1a

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

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

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

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 ;