量子退火算法入门(5):旅行商问题的QUBO建模「下篇之Python实现」

这篇具有很好参考价值的文章主要介绍了量子退火算法入门(5):旅行商问题的QUBO建模「下篇之Python实现」。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


一,旅行商问题QUBO的两种实现

提示:上篇已经讲过了旅行商问题的QUBO建模,这里直接讲两种编程实现:

看过上篇的读者应该已经注意到,因为旅行商问题需要最终返回到初始点的。所以,下面👇的目标函数里,循环进行到 N N N时,最后一个 x j , t + 1 x_{j,t+1} xj,t+1应该确定回到初始点的。

量子退火算法入门(5):旅行商问题的QUBO建模「下篇之Python实现」
针对这个特殊设定,我们可以有两种实现方式:

  • 方式一:使用取余操作符%,在 t = N t=N t=N时,这样的话 ( t + 1 ) % N (t+1)\%N (t+1)%N=1,也就相当于最后一个时间步回到了初始点。
    量子退火算法入门(5):旅行商问题的QUBO建模「下篇之Python实现」

  • 方式二:把 x i , t x_{i,t} xi,t x j , t + 1 x_{j,t+1} xj,t+1对应的数值矩阵,分为独立的两个矩阵。具体来说, x i , t x_{i,t} xi,t从矩阵X中取值和 x j , t + 1 x_{j,t+1} xj,t+1从矩阵Y中取值。矩阵Y的数值就是, y j , t = x j , t + 1 y_{j,t} = x_{j,t+1} yj,t=xj,t+1,从式子上看,有点难以理解,大家可以看下面的图示。其实就是把矩阵X的第一列,转移到最后一列。
    量子退火算法入门(5):旅行商问题的QUBO建模「下篇之Python实现」
    最后我们的目标函数就就看转换如下:

量子退火算法入门(5):旅行商问题的QUBO建模「下篇之Python实现」
大家可以品味一下,∑符号怎么转换为矩阵操作。


提示:下面分别献上python实现:

二,方式一:取余操作

这里代码复制于下面的链接,这里只讲解QUBO部分的代码:

https://github.com/recruit-communications/pyqubo/blob/master/notebooks/TSP.ipynb

旅行问题的QUBO的定义:

%matplotlib inline
from pyqubo import Array, Placeholder, Constraint
import matplotlib.pyplot as plt
import networkx as nx
import numpy as np
import neal

# 地点名和坐标 list[("name", (x, y))]
cities = [
    ("a", (0, 0)),
    ("b", (1, 3)),
    ("c", (3, 2)),
    ("d", (2, 1)),
    ("e", (0, 1))
]

n_city = len(cities)

下面实现约束部分:
量子退火算法入门(5):旅行商问题的QUBO建模「下篇之Python实现」

# ‘BINARY’代表目标变量时0或1 
x = Array.create('c', (n_city, n_city), 'BINARY')

# 约束① : 每个时间步只能访问1个地点
time_const = 0.0
for i in range(n_city):
    # Constraint(...)函数用来定义约束项
    time_const += Constraint((sum(x[i, j] for j in range(n_city)) - 1)**2, label="time{}".format(i))

# 约束② : 每个地点只能经过1次
city_const = 0.0
for j in range(n_city):
    city_const += Constraint((sum(x[i, j] for i in range(n_city)) - 1)**2, label="city{}".format(j))

接下来是目标函数:
量子退火算法入门(5):旅行商问题的QUBO建模「下篇之Python实现」

# 目标函数的定义

distance = 0.0
for i in range(n_city):
    for j in range(n_city):
        for k in range(n_city):
            d_ij = dist(i, j, cities)
            distance += d_ij * x[k, i] * x[(k+1)%n_city, j]

最后就是整体的Hamiltonian量定义和输出采样结果。

# 总体的Hamiltonian,这里的A代表约束项的惩罚系数,数值自由指定
A = Placeholder("A")
H = distance + A * (time_const + city_const)

# 求BQM
model = H.compile()
feed_dict = {'A': 4.0}
bqm = model.to_bqm(feed_dict=feed_dict)


sa = neal.SimulatedAnnealingSampler()
# 这里要注意,退火算法是要采样足够的次数,从中取占比最高的结果作为最优解
sampleset = sa.sample(bqm, num_reads=100, num_sweeps=100)

