Define CVXPY variables for graph coloring problem

血红的双手。 提交于 2019-12-11 17:23:07

问题


I’m trying to solve the minimum graph coloring problem. I’m trying to solve it as an mip using cvxpy. I’m following the outline of a solution described in this url:

https://manas.tech/blog/2010/09/16/modelling-graph-coloring-with-integer-linear-programming.html

I’m not sure if I’m understanding how the cvxpy variables are created correctly, and how I’m defining my constraints. I have sample input data below along with the code creating the variables, constraints, and objective function, solving the problem and the solution returned.

I think the correct answer for this input should be:

‘2 1\n0 1 0 0’

That is that the minimum number colors required is 2 and all nodes are the same color except node 1.

I’m creating the w variable to count the number of colors used:

w = cvxpy.Variable(j, boolean=True)

What I think I am doing is creating a binary variable of length equal to the number of nodes. The idea being that the maximum number of colors you could use would be equal to the number of nodes. So maximum colors:

w=[1,1,1,1]

I’m picturing w as binary variable like a list where the values can be 0 or 1 indicating if that color is used by any of the nodes.

Then to create the objective function:

obj=cvxpy.sum(w,axis=0)

I think I’m summing the entries in the row which are 1, so for example:

w=[1,1,0,0]

obj=2

I also create a variable x to indicate the color of a given node:

x = cvxpy.Variable((j,int(first_line[0])), boolean=True)

I’m picturing this as a 2 dimensional array with binary values, where the column indicates the node and the row indicates the color.

So for example if node 0 had color 0, node 1 had color 1, node 2 had color 2, and node 3 had color 2, I would imagine x to look like:

[[1,0,0,0],[0,1,0,0],[0,0,1,1],[0,0,0,0]]

Can someone please tell me if I’m understanding and creating my selection variables correctly? Also do I understand and have I created my objective function correctly? That is does the way I’ve described my objective function match the way I’ve created it? And any input on the other constraints I’ve defined or my code would be greatly appreciated. I’m learning linear programing and I’m trying to understand cvxpy syntax.

Sample Data:

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'

回答1:


Your solution is almost correct. The main problem here is the definition of variable x. According to the blog post

x_{ij} variables that will be true if and only if node i is assigned color j

which indicates that the size of x is (nb of nodes, nb of colors).

In your code you need to change x to:

x = cvxpy.Variable((node_count, j), boolean=True)

and then, consequently, the second and third constraints:

# for adjacent nodes at most 1 node has color
diff_col = []

for edge in edges:
    for k in range(j):
        diff_col += [
            x[edge[0],k]+x[edge[1],k]<=1
        ]


# w is upper bound for color of node x<=w

upper_bound = []

for i in range(node_count):
    for k in range(j):
        upper_bound += [
            x[i,k]<=w[k]
        ]

Then the output is as expected i.e. 2 colors are used: one color for node 1 and another color for nodes 0, 2, 3 (because they are not adjacent).



来源:https://stackoverflow.com/questions/55985891/define-cvxpy-variables-for-graph-coloring-problem

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!