The OPTLP Procedure

Example 13.1 Oil Refinery Problem

(View the complete code for this example.)

Consider an oil refinery scenario. A step in refining crude oil into finished oil products involves a distillation process that splits crude into various streams. Suppose there are three types of crude available: Arabian light (a_l), Arabian heavy (a_h), and Brega (br). These crudes are distilled into light naphtha (na_l), intermediate naphtha (na_i), and heating oil (h_o). These in turn are blended into two types of jet fuel. Jet fuel j_1 is made up of 30% intermediate naphtha and 70% heating oil, and jet fuel j_2 is made up of 20% light naphtha and 80% heating oil. What amounts of the three crudes maximize the profit from producing jet fuel (j_1, j_2)? This problem can be formulated as the following linear program:

max minus 175 normal a bar normal l minus 165 normal a bar normal h minus 205 normal b normal r plus 350 normal j bar 1 plus 350 normal j bar 2

subject to

StartLayout 1st Row 1st Column left parenthesis normal n normal a normal p normal h normal a bar normal l right parenthesis 2nd Column 0.035 normal a bar normal l 3rd Column plus 4th Column 0.03 normal a bar normal h 5th Column plus 6th Column 0.045 normal b normal r 7th Column equals 8th Column normal n normal a bar normal l 2nd Row 1st Column left parenthesis normal n normal a normal p normal h normal a bar normal i right parenthesis 2nd Column 0.1 normal a bar normal l 3rd Column plus 4th Column 0.075 normal a bar normal h 5th Column plus 6th Column 0.135 normal b normal r 7th Column equals 8th Column normal n normal a bar normal i 3rd Row 1st Column left parenthesis normal h normal t normal g bar normal o normal i normal l right parenthesis 2nd Column 0.39 normal a bar normal l 3rd Column plus 4th Column 0.3 normal a bar normal h 5th Column plus 6th Column 0.43 normal b normal r 7th Column equals 8th Column normal h bar normal o 4th Row 1st Column left parenthesis normal b normal l normal e normal n normal d Baseline 1 right parenthesis 2nd Column Blank 3rd Column Blank 4th Column 0.3 normal j bar 1 5th Column Blank 6th Column Blank 7th Column less than or equals 8th Column normal n normal a bar normal i 5th Row 1st Column left parenthesis normal b normal l normal e normal n normal d Baseline 2 right parenthesis 2nd Column Blank 3rd Column Blank 4th Column Blank 5th Column Blank 6th Column 0.2 normal j bar 2 7th Column less than or equals 8th Column normal n normal a bar normal l 6th Row 1st Column left parenthesis normal b normal l normal e normal n normal d Baseline 3 right parenthesis 2nd Column Blank 3rd Column Blank 4th Column 0.7 normal j bar 1 5th Column plus 6th Column 0.8 normal j bar 2 7th Column less than or equals 8th Column normal h bar normal o 7th Row 1st Column Blank 2nd Column normal a bar normal l 3rd Column Blank 4th Column Blank 5th Column Blank 6th Column Blank 7th Column less than or equals 8th Column 110 8th Row 1st Column Blank 2nd Column Blank 3rd Column Blank 4th Column normal a bar normal h 5th Column Blank 6th Column Blank 7th Column less than or equals 8th Column 165 9th Row 1st Column Blank 2nd Column Blank 3rd Column Blank 4th Column Blank 5th Column Blank 6th Column normal b normal r 7th Column less than or equals 8th Column 80 EndLayout

and

normal a bar normal l comma normal a bar normal h comma normal b normal r comma normal n normal a bar 1 comma normal n normal a bar normal i comma normal h bar normal o comma normal j bar 1 comma normal j bar 2 greater than or equals 0

The constraints "blend1" and "blend2" ensure that j_1 and j_2 are made with the specified amounts of na_i and na_l, respectively. The constraint "blend3" is actually the reduced form of the following constraints:

StartLayout 1st Row 1st Column normal h bar normal o Baseline 1 2nd Column Blank 3rd Column Blank 4th Column greater than or equals 5th Column 0.7 normal j bar 1 2nd Row 1st Column Blank 2nd Column Blank 3rd Column normal h bar normal o Baseline 2 4th Column greater than or equals 5th Column 0.8 normal j bar 2 3rd Row 1st Column normal h bar normal o Baseline 1 2nd Column plus 3rd Column normal h bar normal o Baseline 2 4th Column less than or equals 5th Column normal h bar normal o EndLayout

where h_o1 and h_o2 are dummy variables.

You can use the following SAS code to create the input data set ex1:

data ex1;
   input field1 $ field2 $ field3 $ field4 field5 $ field6;
   datalines;
NAME        .          EX1      .     .         .
ROWS        .          .        .     .         .
 N          profit     .        .     .         .
 E          napha_l    .        .     .         .
 E          napha_i    .        .     .         .
 E          htg_oil    .        .     .         .
 L          blend1     .        .     .         .
 L          blend2     .        .     .         .
 L          blend3     .        .     .         .
COLUMNS     .          .        .     .         .
.           a_l        profit   -175  napha_l   .035
.           a_l        napha_i  .100  htg_oil   .390
.           a_h        profit   -165  napha_l   .030
.           a_h        napha_i  .075  htg_oil   .300
.           br         profit   -205  napha_l   .045
.           br         napha_i  .135  htg_oil   .430
.           na_l       napha_l  -1    blend2    -1
.           na_i       napha_i  -1    blend1    -1
.           h_o        htg_oil  -1    blend3    -1
.           j_1        profit   350   blend1    .3
.           j_1        blend3   .7    .         .
.           j_2        profit   350   blend2    .2
.           j_2        blend3   .8    .         .
BOUNDS      .          .        .     .         .
UP          .          a_l      110   .         .
UP          .          a_h      165   .         .
UP          .          br       80    .         .
ENDATA      .          .        .     .         .
;

