2

Crossposted on Stack Overflow


I have a convex objective function and a convex constraint of the form $$\frac{y^2}{x} + z \leq 1$$ on the domain $x \geq 0$. However, I'm not sure how to encode this constraint in a way that CVXPY will accept it. It seems to be rejecting it because it can't convince itself that the constraint is convex.

Here is a simple example code:

import numpy as np
import cvxpy as cp

n = 5 x = cp.Variable(n)

xtarget = np.random.normal(0, 1, n) A = np.random.normal(0, 1, [n, n]) B = np.random.normal(0, 1, [n, n]) y = A @ x z = B @ x obj = cp.sum_squares(xtarget - x) constraints = [x>= 0, y ** 2 / x + z <= 1] prob = cp.Problem(cp.Minimize(obj), constraints) prob.solve()

This gives the error:

DCPError: Problem does not follow DCP rules. Specifically:
The following constraints are not DCP

I have tried to replace y ** 2 / x + z <= 1 with cp.multiply(y ** 2, cp.pos_inv(x)) + z <= 1 so that it know that $x$ variable is non-negative. It still gives me the DCP error.

Is there a way to reformulate the problem such that it satisfies the DCP rules?


Addendum

Thanks, Rodrigo de Azevedo, for suggesting positive semidefinite programming idea. Here is the code I ended with. I didn't know how to do this cleanly, so here is a hacky way of doing it.

import numpy as np
import cvxpy as cp

n = 5 x = cp.Variable(n, pos = True)

xtarget = np.random.normal(0, 1, n) A = np.random.normal(0, 1, [n, n]) B = np.random.normal(0, 1, [n, n]) y = A @ x z = B @ x obj = cp.sum_squares(xtarget - x) constraints = [x>= 0, y ** 2 <= 1, 1 - z >= 0] Ms = [cp.Variable([2, 2], symmetric = True) for i in range(n)] for i in range(n): constraints.append(Ms[i] >> 0) constraints.append(Ms[i][0,0] == x[i]) constraints.append(Ms[i][0,1] == y[i]) constraints.append(Ms[i][1,0] == y[i]) constraints.append(Ms[i][1,1] == 1 - z[i]) prob = cp.Problem(cp.Minimize(obj), constraints) prob.solve()

JEK
  • 47
  • 6

1 Answers1

2

Using the Schur complement and Sylvester's criterion, the given inequalities (plus the inequality $z \leq 1$) can be encapsulated in the following linear matrix inequality (LMI)

$$ \begin{bmatrix} x & y \\ y & 1 - z \end{bmatrix} \succeq 0$$

Can you now translate this to CVXPY? You might want to use PSD or >>.

  • 1
    Thank you! That’s a really neat solution! I will try it on the computer tonight and once it works, I will accept as answer. – JEK Mar 05 '23 at 17:30
  • @JEK Happy to help. If it works, please consider sharing the code – Rodrigo de Azevedo Mar 05 '23 at 17:31
  • Yup. I will try to write it up tonight when I have access to my computer. – JEK Mar 05 '23 at 18:01
  • 1
    The atom quad_over_lin in cvxpy does the job. Then you can use all SOCP solvers and are not limited to SDP-aware solvers only. And if you want to reformulate it, rather than use a ready-made function, then it will be cheaper to reformulate it directly as SOCP (although an SDP solver will likely presolve a 2x2 SDP to SOCP, but still). – Michal Adamaszek Mar 06 '23 at 07:12
  • @MichalAdamaszek That comment would make a good answer. – Rodrigo de Azevedo Mar 06 '23 at 08:20
  • @MichalAdamaszek You can now consider converting your comment into an answer – Rodrigo de Azevedo May 05 '23 at 19:58