### Example 6.16 Migration to OPTMODEL: Assignment

The following example shows how to solve Example 6.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';

do i = 1 to 6;
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 MACHINES;

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

/* read the set of customers and their demands */
into CUSTOMERS=[customer]

/* read the set of machines, costs, and availability */
into MACHINES=[machine]
avail;

into [machine customer]

/* 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
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 6.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;