Python 如何添加一个约束,使工厂在纸浆中的某段时间内保持打开或关闭?

Python 如何添加一个约束,使工厂在纸浆中的某段时间内保持打开或关闭?,python,optimization,linear-programming,pulp,economics,Python,Optimization,Linear Programming,Pulp,Economics,我对线性规划非常陌生,正在研究一个最小化工厂生产成本的例子。本示例中包括了打开和关闭工厂的功能 我的问题是,如何添加额外的约束条件,即如果工厂关闭,则需要关闭3个月,如果工厂重新打开,则需要继续运行4个月 代码: 将熊猫作为pd导入 进口纸浆 factories=pd.DataFrame.from_csv('csv/factory_variables.csv',index_col=['Month','factory'])) demand=pd.DataFrame.from_csv('csv/mo

我对线性规划非常陌生,正在研究一个最小化工厂生产成本的例子。本示例中包括了打开和关闭工厂的功能

我的问题是,如何添加额外的约束条件,即如果工厂关闭,则需要关闭3个月,如果工厂重新打开,则需要继续运行4个月

代码:

将熊猫作为pd导入
进口纸浆
factories=pd.DataFrame.from_csv('csv/factory_variables.csv',index_col=['Month','factory']))
demand=pd.DataFrame.from_csv('csv/monthly_demand.csv',index_col=['Month']))
#生产
生产=纸浆.LpVariable.dicts(“生产”,
((月,工厂)为月,工厂中的工厂。索引),
下限=0,
cat='Integer')
#出厂状态,开或关
工厂状态=纸浆.LpVariable.dicts(“工厂状态”,
((月,工厂)为月,工厂中的工厂。索引),
cat='Binary')
#工厂开关打开或关闭
switch_on=pill.LpVariable.dicts(“switch_on”,
((月,工厂)为月,工厂中的工厂。索引),
cat='Binary')
#实例化模型
模型=纸浆.LpProblem(“成本最小化调度问题”,纸浆.LpMinimize)
#选择工厂A或B上的索引
factory_A_index=[tpl for tpl in factories.index如果tpl[1]=='A']
factory_B_index=[tpl for tpl in factories.index如果tpl[1]=='B']
#定义目标函数
模型+=纸浆.lpSum(
[生产[m,f]*工厂。工厂中m,f的loc[(m,f),“可变成本”]指数]
+[工厂状态[m,f]*工厂。工厂中m,f的loc[(m,f),“固定成本”]索引]
+[打开[m,f]*20000用于工厂索引中的m,f]
+[打开[m,f]*400000用于工厂索引中的m,f]
)
#任何月份的产量必须等于需求量
月份=需求指数
月份中的月份:
模型+=生产[(月,'A')]+生产[(月,'B')]==需求.loc[月,'demand']
#任何月份的产量必须介于最低和最高产能之间,或为零。
月份,工厂中的工厂。索引:
最低产量=工厂。loc[(月,工厂),“最低产能”]
最大产量=工厂。loc[(月,工厂),“最大产能”]
型号+=生产[(月,工厂)]>=最小生产*工厂状态[月,工厂]
型号+=生产[(月,工厂)]=工厂状态[月,工厂]-工厂状态[月-1,工厂]

model+=switch_on[月,工厂]要对第一组约束进行建模,您需要一个
switch_off
变量,定义类似于
switch_on
。之所以有必要这样做,是因为当
开关打开
变量时,没有办法不知道是否没有开关或关闭(我们当然可以检查出厂状态,但没有一个变量表示该变化)

然后,您可以执行以下操作:

model += factory_status[month, factory] + factory_status[month+1, factory] + \
factory_status[month+2, factory] <= 3 * (1 - switch_off[month, factory])
不需要附加边界条件

这些约束是正确的,它们的优点是只有两个约束(+边界条件)。然而,它们并不紧密,因为模型的线性规划(LP)松弛可能远离最优解。可获得具有更高目标的LP松弛的版本如下:

factory_status[month + u, factory] <= 1 - switch_off[month, factory], for u in {0, 1, 2}, 

factory_status[month + u, factory] >= switch_on[month, factory], for u in {0, 1, 2, 3}
factory_status[month+u,factory]=为{0,1,2,3}中的u打开[month,factory]
这对于您的示例可能更好。对于非常大的模型,可能会首选第一个版本,但它确实是问题(可能是实例)特定的。在我看来,最好的选择是将约束的第二个版本放在一个惰性池中,并将它们的管理委托给解算器,这通常更有效。并不是所有的解算器和接口都允许这样做,但在困难的模型中确实会有所不同

我希望这有帮助

我认为“离开3个月”和“继续4个月”并不完全是这个意思,而是“离开至少3个月”和“继续至少4个月”

这是一个没有额外变量的替代公式:


  • 禁止模式101:
    x[t,i]-x[t+1,i]+x[t+2,i]感谢您的帮助和对我的问题的快速回答!我从未考虑过使用
    关闭
    变量。我的研究还没有扩展到LP松弛或在惰性池中放置约束的主题。你能解释一下还是推荐一些阅读材料?我想我会首先尝试第一种选择,因为我了解那里发生了什么——我会不断更新我的进度。干杯在评论中解释整数规划有些困难。简而言之,在实践中,它比线性规划更难求解,这有很好的理论原因。是开始阅读更多细节的好地方。祝你好运,尽情享受!谢谢你的回答,欧文!是的,你是对的,这正是我的意思。有意义且易于实现,所以我也会尝试一下。我的问题的答案看起来相对容易,因为我已经看到了一些解决方案。干杯,伙计
    
    factory_status[month, factory] + factory_status[month + 1, factory]+ \ 
    factory_status[month + 2, factory] + factory_status[month + 3, factory] >= 
    4 * switch_on[month, factory]
    
    factory_status[month + u, factory] <= 1 - switch_off[month, factory], for u in {0, 1, 2}, 
    
    factory_status[month + u, factory] >= switch_on[month, factory], for u in {0, 1, 2, 3}