You can use the following call to PROC OPTLP to solve the LP problem:

proc optlp data=ex1
   objsense  = max
   algorithm = primal
   primalout = ex1pout
   dualout   = ex1dout
   logfreq   = 1;
run;
%put &_OROPTLP_;

Note that the OBJSENSE=MAX option is used to indicate that the objective function is to be maximized.

The primal and dual solutions are displayed in Output 13.1.1.

Output 13.1.1: Example 1: Primal and Dual Solution Output

Primal Solution

ObsObjective Function IDRHS IDVariable
Name
Variable
Type
Objective
Coefficient
Lower
Bound
Upper BoundVariable ValueVariable
Status
Reduced Cost
1profit a_lD-1750110110.000U10.2083
2profit a_hD-16501650.000L-22.8125
3profit brD-20508080.000U2.8125
4profit na_lN001.7977E3087.450B0.0000
5profit na_iN001.7977E30821.800B0.0000
6profit h_oN001.7977E30877.300B0.0000
7profit j_1N35001.7977E30872.667B0.0000
8profit j_2N35001.7977E30833.042B0.0000

Dual Solution

ObsObjective Function IDRHS IDConstraint NameConstraint
Type
Constraint
RHS
Constraint
Lower
Bound
Constraint
Upper
Bound
Dual Variable
Value
Constraint
Status
Constraint Activity
1profit napha_lE0..0.000U0.00000
2profit napha_iE0..-145.833U0.00000
3profit htg_oilE0..-437.500U0.00000
4profit blend1L0..145.833L0.00000
5profit blend2L0..0.000B-0.84167
6profit blend3L0..437.500L-0.00000


The progress of the solution is printed to the log as follows.

Output 13.1.2: Log: Solution Progress

NOTE: The problem EX1 has 8 variables (0 free, 0 fixed).                        
NOTE: The problem has 6 constraints (3 LE, 3 EQ, 0 GE, 0 range).                
NOTE: The problem has 19 constraint coefficients.                               
NOTE: The MPS read time is 0.01 seconds.                                        
WARNING: The objective sense has been changed to maximization.                  
NOTE: The LP presolver value AUTOMATIC is applied.                              
NOTE: The LP presolver time is 0.00 seconds.                                    
NOTE: The LP presolver removed 3 variables and 3 constraints.                   
NOTE: The LP presolver removed 6 constraint coefficients.                       
NOTE: The presolved problem has 5 variables, 3 constraints, and 13 constraint   
      coefficients.                                                             
NOTE: The LP solver is called.                                                  
NOTE: The Primal Simplex algorithm is used.                                     
                           Objective                Entering      Leaving       
      Phase Iteration        Value         Time     Variable      Variable      
       P 2          1    0.000000E+00         0        j_1         blend1 (S)   
       P 2          2    2.022784E-03         0        j_2         blend2 (S)   
       P 2          3    3.902347E-03         0         br         blend3 (S)   
       P 2          4    4.025073E-03         0        a_l            a_l       
       P 2          5    1.202248E+03         0     blend2 (S)         br       
       P 2          6    1.347921E+03         0                                 
       D 2          7    1.347917E+03         0                                 
NOTE: Optimal.                                                                  
NOTE: Objective = 1347.9166667.                                                 
NOTE: The Primal Simplex solve time is 0.00 seconds.                            
NOTE: The data set WORK.EX1POUT has 8 observations and 10 variables.            
NOTE: The data set WORK.EX1DOUT has 6 observations and 10 variables.            


Note that the %put statement immediately after the OPTLP procedure prints value of the macro variable _OROPTLP_ to the log as follows.

Output 13.1.3: Log: Value of the Macro Variable _OROPTLP_

STATUS=OK ALGORITHM=PS SOLUTION_STATUS=OPTIMAL OBJECTIVE=1347.9166667           
PRIMAL_INFEASIBILITY=3.552714E-15 DUAL_INFEASIBILITY=0 BOUND_INFEASIBILITY=0    
ITERATIONS=7 PRESOLVE_TIME=0.00 SOLUTION_TIME=0.00                              


The value briefly summarizes the status of the OPTLP procedure upon termination.

Alternatively, you can use an MPS-format file instead of a data set. Using the MPS-format file is typically faster than using the data set for large instances. You can use the following file ex1.mps:

   NAME                   EX1
   ROWS
    N          profit
    E          napha_l
    E          napha_i
    E          htg_oil
    L          blend1
    L          blend2
    L          blend3
   COLUMNS
               a_l        profit   -175  napha_l   .035
               a_l        napha_i  .100  htg_oil   .390
               a_h        profit   -165  napha_l   .030
               a_h        napha_i  .075  htg_oil   .300
               br         profit   -205  napha_l   .045
               br         napha_i  .135  htg_oil   .430
               na_l       napha_l  -1    blend2    -1
               na_i       napha_i  -1    blend1    -1
               h_o        htg_oil  -1    blend3    -1
               j_1        profit   350   blend1    .3
               j_1        blend3   .7
               j_2        profit   350   blend2    .2
               j_2        blend3   .8
   BOUNDS
    UP         .          a_l      110
    UP         .          a_h      165
    UP         .          br       80
   ENDATA

You can use the following call to PROC OPTLP to solve the LP problem:

proc optlp mpsfile='ex1.mps'
   objsense  = max
   algorithm = primal
   primalout = ex1pout
   dualout   = ex1dout
   printlevel = 0
   logfreq   = 1;
run;
%put &_OROPTLP_;

The output is the same as when you use the data set for input.

Last updated: October 07, 2022