我写了一段代码,但不明白我哪里出错了。该解决方案变得不可行,特别是与连续性约束有关。也就是说,如果我删除连续性约束,它就可以正常工作。
示例数据的链接:
https://drive.google.com/drive/folders/1QIr-zFhXzNtXQO6H0KkclpPPGZJ7735L?usp=sharing
import pulp
# Define the problem
prob = pulp.LpProblem("Minimize_Employee_Hours", pulp.LpMinimize)
# Define variables
shift_work = pulp.LpVariable.dicts("ShiftWork", [(emp, task, hour) for emp in employees for task in tasks for hour in range(24)],
lowBound=0, cat='Binary')
# Define auxiliary binary variable for start of the shift
start_work = pulp.LpVariable.dicts("ShiftStart", [(emp, start_hour) for emp in employees for start_hour in range(24)],
cat='Binary')
# Objective function: Minimize the total number of employee hours
prob += pulp.lpSum([shift_work[(emp, task, hour)] for emp in employees for task in tasks for hour in range(24)])
# Task requirement constraints for each hour
for task in tasks:
for hour in range(24):
prob += pulp.lpSum([shift_work[(emp, task, hour)] for emp in employees]) >= requirements[task][hour]
# Ensure employees do not work more than 8 hours in total across all tasks
for emp in employees:
prob += pulp.lpSum([shift_work[(emp, task, hour)] for task in tasks for hour in range(24)]) <= 8
# Ensure employees only work on tasks they are skilled for
for emp in employees:
for task in tasks:
for hour in range(24):
prob += shift_work[(emp, task, hour)] <= skills[emp][task]
# Ensure an employee can only work on one task at a time
for emp in employees:
for hour in range(24):
# Sum of shift_work for all tasks at a given hour should be <= 1
prob += pulp.lpSum([shift_work[(emp, task, hour)] for task in tasks]) <= 1
# Ensure employees only work when available
for emp in employees:
for task in tasks:
for hour in range(24):
prob += shift_work[(emp, task, hour)] <= availability[emp][hour]
# max one shift entire day per employee
for emp in employees:
prob += pulp.lpSum([start_work[(emp, start_hour)] for start_hour in range(24)]) <= 1
# Continuous hours constraint
for emp in employees:
for start_hour in range(17): # If the shift starts before 17 (i.e., from 0 to 16)
prob += pulp.lpSum([shift_work[(emp, task, hour)]
for task in tasks
for hour in range(start_hour, start_hour + 8)]) <= 8 * start_work[(emp, start_hour)]
for start_hour in range(17, 24): # If the shift starts at or after 17 (i.e., from 17 to 23)
prob += pulp.lpSum([shift_work[(emp, task, hour)]
for task in tasks
for hour in range(start_hour, 24)]) <= (24 - start_hour) * start_work[(emp, start_hour)]
# Solve the problem
solver = pulp.getSolver('GLPK_CMD')
prob.solve(solver)
尝试将如下所示的内容替换为连续性的约束。
我要假设,因为尚不完全清楚员工在轮班期间可以转向不同的任务,因为在这种情况下,您确实需要一个“工作”变量和一个“开始”变量,所以我想这就是你的意图。
最初设置连续性约束的方式的问题是,员工必须在前面的“所有”起点中从 1 开始才能工作。 您将其写为“与”约束。 这转变为“或”约束,基本上是说,为了在 x
小时内工作,您必须在
{x-7, x-6, ..., x}
小时内开始工作。代码
# Must have started shift constraint
# in order to work in hour x, employee must have a start within the last x-7 shifts, or at hour x
for emp in employees:
for hour in range(24):
start_hours = set(range(max(0, hour-7), hour + 1)) # the start "window" for this hour
prob += pulp.lpSum(shift_work[emp, task, hour] for task in tasks) <= pulp.lpSum(
start_work[emp, start_hour] for start_hour in start_hours)
未测试,因为您的数据未包含在问题中(链接到 Google 中响应者必须处理的内容不算在内。;)