night shift balancing now works!
This commit is contained in:
@@ -241,19 +241,25 @@ class RotaBuilder(object):
|
||||
initialize=0,
|
||||
)
|
||||
|
||||
self.model.worker_weekend_assigned = Var(
|
||||
((worker.id, week) for worker in self.workers
|
||||
for week in self.weeks),
|
||||
domain=NonNegativeReals,
|
||||
initialize=0,
|
||||
)
|
||||
self.model.night_shift_count_w = Var(
|
||||
((worker.id) for worker in self.workers),
|
||||
domain=NonNegativeReals,
|
||||
initialize=0,
|
||||
)
|
||||
|
||||
self.model.works_weekend_count = Var(
|
||||
((worker.id, week) for worker in self.workers
|
||||
for week in self.weeks),
|
||||
domain=NonNegativeIntegers,
|
||||
initialize=0,
|
||||
)
|
||||
# self.model.worker_weekend_assigned = Var(
|
||||
# ((worker.id, week) for worker in self.workers
|
||||
# for week in self.weeks),
|
||||
# domain=NonNegativeReals,
|
||||
# initialize=0,
|
||||
# )
|
||||
|
||||
# self.model.works_weekend_count = Var(
|
||||
# ((worker.id, week) for worker in self.workers
|
||||
# for week in self.weeks),
|
||||
# domain=NonNegativeIntegers,
|
||||
# initialize=0,
|
||||
# )
|
||||
# self.model.works_saturday = Var(
|
||||
# ((worker.id, week) for worker in self.workers
|
||||
# for week in self.weeks),
|
||||
@@ -274,18 +280,39 @@ 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,
|
||||
initialize=0,
|
||||
)
|
||||
if self.constraint_options["balance_weekends"]:
|
||||
|
||||
self.model.worker_weekend_count = Var(
|
||||
((worker.id) for worker in self.workers),
|
||||
domain=NonNegativeIntegers,
|
||||
initialize=0,
|
||||
)
|
||||
self.model.works_weekend = Var(
|
||||
((worker.id, week) for worker in self.workers
|
||||
for week in self.weeks),
|
||||
domain=Binary,
|
||||
initialize=0,
|
||||
)
|
||||
|
||||
self.model.worker_weekend_count = Var(
|
||||
((worker.id) for worker in self.workers),
|
||||
domain=NonNegativeIntegers,
|
||||
initialize=0,
|
||||
)
|
||||
|
||||
|
||||
self.model.weekend_shift_count_t1 = Var(
|
||||
((worker.id) for worker in self.workers),
|
||||
domain=NonNegativeReals,
|
||||
initialize=0,
|
||||
)
|
||||
|
||||
self.model.weekend_shift_count_t2 = Var(
|
||||
((worker.id) for worker in self.workers),
|
||||
domain=NonNegativeReals,
|
||||
initialize=0,
|
||||
)
|
||||
|
||||
self.model.weekend_shift_count_w = Var(
|
||||
((worker.id) for worker in self.workers),
|
||||
domain=NonNegativeReals,
|
||||
initialize=0,
|
||||
)
|
||||
|
||||
# self.model.weekend_count_t1 = Var(
|
||||
# ((worker.id) for worker in self.workers),
|
||||
@@ -418,12 +445,12 @@ class RotaBuilder(object):
|
||||
)
|
||||
|
||||
def nightShiftMinST4Rule(model, week, shift):
|
||||
single_workers = [w for w in self.workers if w.grade > 3]
|
||||
single_workers = [w for w in self.workers if w.grade >= 4]
|
||||
if not single_workers:
|
||||
print(single_workers)
|
||||
return Constraint.Skip
|
||||
return sum(model.shift_week_worker_assigned[shift, week, w.id]
|
||||
for w in single_workers) >= 2
|
||||
for w in single_workers) >= 1
|
||||
|
||||
if self.constraint_options["ensure_1_st4_plus_on_nights"]:
|
||||
self.model.night_shifts_min_st4_constraint = Constraint(
|
||||
@@ -592,6 +619,31 @@ class RotaBuilder(object):
|
||||
self.model.night_shift_count[worker.id] -
|
||||
night_shift_target_number)
|
||||
|
||||
xU = 6
|
||||
xL = 1
|
||||
self.model.constraints.add(
|
||||
inequality(
|
||||
xL,
|
||||
self.model.night_shift_count_t1[worker.id] +
|
||||
self.model.night_shift_count_t2[worker.id] + 1,
|
||||
xU,
|
||||
))
|
||||
|
||||
self.model.constraints.add(
|
||||
self.model.night_shift_count_w[worker.id] >= xL *
|
||||
(self.model.night_shift_count_t1[worker.id] +
|
||||
self.model.night_shift_count_t2[worker.id] + 1) * 2 -
|
||||
xL * xL)
|
||||
|
||||
self.model.constraints.add(
|
||||
self.model.night_shift_count_w[worker.id] >= xU *
|
||||
(self.model.night_shift_count_t1[worker.id] +
|
||||
self.model.night_shift_count_t2[worker.id] + 1) * 2 -
|
||||
xU * xU)
|
||||
|
||||
# self.model.constraints.add(
|
||||
# self.model.night_shift_count_w[worker.id] >= 0)
|
||||
|
||||
# Ensure worker is not allocated shifts on non working days
|
||||
if worker.nwd:
|
||||
for week, day, shift in self.get_all_shiftclass_combinations():
|
||||
@@ -775,11 +827,12 @@ class RotaBuilder(object):
|
||||
shift_balancing = 0
|
||||
|
||||
if self.constraint_options["balance_nights"]:
|
||||
night_balance_modifier_constant = 2000
|
||||
night_balance_modifier_constant = 1
|
||||
night_shift_balancing = sum(
|
||||
night_balance_modifier_constant *
|
||||
(self.model.night_shift_count_t1[(worker.id)] +
|
||||
self.model.night_shift_count_t2[(worker.id)])
|
||||
self.model.night_shift_count_w[(worker.id)]
|
||||
# (self.model.night_shift_count_t1[(worker.id)] +
|
||||
# self.model.night_shift_count_t2[(worker.id)])
|
||||
for worker in self.workers)
|
||||
else:
|
||||
night_shift_balancing = 0
|
||||
@@ -816,7 +869,7 @@ class RotaBuilder(object):
|
||||
return night_shift_balancing
|
||||
#return shift_balancing + preferences + blocks_balancing
|
||||
#return shift_balancing + preferences + nights_site_balancing + blocks_balancing
|
||||
return shift_balancing + night_shift_balancing + preferences + nights_site_balancing + blocks_balancing
|
||||
#return shift_balancing + night_shift_balancing + preferences + nights_site_balancing + blocks_balancing
|
||||
|
||||
# add objective function to the model. rule (pass function) or expr (pass expression directly)
|
||||
self.model.obj = Objective(rule=obj_rule, sense=minimize)
|
||||
@@ -1267,9 +1320,16 @@ class RotaResults(object):
|
||||
def get_night_details(self):
|
||||
for worker in self.rota.workers:
|
||||
print(
|
||||
worker.name,
|
||||
self.rota.model.night_shift_count[(worker.id)].value,
|
||||
self.rota.model.night_shift_count_t1[(worker.id)].value,
|
||||
self.rota.model.night_shift_count_t2[(worker.id)].value,
|
||||
worker.shift_target_number["night_weekday"] +
|
||||
worker.shift_target_number["night_weekend"])
|
||||
"{:20}".format(worker.name),
|
||||
"worked: {},".format(
|
||||
self.rota.model.night_shift_count[(worker.id)].value),
|
||||
"target: {},".format(
|
||||
worker.shift_target_number["night_weekday"] +
|
||||
worker.shift_target_number["night_weekend"]),
|
||||
"target_diff: {},".format(
|
||||
self.rota.model.night_shift_count_t1[(worker.id)].value +
|
||||
self.rota.model.night_shift_count_t2[(worker.id)].value +
|
||||
1),
|
||||
"balance: {},".format(
|
||||
self.rota.model.night_shift_count_w[worker.id].value),
|
||||
)
|
||||
Reference in New Issue
Block a user