# ----------------------------------------
# STOCHASTIC PROGRAMMING PROBLEM
# USING BENDERS DECOMPOSITION
# ----------------------------------------
### SUBPROBLEM (always feasible) ###
set PROD; # products
param T > 0; # number of weeks
set SCEN; # number of scenarios
param rate {PROD} > 0; # tons per hour produced
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,SCEN} >= 0; # projected revenue/ton
param prob {SCEN} >= 0, <= 1;
check: 0.99999 < sum {s in SCEN} prob[s] < 1.00001;
param inv1 {PROD} >= 0; # inventory at end of first period
var Make {PROD,2..T,SCEN} >= 0; # tons produced
var Inv {PROD,2..T,SCEN} >= 0; # tons inventoried
var Sell {p in PROD, t in 2..T, SCEN} # tons sold
>= 0, <= market[p,t];
maximize Stage2_Profit:
sum {s in SCEN} prob[s] *
sum {p in PROD, t in 2..T} (revenue[p,t,s]*Sell[p,t,s] -
prodcost[p]*Make[p,t,s] - invcost[p]*Inv[p,t,s]);
subject to Time {t in 2..T, s in SCEN}:
sum {p in PROD} (1/rate[p]) * Make[p,t,s] <= avail[t];
subject to Balance2 {p in PROD, s in SCEN}:
Make[p,2,s] + inv1[p] = Sell[p,2,s] + Inv[p,2,s];
subject to Balance {p in PROD, t in 3..T, s in SCEN}:
Make[p,t,s] + Inv[p,t-1,s] = Sell[p,t,s] + Inv[p,t,s];
### MASTER PROBLEM ###
param inv0 {PROD} >= 0; # initial inventory
param nCUT >= 0 integer;
param time_price {2..T,SCEN,1..nCUT} >= -0.000001;
param bal2_price {PROD,SCEN,1..nCUT};
param sell_lim_price {PROD,2..T,SCEN,1..nCUT} >= -0.000001;
var Make1 {PROD} >= 0;
var Inv1 {PROD} >= 0;
var Sell1 {p in PROD} >= 0, <= market[p,1];
var Min_Stage2_Profit >= 0;
maximize Expected_Profit:
sum {s in SCEN} prob[s] *
sum {p in PROD} (revenue[p,1,s]*Sell1[p] -
prodcost[p]*Make1[p] - invcost[p]*Inv1[p]) +
Min_Stage2_Profit;
subj to Cut_Defn {k in 1..nCUT}:
Min_Stage2_Profit <=
sum {t in 2..T, s in SCEN} time_price[t,s,k] * avail[t] +
sum {p in PROD, s in SCEN} bal2_price[p,s,k] * (-Inv1[p]) +
sum {p in PROD, t in 2..T, s in SCEN}
sell_lim_price[p,t,s,k] * market[p,t];
subject to Time1:
sum {p in PROD} (1/rate[p]) * Make1[p] <= avail[1];
subject to Balance1 {p in PROD}:
Make1[p] + inv0[p] = Sell1[p] + Inv1[p];