# Decode solution
decoded_samples = model.decode_sampleset(sampleset, feed_dict=feed_dict)
best_sample = min(decoded_samples, key=lambda x: x.energy)


# 如果指定参数only_broken=True,则只会返回损坏的约束。
# 如果best_sample长度为0,就代表没有损坏的约束项,也就满足最优解了。
num_broken = len(best_sample.constraints(only_broken=True))
if num_broken == 0:
	print(best_sample.sample)

三、方式二:独立矩阵

这里的实现复制于以下文章:

https://qiita.com/yufuji25/items/0425567b800443a679f7
import neal
import numpy as np
import networkx as nx
import matplotlib.pyplot as plt
from pyqubo import Array, Placeholder
from scipy.spatial.distance import cdist


def construct_graph(n_pos:int):
    """ construct complete graph """
    pos = nx.spring_layout(nx.complete_graph(n_pos))
    coordinates = np.array(list(pos.values()))
    G = nx.Graph(cdist(coordinates, coordinates))
    nx.set_node_attributes(G, pos, "pos")
    return G

整体Hamiltonian量:量子退火算法入门(5):旅行商问题的QUBO建模「下篇之Python实现」

def create_hamiltonian(G:nx.Graph):
    """ create QUBO model from graph structure """

    # generate QUBO variable
    n_pos = G.number_of_nodes()
    X = np.array(Array.create("X", shape = (n_pos, n_pos), vartype = "BINARY"))

    # construct `Y` matrix
    Xtmp = np.concatenate([X, X[:, 0].reshape(-1, 1)], axis = 1)
    Y = np.delete(Xtmp, 0, 1)

    # Distance matrix
    L = np.array(nx.adjacency_matrix(G).todense())

    # return hamiltonian
    Hbind1 = np.sum((1 - X.sum(axis = 0)) ** 2)
    Hbind2 = np.sum((1 - X.sum(axis = 1)) ** 2)
    Hobj = np.sum(X.dot(Y.T) * L)
    H = Hobj + Placeholder("a1") * Hbind1 + Placeholder("a2") * Hbind2

    return H.compile()

求解并输出结果:

def decode(response, Gorigin:nx.Graph):
    """ return output graph generated from response """

    # derive circuit
    solution = min(response.record, key = lambda x: x[1])[0]
    X = solution.reshape((num_pos, num_pos))
    circuit = np.argmax(X, axis = 0).tolist()
    circuit.append(circuit[0])

    # generate output graph structure
    Gout = nx.Graph()
    Gout.add_edges_from(list(zip(circuit, circuit[1:])))
    positions = nx.get_node_attributes(Gorigin, "pos")
    nx.set_node_attributes(Gout, positions, "pos")

    return Gout


def draw_graph(G:nx.Graph, **config):
    """ drawing graph """
    plt.figure(figsize = (5, 4.5))
    nx.draw(G, nx.get_node_attributes(G, "pos"), **config)
    plt.show()



# configuration for drawing graph
config = {"with_labels":True, "node_size":500, "edge_color":"r", "width":1.5,
          "node_color":"k", "font_color":"w", "font_weight":"bold"}

# construct complete graph
num_pos = 8
G = construct_graph(num_pos)
draw_graph(G, **config)

# sampling
model = create_hamiltonian(G)
qubo, offset = model.to_qubo(feed_dict = {"a1":500, "a2":500})
response = neal.SimulatedAnnealingSampler().sample_qubo(qubo, num_reads = 1000)


# output graph
Gout = decode(response, G)
draw_graph(Gout, **config)

总结

以上就是两种实现方式,大家可以体会一下,怎么实现稍微复杂的Hamiltonian量,接下来,讲解一下量子退火的物理原理。

参考文献:
[*1] : https://www.nttdata.com/jp/ja/-/media/nttdatajapan/files/news/services_info/2021/012800/012800-01.pdf
[*2] : https://qiita.com/yufuji25/items/0425567b800443a679f7文章来源地址https://www.toymoban.com/news/detail-412911.html

