I'm new to this but have some working code for a schedule solver. The only thing I can't figure out is how to ensure that employees don't work consecutive shifts (service_blocks).
I just want to make sure that a doctor doesn't work two shifts in a row. Doesn't seem like that would be tough but I suck. I've tried lots of variations but nothing seems to work. (my tries aren't shown below.) Just looking for some help.
How to read my code: Doctors = employees
Service_blocks = shifts
Roles = basically the hospital they work in.
Here's the code:
class DoctorPartialSolutionPrinter(cp_model.CpSolverSolutionCallback):
"""Print intermediate solutions."""
def __init__(self, roles, num_doctors, num_service_block, num_roles, sols):
cp_model.CpSolverSolutionCallback.__init__(self)
self._roles = roles
self._num_doctors = num_doctors
self._num_service_block = num_service_block
self._num_roles = num_roles
self._solutions = set(sols)
self._solution_count = 0
def on_solution_callback(self):
if self._solution_count in self._solutions:
print('Solution %i' % self._solution_count)
for b in range(self._num_service_block):
print('----------Service Block %i -----------' % (b+1))
for d in range(self._num_doctors):
is_working = False
for r in range(self._num_roles):
if self.Value(self._roles[(d, b, r)]):
is_working = True
str1 = " works role: "
#print("N:" , n)
#print("S:", s)
print(doctor_list[d], str1, role_list[r] )
#print(' Doctor %i works role ' % ((n+1)), end = '')
#print(role_list[s-1])
#if not is_working:
#print(' Doctor {} does not work'.format(n+1))
print()
self._solution_count += 1
def solution_count(self):
return self._solution_count
def main():
# Data.
num_doctors = 27 # we should build this number from the doctor_list array
num_roles = 9 # I think this is really one less since the index is zero
num_service_block = 24
all_doctors = range(num_doctors)
all_roles = range(num_roles)
all_service_blocks = range(num_service_block)
# Creates the model.
model = cp_model.CpModel()
# Creates role variables.
roles = {}
for d in all_doctors:
for b in all_service_blocks:
for r in all_roles:
roles[(d, b, r)] = model.NewBoolVar('role_d%ib%ir%i' % (d, b, r))
# Each role is assigned to exactly one doctor in the schedule period.
for b in all_service_blocks:
for r in all_roles:
model.Add(sum(roles[(d, b, r)] for d in all_doctors) == 1)
# Each doctor works at most one role per service block.
for d in all_doctors:
for b in all_service_blocks:
model.Add(sum(roles[(d, b, r)] for r in all_roles) <= 1)
print((sum(roles[(d, b, r)] for r in all_roles)))
You could use model.AddImplication(boolvar, boolvar)
:
for d in all_doctors:
for b in all_service_blocks[:-1]:
for r in all_roles:
for r1 in all_roles:
model.AddImplication(roles[(d, b, r)], roles[(d, b+1, r1)].Not())