The LP Procedure

Example 5.16 Migration to OPTMODEL: Assignment

The following example shows how to solve Example 5.12 using PROC OPTMODEL. The OBJECT, DEMAND, and RESOURCE data sets are the same as in that example. A new data set, GRADE, is added to aid in separating the data from the model.

title 'An Assignment Problem';

data grade(drop=i);
   do i = 1 to 6;
      grade = 'grade'||put(i,1.);
      output;
   end;
run;

The following PROC OPTMODEL statements read the data sets, build the linear programming model, solve the model, and output the optimal solution to a SAS data set called SOLUTION:

proc optmodel;
   /* declare index sets */
   set CUSTOMERS;
   set <str> GRADES;
   set MACHINES;

   /* declare parameters */
   num return {CUSTOMERS, GRADES, MACHINES} init 0;
   num demand {CUSTOMERS, GRADES};
   num cost {GRADES, MACHINES} init 0;
   num avail {MACHINES};

   /* read the set of grades */
   read data grade into GRADES=[grade];

   /* read the set of customers and their demands */
   read data demand
      into CUSTOMERS=[customer]
      {j in GRADES} <demand[customer,j]=col(j)>;

   /* read the set of machines, costs, and availability */
   read data resource nomiss
      into MACHINES=[machine] 
      {j in GRADES} <cost[j,machine]=col(j)>
      avail;

   /* read objective data */
   read data object nomiss
      into [machine customer]
      {j in GRADES} <return[customer,j,machine]=col(j)>;

   /* declare the model */
   var AmountProduced {CUSTOMERS, GRADES, MACHINES} >= 0;
   max TotalReturn = sum {i in CUSTOMERS, j in GRADES, k in MACHINES}
      return[i,j,k] * AmountProduced[i,j,k];
   con req_demand {i in CUSTOMERS, j in GRADES}:
      sum {k in MACHINES} AmountProduced[i,j,k] = demand[i,j];
   con req_avail {k in MACHINES}:
      sum {i in CUSTOMERS, j in GRADES} 
         cost[j,k] * AmountProduced[i,j,k] <= avail[k];

   /* call the solver and save the results */
   solve;
   create data solution 
      from [customer grade machine] = {i in CUSTOMERS, j in GRADES, 
         k in MACHINES: AmountProduced[i,j,k].sol ne 0}
      amount=AmountProduced;

   /* print optimal solution */
   print AmountProduced;
quit;

The statements use both numeric (NUM) and character (STR) index sets, which are populated from the corresponding data set variables in the READ DATA statements. The OPTMODEL parameters can be either single-dimensional (AVAIL) or multiple-dimensional (COST, DEMAND, RETURN). The RETURN and COST parameters are given initial values of 0, and the NOMISS option in the READ DATA statement tells OPTMODEL to read only the nonmissing values from the input data sets. The model declaration is nearly identical to the mathematical formulation. The logical condition AmountProduced[i,j,k].sol ne 0 in the CREATE DATA statement makes sure that only the nonzero parts of the solution appear in the SOLUTION data set. In Example 5.12, the creation of this data set required postprocessing of the PROC LP output data set.

The main point is that the PROC OPTMODEL statements are much easier to read and maintain than the corresponding DATA step statements required for PROC LP.

The SOLUTION data set can be processed by PROC TABULATE as follows to create a compact representation of the solution:

proc tabulate data=solution; 
   class customer grade machine; 
   var   amount; 
   table (machine*customer), (grade*amount=''*sum=''); 
run;

The output is the same as Output 5.12.2. The log is displayed in Output 5.16.1.

Output 5.16.1: OPTMODEL Log

An Assignment Problem

NOTE: There were 6 observations read from the data set WORK.GRADE.              
NOTE: There were 5 observations read from the data set WORK.DEMAND.             
NOTE: There were 4 observations read from the data set WORK.RESOURCE.           
NOTE: There were 20 observations read from the data set WORK.OBJECT.            
NOTE: The problem has 120 variables (0 free, 0 fixed).                          
NOTE: The problem has 34 linear constraints (4 LE, 30 EQ, 0 GE, 0 range).       
NOTE: The problem has 220 linear constraint coefficients.                       
NOTE: The problem has 0 nonlinear constraints (0 LE, 0 EQ, 0 GE, 0 range).      
NOTE: The OPTMODEL presolver is disabled for linear problems.                   
NOTE: The OPTLP presolver value AUTOMATIC is applied.                           
NOTE: The OPTLP presolver removed 43 variables and 7 constraints.               
NOTE: The OPTLP presolver removed 66 constraint coefficients.                   
NOTE: The presolved problem has 77 variables, 27 constraints, and 154           
      constraint coefficients.                                                  
NOTE: The DUAL SIMPLEX solver is called.                                        
                       Objective                                                
      Phase Iteration  Value                                                    
        2           1       2052796                                             
        2          45        871426                                             
NOTE: Optimal.                                                                  
NOTE: Objective = 871426.038.                                                   
NOTE: The data set WORK.SOLUTION has 26 observations and 4 variables.