
本文详解如何在 PuLP 框架下为经典运输问题引入每条供需路径的流量下界与上界限制,通过 bounds() 方法动态设置变量范围,并确保模型仍满足供需平衡与车辆载重约束。
本文详解如何在 pulp 框架下为经典运输问题引入**每条供需路径的流量下界与上界限制**,通过 `bounds()` 方法动态设置变量范围,并确保模型仍满足供需平衡与车辆载重约束。
在标准运输问题中,通常仅考虑总供给与总需求的平衡,以及单位运输成本最小化。但实际物流场景常存在更精细的运营约束——例如某条运输线路因道路管制或合同约定,必须至少运送 1 吨(下界),且不得超过 9 吨(上界)。这类路径级流量上下界(transit limitations) 无法通过全局供需约束表达,需直接作用于决策变量 flow_s{i}_c{j}。
PuLP 提供了简洁高效的方式:调用变量的 .bounds(low, up) 方法。关键在于——该方法必须在变量创建后、模型求解前执行,且对每个路径变量单独设置。原代码中 flow 变量初始化时未指定 lowBound 和 upBound,因此需额外加载上下界矩阵,并遍历所有 (supplier, consumer) 组合进行绑定:
# 定义下界与上界矩阵(与 suppliers × consumers 维度一致)
flow_lower = pd.DataFrame(
index=suppliers, columns=consumers,
data=[[1, 2, 1, 2, 1],
[2, 1, 1, 1, 3],
[0, 1, 2, 1, 1],
[2, 1, 3, 1, 2]]
)
flow_upper = pd.DataFrame(
index=suppliers, columns=consumers,
data=[[9, 8, 6, 10, 5],
[7, 15, 4, 6, 9],
[5, 6, 6, 5, 10],
[8, 5, 7, 4, 8]]
)
# 为每个 flow 变量设置上下界
for (s, c), var in flow.items():
var.bounds(
low=flow_lower.loc[s, c],
up=flow_upper.loc[s, c]
)⚠️ 重要注意事项:
- bounds() 是 PuLP 变量的原地修改方法,不可链式调用;它会覆盖初始化时的 lowBound/upBound 参数。
- 下界值可为 0(表示允许不运输),但若某路径下界 > 0,则该路径强制启用,可能影响可行性——务必保证总下界和 ≤ 总供给 & ≥ 总需求,否则 prob.solve() 将返回 Infeasible。
- 上界不应小于对应下界,否则约束矛盾,求解器报错。
完成边界设置后,其余建模逻辑保持不变:
✅ 供给约束:∑_c flow[s,c] ≤ supply[s]
✅ 需求约束:∑_s flow[s,c] == demand[c]
✅ 载具容量耦合:flow[s,c] ≤ trucks[s,c] × truck_capacity
最终求解结果中,flow 矩阵每一项均严格落在 [lower, upper] 区间内(如输出所示:flow[0,0] = 2.0 ∈ [1,9],flow[1,4] = 3.0 ∈ [3,9]),验证了约束生效。
总结而言,为运输问题添加路径级流量限制,核心是将业务规则转化为变量边界,而非新增约束方程——这不仅提升模型稀疏性与求解效率,也更符合线性规划的标准建模范式。当面对多层级物流网络(含中转仓、时间窗、多车型)时,此类变量级精细化控制将成为构建高保真优化模型的基础能力。

















