Определите переменные CVXPY для задачи раскраски графа

Я пытаюсь решить задачу минимальной раскраски графа. Я пытаюсь решить эту проблему как mip с помощью cvxpy. Я следую плану решения, описанному в этом 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'

person user3476463    schedule 04.05.2019    source источник


Ответы (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 (потому что они не являются смежными).

person sukkub    schedule 05.07.2019
comment
Спасибо, что ответили мне. Извините, я не ответил раньше. В моем коде выше я определяю j = int (first_line [0]). Так разве j = node_count, способ, которым я определил x, не эквивалентен способу, который вы предложили определить x? - person user3476463; 02.08.2019