为何CVXPY判定最大化$-x^2/y$不符合DCP规则?如何解决?
问题:CVXPY求解$-x^2/y$最大化问题触发DCPError
用户编写的CVXPY代码如下:
import cvxpy as cp # Define variables x = cp.Variable(nonneg = True) y = cp.Variable(nonneg = True) # Define the objective and constraint obj = -1*cp.multiply(cp.power(x,2),cp.inv_pos(y)) objective = cp.Maximize(obj) constraint = [y <= 1, x <= 1] # Example constraint on y # Formulate the problem problem = cp.Problem(objective, constraint) # Solve the problem problem.solve()
用户疑问:$-x^2/y$难道不是凹函数吗?该如何解决这个问题?
运行代码后触发的错误信息:
--------------------------------------------------------------------------- DCPError Traceback (most recent call last) <ipython-input-194-ce998626c87f> in <cell line: 17>() 15 16 # Solve the problem ---> 17 problem.solve() 5 frames /usr/local/lib/python3.10/dist-packages/cvxpy/reductions/solvers/solving_chain.py in _reductions_for_problem_class(problem, candidates, gp, solver_opts) 113 append += (" However, the problem does follow DQCP rules. " 114 "Consider calling solve() with `qcp=True`.") ---> 115 raise DCPError( 116 "Problem does not follow DCP rules. Specifically: " + append) 117 elif gp and not problem.is_dgp(): DCPError: Problem does not follow DCP rules. Specifically: The objective is not DCP. Its following subexpressions are not: power(var243205, 2.0) @ power(var243206 + 0.1, -1.0)
解答
为什么会触发DCPError?
虽然$-x^2/y$在$x,y>0$的定义域内确实是凹函数,但CVXPY的DCP(Disciplined Convex Programming)规则不直接验证函数本身的凹凸性,而是要求表达式通过原子函数的组合规则来推导凹凸性。
你的表达式cp.multiply(cp.power(x,2), cp.inv_pos(y))是两个凸函数的乘积:
cp.power(x,2)(即$x^2$)是凸函数且非负cp.inv_pos(y)(即$1/y$)是凸函数且非负
根据DCP规则,两个凸函数相乘的操作无法被识别为合法的凸/凹表达式(DCP仅允许凸×非负凸、凹×非正凹等有限的组合形式),因此整个目标表达式不符合DCP规范,触发错误。
解决方法
方法1:使用CVXPY内置的兼容原子函数
CVXPY提供了cp.quad_over_lin(x, y)原子函数,专门表示$x^2/y$,这个函数被CVXPY识别为凸函数,完全符合DCP规则。修改后的代码如下:
import cvxpy as cp # Define variables x = cp.Variable(nonneg=True) y = cp.Variable(nonneg=True) # 使用quad_over_lin替代手动组合的表达式 obj = -cp.quad_over_lin(x, y) objective = cp.Maximize(obj) constraint = [y <= 1, x <= 1] problem = cp.Problem(objective, constraint) problem.solve() # 输出结果 print(f"x = {x.value:.4f}, y = {y.value:.4f}, 目标值 = {problem.value:.4f}")
方法2:启用QCP模式求解
错误提示中提到问题符合DQCP(Quadratically Constrained Convex Programming)规则,因此可以直接在solve()方法中添加qcp=True参数,启用QCP模式求解,无需修改原有表达式:
import cvxpy as cp # Define variables x = cp.Variable(nonneg = True) y = cp.Variable(nonneg = True) # 保留原有表达式 obj = -1*cp.multiply(cp.power(x,2),cp.inv_pos(y)) objective = cp.Maximize(obj) constraint = [y <= 1, x <= 1] problem = cp.Problem(objective, constraint) # 启用QCP模式 problem.solve(qcp=True) # 输出结果 print(f"x = {x.value:.4f}, y = {y.value:.4f}, 目标值 = {problem.value:.4f}")
两种方法对比
- 方法1使用DCP兼容的原子函数,求解效率更高,是CVXPY推荐的规范写法
- 方法2无需修改表达式,适合快速验证问题,兼容性稍弱(依赖支持QCP的求解器)
内容的提问来源于stack exchange,提问作者Mahdi Hosseini
相关产品推荐
相关产品推荐

