用python来编写TSP问题

import math
from os import path
import numpy as np
import matplotlib.pyplot as plt


class TSPInstance:
    '''
    设计一个类,实现从文件读入一个旅行商问题的实例
    文件格式为:
    city number
    best known tour length
    list of city position (index x y)

    best known tour (city index starts from 1)

    以文件01eil51.txt为例:
    第一行51为城市数
    第二行426为最优解的路径长度
    第三行开始的51行为各个城市的序号、x坐标和y坐标
    最后是最优解的访问城市系列(注意里面城市序号从1开始,而python的sequence是从0开始)
    Eil51Tour.png是最优解的城市访问顺序图
    '''

    def __init__(self, file_name):
        '''
        从文件file_name读入旅行商问题的数据
        '''
        self.file_name=file_name
        a= open(file_name)
        # 城市数量
        self.city_num = a.readline()
        # 返回坐标 51行,3列
        self.city = np.zeros((int(self.city_num), 3))
        # x坐标
        self.x = np.zeros(int(self.city_num))
        # y坐标
        self.y = np.zeros(int(self.city_num))
        # 城市ID
        self.id = np.zeros(int(self.city_num))
        b = a.readlines()
        for i, content in enumerate(b):
                if i in range(1, 52 ):
                    # 单行赋值
                    self.city[i-1] = content.strip('\n').split(' ')
                    self.x[i-1] = self.city[i-1][1]
                    self.y[i-1] = self.city[i-1][2]
        for i, content in enumerate(b):
                if i in range(53, 104):
                    self.id[i - 53] = content.strip('\n')
    @property
    def citynum(self):
        '''
        返回城市数
        '''
        return self.city_num

    @property
    def optimalval(self):
        '''
        返回最优路径长度
        '''
        c = 0
        i = 1
        s = open(self.file_name)
        str = s.readlines()
        for content in str:
            if i == 2:
                c = content
            i = i + 1
        return c

    @property
    def optimaltour(self):
        '''
        返回最优路径
        '''
        tour = np.array(self.id)
        return tour

    def __getitem__(self, n):
        '''
        返回城市n的坐标,由x和y构成的tuple:(x,y)
        '''
        (x, y) = (self.x[n-1], self.y[n-1])
        return (x, y)

    def get_distance(self, n, m):
        '''
        返回城市n、m间的整数距离(四舍五入)
        '''
        u=int(self.x[n-1] - self.x[m-1])
        v=int(self.y[n-1] - self.y[m-1])
        dis = math.sqrt(pow(u,2) + pow(v,2))
        return int(dis+0.5)

    def evaluate(self, tour):
        '''
        返回访问系列tour所对应的路径程度
        '''
        dis = 0
        for i in range(50):
            dis += self.get_distance(int(tour[i]), int(tour[i + 1]))
        dis += self.get_distance(int(tour[50]), int(tour[0]))
        return dis

    def plot_tour(self, tour):
        '''
        画出访问系列tour所对应的路径路
        '''
        for i in range(51):
            x0,y0 = self.__getitem__(i)
            plt.scatter(int(x0),int(y0),s=10,c='c')
        #记住坐标点的画法
        for i in range(len(tour)-1):
            x1,y1 = self.__getitem__(int(tour[i]))
            x,y = self.__getitem__(int(tour[i+1]))
            plt.plot([x1,x],[y1,y],c='b')
        x2,y2 = self.__getitem__(int(tour[0]))
        x3,y3 = self.__getitem__(int(tour[len(tour)-1]))

        plt.plot([x2,x3],[y2,y3],c='b')
        plt.xlabel('x label')
        plt.ylabel('y label')
        plt.title("City access sequence diagram")
        plt.plot()
        plt.show()

if __name__ == "__main__":
    file_name = path.dirname(__file__) + "/1.txt"
    instance = TSPInstance(file_name)
    print(instance.citynum)
    print(instance.evaluate(instance.optimaltour))
    print(instance.optimaltour)
    print(instance.__getitem__(2))
    print(instance.get_distance(0, 1))
    instance.plot_tour(instance.optimaltour)
    '''
    output:
    51
    426
    [  1.  22.   8.  26.  31.  28.   3.  36.  35.  20.   2.  29.  21.  16.  50.
      34.  30.   9.  49.  10.  39.  33.  45.  15.  44.  42.  40.  19.  41.  13.
      25.  14.  24.  43.   7.  23.  48.   6.  27.  51.  46.  12.  47.  18.   4.
      17.  37.   5.  38.  11.  32.]
    (49.0, 49.0)
    14  
    '''

其实解决TSP问题有很多方法,比如模拟退火算法,贪心算法,回溯算法等等。希望各位博友可以把你们的解决方法出现在评论区。 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值