如何用Pulp定义导师-顾问多分配问题的约束条件?
导师-顾问匹配的线性规划约束修正方案
问题背景
我正在解决一个分配问题:导师可根据与顾问的共同语言数量分配给多个顾问(共同语言越多越优)。约束条件如下:
- 每位导师有固定督导可用工时:14、11、7或0小时
- 每位顾问有固定所需督导工时:6、3、2、1或0小时
- 导师可根据可用工时分配多个顾问(导师工时无需用尽,但顾问工时必须全覆盖)
- 被选中的导师资历需≥对应顾问的资历
现有代码问题
我已编写部分Pulp代码,但在定义工时约束和资历约束时遇到困难,以下是我的代码:
supervisor_h = ... # 每位导师的可用工时列表 consultant_h = ... # 每位顾问的所需工时列表 y = pulp.LpVariable.dicts("pairs", [(i,j) for i in supervisors for j in consultants], cat='Binary') prob = pulp.LpProblem("matching", pulp.LpMaximize) prob += pulp.lpSum([costs[i][m] * y[(i,j)] for i in supervisors for m, j in enumerate(consultants)]) # 每位导师至少分配1位顾问 for i in supervisors: prob += pulp.lpSum(y[(i,j)] for j in consultants) >= 1 # 每位顾问最多分配1位导师 for j in consultants: prob += pulp.lpSum(y[(i,j)] for i in supervisors) <= 1 # 工时约束:此处定义有问题 for n, i in enumerate(supervisors): prob += supervisor_h[n] - pulp.lpSum(qcee_h[m] for m, j in enumerate(consultants)) <= consultant_h[n] # 资历约束:同样无法正确定义
约束条件修正方案
1. 工时约束修正
当前工时约束逻辑完全错误,正确的约束应该是单个导师分配给所有顾问的总工时,不能超过该导师的可用工时。需要通过二进制变量y[(i,j)]关联导师与顾问,仅当y[(i,j)]=1时,才将顾问j的所需工时计入导师i的消耗。
修正后的代码:
# 遍历每个导师,约束其分配的总工时不超过可用工时 for i in supervisors: prob += pulp.lpSum(consultant_h[j] * y[(i,j)] for j in consultants) <= supervisor_h[i]
另外,若要求所有顾问必须被分配(覆盖全部工时需求),需将顾问的分配约束从<=1改为==1:
# 每位顾问必须被分配且仅分配一位导师 for j in consultants: prob += pulp.lpSum(y[(i,j)] for i in supervisors) == 1
2. 资历约束修正
首先需要将导师和顾问的资历转化为可比较的数值(比如数字越大资历越高),假设你有supervisor_seniority[i](导师i的资历值)和consultant_seniority[j](顾问j的资历值)两个数据结构。
约束逻辑为:若导师i分配给顾问j(即y[(i,j)]=1),则导师i的资历必须≥顾问j的资历,线性规划中可通过以下方式实现:
# 遍历所有导师-顾问对,添加资历约束 for i in supervisors: for j in consultants: # 当y[(i,j)]=1时,强制满足资历要求;y=0时约束自动成立 prob += supervisor_seniority[i] >= consultant_seniority[j] * y[(i,j)]
如果资历是字符串类型(如"初级"/"中级"/"高级"),需先映射为数值:
seniority_map = {"初级": 1, "中级": 2, "高级": 3} # 假设supervisors_seniority_list是导师资历字符串列表,consultants同理 supervisor_seniority = {i: seniority_map[val] for i, val in enumerate(supervisors_seniority_list)} consultant_seniority = {j: seniority_map[val] for j, val in enumerate(consultants_seniority_list)}
目标函数修正
原目标函数的索引对应有误,需确保costs[i][j]直接对应导师i与顾问j的共同语言数量:
# 最大化所有匹配对的共同语言总数 prob += pulp.lpSum([costs[i][j] * y[(i,j)] for i in supervisors for j in consultants])
内容的提问来源于stack exchange,提问作者Andrea
相关产品推荐
相关产品推荐

