OR-TOOLS 调度以防止连续轮班

OR-TOOLS Scheduling to prevent consecutive shifts

我是新手,但有一些时间表求解器的工作代码。我唯一想不通的是如何确保员工不连续工作(service_blocks)。

我只想确定医生不会连续两班倒。看起来并不难,但我很烂。我尝试了很多变体,但似乎没有任何效果。 (我的尝试没有在下面显示。)只是寻求帮助。

如何阅读我的代码: 医生 = 雇员

Service_blocks = 班次

角色 = 基本上是他们工作的医院。

代码如下:

    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)))

你可以使用 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())