时间跨度内具有多个工作中心的员工轮班安排

Employee Shift Scheduling with Multiple Work Centers over time horizon

我是 ORTools 的新手,我正在尝试使用 ORTools 实施涉及一个月内多个班次和工作中心的员工排班问题的算法,

https://notebook.community/google/or-tools/examples/notebook/sat/schedule_requests_sat,
https://github.com/google/or-tools/blob/master/examples/python/shift_scheduling_sat.py,

等等.... 对于给定的工作中心,需要在给定班次期间对员工的需求(例如:3 名员工在上午班,2 名员工在下午班,1 名员工在晚班。objective 是分配选定的员工轮班和工作中心。 我在下面为 40 名员工、10 个工作中心和一个月做了类似的事情,但解决方案以一些员工有 42 小时而其他员工有 7 小时的解决方案结束....

            shift = {}
            for n in all_nurses:
                for s in all_shifts:  # range(num_shifts):
                    for d in all_days:
                        for l in all_sites:
                            shift[(n, s, d, l)] = model.NewBoolVar(
                                'shift_n%is%id%il%i' % (n, s, d, l))

每个护士每天最多工作一个班次。

            for n in all_nurses:
                for d in all_days:
                    model.Add(sum(shift[(n, s, d, l)]
                                  for s in range(num_shifts) for l in all_sites) <= 1)

每位护士每周工作 5 天

            for n in all_nurses:
                week = []
                for l in all_sites:
                    for s in all_shifts:
                        for d in all_days:
                            week.append(shift[(n, s, d, l)])
                        # week.append(sum(shifts[(n,d,s)] for s in all_shifts))
                # print(week)
            model.Add(sum(week) == 5)

第 d 天站点 l 班次 s 的护士人数应小于或等于 weekly_cover_demands[l][d][s]

      for l in all_sites:
                for d in all_days:
                    for s in range(num_shifts):
                        model.Add(sum(shift[(n, s, d, l)]
                                      for n in all_nurses) <= weekly_cover_demands[l][d][s])
            model.Maximize(
                sum(shift[(n, s, d, l)]
                    for l in all_sites for d in all_days for n in all_nurses for s in range(num_shifts)))

您的源代码中存在一些问题。

  1. 您希望算法每周 运行,但您提供了每月输入作为输入。您应该 运行 每周或添加周数。

a) 您可以将结束日期更改为 7 天

dates = {'start': '2021-02-01T00:00:00.000Z',
         'end': '2021-02-08T00:00:00.000Z'}

b) 或者您可以使用周数。这个选项可能更难。

all_weeks = range(4)
all_days = range(7)
for n in all_agents:
    for s in all_shifts:
        for w in all_weeks:
            for d in all_days:
                for l in all_sites:
                  ...
  1. model.Add(sum(week) <= 5) 行缺少制表符 space。
for n in all_agents:
    week = []
    for d in all_days:
        for l in all_sites:
            for s in all_shifts:
                week.append(shift[(n, s, d, l)])
    model.Add(sum(week) <= 5)
  1. 日期范围只设置7天,其他21天没有限制。您应该添加 week number 中描述的迭代 2. problem。或者只考虑每周一次的问题。
for l in all_sites:
    for d in range(7):
        for s in range(num_shifts):
            model.Add(sum(shift[(n, s, d, l)]
                          for n in all_agents) == weekly_cover_demands[l, d, s])
  1. 我推荐如下写输出方法。 Append 方法在每 运行 后增加文件大小。每次迭代,文件都在反复打开,很不方便。
with open('___output.txt', 'w') as f:
    for l in all_sites:
        for d in all_days:
            for s in all_shifts:
                for n in all_agents:
                    if solver.Value(shift[(n, s, d, l)]) == 1:
                        print("nurse {} covers shift {} on day {}  at site {}".format(
                            agents[n], s, startschedule + datetime.timedelta(days=d), l), file=f)

结论,ortools找不到可行解。请检查您的约束或输入参数。我认为你应该保持算法简单,每周而不是每月思考。