向问题添加约束时,Python PuLP 警告“覆盖先前设置的目标”

mtruong1999

我正在尝试使用 PuLP 库为诊所构建员工调度系统。但是,每当我尝试添加约束时,我都会收到标题中提到的警告,如下面的代码所示。我使用在 PuLP 文档中找到的本案例研究中的代码作为构建 LP 问题的参考。

问题的快速总结:诊所有 3 个地点,我正在构建一个系统,该系统可以构建最佳解决方案来安排这 3 个地点的员工列表。我们不安排/计算小时数,而只是按天安排(例如,Jim 在星期一、星期二和星期五工作)。每个诊所对每天所需的特定专业(我在下面的代码中称之为角色)的员工人数都有要求。现在,我正在尝试添加一个约束来限制可以在某一天的特定位置安排的特定角色的员工数量。

函数 maxnum_(day,location,role) 现在只返回 3(以测试约束)(即可以在任何位置安排的最大员工数为 3)。当我使用 <= (应该如此)设置约束时,程序完成执行,但是当我打印 shift_model 时,我没有看到任何添加的约束。此外,为了尝试进一步探索该问题,我将 <= 更改为 == 和 >=。对于这两种情况,我都收到了覆盖目标函数的警告,即使它看起来不像我......

from pulp import *
def maxnum_(d,l,r):
    return 3
def coefficients(instance):

    #Given a shift instance, returns the weight of the preference
    #based on the parameters of the instance.
    #Chosen values are subject to change.

    weight = 0
    employee = instance[0]
    day = instance[1]
    location = instance[2]
    role = instance[3]
    global allEmployees
    if day not in allEmployees[employee]['Availability']:
        weight -= 5
    else:
        weight += 1
    if location not in allEmployees[employee]['PreferredLocationOfWork']:
        weight -= 2
    else:
        weight+=1
    return weight


shifts = ['M1','M2','T1','T2','W1','W2','R1','R2','F1','F2']
allEmployees = {'Billy Bob': {'License': 'Nurse Practitioner', 'Specialty': 'Urgent', 'Age': 'Geriatric', 'Availability': ['M1', 'T1', 'F1', 'M2', 'R2', 'F2'], 'PreferredLocationOfWork': 'PPHC', 'Requested_dates_off': ['2020-05-09', '2021-01-31', 'YYYY-MM-DD']}, 'Jimmy John': {'License': 'Physician', 'Specialty': 'Emergency', 'Age': 'Pediatric', 'Availability': ['T1', 'F1', 'W2', 'R2'], 'PreferredLocationOfWork': 'CHCF', 'Requested_dates_off': ['2020-05-09', '2021-01-31', 'YYYY-MM-DD']}}
# Ignoring specialty/age/license required and min number employees required for now, will implement later
allLocations = {'CHCF': {'MinNumberEmployeesRequiredPresent': 1, 'SpecialtyRequired': ['Emergency', 'Urgent', 'Urgent'], 'AgeRequired': ['Pediatric', 'Geriatric', 'Pediatric'], 'LicenseRequired': ['Physician', 'NurseMidwife', 'NursePracticioner']}, 'THS': {'MinNumberEmployeesRequiredPresent': 1, 'SpecialtyRequired': ['Emergency', 'Urgent', 'Primary', 'Obstetrics'], 'AgeRequired': ['Pediatric', 'Geriatric', 'Family', 'Adult'], 'LicenseRequired': ['Physician', 'NurseMidwife', 'NursePracticioner', 'Physician']}, 'PPHC': {'MinNumberEmployeesRequiredPresent': 1, 'SpecialtyRequired': ['Urgent', 'Urgent', 'Urgent'], 'AgeRequired': ['Geriatric', 'Geriatric', 'Pediatric'], 'LicenseRequired': ['Physician', 'NurseMidwife', 'NursePracticioner']}}
age_ = ['Pediatric', 'Adult','Geriatric', 'Family']
specialty_ = ['Emergency', 'Urgent Care', 'Primary Care', 'Obstetrics']
license_ = ['Physician','Nurse Midwife', 'Nurse Practitioner']
roles = [','.join([a,s,l]) for a in age_ for s in specialty_ for l in license_ ]
listOfVariables = []
# Start creating the tuples of shift instances, these will be the variables of our LP problem
for employee in allEmployees.keys():
    specialty = []
    specialty.append(allEmployees[employee]['Age'])
    specialty.append(allEmployees[employee]['Specialty'])
    specialty.append(allEmployees[employee]['License'])
    specialtyString = ','.join(specialty)
    #TODO: Implement weighted alternates...

    for day in shifts:
        # Include all locations, set preferred location coefficient to 10 and non preferred to 1?
        for location in allLocations.keys():
            # In coefficients, set days not in preference to 1, all preferred dates to 10
            listOfVariables.append((employee, day, location, specialtyString))

