1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
|
% from MiniZinc Handbook:
% https://www.minizinc.org/doc-latest/en/predicates.html
% Simple nurse rostering
include "regular.mzn";
enum NURSE;
enum DAY;
int: req_day;
int: req_night;
int: min_night;
enum SHIFT = { d, n, o };
int: S = card(SHIFT);
int: Q = 6; int: q0 = 1; set of int: STATE = 1..Q;
array[STATE,SHIFT] of int: t =
[| 2, 3, 1 % state 1
| 4, 4, 1 % state 2
| 4, 5, 1 % state 3
| 6, 6, 1 % state 4
| 6, 0, 1 % state 5
| 0, 0, 1|]; % state 6
array[NURSE,DAY] of var SHIFT: roster;
constraint forall(j in DAY)(
sum(i in NURSE)(roster[i,j] == d) == req_day /\
sum(i in NURSE)(roster[i,j] == n) == req_night
);
constraint forall(i in NURSE)(
regular([roster[i,j] | j in DAY], Q, S, t, q0, STATE) /\
sum(j in DAY)(roster[i,j] == n) >= min_night
);
solve satisfy;
output [ show(roster[i,j]) ++ if j==card(DAY) then "\n" else " " endif
| i in NURSE, j in DAY ];
/*
Multiline
comment
test
*/
predicate atmostone(array[int] of var bool:x) =
forall(i,j in index_set(x) where i < j)(
(not x[i] \/ not x[j]));
|