1

我是 cvxpy 包的新手。我正在尝试使用它来完成以下博客中的示例:

https://towardsdatascience.com/integer-programming-in-python-1cbdfa240df2

我们正在尝试优化发送给客户的营销渠道组合。

最近对 cvxpy 包进行了一些更改,当我尝试运行 sum_entries 步骤时出现以下错误(在最新版本中已更改为 cvxpy.sum)

我认为问题出在“选择”和“变形金刚”的维度不兼容,但我对 cvxpy 包还不够熟悉。非常感谢任何提示。

Code:

test_probs.shape

(200, 8)



Code:

# selection = cvxpy.Bool(*test_probs.shape) # syntax changed in latest version

selection = cvxpy.Variable(*test_probs.shape, boolean=True)



# constraints

# Constant matrix that counts how many of each 
# material we sent to each customer

TRANSFORMER = np.array([[1,0,0],
                        [0,1,0],
                        [0,0,1],
                        [1,1,0],
                        [1,0,1],
                        [0,1,1],
                        [1,1,1],
                        [0,0,0]])


# can't send customer more promotion than there is supply

# note: sum_entries changed to sum in latest cvxpy version

supply_constraint = cvxpy.sum(selection * TRANSFORMER, axis=0) <= supply


Error:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-47-f2ebf41a00af> in <module>()
     18 # note: sum_entries changed to sum in latest cvxpy version
     19 
---> 20 supply_constraint = cvxpy.sum(selection * TRANSFORMER, axis=0) <= supply
     21 
     22 

~/anaconda2/envs/py36/lib/python3.6/site-packages/cvxpy/expressions/expression.py in cast_op(self, other)
     47         """
     48         other = self.cast_to_const(other)
---> 49         return binary_op(self, other)
     50     return cast_op
     51 

~/anaconda2/envs/py36/lib/python3.6/site-packages/cvxpy/expressions/expression.py in __mul__(self, other)
    385             return cvxtypes.multiply_expr()(self, other)
    386         elif self.is_constant() or other.is_constant():
--> 387             return cvxtypes.mul_expr()(self, other)
    388         else:
    389             warnings.warn("Forming a nonconvex expression.")

~/anaconda2/envs/py36/lib/python3.6/site-packages/cvxpy/atoms/affine/binary_operators.py in __init__(self, lh_exp, rh_exp)
     41 
     42     def __init__(self, lh_exp, rh_exp):
---> 43         super(BinaryOperator, self).__init__(lh_exp, rh_exp)
     44 
     45     def name(self):

~/anaconda2/envs/py36/lib/python3.6/site-packages/cvxpy/atoms/atom.py in __init__(self, *args)
     42         self.args = [Atom.cast_to_const(arg) for arg in args]
     43         self.validate_arguments()
---> 44         self._shape = self.shape_from_args()
     45         if len(self._shape) > 2:
     46             raise ValueError("Atoms must be at most 2D.")

~/anaconda2/envs/py36/lib/python3.6/site-packages/cvxpy/atoms/affine/binary_operators.py in shape_from_args(self)
    107         """Returns the (row, col) shape of the expression.
    108         """
--> 109         return u.shape.mul_shapes(self.args[0].shape, self.args[1].shape)
    110 
    111     def is_atom_convex(self):

~/anaconda2/envs/py36/lib/python3.6/site-packages/cvxpy/utilities/shape.py in mul_shapes(lh_shape, rh_shape)
    140     lh_old = lh_shape
    141     rh_old = rh_shape
--> 142     lh_shape, rh_shape, shape = mul_shapes_promote(lh_shape, rh_shape)
    143     if lh_shape != lh_old:
    144         shape = shape[1:]

~/anaconda2/envs/py36/lib/python3.6/site-packages/cvxpy/utilities/shape.py in mul_shapes_promote(lh_shape, rh_shape)
    107     if lh_mat_shape[1] != rh_mat_shape[0]:
    108         raise ValueError("Incompatible dimensions %s %s" % (
--> 109             lh_shape, rh_shape))
    110     if lh_shape[:-2] != rh_shape[:-2]:
    111         raise ValueError("Incompatible dimensions %s %s" % (

ValueError: Incompatible dimensions (1, 200) (8, 3)

更新:

我尝试按照下面评论中的建议更改选择形状。

代码:

selection = cvxpy.Variable(test_probs.shape, boolean=True)

现在,当我运行下面代码的 supply_constraint 部分时,我得到了新的错误。

代码:

# constraints

# Constant matrix that counts how many of each 
# material we sent to each customer

TRANSFORMER = np.array([[1,0,0],
                        [0,1,0],
                        [0,0,1],
                        [1,1,0],
                        [1,0,1],
                        [0,1,1],
                        [1,1,1],
                        [0,0,0]])


# can't send customer more promotion than there is supply

# note: sum_entries changed to sum in latest cvxpy version

supply_constraint = cvxpy.sum(selection * TRANSFORMER, axis=0) <= supply

错误:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-10-6eb7a55ea896> in <module>()
     18 # note: sum_entries changed to sum in latest cvxpy version
     19 
---> 20 supply_constraint = cvxpy.sum(selection * TRANSFORMER, axis=0) <= supply
     21 
     22 

~/anaconda2/envs/py36/lib/python3.6/site-packages/cvxpy/expressions/expression.py in cast_op(self, other)
     47         """
     48         other = self.cast_to_const(other)