x = LpVariable.dicts('shift', listOfVariables, lowBound = 0, upBound = 1, cat = LpInteger)

shift_model = LpProblem("Employee_Scheduling_Model" , LpMaximize)
# The objective function
shift_model += sum([coefficients(shift_instance) * x[shift_instance] for shift_instance \
            in listOfVariables])

# Add Constraint limiting the number of possible employees of a specific role to schedule on a given day at a given location
for day in shifts: # for each day in pay period
    for location in allLocations.keys(): # for each clinic
        for role in roles: # for each role
            shift_model += sum([x[shift_instance] for shift_instance in listOfVariables if day in shift_instance and location in shift_instance\
                    and role in shift_instance]) == maxnum_(day, location, role), "Max employees for {} {} {}".format(day,location,role)

shift_model.solve()
print("Optimal employee schedule: ")
for shift_instance in listOfVariables:
    if x[shift_instance].value() == 1.0:
        print(x[shift_instance])

shift_model 是元组 (e, d, l, r) 乘以计算系数的总和。该元组是一个“shift_instance”,其中员工 e 在第 d 天在位置 l 为角色 r 工作。这些元组是问题的变量,可以是 0 或 1,其中 1 表示该 shift_instance 将成为计划的一部分。计算的系数几乎是员工的偏好(例如,如果 Jimmy John 在星期二不可用,则 ('Jimmy John', 'Tuesday', "Clinic A', 'Pediatrician') 的系数是负数,而如果他有空,那么它将是一个正数)。因此目标是最大化这个模型。哦,

我的问题是,为什么我会收到这些警告以及为什么没有将约束添加到 LpProblem 中?

pchtsp

再会!

您不应该sum在纸浆中使用 python 的标准函数 tu sum 表达式或变量。您应该使用lpSum包提供功能。它不仅效率更高,而且在这种情况下,它可以解决您的问题。不过,我无法解释原因。

所以,在约束的代码中你应该有:

shift_model += lpSum([coefficients(shift_instance) * x[shift_instance] for shift_instance \
            in listOfVariables])

# Add Constraint limiting the number of possible employees of a specific role to schedule on a given day at a given location
for day in shifts: # for each day in pay period
    for location in allLocations.keys(): # for each clinic
        for role in roles: # for each role
            shift_model += lpSum([x[shift_instance] for shift_instance in listOfVariables if day in shift_instance and location in shift_instance\
                    and role in shift_instance]) == maxnum_(day, location, role), "Max employees for {} {} {}".format(day,location,role)

此外,这是关于性能的一般建议,在迭代之前预过滤变量字典更有效。它还使代码更清晰。以下是编辑后的模型部分:


x = LpVariable.dicts('shift', listOfVariables, lowBound = 0, upBound = 1, cat = LpInteger)

shift_model = LpProblem("Employee_Scheduling_Model" , LpMaximize)
# The objective function
shift_model += lpSum([coefficients(shift_instance) * x[shift_instance] for shift_instance \
            in listOfVariables])

# for each day, location and role: a list of variables
x_dlr = {}
for (e, d, l, r), _x in x.items():
    _tup = d, l, r
    if _tup not in x_dlr:
        x_dlr[_tup] = []
    x_dlr[_tup].append(_x)

# Add Constraint limiting the number of possible employees of a specific role to schedule on a given day at a given location
for day in shifts: # for each day in pay period
    for location in allLocations.keys(): # for each clinic
        for role in roles: # for each role
            _tup = day, location, role
            shift_model += lpSum(x_dlr.get(_tup, [])) == maxnum_(*_tup), "Max employees for {} {} {}".format(day,location,role)

shift_model.solve()
print("Optimal employee schedule: ")
for shift_instance in listOfVariables:
    if x[shift_instance].value() == 1.0:
        print(x[shift_instance])

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章