【问题标题】:using GEKKO to optimize with a large number of variables, bounds and constraints使用 GEKKO 对大量变量、边界和约束进行优化
【发布时间】:2020-04-12 14:43:39
【问题描述】:

我很想用 GEKKO 解决优化问题。最初的问题是一个线性目标函数,其中包含数千个变量、约束(其中一些是非线性的)和边界。有人建议我使用 GEKKO,由于我不完全理解它的机制,所以在实现它时遇到了一些问题。我不断收到object of type 'int' has no len() 错误。我已经简化了这个问题,所以现在它只有 20 个变量,并且没有任何限制,但必须遵守 10 个界限。通过这种方式,我想我可以隔离并确定错误的来源。代码如下:

import pandas as pd
import numpy as np
import copy as cp
from gekko import GEKKO  
from scipy.optimize import minimize

df_uni = pd.read_csv(r'D:\US\IIT\lectures_textbooks\QIS\week_4\universe_sets.csv')
df_uni["begin_wt"]=np.zeros(10)

#df_holding=df_uni
df_holding=cp.deepcopy(df_uni)

x_holding=np.array([0.1,0.25,0.2,0.2,0.05,0.05,0.1,0.15,-0.05,-0.05])

df_holding["begin_wt"]=x_holding

df_holding.loc[df_holding['begin_wt'] >0, "up_limit"] = df_holding['begin_wt']
df_holding.loc[df_holding['begin_wt'] <0, "up_limit"] = 0

Alpha_pickup=3
df_holding.loc[df_holding['begin_wt'] >0, "Alpha"] = df_holding['Alpha']+Alpha_pickup
df_holding.loc[df_holding['begin_wt'] <0, "Alpha"] = df_holding['Alpha']-Alpha_pickup


df_holding.loc[df_holding['begin_wt'] >0, "low_limit"] = 0
df_holding.loc[df_holding['begin_wt'] <0,"low_limit"]=df_holding['begin_wt']


df_holding=df_holding.drop("begin_w",axis=1)
df_uni=df_uni.drop("begin_w",axis=1)

sect_offset=0.1
lncap_offset=0.1

sect1=sum(df_uni.loc[df_holding['Sector_1'] ==1]['ben_wt'])
sect2=sum(df_uni.loc[df_holding['Sector_2'] ==1]['ben_wt'])

lncap1=sum(df_uni.loc[df_holding['Sector_1'] ==1]['lncap'])
lncap2=sum(df_uni.loc[df_holding['Sector_2'] ==1]['lncap'])


list_uni_alpha=list(df_uni['Alpha'])
list_holding_alpha=list(df_holding['Alpha'])
bind_list_alpha=list_uni_alpha+list_holding_alpha

#x=[1 for i in range(20)]

def objective(x):
    l=0
    sum_of_Alpha=0
    for i in bind_list_alpha:
        sum_of_Alpha=sum_of_Alpha+x[l]*i
        print(sum_of_Alpha)
        l=l+1
    return sum_of_Alpha
# constraints always writing them in terms of f(x)>0
# consolidated weights are bound 
# security offsets
uni_begin=list(df_uni['begin_wt'])
holding_begin=list(df_holding['begin_wt'])
#initial guess
ig=cp.deepcopy(uni_begin+holding_begin)

m=GEKKO()
x = m.Array(m.Var,(20)) 
x_holding=x[10:20]
i=0
#bounds
for xi in x_holding:

    xi.value = x_holding[i]
    xi.lower = df_holding['low_limit'][i]
    xi.upper = df_holding['up_limit'][i]
    i = i + 1

m.Obj(objective(x))
m.solve()
print(x)

请原谅我包含了似乎不相关的代码块。但是为了给那些熟悉投资组合构建的人提供背景信息,我实际上是在尝试构建一个股票组合。 obejctve 函数是股票 alpha 的线性组合。 “持有”是指您当前持有的股票,而“宇宙”是您可以投资的大量股票。我正在进行主动管理,因此我倾向于增持我认为前景良好的股票并减持那些prosepct 我不认为是好的。但我当然不希望我的投资组合看起来与基准有很大不同,因为这会使投资组合承担很多系统性风险。因此,您将在代码末尾看到这些约束。我一直在寻找可以适应以 aX=b 形式编写的约束的优化器,其中 a 和 b 都是类似数组的,而 X 是矩阵。但就目前而言,我认为这个特殊的优化器对我也一样好!

谢谢!

