2

In the following code snippet I intend to do the following:

(1) Multiply each element of the identity by the d optimization variable.
(2) Sum a vector of ones to a CVXPY affine expression, which is also a vector of 24 elements.
(3) Create a constraint which compares two vectors element-wise.

    import numpy as np
    import cvxpy as cp

    weights = cp.Variable(5)
    d = cp.Variable(1)
    meas = np.random.rand(8, 3)
    det = np.random.rand(24, 5)

    dm = d * np.eye(3)   # (1)
    beh = np.ones([24, 1]) + cp.reshape((dm @ meas.T).T, [24, 1])    # (2)
    constrs = [beh == det @ weights]   #(3)

My questions are:

Q1: Did I code what I wanted?

Q2: At (2), I get the following error:

/usr/lib/python3.8/site-packages/cvxpy/utilities/shape.py in sum_shapes(shapes)
     45         # Only allow broadcasting for 0D arrays or summation of scalars.
     46         if shape != t and len(squeezed(shape)) != 0 and len(squeezed(t)) != 0:
---> 47             raise ValueError(
     48                 "Cannot broadcast dimensions " +
     49                 len(shapes)*" %s" % tuple(shapes))

ValueError: Cannot broadcast dimensions  (24, 1) [24, 1]

What exactly does this mean, and how do I fix it?

Q3: When I do det @ weights, at (3), I get an Expression(AFFINE, UNKNOWN, (24,)). In the constraint, I'll compare it with beh, which I'm guessing will be an Expression(AFFINE, UNKNOWN, (24, 1)). Will this comparison also bring an issue?

cab20
  • 35
  • 1
  • 5
  • Two questions. 1. What "ones" function are you using. Is it np.ones? 2. I am not understanding how detp will work there is no variable in your code that is detp. Should it be det @ weights? – jawsem Feb 17 '20 at 14:32
  • Yes to both. I forgot to specify np.ones, and had a typo in detp. I edited the question. Thank you for pointing these out. – cab20 Feb 17 '20 at 14:41

1 Answers1

0

When I started using cvxpy, I also had some trouble making dimensions fit. In my experience, it is a good idea to use arrays with as few dimensions as possible. So if you have a 2-dimensional array where 1 of the dimensions only has length 1, see if you can reduce the dimension. (see below)

The problem in (2) is solved when you changed the brackets you use when reshaping the cvxpy expression to (24,1), like this:

beh = np.ones([24, 1]) + cp.reshape((dm @ meas.T).T, (24, 1))    # (2)

You could also avoid your problem by simply doing:

beh = 1 + cp.reshape((dm @ meas.T).T, (24, 1))    # (2)

which will do the same: add 1 to each entry of the cvxpy array.

After this is done, you will have a problem with your final line: "ValueError: Cannot broadcast dimensions (24, 1) (24,)"

This can be remedied by making beh of the dimension (24, ) too (reduce the dimension will solve your problems here, as mentioned before). The full working code would be:

import numpy as np
import cvxpy as cp
weights = cp.Variable(5)
d = cp.Variable(1)
meas = np.random.rand(8, 3)
det = np.random.rand(24, 5)

dm = d * np.eye(3)   # (1)
beh = 1 + cp.reshape((dm @ meas.T).T, (24, ))    # (2)
constrs = [beh == det @ weights]   #(3)

Hope this helps!

linx
  • 78
  • 1
  • 7