简体   繁体   English

Google OR Tools CP-SAT Solver - 调度问题,目标是在没有硬约束的情况下平均轮班分布(每个周期的最大/最小值)

[英]Google OR Tools CP-SAT Solver - scheduling problem with objective to even out shift distribution without hard constraints (max/min per period)

I am using Google ORTools using the Python wrapper to solve a nurse scheduling problem but I am having trouble finding a way to implement a constraint that attempts to evenly distribute worked shifts without using hard constraints.我正在使用使用 Python 包装器的 Google ORTools 来解决护士调度问题,但我无法找到一种方法来实施约束,该约束试图在不使用硬约束的情况下平均分配工作班次。

As an example, I working with a number of weeks, distinct shifts, and employees.例如,我与多个星期、不同的轮班和员工一起工作。 For illustration I add a very simple constraint which is that no employee can work on average more than the others for the full time period.为了说明,我添加了一个非常简单的约束,即没有员工在整个时间段内的平均工作时间不能超过其他人。

In the example below, one of many solutions with 5 weeks, 5 shifts, and 5 employees is to just have employee 0 work all the shifts in week 0, employee 1 all the shifts in week 1, etc.在下面的示例中,有 5 周、5 个轮班和 5 名员工的众多解决方案之一是让员工 0 在第 0 周的所有班次工作,让员工 1 在第 1 周的所有班次工作,等等。

What I want to add, however, is a constraint that maximizes the number of distinct weeks each employee works WITHOUT using a weekly constraint such as each employee can only work up to 1 shift per week.然而,我想添加的是一个约束,它可以在不使用每周约束的情况下最大化每个员工工作的不同周数,例如每个员工每周最多只能工作 1 个班次。

A few things that I have attempted but have failed to get working: Create a binary grid indexed by employee and week with a 1 if the employee has at least 1 shift that week and 0 otherwise and maximize the total sum of the grid.我尝试过但未能奏效的一些事情:创建一个由员工和周索引的二进制网格,如果该员工该周至少有 1 个轮班,则为 1,否则为 0,并最大化网格的总和。

Use a hard constraint such that each employee can only work so many shifts in a given week.使用硬性约束,使每个员工在给定的一周内只能轮班工作这么多次。 This is what I want to avoid, I would rather the solver consider this as an objective than a hard constraint.这是我想避免的,我宁愿求解器将其视为目标而不是硬约束。

My sample code is below:我的示例代码如下:


import os
import math
import pandas as pd
from ortools.sat.python import cp_model

num_weeks = 5
num_shifts = 5
num_employees = 5

all_weeks = range(num_weeks)
all_shifts = range(num_shifts)
all_employees = range(num_employees)

model = cp_model.CpModel()
assignments = {}

#Calculate a maximum number of shifts to balance everyone out for the full period 
max_total_shifts = math.ceil((num_weeks*num_shifts)/num_employees)

#Create a space of new boolean variables where the value is 1 if the employee is working that shift in that week, else 0
for w in all_weeks:
    for s in all_shifts:
        for e in all_employees:
            assignments[(w,s,e)] = model.NewBoolVar('w%i-s%i-e%i' % (w,s,e) )
        model.AddAtMostOne(assignments[(w,s,e)] for e in all_employees)

#Add the max constraint
for e in all_employees:
    model.Add(sum(assignments[w,s,e] for w in all_weeks for s in all_shifts) <= max_total_shifts)

#Assign as many shifts as possible
model.Maximize( sum(assignments[(w,s,e)] for w in all_weeks for s in all_shifts for e in all_employees) )


#Solve the model
solver = cp_model.CpSolver()
status = solver.Solve(model)        
print(status)

#Using pandas, view the solution
solution = pd.DataFrame()
data = []
for i,field in enumerate(model._CpModel__model.variables):
    model._CpModel__model.solution_hint.vars.extend([i])
    model._CpModel__model.solution_hint.values.extend([solver._CpSolver__solution.solution[i]])
    if solver._CpSolver__solution.solution[i]==1:
        data.append( [field.name,solver._CpSolver__solution.solution[i] ])
        #print("{} has value {}".format(field.name,solver._CpSolver__solution.solution[i]))  #         

solution = pd.DataFrame(data)

Fairness is the most complex question in OR.公平是 OR 中最复杂的问题。 You need to try to capture what you want with equations as sample as possible.您需要尝试使用方程式尽可能地捕获您想要的内容。

Std deviation, variance are not simple.标准偏差,方差并不简单。 Minimizing max(worked per person) - min(worked per person);is simple.最小化 max(worked per person) - min(worked per person); 很简单。

Good luck, this is a tough question to come up with a business acceptable definition of a good schedule.祝你好运,这是一个很难得出业务可接受的良好时间表定义的问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 OR-tools CP-SAT 求解器是否支持“反射”方法,例如 x.Min() 和 x.Max()? - Does OR-tools CP-SAT solver supports “reflection” methods such as x.Min() and x.Max()? 使用 OR-Tools CP-SAT Solver 约束分配优化问题的唯一性 - Constraint on uniqueness for Assignement Optimization Problem using OR-Tools CP-SAT Solver 使用 Google OR Tools CP-SAT Solver Log 来改进优化运行时 (Python) - Using Google OR Tools CP-SAT Solver Log To Improve Optimization Runtime (Python) 将 or 语句添加到 OR-Tools 约束(CP-SAT 求解器) - Adding an or-statement to an OR-Tools constraint (CP-SAT solver) 播种 CP-SAT 求解器 - Seeding the CP-SAT solver 使用 CP-SAT Solver 求解非线性目标函数 - Using CP-SAT Solver for non-linear objective function 如何在 CP-SAT 中指定条件约束 - How to specify conditional constraints in CP-SAT Or-Tools CP-SAT 求解器导出/导入:加载 model 后如何访问变量? - Or-Tools CP-SAT solver export/import: how to access vars after loading a model? 如何使用 Google 的 CP-SAT 求解器计算“AddAbsEquality”或“AddMultiplicationEqualit”以进行非线性优化? - How to calculate the “AddAbsEquality” or “AddMultiplicationEqualit” using Google's CP-SAT solver for non-linear optimization? 如何将 CP-SAT 公式(在 python 中)中的目标指定为所有决策变量值的最大值的最小化? - How can I specify the objective in a CP-SAT formulation (in python) to be the minimization of the max of all decision variable values?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM