Only scalar quadratic forms can be specified in CVX toolbox

Here is my code:

cvx_begin

variable W(N,I) complex

maximize(a1’Wa1)

subject to

trace(W’*W) <= P;

cvx_end

The error says “Only scalar quadratic forms can be specified in CVX” and it happens at this line “trace(W’*W) <= P;”. I know W is a matrix and this makes this error happens, but i have no good idea how to replace it by a simple and correct code. Do i have to extract each column W(:,l) of W and use “for loop” to sum the W(:,l)'*W(:,l) together?

I will presume you actually mean trace(W'*W). Otherwise, W*W is not conformal unless J = N. Or if J does equal N, and you actually do mean trace(W*W), I will assume that W is hermitian, otherwise I believe the constraint is non-convex.

trace(W'*W) = square_pos(norm(W,'fro'))

But it is numerically better not to square, so use the constraint
norm(W,'fro') <= sqrt(P)

Yes, it really works. In my simulation, W is a complex matrix with dimension N*J and N is not equal to J, so only W’*W is well-defined. I have another question. I want to use diag(W’*W) in cvx, so how to write it as a compact form? (since W’W is a JJ matrix, and diag is to extract all the diagonal elements of W’*W and put it as a column vector)

I now see that you did have W'*W in your original post.

As for diag(W'*W), that can be formulated as
square_pos(norms(W',2,2))
or
square_pos(norms(W))'
+++++++++++++++
help norms

norms Computation of multiple vector norms.
norms( X ) provides a means to compute the norms of multiple vectors
packed into a matrix or N-D array. This is useful for performing
max-of-norms or sum-of-norms calculations.

All of the vector norms, including the false "-inf" norm, supported
by NORM() have been implemented in the norms() command.
  norms(X,P)           = sum(abs(X).^P).^(1/P)
  norms(X)             = norms(X,2).
  norms(X,inf)         = max(abs(X)).
  norms(X,-inf)        = min(abs(X)).
If X is a vector, these computations are completely identical to
their NORM equivalents. If X is a matrix, a row vector is returned
of the norms of each column of X. If X is an N-D matrix, the norms
are computed along the first non-singleton dimension.

norms( X, [], DIM ) or norms( X, 2, DIM ) computes Euclidean norms
along the dimension DIM. norms( X, P, DIM ) computes its norms
along the dimension DIM.

Disciplined convex programming information:
    norms is convex, except when P<1, so an error will result if these
    non-convex "norms" are used within CVX expressions. norms is
    nonmonotonic, so its input must be affine.

Thanks! I have tried norms(W), it really gives me a row vector which is indeed the norm-2 of each column of W. But i test the square_pos function in Matlab (without cvx), for example, square_pos(b). It is not the square of each element in b. Let me show your my test code and result
截图20240726042128

I also test this square_pos function in cvx (I set a breakpoint when my codes run into cvx), it still gives me the same answer. Here is the result

So i am wondering whether square_pos(norms(W))’ will return the same result as diag(W’*W)

The variable name is “a”, not “b”, sorry bro.

My guess is that you have the square from the Signal Processing Toolbox installed, and that is getting called by CVX’s square_pos instead of CVX’s square (see 2nd to last paragraph below for explanation).

On my machine,
which -all square_pos
C:\cvx_2.2.2\functions\square_pos.m
C:\cvx_2.2.2\functions@cvx\square_pos.m % cvx method

The first of these is supposed to be called when called with a numeric argument, whether or not interspersed between other CVX statements. You can look at the source code and see that it is basically returning square( max( x, 0 ) ), which would explain your results if the “wrong” square is being called.

The second of these is called for CVX expression (or CVX variable) argument. This does not use square, and perhaps is doing the “correct” thing for CVX, despite your having a non-CVX square. The code I suggested in my preceding post would be using this version of square_pos, because its argument is a CVX expression.

I use “help square_pos”, it returns this thing,


it is max( x, 0 ).^2.
Besides, i use “which” to search the position of the square_pos function, it returns this thing

On the other hand, i use “help square”, it says this function is introduced into the Signal Processing Toolbox, and this “square function” generates a square wave.

So do i need to remove the Signal Processing Toolbox to make the square_pos work properly?

i think, but am not 100% sure, square_pos when applied to a CVX expression or variable argument will work correctly.

To get square_pos to work correctly when applied to a numeric argument, you could change the line
y = square( max( x, 0 ) );
to
y = max(x,0).^2;
in
cvx\functions\square_pos.m

It really works after i replace this code y = square( max( x, 0 ) ); by y = max(x,0).^2;. Thank you very much!