MODEL:
! Illustration of Multi-criteria/Lexico/Pre-emptive goal programming
! for a staffing problem with multiple work patterns available;
! Step 1:
- Minimize total cost
Step 2:
- Given total costs minimized from Step 1
- Solve to minimize max staff overage
on any given day, thereby spreading
excess staff through the week
Step 3:
- 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, Multi-criteria,
Preemptimve criteria, Pareto optimal, Staff scheduling;
SETS:
DAY : NEED, EXCESS;
PTRN : DAYSON, HRPDAY, COST, PUB;
PXD( PTRN, DAY): START;
LOBJ: OBJ, WGT, SUB; ! The set of objectives;
ENDSETS
DATA:
PTRN = P5X8 P4X10; ! The names of the work patterns;
DAYSON = 5 4; ! Number days on per week for each;
HRPDAY = 8 10; ! Hours per day for each pattern type;
PUB = 999 999; ! Upper bound on number that can be hired;
COST = 400 400; ! Cost per week for each;
! Days of the week;
DAY = MON, TUE, WED, THU, FRI, SAT, SUN;
! Hours needed each day;
NEED = 1520, 1360, 1200, 1520, 1360, 1120, 1008;
! The Lexico objectives;
LOBJ = Total_Cost Max_Excess Work_Sunday;
ENDDATA
SUBMODEL STAFFEM:
! Minimize the appropriate objective, based on WGT();
MIN = @SUM( LOBJ( p) : WGT( p) * OBJ( p));
! Compute cost;
TTL_COST = @SUM( PXD(p,d) : COST(p)*START( p,D) );
! The constraints;
! We must satisfy the number hours needed each day.
Hours provided = hours needed + excess;
@FOR( DAY( D):
@SUM( PTRN( p):
@SUM( DAY( COUNT)| COUNT #LE# DAYSON(p):
HRPDAY( p)*START( p, @WRAP( D - COUNT + 1, @SIZE( DAY)))))
= NEED( D) + EXCESS( D) ;
);
! Cannot use more than allowed of each pattern;
@FOR( PTRN(p):
@SUM( PXD( p,d): START(p,d)) <= PUB( p);
);
! Computes the maximum staff excess;
@FOR( DAY( D): MAX_EXCESS >= EXCESS( D));
! Starts must be integral;
@FOR( PXD(p,d): @GIN( START(p,d)));
! A redundant but helpful constraint, Total staff >= total need;
@SUM( DAY( d):
@SUM( PTRN( p):
@SUM( DAY( COUNT)| COUNT #LE# DAYSON(p):
HRPDAY( p)*START( p, @WRAP( D - COUNT + 1, @SIZE( DAY))))))
>= @SUM( DAY( d): NEED( D)) ;
! Objective related stuff;
! Total cost;
! Compute cost;
TTL_COST = @SUM( PXD(p,d) : COST(p)*START( p,D) );
! Excess maximum staff ;
@FOR( DAY( D): MAX_EXCESS >= EXCESS( D));
! The Lexico stuff. Define the objectives;
OBJ( 1) = TTL_COST;
OBJ( 2) = MAX_EXCESS;
OBJ( 3) = EXCESS( @INDEX( DAY, SUN));
! Their bounds, if any;
@FOR( LOBJ( p):
OBJ( p) <= SUB( p);
);
ENDSUBMODEL
PROCEDURE REPORT:
@WRITE(' ');
@FOR( DAY( D): @WRITE( DAY( D), ' '));
@WRITE( 'TOTAL COST', @NEWLINE( 1));
@FOR( PTRN( p):
@WRITE( ' Start ',@FORMAT( PTRN(p),"5s"),':');
@FOR( DAY( d): @WRITE( @FORMAT( START( p, d), '6.0f')));
@WRITE( @FORMAT( @SUM( DAY(d): COST( p)* START( p, d)), '8.0f'));
@WRITE( @NEWLINE( 1));
);
@WRITE( 'Hrs provided:');
@FOR( DAY: @WRITE( @FORMAT( NEED + EXCESS, '6.0f')));
@WRITE( @NEWLINE( 1));
@WRITE( ' Required:');
@FOR( DAY: @WRITE( @FORMAT( NEED, '6.0f')));
@WRITE( @NEWLINE( 1));
@WRITE( ' Excess:');
@FOR( DAY: @WRITE( @FORMAT( EXCESS, '6.0f')));
@WRITE( @NEWLINE( 2));
ENDPROCEDURE
CALC:
!Run in quiet mode;
@SET( 'TERSEO', 2);
@WRITE('Illustrate preemptive objectives in staffing:', @NEWLINE(1),
' 1) Minimize cost, 2) Minimize max excess any day, 3) Minimize Sunday staffing.',@NEWLINE(2));
! Initially no weights on any objective;
@FOR( LOBJ( p): WGT( p) = 0);
! Loop over the objectives;
@FOR( LOBJ( p):
@IFC( p #GT# 1: WGT( p-1) = 0);
WGT( p) = 1; ! Put all wgt on current obj;
@SOLVE( STAFFEM);
@WRITE( 'Minimize ', LOBJ( p), @NEWLINE( 1));
REPORT; ! Display standard report;
SUB( p) = OBJ( p); !Fix current objective;
);
ENDCALC
END
|