我正在尝试使用 Gekko 中的优化程序对电池充电/放电过程进行建模。我在模型中使用了以下能量平衡方程:
可再生电力[t] - (充电[t] + 剩余[t])+(放电[t] + 未满足[t])= 需求[t]
充电/放电状态 (SOC) 通过以下公式更新:
SOC[t]=SOC[t-1]+充电[t]-放电[t]
我在 Gekko 中制定了上述方程,但在放电阶段遇到了问题。例如,我没有收到下图所示数据集的第二行(图中的黄色部分)的解决方案。我预计 SOC[第二行]=196400,但我没有在 Gekko 模型中收到解决方案。对于这个问题,我感谢您的建议。
from gekko import GEKKO
import sys
Battery_capacity=589200 #kW-h
Battery_Initial_capacity=589200
max_discharge=Battery_capacity/3
max_charge=Battery_capacity
Big_M=1000000000000
epsilon=sys.float_info.epsilon
m = GEKKO(remote=False)
m.solver_options = ['minlp_gap_tol 1.0e-2',\
'minlp_maximum_iterations 10000',\
'minlp_max_iter_with_int_sol 500',\
'minlp_branch_method 1',\
'minlp_integer_tol 1e-100', \
'minlp_integer_leaves 2']
Demand_total=[5629940,5327262,4669939]
RE_total=[5204098,4410247,3694715]
Price_total=[15,17,17]
row=1
finish=0
counter=0
for r in range(3):
start=finish
finish=(r+1)*row
Demand = [Demand_total[r]]
RE = [RE_total[r]]
Price = [Price_total[r]]
# Objective function
c = [None] * row
for t in range(row):
c[t] = (Demand[t] * Price[t])
B_ch_over = [m.Var(lb=0) for t in range(row)]
B_disch_over = [m.Var(lb=0) for t in range(row)]
B_ch = [m.Var(lb=0) for t in range(row)]
B_disch = [m.Var(lb=0) for t in range(row)]
Unmet = [m.Var(lb=0) for t in range(row)]
Surplus = [m.Var(lb=0) for t in range(row)]
B_SOC = [m.Var() for t in range(row)]
if r==0:
starting_point = 0
Last_BOS=Battery_Initial_capacity
m.Equation(B_SOC[0]==Last_BOS) # initial charge at start
else:
m.Equation(B_SOC[0] == Last_BOS[0]) # initial charge at start
for t in range(starting_point,row):
m.Equation(RE[t] - B_ch_over[t] + B_disch_over[t] == Demand[t])
m.Equation(B_ch_over[t] * B_disch_over[t] <= 0)
B_ch[t] = m.if3(max_charge - m.if3(B_ch_over[t] - (Battery_capacity - B_SOC[t - 1]), B_ch_over[t],Battery_capacity - B_SOC[t - 1]), max_charge,m.if3(B_ch_over[t] - (Battery_capacity - B_SOC[t - 1]), B_ch_over[t],Battery_capacity - B_SOC[t - 1]))
B_disch[t]=m.if3(max_discharge-m.if3(B_disch_over[t]-B_SOC[t-1],B_disch_over[t],B_SOC[t-1]),max_discharge,m.if3(B_disch_over[t]-B_SOC[t-1],B_disch_over[t],B_SOC[t-1]))
B_SOC[t]=m.if3(Battery_capacity-(B_SOC[t - 1] + B_ch[t] - B_disch[t]),Battery_capacity,B_SOC[t - 1] + B_ch[t] - B_disch[t])
m.Equation(B_ch[t] + Surplus[t] == B_ch_over[t])
m.Equation(B_disch[t] + Unmet[t] == B_disch_over[t])
counter+=1
m.Maximize(m.sum(c))
m.options.SOLVER = 1
# m.open_folder()
m.solve(disp=False)
Last_BOS=B_SOC[t].value
if r==0:
print('Results')
for t in range(starting_point, row):
print('B_ch{}={} B_disch{}={} B_SOC{}={} B_ch_over{}={} B_disch_over{}={} Unmet{}={} Surplus{}={} RE{}={} Demand{}={}'.format(counter-row+t, B_ch[t].value, counter-row+t, B_disch[t].value, counter-row+t, B_SOC[t].value, counter-row+t, B_ch_over[t].value, counter-row+t,B_disch_over[t].value, counter-row+t, Unmet[t].value, counter-row+t, Surplus[t].value, counter-row+t, RE[t], counter-row+t,Demand[t]))
print('Objective: ' + str(m.options.objfcnval))
我使用了两个附加变量,并分解了充电和放电时间中嵌套的 m.if3,如下面的代码所示,并收到了结果。但是,我没有注意到为什么嵌套的 m.if3 在初始代码中不起作用。
from gekko import GEKKO
import sys
Battery_capacity=589200 #kW-h
Battery_Initial_capacity=589200
max_discharge=Battery_capacity/3
max_charge=Battery_capacity
Big_M=1000000000000
epsilon=sys.float_info.epsilon
m = GEKKO(remote=False)
m.solver_options = ['minlp_gap_tol 1.0e-2',\
'minlp_maximum_iterations 10000',\
'minlp_max_iter_with_int_sol 500',\
'minlp_branch_method 1',\
'minlp_integer_tol 1e-100', \
'minlp_integer_leaves 2']
Demand_total=[5629940,5327262,4669939]
RE_total=[5204098,4410247,3694715]
Price_total=[15,17,17]
row=1
finish=0
counter=0
for r in range(3):
start=finish
finish=(r+1)*row
Demand = [Demand_total[r]]
RE = [RE_total[r]]
Price = [Price_total[r]]
# Objective function
c = [None] * row
for t in range(row):
c[t] = (Demand[t] * Price[t])
B_ch_over = [m.Var(lb=0) for t in range(row)]
B_disch_over = [m.Var(lb=0) for t in range(row)]
B_ch = [m.Var(lb=0) for t in range(row)]
B_disch = [m.Var(lb=0) for t in range(row)]
Unmet = [m.Var(lb=0) for t in range(row)]
Surplus = [m.Var(lb=0) for t in range(row)]
B_ch_if2 = [m.Var(lb=0) for t in range(row)]
B_disch_if2 = [m.Var(lb=0) for t in range(row)]
B_SOC = [m.Var() for t in range(row)]
if r==0:
starting_point = 0
Last_BOS=Battery_Initial_capacity
m.Equation(B_SOC[0]==Last_BOS) # initial charge at start
else:
m.Equation(B_SOC[0] == Last_BOS[0]) # initial charge at start
for t in range(starting_point,row):
m.Equation(RE[t] - B_ch_over[t] + B_disch_over[t] == Demand[t])
m.Equation(B_ch_over[t] * B_disch_over[t] <= 0)
B_ch_if2[t] = m.if3(B_ch_over[t] - (Battery_capacity - B_SOC[t - 1]), B_ch_over[t],Battery_capacity - B_SOC[t - 1])
B_ch[t] = m.if3(max_charge - B_ch_if2[t], max_charge, B_ch_if2[t])
B_disch_if2[t] = m.if3(B_disch_over[t] - B_SOC[t - 1], B_disch_over[t], B_SOC[t - 1])
B_disch[t] = m.if3(max_discharge - B_disch_if2[t], max_discharge, B_disch_if2[t])
B_SOC[t]=m.if3(Battery_capacity-(B_SOC[t - 1] + B_ch[t] - B_disch[t]),Battery_capacity,B_SOC[t - 1] + B_ch[t] - B_disch[t])
m.Equation(B_ch[t] + Surplus[t] == B_ch_over[t])
m.Equation(B_disch[t] + Unmet[t] == B_disch_over[t])
counter+=1
m.Maximize(m.sum(c))
m.options.SOLVER = 1
# m.open_folder()
m.solve(disp=False)
Last_BOS=B_SOC[t].value
if r==0:
print('Results')
for t in range(starting_point, row):
print('B_ch{}={} B_disch{}={} B_SOC{}={} B_ch_over{}={} B_disch_over{}={} Unmet{}={} Surplus{}={} RE{}={} Demand{}={}'.format(counter-row+t, B_ch[t].value, counter-row+t, B_disch[t].value, counter-row+t, B_SOC[t].value, counter-row+t, B_ch_over[t].value, counter-row+t,B_disch_over[t].value, counter-row+t, Unmet[t].value, counter-row+t, Surplus[t].value, counter-row+t, RE[t], counter-row+t,Demand[t]))
print('目标:' + str(m.options.objfcnval))