Система уравнений FOPDT в GEKKO - используйте более одного входа

Я хочу использовать два или более входных параметра, чтобы получить более точную оценку переменной. Я уже оценил это, используя только один вход и одно уравнение FOPDT, но когда я пытаюсь добавить еще один вход и соответствующие k, tau и theta вместе с другим уравнением, я получаю ошибку Solution Not Found. Могу ли я таким образом составить систему уравнений?

Подробнее о выходе решателя ниже. Несмотря на то, что я добавил больше переменных, чем уравнений, чтобы использовать более одного ввода, это привело к тому, что моя проблема имела отрицательные степени свободы.

--------- APM Model Size ------------
 Each time step contains
   Objects      :            2
   Constants    :            0
   Variables    :           15
   Intermediates:            0
   Connections  :            4
   Equations    :            6
   Residuals    :            6
 
 Number of state variables:           1918
 Number of total equations: -         2151
 Number of slack variables: -            0
 ---------------------------------------
 Degrees of freedom       :           -233
 
 * Warning: DOF <= 0
 **********************************************
 Dynamic Estimation with Interior Point Solver
 **********************************************
  
  
 Info: Exact Hessian

******************************************************************************
This program contains Ipopt, a library for large-scale nonlinear optimization.
 Ipopt is released as open source code under the Eclipse Public License (EPL).
         For more information visit http://projects.coin-or.org/Ipopt
******************************************************************************

This is Ipopt version 3.12.10, running with linear solver ma57.

Number of nonzeros in equality constraint Jacobian...:     6451
Number of nonzeros in inequality constraint Jacobian.:        0
Number of nonzeros in Lagrangian Hessian.............:     1673

Exception of type: TOO_FEW_DOF in file "IpIpoptApplication.cpp" at line 891:
 Exception message: status != TOO_FEW_DEGREES_OF_FREEDOM evaluated false: Too few degrees of freedom (rethrown)!

EXIT: Problem has too few degrees of freedom.
 
 An error occured.
 The error code is          -10
 
 
 ---------------------------------------------------
 Solver         :  IPOPT (v3.12)
 Solution time  :   2.279999999154825E-002 sec
 Objective      :   0.000000000000000E+000
 Unsuccessful with error code            0
 ---------------------------------------------------
 
 Creating file: infeasibilities.txt
 Use command apm_get(server,app,'infeasibilities.txt') to retrieve file
 @error: Solution Not Found

А вот код

from gekko import GEKKO
import numpy as np
import pandas as pd
import plotly.express as px 

d19jc = d19jc.dropna()

d19jcSlice = d19jc.loc['2019-10-22 05:30:00':'2019-10-22 09:30:00'] #jc22

d19jcSlice.index = pd.to_datetime(d19jcSlice.index)
d19jcSliceGroupMin = d19jcSlice.groupby(pd.Grouper(freq='T')).mean()
data = d19jcSliceGroupMin.dropna()

xdf1 = data['Cond_PID_SP']
xdf2 = data['Front_PID_SP']
ydf1 = data['Cond_Center_Top_TC']

xms1 = pd.Series(xdf1)
xm1 = np.array(xms1)
xms2 = pd.Series(xdf2)
xm2 = np.array(xms2)
yms = pd.Series(ydf1)
ym = np.array(yms)

xm_r = len(xm1)
tm = np.linspace(0,xm_r-1,xm_r)

m = GEKKO()
m.options.IMODE=5
m.time = tm; time = m.Var(0); m.Equation(time.dt()==1)

k1 = m.FV(lb=0.1,ub=5); k1.STATUS=1
tau1 = m.FV(lb=1,ub=300); tau1.STATUS=1
theta1 = m.FV(lb=0,ub=30); theta1.STATUS=1
k2 = m.FV(lb=0.1,ub=5); k2.STATUS=1
tau2 = m.FV(lb=1,ub=300); tau2.STATUS=1
theta2 = m.FV(lb=0,ub=30); theta2.STATUS=1

