图形着色Gurobi约束

时间:2018-10-26 16:13:01

标签: python networkx graph-theory gurobi

我正在尝试使用networkx和gurobi来解决Graph着色问题的一些约束。这就是我编写的所有代码:

import networkx as nx
import gurobi as gb
from itertools import combinations, chain
import pygraphviz as pygv
import os
import matplotlib.pyplot as plt
from IPython.display import SVG, display

创建图,添加节点和边以及两个列表。

G = nx.Graph()
G.add_nodes_from ([1,2,3,4,5])
G.add_edge(1,2)
G.add_edge(1,3)
G.add_edge(1,4)
G.add_edge(1,5)
G.add_edge(2,3)
G.add_edge(2,4)
G.add_edge(3,5)
G.add_edge(4,5)
U = list(G.nodes)
K = G.number_of_edges()
Z = []

创建带有颜色的列表。我们假设K = {0,1,。。 。 。 ,K − 1}和K≤| E |

def nrofCol():
    Z.clear()
    z = 0
    while z < K - 1:
        Z.append(z)
        z = z+1
    return Z

Z = nrofCol()

为每个边缘添加颜色属性

for colored_arc in ((u,v,z) for u,v in G.edges() for z in Z):
    G[colored_arc[0]][colored_arc[1]][colored_arc[2]] = colored_arc

并使用Gurobi向模型添加变量:

mdic = gb.Model()
indices = []

for u,v in G.edges(): 
    for z in Z:
        indices.append((u,v,z))

# binary variable that assing 1.0 to the color associated to the edge and 0.0 to the others

x = mdic.addVars(indices, vtype = gb.GRB.BINARY)

# decision variable S i for i ∈ V represents the maximum color in the set of colors assigned to edges incident to vertex i

S_i = []
for u in U:
    S_i.append(mdic.addVar(vtype=gb.GRB.CONTINUOUS, lb = G.degree[u] - 1, ub = K - 1, \
                        name = 'max_color'+str(u)))

# decision variable s_i for i ∈ V represents the minimum color in the set of colors assigned to edges incident to vertex i
s_i = []
for u in U:
    s_i.append(mdic.addVar(vtype=gb.GRB.CONTINUOUS, lb = 0.0, ub = K - G.degree[u], \
                        name='min_color'+str(u)))

mdic.update()

然后是约束:

# 1a- Guarantee that adjacent edges take different colors

for u in U:
    for z in Z: 
        mdic.addConstr(x.sum(u,'*',z) <= 1, name='different_color')


mdic.update()


# 1a- Guarantee that adjacent edges take different colors

for u in U:
    for z in Z:
        mdic.addConstr(x.sum('*',u,z) <= 1, name='different_color')


mdic.update()

# 1b- Guarantee that every edge takes exactly one color
for u,v in G.edges():
    mdic.addConstr(x.sum(u,v) == 1, name='one_color')

mdic.update()

# 1c- Enforce Si to be greater than or equal to the max color assigned to the edges incident to vertex i

expr = 0
for u,v in G.edges():
    for z in Z:       
        expr += z * x[u,v,z]
    mdic.addConstr(S_i[u] >= expr, name='max')
    expr = 0

# 1d- Enforce si to be less than or equal to the min color assigned to the edges incident to vertex i

expr = 0
for u,v in G.edges():
    for z in Z:       
        expr += z * x[u,v,z]
mdic.addConstr(s_i[u] <= expr, name='min')
expr = 0

mdic.update()

其中Z是可用颜色的集合。

# objective function
expr20=0
for u in U:
    expr20+=(S_i[u] - s_i[u] - G.degree[u] + 1)
mdic.setObjective(expr20, gb.GRB.MINIMIZE)

mdic.update()

mdic.optimize()

Constraints

第一个是目标函数,1a到1d是约束,其他是ub和lb。

1 个答案:

答案 0 :(得分:0)

假设您使用的是无向图,我发现了几个问题:

屏幕快照中的

约束(1a)确保相邻的边缘具有不同的颜色。但是,使用此约束的实现可能会发生传入和传出边缘具有相同颜色的情况。例如,边缘{1,3}和{3,5}可以具有相同的颜色。那是因为您分别处理传入和传出边缘。作为解决方案,您可以将循环合并为一个:

for u in U:
    for z in Z: 
        mdic.addConstr(x.sum(u,'*',z) + x.sum('*',u,z) <= 1, name='different_color')

约束(1c)在实现中也仅考虑传出边缘。例如,S_i[5]不会分配,因为它只有传入的边。这应该起作用:

expr = 0
for u,v in G.edges():
    for z in Z:       
        expr += z * x[u,v,z]
    mdic.addConstr(S_i[u] >= expr, name='max')
    mdic.addConstr(S_i[v] >= expr, name='max')
    expr = 0

约束(1d)也是如此。 addConstr行在循环之外,但这可能只是格式错误:

expr = 0
for u,v in G.edges():
    for z in Z:       
        expr += z * x[u,v,z]
    mdic.addConstr(s_i[u] <= expr, name='min')
    mdic.addConstr(s_i[v] <= expr, name='min')
    expr = 0