Чтобы проанализировать это, пометьте ваши ограничения (см. Добавленный 'c1'):
forall(h in Hours,
d in days,
p in People,
rp in rosterPatterns,
shiftsInRP in shiftsPerRP
: shiftsInRP.ID == rp)
c1:
sum(s in Skills)
Assign[d][h][p][s] == shiftsInRP.shifts;
С этим OPL следует вычислить минимальный конфликт, который показывает, какие ограничения недопустимы.Делая это (в командной строке), я обнаружил, что самое первое сгенерированное ограничение недопустимо.Ограничение имеет только три переменные с левой стороны, но с правой стороны - 5. Это никогда не может быть удовлетворено.
Учитывая, что в вашем наборе только три элемента Skills
, леваяСторона стороны ограничения всегда будет иметь 3 переменные.Таким образом, он может принимать значения в {0, 1, 2, 3}.Если для любого кортежа shifts
имеет значение больше 3, то это ограничение, очевидно, не может быть выполнено.
РЕДАКТИРОВАТЬ : похоже, вы перепутали то, что должно войти в forall
и что должно идти в sum
.Чтобы сформулировать это правильно, я думаю, что вам понадобится вспомогательная переменная
dvar boolean RosterAssigned[People][rosterPatterns];
, которая равна 1, если человек назначен в список, и 0 в противном случае.При этом вы можете сформулировать ограничение как
forall(p in People)
sum(h in Hours, s in Skills, d in days)
Assign[d][h][p][s]
== sum(rp in rosterPatterns, shiftsInRP in shiftsPerRP : shitsInRP.ID == rp) (RosterAssigned[p][rp] * shiftsInRP.shifts);
В левой части указано количество смен, которые человек p
фактически работает.В правой части указано количество сдвигов, требуемых по шаблону реестра.Конечно, вы также должны добавить ограничения, которые гарантируют, что каждому сотруднику будет присвоен ровно один список.