Gekko 不尊重变量的限制

Posted

技术标签:

【中文标题】Gekko 不尊重变量的限制【英文标题】:Gekko is not respecting the restrictions of the variables 【发布时间】:2021-12-21 07:37:12 【问题描述】:

Gekko 不遵守限制,因此无法找到与 Excel 求解器相同的解决方案。

这是要解决的问题,尽量减少错误

from gekko import GEKKO
import numpy as np
obj = 0
obj2 = 0
m = GEKKO(remote=False)
v0 = m.Var(0.002, -0.005, 0.005)
v1 = m.Var(0.004, -0.005, 0.005)
v2 = m.Var(0.002, -0.005, 0.005)
v3 = m.Var(0.002, -0.005, 0.005)
v4 = m.Var(0.002, -0.005, 0.005)
v5 = m.Var(0.001, -0.005, 0.005)
v6 = m.Var(0.003, -0.005, 0.005)
v7 = m.Var(-0.005, -0.005, 0.005)
v8 = m.Var(-0.002, -0.005, 0.005)
v9 = m.Var(-0.001, -0.005, 0.005)
y = []
y.append(v0)
y.append(v1)
y.append(v2)
y.append(v3)
y.append(v4)
y.append(v5)
y.append(v6)
y.append(v7)
y.append(v8)
objetivos = []
obj = 0
pq = []
p = ponderaciones[:9]
p2 = ponderaciones[9:]
r = rentabilidades[:9]
r2 = rentabilidades[9:]
for j in range(len(r2) + len(r)):
    if j < (len(r)):
        obj += p[j]/(1+y[j])*r[j]
    else:
        iterator = j - len(r)
        obj += p2[iterator]*r2[iterator]
objetivos.append(obj)
pq.append(obj)
a = np.array(objetivos)
b = un_pickle
print(b[0])
z = (np.sum(b[0]- a[0]))**2
m.Minimize(z)
m.solve(disp=False)
print(y)
print('Objective = '+str(m.options.objfcnval*1000000000/5))

我试图通过这样做来限制变量,

yb = m.Array(m.Var, 0.004, lb = -0.005, ub = 0.005)

但它也不起作用。

最终的解和变量是这样结束的

[[0.00039421467367], [0.00078856597697], [0.00039428301399], [0.00039428298849], [0.00039428298849], [0.00019714149424], [0.00059142448273], [-0.00096599525378], [-0.0003942834613]]
Objective = 9.2421428926

我不确定为什么这些限制不起作用。

为了重现问题,我限制了数据量,但在完整的情况下 ponderacionesrentabilidades 是具有许多 DF 内部的字典,在这种情况下它们只是一个系列。

ponderaciones = pd.Series('ACC': 0.07645771,
 'UAA': 0.0,
 'EOAO': 0.000712,
 'CIA': 0.0055,
 'BJA': 0.01,
 'BOEA': 0.03,
 'UA': 0.110,
 'EOA': 0.0712,
 'CI': 0.00557,
 'BJ': 0.0161,
 'BOE': 0.0355,
 'U': 0.0553,
 'E': 0.00071231,
 'C': 0.005555,
 'B': 0.0157,
 'E': 0.0335
)

rentabilidades = pd.Series('ACC': 0.0035323168,
 'UAA': 0.033975,
 'EOAO': -0.0016047,
 'CIA': -0.00248652,
 'BJA': -0.0075425,
 'BOEA': 0.0016429,
 'UA': 0.550,
 'EOA': 0.0512,
 'CI': 0.00157,
 'BJ': 0.0861,
 'BOE': 0.0555,
 'U': 0.0593,
 'E': 0.00231,
 'C': 0.0555,
 'B': 0.07,
 'E': 0.05
)

un_pickle = [0.00119,  0.00107,  0.0013,  0.00105,  0.00182]

【问题讨论】:

【参考方案1】:

脚本为所有变量提供了一个在-0.005&lt;y&lt;0.005 范围内的解决方案。未观察到边界的一个潜在原因是求解器未能找到解决方案。切换到disp=True 会显示求解器输出,以确保找到成功的解。

EXIT: Optimal Solution Found.

 The solution was found.

 The final value of the objective function is  0.005269679643169275
 
 ---------------------------------------------------
 Solver         :  IPOPT (v3.12)
 Solution time  :  0.011 sec
 Objective      :  0.005269679643169275
 Successful solution
 ---------------------------------------------------
