Pyomo,如何编写一个约束,以确保Pyomo设备的最大启动时间?



我正在研究一个优化问题,其中有一个可移动的设备,可以安排在其他时间,而不是其初始时间表。问题是这个设备有一个特定的占空比,我的意思是,如果它是开的,它必须至少开T_ON小时,不能超过T_ON小时。

有一个二进制变量,I(t)表示设备的ON(1)或OFF(0)状态。在Pyomo中,据我所知,我们不能在变量上定义if语句,所以我非常困惑于如何在Pyomo中公式化这个问题。我也试着做一个图形版本的我正在寻找下图。

如果有人能给我出主意,告诉我如何表述这个问题,我将不胜感激。

干杯!:)

请看这里的图表!:)

如果"语句在Pyomo中工作,我会这样写:


model.Gen  = Set(initialize=RangeSet(0,End_uses -1), doc='set of enduses') #index of end uses
model.T  = Set(initialize=RangeSet(0,50-1), doc='Time') #index of data samples
model.taw = SetOf(model.T) # references whatever is in T

#Yes/No of each item (binary variable) --> include or exclude an item
model.I_test=Var(model.Gen,model.T,within=Binary)
#Min Up time
def MinUp(model,g,t):
if t > 0:
if model.I_test[g,t]-model.I_test[g,t-1]>0:
return sum(model.I_test[g,t2] for t2 in model.taw if t2>=t and t2<=t+T_on[g]) >= T_on[g]*(model.I_test[g,t]-model.I_test[g,t-1])
else:
return Constraint.Skip
model.cons5 = Constraint(model.Gen,model.T,rule=MinUp)

我正在寻找一个帮助制定问题,甚至一个类似的代码块,可以帮助我解决这个问题。

您缺少的部分是用于跟踪机器在中启动的周期的附加变量。这将允许使用一些整数运算来绘制其他几种类型的约束。下面是几个例子。

从你的问题来看,哪一个对你最有用并不是很清楚。你似乎暗示了min_runtime==max_runtime,然后你提到了占空比,但没有定义它。

如果您的规范简化为正好是n小时开,然后是最少的n小时关,您可以在下面重写这些类型的约束之一,以便开始后的n周期为"开";然后n+12n周期关闭,并删除其他约束。

代码:

# cycling machine example
import pyomo.environ as pyo
# machine characteristics
min_runtime = 2        # minimum number of periods to run after startup
min_reset_time = 3     # off periods after being turned off
duty_cycle = (4, 8)    # 50% duty cycle evaluated over 8 periods "4 of 8"
time_periods = 12
demand = 7 # periods of 'runtime' from the machine
m = pyo.ConcreteModel()
# SETS
m.T = pyo.Set(initialize=range(time_periods))
# VARS
m.start   = pyo.Var(m.T, domain=pyo.Binary, doc='start machine')
m.running = pyo.Var(m.T, domain=pyo.Binary, doc='machine running')
# OBJ
m.obj = pyo.Objective(expr=sum(m.running[t] for t in m.T))   # minimze the runtime
# CONSTRAINTS
# satisfy the demand
m.satisfy_demand = pyo.Constraint(expr=sum(m.running[t] for t in m.T) >= demand)
@m.Constraint(m.T)
def link_running(m, t):
"""machine can only be running if it was running in prior period or started in this one"""
if t == m.T.first():
return pyo.Constraint.Skip
return m.running[t] <= m.running[t-1] + m.start[t]
@m.Constraint(m.T)
def min_runtime(m, t):
"""force the minimum runtime after a start event"""
# make a subset of the time periods of interest...
next_time_periods = {t + offset for offset in range(min_runtime) if t + offset < time_periods}
return sum(m.running[tt] for tt in next_time_periods) >= len(next_time_periods) * m.start[t]
@m.Constraint(m.T)
def honor_reset_time(m, t):
if t == m.T.first():
return pyo.Constraint.Skip
previous_time_periods = {t - offset for offset in range(1, min_reset_time + 1) if t - offset >=0}
return len(previous_time_periods) * m.start[t] <= sum(1-m.running[tt] for tt in previous_time_periods)
@m.Constraint(m.T)
def duty_cycle_limit(m, t):
""" evaluate all possible duty cycles and impose limit """
if t + duty_cycle[1] > time_periods:
return pyo.Constraint.Skip
duty_cycle_periods = list(range(t, t + duty_cycle[1]))
return sum(m.running[tt] for tt in duty_cycle_periods) <= duty_cycle[0]

m.pprint()
solver = pyo.SolverFactory('glpk')
soln = solver.solve(m)
print(soln)
m.running.display()
输出(部分):

Solver: 
- Status: ok
Termination condition: optimal
Statistics: 
Branch and bound: 
Number of bounded subproblems: 1
Number of created subproblems: 1
Error rc: 0
Time: 0.0057790279388427734
Solution: 
- number of solutions: 0
number of solutions displayed: 0
running : machine running
Size=12, Index=T
Key : Lower : Value : Upper : Fixed : Stale : Domain
0 :     0 :   1.0 :     1 : False : False : Binary
1 :     0 :   1.0 :     1 : False : False : Binary
2 :     0 :   1.0 :     1 : False : False : Binary
3 :     0 :   1.0 :     1 : False : False : Binary
4 :     0 :   0.0 :     1 : False : False : Binary
5 :     0 :   0.0 :     1 : False : False : Binary
6 :     0 :   0.0 :     1 : False : False : Binary
7 :     0 :   0.0 :     1 : False : False : Binary
8 :     0 :   1.0 :     1 : False : False : Binary
9 :     0 :   1.0 :     1 : False : False : Binary
10 :     0 :   1.0 :     1 : False : False : Binary
11 :     0 :   0.0 :     1 : False : False : Binary

最新更新