There are four sets of constraints in this model. Two of which are merely computational.

This first computational set of constraints computes the batch size of each finished good with the following expression:

!Batch size computation;

 [BATCOMP] BATCH( F) =

  @SUM( RAWMAT( R): USED( R, F));

In words, the batch size of finished good F is the sum of all the raw materials used in the production of the finished good.

The second set of computational constraints computes the slack on the upper quality limit for each finished good and each quality measure as follows:

[QRESUP] @SUM( RAWMAT( R):

QLEVEL( R, Q) * USED( R, F))

 + QSLACK( Q, F) = QUP( Q, F) *

  BATCH( F);

In words, the actual quality level plus the slack on the upper quality level is equal to the upper quality level.

The first true constraint is on the batch sizes of the finished products, which must fall within minimum and maximum levels. We use the @BND function to set this up as follows:

!Batch size limits;

@BND( MINREQ, BATCH, MAXSELL);

Note that we could have entered explicit constraints for the batch size limits, but the @BND function is more efficient at handling simple bounds on variables.

The final constraint forces the quality level of each finished good for each quality measure to fall within specifications. We do this with the following:

[QRESDN] QSLACK( Q, F) <=

( QUP( Q, F) - QLOW( Q, F)) *

 BATCH( F);

In words, the slack must be less than the difference between the upper limit and the lower limit. If this were not true, quality would be beneath the lower limit. The fact that the slack variable cannot be negative guarantees we won't exceed the quality limit.