# create cubic spline with t versus u
uc1 = m.Var(xm1); tc1 = m.Var(tm); m.Equation(tc1==time-theta1)
m.cspline(tc1,uc1,tm,xm1,bound_x=False)
# create cubic spline with t versus u
uc2 = m.Var(xm2); tc2 = m.Var(tm); m.Equation(tc2==time-theta2)
m.cspline(tc2,uc2,tm,xm2,bound_x=False)

x1 = m.Param(value=xm1)
x2 = m.Param(value=xm2)
y = m.Var(value=ym)
yObj = m.Param(value=ym)

m.Equation(tau1*y.dt()+(y-ym[0])==k1 * (uc1-xm1[0]))
m.Equation(tau2*y.dt()+(y-ym[0])==k2 * (uc2-xm2[0]))
m.Minimize((y-yObj)**2)
m.options.EV_TYPE=2

print('solve start')
m.solve(disp=True)

print('k1: ', k1.value[0])
print('tau1: ',  tau1.value[0])
print('theta1: ', theta1.value[0])
print('k2: ', k2.value[0])
print('tau2: ',  tau2.value[0])
print('theta2: ', theta2.value[0])

df_plot = pd.DataFrame({'DateTime' : data.index,
                        'Cond_Center_Top_TC' : np.array(yObj),
                        'Fit Cond_Center_Top_TC - Train' : np.array(y),
figGekko = px.line(df_plot, 
                   x='DateTime',
                   y=['Cond_Center_Top_TC','Fit Cond_Center_Top_TC - Train'],
                   labels={"value": "Degrees Celsius"},
                   title = "(Cond_PID_SP & Front_PID_SP) -> Cond_Center_Top_TC JC only - Train")
figGekko.update_layout(legend_title_text='')
figGekko.show()

person Daniel Baptista    schedule 04.11.2020    source источник


Ответы (2)


В настоящее время у вас есть только одна переменная и два уравнения.

y = m.Var(value=ym)
yObj = m.Param(value=ym)

m.Equation(tau1*y.dt()+(y-ym[0])==k1 * (uc1-xm1[0]))
m.Equation(tau2*y.dt()+(y-ym[0])==k2 * (uc2-xm2[0]))

Вам нужно создать две отдельные переменные y1 и y2 для двух уравнений.

y1 = m.Var(value=ym)
y2 = m.Var(value=ym)
yObj = m.Param(value=ym)

m.Equation(tau1*y1.dt()+(y1-ym[0])==k1 * (uc1-xm1[0]))
m.Equation(tau2*y2.dt()+(y2-ym[0])==k2 * (uc2-xm2[0]))

Вам также может потребоваться создать два отдельных вектора измерений для ym1 и ym2, если у вас есть разные данные для каждого из них.

Изменить: система с несколькими входами и одним выходом (MISO)

Для системы MISO вам необходимо настроить уравнение, как показано в курсе Динамика процессов и управление.

y = m.Var(value=ym)
yObj = m.Param(value=ym)

m.Equation(tau*y.dt()+(y-ym[0])==k1 * (uc1-xm1[0]) + k2 * (uc2-xm2[0]))

В этой форме есть только одна постоянная времени. Если им нужны разные постоянные времени, вы также можете добавить два выхода вместе с:

y1 = m.Var(value=ym[0])
y2 = m.Var(value=ym[0])
y  = m.Var(value=ym)
yObj = m.Param(value=ym)

m.Equation(tau1*y1.dt()+(y1-ym[0])==k1 * (uc1-xm1[0]))
m.Equation(tau2*y2.dt()+(y2-ym[0])==k2 * (uc2-xm2[0]))
m.Equation(y==y1+y2)

В этом случае y - это переменная с данными, а y1 и y2 - неизмеряемые состояния.

person John Hedengren    schedule 05.11.2020
comment
Спасибо за ваш ответ. Я уже пробовал это, но это полностью разделяет мою проблему на две разные оценки. Возможно, система уравнений - не лучший подход, но я хочу оценить один и тот же y, используя разные x, чтобы минимизировать ошибку, используя лучшие k, tau и theta для каждого x. Я делаю вид, что делаю MISO-контроль (несколько входов, один выход). Есть какие-нибудь решения? - person Daniel Baptista; 05.11.2020
comment
Спасибо за разъяснения. Надеюсь, новая редакция поможет. - person John Hedengren; 05.11.2020
comment
Спасибо за предложение, я получил решение, использующее это редактирование. Однако мне нужно было скорректировать границы, и у меня все еще была высокая нестабильность на старте. Поскольку y равно y1 + y2, я изменил начальные значения y1 и y2 на ym [0] / 2, и это устранило нестабильность ... Есть ли в этом проблемы? Поскольку у меня есть хорошее решение, но когда я применяю эту модель для оценки значений в другом временном интервале, мои результаты оказываются далекими, и решение продолжает расти до более высоких значений. Этого не происходило, когда я использовал только один вход, я получал разумные оценки, но я хотел повысить точность. - person Daniel Baptista; 09.11.2020
comment
ym [0] и xm1 [0] - установившиеся значения. Вы можете убедиться в том, что это хорошие значения, с помощью областей в вашем наборе данных с нулевым уровнем. - person John Hedengren; 10.11.2020

См. Приведенный ниже пример кода для модели FOPDT с двумя входами и одним выходом. Обе модели передаточной функции имеют разные параметры FOPDT, включая разное время задержки.
Она все еще находится в режиме динамического моделирования (IMODE = 4), но вы можете начать с этого, немного изменив бит в сторону режима динамической оценки (IMODE = 5) и режима MPC (IMODE = 6) позже.

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

tf = 100 
npt = 101 
t = np.linspace(0,tf,npt)
u1 = np.zeros(npt)
u2 = np.zeros(npt)
u1[10:] = 5
u2[40:] = -5

m = GEKKO(remote=True)
m.time = t 
time = m.Var(0) 
m.Equation(time.dt()==1)

K1 = m.FV(1,lb=0,ub=1);      K1.STATUS=1
tau1 = m.FV(5, lb=1,ub=300);  tau1.STATUS=1
theta1 = m.FV(10, lb=2,ub=30); theta1.STATUS=1

K2 = m.FV(0.5,lb=0,ub=1);      K2.STATUS=1
tau2 = m.FV(10, lb=1,ub=300);  tau2.STATUS=1
theta2 = m.FV(20, lb=2,ub=30); theta2.STATUS=1

uc1 = m.Var(u1) 
uc2 = m.Var(u2) 
tc1 = m.Var(t) 
tc2 = m.Var(t)
m.Equation(tc1==time-theta1)
m.Equation(tc2==time-theta2)
m.cspline(tc1,uc1,t,u1,bound_x=False)
m.cspline(tc2,uc2,t,u2,bound_x=False)

yp = m.Var() 
yp1 = m.Var()
yp2 = m.Var()
m.Equation(yp1.dt() == -yp1/tau1 + K1*uc1/tau1) 
m.Equation(yp2.dt() == -yp2/tau2 + K2*uc2/tau2)
m.Equation(yp == yp1 + yp2)

m.options.IMODE=4
m.solve()

print('K1: ', K1.value[0])
print('tau1: ',  tau1.value[0])
print('theta1: ', theta1.value[0])
print('')

print('K2: ', K2.value[0])
print('tau2: ',  tau2.value[0])
print('theta2: ', theta2.value[0])

plt.figure()
plt.subplot(2,1,1)
plt.plot(t,u1)
plt.plot(t,u2)
plt.legend([r'u1', r'u2'])
plt.ylabel('Inputs 1 & 2')
plt.subplot(2,1,2)
plt.plot(t,yp)
plt.legend([r'y1'])
plt.ylabel('Output')
plt.xlabel('Time')
plt.savefig('sysid.png')
plt.show()

введите описание изображения здесь

K1:  1.0
tau1:  5.0
theta1:  10.0

K2:  0.5
tau2:  10.0
theta2:  20.0
person Junho Park    schedule 13.11.2020