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


      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()
  • 相关阅读:
    Oracle FGA审计记录的清理步骤
    UVa11488-Hyper Prefix Sets(trie树)
    配置Log4j(非常具体)
    poj1190生日蛋糕
    zju1610Count the Colors
    【例9.3】求最长不下降序列
    P1364 医院设置
    P1629 邮递员送信
    P1476 休息中的小呆
    P1330 封锁阳光大学
  • 原文地址:https://www.cnblogs.com/yangmingustb/p/8634306.html
Copyright © 2020-2023  润新知