So at first some things unusual in your problem definition:
- This is not a real optimization problem, since your objective function is fixed per definition (every shift has 7 nurses, and every nurse has an equal price per shift)
- In your Problem you defined 7 nurses per shift with a maimum of 5 working days. So you need 7 nurses on three shifts on seven days. This equals 147 nurse/shifts. But with the cap of five working days and only one shift per day, you just have 20 Nurses on 5 shifts, which equals to 100 nurse/shifts.
I've built the problem in Mathprog but the code should be more or less equal to AMPL. I've started with three sets for the nurses, days and shifts.
set shifts := {1,2,3};
set days := {1,2,3,4,5,6,7};
set nurses := {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
The shedule is defined as a set of binary variables:
var schedule{nurses, days, shifts}, binary;
The simple objective contains the sum of all nurse/shifts in this week with the related prices:
minimize cost: sum{i in nurses, j in days}(schedule[i,j,1]*c_morning+schedule[i,j,2]*c_day+schedule[i,j,3]*c_night);
To your first constraint one can limit the sum of all shifts per nurse to five, since there is only one shift per day possible:
s.t. working_days{n in nurses}:
sum{i in days, j in shifts}(schedule[n,i,j]) <= 5;
The restday is the hardest part of the problem. For simplicity I've created another set which just contains the days, where a nurse could have achived four night-shifts in a row. You can also formulate the constraint with the original set of days and exclude the first four days.
set nigth_days := {5,6,7};
s.t. rest{n in nurses,i in nigth_days}:
(schedule[n,i-4,3]+schedule[n,i-3,3]+schedule[n,i-2,3]+schedule[n,i-1,3]+sum{j in shifts}(schedule[n,i,j])) <= 4;
For not having a morning-shift after a night-shift I used the same attempt like for the rest days. The seventh day is excluded, since there is no eigth day where we can look for a morning-shift.
set yester_days := {1,2,3,4,5,6};
s.t. night_morning{i in yester_days, n in nurses}:
(schedule[n,i,3]+schedule[n,i+1,1]) <= 1;
The demand of four nurses per shift should be met (I've reduced the number since more then 4 nurses are infeasible, due to the 5 shift limit)
s.t. demand_shift{i in days, j in shifts}:
sum{n in nurses}(schedule[n,i,j]) = 4;
The fifth constraint is to limit the shifts per day to a max of one.
s.t. one_shift{n in nurses, i in days}:
sum{ j in shifts}(schedule[n,i,j]) <= 1;