【问题标题】:Gekko is not respecting the restrictions of the variablesGekko 不尊重变量的限制
【发布时间】: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]

【问题讨论】:

    标签: python pandas gekko


    【解决方案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。如果求解器报告一个成功的解决方案,那么它可能是一个局部最小值。尝试不同的初始猜测。
    猜你喜欢
    • 1970-01-01
    • 2019-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多