在 ipopt 的等式中使用 scipy Odeint 的灵活性

flexibility using scipy Odeint in equation for ipopt

我正在验证我在 pyoptsparse 和 scipy 中编写的几个模型。我希望能够在 Gekko 中测试相同的代码,看看结果是否与我最初制作的更具象征意义的 Gekko 版本一致。为此,我尝试使用 Odeint 并与我自己的代码集成,而不是使用内置的 Gekko 功能。可以这样做吗?优化器采用 Odeint 梯度的能力有问题吗?

import numpy as np
from scipy.integrate import odeint
from gekko import GEKKO

nhrs = 24
time = np.arange(nhrs)
m = GEKKO(remote=True)

gen = m.Array(m.Param, nhrs)
for geni in gen:
    geni.value = 1

tes_store = m.Array(m.Var, nhrs)
for tesi in tes_store:
    tesi.value = 0
    tesi.lower = -1
    tesi.upper = 1

T = m.Array(m.SV, nhrs)
for testi in T:
    testi.upper = 24
    testi.lower = 0

def tes_T_dt(t, T, gen, tes_store):
    return gen*tes_store

def tes_T(gen, tes_store, t):
    T_hist = [0]
    T_new = 0
    for i in range(len(t)):
        step = odeint(tes_T_dt, T_new, [0, 1], args=(gen[i].value, tes_store[i].value))
        T_new = step[1][0]
        T_hist.append(T_new)
    return T_hist

Temp = tes_T(gen, tes_store, time)[1:]

equations = []
m.Equation(T == tes_T(gen, tes_store, time)[1:])

m.Obj(-T[23])
Temp = tes_T(gen, tes_store, time)[1:]

m.options.SOLVER = 3
m.solve()

for i in range(len(T)):
    print(f'{i} gen={gen[i].value}, tes_store={tes_store[i].value}, T={T[i].value}, Temp={Temp[i]}')

我收到以下错误

 @error: Equation Definition
 Equation without an equality (=) or inequality (>,<)
 false
 STOPPING...
Traceback (most recent call last):
  File "gekkopyoptsimpleTEST.py", line 54, in <module>
    m.solve()
  File "/home/prism/miniconda3/lib/python3.7/site-packages/gekko/gekko.py", line 2103, in solve
    raise Exception(response)
Exception:  @error: Equation Definition
 Equation without an equality (=) or inequality (>,<)
 false
 STOPPING...

Gekko 中的所有表达式都必须使用 Gekko 变量,以便模型可以编译为字节码。如果您打开 运行 文件夹和 gk_model0.apm,您将看到您使用此脚本创建的模型:

Model
Parameters
    p1 = 1
    p2 = 1
    p3 = 1
    p4 = 1
    ! removed p5-p21
    p22 = 1
    p23 = 1
    p24 = 1
End Parameters
Variables
    v1 = 0, <= 1, >= -1
    v2 = 0, <= 1, >= -1
    v3 = 0, <= 1, >= -1
    v4 = 0, <= 1, >= -1
    ! removed v5-v45
    v46 = 0, <= 24, >= 0
    v47 = 0, <= 24, >= 0
    v48 = 0, <= 24, >= 0
End Variables
Equations
    False
    minimize (-v48)
End Equations

End Model

如您所见 Equations - End Equations 部分,公式:

m.Equation(T == tes_T(gen, tes_store, time)[1:])

计算为 False 因为它正在将一个数组与另一个不相等的数组进行比较。您需要在那里使用 Gekko 表达式,例如 m.Equation(T[i] == tes_T(gen, tes_store, time)[i+1])。然而,tes_T 不能被 gekko 调用,所以等式的右边只是模型中永远不会更新的数字。 gekko 目前不支持黑盒函数。

Gekko 可以对微分方程进行积分。这是否接近您要通过调整 gen 并服从微分方程 dT/dt==gen*tes_store 来最大化 T 的最终值?

import numpy as np
from gekko import GEKKO
import matplotlib.pyplot as plt

nhrs = 24
m = GEKKO(remote=False)
m.time = np.arange(nhrs)
gen = m.Param(value=1)
tes_store = m.Var(value=0,lb=-1,ub=1)
T = m.SV(lb=0,ub=24)
m.Equation(T.dt()==gen*tes_store)
p = np.zeros(nhrs); p[-1]=1
final = m.Param(p)
m.Maximize(T*final)
m.options.SOLVER = 3
m.options.NODES = 2
m.options.IMODE = 6
m.solve()

plt.plot(m.time,T.value,'k-',label='T')
plt.plot(m.time,gen.value,'b.-',label='gen')
plt.plot(m.time,tes_store,'r--',label='tes_store')
plt.legend()
plt.show()