【问题讨论】:

    标签: optimization mathematical-optimization portfolio gekko


    【解决方案1】:

    您可能对xi.value = x_holding[i] 行有疑问,其中gekko 需要一个数字的初始猜测值,而不是gekko 变量。这是您问题的简化版本:

    from gekko import GEKKO 
    import numpy as np
    
    def objective(x):
        return m.sum(x)
    
    m=GEKKO()
    x = m.Array(m.Var,(20)) 
    for i,xi in enumerate(x[0:10]):
        xi.value = 0.5
        xi.lower = 0
        xi.upper = i
    for i,xi in enumerate(x[10:]):
        xi.value = 0.5
        xi.lower = 0
        xi.upper = i
    
    m.Maximize(objective(x))
    m.solve()
    print(x)
    

    这给出了一个解决方案[0,1,...,8,9,0,1,...,8,9],因为所有变量都达到了m.Maximize 的上限。他们都用m.Minimize 降到最低。我同意另一个答案,即使用具有稀疏矩阵的 m.axbm.qobj 函数来解决您的投资组合优化问题会更有效,尤其是对于大规模问题。

    【讨论】:

    • 谢谢!我不明白我初始化猜测的方式是如何错误的。我从这里的另一个线程复制了您的演示代码stackoverflow.com/questions/52944970/… 我还注意到,在您刚刚提供的这个回复中,您甚至没有初始化猜测。最后,我再次花了一些时间浏览了 gekko 网站上提供的所有示例,但找不到具有大量非线性和线性类型约束的示例。你能把我推向正确的方向吗?
    • 在使用xi.value = 0.5 创建变量后初始化x[i] 的猜测。您还可以在声明变量时使用可选参数设置value = 0.5 进行初始化。这里还有其他示例:github.com/BYU-PRISM/GEKKO/tree/master/examples 尽管大多数问题都是示例,而不是像 github.com/BYU-PRISM/USTAR-Artificial-Liftgithub.com/BYU-PRISM/hale-trajectory 这样具有 10,000 多个变量和非线性方程的完整问题。
    • 谢谢!我正在查看您在此处发布的三个链接。
    • 您愿意在这里展示他们试图解决的优化问题吗? github.com/BYU-PRISM/GEKKO/tree/master/examples 当我试图通过查看这些示例中的任何一个来了解 GEKKO 的工作原理时,我发现没有任何关于它试图解决的优化问题的解释或陈述。有没有一本书可以很容易地找到这些优化?再次感谢您!
    • 其中许多都在apmonitor.com/do 的动态优化课程或apmonitor.com/wiki 的APMonitor 文档中
    【解决方案2】:

    Gekko 有functions to load dense or sparse matrices for linear programming problems 的形式:

    min c x
    s.t. A1 x = b1
         A2 x < b2 
    

    如果你有一个非常大规模的问题,矩阵中有很多零,那么稀疏形式可能是最有效的。以下是您编写模型方程的方式:

    from gekko import GEKKO
    m = GEKKO()
    x1 = m.Var(lb=0, ub=5) # Product 1
    x2 = m.Var(lb=0, ub=4) # Product 2
    m.Maximize(100*x1+125*x2) # Profit function
    m.Equation(3*x1+6*x2<=30) # Units of A
    m.Equation(8*x1+4*x2<=44) # Units of B
    m.solve(disp=False)
    p1 = x1.value[0]; p2 = x2.value[0]
    print ('Product 1 (x1): ' + str(p1))
    print ('Product 2 (x2): ' + str(p2))
    print ('Profit        : ' + str(100*p1+125*p2))
    

    如果你想使用 Gekko 内置的线性方程和二次目标模型,密集矩阵形式是:

    from gekko import GEKKO
    m = GEKKO(remote=False)
    c = [100, 125]
    A = [[3, 6], [8, 4]]
    b = [30, 44]
    x = m.qobj(c,otype='max')
    m.axb(A,b,x=x,etype='<')
    x[0].lower=0; x[0].upper=5
    x[1].lower=0; x[1].upper=4
    m.options.solver = 1
    m.solve(disp=True)
    print ('Product 1 (x1): ' + str(x[0].value[0]))
    print ('Product 2 (x2): ' + str(x[1].value[0]))
    print ('Profit        : ' + str(m.options.objfcnval))
    

    在稀疏矩阵形式中是:

    # solve with GEKKO and sparse matrices
    import numpy as np
    from gekko import GEKKO
    m = GEKKO(remote=False)
    # [[row indices],[column indices],[values]]
    A_sparse = [[1,1,2,2],[1,2,1,2],[3,6,8,4]]
    # [[row indices],[values]]
    b_sparse = [[1,2],[30,44]]
    x = m.axb(A_sparse,b_sparse,etype='<',sparse=True)
    # [[row indices],[values]]
    c_sparse = [[1,2],[100,125]]
    m.qobj(c_sparse,x=x,otype='max',sparse=True)
    x[0].lower=0; x[0].upper=5
    x[1].lower=0; x[1].upper=4
    m.solve(disp=True)
    print(m.options.OBJFCNVAL)
    print('x: ' + str(x))
    

    sparse matrices[rows,columns,values] 以坐标列表 (COO) 形式存储。我更喜欢压缩稀疏行 (CSR) 形式的矩阵,但如果问题不是很大并且接近计算机的内存限制,COO 是可以的。如果您的问题是线性的,您可能还想查看求解器 CPLEX、Gurobi 或 Xpress Mosel,因为这些是专用的线性求解器,而 Gekko 使用混合整数非线性规划求解器。他们应该给出相同的答案,但混合整数线性规划求解器会更快。

    【讨论】:

    • 谢谢!但我真正的问题是一个线性目标函数和数千个线性类型和非线性类型的约束,这就是为什么我想知道是否有一种方法可以同时使用 m.Equation 和 m.axb 的格式,一种用于非线性另一个是线性的?
    • 是的,您可以将 m.axb m.qobj 模型包含在其他方程和目标函数中。
    • @John Hedengren 非常感谢您的回复!你是说我实际上可以把它们混合起来。我要试一试。尽管似乎没有那么多非线性优化包适合现实世界的投资组合构建,但我真的很惊讶。我刚刚和我的主管谈过,他告诉我他曾经用 SAS 或 C++ 或 Matlab 做任何事情。顺便说一句,当我说现实世界的构建时,我的意思是他们倾向于构建一个试图超越基准的股票投资组合的方式。
    • 非线性优化有些独特。许多人使用线性模型,因为它们对于大规模问题的速度要快得多。 Gekko 的独特之处之一是能够将线性/非线性与时间序列经验或基于基础的方程混合。
    猜你喜欢
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    • 2021-03-11
    • 2022-10-13
    • 2023-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多