---> 49         return binary_op(self, other)
     50     return cast_op
     51 

~/anaconda2/envs/py36/lib/python3.6/site-packages/cvxpy/expressions/expression.py in __le__(self, other)
    482         """NonPos : Creates an inequality constraint.
    483         """
--> 484         return NonPos(self - other)
    485 
    486     def __lt__(self, other):

~/anaconda2/envs/py36/lib/python3.6/site-packages/cvxpy/expressions/expression.py in cast_op(self, other)
     47         """
     48         other = self.cast_to_const(other)
---> 49         return binary_op(self, other)
     50     return cast_op
     51 

~/anaconda2/envs/py36/lib/python3.6/site-packages/cvxpy/expressions/expression.py in __sub__(self, other)
    370         """Expression : The difference of two expressions.
    371         """
--> 372         return self + -other
    373 
    374     @_cast_other

~/anaconda2/envs/py36/lib/python3.6/site-packages/cvxpy/expressions/expression.py in cast_op(self, other)
     47         """
     48         other = self.cast_to_const(other)
---> 49         return binary_op(self, other)
     50     return cast_op
     51 

~/anaconda2/envs/py36/lib/python3.6/site-packages/cvxpy/expressions/expression.py in __add__(self, other)
    358         """Expression : Sum two expressions.
    359         """
--> 360         return cvxtypes.add_expr()([self, other])
    361 
    362     @_cast_other

~/anaconda2/envs/py36/lib/python3.6/site-packages/cvxpy/atoms/affine/add_expr.py in __init__(self, arg_groups)
     34         # For efficiency group args as sums.
     35         self._arg_groups = arg_groups
---> 36         super(AddExpression, self).__init__(*arg_groups)
     37         self.args = []
     38         for group in arg_groups:

~/anaconda2/envs/py36/lib/python3.6/site-packages/cvxpy/atoms/atom.py in __init__(self, *args)
     42         self.args = [Atom.cast_to_const(arg) for arg in args]
     43         self.validate_arguments()
---> 44         self._shape = self.shape_from_args()
     45         if len(self._shape) > 2:
     46             raise ValueError("Atoms must be at most 2D.")

~/anaconda2/envs/py36/lib/python3.6/site-packages/cvxpy/atoms/affine/add_expr.py in shape_from_args(self)
     42         """Returns the (row, col) shape of the expression.
     43         """
---> 44         return u.shape.sum_shapes([arg.shape for arg in self.args])
     45 
     46     def expand_args(self, expr):

~/anaconda2/envs/py36/lib/python3.6/site-packages/cvxpy/utilities/shape.py in sum_shapes(shapes)
     50             raise ValueError(
     51                 "Cannot broadcast dimensions " +
---> 52                 len(shapes)*" %s" % tuple(shapes))
     53 
     54         longer = shape if len(shape) >= len(t) else t

ValueError: Cannot broadcast dimensions  (3,) (1, 3)
4

1 回答 1

1

selection创建变量时,您的问题正在发生。您正在将形状元组解压缩为多个参数。第一个参数Variable应该是一个形状。所以正确的构造是:

selection = cvxpy.Variable(test_probs.shape, boolean=True)

您可以通过检查 shape 属性来验证这是否正确:

selection.shape

现在应该给出:

(200, 8)
于 2018-09-18T05:42:52.047 回答