如何存储 pyomo 优化循环的最后一个值并将其用作下一个优化循环的初始化?
How to store last value from a pyomo optimization loop and use it as initialisation for the next optimization loop?
更新
忙于优化电池存储,我在尝试基于 36 小时循环优化模型时遇到问题,例如,运行 全年数据。
通过这样做,我重新初始化了在每个步骤中重要的变量,因此损害了模型。如何提取变量的最后一个值并将其用作下一次迭代的第一个值?这是一个简单的问题:
#creation of list to store last variable values:
df1=[]
df2=[]
df3=[]
# Loop
for i in range (0,3)
step = 36
first_model_hour = step * i
last_model_hour = (step * (i+1)) - 1
model = ConcreteModel()
model.T = Set(doc='hour of year',initialize=df.index.tolist())
model.A = Var(model.T, NonNegativeReals)
model.B = Var(model.T, NonNegativeReals)
model.C = Var(model.T, NonNegativeReals)
def constraints_x(model,t)
for t == 0
return model.C == 100
elif t == first_model_hour
return model.C[t] == model.A[from previous loop] + model.B[from previous loop] + model.C[from previous loop]
else
return model.C[t] == model.A[t-1]+model.B[t-1]+model.C[t-1]
model.constraint = Constraint(model.T, rule=constraint_x)
solver = SolverFactory('cbc')
solver.solve(model)
df1.append(model.S[last_model_hour])
df2.append(model.B[last_model_hour])
df3.append(model.C[last_model_hour])
是否可以从 pyomo 中检索变量的最后一个值以将其用于下一个循环的初始化,从而不会随着时间的推移失去电池的连续充电状态?
这是一个很长的 post,我认为您可以将其缩减为一个更小的示例。我认为您是在问 if/how 您可以根据某个已知值(在您的情况下是前面 运行 中的某些值)设置特定变量的值(在您的情况下是第一个索引变量)。
您可以通过简单地为变量赋值,然后“固定”该变量的值来做到这一点 运行,然后继续解决...
In [11]: import pyomo.environ as pyo
In [12]: model = pyo.ConcreteModel()
In [13]: model.S = pyo.Set(initialize=range(3))
In [14]: model.X = pyo.Var(model.S, domain=pyo.NonNegativeReals)
In [15]: model.X[0]=3.2
In [16]: model.X[0].fix()
In [17]: model.X.pprint()
X : Size=3, Index=S
Key : Lower : Value : Upper : Fixed : Stale : Domain
0 : 0 : 3.2 : None : True : False : NonNegativeReals
1 : 0 : None : None : False : True : NonNegativeReals
2 : 0 : None : None : False : True : NonNegativeReals
对您的模型的一些看法...解决一个超过 9000 个时间步长的优化模型有点过头了,即使您通过像您那样将其切碎来进行攻击也是如此。您可能会尝试一些其他的事情,例如将时间间隔增加到 4-6 小时,或者可能更多 real-world 以假设在某些感兴趣的时间段内,系统将 start/stop 大致相同状态(相同的电池状态)所以只需在特定季节或时间段内解决一个星期,您认为系统的性能会有所不同并说电池 starts/stops 为 80%...只是一些想法...
这是一个完整的模型,它实现了我认为你想要做的事情;这是从以前的迭代中继承一个值。这建立在之前的 answer/example.
之上
# rolling time horizon
import pyomo.environ as pyo
periods = 3
num_segments = 4
starting_value = 2.0
solver = pyo.SolverFactory('cbc')
for period in range(periods):
segments = list(range(period*num_segments, (period + 1) * num_segments)) # the time segments in this per
model = pyo.ConcreteModel()
model.S = pyo.Set(initialize=segments)
model.X = pyo.Var(model.S, domain=pyo.NonNegativeReals)
# assign the first value and fix it
model.X[model.S.first()] = starting_value
model.X[model.S.first()].fix()
# dummy constraint to constrain each value to 1 greater than previous.
def C1(model, s):
if s == model.S.first():
return pyo.Constraint.Skip
return model.X[s] <= model.X[s-1] + 1
model.C1 = pyo.Constraint(model.S, rule=C1)
# obj: maximize X
model.obj = pyo.Objective(expr=pyo.summation(model.X), sense=pyo.maximize)
# solve
result = solver.solve(model)
assert(result.Solver()['Termination condition'].value == 'optimal') # a little insurance
# print(result)
# model.display()
starting_value = pyo.value(model.X[model.S.last()]) + 1
# rolling printout of results...
print(f'From iteration {period}:')
model.X.display()
产量:
From iteration 0:
X : Size=4, Index=S
Key : Lower : Value : Upper : Fixed : Stale : Domain
0 : 0 : 2.0 : None : True : True : NonNegativeReals
1 : 0 : 3.0 : None : False : False : NonNegativeReals
2 : 0 : 4.0 : None : False : False : NonNegativeReals
3 : 0 : 5.0 : None : False : False : NonNegativeReals
From iteration 1:
X : Size=4, Index=S
Key : Lower : Value : Upper : Fixed : Stale : Domain
4 : 0 : 6.0 : None : True : True : NonNegativeReals
5 : 0 : 7.0 : None : False : False : NonNegativeReals
6 : 0 : 8.0 : None : False : False : NonNegativeReals
7 : 0 : 9.0 : None : False : False : NonNegativeReals
From iteration 2:
X : Size=4, Index=S
Key : Lower : Value : Upper : Fixed : Stale : Domain
8 : 0 : 10.0 : None : True : True : NonNegativeReals
9 : 0 : 11.0 : None : False : False : NonNegativeReals
10 : 0 : 12.0 : None : False : False : NonNegativeReals
11 : 0 : 13.0 : None : False : False : NonNegativeReals
更新
忙于优化电池存储,我在尝试基于 36 小时循环优化模型时遇到问题,例如,运行 全年数据。
通过这样做,我重新初始化了在每个步骤中重要的变量,因此损害了模型。如何提取变量的最后一个值并将其用作下一次迭代的第一个值?这是一个简单的问题:
#creation of list to store last variable values:
df1=[]
df2=[]
df3=[]
# Loop
for i in range (0,3)
step = 36
first_model_hour = step * i
last_model_hour = (step * (i+1)) - 1
model = ConcreteModel()
model.T = Set(doc='hour of year',initialize=df.index.tolist())
model.A = Var(model.T, NonNegativeReals)
model.B = Var(model.T, NonNegativeReals)
model.C = Var(model.T, NonNegativeReals)
def constraints_x(model,t)
for t == 0
return model.C == 100
elif t == first_model_hour
return model.C[t] == model.A[from previous loop] + model.B[from previous loop] + model.C[from previous loop]
else
return model.C[t] == model.A[t-1]+model.B[t-1]+model.C[t-1]
model.constraint = Constraint(model.T, rule=constraint_x)
solver = SolverFactory('cbc')
solver.solve(model)
df1.append(model.S[last_model_hour])
df2.append(model.B[last_model_hour])
df3.append(model.C[last_model_hour])
是否可以从 pyomo 中检索变量的最后一个值以将其用于下一个循环的初始化,从而不会随着时间的推移失去电池的连续充电状态?
这是一个很长的 post,我认为您可以将其缩减为一个更小的示例。我认为您是在问 if/how 您可以根据某个已知值(在您的情况下是前面 运行 中的某些值)设置特定变量的值(在您的情况下是第一个索引变量)。
您可以通过简单地为变量赋值,然后“固定”该变量的值来做到这一点 运行,然后继续解决...
In [11]: import pyomo.environ as pyo
In [12]: model = pyo.ConcreteModel()
In [13]: model.S = pyo.Set(initialize=range(3))
In [14]: model.X = pyo.Var(model.S, domain=pyo.NonNegativeReals)
In [15]: model.X[0]=3.2
In [16]: model.X[0].fix()
In [17]: model.X.pprint()
X : Size=3, Index=S
Key : Lower : Value : Upper : Fixed : Stale : Domain
0 : 0 : 3.2 : None : True : False : NonNegativeReals
1 : 0 : None : None : False : True : NonNegativeReals
2 : 0 : None : None : False : True : NonNegativeReals
对您的模型的一些看法...解决一个超过 9000 个时间步长的优化模型有点过头了,即使您通过像您那样将其切碎来进行攻击也是如此。您可能会尝试一些其他的事情,例如将时间间隔增加到 4-6 小时,或者可能更多 real-world 以假设在某些感兴趣的时间段内,系统将 start/stop 大致相同状态(相同的电池状态)所以只需在特定季节或时间段内解决一个星期,您认为系统的性能会有所不同并说电池 starts/stops 为 80%...只是一些想法...
这是一个完整的模型,它实现了我认为你想要做的事情;这是从以前的迭代中继承一个值。这建立在之前的 answer/example.
之上# rolling time horizon
import pyomo.environ as pyo
periods = 3
num_segments = 4
starting_value = 2.0
solver = pyo.SolverFactory('cbc')
for period in range(periods):
segments = list(range(period*num_segments, (period + 1) * num_segments)) # the time segments in this per
model = pyo.ConcreteModel()
model.S = pyo.Set(initialize=segments)
model.X = pyo.Var(model.S, domain=pyo.NonNegativeReals)
# assign the first value and fix it
model.X[model.S.first()] = starting_value
model.X[model.S.first()].fix()
# dummy constraint to constrain each value to 1 greater than previous.
def C1(model, s):
if s == model.S.first():
return pyo.Constraint.Skip
return model.X[s] <= model.X[s-1] + 1
model.C1 = pyo.Constraint(model.S, rule=C1)
# obj: maximize X
model.obj = pyo.Objective(expr=pyo.summation(model.X), sense=pyo.maximize)
# solve
result = solver.solve(model)
assert(result.Solver()['Termination condition'].value == 'optimal') # a little insurance
# print(result)
# model.display()
starting_value = pyo.value(model.X[model.S.last()]) + 1
# rolling printout of results...
print(f'From iteration {period}:')
model.X.display()
产量:
From iteration 0:
X : Size=4, Index=S
Key : Lower : Value : Upper : Fixed : Stale : Domain
0 : 0 : 2.0 : None : True : True : NonNegativeReals
1 : 0 : 3.0 : None : False : False : NonNegativeReals
2 : 0 : 4.0 : None : False : False : NonNegativeReals
3 : 0 : 5.0 : None : False : False : NonNegativeReals
From iteration 1:
X : Size=4, Index=S
Key : Lower : Value : Upper : Fixed : Stale : Domain
4 : 0 : 6.0 : None : True : True : NonNegativeReals
5 : 0 : 7.0 : None : False : False : NonNegativeReals
6 : 0 : 8.0 : None : False : False : NonNegativeReals
7 : 0 : 9.0 : None : False : False : NonNegativeReals
From iteration 2:
X : Size=4, Index=S
Key : Lower : Value : Upper : Fixed : Stale : Domain
8 : 0 : 10.0 : None : True : True : NonNegativeReals
9 : 0 : 11.0 : None : False : False : NonNegativeReals
10 : 0 : 12.0 : None : False : False : NonNegativeReals
11 : 0 : 13.0 : None : False : False : NonNegativeReals