繁体   English   中英

使用 openopt 和 scipy 求解具有动态约束的非线性优化系统时出错

[英]Error in solving a nonlinear optimization system with dynamic constraint using openopt and scipy

我正在尝试解决受动态( h(x, x', u) = 0 )约束的非线性最优控制问题。
给定:
f(x) = (u(t) - u(0)(t))^2 # u0(t) 是提供给系统的初始输入
h(x) = y'(t) - integral(sqrt(u(t))*y(t) + y(t)) = 0 # 一个非线性微分方程
-2 < y(t) < 10 # 系统状态限制在这个范围内
-2 < u(t) < 10 # 系统状态限制在这个范围内
u0(t) # 将被定义为任意分段线性函数

我尝试使用 openopt 和 scipy 将问题转换为 python 代码:

import numpy as np
from scipy.integrate import *
from openopt import NLP
import matplotlib.pyplot as plt
from operator import and_

N = 15*4
y0 = 10
t0 = 0
tf = 10
lb, ub = np.ones(2)*-2, np.ones(2)*10

t = np.linspace(t0, tf, N)
u0 = np.piecewise(t, [t < 3, and_(3 <= t, t < 6), 6 <= t], [2, lambda t: t - 3, lambda t: -t + 9])

p = np.empty(N, dtype=np.object)
r = np.empty(N, dtype=np.object)
y = np.empty(N, dtype=np.object)
u = np.empty(N, dtype=np.object)
ff = np.empty(N, dtype=np.object)
for i in range(N):
    t = np.linspace(t0, tf, N)
    b, a = t[i], t[i - 1]
    integrand = lambda t, u1, y1 : np.sqrt(u1)*y1 + y1
    integral = lambda u1, y1 : fixed_quad(integrand, a, b, args=(u1, y1))[0]
    f = lambda x1: ((x1[1] - u0[i])**2).sum()
    h = lambda x1: x1[0] - y0 - integral(x1[0], x1[1])
    p[i] = NLP(f, (y0, u0[i]), h=h, lb=lb, ub=ub)
    r[i] = p[i].solve('scipy_slsqp')
    y0 = r[i].xf[0]
    y[i] = r[i].xf[0]
    u[i] = r[i].xf[1]
    ff[i] = r[i].ff

figure1 = plt.figure()
axis1 = figure1.add_subplot(311)
plt.plot(u0)
axis2 = figure1.add_subplot(312)
plt.plot(u)
axis2 = figure1.add_subplot(313)
plt.plot(y)
plt.show()

现在的问题是,使用像y0 = 10这样的正初始 y0 运行代码,代码将产生令人满意的结果。 但是给y0 = 0或负一个y0 = -1 ,nlp 问题将是有缺陷的,说:
没有获得可行的解决方案(1个约束等于NaN,MaxResidual = 0,objFunc = nan)
此外,考虑到分段线性初始 u0,如果t < 3处将除 0 之外的任何数字放在函数的第一个范围内,则意味着:
u0 = np.piecewise(t, [t < 3, and_(3 <= t, t < 6), 6 <= t], [2, lambda t: t - 3, lambda t: -t + 9])
代替:
u0 = np.piecewise(t, [t < 3, and_(3 <= t, t < 6), 6 <= t], [0, lambda t: t - 3, lambda t: -t + 9])
这将再次导致相同的错误。
有任何想法吗 ?
提前致谢。

我的第一个想法是,您似乎正在解决二维最优控制问题,就好像它是一维问题一样。

约束动力学 $h(x, x', t)$ 实际上是二阶 ODE。

y''(t) - sqrt(u(t))*y(t) + y(t)) = 0

从这里开始,我将以标准方式将我的系统改写为二维的一阶系统。

我的第二个想法是,您似乎在每个时间步为 $u(t)$ 独立优化,而问题是为整个函数 $u(.)$ 全局优化。 所以如果有的话,对 NLP 的调用应该在 for 循环之外......

有专门的 Optimal Control 开源工具箱:

在 Python 上,有 JModellica: http ://www.jmodelica.org/。

或者,我也成功地使用了:ACADO,http: //sourceforge.net/p/acado/wiki/Home/ (在 C++ 中)

现在有一些功能非常强大的建模工具,例如 CasADi、Pyomo 和 Gekko,但在提出问题时它们并不存在。 这是Gekko的解决方案。 一个问题是sqrt(u)需要有一个正的u值以避免虚数。

壁虎解决方案

from gekko import GEKKO
import numpy as np

m = GEKKO(remote=False)
u0=1; N=61
m.time = np.linspace(0,10,N)

# lb of -2 leads to imaginary number with sqrt(-)
u = m.MV(u0,lb=1e-2,ub=10); u.STATUS=1
m.options.MV_STEP_HOR = 18 # allow move at 3, 6 time units
m.options.MV_TYPE = 1 # piecewise linear
y = m.Var(10,lb=-2,ub=10)

m.Minimize((u-u0)**2)
m.Minimize(y**2) # otherwise solution is u=u0
m.Equation(y.dt()==m.integral(m.sqrt(u)*y-y))
m.options.IMODE=6
m.options.SOLVER=1
m.solve()

import matplotlib.pyplot as plt
plt.figure(figsize=(7,4))
plt.plot(m.time,u,label='u')
plt.plot(m.time,y,label='y')
plt.legend(); plt.grid()
plt.savefig('solution.png',dpi=300)
plt.show()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM