【发布时间】:2019-07-06 00:43:06
【问题描述】:
我正在尝试解决最小图形着色问题。我正在尝试使用 cvxpy 将其解决为mip。我正在遵循此 url 中描述的解决方案大纲:
https://manas.tech/blog/2010/09/16/modelling-graph-coloring-with-integer-linear-programming.html
我不确定我是否理解如何正确创建 cvxpy 变量,以及如何定义我的约束。我在下面有示例输入数据以及创建变量、约束和目标函数、解决问题和返回解决方案的代码。
我认为这个输入的正确答案应该是:
‘2 1\n0 1 0 0’
即要求的最小颜色数为2,除节点1外,所有节点颜色相同。
我正在创建 w 变量来计算使用的颜色数量:
w = cvxpy.Variable(j, boolean=True)
我认为我正在做的是创建一个长度等于节点数的二进制变量。这个想法是您可以使用的最大颜色数将等于节点数。所以最大的颜色:
w=[1,1,1,1]
我把 w 想象成一个二进制变量,就像一个列表,其中的值可以是 0 或 1,表示该颜色是否被任何节点使用。
然后创建目标函数:
obj=cvxpy.sum(w,axis=0)
我想我正在对行中为 1 的条目求和,例如:
w=[1,1,0,0]
obj=2
我还创建了一个变量 x 来指示给定节点的颜色:
x = cvxpy.Variable((j,int(first_line[0])), boolean=True)
我把它想象成一个具有二进制值的二维数组,其中列表示节点,行表示颜色。
例如,如果节点 0 的颜色为 0,节点 1 的颜色为 1,节点 2 的颜色为 2,节点 3 的颜色为 2,我会想象 x 的样子:
[[1,0,0,0],[0,1,0,0],[0,0,1,1],[0,0,0,0]]
谁能告诉我我是否正确理解并创建了我的选择变量?我是否理解并正确创建了目标函数?那就是我描述目标函数的方式与我创建它的方式相匹配吗?对于我定义的其他约束或我的代码的任何输入将不胜感激。我正在学习线性编程,并且正在尝试理解 cvxpy 语法。
样本数据:
input_data
'4 3\n0 1\n1 2\n1 3\n'
# parse the input
lines = input_data.split('\n')
first_line = lines[0].split()
node_count = int(first_line[0])
edge_count = int(first_line[1])
edges = []
for i in range(1, edge_count + 1):
line = lines[i]
parts = line.split()
edges.append((int(parts[0]), int(parts[1])))
edges
# Output:
[(0, 1), (1, 2), (1, 3)]
# solution using cvxpy solver
import numpy as np
import cvxpy
from collections import namedtuple
# selection variables
# binary variable if at least one node is color j
j=int(first_line[0])
# w=1 if at least one node has color j
w = cvxpy.Variable(j, boolean=True)
# x=1 if node i is color j
x = cvxpy.Variable((j,int(first_line[0])), boolean=True)
# Objective function
# minimize number of colors needed
obj=cvxpy.sum(w,axis=0)
# constraints
# 1 color per node
node_color=cvxpy.sum(x,axis=1)==1
# for adjacent nodes at most 1 node has color
diff_col = []
for edge in edges:
for k in range(node_count):
diff_col += [
# x[edge[0],k]+x[edge[1],k]<=1
x[k,edge[0]]+x[k,edge[1]]<=1
]
# w is upper bound for color of node x<=w
upper_bound = []
for i in range(j):
for k in range(j):
upper_bound += [
x[k,i]<=w[i]
]
# constraints
constraints=[node_color]+diff_col+upper_bound
# solving problem
# cvxpy must be passed as a list
graph_problem = cvxpy.Problem(cvxpy.Minimize(obj), constraints)
# Solving the problem
graph_problem.solve(solver=cvxpy.GLPK_MI)
value2=int(graph_problem.solve(solver=cvxpy.GLPK_MI))
# taken2=[int(i) for i in selection.value.tolist()]
# taken2=[int(i) for i in w.value.tolist()]
taken2=[int(i) for i in w.value.tolist()]
# prepare the solution in the specified output format
output_data2 = str(value2) + ' ' + str(0) + '\n'
output_data2 += ' '.join(map(str, taken2))
output_data2
'1 0\n0 0 0 1'
【问题讨论】:
标签: python-3.x linear-programming cvxpy mixed-integer-programming