公平班次分配

Posted

技术标签:

【中文标题】公平班次分配【英文标题】:Fair Shift Distribution 【发布时间】:2018-11-17 22:25:53 【问题描述】:

我有一个稍微修改过的nurse_sat版本https://github.com/google/or-tools/blob/master/examples/python/nurses_sat.py 我有一个键值字典(天,护士,班次)= BoolVar 我想让所有护士每次轮班的数量都相同。

E.G:假设我们有 30 天,每天有 3 个班次 0,1,2,我们有 3 名护士 a,b,c 我想让所有护士做 0 班 10、2 班 10 和 3 班 10。

我试图实现的方法是:

fairshift = 
for j in range(num_nurses):
 for k in range(num_shifts):
  fairshift[(j,k)] = sum(shifts[(i, j, k)] for i in range(num_days))

理论上,这应该让我知道一名护士有多少特定的班次。例如: fairshift[(0, 0)] 应该有护士 A 一周内的 0 班次的数量。然后为了让他们平等,我做了这样的事情:

for k in range(num_shifts):
 solver.Add(min([fairshift[(j, k)] for j in range(num_nurses)]) == max([fairshift[(j,k)] for j in range(num_nurses)]))

因此,护士的最大 k 班次将等于最小的一次,如果 num_days 为 30,则他们都应该有 10 班 k 班次。

但是,我无法让它工作,我不确定为什么。为了有 IntVar 而不是 _SumArray,我做了这样的事情:

for j in range(num_nurses):
 for k in range(num_shifts):
  fairshift[(j,k)] = solver.NewIntVar(0, num_days, "%i,%i" % (j,k))
  solver.Add(fairshift[(j,k)] == sum(shifts[(i, j, k)] for i in range(num_days)))

在 min .== max 的情况下,它可以工作,但会给出错误的结果。我想我总结错了,但我不确定它是什么。

【问题讨论】:

第一个快速评论,你应该有max(fair_shifts) - min(fair_shifts) <= 1 来解释当班次数不是人数的倍数时的情况。 但真正的问题是你不能使用 python 的 min() 和 max() 操作符,因为它被扩展为模型无法理解的东西。它适用于 sum() 但不适用于 min/max。您应该将model.AddMaxEquality()model.AddMinEquality() 与中间整数变量一起使用。 你好@Laurent Perron,我想既然 max([IntVar]) 返回 IntVar,它也可以工作,现在已经修复了。我之前尝试过 AddMaxEquality,但出现错误但 _SumArray 没有索引,但它可以将 IntVars 分配给 fairshift[(j, k)]。谢谢!如果您想将此作为答案,我很乐意接受。 【参考方案1】:
fairshift = 
for n in range(num_nurses):
  for s in range(num_shifts):
    sum_of_shifts[(n, s)] = model.NewIntVar(0, num_days, 'sum_of_shifts_%i_%i' % (n, s))
    model.Add(sum_of_shifts[(n, s)] == sum(shifts[(d, n, s)] for d in range(num_days)))


for s in range(num_shifts):
  min_fair_shift = model.NewIntVar(0, num_days, 'min_fair_shift_%i' % s)
  max_fair_shift = model.NewIntVar(0, num_days, 'max_fair_shift_%i' % s)
  model.AddMinEquality(min_fair_shift, [sum_of_shifts[(n, s)] for n in range(num_nurses)])
  model.AddMaxEquality(max_fair_shift, [sum_of_shifts[(n, s)] for n in range(num_nurses)]) 

  model.Add(max_fair_shift - min_fair_shift <= 1)

【讨论】:

以上是关于公平班次分配的主要内容,如果未能解决你的问题,请参考以下文章

基于技能公平分配任务给工人的算法

公平分布式资源分配共识推荐算法

公平调度和容量调度的区别

多线程学习 公平锁和非公平锁

max-min fairness 最大最小公平算法

[转] max-min fairness 最大最小公平算法