微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决跨时间范围内具有多个工作中心的员工轮班安排

我是 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,l))

每位护士每天最多工作一班。

            for n in all_nurses:
                for d in all_days:
                    model.Add(sum(shift[(n,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,l)])
                        # week.append(sum(shifts[(n,s)] for s in all_shifts))
                # print(week)
            model.Add(sum(week) == 5)

第 d 天第 l 班次的护士人数应小于或等于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,l)]
                                      for n in all_nurses) <= weekly_cover_demands[l][d][s])
            model.Maximize(
                sum(shift[(n,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) 行缺少制表符空间。
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,l)]
                          for n in all_agents) == weekly_cover_demands[l,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,l)]) == 1:
                        print("nurse {} covers shift {} on day {}  at site {}".format(
                            agents[n],startschedule + datetime.timedelta(days=d),l),file=f)

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。