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

2024-05-08 14:11:41 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试使用纸浆库为一家诊所构建一个员工调度系统。但是,每当我尝试添加约束时,我总是会收到标题中提到的警告,如下面的代码所示。我使用了在纸浆文档中找到的this case study中的代码作为构建LP问题的参考

问题的简要总结:诊所有3个地点,我正在构建一个系统,可以构建一个最优解决方案,在这3个地点安排员工名单。我们没有安排/计算时间,而是按天安排(例如,Jim在周一、周二和周五工作)。每个诊所对每天所需的特定专业(我在下面的代码中称之为角色)的员工数量都有要求。目前,我正试图添加一个限制条件,限制特定角色的员工数量,这些员工可以安排在某一天的特定位置

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

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_模型是元组(e,d,l,r)乘以计算系数的总和。元组是一个“shift_实例”,其中员工e在d天在角色r的位置l工作。这些元组是问题的变量,可以是0或1,其中1表示该shift_实例将是计划的一部分。计算出的系数基本上是员工的偏好(例如,如果Jimmy John周二没有空,那么(‘Jimmy John’、‘周二’、‘诊所A’、‘儿科医生’)的系数是负数,而如果他有空,则是正数)因此,我们的目标是最大化这个模型。哦,x是一个字典,它将shift_实例映射到LpVariable,而listOfVariables是所有可能的元组/shift_实例的列表

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


Tags: thetoinstanceinforshift员工employee
1条回答
网友
1楼 · 发布于 2024-05-08 14:11:41

你好

您不应该在pulp中使用python的标准sum函数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])

相关问题 更多 >