CVXPY求解凸优化问题遇DCP报错:目标函数不满足DCP规则
CVXPY DCPError 问题排查与解决
问题背景
尝试求解凸优化问题,主观判断目标函数为凸函数,但运行CVXPY代码时触发报错:
DCPError Problem does not follow DCP rules. Specifically: The objective is not DCP
报错原因
CVXPY的DCP规则要求最小化问题的目标函数必须是凸函数,且所有表达式需符合原子操作的凸性组合规则。问题出在目标函数中的pp*(d/(W*cp.log(1+pp)))项:
- 对函数
f(pp) = pp / log(1+pp)(pp>0)求二阶导数,可验证其为凹函数。 - 目标函数中
we * pp*(d/(W*cp.log(1+pp)))是正系数乘以凹函数,整体为凹函数。最小化包含凹项的目标函数违反DCP规则,导致报错。
解决方法
方案1:改用非凸优化求解器
若原问题建模正确(确实需要最小化该非凸目标),可使用CVXPY支持的非凸求解器(如SLSQP、COBYLA)绕过DCP检查。这类求解器能处理非凸问题,但仅能保证找到局部最优解。
方案2:检查并修正建模逻辑
若原问题应为凸优化问题,需重新核对目标函数的推导,确认是否存在符号、项的组合错误(比如是否将凸函数误写为凹函数形式)。
修改后的代码
以下是使用SLSQP求解器的修正代码,同时添加了变量非负约束(符合功率的实际物理意义):
import cvxpy as cp import numpy as np ppMax = 1 Tmax = np.array([1.19, 1.99, 4.16, 1.98, 2.53]) d = np.array([2648000, 5552000, 4744000, 4056000, 6168000]) p = np.array([0.19952623149688797, 0.00018021843172751523, 0.0020210434604112652, 0.001602417432034276, 0.003647501823979989]) r = np.array([8574212.020483451, 6619470.077787987, 7521159.373986546, 7135440.631765847, 6832684.423897811]) c = np.array([430000000.0, 700000000.0, 400000000.0, 220000000.0, 170000000.0]) fc = np.array([40000000000, 40000000000, 40000000000, 40000000000, 40000000000]) ff = np.array([4000000000, 4000000000, 4000000000, 4000000000, 4000000000]) W = np.array([0.7, 0.2, 0.3, 0.7, 0.5]) wt = np.array([0.609, 0.04000000000000001, 0.255, 0.308, 0.43]) we = np.array([4.336742687028045, 10.647756980938421, 8.263103073749088, 7.675258157093112, 6.322105707432189]) # 添加非负约束,避免log(1+pp)出现无意义输入 pp = cp.Variable(len(Tmax), nonneg=True) cons = [ cp.sum(pp) <= ppMax, d/r + c/fc + d/(W*cp.log(1+pp)) <= Tmax ] objective = cp.Minimize( wt*(2*d/r + c/ff + c/fc + d/(W*cp.log(1+pp))) + we*(2*p*(d/r) + pp*(d/(W*cp.log(1+pp)))) ) prob = cp.Problem(objective, cons) # 使用SLSQP非凸求解器,开启verbose查看迭代过程 prob.solve(solver=cp.SLSQP, verbose=True) print(prob.value, pp.value)
注意事项
- 非凸求解器无法保证全局最优解,若需全局最优,需使用专门的全局优化工具(如Pyomo搭配全局求解器)。
- 变量非负约束是必要的,既符合物理意义,也避免
log(1+pp)出现负数输入导致的计算错误。
内容的提问来源于stack exchange,提问作者Arash hosseini Rezaei
相关产品推荐
相关产品推荐

