model "StaffRoster" uses "mmxprs" !Use Xpress-Optimizer !Pre-define "constants" parameters DATAFILE= "" !"initialise.txt" !File with input data OUTFILE= "" !"roster.txt" !File where results are stored OUTFILE2= "" !File where results are stored end-parameters !Declare a procedure forward procedure print_sol forward procedure print_sol2 !Declare input parameters first, since we don't know !the number of staffs and working days - dynamic objects declarations DAY: set of string !Working Days STAFF: set of string !Employees SKILL: set of string !Skill type c: array(STAFF) of real !Salary a: array(STAFF,SKILL) of integer !Skill matrix d: array(SKILL,DAY) of integer !Skill demand MAXWORKDAY: integer !4 MINWORKDAY: integer !2 MINSTAFF: integer !3 end-declarations !Initialise input parameters from DATAFILE initializations from DATAFILE DAY SKILL STAFF a d c MINWORKDAY MAXWORKDAY MINSTAFF end-initializations !Make the sets static after initialisation. This is more !efficient and enables Mosel to check for 'out of range' ! errors that cannot be detected if the sets are dynamic. finalize(DAY) finalize(STAFF) finalize(SKILL) !Define decision variable here, after getting information about !the number of staffs and working days declarations x: array(STAFF,DAY) of mpvar !Decision variable end-declarations !Objective function Cost:= sum(i in STAFF,k in DAY) c(i)*x(i,k) !Constraints forall(j in SKILL,k in DAY) sum(i in STAFF) a(i,j)*x(i,k) >= d(j,k) forall(i in STAFF) sum(k in DAY) x(i,k) <= MAXWORKDAY forall(i in STAFF) sum(k in DAY) x(i,k) >= MINWORKDAY forall(k in DAY) sum(i in STAFF) x(i,k) >= MINSTAFF forall(i in STAFF,k in DAY) x(i,k) is_binary !Optimisation statement minimize(Cost) !Display results in Run Bar fopen(OUTFILE2,F_OUTPUT) print_sol fclose(F_OUTPUT) !Print solution to OUTFILE fopen(OUTFILE,F_OUTPUT) print_sol2 fclose(F_OUTPUT) !-------------------------------------------------------------------------- !Procedure to print results procedure print_sol !Print value of objective function writeln("Total Cost: $", getobjval) writeln !New line !Write 1st row of table write("Staff "); forall(k in DAY) write(strfmt(k,5)) write(" TOTAL") writeln !Print roster forall(i in STAFF) do write(strfmt(i,-6)) !Name of staff forall(k in DAY) do if getsol(x(i,k)) = 1 then !Write "W" to indicate working day write(strfmt(" W ",5)) else write(strfmt(" ",5)) end-if end-do write(" ", getsol(sum(k in DAY)x(i,k))) writeln end-do write(strfmt("TOTAL",5)) forall(k in DAY) write(strfmt(getsol(sum(i in STAFF) x(i,k)),5)) end-procedure !Procedure to print results procedure print_sol2 !Print roster forall(i in STAFF) do forall(k in DAY) do if getsol(x(i,k)) = 1 then writeln("1") else writeln("0") end-if end-do end-do end-procedure end-model