Here are some small examples of convex objectives (under minimization) one would expect to work.
Objective | CVXPY code | Result | Notes |
---|---|---|---|
xTx | x.T@x | DCP error | print shows minimize x@x, i.e. transpose is dropped |
xTx | x@x | DCP error | |
xTx | cp.sum_squares(x) | transformed into quad_over_lin(x, 1.0) | |
xTQx | x.T@Q@x | transformed into QuadForm(x,Q) | |
y:=x−pxTQy | y=x-p x.T@Q@y | DCP error | |
xTQx−xTQp | x.T@Q@x - x.T@Q@p | first term transformed into QuadForm(x,Q) |
Not everything makes sense to me. I am not sure why x.T@x is not properly recognized, but x.T@Q@x is.
import cvxpy as cp import numpy as np n = 5 x = cp.Variable(n, "x", nonneg=True) Q = np.eye(n) p = np.ones(n) obj = x.T @ x # not DCP ??? Print says x @ x #obj = x @ x # not DCP #obj = cp.sum_squares(x) # transformed into quad_over_lin(x, 1.0) #obj = x.T @ Q @ x # transformed into QuadForm(x,Q) y = x-p #obj = x.T @ Q @ y # not DCP #obj = x.T @ Q @ x - x.T @ Q @ p # accepted prob = cp.Problem(cp.Minimize(obj), [sum(x)==1]) print(prob) result = prob.solve(verbose=True)
We can use: x = cp.Variable((n,1), "x", nonneg=True). This would generate an (n×1) matrix. The printed model now shows the correct objective (with the transpose): minimize x.T @ x. But still, we are getting:
DCPError: Problem does not follow DCP rules. Specifically:The objective is not DCP. Its following subexpressions are not:x.T @ x
I suspect this is interpreted as xTy, i.e., as two possibly different vectors. Just a guess. Of course, the workarounds are obvious: use cp.sum_squares(x), or use xTIx. I think, not being able to recognize xTx as convex, can be classified as a bug.
I think the rule is that in DCP you are not allowed to multiply two variables together. You are right that x^Tx is just a quadform with an identity matrix as Q. Maybe this particular case could be added to be DCP, but I am afraid users are going to request many other similar "evidently" convex operations.
ReplyDelete