【问题标题】:How to construct a SOCP problem and solve using cvxpy and cvxpylayers如何构建 SOCP 问题并使用 cvxpy 和 cvxpylayers 解决
【发布时间】:2021-03-21 10:51:02
【问题描述】:

我正在尝试使用 cvxpy 解决 SOCP 问题并将其集成到 cvxpylayers。我正在查看this SOCP 问题(问题 11)(here 是 scihub 链接,以防您无法访问),这里是问题的 sn-p(注意min (p-t) 来自使用上面链接中的表达式 8 改编的问题 4):

转到 ---> 编辑 2

我查看了this 示例,但仍然卡住,无法解决问题。这是我尝试的示例代码:

import cvxpy as cp
import numpy as np

N = 5

Q_sqrt = cp.Parameter((N, N))
x = cp.Variable(N)

z = []
zero = []
for n in range(N):
    z.append((Q_sqrt @ x)[n])
    zero.append(cp.Constant(0))
    
p = cp.sqrt(cp.sum_squares(Q_sqrt @ x)/N) # based on expression 8
t = cp.sqrt(cp.min(x * (Q_sqrt @ x)))     # based on expression 8

objective = cp.Minimize(p - t)            # based on expression 8

constraint_soc1 = [cp.SOC(z[n], (Q_sqrt @ x)[n]) for n in range(N)]
constraint_soc2 = [cp.SOC(cp.quad_over_lin(t, z[n]), x[n]) for n in range(N)]
constraint_soc3 = [cp.SOC(z[n], zero[n]) for n in range(N)]
constraint_soc4 = [cp.SOC(x[n], zero[n]) for n in range(N)]

constraint_other = [cp.sum_squares(Q_sqrt @ x) <= N * (p ** 2),
                    cp.sum(x) == 1, p >= 0, t >= 0]

constraint_all = constraint_other + constraint_soc1 + constraint_soc2 + constraint_soc3 + constraint_soc4

matrix = np.random.random((N, N))
Q_sqrt.value = matrix.T @ matrix # to make positive definite

prob = cp.Problem(objective, constraint_all)

prob.solve()
print("status:", prob.status)
print("optimal value", prob.value)

请注意,我使用 cp.sum_squares(Q_sqrt @ x) 语法来确保它不仅符合 DCP,而且也符合 DPP(请参阅 Section 4.1)。

首先,我注意到我的p = cp.sqrt(cp.sum_squares(Q_sqrt @ x)/N) 部分目标(表达式 8 的第一项)不是 DCP,并且不知道如何解决它。

另外,有人告诉我,这个 x.T @ Q @ x &lt;= N * p**2 约束需要使用 cp.quad_over_lin 重新制定,但是,如上所述,我要求它也遵守 DPP 规则(对于 cvxpylayers),因此我不确定如何将cp.sum_squares(Q_sqrt @ x) &lt;= N * (p ** 2) 更改为关注cp.quad_over_lin

最后,我确信我的代码的其他部分也错误地实现了。非常感谢您对此问题的任何帮助!

编辑 1:请注意,最终解决方案不必调用 cvxpylayers,而只需符合 DPP,以便之后可以与 cvxpylayers 集成。

__________________________________________________________________________

编辑 2:我现在意识到这可能是一个多变量问题,在给定变量 x,z,p,t 的情况下最小化 p - t。我不知道为什么我没有早点想到这一点。

鉴于上面的sn-p问题,我最近的尝试如下:

import cvxpy as cp
import numpy as np

N = 5

Q_sqrt = cp.Parameter((N, N))
Q = cp.Parameter((N, N))

x = cp.Variable(N)
z = cp.Variable(N)
p = cp.Variable()
t = cp.Variable()

objective = cp.Minimize(p - t)

constraint_soc = [z == Q @ x, x.value * z >= t ** 2, z >= 0, x >= 0]

constraint_other = [cp.quad_over_lin(Q_sqrt @ x, N) <= p ** 2, cp.sum(x) == 1, p >= 0, t >= 0]

constraint_all = constraint_other + constraint_soc

matrix = np.random.random((N, N))
a_matrix = matrix.T @ matrix
Q.value = a_matrix
Q_sqrt.value = np.sqrt(a_matrix)

prob = cp.Problem(objective, constraint_all)

prob.solve(verbose=True)
print("status:", prob.status)
print("optimal value", prob.value)

但是,我仍然收到错误:

DCPError:问题不遵循 DCP 规则。具体来说: 以下约束不是 DCP: quad_over_lin(param7788 @ var7790, 5.0)

对于这个x.T @ Q @ x &lt;= N * p**2 约束(我的尝试:cp.quad_over_lin(Q_sqrt @ x, N) &lt;= p ** 2)。

除了上面提到的问题也是SOCP,所以我在constraint_soc中的约束可能是错误的,但我不确定如何根据this循环/分配变量。

编辑 3:在 ErlingMOSEK 对约束提出建议后,我将约束从 cp.quad_over_lin(Q_sqrt @ x, N) &lt;= p ** 2 更改为 cp.quad_over_lin(Q_sqrt @ x, p) &lt;= N * p,但它现在可以运行了,

出现新错误

求解器“ECOS”失败。尝试其他求解器,或使用 verbose=True 求解以了解更多信息。

我认为这是由于问题是 SOCP(我的第二个问题),我不确定如何仅基于 this 示例构建 SOCP。

EDIT 4:使用 EDIT 2/3 和 Erling 的答案以及 Erling 建议的不同求解器,问题就解决了。注意我使用了XPRESS 求解器。

【问题讨论】:

    标签: portfolio cvxpy convex-optimization cvxopt


    【解决方案1】:

    你应该改变

    x.T@Q@x

    (x.T@Q@x)/p

    假设 p>=0。

    顺便说一句,如果您想了解更多关于如何将其表述为 SOCP 的信息,请咨询the Mosek modelling cookbok

    【讨论】:

    • 嗨,根据您的建议,通过将我的约束更改为看起来像 cp.quad_over_lin(Q_sqrt @ x, p)
    • 你为什么不试试像 www.mosek.com 这样的优化器。我认为可以说 Mosek 比 Ecos 更强大。
    • 嗯,mosek 已经付钱了,对不起,我买不起
    • 它是免费的学术研究。无论如何,祝你好运。
    • 我不完全确定,但我觉得我的问题在于我构建表达式/问题的方式与 SOCP 不正确,我无法让它采用与此示例类似的格式@ 987654322@
    猜你喜欢
    • 1970-01-01
    • 2020-08-31
    • 2020-09-07
    • 1970-01-01
    • 1970-01-01
    • 2020-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多