cvxpy中SOCP问题不符合DCP规则的排查求助
解决CVXPY中SOCP问题的DCP规则报错
问题描述
我尝试用Mosek求解一个SOCP问题,代码如下:
objective = cp.Minimize(cp.power(cp.norm(beta, 2), 2)/2 + cp.power(lambda_var, 2)/2 - beta @ y_train) # Constraints constraints = [ cp.quad_form(beta, K_1) / cp.power(rho_g, 2) <= cp.power(lambda_var, 2), cp.quad_form(beta, K_2) / cp.power(rho_g, 2) <= cp.power(lambda_var, 2) ] # Define the problem problem = cp.Problem(objective, constraints) problem.solve(solver = cp.MOSEK)
我已经用cp.psd_wrap把K矩阵包装成PSD矩阵,目标函数和约束里的项也都是凸函数或线性函数,但还是一直报不符合DCP规则的错误。报错信息如下:
DCPError: Problem does not follow DCP rules. Specifically: The following constraints are not DCP: QuadForm(var303, psd_wrap([[1.00 0.96 ... 0.94 0.91] [0.96 1.00 ... 0.92 0.85] ... [0.94 0.92 ... 1.00 0.98] [0.91 0.85 ... 0.98 1.00]])) / power(40.0, 2.0) <= power(var304, 2.0) , because the following subexpressions are not: |-- QuadForm(var303, psd_wrap([[1.00 0.96 ... 0.94 0.91] [0.96 1.00 ... 0.92 0.85] ... [0.94 0.92 ... 1.00 0.98] [0.91 0.85 ... 0.98 1.00]])) / power(40.0, 2.0) <= power(var304, 2.0) QuadForm(var303, psd_wrap([[6.61 0.37 ... 7.94 6.49] [0.37 1.93 ... 0.04 1.83] ... [7.94 0.04 ... 90.47 17.66] [6.49 1.83 ... 17.66 470.43]])) / power(40.0, 2.0) <= power(var304, 2.0) , because the following subexpressions are not: |-- QuadForm(var303, psd_wrap([[6.61 0.37 ... 7.94 6.49] [0.37 1.93 ... 0.04 1.83] ... [7.94 0.04 ... 90.47 17.66] [6.49 1.83 ... 17.66 470.43]])) / power(40.0, 2.0) <= power(var304, 2.0)
问题原因
DCP规则要求约束必须满足凸函数 ≤ 凹函数、凹函数 ≥ 凸函数,或者线性等式/不等式。你的约束左边cp.quad_form(beta, K)/rho_g²是凸函数(K为PSD矩阵),右边cp.power(lambda_var, 2)也是凸函数,凸函数 ≤ 凸函数不符合DCP规则,因此报错。
解决方法
将约束转换为SOCP的标准形式:利用二次型与范数的等价关系,cp.quad_form(beta, K) = cp.norm(cp.sqrtm(K) @ beta, 2)²,因此原约束可以改写为范数约束,此时左边是凸函数(L2范数),右边是线性函数(rho_g为正数常数,lambda_var是变量),完全符合DCP规则。
修改后的完整代码:
import cvxpy as cp # 假设beta、lambda_var、y_train、K_1、K_2、rho_g已提前定义 objective = cp.Minimize(cp.power(cp.norm(beta, 2), 2)/2 + cp.power(lambda_var, 2)/2 - beta @ y_train) # 转换后的合规约束 constraints = [ cp.norm(cp.sqrtm(K_1) @ beta, 2) <= rho_g * lambda_var, cp.norm(cp.sqrtm(K_2) @ beta, 2) <= rho_g * lambda_var ] problem = cp.Problem(objective, constraints) problem.solve(solver=cp.MOSEK)
补充说明
- 若K矩阵的PSD属性存疑,可继续使用
cp.psd_wrap(K)包裹矩阵,确保CVXPY将其识别为正定矩阵。 - 这种转换是SOCP问题的标准写法,既满足DCP规则,也能被Mosek正确识别并高效求解。
内容的提问来源于stack exchange,提问作者yocut
相关产品推荐
相关产品推荐

