动态规划求解TSP问题

设计思路:

程序清单:

文件名

定位

作用

cities.json

json数据

存储城市坐标信息

tool.py

工具模块

提供读取JSON数据、生成随机点、生成距离矩阵等函数

main.py

主模块

程序入口,求解TSP问题并可视化

cities.json:json数据

[[88, 88], [93, 13], [17, 20], [13, 70]]

tool.py:工具模块

# -*- coding:utf-8 -*-



import math

import json

import random



# 生成一定范围的随机数

def random_double(_min, _max):

    return random.random() * (_max - _min) + _min



# 生成随机城市坐标

def random_cities(_min, _max, num):

    return [[random_double(_min, _max), random_double(_min, _max)] for _ in range(num)]



# 计算欧式距离

def distance(c1, c2):

    return math.sqrt(square_distance(c1, c2))



# 计算平方欧式距离

def square_distance(c1, c2):

    return (c1[0] - c2[0]) ** 2 + (c1[1] - c2[1]) ** 2



# 由城市坐标列表,生成距离矩阵

def distance_matrix(_cities):

    length = len(_cities)

    matrix = [[-1.0] * length for _ in range(length)]

    for i in range(length - 1):

        for j in range(i + 1, length):

            matrix[i][j] = matrix[j][i] = distance(_cities[i], _cities[j])



    return matrix



# 从json文件中,读取城市信息

def read_cities():

    json_path = 'cities.json'

    with open(json_path, 'r') as f:

        return json.load(f)

main.py:主模块

# -*- coding:utf-8 -*-



from tool import read_cities, distance_matrix

import matplotlib.pyplot as plt



class Solution:



    def __init__(self, _matrix, start_node):

        # 距离矩阵

        self.matrix = _matrix

        # 节点数目

        self.height = len(self.matrix)

        # 宽度

        self.width = 2 ** self.height

        # 开始节点

        self.start_node = start_node

        # 记录处于x节点,未经历M个节点时

        # 矩阵储存x的下一步是M中哪个节点

        self.array = [[0] * self.width for _ in range(self.height)]



    def tsp(self):

        # 开始节点

        s = self.start_node

        # 节点数目

        num = self.height

        # 未遍历节点集合

        _cities = list(range(num))

        _cities.pop(s)

        # 求解函数

        return self.solve(s, _cities)



    @staticmethod

    def transfer(sets):

        _sum = 0

        for s in sets:

            _sum += 2 ** s  # 二进制转换

        return _sum



    def solve(self, node, future_sets):

        # 迭代终止条件,

        # 表示没有了未遍历节点,直接连接当前节点和起点即可

        if len(future_sets) == 0:

            return self.matrix[node][self.start_node]

        # node如果经过future_sets中节点,最后回到原点的距离

        distance = []

        # 遍历未经历的节点

        for i in range(len(future_sets)):

            s_i = future_sets[i]

            # 访问s_i,更新当前未访问节点集合

            copy = future_sets[:]

            copy.pop(i)

            # 递归,动态规划递推方程

            distance.append(self.matrix[node][s_i] + self.solve(s_i, copy))

        # 最小距离

        d = min(distance)

        # node需要连接的下一个节点

        next_one = future_sets[distance.index(d)]

        # 未遍历节点集合

        c = self.transfer(future_sets)

        # (当前节点,未遍历节点集合)-->下一个节点

        self.array[node][c] = next_one

        return d



if __name__ == '__main__':

    # 从JSON读取数据

    cities = read_cities()

    # 生成距离矩阵

    mat = distance_matrix(cities)

    # 调用tsp

    S = Solution(mat, 0)

    S.tsp()

    # 开始回溯

    lists = list(range(len(S.matrix)))

    start_node = S.start_node

    # 生成路径

    output_path = list()

    while len(lists) > 0:

        lists.pop(lists.index(start_node))

        # 未访问节点集合 矩阵中的y坐标

        y = S.transfer(lists)

        # 下一节点

        next_node = S.array[start_node][y]

        # 添加下一组合

        output_path.append([start_node, next_node])

        # 从下一节点出发

        start_node = next_node

    # 输出城市列表

    print('城市坐标集合为:')

    for city in cities:

        print(city, end=' ')

    print()

    # 距离矩阵

    print('距离矩阵为:')

    for row in mat:

        for col in row:

            print('%10.2f' % col, end='   ')

        print()

    # 输出路径

    print('最优路径为:')

    for i in output_path:

        print(i[0], '-->', end='')

    print('0')

    # 画散点图

    i = 0

    for city in cities:

        plt.scatter(city[0], city[1])

        plt.annotate("City%d(%d, %d)" % (i, city[0], city[1]), (city[0] + 2, city[1] + 2))

        i += 1

    # 画出路径

    for start_node, next_node in output_path:

        cs = cities[start_node]

        cn = cities[next_node]

        plt.plot([cs[0], cn[0]], [cs[1], cn[1]])

    # 不显示坐标轴

    plt.axis('off')

    # 绘图

plt.show()

TSP问题

输出结果:

绘图结果:

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值