首页 > 解决方案 > Scipy 最小化 - 创建约束以使 20 个中只有 5 个

问题描述

我在周末学习使用 scipy 最小化,并在下面遇到了这段代码。本网站的所有学分http://apmonitor.com/che263/index.php/Main/Python优化

我的问题是......有没有办法设置一个约束,将解决方案限制为在 x0 中只有 2 个非零元素?

在我的问题中,x0 是假设股票组合的权重。这些乘以各自的个股收益。我有 20 只股票可供选择,但我只想在我的最终投资组合中最多有 5 只股票(共 20 只),同时将风险降至最低。

我想要得到的可能看起来像这样:

x0 = [0, 0, 0, 0.2, 0, 0, 0, 0, 0.2, 0.2, 0.2, 0.2, 0, 0, 0, 0, 0, 0, 0, 0]

我的权重数组中只有 5 个非零值。

Ps 如果这是一个简单的问题,我很抱歉,我在空闲时间自学python。

import numpy as np
from scipy.optimize import minimize

def objective(x):
    return x[0]*x[3]*(x[0]+x[1]+x[2])+x[2]

def constraint1(x):
    return x[0]*x[1]*x[2]*x[3]-25.0

def constraint2(x):
    sum_eq = 40.0
    for i in range(4):
        sum_eq = sum_eq - x[i]**2
    return sum_eq

# initial guesses
n = 4
x0 = np.zeros(n)
x0[0] = 1.0
x0[1] = 5.0
x0[2] = 5.0
x0[3] = 1.0

# show initial objective
print('Initial Objective: ' + str(objective(x0)))

# optimize
b = (1.0,5.0)
bnds = (b, b, b, b)
con1 = {'type': 'ineq', 'fun': constraint1}
con2 = {'type': 'eq', 'fun': constraint2}
cons = ([con1,con2])
solution = minimize(objective,x0,method='SLSQP',\
                    bounds=bnds,constraints=cons)
x = solution.x

# show final objective
print('Final Objective: ' + str(objective(x)))

# print solution
print('Solution')
print('x1 = ' + str(x[0]))
print('x2 = ' + str(x[1]))
print('x3 = ' + str(x[2]))
print('x4 = ' + str(x[3]))

标签: pythonnumpyoptimizationscipy

解决方案


这是不可能的。

scipy.minimize 是关于持续优化的,并且有很强的假设,包括约束+目标的两倍可微性。在其核心中,所有这些算法都属于(一般)非线性优化NLP)领域。

这与您具有分离性质的用例相矛盾。有关比您的问题更简单的问题的含义,请参阅整数编程。

虽然投资组合问题通常是凸二次规划或二阶锥问题(与 NLP 相比这是一个限制),但人们通常使用专门的求解器,与 NLP 求解器(利用额外的假设)相比,它的性能和鲁棒性要高得多。凸性还意味着易处理性(多项式复杂性)。

但是由于析取性质,QP/SOCP 求解器在这里是不够的。你需要去:

  • 混合整数 QP / SOCP(如果问题兼容)
  • MINLP

求解器。

然后,凸性的易处理性就丢失了(析取的)!

这些求解器在 scipy 中不可用。并且少数可用的非商业求解器并不那么容易设置(尤其是在 Windows 上)。一些候选者:Bonmin(凸 MINLP;非凸情况下的启发式解决方案)或Couenne(非凸 MINLP)。OSQP可以工作,但我持怀疑态度(尤其是关于它的分支定界实现)。osqp 的好处是,安装应该很容易。

您可能会得到一些搜索基数约束优化的想法。示例:斯坦福讲座

一般凸基数问题是 (NP-) 困难的

(该链接还显示了一些现实世界中以任务为中心的启发式方法,以使问题易于处理:L1-norm)

如果您不想探索组合优化的复杂世界并且有一些耐心 + 该示例反映了您的用例,您可以对所有选择组合运行优化(在 [0,0] 中强制变量边界所有未选择的变量)并选择最佳结果。对于您的 <= 20 中的 5,这将导致 ~ 20000 次优化。


推荐阅读