[[0.00080192314638], [0.00066898310209], [0.00033248534634], [0.00031046466289], \
[0.00020163446647], [0.00025390495361], [0.004994273964], [0.0049445497412], \
[-0.00031911076974]]
Objective = 1053935.92864

要检查的另一件事是目标函数是否定义正确。

z = (np.sum(b[0]- a[0]))**2
m.Minimize(z)

此语句仅对一个值进行求和,求和之外的正方形 **2。如果它是平方误差之和,则平方通常在求和之前执行。在这种情况下,它不会改变问题结果,因为b[0]a[0] 只是一个值和一个表达式。

from gekko import GEKKO
import numpy as np
import pandas as pd
obj = 0
obj2 = 0

ponderaciones = pd.Series('ACC': 0.07645771,
 'UAA': 0.0,
 'EOAO': 0.000712,
 'CIA': 0.0055,
 'BJA': 0.01,
 'BOEA': 0.03,
 'UA': 0.110,
 'EOA': 0.0712,
 'CI': 0.00557,
 'BJ': 0.0161,
 'BOE': 0.0355,
 'U': 0.0553,
 'E': 0.00071231,
 'C': 0.005555,
 'B': 0.0157,
 'E': 0.0335
)

rentabilidades = pd.Series('ACC': 0.0035323168,
 'UAA': 0.033975,
 'EOAO': -0.0016047,
 'CIA': -0.00248652,
 'BJA': -0.0075425,
 'BOEA': 0.0016429,
 'UA': 0.550,
 'EOA': 0.0512,
 'CI': 0.00157,
 'BJ': 0.0861,
 'BOE': 0.0555,
 'U': 0.0593,
 'E': 0.00231,
 'C': 0.0555,
 'B': 0.07,
 'E': 0.05
)

un_pickle = [0.00119,  0.00107,  0.0013,  0.00105,  0.00182]

m = GEKKO(remote=False)
v0 = m.Var(0.002, -0.005, 0.005)
v1 = m.Var(0.004, -0.005, 0.005)
v2 = m.Var(0.002, -0.005, 0.005)
v3 = m.Var(0.002, -0.005, 0.005)
v4 = m.Var(0.002, -0.005, 0.005)
v5 = m.Var(0.001, -0.005, 0.005)
v6 = m.Var(0.003, -0.005, 0.005)
v7 = m.Var(-0.005, -0.005, 0.005)
v8 = m.Var(-0.002, -0.005, 0.005)
v9 = m.Var(-0.001, -0.005, 0.005)
y = []
y.append(v0)
y.append(v1)
y.append(v2)
y.append(v3)
y.append(v4)
y.append(v5)
y.append(v6)
y.append(v7)
y.append(v8)
objetivos = []
obj = 0
pq = []
p = ponderaciones[:9]
p2 = ponderaciones[9:]
r = rentabilidades[:9]
r2 = rentabilidades[9:]
for j in range(len(r2) + len(r)):
    if j < (len(r)):
        obj += p[j]/(1+y[j])*r[j]
    else:
        iterator = j - len(r)
        obj += p2[iterator]*r2[iterator]
objetivos.append(obj)
pq.append(obj)
a = np.array(objetivos)
b = un_pickle
print(b[0])
z = (np.sum(b[0]- a[0]))**2
m.Minimize(z)
m.solve(disp=True)
print(y)
print('Objective = '+str(m.options.objfcnval*1000000000/5))

【讨论】:

好点,是的,现在我得到了一个可行的解决方案,但我无法使用 scipy 甚至 excel 求解器找到相同的解决方案。我更改了函数目标,因为我缺少原始问题的括号。有一种方法可以知道 z 取什么值,在原始问题中还有很多其他 z,所以知道这些值对开始调试很有帮助。原始函数看起来像,m.Minimize(z+z1+z2+z3+z4) 目标函数也很小。也许尝试缩放目标或将求解器容差设置为较小的值,例如m.options.RTOL=1e-10m.options.OTOL=1e-10。如果求解器报告一个成功的解决方案,那么它可能是一个局部最小值。尝试不同的初始猜测。

以上是关于Gekko 不尊重变量的限制的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 gekko 变量作为数组的组件?

GEKKO:数组大小作为模型变量

GEKKO 变量实时更新

优化的输出(使用 GEKKO)为操纵变量(IMODE=6)给出零

查看不尊重约束,这是为啥呢?

如何限制 UVC 小工具的 FPS?