在 Gekko 中使用样条或分段函数作为输入(中间)

计算科学 壁虎
2021-12-23 06:05:38

我的问题的简单解释是使用表格或曲线作为 Gekko(和/或 AP Monitor)中优化问题的输入的最佳方法是什么?

例如,我按高度简化了大气密度数据。我可以将数据拟合到具有大约 5 个控制点的 Hermite 形式的三次样条曲线(明确给出控制点的斜率,参考 wikipedia),并且我有一个 python 函数来插值,但据我所知,我不能使用Gekko 模型中的 python 函数。

我对可能性的理解和假设:

通常,第一选择是将数据拟合到方程中,但是在这种情况下它不适合。我可以将它拟合到具有足够精度的 2 或 3 段分段函数中,但即使这样也不总是可行的。这也将涉及不等式条件和导数中可能的不连续性,这在优化问题中至少可以说是不可取的。

我可以在技术上重写我作为模型方程的插值例程,但它很快就会变得非常混乱。

似乎内置的cspline 对象可能会起作用,但是这些示例仅显示了将样条曲线拟合到数据。我的理解是,您可以在模型中拥有一个模型,因此似乎有可能拥有一个内部嵌套模型来解决插值点。这似乎有点矫枉过正,而且似乎可能存在性能问题,尤其是在需要顺序求解器的情况下。

类似地,AP Monitor 具有pwl(分段线性)对象和查找对象该文档显示了 Gekko 中 pwl 对象的实现(基本上使用松弛变量进行线性插值),但是当需要多个此类输入时,这似乎会变得混乱。

因此,更具体地重申我的问题:关于如何做到这一点,是否有明确的最佳实践?如果没有,是否有我错过的每个重要决定因素(即优点/缺点)?

额外的问题 - 同样的事情,但是像阻力系数这样的二维数据取决于马赫和攻角?(使用bspline 对象而不是 cspline)

我最初的假设是将压力、温度和密度数据作为 csplines,将阻力和升力系数作为 bsplines。我仍在学习 Gekko/AP Monitor 和 python,所以我认为现在最好先问清楚,然后再花几天时间尝试解决一些不实用的问题。

1个回答

正如您所提到的,Gekko 中提供了csplinebspline对象。我们已经成功地将它们用于在高空、长航时 (HALE) 飞机的飞行动力学(源代码)的大规模优化问题中的阻力,在高空太阳能飞机轨迹的动态优化下驻站约束 (链接到文章) .

HALE 飞机优化

您作为高度函数的大气建模可能是相关的。除了让 Gekko 创建 bspline 对象外,您还可以在外部对其进行拟合并传入样条参数。

from gekko import GEKKO
import numpy as np
#knots and coeffs
m = GEKKO(remote=False)
tx = [ -1, -1, -1, -1,  1,  1,  1,  1]
ty = [ -1, -1, -1, -1,  1,  1,  1,  1]
c = [1.0, 0.33333333, -0.33333333, -1.0, 0.33333333, \
     0.11111111, -0.11111111, -0.33333333, -0.33333333, \
    -0.11111111, 0.11111111, 0.33333333, -1.0, -0.33333333,\
     0.33333333, 1.0]
x = m.Var(0.5,-1,1)
y = m.Var(0.5,-1,1)
z = m.Var(2)
m.bspline(x,y,z,tx,ty,c,data=False)
m.Obj(z)
m.solve()

您也可以让 Gekko 为您创建 bspline。

from gekko import GEKKO
import numpy as np
#raw data
m = GEKKO(remote=False)
xgrid = np.linspace(-1, 1, 20)
ygrid = xgrid
z_data = x*y
x = m.Var(0.5,-1,1)
y = m.Var(0.5,-1,1)
z = m.Var(2)
m.bspline(x,y,z,xgrid,ygrid,z_data)
m.Obj(z)
m.solve()

Gekko 的后端代码是用 Fortran 编译的,因此它甚至可能比在 Python 中创建 bspline 更快。