我正在尝试使用CVXPY对图形着色问题的约束进行编码。我对混合整数编程(MIP)还是很陌生,并且在指定约束时遇到了一些困难。我有输入数据,例如下面的“边”列表。列表中的每个元组都是从一个节点开始到另一节点结束的边。例如,第一条边开始于节点“ 0”,结束于节点“ 1”。
我要指定的约束是:
每个节点只能有一种颜色。
共享一条边的顶点应具有不同的颜色。
每个节点必须至少具有一种颜色。
目标函数是所用颜色的数量。
对于选择变量,我想指定每个节点采用的颜色。
我正在使用colors
数组乘以选择变量,然后对每个节点求和,以选择节点的颜色并指定每个节点只能具有一种颜色。
我在下面收到错误消息。我可以正确构造选择变量吗?
这似乎是很多工作,有人看到一种更简单的方法吗?还是没有人知道使用CVXPY解决图形着色问题的示例吗?
还有一件事,如果我转置颜色数组,错误就会消失。
输入数据:
边缘
[(0, 1), (1, 2), (1, 3)]
代码:
# selection variable
# 4 is the number of nodes
selection = cvxpy.Variable(4, boolean=True)
# array for colors
colors = np.array([[1,0,0,0],
[0,1,0,0],
[0,0,1,0],
[0,0,0,1],
[1,1,0,0],
[1,1,1,0],
[1,1,1,1],
[0,1,1,1],
[0,0,1,1],
[1,0,1,0],
[0,1,0,1],
[0,1,1,0],
[1,1,0,0],
[0,0,0,0]])
# each node can only have one color constraint
one_color = cvxpy.sum(selection * colors, axis=0) == 1
错误:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-18-b22226c89a2f> in <module>()
1 # each node can only have one color constraint
2
----> 3 one_color = cvxpy.sum(selection * colors, axis=0) == 1
~/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, 4) (14, 4)