

新闻资讯
技术学院本文详解如何使用 pulp 库为「 supervisor–consultant 多对一分配」问题建模,重点解决小时容量约束、一对一/一对多逻辑、以及基于 seniority 的资格筛选等关键约束的正确表达方式。
在运筹优化实践中,多对一(如多位顾问由一位主管指导)的分配问题常需兼顾资源容量、个体需求与资质匹配。PuLP 作为 Python 中轻量但功能完备的线性规划建模工具,能清晰表达此类混合整数规划(MIP)模型。但初学者易在约束构造上出错——例如混淆变量索引、误用求和维度,或未能将“软性”业务规则(如 seniority ≥ consultant_sen)转化为线性约
束。
以下是一个结构清晰、可直接运行的完整实现,涵盖四大核心约束:
相比 dicts,matrix 更直观地映射二维关系(supervisor × consultant),便于后续按行/列操作:
pairs = pulp.LpVariable.matrix(
name='pairs',
cat=pulp.LpBinary,
indices=(supervisors, consultants)
)每个 pairs[i][j] 表示 supervisor i 是否分配给 consultant j(1=是,0=否)。
使用 lpDot 实现矩阵点积,简洁且高效:
prob.setObjective(pulp.lpDot(costs, pairs))
其中 costs[i][j] 是 supervisor i 与 consultant j 的适配得分(如共同语言数、经验匹配度等)。
for i in supervisors:
prob.addConstraint(pulp.lpSum(pairs[i]) >= 1, name=f'sup{i}_mincount')for j in consultants:
prob.addConstraint(
pulp.lpSum(pairs[i][j] for i in supervisors) == 1,
name=f'con{j}_assigned'
)错误写法常试图动态追踪“剩余小时”,但线性规划中应静态建模总占用量 ≤ 可用量。
每位顾问 j 占用 supervisor i 的小时数 = consultant_h[j](若分配)或 0(若未分配)。因此,supervisor i 的总占用小时为:
$$\sum_{j} \text{pairs}[i][j] \times \text{consultant_h}[j] \leq \text{supervisor_h}[i]$$
代码实现:
for i in supervisors:
prob.addConstraint(
pulp.lpDot(pairs[i], consultant_h) <= supervisor_h[i],
name=f'sup{i}_hourmax'
)该约束本质是:为顾问 j 分配的主管,其 seniority 必须 ≥ consultant_sen[j]。
等价于:顾问 j 所有被选中的主管 seniority 的加权平均 ≥ consultant_sen[j](因仅一个主管被选中,权重为 1)。
即:
$$\sum_{i} \text{pairs}[i][j] \times \text{supervisor_sen}[i] \geq \text{consultant_sen}[j]$$
代码:
for j in consultants:
prob.addConstraint(
pulp.lpDot([pairs[i][j] for i in supervisors], supervisor_sen)
>= consultant_sen[j],
name=f'con{j}_sen'
)通过以上结构化建模,你不仅能准确表达复杂的业务规则,还能获得可解释、可维护、可扩展的优化模型。实际应用中,还可进一步引入优先级权重、公平性约束(如负载均衡)、或分层优化目标,而本框架已为其奠定坚实基础。