Download
language ESSENCE' 1.0
letting daysPerWeek = 7
given numberOfWeeks : int(1..)
letting numberOfDays = numberOfWeeks * daysPerWeek
given s_min : int(1..)
given s_max : int(1..)
$ 3 shifts: early = 1, late = 2 and night shift = 3 + day off (rest day) = 0
letting numberOfShifts = 3
given shiftRequirements : matrix indexed by [int(1..daysPerWeek), int(1..numberOfShifts+1)] of int(0..)
find plan1d : matrix indexed by [int(1..numberOfWeeks * daysPerWeek)] of int(0..numberOfShifts)
find plan2d : matrix indexed by [int(1..numberOfWeeks), int(1..daysPerWeek)] of int(0..numberOfShifts)
find s_min_arrays : matrix indexed by [int(1..s_min), int(1..s_min)] of int(0..numberOfShifts)
find s_max_arrays : matrix indexed by [int(1..s_max), int(1..s_max)] of int(0..numberOfShifts)
branching on [plan1d]
such that
$ flatten
forAll week : int(1..numberOfWeeks) .
forAll day : int(1..daysPerWeek) .
plan2d[week,day] = plan1d[(week-1) * daysPerWeek + day],
$ C_equalDays: constrains that weekend days (Saturday and Sunday) always have the same shift
forAll week : int(1..numberOfWeeks) .
plan2d[week, daysPerWeek - 1] = plan2d[week, daysPerWeek],
$ create the sub arrays over the array bounds
forAll i : int(1..s_min) .
forAll j : int(1..s_min) .
s_min_arrays[i,j] = plan1d[((numberOfDays - s_min - 1 + i +j) % numberOfDays) + 1],
$ C_shiftRepetitions:for every shift type a minimum number of consecutive assignments to this shift is given
forAll day : int(1..numberOfDays-s_min) .
plan1d[day] != plan1d[day+1] ->
forAll i : int(day+1..day+s_min) .
plan1d[i] = plan1d[i+1],
$ the constraints over the array bounds
forAll d : int(1..s_min) .
plan1d[d+numberOfDays - s_min] != plan1d[((d+numberOfDays-s_min) % numberOfDays) + 1] ->
forAll i : int(2..s_min) .
s_min_arrays[d,1] = s_min_arrays[d,i],
$ create the sub arrays other the array bounds
forAll i : int(1..s_max) .
forAll j : int(1..s_max) .
s_max_arrays[i,j] = plan1d[((numberOfDays - s_max - 2 + i +j) % numberOfDays) + 1],
$ C_shiftRepetitions:for every shift type a maximum number of consecutive assignments to this shift is given
forAll d : int(1..numberOfWeeks * daysPerWeek - s_max) .
(forAll i : int(d+1..d+s_max-1) .
plan1d[d] = plan1d[i]) ->
plan1d[d] != plan1d[d + s_max],
$ the constraints over the array bounds
forAll d : int(1..s_max) .
(forAll i : int(2..s_max) .
s_max_arrays[d,1] = s_max_arrays[d,i]) ->
plan1d[d+numberOfDays-s_max] != plan1d[d],
$ C_restDays: at least 2 days must be rest days every 2 weeks
forAll day : int(1..((numberOfWeeks - 2)*daysPerWeek)) .
sum([plan1d[i] = 0 | i : int(day..(day+daysPerWeek*2))]) >= 2,
forAll i : int(1..(2*daysPerWeek-1)) .
sum([plan1d[j] = 0 | j : int(numberOfWeeks*daysPerWeek-i..numberOfWeeks * daysPerWeek)]) + sum([plan1d[k]=0 | k : int(1..2*daysPerWeek-i)]) >= 2,
$ C_shiftOrder: restricts the order of shifts.
$ There is a forward rotating principle. This means, that after an early shift there can only follow a shift with the same or a higher value, or a rest shift.
forAll day : int(2..numberOfWeeks*daysPerWeek-1) .
(plan1d[day] <= plan1d[day+1])
\/ (plan1d[day+1] = 0),
$ forward rotating
(plan1d[1] >= plan1d[numberOfDays]) \/ plan1d[1] = 0,
forAll day : int(1..daysPerWeek) .
gcc(plan2d[..,day], [0,1,2,3], shiftRequirements[day, ..])