Try to split weekend nwdsTry to split weekend nwds

This commit is contained in:
Ross
2021-06-28 17:01:35 +01:00
parent d18c5e8a91
commit 5e4149a36d
3 changed files with 109 additions and 89 deletions
+46 -26
View File
@@ -21,6 +21,8 @@ WeekInt = int
days = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
full_weekend_count = 2
# weeks = [i for i in range(1,weeks_to_rota+1)]
# weeks_days_product = list(itertools.product(weeks, days))
@@ -207,13 +209,12 @@ class RotaBuilder(object):
initialize=0,
)
#self.model.worker_block_shift_counts = Var(
# ((worker.id, week, shift) for week in self.weeks
# for shift in self.shifts_to_assign_or_force_as_blocks()
# for worker in self.workers),
# within=NonNegativeIntegers,
# initialize=0,
#)
self.model.worker_block_shift_split = Var(
((week, shift) for week in self.weeks
for shift in self.shifts_to_assign_or_force_as_blocks()),
within=Binary,
initialize=0,
)
self.model.blocks_worker_shift_assigned = Var(
((worker.id, week, shift) for worker in self.workers
@@ -222,6 +223,7 @@ class RotaBuilder(object):
within=Binary,
initialize=0,
)
self.model.blocks_assigned = Var(
((week, shift) for week in self.weeks
@@ -464,11 +466,14 @@ class RotaBuilder(object):
workers_required,
site_required,
) in self.get_required_workers_and_site_combinations():
#print(week, day, shift, workers_required, site_required)
print(week, day, shift, workers_required, site_required)
self.model.constraints.add(workers_required == sum(
self.model.works[worker.id, week, day, shift]
for worker in self.workers if worker.site in site_required))
# And it is not assigned if the worker is from the wrong site
self.model.constraints.add(0 == sum(
self.model.works[worker.id, week, day, shift]
for worker in self.workers if worker.site not in site_required))
# # Ensure shifts are only assigned by workers from the allowed sites
# self.model.constraints.add(0 == sum(
# self.model.works[worker.id, week, day, shift]
@@ -609,11 +614,7 @@ class RotaBuilder(object):
for worker in self.workers))
if shift.force_as_block:
#self.model.constraints.add(
# self.model.worker_block_shift_counts[worker.id, week,
# shift.name] ==
# sum(self.model.works[worker.id, week, day, shift.name]
# for day in self.days))
if shift.force_as_block_unless_nwd:
workers = self.get_workers_for_shift(shift)
@@ -658,6 +659,18 @@ class RotaBuilder(object):
week,
shift.name]
for worker in workers) <= 2)
#self.model.constraints.add(
# self.model.worker_block_shift_split[week, shift.name] <= 2 - sum(self.model.blocks_worker_shift_assigned[worker.id,
# week,
# shift.name]
# for worker in workers))
#
#self.model.constraints.add(
# sum(self.model.works[w.id, week, day,shift.name]
# for w in nwd_workers for day in shift.shift_days) - sum(self.model.works[w.id, week, day,shift.name]
# for w in full_workers for day in shift.shift_days) >= self.model.worker_block_shift_split[week, shift.name] )
else:
self.model.constraints.add(
@@ -672,11 +685,14 @@ class RotaBuilder(object):
if self.constraint_options[
"avoid_st2_first_month"] and worker.grade == 2:
# Avoid ST1s on the first month
self.model.constraints.add(0 == sum(
self.model.works[worker.id, week, day, shift] for week,
day, shift in self.get_all_shiftname_combinations()
if week in (1, 2, 3, 4) and shift in ("night_weekday", "night_weekend")))
try:
self.model.constraints.add(0 == sum(
self.model.works[worker.id, week, day, shift] for week,
day, shift in self.get_all_shiftname_combinations()
if week in (1, 2, 3, 4) and shift in ("night_weekday", "night_weekend")))
except ValueError as e:
print("Failure setting constraint", "avoid_st2_first_month")
print(e)
# Count number of weekends an worker works
if self.constraint_options["balance_weekends"]:
self.model.constraints.add(
@@ -938,7 +954,7 @@ class RotaBuilder(object):
# Ignore last week
if week + 1 in self.weeks:
self.model.constraints.add(
2 >= sum(self.model.works[worker.id, week, "Sat",
full_weekend_count >= sum(self.model.works[worker.id, week, "Sat",
shift.name]
for shift in self.get_shifts()) +
sum(self.model.works[worker.id, week, "Sun",
@@ -952,7 +968,7 @@ class RotaBuilder(object):
# Ignore last week
if week + 1 in self.weeks:
self.model.constraints.add(
2 >= sum(self.model.works[worker.id, week, "Sat",
full_weekend_count >= sum(self.model.works[worker.id, week, "Sat",
shift.name]
for shift in self.get_shifts()) +
sum(self.model.works[worker.id, week, "Sun",
@@ -967,7 +983,7 @@ class RotaBuilder(object):
if worker.site in self.constraint_options[
"prevent_fridays_before_full_weekends"]:
self.model.constraints.add(
2 >= sum(self.model.works[worker.id, week, "Sat",
full_weekend_count >= sum(self.model.works[worker.id, week, "Sat",
shift.name]
for shift in self.get_shifts()
if "night" not in shift.constraints) +
@@ -982,7 +998,7 @@ class RotaBuilder(object):
if worker.site in self.constraint_options[
"prevent_thursdays_before_full_weekends"]:
self.model.constraints.add(
2 >= sum(self.model.works[worker.id, week, "Sat",
full_weekend_count >= sum(self.model.works[worker.id, week, "Sat",
shift.name]
for shift in self.get_shifts()
if "night" not in shift.constraints) +
@@ -1645,7 +1661,7 @@ class RotaResults(object):
for week, day in self.rota.get_week_day_combinations():
a = "-"
for shift in self.rota.get_shift_names_by_week_day(week, day):
if model.works[worker.id, week, day, shift].value == 1:
if model.works[worker.id, week, day, shift].value > 0:
shifts.append(shift)
a = shift[0]
w.append(a)
@@ -1714,7 +1730,10 @@ class RotaResults(object):
for worker in self.rota.workers:
if worker.site != current_site:
timetable.append("<tr><th class='site-title'>{} n={} fte={}</th><tr>".format(worker.site, len(self.rota.workers_at_sites[worker.site]), self.rota.full_time_equivalent_sites[worker.site]))
try:
timetable.append("<tr><th class='site-title'>{} n={} fte={}</th><tr>".format(worker.site, len(self.rota.workers_at_sites[worker.site]), self.rota.full_time_equivalent_sites[worker.site]))
except KeyError as e:
print(e)
current_site = worker.site
shifts = []
@@ -1739,7 +1758,7 @@ class RotaResults(object):
shift_name = ""
for shift in self.rota.get_shift_names_by_week_day(week, day):
if model.works[worker.id, week, day, shift].value == 1:
if model.works[worker.id, week, day, shift].value > 0:
shifts.append(shift)
a = shift[0]
shift_name = shift
@@ -1988,3 +2007,4 @@ class RotaResults(object):
"balance: {},".format(
self.rota.model.weekend_shift_count_w[worker.id].value),
)