在pyomo Python中优化批处理 - 如何为每个批设置固定的操作时间?

问题描述 投票:0回答:1

我想在 Python 中使用 pyomo 优化工业批处理过程。目标函数是最小化系统成本。在我的简化示例中,我使用随机值指定生产成本。批处理的独特之处在于,一旦系统打开,它必须运行四个或四个时间步的倍数(连续多个批次)。 down_time 不必是四的倍数。 (仅在简化问题中,实际上停机时间不应超过两个或至少 20 个时间步)。

我尝试定义一个阻止规则,这应该确保运行时%4,但它不起作用。仍然出现运行时间 > 4。如果我将约束从 >= 4 切换到 == 4(见下文),则优化根本不起作用。

import pyomo.environ as pyo
import matplotlib.pyplot as plt

# Define the model
model = pyo.ConcreteModel()

# 1. Define the model, sets, and parameters.
T = 56  # number of timesteps
production_goal = 16
model.timesteps = pyo.RangeSet(1, T)

# Assuming a simple production cost function
import random 
production_cost = [random.randint(0, 100) for _ in range(T)]
# Create a sin wave for the production cost
import numpy as np
production_cost = (np.sin(np.linspace(0, 8*np.pi, T))+1)*50

# 2. Define the decision variables.
model.x = pyo.Var(model.timesteps, within=pyo.Binary)  # production decision
model.y = pyo.Var(model.timesteps, within=pyo.Binary)  # plant status
model.batch_over = pyo.Var(model.timesteps, within=pyo.Binary)  # batch over decision
# 3. Define the objective function.
def obj_rule(model):
    return sum(production_cost[t-1] * model.x[t] + model.batch_over[t] for t in model.timesteps)
model.obj = pyo.Objective(rule=obj_rule, sense=pyo.minimize)

# 4. Define the constraints.
# Total production constraint
def total_production_rule(model):
    return sum(model.x[t] for t in model.timesteps) == production_goal
model.total_production_con = pyo.Constraint(rule=total_production_rule)

# Production is only possible if plant is on
def production_on_rule(model, t):
    return model.x[t] == model.y[t]
model.production_on_con = pyo.Constraint(model.timesteps, rule=production_on_rule)

# Plant has to work in blocks of 4 hours
def block_rule(model, t):
    if t>1 and t < T-2:
        return model.y[t] + model.y[t+1] + model.y[t+2] + model.y[t+3] >= 4 * (model.y[t]-model.y[t-1])
    return pyo.Constraint.Skip
model.block_con = pyo.Constraint(model.timesteps, rule=block_rule)


# 5. Solve the model using Gurobi.
solver = pyo.SolverFactory('gurobi')
results = solver.solve(model)
python optimization batch-processing linear-programming pyomo
1个回答
0
投票

我要考虑的第一件事就是让你的时间周期是现在的 4 倍,然后运行 4 个周期的整个问题就会消失,但似乎你还有其他限制来激发更小的时间步长。这导致一些适度复杂的逻辑来控制工厂的运行(正如您所发现的),并且传达的约束开始快速增长,但只要您没有建模太大的时间跨度,它应该是可行的.

我不确定你的模型中的

x
y
到底是什么,但你在约束中将它们设置为彼此相等,所以你实际上只有 1 个变量。使用更清晰的名称!

这是伪代码中的框架思想:

有一个二进制变量表示植物何时启动,另一个表示植物是否运行。我已经发布了几个与此类似的其他答案,因此您可以在我的一些答案中搜索“跑步”,看看您会得到什么。喜欢这个

所以:

running[t] ∈ {0, 1}
start[t] ∈ {0, 1}

为了在任何时期运行,您需要在当前或之前的 3 个时期开始......听起来像是一个限制!只有在前 3 个周期或当前周期开始时,我们才能运行:

running[t] <= sum(start[tt] for tt in range(t-3, t+1) if tt > 0)

for all t

而且我们不能在运行时任意“启动”,所以我们需要在启动发生后限制启动。只有在前 3 个周期没有开始的情况下,我们才能开始:

start[t] <= 1 - sum(start[tt] for tt in range(t-3, t) if tt > 0)

for all t

然后你可以考虑关闭窗口。如果系统关闭(如

running[t-1] - running[t] ≥ 0
所示),那么我们有一个从
[t+2, t+20]
开始新启动的排除窗口。我想我们可以对其进行编码...

sum(start[tt] for tt in range(t+2, t+21)) <= 1 - (running[t-1] - running[t])

for all t ∈ {4, ...}

尝试重构并合并类似的东西。将模型保留为“小”,例如 9 个时间段,将其打印出来并手动验证您的约束以确保它们是正确的。如果您遇到困难,请评论回来。

© www.soinside.com 2019 - 2024. All rights reserved.