我正在研究一个优化问题,其中有一个可移动的设备,可以安排在其他时间,而不是其初始时间表。问题是这个设备有一个特定的占空比,我的意思是,如果它是开的,它必须至少开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+1
到2n
周期关闭,并删除其他约束。
代码:
# 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