如何确保 GEKKO 中的阶跃函数控制以及对 MV_TYPE 的困惑

How to ensure a Step Function Control in GEKKO and confusion about MV_TYPE

我有一个简单的最优控制问题,我必须找到阶跃函数 f(t) 来最大化 objective 函数式 (IMODE=6)。现在 f(t) 在 [0, 10) 中为 t 定义 f 采用 10 个不同的等距值。 (即 f(t)=f0 对于0 ≤ t < 1 等)。此外 f 本身仅采用 0 到 10 之间的整数值。

首先,我 m.time=np.linspace(0, 10, 11)[0, 1, 2, ..., 10] 成为我的时间网格中的点。然后我采用 f=m.MV(lb=0, ub=10, integer=True) 并使用 m.options.SOLVER = 1 通过 APOPT 解决,只是忽略了 f(10).

的值

这解决得很好,我能够获得整数解。其结果似乎是 f 的线性插值,而不是我想要的 f 的阶跃函数插值。阅读文档后,我认为 MV_TYPE 是我需要的标志。因此,我尝试通过设置 m.options.MV_TYPE=0f 切换为阶跃函数,但这给了我与 m.options.MV_TYPE=1 相同的结果。 (告诉我我完全误解了 MV_TYPE 应该做什么。)所以对于我的第一个问题:甚至 MV_TYPE 标志在做什么?我的读物是 MV_TYPE=0 使用阶跃函数对所有 MV 变量进行插值,MV_TYPE=1 使用线性插值对所有 MV 变量进行插值。但是,MV_TYPE 的两个选项的两次单独运行会产生具有相同 objective 函数值的相同解决方案。

其次,有没有更好的方法来做我想做的事? (强制我的控件采用不连续阶跃函数的形式)。我在文档(18 个示例中的第 17 个示例)中看到,制作阶跃函数的适当方法基本上是使时间网格足够精细以覆盖接缝。事实上,像 m.time=[0, 0.999, 1, 1.999, 2, 2.999, ..., 9, 9.999] 这样的网格对我来说是一个合理的网格。但是,然后我的 f=m.MV 行将导致 f 具有 20 个独立值(而不是我想要的 10 个)。为了确保我的函数是阶跃函数?

我忍不住觉得我在这里遗漏了一些明显的东西!

您对MV_TYPE的理解是正确的。来自 document for MV_TYPE:

MV_TYPE 指定 MV 端点之间的零阶保持 (0) 或一阶线性 (1) 插值。当 MV_STEP_HOR 为 2 或更大时,MV_TYPE 仅应用于允许调整的每个段。 MV 段在其他方面与先前的时间段相同。 MV_TYPE只影响NODES个数在3到6之间时的解。当NODES=2时不重要,因为端点之间没有插值节点。

很可能给出相同的答案,因为默认情况下 m.options.NODES=2。设置 m.options.NODES>=3 可能会导致带有 MV_TYPE=1 的整数类型 MV 出现问题,因为线性插值点也需要是整数。如果您仍想使用 NODES=2 但需要更多的模拟分辨率,请尝试以下操作:

m.time = [0,0.5,0.9999,1,1.5,1.9999,2,2.5,2.9999,3]