【问题标题】:Why am I getting this DCPError?为什么我会收到此 DCPError?
【发布时间】:2020-02-24 04:46:49
【问题描述】:

我正在尝试使用 CVXPY 优化二元投资组合向量,使其大于基准。

import cvxpy as cp
import numpy as np

# Generate a random non-trivial quadratic program.

n = 10 # number of options

np.random.seed(1)
mu = np.random.randn(n) # expected means
var_covar = np.random.randn(n,n) # variance-covariance matrix
var_covar = var_covar.T.dot(var_covar) # cont'd
bench_cov = np.random.randn(n) # n-length vector of cov(benchmark, returns)

lamd = 0.01 # risk tolerance

# Define and solve the CVXPY problem.

x = cp.Variable(n, boolean=True)

prob = cp.Problem(cp.Maximize(mu.T@x + lamd * (cp.quad_form(x, var_covar) - (2 * bench_cov.T@x))), [cp.sum(x) == 4])

prob.solve()

我使用 CVXPY 版本 1.1.0a0(直接从 github 下载)收到此错误:

DCPError:问题不符合 DCP 规则。具体来说:

目标不是 DCP,尽管每个子表达式都是。

你试图最大化一个凸函数。

根据我的阅读,最大化凸函数非常困难,但我从一篇论文中得到了这个方程。我想我一定是做错了,因为我是二次规划和 CVXPY 的新手。

谢谢!

【问题讨论】:

  • 最大化凸函数是一个-凸问题。 CVXPY 中的非凸问题很难解决。
  • @RodrigodeAzevedo 你知道我可能会看一个不同的库吗?或者也许是一种使这个问题变得凸出的方法?
  • 不应该在 SO 上问数学问题。试试scicomp.stackexchange.com(有一个CVXPY标签)。
  • 非凸 QP 很困难,需要全局求解器(例如 Baron、Couenne、Antigone、Cplex)。还有一个有趣的重新表述为 MIP 问题(基本上形成了 KKT 条件)。

标签: python cvxpy quadratic-programming


【解决方案1】:

您的模型的问题是max x'Qx 是非凸的。由于我们有二进制变量x,我们可以使用一个技巧。

定义

y(i,j) = x(i)*x(j)

作为额外的二进制变量。然后我们可以写

sum((i,j), x(i)*Q(i,j)*x(j)) 

作为

sum((i,j), y(i,j)*Q(i,j)) 

二进制乘法y(i,j) = x(i)*x(j)可以线性化为:

 y(i,j) <= x(i)
 y(i,j) <= x(j)
 y(i,j) >= x(i)+x(j)-1

通过这种重新制定,我们有一个完全线性的模型。它是一个 MIP,因为我们有二进制变量。

我们可以在 CVXPY 中这样做:

import numpy as np
import cvxpy as cp

# Generate a random non-trivial quadratic program.

n = 10 # number of options

np.random.seed(1)
mu = np.random.randn(n) # expected means
var_covar = np.random.randn(n,n) # variance-covariance matrix
var_covar = var_covar.T.dot(var_covar) # cont'd
bench_cov = np.random.randn(n) # n-length vector of cov(benchmark, returns)

lamd = 0.01 # risk tolerance

e = np.ones((1,n))

x = cp.Variable((n,1), "x", boolean=True)
y = cp.Variable((n,n), "y", boolean=True)


prob = cp.Problem(cp.Maximize(mu.T@x + lamd * (cp.sum(cp.multiply(y,var_covar)) -2*bench_cov.T@x) ),
                  [y <= x@e, y <= (x@e).T, y >= x@e + (x@e).T - e.T@e, cp.sum(x)==4 ])

prob.solve(solver=cp.ECOS_BB)
print("status",prob.status)
print("obj",prob.value)
print("x",x.value)

这给出了结果:

status optimal
obj 4.765120794509871
x [[1.00000000e+00]
 [3.52931931e-10]
 [3.80644178e-10]
 [2.53300872e-10]
 [9.99999999e-01]
 [1.79871537e-10]
 [1.00000000e+00]
 [3.46298454e-10]
 [9.99999999e-01]
 [1.00172269e-09]]

注意事项:

  • 鼓励您使用比 ECOS_BB 更好的 MIP 求解器。对于这个模型,它给出了正确的结果,但它有点像一个玩具求解器,并且已知会在更困难的数据集上给出问题。
  • 我不了解该模型的经济学原理。我们在这里最大化风险。将您的投资决策基于此模型的结果可能并不谨慎。
  • 请注意,一些高端求解器(如 Cplex 和 Gurobi)会自动执行此重新公式化。但是 CVXPY 不允许您将非凸模型传递给求解器。

【讨论】:

  • 我很欣赏这个回复的细节——是的,自从我发布这篇文章以来,我已经意识到我的二次项是非凸的。我最终使用了您在评论中提到的全局非凸求解器之一。这是将 QP 问题转化为线性问题的一个非常有用的技巧,感谢您让我意识到这一点 :) -- 最后,模型的经济学有点复杂。我正在尝试创建一个投资组合来超越基准。 E[benchmark] 高于任何 E[portfolio],因此,如果 E[benchmark] 低于 E[portfolio],我需要最大化风险,而不是尽可能降低风险。
  • 如果您有兴趣,我很乐意将我正在关注的研究转发给您
  • 是的,我对底层论文很感兴趣。
  • @ErwinKalvelagen 这与我看到的问题相似吗? stackoverflow.com/questions/68136486/…
猜你喜欢
  • 1970-01-01
  • 2019-05-14
  • 2013-12-09
  • 2018-08-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-08
相关资源
最近更新 更多