! A Packing Line problem with buffering.
 Apples of random weight come down a packing line 
into a weigh station buffer with NBUF slots. 
The apple in each slot is weighed.
Then NPACK ( NPACK <= NBUF) of these apples are selected
and placed into a box of NPACK apples.
A new set of NPACK apples then enter the weigh station
buffer to replace the apples just packed, and the cycle repeats.
There is a target weight, TARG, we want to achieve for each box.
There are relative penalties,UNPEN and OVPEN, of being 
under and over target. 
 Which set of NPACK out of NBUF apples should be selected
at each cycle so as to have boxes that are close to target?
 If there are alternate ways of getting a perfect packing of
the first box, which packing would you prefer?;
! Keywords: Packing line, Knapsack, Buffer, Line buffer;
SETS:
  LINE: WOF, Y, INBUF;
ENDSETS
DATA: ! For this data set, a buffer size of 15 or more allows a perfect packing. A buffer of 14 or less is insufficient; NBUF = 14; ! The number of units in the candidate buffer; NPACK = 12; ! Number of units to pack in each box; TARG = 68; ! Target weight of box in oz.; UNPEN = 5; ! Penalty per unit under; OVPEN = 1; ! Penalty per unit over; WOF = ! Weight of items in oz. as they come down the line; 5.6, 5.3, 6.0, 5.3, 5.6, 5.3, 5.0, 5.4, 6.2, 5.9, 5.1, 6.1, 5.8, 5.1, 6.3, 5.7, 5.5, 5.5, 5.3, 6.8, 5.4, 5.2, 5.8, 6.0 5.7, 5.7, 6.1, 5.5, 6.3, 6.2, 6.5, 5.1, 5.3, 5.4, 5.1, 5.9 ; ! Variables: Y(j) = 1 if item j is packed in current box, INBUF(j) = 1 if item j is in the buffer(available), = 0 if not available to be packed; ENDDATA SUBMODEL PACKEM: ! Must choose the required number to pack; @SUM( LINE( j) | INBUF(j) #EQ# 1: Y(j)) = NPACK; ! Must choose all or nothing ( 1 or 0) of an item; @FOR( LINE(j) | INBUF(j) #EQ# 1: @BIN( Y(j)); ); ! Weight in current box; WGT1 = @SUM( LINE(j) | INBUF(j) #EQ# 1 : WOF(j)*Y(j)); ! Measure amount under and over the target average; U1 - V1 = ( TARG - WGT1)/ NPACK; ! Minimize the over/under penalties; MIN = UNPEN*U1 + OVPEN*V1; ENDSUBMODEL
CALC: @SET('TERSEO', 2); ! Turn off default output; NITEMS = @SIZE( LINE); ! Number items in this test set; ! Initial load of buffer, first NBUF items; @FOR( LINE( j): INBUF(j) = j #LE# NBUF; ); ibox = 1; ! Index of current box; CURPOS = NBUF; ! Current position in line; @WRITE(' Box size= ', NPACK,', Buffer size= ', NBUF, @NEWLINE(1)); ! Cycle through the boxes until we run out of items; @WHILE( ibox*NPACK #LE# NITEMS: @SOLVE( PACKEM); @WRITE(@NEWLINE(1),' Current box ', ibox,' has weight ', @FORMAT( WGT1,'10.2f'), ' vs. target of ',@FORMAT( TARG,'10.2f'),@NEWLINE(1)); @WRITE(' Items in box are: '); @FOR( LINE(j) | INBUF(j) #EQ# 1 #AND# Y(j) #GT# 0.5: @WRITE(' ', j); ); @WRITE( @NEWLINE(1)); ! Get ready for next box; ibox = ibox + 1; ! Remove recently packed items from buffer; @FOR( LINE(j) | INBUF(j) #EQ# 1 #AND# Y(j) #GT# 0.5: INBUF(j) = 0; ); ! Load new items to replace packed ones; CURPOS = CURPOS + NPACK; ! Mark new ones as in the buffer; @FOR( LINE(j) | CURPOS - NPACK #LT# j #AND# j #LE# CURPOS: INBUF(j) = 1; ); ); ENDCALC