remove some old code
This commit is contained in:
+194
-230
@@ -47,8 +47,8 @@ SHIFT_BOUNDS = {
|
||||
|
||||
class SingleShift(object):
|
||||
"""Class to hold all details for a shift
|
||||
|
||||
|
||||
|
||||
|
||||
Valid constraints
|
||||
|
||||
balance_across_groups (requires block assignment)
|
||||
@@ -56,14 +56,14 @@ class SingleShift(object):
|
||||
postclear(2) / preclear(2)
|
||||
|
||||
night
|
||||
|
||||
|
||||
limit_grade_number:
|
||||
options: {grade: max_number, grade2: max_number2}
|
||||
|
||||
minimum_grade_number:
|
||||
options: (grade, min_number)
|
||||
|
||||
|
||||
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
@@ -199,8 +199,8 @@ class RotaBuilder(object):
|
||||
"balance_nights_across_sites": True,
|
||||
"balance_bank_holidays": True,
|
||||
"balance_blocks": True,
|
||||
"balance_shifts": True, # Does not use a quadratic function
|
||||
"balance_shifts_quadratic": False,
|
||||
"balance_shifts": True, # Does not use a quadratic function
|
||||
"balance_shifts_quadratic": False,
|
||||
"balance_shifts_over_workers": True,
|
||||
"minimise_shift_diffs": False, # less sophisticated version of balance_shifts_over_workers
|
||||
"balance_weekends": True,
|
||||
@@ -266,7 +266,6 @@ class RotaBuilder(object):
|
||||
|
||||
self.solve_model(options=options)
|
||||
|
||||
|
||||
def build_model(self):
|
||||
# Initialize model
|
||||
self.model = ConcreteModel()
|
||||
@@ -283,15 +282,6 @@ class RotaBuilder(object):
|
||||
initialize=0,
|
||||
)
|
||||
|
||||
# The nights self.model is used to ensure nights are assigned as a block (and limit the number of workers required)
|
||||
# self.model.nights = Var(
|
||||
# ((worker.id, week, block) for worker in self.workers
|
||||
# for week in self.weeks for block in self.night_blocks),
|
||||
# within=Binary,
|
||||
# initialize=0,
|
||||
# )
|
||||
|
||||
# The nights self.model is used to ensure nights are assigned as a block (and limit the number of workers required)
|
||||
self.model.shift_week_worker_assigned = Var(
|
||||
(
|
||||
(shift, week, worker.id)
|
||||
@@ -347,13 +337,6 @@ class RotaBuilder(object):
|
||||
within=NonNegativeIntegers,
|
||||
initialize=0,
|
||||
)
|
||||
# self.model.bank_holiday_count = Var(
|
||||
# ((worker.id, week, day) for worker in self.workers
|
||||
# for week, day in self.get_week_day_combinations() if self.week_day_date_map[(week, day)] in bank_holiday_map
|
||||
# ),
|
||||
# within=Binary,
|
||||
# initialize=0,
|
||||
# )
|
||||
|
||||
# Used to limit number of workers on night shift per site
|
||||
# if we force a binary it will in effect hard constrain to < 2
|
||||
@@ -466,7 +449,10 @@ class RotaBuilder(object):
|
||||
initialize=0,
|
||||
)
|
||||
|
||||
if self.constraint_options["balance_shifts"] or self.constraint_options["balance_shifts_quadratic"]:
|
||||
if (
|
||||
self.constraint_options["balance_shifts"]
|
||||
or self.constraint_options["balance_shifts_quadratic"]
|
||||
):
|
||||
self.model.shift_count_t1 = Var(
|
||||
(
|
||||
(worker.id, shift.name)
|
||||
@@ -558,7 +544,6 @@ class RotaBuilder(object):
|
||||
# initialize=0,
|
||||
# )
|
||||
|
||||
|
||||
self.model.works_weekend = Var(
|
||||
((worker.id, week) for worker in self.workers for week in self.weeks),
|
||||
domain=Binary,
|
||||
@@ -696,16 +681,6 @@ class RotaBuilder(object):
|
||||
# self.model.works[worker.id, week, day, shift]
|
||||
# for worker in self.workers if worker.site not in site_required))
|
||||
|
||||
# THIS SHOULD NO LONGER BE REQUIRED
|
||||
# Ensure no workers are assigned to shifts that are not required
|
||||
#for week, day, shift in self.get_not_required_shifts():
|
||||
# self.model.constraints.add(
|
||||
# 0
|
||||
# == sum(
|
||||
# self.model.works[worker.id, week, day, shift.name]
|
||||
# for worker in self.workers
|
||||
# )
|
||||
# )
|
||||
|
||||
# Constraint: total hours worked hours worked
|
||||
# for worker in self.workers:
|
||||
@@ -757,23 +732,29 @@ class RotaBuilder(object):
|
||||
|
||||
for shift in self.get_shifts_with_constraint("limit_grade_number"):
|
||||
if not shift.constraint_options["limit_grade_number"]:
|
||||
raise ValueError("Constraint option must be defined for 'limit_grade_number'")
|
||||
raise ValueError(
|
||||
"Constraint option must be defined for 'limit_grade_number'"
|
||||
)
|
||||
for grade in shift.constraint_options["limit_grade_number"]:
|
||||
#self.model.limit_grades_constraint = Constraint(
|
||||
setattr(self.model, f"limit_grades_constraint_{shift.name}_{grade}", Constraint(
|
||||
[week for week in self.weeks],
|
||||
#[shift for shift in self.get_shifts_with_constraint("limit_grade_number")],
|
||||
[shift],
|
||||
[grade],
|
||||
[shift.constraint_options["limit_grade_number"][grade]],
|
||||
rule=limitGradesRule,
|
||||
#name=f"limit_grades_constraint_{shift.name}_{grade}"
|
||||
))
|
||||
# self.model.limit_grades_constraint = Constraint(
|
||||
setattr(
|
||||
self.model,
|
||||
f"limit_grades_constraint_{shift.name}_{grade}",
|
||||
Constraint(
|
||||
[week for week in self.weeks],
|
||||
# [shift for shift in self.get_shifts_with_constraint("limit_grade_number")],
|
||||
[shift],
|
||||
[grade],
|
||||
[shift.constraint_options["limit_grade_number"][grade]],
|
||||
rule=limitGradesRule,
|
||||
# name=f"limit_grades_constraint_{shift.name}_{grade}"
|
||||
),
|
||||
)
|
||||
|
||||
def minimumGradesRule(model, week, shift, grade, limit):
|
||||
workers = [w for w in self.workers if w.grade >= grade]
|
||||
if len(workers) < limit:
|
||||
#return Constraint.Skip
|
||||
# return Constraint.Skip
|
||||
raise ValueError("minimum_grade_number: not enough valid workers")
|
||||
return (
|
||||
sum(
|
||||
@@ -785,19 +766,24 @@ class RotaBuilder(object):
|
||||
|
||||
for shift in self.get_shifts_with_constraint("minimum_grade_number"):
|
||||
if not shift.constraint_options["minimum_grade_number"]:
|
||||
raise ValueError("Constraint option must be defined for 'minimum_grade_number'")
|
||||
raise ValueError(
|
||||
"Constraint option must be defined for 'minimum_grade_number'"
|
||||
)
|
||||
grade, min_required = shift.constraint_options["minimum_grade_number"]
|
||||
#self.model.limit_grades_constraint = Constraint(
|
||||
setattr(self.model, f"minimum_grade_number_{shift.name}", Constraint(
|
||||
[week for week in self.weeks],
|
||||
#[shift for shift in self.get_shifts_with_constraint("limit_grade_number")],
|
||||
[shift],
|
||||
[grade],
|
||||
[min_required],
|
||||
rule=minimumGradesRule,
|
||||
#name=f"limit_grades_constraint_{shift.name}_{grade}"
|
||||
))
|
||||
|
||||
# self.model.limit_grades_constraint = Constraint(
|
||||
setattr(
|
||||
self.model,
|
||||
f"minimum_grade_number_{shift.name}",
|
||||
Constraint(
|
||||
[week for week in self.weeks],
|
||||
# [shift for shift in self.get_shifts_with_constraint("limit_grade_number")],
|
||||
[shift],
|
||||
[grade],
|
||||
[min_required],
|
||||
rule=minimumGradesRule,
|
||||
# name=f"limit_grades_constraint_{shift.name}_{grade}"
|
||||
),
|
||||
)
|
||||
|
||||
# def nightShiftDerrifordRule(model, week, shift):
|
||||
# derriford_workers = [w for w in self.workers if w.night_at_derriford >= 1]
|
||||
@@ -831,21 +817,26 @@ class RotaBuilder(object):
|
||||
>= required_number
|
||||
)
|
||||
|
||||
|
||||
for shift in self.get_shifts_with_constraint("require_home_site_presence"):
|
||||
site, required_number = shift.constraint_options["require_home_site_presence"]
|
||||
#self.model.require_presence_at_site_overnight_rule = Constraint(
|
||||
setattr(self.model, f"require_home_site_presence_{shift.name}", Constraint(
|
||||
[week for week in self.weeks],
|
||||
[shift.name],
|
||||
[site],
|
||||
[required_number],
|
||||
rule=presenceAtHomeSite,
|
||||
))
|
||||
site, required_number = shift.constraint_options[
|
||||
"require_home_site_presence"
|
||||
]
|
||||
# self.model.require_presence_at_site_overnight_rule = Constraint(
|
||||
setattr(
|
||||
self.model,
|
||||
f"require_home_site_presence_{shift.name}",
|
||||
Constraint(
|
||||
[week for week in self.weeks],
|
||||
[shift.name],
|
||||
[site],
|
||||
[required_number],
|
||||
rule=presenceAtHomeSite,
|
||||
),
|
||||
)
|
||||
|
||||
# # Count the number of workers from each site on each night shift
|
||||
# # As 1 or 0 is optimum we can simply subtract 1 from the number
|
||||
#if self.constraint_options["balance_nights_across_sites"]:
|
||||
# if self.constraint_options["balance_nights_across_sites"]:
|
||||
# for site in self.sites:
|
||||
# for shift in self.get_shifts_with_constraint("night"):
|
||||
# block = shift.name
|
||||
@@ -1032,12 +1023,10 @@ class RotaBuilder(object):
|
||||
print(e)
|
||||
|
||||
# Count number of weekends an worker works
|
||||
#if self.constraint_options["balance_weekends"]:
|
||||
# if self.constraint_options["balance_weekends"]:
|
||||
self.model.constraints.add(
|
||||
self.model.worker_weekend_count[worker.id]
|
||||
== sum(
|
||||
self.model.works_weekend[worker.id, week] for week in self.weeks
|
||||
)
|
||||
== sum(self.model.works_weekend[worker.id, week] for week in self.weeks)
|
||||
)
|
||||
|
||||
if self.constraint_options["max_weekends"] > -1:
|
||||
@@ -1102,9 +1091,11 @@ class RotaBuilder(object):
|
||||
min_shifts,
|
||||
sum(
|
||||
self.model.works[worker.id, week, day, shift.name]
|
||||
for week, day in self.get_week_day_combinations_for_shift(shift)
|
||||
#for week, day in self.get_week_day_combinations()
|
||||
#if shift.name in self.get_shift_names_by_week_day(week, day)
|
||||
for week, day in self.get_week_day_combinations_for_shift(
|
||||
shift
|
||||
)
|
||||
# for week, day in self.get_week_day_combinations()
|
||||
# if shift.name in self.get_shift_names_by_week_day(week, day)
|
||||
),
|
||||
max_shifts,
|
||||
)
|
||||
@@ -1115,8 +1106,10 @@ class RotaBuilder(object):
|
||||
0
|
||||
== sum(
|
||||
self.model.works[worker.id, week, day, shift.name]
|
||||
for week, day in self.get_week_day_combinations_for_shift(shift)
|
||||
#for week, day in self.get_week_day_combinations()
|
||||
for week, day in self.get_week_day_combinations_for_shift(
|
||||
shift
|
||||
)
|
||||
# for week, day in self.get_week_day_combinations()
|
||||
)
|
||||
)
|
||||
|
||||
@@ -1143,7 +1136,6 @@ class RotaBuilder(object):
|
||||
== self.model.shift_count_diff[worker.id, shift.name]
|
||||
)
|
||||
|
||||
|
||||
if self.constraint_options["balance_shifts_quadratic"]:
|
||||
# This may need to be updated
|
||||
xU = 25
|
||||
@@ -1182,7 +1174,6 @@ class RotaBuilder(object):
|
||||
- xU * xU
|
||||
)
|
||||
|
||||
|
||||
# Define worker_shift_count_t1 and worker_shift_count_t2 constraints for the object
|
||||
# Thus bypassing the need for a quadratic solver
|
||||
# t1-t2 is the target
|
||||
@@ -1241,9 +1232,11 @@ class RotaBuilder(object):
|
||||
self.model.night_shift_count[worker.id]
|
||||
== sum(
|
||||
self.model.works[worker.id, week, day, shift.name]
|
||||
for week, day, shift in self.get_week_day_shift_combinations_for_constraint("night")
|
||||
#for week, day in self.get_week_day_combinations_for_shift(shift)
|
||||
#for shift in self.get_shifts_with_constraint("night")
|
||||
for week, day, shift in self.get_week_day_shift_combinations_for_constraint(
|
||||
"night"
|
||||
)
|
||||
# for week, day in self.get_week_day_combinations_for_shift(shift)
|
||||
# for shift in self.get_shifts_with_constraint("night")
|
||||
)
|
||||
)
|
||||
|
||||
@@ -1387,10 +1380,8 @@ class RotaBuilder(object):
|
||||
)
|
||||
)
|
||||
|
||||
#if self.constraint_options["balance_weekends"]:
|
||||
for week_blocks in self.get_week_block_iterator(
|
||||
self.max_weekend_frequency
|
||||
):
|
||||
# if self.constraint_options["balance_weekends"]:
|
||||
for week_blocks in self.get_week_block_iterator(self.max_weekend_frequency):
|
||||
# Prevent weekend shifts more than once every n weeks
|
||||
self.model.constraints.add(
|
||||
1
|
||||
@@ -1406,14 +1397,16 @@ class RotaBuilder(object):
|
||||
self.constraint_options["max_shifts_per_week"]
|
||||
>= sum(
|
||||
self.model.works[worker.id, week, day, shiftname]
|
||||
#for shiftname in self.get_shift_names_by_week_day(week, day)
|
||||
#for day in self.days
|
||||
for w, day, shiftname in self.get_all_shiftname_combinations(week=week)
|
||||
# for shiftname in self.get_shift_names_by_week_day(week, day)
|
||||
# for day in self.days
|
||||
for w, day, shiftname in self.get_all_shiftname_combinations(
|
||||
week=week
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
# TODO: generic implementation
|
||||
#for shift in self.get_shifts_with_constraint("max_2_shifts_per_week"):
|
||||
# for shift in self.get_shifts_with_constraint("max_2_shifts_per_week"):
|
||||
# self.model.constraints.add(
|
||||
# 2
|
||||
# >= sum(
|
||||
@@ -1431,16 +1424,22 @@ class RotaBuilder(object):
|
||||
self.model.constraints.add(
|
||||
full_weekend_count
|
||||
>= sum(
|
||||
self.model.works[worker.id, week, "Sat", shift.name]
|
||||
for shift in self.get_shifts()
|
||||
self.model.works[worker.id, week, "Sat", shift]
|
||||
for shift in self.get_shift_names_by_week_day(
|
||||
week, "Sat"
|
||||
)
|
||||
)
|
||||
+ sum(
|
||||
self.model.works[worker.id, week, "Sun", shift.name]
|
||||
for shift in self.get_shifts()
|
||||
self.model.works[worker.id, week, "Sun", shift]
|
||||
for shift in self.get_shift_names_by_week_day(
|
||||
week, "Sun"
|
||||
)
|
||||
)
|
||||
+ sum(
|
||||
self.model.works[worker.id, week + 1, "Mon", shift.name]
|
||||
for shift in self.get_shifts()
|
||||
self.model.works[worker.id, week + 1, "Mon", shift]
|
||||
for shift in self.get_shift_names_by_week_day(
|
||||
week+1, "Mon"
|
||||
)
|
||||
)
|
||||
)
|
||||
if (
|
||||
@@ -1454,20 +1453,31 @@ class RotaBuilder(object):
|
||||
self.model.constraints.add(
|
||||
full_weekend_count
|
||||
>= sum(
|
||||
self.model.works[worker.id, week, "Sat", shift.name]
|
||||
for shift in self.get_shifts()
|
||||
self.model.works[worker.id, week, "Sat", shift]
|
||||
for shift in self.get_shift_names_by_week_day(
|
||||
week, "Sat"
|
||||
)
|
||||
)
|
||||
+ sum(
|
||||
self.model.works[worker.id, week, "Sun", shift.name]
|
||||
for shift in self.get_shifts()
|
||||
self.model.works[worker.id, week, "Sun", shift]
|
||||
for shift in self.get_shift_names_by_week_day(
|
||||
week, "Sun"
|
||||
)
|
||||
# for shift in self.get_shifts()
|
||||
)
|
||||
+ sum(
|
||||
self.model.works[worker.id, week + 1, "Mon", shift.name]
|
||||
for shift in self.get_shifts()
|
||||
self.model.works[worker.id, week + 1, "Mon", shift]
|
||||
for shift in self.get_shift_names_by_week_day(
|
||||
week + 1, "Mon"
|
||||
)
|
||||
# for shift in self.get_shifts()
|
||||
)
|
||||
+ sum(
|
||||
self.model.works[worker.id, week + 1, "Tue", shift.name]
|
||||
for shift in self.get_shifts()
|
||||
self.model.works[worker.id, week + 1, "Tue", shift]
|
||||
for shift in self.get_shift_names_by_week_day(
|
||||
week + 1, "Tue"
|
||||
)
|
||||
# for shift in self.get_shifts()
|
||||
)
|
||||
)
|
||||
if (
|
||||
@@ -1528,12 +1538,15 @@ class RotaBuilder(object):
|
||||
# self.model.works[worker.id, week, day, shift.name]
|
||||
# for day in self.days[5:]
|
||||
# for shift in self.get_shifts()) / 2)
|
||||
#if self.constraint_options["balance_weekends"]:
|
||||
# if self.constraint_options["balance_weekends"]:
|
||||
self.model.constraints.add(
|
||||
self.model.works_weekend[worker.id, week]
|
||||
>= sum(
|
||||
self.model.works[worker.id, week, day, shiftname]
|
||||
for w, day, shiftname in self.get_all_shiftname_combinations(week=week) if day in self.days[5:]
|
||||
for w, day, shiftname in self.get_all_shiftname_combinations(
|
||||
week=week
|
||||
)
|
||||
if day in self.days[5:]
|
||||
)
|
||||
/ 2
|
||||
)
|
||||
@@ -1541,7 +1554,10 @@ class RotaBuilder(object):
|
||||
self.model.works_weekend[worker.id, week]
|
||||
<= sum(
|
||||
self.model.works[worker.id, week, day, shiftname]
|
||||
for w, day, shiftname in self.get_all_shiftname_combinations(week=week) if day in self.days[5:]
|
||||
for w, day, shiftname in self.get_all_shiftname_combinations(
|
||||
week=week
|
||||
)
|
||||
if day in self.days[5:]
|
||||
)
|
||||
)
|
||||
# self.model.constraints.add(
|
||||
@@ -1557,7 +1573,7 @@ class RotaBuilder(object):
|
||||
# self.model.shift_week_worker_assigned[s.name, week, worker.id]
|
||||
# for s in self.get_shifts_with_constraint("night")))
|
||||
|
||||
#for shift in self.get_shifts_with_constraint("night"):
|
||||
# for shift in self.get_shifts_with_constraint("night"):
|
||||
for shift in self.get_shifts():
|
||||
if shift.force_as_block:
|
||||
# Force nights to be assigned in blocks
|
||||
@@ -1663,10 +1679,14 @@ class RotaBuilder(object):
|
||||
if day in constraint_shift.shift_days:
|
||||
self.model.constraints.add(
|
||||
1
|
||||
>= self.model.works[worker.id, week, day, constraint_shift.name]
|
||||
>= self.model.works[
|
||||
worker.id, week, day, constraint_shift.name
|
||||
]
|
||||
+ sum(
|
||||
p1 * self.model.works[w.id, pweek, pday, shiftname]
|
||||
for shiftname in self.get_shift_names_by_week_day(pweek, pday)
|
||||
for shiftname in self.get_shift_names_by_week_day(
|
||||
pweek, pday
|
||||
)
|
||||
if shiftname != constraint_shift.name
|
||||
for w in workers
|
||||
)
|
||||
@@ -1676,10 +1696,14 @@ class RotaBuilder(object):
|
||||
if day in constraint_shift.shift_days:
|
||||
self.model.constraints.add(
|
||||
1
|
||||
>= self.model.works[worker.id, week, day, constraint_shift.name]
|
||||
>= self.model.works[
|
||||
worker.id, week, day, constraint_shift.name
|
||||
]
|
||||
+ sum(
|
||||
p2 * self.model.works[w.id, p2week, p2day, shiftname]
|
||||
for shiftname in self.get_shift_names_by_week_day(p2week, p2day)
|
||||
for shiftname in self.get_shift_names_by_week_day(
|
||||
p2week, p2day
|
||||
)
|
||||
if shiftname != constraint_shift.name
|
||||
for w in workers
|
||||
)
|
||||
@@ -1691,10 +1715,14 @@ class RotaBuilder(object):
|
||||
if day in constraint_shift.shift_days:
|
||||
self.model.constraints.add(
|
||||
1
|
||||
>= self.model.works[worker.id, week, day, constraint_shift.name]
|
||||
>= self.model.works[
|
||||
worker.id, week, day, constraint_shift.name
|
||||
]
|
||||
+ sum(
|
||||
n1 * self.model.works[w.id, nweek, nday, shiftname]
|
||||
for shiftname in self.get_shift_names_by_week_day(nweek, nday)
|
||||
for shiftname in self.get_shift_names_by_week_day(
|
||||
nweek, nday
|
||||
)
|
||||
if shiftname != constraint_shift.name
|
||||
for w in workers
|
||||
)
|
||||
@@ -1704,18 +1732,28 @@ class RotaBuilder(object):
|
||||
if day in constraint_shift.shift_days:
|
||||
self.model.constraints.add(
|
||||
1
|
||||
>= self.model.works[worker.id, week, day, constraint_shift.name]
|
||||
>= self.model.works[
|
||||
worker.id, week, day, constraint_shift.name
|
||||
]
|
||||
+ sum(
|
||||
n2 * self.model.works[w.id, n2week, n2day, shiftname]
|
||||
for shiftname in self.get_shift_names_by_week_day(n2week, n2day)
|
||||
for shiftname in self.get_shift_names_by_week_day(
|
||||
n2week, n2day
|
||||
)
|
||||
if shiftname != constraint_shift.name
|
||||
for w in workers
|
||||
)
|
||||
)
|
||||
|
||||
# Night constraint means we won't assign a shift the day before
|
||||
# an unavailability
|
||||
for constraint_shift in self.get_shifts_with_constraint("night"):
|
||||
#if day in constraint_shift.shift_days:
|
||||
if (worker.id, pweek, pday, constraint_shift.name) in self.model.works:
|
||||
if (
|
||||
worker.id,
|
||||
pweek,
|
||||
pday,
|
||||
constraint_shift.name,
|
||||
) in self.model.works:
|
||||
# Ensure night prior to unavalibity is not assigned
|
||||
self.model.constraints.add(
|
||||
self.model.available[worker.id, week, day]
|
||||
@@ -1723,86 +1761,6 @@ class RotaBuilder(object):
|
||||
worker.id, pweek, pday, constraint_shift.name
|
||||
]
|
||||
)
|
||||
# # NOTE: use pre / post clear instead
|
||||
# # DEPRECATED
|
||||
# # if working a night ensure preceeding (1) or subsequent (2) shifts can only be nights
|
||||
# if self.constraint_options["constrain_time_off_after_nights"]:
|
||||
# for constraint_shift in self.get_shifts_with_constraint("night"):
|
||||
# if day in constraint_shift.shift_days:
|
||||
# # Ensure night prior to unavalibity is not assigned
|
||||
# self.model.constraints.add(
|
||||
# self.model.available[worker.id, week, day]
|
||||
# >= self.model.works[
|
||||
# worker.id, pweek, pday, constraint_shift.name
|
||||
# ]
|
||||
# )
|
||||
#
|
||||
# # print("Workers", workers)
|
||||
#
|
||||
# self.model.constraints.add(
|
||||
# 1
|
||||
# >= self.model.works[
|
||||
# worker.id, week, day, constraint_shift.name
|
||||
# ]
|
||||
# + sum(
|
||||
# n1 * self.model.works[w.id, nweek, nday, shift]
|
||||
# for shift in self.get_shift_names_by_week_day(
|
||||
# nweek, nday
|
||||
# )
|
||||
# if shift != constraint_shift.name
|
||||
# for w in workers
|
||||
# )
|
||||
# )
|
||||
#
|
||||
# self.model.constraints.add(
|
||||
# 1
|
||||
# >= self.model.works[
|
||||
# worker.id, week, day, constraint_shift.name
|
||||
# ]
|
||||
# + sum(
|
||||
# n2 * self.model.works[w.id, n2week, n2day, shift]
|
||||
# for shift in self.get_shift_names_by_week_day(
|
||||
# n2week, n2day
|
||||
# )
|
||||
# if shift != constraint_shift.name
|
||||
# for w in workers
|
||||
# )
|
||||
# )
|
||||
# # self.model.constraints.add(
|
||||
# # 1 >= self.model.works[worker.id, week, day,
|
||||
# # constraint_shift.name] +
|
||||
# # sum(n3 * self.model.works[worker.id, n3week, n3day,
|
||||
# # shift]
|
||||
# # for shift in self.get_shift_names_by_week_day(week, n3day)
|
||||
# # if shift != constraint_shift.name))
|
||||
# self.model.constraints.add(
|
||||
# 1
|
||||
# >= self.model.works[
|
||||
# worker.id, week, day, constraint_shift.name
|
||||
# ]
|
||||
# + sum(
|
||||
# p1 * self.model.works[w.id, pweek, pday, shift]
|
||||
# for shift in self.get_shift_names_by_week_day(
|
||||
# pweek, pday
|
||||
# )
|
||||
# if shift != constraint_shift.name
|
||||
# for w in workers
|
||||
# )
|
||||
# )
|
||||
# self.model.constraints.add(
|
||||
# 1
|
||||
# >= self.model.works[
|
||||
# worker.id, week, day, constraint_shift.name
|
||||
# ]
|
||||
# + sum(
|
||||
# p2 * self.model.works[w.id, p2week, p2day, shift]
|
||||
# for shift in self.get_shift_names_by_week_day(
|
||||
# p2week, p2day
|
||||
# )
|
||||
# if shift != constraint_shift.name
|
||||
# for w in workers
|
||||
# )
|
||||
# )
|
||||
|
||||
self.define_objectives()
|
||||
|
||||
@@ -1932,7 +1890,6 @@ class RotaBuilder(object):
|
||||
else:
|
||||
nights_site_balancing = 0
|
||||
|
||||
|
||||
if self.get_shifts_with_constraint("balance_across_groups"):
|
||||
block_site_balancing = sum(
|
||||
(
|
||||
@@ -1942,7 +1899,9 @@ class RotaBuilder(object):
|
||||
* 2000
|
||||
# self.model.night_per_site2[week, block, site]
|
||||
for week in self.weeks
|
||||
for shift in self.get_shifts_with_constraint("balance_across_groups")
|
||||
for shift in self.get_shifts_with_constraint(
|
||||
"balance_across_groups"
|
||||
)
|
||||
for site in self.sites
|
||||
)
|
||||
else:
|
||||
@@ -2112,32 +2071,34 @@ class RotaBuilder(object):
|
||||
for site in s.site:
|
||||
self.sites.add(site)
|
||||
|
||||
# # Todo replace with week_day.....
|
||||
# self.day_shift_product = []
|
||||
# self.day_shiftclass_product = []
|
||||
# for s in self.shifts:
|
||||
# for day in days:
|
||||
# if day in s.shift_days:
|
||||
# self.day_shift_product.append((day, s.name))
|
||||
# self.day_shiftclass_product.append((day, s))
|
||||
#
|
||||
# def get_day_shiftname_combinations(self):
|
||||
# """Returns a list of all required day / shift combinations
|
||||
#
|
||||
# Returns:
|
||||
# list: list of in the following format (str->day, str->shift)
|
||||
# """
|
||||
# return self.day_shift_product
|
||||
#
|
||||
# def get_day_shiftclass_combinations(self) -> List[Tuple[DayStr, SingleShift]]:
|
||||
# """Returns a list of all required day / shift combinations
|
||||
#
|
||||
# Returns:
|
||||
# list: list of in the following format (str->day, shiftObject->shift)
|
||||
# """
|
||||
# return self.day_shiftclass_product
|
||||
# # Todo replace with week_day.....
|
||||
# self.day_shift_product = []
|
||||
# self.day_shiftclass_product = []
|
||||
# for s in self.shifts:
|
||||
# for day in days:
|
||||
# if day in s.shift_days:
|
||||
# self.day_shift_product.append((day, s.name))
|
||||
# self.day_shiftclass_product.append((day, s))
|
||||
#
|
||||
# def get_day_shiftname_combinations(self):
|
||||
# """Returns a list of all required day / shift combinations
|
||||
#
|
||||
# Returns:
|
||||
# list: list of in the following format (str->day, str->shift)
|
||||
# """
|
||||
# return self.day_shift_product
|
||||
#
|
||||
# def get_day_shiftclass_combinations(self) -> List[Tuple[DayStr, SingleShift]]:
|
||||
# """Returns a list of all required day / shift combinations
|
||||
#
|
||||
# Returns:
|
||||
# list: list of in the following format (str->day, shiftObject->shift)
|
||||
# """
|
||||
# return self.day_shiftclass_product
|
||||
|
||||
def get_all_shiftname_combinations(self, week: int =None, day: int =None) -> List[Tuple[WeekInt, DayStr, ShiftName]]:
|
||||
def get_all_shiftname_combinations(
|
||||
self, week: int = None, day: int = None
|
||||
) -> List[Tuple[WeekInt, DayStr, ShiftName]]:
|
||||
"""Returns a list of all possible week / day / shift combinations
|
||||
|
||||
Returns:
|
||||
@@ -2154,7 +2115,7 @@ class RotaBuilder(object):
|
||||
return week_day_shifts
|
||||
|
||||
def get_all_shiftclass_combinations(
|
||||
self, week: int =None, day: int =None
|
||||
self, week: int = None, day: int = None
|
||||
) -> List[Tuple[WeekInt, DayStr, SingleShift]]:
|
||||
"""Returns a list of all possible week / day / shift combinations
|
||||
|
||||
@@ -2181,7 +2142,11 @@ class RotaBuilder(object):
|
||||
return self.weeks_days_product
|
||||
|
||||
def get_week_day_combinations_for_shift(self, shift) -> list:
|
||||
return [(week, day) for week, day in self.get_week_day_combinations() if shift.name in self.get_shift_names_by_week_day(week, day)]
|
||||
return [
|
||||
(week, day)
|
||||
for week, day in self.get_week_day_combinations()
|
||||
if shift.name in self.get_shift_names_by_week_day(week, day)
|
||||
]
|
||||
|
||||
def get_week_day_shift_combinations_for_constraint(self, constraint) -> list:
|
||||
constraint_shifts = self.get_shifts_with_constraint(constraint)
|
||||
@@ -2605,7 +2570,6 @@ class RotaBuilder(object):
|
||||
bank_holiday_count = -1
|
||||
bank_holiday_count_w = -1
|
||||
|
||||
|
||||
# print(worker.name, bank_holiday_count, bank_holiday_count_w)
|
||||
timetable.append(
|
||||
f"<tr class='worker-row'>{worker_td}{''.join(shift_tds)}</tr>"
|
||||
|
||||
Reference in New Issue
Block a user