首页 > 解决方案 > 为什么此约束会引发 DCP 错误?

问题描述

我已经定义了一个问题,它将最小化运行泵的成本。这被定义为问题的目标。

cost_cp = cp.sum(cp.multiply(cost_,selection))
objective = cp.Minimize(cost_cp)

定义的问题是:

problem = cp.Problem(objective, constraints)

我已经使用cp.multiplycp.vec进行了计算来计算水库体积的差异,这提供了我期望的正确差异的答案。

flow_in = cp.vec(cp.multiply(input_flow_, flow_in_minutes))
flow_out = cp.vec(flow_out_)
flow_diff = flow_in - flow_out

当我使用cp.cumsum. 它可以正确工作和计算,但是当我希望为此添加约束时DCPError,我可以确定在这种计算中我哪里出错了,因为它以前对我来说没有问题。

我希望定义的约束是:

volume_constraint = volume_cp >= 300000
min_level_constraint = res_level >= min_level
max_level_constraint = res_level <= max_level

constraints = [assignment_constraint, volume_constraint, min_level_constraint, max_level_constraint]

volume_constraint作品完美。问题在于min_level_constraintand max_level_constraint

我尝试使用解决方案

problem.solve(solver=cp.CPLEX, verbose=False)  

我提供的回溯是:

DCPError                                  Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_14560/1602474026.py in <module>
     33 
     34 # Problem solve
---> 35 problem.solve(solver=cp.CPLEX, verbose=False)

~\AppData\Local\Programs\Python\Python38\lib\site-packages\cvxpy\problems\problem.py in solve(self, *args, **kwargs)
    457         else:
    458             solve_func = Problem._solve
--> 459         return solve_func(self, *args, **kwargs)
    460 
    461     @classmethod

~\AppData\Local\Programs\Python\Python38\lib\site-packages\cvxpy\problems\problem.py in _solve(self, solver, warm_start, verbose, gp, qcp, requires_grad, enforce_dpp, **kwargs)
    936                 return self.value
    937 
--> 938         data, solving_chain, inverse_data = self.get_problem_data(
    939             solver, gp, enforce_dpp, verbose)
    940 

~\AppData\Local\Programs\Python\Python38\lib\site-packages\cvxpy\problems\problem.py in get_problem_data(self, solver, gp, enforce_dpp, verbose)
    563         if key != self._cache.key:
    564             self._cache.invalidate()
--> 565             solving_chain = self._construct_chain(
    566                 solver=solver, gp=gp, enforce_dpp=enforce_dpp)
    567             self._cache.key = key

~\AppData\Local\Programs\Python\Python38\lib\site-packages\cvxpy\problems\problem.py in _construct_chain(self, solver, gp, enforce_dpp)
    789         candidate_solvers = self._find_candidate_solvers(solver=solver, gp=gp)
    790         self._sort_candidate_solvers(candidate_solvers)
--> 791         return construct_solving_chain(self, candidate_solvers, gp=gp,
    792                                        enforce_dpp=enforce_dpp)
    793 

~\AppData\Local\Programs\Python\Python38\lib\site-packages\cvxpy\reductions\solvers\solving_chain.py in construct_solving_chain(problem, candidates, gp, enforce_dpp)
    153     if len(problem.variables()) == 0:
    154         return SolvingChain(reductions=[ConstantSolver()])
--> 155     reductions = _reductions_for_problem_class(problem, candidates, gp)
    156 
    157     dpp_context = 'dcp' if not gp else 'dgp'

~\AppData\Local\Programs\Python\Python38\lib\site-packages\cvxpy\reductions\solvers\solving_chain.py in _reductions_for_problem_class(problem, candidates, gp)
     89             append += ("\nHowever, the problem does follow DQCP rules. "
     90                        "Consider calling solve() with `qcp=True`.")
---> 91         raise DCPError(
     92             "Problem does not follow DCP rules. Specifically:\n" + append)
     93     elif gp and not problem.is_dgp():

我查看了有关 CVXPY 和 Stack Overflow 的文档,但没有发现任何适合我的问题的文档。我很困惑,因为它过去对我有用。

更新

在进一步研究之后,我检查了每个变量,看看它是否is_dcp()True在符合 DCP 的情况下返回。

flow_in = cp.vec(cp.multiply(input_flow_, flow_in_minutes)) # False
flow_out = cp.vec(flow_out_) # True
flow_diff = flow_in - flow_out # False
res_level = cp.cumsum(flow_diff) * FACTOR + 2.3 # False

我假设flow_in失败,那么我的其余计算也将因此失败。

标签: pythonconstraintsmathematical-optimizationcvxpyconvex-optimization

解决方案


经过几个小时的额外审议并解决了这个问题,我能够找出原因。

正如我最初所想的那样,我的计算flow_in不是 DCP,我不完全确定或理解为什么,但我肯定会在未来的时间里自学这一点。

如果将来有人遇到类似情况,我可以将计算调整为如下所示,并且可以看到我的计算在问题与答案中的变化。

flow_in = cp.sum(cp.multiply(volume_,selection),axis=1)
flow_out = cp.vec(flow_out_) # Value in litres -> must convert to a volume
flow_diff = (flow_in - flow_out) / 1000
res_level = cp.cumsum(flow_diff) / 160.6 + 2.3

推荐阅读