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

减少 Google OR-tools python 脚本的运行时间使用 Google Cloud

如何解决减少 Google OR-tools python 脚本的运行时间使用 Google Cloud

我正在用 Python 为我工作的医院的一个科室开发护士排班程序。此类程序的各种示例已经存在并在线共享。其中之一如下:https://github.com/google/or-tools/blob/master/examples/python/shift_scheduling_sat.py

到目前为止,我已经修改了上面链接中的代码,以包含各种类型的劳动法规以及个别护士的偏好。现在,我想使用这个量身定制的脚本为 25 名护士在 7 周内(5 种轮班类型,可以减少到 4 人)制作名册。

但是,实施特定类型的约束会导致运行时间显着增加。这些约束是:

  • 对早/晚/夜班系列长度的限制:

     shift_constraints = [
    
          #Morning shifts
          (1,2,4,0),#Evening shifts
          (2,Night shifts
          (3,1,5,0)
    
    ]
    
  • 限制休息日。我想通过添加到轮班限制列表来阻止安排单天休假:

    (0,10,0)
    
  • 强制周末(周六和周日)都安排休息:

            for e in range(num_employees):
              for d in range(num_days):
                  if ( ( d in weekend_day ) & ( ( d+1 ) in weekend_day) ):
                      model.Add(work[e,d + 1] == 1 ).OnlyEnforceIf(work[e,d])
    
  • 强制员工在连续 3 次夜班后休息 2 天

            for e in range(num_employees):
              for d in range(num_days):
                  if ((d > 3) and (d<45)):
                      model.Add(work[e,d] == 1).OnlyEnforceIf(work[e,3,d-3] and work[e,d-2] and work[e,d-1])
                      model.Add(work[e,d + 1] == 1).OnlyEnforceIf(work[e,d-1])
    
  • 强制员工不能连续工作超过 7 天:

    max_seq_length = 7
      for e in range(num_employees):
          works = [work[e,d].Not() for d in range(num_days)]
          variables,coeffs = add_soft_sequence_constraint(
                 model,works,max_seq_length,'shift_constraint(employee %i,shift %i)' % (e,0))
          # model,hard_min,soft_min,min_cost,soft_max,hard_max,#max_cost,shift %i)' % (23 shift))
          obj_bool_vars.extend(variables)
          obj_bool_coeffs.extend(coeffs)
    

在没有任何这些限制的情况下运行脚本只需不到 1 分钟。但是,将所有这些同时添加到脚本中时,可能需要 48 多个小时才能找到解决方案。因此我想知道是否可以减少运行时间?如果有帮助,我不一定需要最佳解决方案。由于我很少使用惩罚约束,因此任何满足指定约束的解决方案都可以。

解决方法

您的代码中存在错误:

.OnlyEnforceIf(work[e,3,d-3] and work[e,d-2] and work[e,d-1])

应该是:

.OnlyEnforceIf([work[e,d-3],work[e,d-2],d-1]])

不要将 min(),max(),and,not,if 与 ortools 变量一起使用

,

我终于设法解决了这个问题。下面我将介绍我使用 Google 服务计算引擎的方法。

在我找到解决方案之前,我尝试了几件事:

  • 首先,我在运行时优化了代码。例如,我删除了一个每月只分配几次的班次类型,以减少搜索空间。我还删除了个别特定的轮班轮换规则和系列长度限制,因为这些会导致运行时间大幅增加
  • 我尝试了“num_search_workers”参数的各种设置。请注意,在最新版本的脚本中,此参数不再包含在代码中,必须手动添加。

但是,这些更改并没有导致运行时间的预期减少。很明显代码很好,但我只是没有足够的计算能力。因此我考虑如何在更强大的设备上运行脚本。我开始尝试在 Google Colab 中运行它,但这里的运行时间比在我自己的设备上还要长

然后我决定在 Google 云服务上试用计算引擎。只需点击几下,GCS 即可设置专用于 CPU 密集型任务(具有自定义规范)的虚拟机。此外,如果您以前从未使用过该服务,您可以获得 300 美元的信用来租用服务器。如果您注册,默认情况下您会获得一个测试帐户,该帐户对 VM 的规格有一些限制。但是,如果您切换到付费帐户,则信用额度会添加到您的帐户中,并且限制会解除。通过这种方式,我可以使用比我的笔记本电脑强大几个数量级的机器。

对于那些对使用 GCS 运行 python 脚本感兴趣的人,我建议观看这个视频作为介绍:

此外,Google 在此代码实验室中提供了使用 VM 的介绍:

这些视频介绍了如何在 Debian 操作系统上设置 python:

如果您正在设置 Python,请不要忘记创建一个虚拟环境来安装包和运行脚本:

在我弄清楚如何在 VM 上运行脚本后,我尝试了 VM 配置/num-search 工作器设置。不要忘记,如果您使用多核处理器,则可以增加搜索工作器的数量,从而降低运行时间。

我注意到 8 核(30 GB RAM)计算专用系统(在“试用帐户”中提供)在运行时间方面比我的笔记本电脑快 20-30。但是,我决定使用更强大的 VM。使用 30 核设置(130 GB RAM),脚本在 20 秒内运行完成,而不是 48 小时。

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