Я использую решатель CP-SAT, начиная с этого примера: https://github.com/google/or-tools/blob/master/examples/python/shift_scheduling_sat.py
Для принудительного отдыха на выходных я ввел эту часть кода:
# Force weekends to OFF.
for e in range(num_employees):
fixed_assignments.append((e,0,5))
fixed_assignments.append((e,0,6))
fixed_assignments.append((e,0,12))
fixed_assignments.append((e,0,13))
fixed_assignments.append((e,0,19))
fixed_assignments.append((e,0,20))
fixed_assignments.append((e,0,26))
fixed_assignments.append((e,0,27))
Стем же методом я могу назначить целую неделю отпуска одному сотруднику, исключив ограничение:
shift_constraints = [
# One or two consecutive days of rest, this is a hard constraint.
# (0, 1, 1, 0, 2, 2, 0), <-- removed
# added to facilitate the assignment of the shifts for all the week
# penalized but not hard to allow even rest days, otherwise the result
# would be NOT FEASIBLE
(1, 5, 5, 2, 5, 5, 2),
(2, 5, 5, 2, 5, 5, 2),
(3, 5, 5, 7, 5, 5, 7), # <- night shift
]
Я также добавил это дополнительное ограничение, чтобы один и тот же сотрудник не выполнял одну и ту же смену в течение двух недель подряд:
weekly_sum_constraints = [
# Constraints on rests per week.
#(0, 1, 2, 7, 2, 3, 4),
# At least 1 shift per week (penalized). At most 5 (hard).
(1, 0, 1, 3, 5, 5, -2),
(2, 0, 1, 3, 5, 5, -2),
(3, 0, 1, 3, 5, 5, 2),
]
# Penalized weeks transitions:
# (previous_shift, next_shift, penalty (0 means forbidden))
penalized_weeks_transitions = [
# Night to Night is forbidden.
(3, 3, 0),
(2, 2, 0),
(1, 1, 0),
]
с кодом:
# Penalized weeks transitions
for previous_shift, next_shift, cost in penalized_weeks_transitions:
for e in range(num_employees):
for d in range(num_days - 8):
transition = [
work[e, previous_shift, d].Not(),
work[e, next_shift, d + 7].Not()
]
if cost == 0:
model.AddBoolOr(transition)
else:
trans_var = model.NewBoolVar(
'wtransition (employee=%i, day=%i)' % (e, d))
transition.append(trans_var)
model.AddBoolOr(transition)
obj_bool_vars.append(trans_var)
obj_bool_coeffs.append(cost)
Таким образом, я могу получить план, но из-за ограничения на запросы о покрытии смен:
weekly_cover_demands = [
(14, 14, 7), # Monday
(14, 14, 7), # Tuesday
(14, 14, 7), # Wednesday
(14, 14, 7), # Thursday
(14, 14, 7), # Friday
(0, 0, 0), # Saturday
(0, 0, 0), # Sunday
]
У меня могут быть сотрудники с отдыхом в течение недели, особенно если им назначена ночная смена.Таким образом, логика такова: если вам нужно только 7 человек в ночную смену, остальные лишние люди получат ход 0 (отдых), так что штраф за ночную смену будет снижен.
С другой стороныЯ хотел бы назначить действительный сдвиг в этих случаях, может быть, утром или днем, но не в остальные смены.
Итак, вопрос в следующем:
1) Как правильно управлятьсотрудник когда он в отпуске?Правильно ли сделать это так, как я сделал принудительное включение поворота в 0 (отдых) в качестве жесткого ограничения?
2) Как я могу написать ограничение, чтобы обеспечить равномерное распределение ночных смен или, возможно, прощеобеспечить, чтобы в течение 4 недель была только одна неделя с ночной сменой?
3) как избежать автоматического назначения остальной смены, если запрос на ночную смену меньше, чем наличие сотрудников?(в этом случае сотрудники должны работать в любом случае, но утром или днем)?
Заранее благодарен за любую помощь.