模拟退火算法解旅行商问题(陷入局部最优_待更改)

  1 # 模拟退火算法求解三十城市TSP问题
  2 # 2018-3-21开始求解
  3 # yangmingustb@outlook.com
  4 
  5 
  6 import math
  7 import random
  8 import datetime
  9 
 10 class SaTSP(object):
 11 
 12     def __init__(self, tf=0.01, alpha=0.9):
 13         self.tf = tf  # 最低温度
 14         self.alpha = alpha  # 降温系数
 15 
 16         # 30城市坐标
 17         self.coordinates = [[41, 94], [37, 84], [54, 67], [25, 62], [7, 64],
 18                        [2, 99], [68, 58], [71, 44], [54, 62], [83, 69],
 19                        [64, 60], [18, 54], [22, 60], [83, 46], [91, 38],
 20                        [25, 38], [24, 42], [58, 69], [71, 71], [74, 78],
 21                        [87, 76], [18, 40], [13, 40], [82, 7], [62, 32],
 22                        [58, 35], [45, 21], [41, 26], [44, 35], [4, 50]
 23                        ]
 24 
 25         self.iteration = 200 * len(self.coordinates)  # 每一个温度过程中迭代次数
 26 
 27     def initial_temperature(self):  # 温度初始化,采用t0=-delta(f)/(ln0.9)
 28         # number_list = []
 29         # for index, item in enumerate(self.coordinates):
 30         #     number_list.append([index, item])
 31         # print(number_list)
 32 
 33         # print(path)
 34         # print(path[0])
 35         dist_list = []
 36         for i in range(100):  # 生成一百条路径
 37 
 38             path = random.sample(self.coordinates, len(self.coordinates))  # 生成一条随机序列
 39             dist_list.append(self.all_dist(path))
 40 
 41         t0 = -(max(dist_list) - min(dist_list)) / math.log(0.9)  # 设置初温
 42         print('初始温度是:', t0)
 43         return t0
 44 
 45     def convergence(self, t_update, iteration_update):  # 收敛
 46         while t_update >= 0.01:
 47             while iteration_update <= self.iteration:
 48                 self.metropolis_rule()
 49             else:
 50                 self.shuchu()
 51         else:
 52             self.shuchu()
 53 
 54     def D_value(self, current_path, update_path):  # 变换前后目标函数差值
 55         # value_list = []
 56         print('计算两个状态的差值...')
 57         current_distance = self.all_dist(current_path)
 58         # value_list.append(current_path)
 59         update_distance = self.all_dist(update_path)
 60         # value_list.append(update_path)
 61         d_value = update_distance-current_distance
 62         return d_value
 63 
 64     def metropolis_rule(self, current_path, update_path,update_t):
 65         de = self.D_value(current_path, update_path)
 66         if de < 0:
 67 
 68             current_path = update_path
 69         else:
 70             p = math.exp(-de/update_t)
 71             if random.random() <= p:
 72                 current_path = update_path
 73 
 74             else:
 75                 path = self.swap(update_path)
 76                 self.metropolis_rule(current_path, path,update_t)
 77         return current_path
 78 
 79     def first_path(self):  # 生成第一条初始化的路径
 80         length = len(self.coordinates)
 81         # 因为对初值不敏感,生成一条随机序列, 第一条路径是随机的
 82         path = random.sample(self.coordinates, length)
 83         return path
 84 
 85     def swap(self, path):  # 随机交换2个城市顺序
 86         print('产生新解...')
 87         city_1 = random.randint(0, len(self.coordinates) - 1)  # 产生第一个交换点
 88         while True:
 89             city_2 = random.randint(0, len(self.coordinates) - 1)  # 产生第二个交换点
 90             if city_2 != city_1:
 91                 break
 92             else:
 93                 continue
 94         path[city_1], path[city_2] = path[city_2], path[city_1]
 95         print('产生新解结束')
 96         return path
 97 
 98     def update_t(self, t):
 99         t_update = self.alpha*t
100         return t_update
101 
102     def between_dist(self, point1, point2):  # 计算两点距离
103 
104         dist_x = point1[0] - point2[0]
105         dist_y = point1[1] - point2[1]
106         dist = dist_x ** 2 + dist_y ** 2
107         dist = math.sqrt(dist)
108         return dist
109 
110     def all_dist(self, path):  # 计算所有点距离,总共30段距离
111         sum_cities = 0
112         n = len(path)
113         for i in range(n - 1):  # 先计算前29段距离
114             sum_cities += self.between_dist(path[i], path[i + 1])
115         sum_cities += self.between_dist(path[n - 1], path[0])  # 计算第30个点和第一个点的距离,形成闭环
116         return sum_cities
117 
118     def shuchu(self):
119         pass
120 
121     def main(self):  # 函数式编程,调用其它函数,进入这个大循环
122 
123         start_time = datetime.datetime.now()
124         t = self.initial_temperature()  # 调用生成初温函数
125         current_path = self.first_path()
126         while t > self.tf:  # 终止条件
127             iteration_number = 0
128             while iteration_number < self.iteration:  # metropolis终止条件
129                     update_path = self.swap(current_path)
130                     de = self.D_value(current_path, update_path)
131 
132                     if de < 0:  # 如果增量为负值,则接受
133 
134                         current_path = update_path
135 
136                     else:  # 产生新解比较
137                         p = math.exp(-de / t)
138                         if random.random() <= p:
139                             current_path = update_path
140 
141                         else:  # 否则保留当前解解,而不是一直产生新解比较,注意误区
142                             current_path = current_path
143                         # else:
144                         #     path = self.swap(update_path)
145                         #     self.metropolis_rule(current_path, path, update_t)
146                     # return current_path
147                     iteration_number += 1
148             t = self.alpha*t
149         distance = self.all_dist(current_path)
150         print(distance)
151         end_time = datetime.datetime.now()
152         this_time = end_time - start_time
153         print('程序运行时间:', this_time)
154         return current_path
155 
156 
157 s1 = SaTSP()
158 s1.main()

 

posted @ 2018-03-23 20:41  最后的绝地武士  阅读(398)  评论(0编辑  收藏  举报