Refinery Optimization (mpex06)

/***************************************************************/
/*                                                             */
/*          S A S   S A M P L E   L I B R A R Y                */
/*                                                             */
/*    NAME: mpex06                                             */
/*   TITLE: Refinery Optimization (mpex06)                     */
/* PRODUCT: OR                                                 */
/*  SYSTEM: ALL                                                */
/*   PROCS: OPTMODEL                                           */
/*    DATA:                                                    */
/*                                                             */
/* SUPPORT:                             UPDATE:                */
/*     REF:                                                    */
/*    MISC: Example 06 from the Mathematical Programming       */
/*          Examples book.                                     */
/*                                                             */
/***************************************************************/

data crude_data;
   input crude $ crude_ub;
   datalines;
crude1 20000
crude2 30000
;

data arc_data;
   input i $18. j $18. multiplier;
   datalines;
source            crude1            6
source            crude2            6
crude1            light_naphtha     0.1
crude1            medium_naphtha    0.2
crude1            heavy_naphtha     0.2
crude1            light_oil         0.12
crude1            heavy_oil         0.2
crude1            residuum          0.13
crude2            light_naphtha     0.15
crude2            medium_naphtha    0.25
crude2            heavy_naphtha     0.18
crude2            light_oil         0.08
crude2            heavy_oil         0.19
crude2            residuum          0.12
light_naphtha     regular_petrol    .
light_naphtha     premium_petrol    .
medium_naphtha    regular_petrol    .
medium_naphtha    premium_petrol    .
heavy_naphtha     regular_petrol    .
heavy_naphtha     premium_petrol    .
light_naphtha     reformed_gasoline 0.6
medium_naphtha    reformed_gasoline 0.52
heavy_naphtha     reformed_gasoline 0.45
light_oil         jet_fuel          .
light_oil         fuel_oil          .
heavy_oil         jet_fuel          .
heavy_oil         fuel_oil          .
light_oil         light_oil_cracked 2
light_oil_cracked cracked_oil       0.68
light_oil_cracked cracked_gasoline  0.28
heavy_oil         heavy_oil_cracked 2
heavy_oil_cracked cracked_oil       0.75
heavy_oil_cracked cracked_gasoline  0.2
cracked_oil       jet_fuel          .
cracked_oil       fuel_oil          .
reformed_gasoline regular_petrol    .
reformed_gasoline premium_petrol    .
cracked_gasoline  regular_petrol    .
cracked_gasoline  premium_petrol    .
residuum          lube_oil          0.5
residuum          jet_fuel          .
residuum          fuel_oil          .
;

data octane_data;
   input i $18. octane;
   datalines;
light_naphtha      90
medium_naphtha     80
heavy_naphtha      70
reformed_gasoline 115
cracked_gasoline  105
;

data petrol_data;
   input petrol $15. octane_lb;
   datalines;
regular_petrol 84
premium_petrol 94
;

data vapour_pressure_data;
   input oil $12. vapour_pressure;
   datalines;
light_oil   1.0
heavy_oil   0.6
cracked_oil 1.5
residuum    0.05
;

data fuel_oil_ratio_data;
   input oil $12. coefficient;
   datalines;
light_oil   10
cracked_oil  4
heavy_oil    3
residuum     1
;

data final_product_data;
   input product $15. profit;
   datalines;
premium_petrol 700
regular_petrol 600
jet_fuel       400
fuel_oil       350
lube_oil       150
;

%let vapour_pressure_ub = 1;
%let crude_total_ub = 45000;
%let naphtha_ub = 10000;
%let cracked_oil_ub = 8000;
%let lube_oil_lb = 500;
%let lube_oil_ub = 1000;
%let premium_ratio = 0.40;

