如何将条件约束应用于 Python Pulp 函数
How to apply conditional constraints to Python Pulp function
我正在 Python 中使用 Pulp 设置线性优化。我想对问题设置条件约束。
比如,我想最大化工厂的利润。对于 material 的成本,前 1000 件每件售价 5 美元,更多的每件售价 3 美元。例如,如果工厂订购 1100 件,则总成本将为 1000*5+100*3。我有一个 material 的列表:material_list
,materials 的基准字典:benchmark_dic={material_a: 1000, material_b:2000 ....}
,如果订单损失比基准的价格字典:price_A_dic,如果您订购的数量超过 benchark:price_B_dic,还有价格字典。
这是我的代码:
x=pulp.LpVariable.dicts('x',material_list,lowBound=0 , cat='Integer')
New_cost_dic=pd.Series(0,index=dat.index).to_dict()
for seg in material_list:
if x[seg]>benchmark_dic[seg]:
New_cost_dic[seg]=(x[seg]-benchmark_dic[seg])*price_b_dic[seg]+benchmark[seg]*price_A_dic[seg]
else:
New_cost_DIC[seg]=x[seg]*price_A_dic[seg]
我也有类似的销售额计算。我可以从中得到结果,但我不知道我是否做对了。当我得到每个 material 的单位数量的最终结果时,我尝试使用相同的计算来获得总成本和总销售额,但我得到的利润(总销售额 - 总成本)不等于我从 pulp.value(prob.objective) 获得的最大利润。
我应该如何为这个条件约束或条件函数编码。
我认为您实施的条件约束不会起作用。
对于像这样的条件约束,您需要重新表述问题以使用指示变量,这些变量是跟踪您感兴趣的条件(真或假)的二元变量。
对于你的具体问题,我会建议如下,有一组变量,比如 x1[seg]
每个 material 跟踪购买到基准的数量,然后是另一个一组变量,比如 x2[seg]
跟踪高于基准的购买数量,最后是一组二进制变量,比如 z[seg]
跟踪我们是否达到价格断点。
每个成本项将是:
x1[seg]*price_A_dic[seg] + x2[seg]*price_B_dic[seg]
然后我们需要添加强制变量采用适当值的约束。我认为以下应该有效:
x1[seg] >= 0
x1[seg] >= benchmark_dic[seg] * z[seg]
x2[seg] >= 0
x2[seg] <= z[seg]*MAX_POSSIBLE_ORDER
其中 MAX_POSSIBLE_ORDER
是我们在购买数量方面永远不会超过的某个上限。您可以看到,为了让 z[seg]
具有价值 1
,我们首先必须以较高的价格订购 benchmark_dic[seg]
数量。同样,如果 z[seg]
值 1
.
,我们只能以较低的价格订购
可能有一种 neater/more 有效的方法可以做到这一点,但上面的方法应该有效。
我认为上面的答案需要修改第二个约束:
x1[seg] >= 0
x1[seg] <= benchmark_dic[seg]
x2[seg] >= 0
x2[seg] <= z[seg]*MAX_POSSIBLE_ORDER
否则如果 z[seg]
总是 0
无论 x1[seg]
的值如何。
例如,如果 benchmark_disc[1]
是 1000
并且 x1[1]
可以是 1500
并且 z[1]
是 0
并且仍然满足约束:
1500 >= 1000 * 0
我正在 Python 中使用 Pulp 设置线性优化。我想对问题设置条件约束。
比如,我想最大化工厂的利润。对于 material 的成本,前 1000 件每件售价 5 美元,更多的每件售价 3 美元。例如,如果工厂订购 1100 件,则总成本将为 1000*5+100*3。我有一个 material 的列表:material_list
,materials 的基准字典:benchmark_dic={material_a: 1000, material_b:2000 ....}
,如果订单损失比基准的价格字典:price_A_dic,如果您订购的数量超过 benchark:price_B_dic,还有价格字典。
这是我的代码:
x=pulp.LpVariable.dicts('x',material_list,lowBound=0 , cat='Integer')
New_cost_dic=pd.Series(0,index=dat.index).to_dict()
for seg in material_list:
if x[seg]>benchmark_dic[seg]:
New_cost_dic[seg]=(x[seg]-benchmark_dic[seg])*price_b_dic[seg]+benchmark[seg]*price_A_dic[seg]
else:
New_cost_DIC[seg]=x[seg]*price_A_dic[seg]
我也有类似的销售额计算。我可以从中得到结果,但我不知道我是否做对了。当我得到每个 material 的单位数量的最终结果时,我尝试使用相同的计算来获得总成本和总销售额,但我得到的利润(总销售额 - 总成本)不等于我从 pulp.value(prob.objective) 获得的最大利润。
我应该如何为这个条件约束或条件函数编码。
我认为您实施的条件约束不会起作用。
对于像这样的条件约束,您需要重新表述问题以使用指示变量,这些变量是跟踪您感兴趣的条件(真或假)的二元变量。
对于你的具体问题,我会建议如下,有一组变量,比如 x1[seg]
每个 material 跟踪购买到基准的数量,然后是另一个一组变量,比如 x2[seg]
跟踪高于基准的购买数量,最后是一组二进制变量,比如 z[seg]
跟踪我们是否达到价格断点。
每个成本项将是:
x1[seg]*price_A_dic[seg] + x2[seg]*price_B_dic[seg]
然后我们需要添加强制变量采用适当值的约束。我认为以下应该有效:
x1[seg] >= 0
x1[seg] >= benchmark_dic[seg] * z[seg]
x2[seg] >= 0
x2[seg] <= z[seg]*MAX_POSSIBLE_ORDER
其中 MAX_POSSIBLE_ORDER
是我们在购买数量方面永远不会超过的某个上限。您可以看到,为了让 z[seg]
具有价值 1
,我们首先必须以较高的价格订购 benchmark_dic[seg]
数量。同样,如果 z[seg]
值 1
.
可能有一种 neater/more 有效的方法可以做到这一点,但上面的方法应该有效。
我认为上面的答案需要修改第二个约束:
x1[seg] >= 0
x1[seg] <= benchmark_dic[seg]
x2[seg] >= 0
x2[seg] <= z[seg]*MAX_POSSIBLE_ORDER
否则如果 z[seg]
总是 0
无论 x1[seg]
的值如何。
例如,如果 benchmark_disc[1]
是 1000
并且 x1[1]
可以是 1500
并且 z[1]
是 0
并且仍然满足约束:
1500 >= 1000 * 0