Advertisement

模拟退火算法解决TSP问题

阅读量:

GitHub地址:https://github.com/Poe2016/Combinatorial_optimization_methods

1、TSP问题描述

TSP问题(Traveling Salesman Problem),也被称为Traveling Salesperson Problem或Tour Guide Problem,在运筹学领域具有重要意义。该问题是寻找一条经过给定所有城市的闭合回路路径,并且使得总路程最短。具体而言,在图论领域中被抽象为一个特定的问题:给定一个包含n个节点的完全加权图,在满足每个节点仅访问一次的前提下找到一条经过所有节点并最终返回起点的回路路径,并使得该路径的总长度最小化。

旅行商问题是NP完全问题。随着n的增大,无法通过精确算法求得最优解;此时必须采用近似算法来获得接近最优的解决方案。

2、模拟退火算法简述

模拟退火算法源于上世纪八十年代初,在理论研究与应用实践方面均取得了重要进展。原始论文是该领域的重要文献之一,请有需要的朋友可以上网查阅:https://pdfs.semanticscholar.org/e893/4a942f06ee91940ab57732953ec6a24b3f00.pdf

3、使用模拟退火算法解决TSP问题

读取问题件函数,返回一个列表,列表中存储了城市

复制代码
 def load_data(path):

    
     f_open = open(path)
    
     lines = f_open.readlines()
    
     f_open.close()
    
     point_list = []
    
     for line in lines[6:len(lines)-1]:
    
     line_list = line.strip().split()
    
     point_list.append(Point(line_list[1], line_list[2]))
    
     return point_list

计算两个城市之间距离的函数,返回一个二维列表

复制代码
 # return the distance matrix of every two cities

    
 def dist_matrix(point_list):
    
     num = len(point_list)
    
     dist = [[0]*num for i in range(num)]
    
     for i in range(num):
    
     for j in range(num):
    
         dist[i][j] = round(math.sqrt(math.pow(point_list[i].x-point_list[j].x, 2) + math.pow(point_list[i].y-point_list[j].y, 2)), 2) if i != j else 0
    
     return dist

模拟退火算法实现函数

复制代码
 def simulated_annealing(t, t_min, factor, point_list, dist):

    
     num = len(point_list)
    
     total_cost = 0
    
     # the initial sequence of cities
    
     init_seq = [i for i in range(num)]
    
     selected_seq = []
    
     selected_city = 0
    
     while len(selected_seq) < num:
    
     if len(selected_seq) == 0:
    
         selected_city = choice(init_seq)
    
         init_seq.remove(selected_city)
    
         selected_seq.append(selected_city)
    
         continue
    
     if len(selected_seq) == num:
    
         break
    
     left_num = len(init_seq)
    
     sample_num = left_num // 10 if left_num >= 10 else left_num % 10
    
     # select cities by random sampling
    
     sample_list = sample(init_seq, sample_num)
    
     curr_city = selected_seq[-1]
    
     cost = sys.maxsize
    
     sample_city = 0
    
     t_sample = t
    
     for city in sample_list:
    
         t_sample *= factor
    
         if dist[curr_city][city] < cost:
    
             cost = dist[curr_city][city]
    
             sample_city = city
    
         else:
    
             r = uniform(0, 1)
    
             if dist[curr_city][city] > cost and t_sample > t_min and math.exp(dist[curr_city][city] - cost)/t_sample > r:
    
                 sample_city = city
    
                 cost = dist[curr_city][city]
    
                 break
    
     init_seq.remove(sample_city)
    
     selected_seq.append(sample_city)
    
     total_cost += cost
    
     print '模拟退火得最小开销:', total_cost
    
     print '选择路径为:', selected_seq

全部评论 (0)

还没有任何评论哟~