proc optmodel;
   set <str,str> ARCS;
   num arc_mult {ARCS} init 1;
   read data arc_data nomiss into ARCS=[i j] arc_mult=multiplier;
   var Flow {ARCS} >= 0;

   set <str> FINAL_PRODUCTS;
   num profit {FINAL_PRODUCTS};
   read data final_product_data into FINAL_PRODUCTS=[product] profit;

   for {product in FINAL_PRODUCTS} profit[product] = profit[product] / 100;

   ARCS = ARCS union (FINAL_PRODUCTS cross {'sink'});

   set NODES = union {<i,j> in ARCS} {i,j};

   max TotalProfit = sum {i in FINAL_PRODUCTS} profit[i] * Flow[i,'sink'];

   con Flow_balance {i in NODES diff {'source','sink'}}:
      sum {<(i),j> in ARCS} Flow[i,j]
         = sum {<j,(i)> in ARCS} arc_mult[j,i] * Flow[j,i];

   set <str> CRUDES;
   var CrudeDistilled {CRUDES} >= 0;

   read data crude_data into CRUDES=[crude] CrudeDistilled.ub=crude_ub;
   con Distillation {<i,j> in ARCS: i in CRUDES}:
      Flow[i,j] = CrudeDistilled[i];

   set OILS = {'light_oil','heavy_oil'};
   set CRACKED_OILS = setof {i in OILS} i||'_cracked';
   var OilCracked {CRACKED_OILS} >= 0;
   con Cracking {<i,j> in ARCS: i in CRACKED_OILS}:
      Flow[i,j] = OilCracked[i];

   num octane {NODES} init .;
   read data octane_data nomiss into [i] octane;

   set <str> PETROLS;
   num octane_lb {PETROLS};
   read data petrol_data into PETROLS=[petrol] octane_lb;

   num vapour_pressure {NODES} init .;
   read data vapour_pressure_data nomiss into [oil] vapour_pressure;

   con Blending_petrol {petrol in PETROLS}:
      sum {<i,(petrol)> in ARCS}
         octane[i] * arc_mult[i,petrol] * Flow[i,petrol]
   >= octane_lb[petrol] *
      sum {<i,(petrol)> in ARCS} arc_mult[i,petrol] * Flow[i,petrol];

   con Blending_jet_fuel:
      sum {<i,'jet_fuel'> in ARCS}
         vapour_pressure[i] * arc_mult[i,'jet_fuel'] * Flow[i,'jet_fuel']
   <= &vapour_pressure_ub *
      sum {<i,'jet_fuel'> in ARCS} arc_mult[i,'jet_fuel'] * Flow[i,'jet_fuel'];

   num fuel_oil_coefficient {NODES} init 0;
   read data fuel_oil_ratio_data nomiss into [oil]
      fuel_oil_coefficient=coefficient;
   num sum_fuel_oil_coefficient
      = sum {<i,'fuel_oil'> in ARCS} fuel_oil_coefficient[i];
   con Blending_fuel_oil {<i,'fuel_oil'> in ARCS}:
      sum_fuel_oil_coefficient * Flow[i,'fuel_oil']
   = fuel_oil_coefficient[i] * sum {<j,'fuel_oil'> in ARCS} Flow[j,'fuel_oil'];

   con Crude_total_ub_con:
      sum {i in CRUDES} CrudeDistilled[i] <= &crude_total_ub;

   con Naphtha_ub_con:
      sum {<i,'reformed_gasoline'> in ARCS: index(i,'naphtha') > 0}
         Flow[i,'reformed_gasoline']
   <= &naphtha_ub;

   con Cracked_oil_ub_con:
      sum {<i,'cracked_oil'> in ARCS} Flow[i,'cracked_oil'] <= &cracked_oil_ub;

   con Lube_oil_range_con:
      &lube_oil_lb <= Flow['lube_oil','sink'] <= &lube_oil_ub;

   con Premium_ratio_con:
      sum {<'premium_petrol',j> in ARCS} Flow['premium_petrol',j]
   >= &premium_ratio *
      sum {<'regular_petrol',j> in ARCS} Flow['regular_petrol',j];

   num octane_sol {petrol in PETROLS} =
      (sum {<i,(petrol)> in ARCS}
         octane[i] * arc_mult[i,petrol] * Flow[i,petrol].sol) /
      (sum {<i,(petrol)> in ARCS} arc_mult[i,petrol] * Flow[i,petrol].sol);

   num vapour_pressure_sol =
      (sum {<i,'jet_fuel'> in ARCS} vapour_pressure[i] *
         arc_mult[i,'jet_fuel'] * Flow[i,'jet_fuel'].sol)
      / (sum {<i,'jet_fuel'> in ARCS} arc_mult[i,'jet_fuel'] *
         Flow[i,'jet_fuel'].sol);

   num fuel_oil_ratio_sol {<i,'fuel_oil'> in ARCS} =
      (arc_mult[i,'fuel_oil'] * Flow[i,'fuel_oil'].sol) /
      (sum {<j,'fuel_oil'> in ARCS} arc_mult[j,'fuel_oil'] *
         Flow[j,'fuel_oil'].sol);

   solve;
   print CrudeDistilled;
   print OilCracked Flow;
   print octane_sol octane_lb;

   print {<i,'jet_fuel'> in ARCS} vapour_pressure vapour_pressure_sol;
   print {<i,'fuel_oil'> in ARCS} fuel_oil_coefficient fuel_oil_ratio_sol;
   create data sol_data1 from [i j] Flow;
quit;