MODEL:
! A model with three criteria with "Pre-emptive" importance.
 ! Staffing example:
    Step 1: (Give 1st priority to)
       - Minimize total cost
    Step 2: (Give 2nd priority to)
       - Fix costs to level from Step 1
       - Solve to minimize max staff overage
         on any given day, thereby spreading
         excess staff through the week
    Step 3: (Give 2nd priority to)
       - Fix max overage to it's level from  
         Step 2
       - Solve to minimize the number working
         on a Sunday
 ! Any Preemptive optimal solution is also Pareto optimal;
! Keywords:  Goal programming, Lexico-goal programming,
   Preemptimve criteria, Pareto optimal, Staff Scheduling;

SETS:
   DAY :
       NEED, START, COST, EXCESS;
 ENDSETS
DATA: DAY = MON, TUE, WED, THU, FRI, SAT, SUN; NEED = 19, 17, 15, 19, 17, 14, 12; COST = 200, 200, 200, 200, 200, 200, 200; ENDDATA SUBMODEL OBJ_COST: MIN = TTL_COST; ENDSUBMODEL
SUBMODEL OBJ_MAX_EXCESS: MIN = MAX_EXCESS; ENDSUBMODEL
SUBMODEL OBJ_MIN_SUNDAY_STAFF: MIN = EXCESS( @INDEX( DAY, SUN)); ENDSUBMODEL
SUBMODEL BASE: ! Compute cost; TTL_COST = @SUM( DAY( D) : START( D) * COST( D)); ! The constraints; @FOR( DAY( D): @SUM( DAY( COUNT)| COUNT #LE# 5: START( @WRAP( D - COUNT + 1, @SIZE( DAY)))) - EXCESS( D)= NEED( D) ); ! Computes the maximum staff excess; @FOR( DAY( D): MAX_EXCESS >= EXCESS( D)); ! Starts must be integral; @FOR( DAY: @GIN( START)); @BND( 0, TTL_COST, BNDU_COST); @BND( 0, MAX_EXCESS, BNDU_MAX_EXCESS); ENDSUBMODEL
PROCEDURE REPORT: ! Procedure to write a standard report; @WRITE(' '); @WRITEFOR( DAY( D): DAY( D), ' '); @WRITE( 'TOTAL COST', @NEWLINE( 1)); @WRITE( ' Start: '); @WRITEFOR( DAY: @FORMAT( START, '6.0f')); @WRITE( @FORMAT( @SUM( DAY: COST*START), '8.0f')); @WRITE( @NEWLINE( 1)); @WRITE( ' On Duty: '); @WRITEFOR( DAY: @FORMAT( NEED + EXCESS, '6.0f')); @WRITE( @NEWLINE( 1)); @WRITE( ' Required: '); @WRITEFOR( DAY: @FORMAT( NEED, '6.0f')); @WRITE( @NEWLINE( 1)); @WRITE( ' Excess: '); @WRITEFOR( DAY: @FORMAT( EXCESS, '6.0f')); @WRITE( @NEWLINE( 2)); ENDPROCEDURE CALC: !Run in quiet mode; @SET( 'TERSEO', 2); !Free up bounds; BNDU_COST = 1.E10; BNDU_MAX_EXCESS = 1.E10; @WRITE('Illustrate preemptive objectives in staffing:', @NEWLINE(1), ' 1) Minimize cost, 2) Minimize max excess any day, 3) Minimize Sunday staffing.',@NEWLINE(2)); !Solve to minimize cost; @SOLVE( OBJ_COST, BASE); @WRITE( 'Solution 1 - Simply minimize cost:', @NEWLINE( 1)); REPORT; ! Display standard report; !Fix TTL_COST to optimal value; BNDU_COST = TTL_COST; !Re-solve to minimize the max excess staff on any given day in order to spread any excess staff throughout the week; @SOLVE( OBJ_MAX_EXCESS, BASE); @WRITE( 'Solution 2 - min cost, then minimize max excess:', @NEWLINE( 1)); REPORT; !Fix max excess to optimal level; BNDU_MAX_EXCESS = MAX_EXCESS; !Re-solve to minimize total workers on Sundays; @SOLVE( OBJ_MIN_SUNDAY_STAFF, BASE); @WRITE( 'Solution 3 - min cost / min max excess / min Sunday:', @NEWLINE( 1)); REPORT; ENDCALC END