带运输量上下限的运输问题求解及代码适配咨询
带运输量上下限的运输问题Pulp实现方案
要给现有的运输模型添加每个供应商-消费者对的运输量上下限约束,只需两步:定义上下限数据,再为每个运输变量添加边界约束。
实现步骤
- 定义运输量上下限数据
把你提供的上下限表格转换成和现有suppliers、consumers索引匹配的DataFrame:
# 运输量下界(4×5) 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), ) ).stack() flow_lower.name = 'lower_bound' # 运输量上界(4×5) 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), ) ).stack() flow_upper.name = 'upper_bound'
- 添加上下限约束
遍历每个供应商-消费者对,为flow变量添加上下限约束:
# 添加运输量下界约束 for (supplier, consumer), lower in flow_lower.items(): prob.addConstraint( name=f'flow_lower_s{supplier}_c{consumer}', constraint=flow[(supplier, consumer)] >= lower ) # 添加运输量上界约束 for (supplier, consumer), upper in flow_upper.items(): prob.addConstraint( name=f'flow_upper_s{supplier}_c{consumer}', constraint=flow[(supplier, consumer)] <= upper )
修改后的完整代码
import pandas as pd import pulp truck_capacity = 6 suppliers = pd.RangeIndex(name='supplier', stop=4) consumers = pd.RangeIndex(name='consumer', stop=5) supply = pd.Series( name='supply', index=suppliers, data=(17, 8, 10, 9), ) demand = pd.Series( name='demand', index=consumers, data=(6, 15, 7, 8, 8), ) price_per_tonne = pd.DataFrame( index=suppliers, columns=consumers, data=( (10, 8, 5, 9, 16), ( 4, 3, 4, 11, 12), ( 5, 10, 29, 7, 6), ( 9, 2, 4, 1, 3), ), ).stack() price_per_tonne.name = 'price' # 新增:定义运输量上下限 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), ) ).stack() flow_lower.name = 'lower_bound' 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), ) ).stack() flow_upper.name = 'upper_bound' flow = pd.DataFrame( index=suppliers, columns=consumers, data=pulp.LpVariable.matrix( name='flow_s%d_c%d', cat=pulp.LpContinuous, lowBound=0, indices=(suppliers, consumers), ), ).stack() flow.name = 'flow' trucks = pd.DataFrame( index=suppliers, columns=consumers, data=pulp.LpVariable.matrix( name='trucks_s%d_c%d', cat=pulp.LpInteger, lowBound=0, indices=(suppliers, consumers), ) ).stack() trucks.name = 'trucks' price = truck_capacity * pulp.lpDot(price_per_tonne, trucks) prob = pulp.LpProblem(name='transportation', sense=pulp.LpMinimize) prob.setObjective(price) # The flow must not exceed the supply for supplier, group in flow.groupby('supplier'): prob.addConstraint( name=f'flow_supply_s{supplier}', constraint=pulp.lpSum(group) <= supply[supplier], ) # The flow must exactly meet the demand for consumer, group in flow.groupby('consumer'): prob.addConstraint( name=f'flow_demand_c{consumer}', constraint=pulp.lpSum(group) == demand[consumer], ) # The capacity must be able to carry the flow for (supplier, consumer), truck_flow in flow.items(): prob.addConstraint( name=f'capacity_s{supplier}_c{consumer}', constraint=truck_flow <= trucks[(supplier, consumer)] * truck_capacity ) # 新增:添加运输量上下限约束 for (supplier, consumer), lower in flow_lower.items(): prob.addConstraint( name=f'flow_lower_s{supplier}_c{consumer}', constraint=flow[(supplier, consumer)] >= lower ) for (supplier, consumer), upper in flow_upper.items(): prob.addConstraint( name=f'flow_upper_s{supplier}_c{consumer}', constraint=flow[(supplier, consumer)] <= upper ) print(prob) prob.solve() assert prob.status == pulp.LpStatusOptimal print(f'Total price: ${price.value():.2f}') print() print('Flow:') flow = flow.apply(pulp.value).unstack(level='consumer') print(flow) print() print('Trucks:') trucks = trucks.apply(pulp.value).unstack(level='consumer') print(trucks) print() print('Prices:') print(trucks * truck_capacity * price_per_tonne.unstack(level='consumer'))
注意事项
- 确保上下限约束和现有供需约束不冲突:比如所有供应商的下界总和不能超过总需求,上界总和不能低于总需求,否则模型会返回无解状态。
- 原代码中
flow变量的lowBound=0可以保留,因为我们添加的下界可能比0大,约束会自动覆盖这个默认值。
内容的提问来源于stack exchange,提问作者Pavel Jefimovich
相关产品推荐
相关产品推荐

