The OPTLP Procedure

Example 5.1 Oil Refinery Problem

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 normal bar normal l minus 165 normal a normal bar normal h minus 205 normal b normal r plus 350 normal j normal bar 1 plus 350 normal j normal bar 2

subject to

StartLayout 1st Row 1st Column left-parenthesis normal n normal a normal p normal h normal a normal bar normal l right-parenthesis 2nd Column 0.035 normal a normal bar normal l 3rd Column plus 4th Column 0.03 normal a normal bar normal h 5th Column plus 6th Column 0.045 normal b normal r 7th Column equals 8th Column normal n normal a normal bar normal l 2nd Row 1st Column left-parenthesis normal n normal a normal p normal h normal a normal bar normal i right-parenthesis 2nd Column 0.1 normal a normal bar normal l 3rd Column plus 4th Column 0.075 normal a normal bar normal h 5th Column plus 6th Column 0.135 normal b normal r 7th Column equals 8th Column normal n normal a normal bar normal i 3rd Row 1st Column left-parenthesis normal h normal t normal g normal bar normal o normal i normal l right-parenthesis 2nd Column 0.39 normal a normal bar normal l 3rd Column plus 4th Column 0.3 normal a normal bar normal h 5th Column plus 6th Column 0.43 normal b normal r 7th Column equals 8th Column normal h normal 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 normal bar 1 5th Column Blank 6th Column Blank 7th Column less-than-or-equal-to 8th Column normal n normal a normal 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 normal bar 2 7th Column less-than-or-equal-to 8th Column normal n normal a normal 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 normal bar 1 5th Column plus 6th Column 0.8 normal j normal bar 2 7th Column less-than-or-equal-to 8th Column normal h normal bar normal o 7th Row 1st Column Blank 2nd Column normal a normal bar normal l 3rd Column Blank 4th Column Blank 5th Column Blank 6th Column Blank 7th Column less-than-or-equal-to 8th Column 110 8th Row 1st Column Blank 2nd Column Blank 3rd Column Blank 4th Column normal a normal bar normal h 5th Column Blank 6th Column Blank 7th Column less-than-or-equal-to 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-equal-to 8th Column 80 EndLayout

and

normal a normal bar normal l comma normal a normal bar normal h comma normal b normal r comma normal n normal a normal bar 1 comma normal n normal a normal bar normal i comma normal h normal bar normal o comma normal j normal bar 1 comma normal j normal bar 2 greater-than-or-equal-to 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 normal bar normal o Baseline 1 2nd Column Blank 3rd Column Blank 4th Column greater-than-or-equal-to 5th Column 0.7 normal j normal bar 1 2nd Row 1st Column Blank 2nd Column Blank 3rd Column normal h normal bar normal o Baseline 2 4th Column greater-than-or-equal-to 5th Column 0.8 normal j normal bar 2 3rd Row 1st Column normal h normal bar normal o Baseline 1 2nd Column plus 3rd Column normal h normal bar normal o Baseline 2 4th Column less-than-or-equal-to 5th Column normal h normal 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 table ex1:

data mylib.ex1;
   input _id_ field1 $ field2 $ field3 $ field4 field5 $ field6;
   datalines;
1  NAME        .          EX1      .     .         .
2  ROWS        .          .        .     .         .
3  N           profit     .        .     .         .
4  E           napha_l    .        .     .         .
5  E           napha_i    .        .     .         .
6  E           htg_oil    .        .     .         .
7  L           blend1     .        .     .         .
8  L           blend2     .        .     .         .
9  L           blend3     .        .     .         .
10 COLUMNS     .          .        .     .         .
11 .           a_l        profit   -175  napha_l   .035
12 .           a_l        napha_i  .100  htg_oil   .390
13 .           a_h        profit   -165  napha_l   .030
14 .           a_h        napha_i  .075  htg_oil   .300
15 .           br         profit   -205  napha_l   .045
16 .           br         napha_i  .135  htg_oil   .430
17 .           na_l       napha_l  -1    blend2    -1
18 .           na_i       napha_i  -1    blend1    -1
19 .           h_o        htg_oil  -1    blend3    -1
20 .           j_1        profit   350   blend1    .3
21 .           j_1        blend3   .7    .         .
22 .           j_2        profit   350   blend2    .2
23 .           j_2        blend3   .8    .         .
24 BOUNDS      .          .        .     .         .
25 UP          .          a_l      110   .         .
26 UP          .          a_h      165   .         .
27 UP          .          br       80    .         .
28 ENDATA      .          .        .     .         .
;

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

proc optlp data=mylib.ex1
   objsense  = max
   algorithm = primal
   primalout = mylib.ex1pout
   dualout   = mylib.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 5.1.1.

Output 5.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 SolutionConstraint
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 5.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.                               
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 Cloud Analytic Services server processed the request in 0.323291      
      seconds.                                                                  
NOTE: The data set MYLIB.EX1POUT has 8 observations and 10 variables.           
NOTE: The data set MYLIB.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 5.1.3: Log: Value of the Macro Variable _OROPTLP_

STATUS=OK ALGORITHM=PS SOLUTION_STATUS=OPTIMAL OBJECTIVE=1347.9166667           
PRIMAL_INFEASIBILITY=0 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.

Last updated: June 22, 2026