我正在使用以下代码在GEKKO中模拟优化问题。
# Copyright 2020, Natasha, All rights reserved.
import numpy as np
from gekko import GEKKO
from pprint import pprint
import matplotlib.pyplot as plt
from scipy.integrate import odeint
def get_mmt():
"""
M and M transpose required for differential equations
:params: None
:return: M transpose and M -- 2D arrays ~ matrices
"""
MT = np.array([[-1, 0, 0, 0, 0, 0, 0, 0, 0],
[1, -1, 0, 0, 0, 0, 0, 0, 0],
[0, 1, -1, 0, 0, 0, 0, 0, 0],
[0, 0, 1, -1, 0, 0, 0, 0, 0],
[0, 0, 0, 1, -1, 0, 0, 0, 0],
[0, 0, 0, 0, 1, -1, 0, 0, 0],
[0, 0, 0, 0, 0, 1, -1, 0, 0],
[0, 0, 0, 0, 0, 0, 1, -1, 0],
[0, 0, 0, 0, 0, 0, 0, 1, -1],
[0, 0, 0, 0, 0, 0, 0, 0, 1]])
M = np.transpose(MT)
return M, MT
def actual(phi, t):
"""
Actual system/ Experimental measures
:param phi: 1D array
:return: time course of variable phi -- 2D arrays ~ matrices
"""
# spatial nodes
ngrid = 10
end = -1
M, MT = get_mmt()
D = 5000*np.ones(ngrid-1)
A = MT@np.diag(D)@M
A = A[1:ngrid-1]
# differential equations
dphi = np.zeros(ngrid)
# first node
dphi[0] = 0
# interior nodes
dphi[1:end] = -A@phi # value at interior nodes
# terminal node
dphi[end] = D[end]*2*(phi[end-1] - phi[end])
return dphi
if __name__ == '__main__':
# ref: https://apmonitor.com/do/index.php/Main/PartialDifferentialEquations
ngrid = 10 # spatial discretization
end = -1
# integrator settings (for ode solver)
tf = 0.5
nt = int(tf / 0.01) + 1
tm = np.linspace(0, tf, nt)
# ------------------------------------------------------------------------------------------------------------------
# measurements
# ref: https://www.youtube.com/watch?v=xOzjeBaNfgo
# using odeint to solve the differential equations of the actual system
# ------------------------------------------------------------------------------------------------------------------
phi_0 = np.array([5, 0, 0, 0, 0, 0, 0, 0, 0, 0])
phi = odeint(actual, phi_0, tm)
# plot results
plt.figure()
plt.plot(tm*60, phi[:, :])
plt.ylabel('phi')
plt.xlabel('Time (s)')
plt.show()
# ------------------------------------------------------------------------------------------------------------------
# GEKKO model
# ------------------------------------------------------------------------------------------------------------------
m = GEKKO(remote=False)
m.time = tm
# ------------------------------------------------------------------------------------------------------------------
# initialize state variables: phi_hat
# ref: https://apmonitor.com/do/uploads/Main/estimate_hiv.zip
# ------------------------------------------------------------------------------------------------------------------
phi_hat = [m.CV(value=phi_0[i]) for i in range(ngrid)] # initialize phi_hat; variable to match with measurement
# ------------------------------------------------------------------------------------------------------------------
# parameters (/control parameters to be optimized while minimizing the cost function in GEKKO)
# ref: http://apmonitor.com/do/index.php/Main/DynamicEstimation
# ref: https://apmonitor.com/do/index.php/Main/EstimatorObjective
# def model
# ------------------------------------------------------------------------------------------------------------------
# Manually enter guesses for parameters
Dhat0 = 5000*np.ones(ngrid-1)
Dhat = [m.MV(value=Dhat0[i]) for i in range(0, ngrid-1)]
for i in range(ngrid-1):
Dhat[i].STATUS = 1 # Allow optimizer to fit these values
# Dhat[i].LOWER = 0
# ------------------------------------------------------------------------------------------------------------------
# differential equations
# ------------------------------------------------------------------------------------------------------------------
M, MT = get_mmt()
A = MT @ np.diag(Dhat) @ M
A = A[1:ngrid - 1]
# first node
m.Equation(phi_hat[0].dt() == 0)
# interior nodes
int_value = -A @ phi_hat # function value at interior nodes
m.Equations(phi_hat[i].dt() == int_value[i] for i in range(0, ngrid-2))
# terminal node
m.Equation(phi_hat[ngrid-1].dt() == Dhat[end] * 2 * (phi_hat[end-1] - phi_hat[end]))
# ------------------------------------------------------------------------------------------------------------------
# simulation
# ------------------------------------------------------------------------------------------------------------------
m.options.IMODE = 5 # simultaneous dynamic estimation
m.options.NODES = 3 # collocation nodes
m.options.EV_TYPE = 2 # squared-error :minimize model prediction to measurement
for i in range(ngrid):
phi_hat[i].FSTATUS = 1 # fit to measurement phi obtained from 'def actual'
phi_hat[i].STATUS = 1 # build objective function to match measurement and prediction
phi_hat[i].value = phi[:, i]
m.solve()
pprint(Dhat)
在代码中,修改了
tm = np.linspace(0, tf, nt)
变量以检查tm
如何更改估计的参数值。当nt
更大时,求解器收敛到一个解所花费的时间就很大。所以我正在尝试并行化代码。我看了this教程中可用的GEKKO示例。我想调整上述链接中给出的过程。但是,我可以理解一些步骤。
例如,在链接中提供的以下代码中:
def __init__(self, id, server, ai, bi):
s = self
s.id = id
s.server = server
s.m = GEKKO()
s.a = ai
s.b = bi
s.objective = float('NaN')
# initialize variables
s.m.x1 = s.m.Var(1,lb=1,ub=5)
s.m.x2 = s.m.Var(5,lb=1,ub=5)
s.m.x3 = s.m.Var(5,lb=1,ub=5)
s.m.x4 = s.m.Var(1,lb=1,ub=5)
# Equations
s.m.Equation(s.m.x1*s.m.x2*s.m.x3*s.m.x4>=s.a)
s.m.Equation(s.m.x1**2+s.m.x2**2+s.m.x3**2+s.m.x4**2==s.b)
# Objective
s.m.Obj(s.m.x1*s.m.x4*(s.m.x1+s.m.x2+s.m.x3)+s.m.x3)
# Set global options
s.m.options.IMODE = 3 # steady state optimization
s.m.options.SOLVER = 1 # APOPT solver
在此,所有变量均附有s.m。 。
1.我还应该在所有变量后加上s.m吗?还是只有一行东西?
2.在上面的代码中将ai,bi传递给def _init,在我的示例中,我应该传递
tm
吗?澄清这些疑惑,并就如何进行进行解释,将大有帮助。
编辑:从下面给出的解释以及从下面提到的引用文献中提供的表3中,我了解我应该使用
1.当求解器设置为IPOPT或COLDSTART = 2时
2。
initialization with IMODE=7 and then feed that simulation solution as an initial guess for IMODE=5.
我已经尝试实现第二个策略(2)。代码尚未完成。
feed that simulation solution as an initial guess for IMODE=5
-在这里,我想确认
ìnitial guess
是否引用了对参数的猜测我的代码中的
Dhat0 = 5000*np.ones(ngrid-1)
或m.Equations中给出的ode中状态变量的初始条件。I tried,
m.options.IMODE = 5
m.solve()
print(Dhat)
打印所有与输入相同的5000。
请提供进一步的建议。
# Copyright 2013, Natasha, All rights reserved.
import numpy as np
from gekko import GEKKO
from pprint import pprint
import matplotlib.pyplot as plt
from scipy.integrate import odeint
def get_mmt():
"""
M and M transpose required for differential equations
:params: None
:return: M transpose and M -- 2D arrays ~ matrices
"""
MT = np.array([[-1, 0, 0, 0, 0, 0, 0, 0, 0],
[1, -1, 0, 0, 0, 0, 0, 0, 0],
[0, 1, -1, 0, 0, 0, 0, 0, 0],
[0, 0, 1, -1, 0, 0, 0, 0, 0],
[0, 0, 0, 1, -1, 0, 0, 0, 0],
[0, 0, 0, 0, 1, -1, 0, 0, 0],
[0, 0, 0, 0, 0, 1, -1, 0, 0],
[0, 0, 0, 0, 0, 0, 1, -1, 0],
[0, 0, 0, 0, 0, 0, 0, 1, -1],
[0, 0, 0, 0, 0, 0, 0, 0, 1]])
M = np.transpose(MT)
return M, MT
def actual(phi, t):
"""
Actual system/ Experimental measures
:param phi: 1D array
:return: time course of variable phi -- 2D arrays ~ matrices
"""
# spatial nodes
ngrid = 10
end = -1
M, MT = get_mmt()
D = 5000*np.ones(ngrid-1)
A = MT@np.diag(D)@M
A = A[1:ngrid-1]
# differential equations
dphi = np.zeros(ngrid)
# first node
dphi[0] = 0
# interior nodes
dphi[1:end] = -A@phi # value at interior nodes
# terminal node
dphi[end] = D[end]*2*(phi[end-1] - phi[end])
return dphi
if __name__ == '__main__':
# ref: https://apmonitor.com/do/index.php/Main/PartialDifferentialEquations
ngrid = 10 # spatial discretization
end = -1
# integrator settings (for ode solver)
tf = 0.5
nt = int(tf / 0.01) + 1
tm = np.linspace(0, tf, nt)
# ------------------------------------------------------------------------------------------------------------------
# measurements
# ref: https://www.youtube.com/watch?v=xOzjeBaNfgo
# using odeint to solve the differential equations of the actual system
# ------------------------------------------------------------------------------------------------------------------
phi_0 = np.array([5, 0, 0, 0, 0, 0, 0, 0, 0, 0])
phi = odeint(actual, phi_0, tm)
# ------------------------------------------------------------------------------------------------------------------
# GEKKO model
# https://apmonitor.com/wiki/index.php/Main/Simulation
# ------------------------------------------------------------------------------------------------------------------
# Initialize GEKKO
m1 = GEKKO(remote=False)
m2 = GEKKO(remote=False)
for m in [m1,m2]:
m.time = tm
# ------------------------------------------------------------------------------------------------------------------
# initialize state variables: phi_hat
# ref: https://apmonitor.com/do/uploads/Main/estimate_hiv.zip
# ------------------------------------------------------------------------------------------------------------------
phi_hat = [m.CV(value=phi_0[i]) for i in range(ngrid)] # initialize phi_hat; variable to match with measurement
# ------------------------------------------------------------------------------------------------------------------
# parameters (/control parameters to be optimized while minimizing the cost function in GEKKO)
# ref: http://apmonitor.com/do/index.php/Main/DynamicEstimation
# ref: https://apmonitor.com/do/index.php/Main/EstimatorObjective
# def model
# ------------------------------------------------------------------------------------------------------------------
# Manually enter guesses for parameters
Dhat0 = 5000*np.ones(ngrid-1)
Dhat = [m.FV(value=Dhat0[i]) for i in range(0, ngrid-1)]
for i in range(ngrid-1):
Dhat[i].STATUS = 1 # Allow optimizer to fit these values
# Dhat[i].LOWER = 0
# ------------------------------------------------------------------------------------------------------------------
# differential equations
# ------------------------------------------------------------------------------------------------------------------
M, MT = get_mmt()
A = MT @ np.diag(Dhat) @ M
A = A[1:ngrid - 1]
# first node
m.Equation(phi_hat[0].dt() == 0)
# interior nodes
int_value = -A @ phi_hat # function value at interior nodes
m.Equations(phi_hat[i].dt() == int_value[i] for i in range(0, ngrid-2))
# terminal node
m.Equation(phi_hat[ngrid-1].dt() == Dhat[end]*2*(phi_hat[end-1] - phi_hat[end]))
# ------------------------------------------------------------------------------------------------------------------
# simulation
# ------------------------------------------------------------------------------------------------------------------
m.options.NODES = 3 # collocation nodes
m.options.EV_TYPE = 2 # squared-error :minimize model prediction to measurement
m.options.SOLVER = 3 # 1 APOPT, 2 BPOPT, 3 IPOPT
# ------------------------------------------------------------------------------------------------------------------
# Initialization
# Ref: Initialization strategies for optimization of dynamic systems
# ------------------------------------------------------------------------------------------------------------------
m1.options.IMODE = 7 # simultaneous dynamic estimation
for i in range(ngrid):
phi_hat[i].FSTATUS = 1 # fit to measurement phi obtained from 'def actual'
phi_hat[i].STATUS = 1 # build objective function to match measurement and prediction
phi_hat[i].value = phi[:, i]
m1.solve()
# ------------------------------------------------------------------------------------------------------------------
# MPH
# Ref: Initialization strategies for optimization of dynamic systems
# ------------------------------------------------------------------------------------------------------------------
m2.options.IMODE = 5 # simultaneous dynamic estimation
for i in range(ngrid):
phi_hat[i].FSTATUS = 1 # fit to measurement phi obtained from 'def actual'
phi_hat[i].STATUS = 1 # build objective function to match measurement and prediction
phi_hat[i].value = phi[:, i]
m2.solve()
pprint(Dhat)
最佳答案
Gekko中提供了两种不同类型的并行计算。
如果要提高速度,建议您尝试使用
IMODE=7
进行初始化,然后将该模拟解决方案作为对IMODE=5
的初始猜测。另一种方法是使用COLDSTART=2
,然后使用COLDSTART=0
和TIME_SHIFT=0
解决优化问题,作为下一个解决方案。这些策略的讨论如下:对编辑的响应
尝试插入以下内容而不是单个
m.solve()
命令:m.options.IMODE = 5 # simultaneous estimation
m.options.COLDSTART = 2 # coldstart on
m.solve(disp=False) # first solve
m.options.COLDSTART = 0 # coldstart off
m.options.TIME_SHIFT = 0 # turn off time-shift (default=1)
m.solve(disp=False) # second solve
关于python-3.x - GEKKO中优化问题的并行化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61143557/