【问题标题】:Define CVXPY variables for graph coloring problem为图形着色问题定义 CVXPY 变量
【发布时间】: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


    【解决方案1】:

    您的解决方案几乎是正确的。这里的主要问题是变量 x 的定义。根据博文

    x_{ij} 变量当且仅当节点 i 被分配颜色 j 时才为真

    表示x的大小是(nb个节点,nb个颜色)。

    在您的代码中,您需要将 x 更改为:

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

    然后是第二个和第三个约束:

    # 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]
            ]
    

    然后输出如预期的那样,即使用 2 种颜色:一种颜色用于节点 1,另一种颜色用于节点 0、2、3(因为它们不相邻)。

    【讨论】:

    • 感谢您回复我。抱歉我没有早点回复。在我上面的代码中,我定义了“j=int(first_line[0])” 那么 j = node_count,我定义 x 的方式不等同于您建议定义 x 的方式吗?
    猜你喜欢
    • 1970-01-01
    • 2019-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-11
    • 1970-01-01
    • 2021-03-13
    相关资源
    最近更新 更多