首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >或-工具,员工计划,顺序分配,员工组

或-工具,员工计划,顺序分配,员工组
EN

Stack Overflow用户
提问于 2020-06-04 08:07:52
回答 1查看 334关注 0票数 1

使用标准/简单护理实例:排程

我正试图强制要求某一组/团队的护士连续分配几天。如下所示,护士1-9分成“小组”。如果首先分配护士9,那么组(4和7)的其他成员应该分配到接下来的几天。

我认为,我可以通过计算一组成员一天又一天分配的次数来实现这一点,但我无法计算何时发生这种情况,即day_i和day_i+1都分配给来自同一组的护士。

代码语言:javascript
复制
groups = [[3,7,8],[1,6],[5],[4,9,7]] #nurses 3,7,8 are in same group
...
for g in groups:
    for d1, d2 in zip(all_days[:-1],all_days[1:]):
        d1_alloc = sum(shifts[(n, d1, s)] for n in g)
        d2_alloc = sum(shifts[(n, d2, s)] for n in g)
        # ??? how to say only count when both sums = 1/true ???
        # for a group of 3, i.e. [3,7,8] this should occur twice within period

完整法典:

代码语言:javascript
复制
from ortools.sat.python import cp_model

all_days = range(1,10)
all_nurses = range(1,10)
groups = [[3,7,8],[1,6],[5],[4,9,7]] #nurses 3,7,8 are in same group
s=1 #1 shift only

model = cp_model.CpModel()

shifts = {}
for d in all_days:
    for n in all_nurses:
        shifts[(n, d, s)] = model.NewBoolVar('shift_n%sd%is%i' % (n, d, s))
            
# one nurse per shift
for d in all_days:
    model.Add(sum(shifts[(n, d, s)] for n in all_nurses) == 1)
               
# everyone works a shift
for n in all_nurses:
    model.Add(sum(shifts[(n, d, s)] for d in all_days) == 1)
 
# nurses within group should be allocated days one after another
# order of groups is not important - last group [4,9,7] could be allocated firts
# order within groups is not important - can be 7,4,9
    
for g in groups:
    for d1, d2 in zip(all_days[:-1],all_days[1:]):
        d1_alloc = sum(shifts[(n, d1, s)] for n in g)
        d2_alloc = sum(shifts[(n, d2, s)] for n in g)
        # ??? how to say only count when both sums 1/true ???
        # for a group of 3, i.e. [3,7,8] this should occur twice within period


solver = cp_model.CpSolver()
solver.Solve(model)

for d in all_days:
    for n in all_nurses:
        if solver.Value(shifts[(n, d, s)]) == 1:
            print('Day: '+str(d)+' = Nurse '+str(n))

编辑:可以使用以下逻辑来实现这一点

代码语言:javascript
复制
for group in groups:     
    for n1, n2 in zip(group[:-1],group[1:]):
        for d in all_days[:-1]:

            model.AddBoolOr([shifts[n1, d, 1],shifts[n2, d+1, 1].Not()])
            model.AddBoolOr([shifts[n1, d, 1].Not(),shifts[n2, d+1, 1]])

此解决方案是限制性的-分配必须遵循与所列组相同的顺序。第3,7,8组总是3,7,8,但不是7,3,8或8,3,7,例如.这也很好。

还必须确保第一天从一开始就分配给某个人。Model.Add(3,1,5,4中n的移位(n,1,s) ==1)

如果只有最多2名成员的组,以下将允许任何一种命令。比如第三组,第七组.3、7或7.3。

代码语言:javascript
复制
for group in groups:     
    for n1, n2 in zip(group[:-1],group[1:]):
        
        #Day1
        model.AddImplication(shifts[n1, 1, 1],shifts[n2, 2, 1])
        model.AddImplication(shifts[n2, 1, 1],shifts[n1, 2, 1])
        
        #Day2 + must check preceding day to avoid circular/repeated allocations
        for d in all_days[1:-1]:
            
          model.AddImplication(shifts[n1, d, 1],shifts[n2, d+1, 1]).OnlyEnforceIf(shifts[n2, d-1, 1].Not())
          model.AddImplication(shifts[n2, d, 1],shifts[n1, d+1, 1]).OnlyEnforceIf(shifts[n1, d-1, 1].Not())

编辑2:以下内容可用于任何大小的组.

代码语言:javascript
复制
for g in groups:
    
    for i in range(0,len(g)):
        #1 cycle for every group order [3,7,2], [7,2,3],[2,3,7]

        for d in all_days[:-(len(g)-1)]:
            
            conditions_met = [shifts[g[0], d, 1]] #n1 allocated today
            if d > 1:
                #ensure group members not allocated previous day
                for n in g:
                    conditions_met.append(shifts[n, d-1, 1].Not())
            
            #apply rules for next x days - depending on size of group
            for day in range(d+1,d+len(g)):
                or_cond = []
                for n in g[1:]:
                    or_cond.append(shifts[n,day,1])
                model.AddBoolOr(or_cond).OnlyEnforceIf(conditions_met)

        x = g.pop(0)
        g.append(x)
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-06-04 09:52:19

对于更复杂的约束,我建议查看此移位调度示例

特别是包含min和max序列约束。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62189770

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档