0

我是 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名员工上晚班。目标是分配选择员工轮班和工作中心。我在下面为 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)

站点 l 轮班 s 中第 d 天的护士人数应小于或等于 week_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)))
4

1 回答 1

0

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

  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)行缺少制表符空间。
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. 我建议编写输出方法如下。每次运行后附加方法都会增加文件大小。在每次迭代中,文件一次又一次地打开,不方便。
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找不到任何可行的解决方案。请检查您的约束或输入参数。我认为你应该保持算法简单,每周而不是每月思考。

于 2021-01-04T18:23:40.677 回答