简介:
Maximum Cut 问题,俗称最大割问题,NP-hard。给定一张,求一种分割方法,将所有顶点(Vertex)分割成两群,同时使得被切断的边(Edge)数量最大。
转化:
此问题最大化形式为:
PS:参数(-2)可调节,只要将(0,0),(0,1)/(1,0),(1,1)分割开即可,并且使得(0,1)/(1,0)输出的值最大或者最小即可。(最小化加一个负号即可)
实例
这里给一个例子,图中包含10个节点,16条边:
代码
from pyqubo import Array, Binary
import networkx as nx
import itertools
import neal
def random_graph(node_num,p = 0.3):
G = nx.Graph()
H = nx.path_graph(node_num)
G.add_nodes_from(H)
comb = list(itertools.combinations(range(node_num),2))
for e in comb:
probability =random.random()#生成随机小数
if(probability<p): #如果小于p
G.add_edge(e[0],e[1])
return G
def binary_array(G):
b_arr = Array.create('b', shape=(len(G.nodes), 1), vartype='BINARY')
H = []
for e in list(G.edges):
H.append(b_arr[e[0]]+b_arr[e[1]]-2*b_arr[e[0]]*b_arr[e[1]])
H_t = -sum(H)
return H_t
def solver(H_t):
# 编译
model = H_t.compile()
# 模型返回QUBO
qubo, offset = model.to_qubo()
print(qubo)
# 创建SA求解器
sa = neal.SimulatedAnnealingSampler()
# 采样
sampleset = sa.sample_qubo(qubo)
# 解码
decoded_samples = model.decode_sampleset(sampleset)
best_sample = min(decoded_samples, key=lambda x: x.energy)
# 输出最优解
best_sample.sample
return best_sample.sample
运行
G=random_graph(10)
H_t=binary_array(G)
result = solver(H_t)
pprint.pprint(result)
{'b[0][0]': 1,
'b[1][0]': 1,
'b[2][0]': 1,
'b[3][0]': 0,
'b[4][0]': 0,
'b[5][0]': 0,
'b[6][0]': 1,
'b[7][0]': 1,
'b[8][0]': 0,
'b[9][0]': 0}
切割方式为:
参考文献: