旅行商问题TSP-改良圈算法

库的版本号

列了这个是因为在学习过程中,会有很多文章,可能时间稍微久点了,用起来因为版本迭代,函数可能发生了变化,但你也不确实到底是什么问题。。这样指明版本,可以避免很多复现的困惑。

import numpy as np
import sys
print(sys.version)
print(nx.__version__)

# 3.9.5 (default, May 18 2021, 14:42:02) [MSC v.1916 64 bit (AMD64)]
# 2.5.1

旅行商问题描述(travelling salesman problem,TSP)

首先,旅行商问题是一个被证明的NPC的问题,所以没有满足多项式时间复杂度的算法,所以只能用近似优化去求解啦。
然后,旅行商问题更普遍有点就是叫求最小哈密顿圈(halmiton circuit)的问题。
哈密顿圈:Hamilton 图就是从一顶点出发每顶点恰通过一次能回到出发点的那种图,即不重复地行遍所有的顶点再回到出发点
注意区别欧拉回路,欧拉回路是通过所有的边

改良圈算法

在这里插入图片描述

import networkx as nx

# 生成图
G = nx.complete_graph(['L','M','N','Pa','Pe','T'])

names = ['L','M','N','Pa','Pe','T']
weights = [56, 35, 21, 51, 60,
               21, 57, 78, 70,
                   36, 68, 68,
                       51, 61,
                           13]
count = 0
for i in range(0,6):
    for j in range(i+1,6):
        G.edges[names[i], names[j]]['weight'] = weights[count]
        count += 1

G.edges(data='weight')
nx.draw(G, with_labels=True, pos=nx.spring_layout(G), font_weight='bold')
nx.draw_networkx_edge_labels(G, pos=nx.spring_layout(G), edge_labels=nx.get_edge_attributes(G, 'weight'), label_pos=0.5)

在这里插入图片描述
生成了图,下面我们来写两个函数,因为改良圈算法需要基于一条已知的哈密顿路径,进行优化。但是我看很多网上求解这题的时候,包括书上,都手动给了一条,不得不说不是很满意。所以第一个函数,是找一条哈密顿圈。

第二个函数就是改良圈的过程了,其实也很简短,但为了消化这个问题和学了一下networkx这个python库,还是花了好几天。。菜鸡实锤了

def find_halmiton_circuit(G,s,path):
    '''
    找到一条任意的哈密顿圈,如果有则存到path里,没有则返回False
    '''
    # 若已经遍历了所有节点了,此时可以判断是否形成闭环。
    if len(path) == len(list(G.nodes())):
        if path[-1] in dict(G.adj[path[0]]):
            path.append(path[0])
            return True
        else:
            return False

    # 判断该节点是否已经在路径中
    if s not in path:
        path.append(s)
    else:
        return False
    print(path)
#     # 如果该节点没有后续节点了,返回FALSE
#     if G.adj[path[-1]] == None:
#         return False   
    for nbr, datadict in G.adj[path[-1]].items():
        if find_halmiton_circuit(G, nbr, path):
            return True 
    return False


def circle_modification(G,path):
#     names = list(G.nodes)
    n = len(path)
    for i in range(n):
        for j in range(i+2, n-1):
            try:
                # 如果存在更短的路径,更换两条边的选择
                if G.edges[path[i],path[j]]['weight'] + G.edges[path[i+1],path[j+1]]['weight'] < G.edges[path[i],path[i+1]]['weight'] + G.edges[path[j],path[j+1]]['weight']:
                    path[i+1:j+1] = path[j:i:-1]
            except KeyError:
                print(i,j,"not connected")
    return True

最后的调用

path = []
s = 'Pe'
if find_halmiton_circuit(G, s, path):
    print(path)
print("Found one feasible halmiton circuit")
if circle_modification(G, path):
    print(path)
['Pe']
['Pe', 'L']
['Pe', 'L', 'M']
['Pe', 'L', 'M', 'N']
['Pe', 'L', 'M', 'N', 'Pa']
['Pe', 'L', 'M', 'N', 'Pa', 'T']
['Pe', 'L', 'M', 'N', 'Pa', 'T', 'Pe']
Found one feasible halmiton circuit

['Pe', 'Pa', 'L', 'N', 'M', 'T', 'Pe']
  • 5
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值