到了这里,关于量子退火算法入门(5):旅行商问题的QUBO建模「下篇之Python实现」的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 量子退火算法入门(7):如何QUBO中的三次多项式怎么转换?

    本文还是大部分截图来自于:《最適化問題とWildqatを用いた量子アニーリング計算入門》 https://booth.pm/ja/items/1415833 终于有人问到怎么将QUBO中的三次多项式转换为二次多项式了。直接以一个例题开始讲解。中间会用到之前文章里的知识,大家最好读了该系列前两篇之后,再阅

    2023年04月14日
    浏览(38)
  • Baltamatica 北太天元 —— 基于模拟退火算法的旅行商问题

    北太天元(Baltam)是一款对标矩阵实验室(Matlab)的国产通用科学计算软件,目前版本还在持续更新迭代中,并在国内不断提升知名度,营造良好的生态社区氛围。在很多外行、内行人都不看好Matlab国产化,甚至面对工业软件国产化的项目“谈虎色变”的形势下,北太天元横

    2024年02月11日
    浏览(63)
  • Matlab【旅行商问题】—— 基于模拟退火算法的无人机药品配送路线最优化

    某市引进一架专业大型无人机用于紧急状态下的药品投递,每个站点只能投放一次,可选择指派任意站点的无人机起飞出发完成投递任务,但必须在配送完毕后返回原来的站点。站点地理位置坐标(单位为公理)如下图所示。每个站点及容纳的病人数量见附件.mat数据,现要求

    2024年02月12日
    浏览(52)
  • 模拟退火算法与遗传算法求解多目标优化问题的算法实现(数学建模)

    模拟退火算法是一种全局优化算法,解决的问题通常是找到一个最小化(或最大化)某个函数的全局最优解。它通过模拟物理退火的过程来搜索解空间,在开始时以一定的温度随机生成初始解,然后一步步降低温度,同时在当前解的周围随机搜索新的解,并根据一定概率接受

    2024年02月02日
    浏览(53)
  • 数学建模|通过模拟退火算法求解供货与选址问题:问题二(python代码实现)

    今天继续用模拟退火算法供货与选址问题的问题二,如果还没看过问题一的可以看我之前的博客 数学建模|通过模拟退火算法求解供应与选址问题:问题一(python代码实现)-CSDN博客 这里还是把题目放上来(题目来自数学建模老哥的视频): 那么我们可以分析一下,第一问和

    2024年01月16日
    浏览(56)
  • 计算机设计大赛国奖作品_5. 模拟退火求解旅行商问题

    本系列是2021年中国大学生计算机设计大赛作品“环境监测无人机航线优化”的相关文档,获得2021年西北赛区一等奖,国赛三等奖。学生习作,只供大家参考。 计算机设计大赛国奖作品_1. 项目概要 计算机设计大赛国奖作品_2. 报名材料 计算机设计大赛国奖作品_3. 需求分析 计

    2023年04月09日
    浏览(54)
  • 集货运输优化:数学建模步骤,Python实现蚁群算法(解决最短路径问题), 蚁群算法解决旅行商问题(最优路径问题),节约里程算法

    目录 数学建模步骤 Python实现蚁群算法(解决最短路径问题)  蚁群算法解决旅行商问题(最优路径问题)

    2024年02月09日
    浏览(54)
  • 数学建模-退火算法和遗传算法

    退火算法和遗传算法 一.退火算法 退火算法Matlab程序如下: [W]=load(\\\'D:100个目标经度纬度.txt\\\'); 二、遗传算法 [E]=xlsread(\\\'D:100个目标经度纬度\\\');  % 加载敌方 100 个目标的数据, 数据按照表格中的位置保存在纯文本文件 sj.txt 中 x=[E(:,1)]; y=[E(:,2)]; e =[x y]; d1=[70,40]; e =[d1;  e ;d1];

    2024年02月20日
    浏览(55)
  • 【数学建模学习(9):模拟退火算法】

    模拟退火算法(Simulated Annealing, SA)的思想借 鉴于固体的退火原理,当固体的温度很高的时候,内能比 较大,固体的内部粒子处于快速无序运动,当温度慢慢降 低的过程中,固体的内能减小,粒子的慢慢趋于有序,最 终,当固体处于常温时,内能达到最小,此时,粒子最为 稳

    2024年02月14日
    浏览(41)
  • 数学建模学习(9):模拟退火算法

    模拟退火算法(Simulated Annealing, SA)的思想借 鉴于固体的退火原理,当固体的温度很高的时候,内能比 较大,固体的内部粒子处于快速无序运动,当温度慢慢降 低的过程中,固体的内能减小,粒子的慢慢趋于有序,最 终,当固体处于常温时,内能达到最小,此时,粒子最为 稳

    2024年02月14日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包