python3 SA模拟退火算法解决100个城市的TSP问题

该项目应用局部搜索算法(LS)和模拟退火算法(SA)解决旅行商问题(TSP)。通过比较,发现SA在效率上优于LS。在LS基础上使用SA和2-OPT策略优化,成功达到实验目标的10%,针对eil101(101个城市)的最优解为629。Python实现的算法在Intel Core i5-8400上运行,展示了不同参数下的性能和效果,强调了正确选择局部搜索策略的重要性。
摘要由CSDN通过智能技术生成

由于内容是从自己写的报告(word文件)中复制而来,因此排版可能有问题,建议直接看github中的报告pdf

地址:https://github.com/c980129/Simulated-annealing-algorithm

 

摘要:该项目主要是利用局部搜索算法(LS)和模拟退火算法(SA)解决TSP问题。先是使用LS求解TSP问题,再尝试SA问题,比较两者,在效率上SA更占有。最后再在LS的基础上使用SA,再优化SA部分算法,尝试求解TSP问题。选用的TSP测例为eil101(有101个城市)。代码使用python语言编写,因此运算速度因为语言特性比编程语言要低。

 

1.导言

旅行商问题,即TSP问题(Traveling Salesman Problem),是求最短路径的问题,即“已给一个n个点的完全图,每条边都有一个长度,求总长度最短的经过每个顶点正好一次的封闭回路”。TSP是组合优化问题,可以被证明具有NPC计算复杂性。如果希望暴力搜索其最佳解,其复杂度将是O(n!),其计算量随着n的增加将轻易超过目前计算机的可能算力。因此我们需要用更智能的方法求解。

于是我们先考虑局部搜索算法。局部搜索算法是贪心算法,他往往往邻域中最好的状态搜索,因此容易进入局部最优结果,而无法跳出局部最优的区域。

第二部分使用模拟退火算法。模拟退火算法从某一较高初温出发,伴随温度参数的不断下降,结合概率突跳特性在解空间中随机寻找目标函数的全局最优解,即在局部最优解能概率性地跳出并最终趋于全局最优。模拟退火算法比起局部搜索算法,赋予了一定跳出局部最优解的能力,但能否跳出局部最优解依然依赖随机性。

 

2.实验过程

       首先使用两种不同的局部搜索算法。

       第一种选择邻域的方法是随机交换两个城市在序列中的顺序。每次循环中产生的候选序列为城市数(以下用Cs表示)*10,并从中选择一个最优的(距离最短的)作为下一步。

       第二种选择邻域的方法是随机交换三个城市在序列中的顺序。每次循环中产生的候选序列为Cs*10,并从中选择一个最优的(距离最短的)作为下一步。

       这两种算法都按以下步骤实现:

  1. 录入初始状态,并打乱顺序产生一组随机状态,从这组状态(包括初始状态)中选最佳的状态作为起点;
  2. Repeat:
    1. 产生一个集合S
    2. Repeat 10 * Cs times:
      1. 将当前状态加入S
      2. 产生2个(或3个)互不相同的、范围为[1, 城市数-1]的随机数
      3. 以这2个(或3个)随机数作为下标交换城市在序列中的顺序
      4. 将交换后的序列加入S中
    3. 从S中选择一个最优的序列,作为当前状态
    4. 如果当前状态与之前状态一样,则跳出循环。

可以知道,当当前状态与邻域中最佳状态一样时跳出循环,可以理解成到达局部最优解。虽然实际上这个邻域并没有完全覆盖当前状态的所有邻居,但覆盖全部邻居需要(Cs-1) * (Cs-2)(第二种邻域为(Cs-1) * (Cs-2) * (Cs-3))个数据,将加大每次循环的耗时,而且最终结果同样是会进入局部最优结果而无法跳出。

 

第二部分在LS的基础上加入SA。

一开始我的SA流程如下:

  1. 得到初始状态,设定初温T,降温方式,结束条件
  2. 外循环:
    1. 当符合结束条件则跳出循环
    2. 内循环:
      1. 令当前解能量为D0
      2. 通过邻域搜索策略得到一组解并取其中最优(不包括当前状态)解能量为D1
      3. 令ΔE = D1–D0
        1. If ΔE <= 0: 则使P = 1
  • 2
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是用Python实现模拟退火算法解决TSP问题的示例代码: ```python import random import math import sys class TSP: def __init__(self, filename): self.nodes = [] self.distances = {} self.read_file(filename) def read_file(self, filename): with open(filename, "r") as f: for line in f: x, y = map(float, line.split()) self.nodes.append((x, y)) def calc_distance(self, node1, node2): return math.sqrt((node1[0] - node2[0]) ** 2 + (node1[1] - node2[1]) ** 2) def calc_distances(self): n = len(self.nodes) for i in range(n): for j in range(i + 1, n): distance = self.calc_distance(self.nodes[i], self.nodes[j]) self.distances[(i, j)] = distance self.distances[(j, i)] = distance def get_distance(self, node1, node2): if node1 > node2: node1, node2 = node2, node1 return self.distances[(node1, node2)] def get_path_distance(self, path): distance = 0 for i in range(len(path)): distance += self.get_distance(path[i], path[(i + 1) % len(path)]) return distance class SimulatedAnnealing: def __init__(self, tsp, initial_temp, cooling_rate, num_iterations): self.tsp = tsp self.initial_temp = initial_temp self.cooling_rate = cooling_rate self.num_iterations = num_iterations self.current_path = list(range(len(self.tsp.nodes))) self.best_path = self.current_path.copy() self.temperature = self.initial_temp def acceptance_probability(self, current_energy, new_energy, temperature): if new_energy < current_energy: return 1.0 else: return math.exp((current_energy - new_energy) / temperature) def run(self): for i in range(self.num_iterations): new_path = self.current_path.copy() index1 = random.randint(0, len(self.current_path) - 1) index2 = random.randint(0, len(self.current_path) - 1) new_path[index1], new_path[index2] = new_path[index2], new_path[index1] current_energy = self.tsp.get_path_distance(self.current_path) new_energy = self.tsp.get_path_distance(new_path) if self.acceptance_probability(current_energy, new_energy, self.temperature) > random.random(): self.current_path = new_path if self.tsp.get_path_distance(self.current_path) < self.tsp.get_path_distance(self.best_path): self.best_path = self.current_path.copy() self.temperature *= self.cooling_rate return self.best_path if __name__ == "__main__": tsp = TSP(sys.argv[1]) tsp.calc_distances() sa = SimulatedAnnealing(tsp, 100000.0, 0.99, 10000) best_path = sa.run() print("Best path found: ", best_path) print("Path distance: ", tsp.get_path_distance(best_path)) ``` 在此示例中,`TSP`类用于读取TSP问题的节点坐标,并计算节点之间的距离。`SimulatedAnnealing`类实现模拟退火算法,包括计算能量、接受概率和运行算法的主循环。最后,我们使用这些类来解决TSP问题,找到最短的路径并输出结果。 要运行脚本,请在命令行中输入以下命令: ```bash python tsp.py <tsp_file> ``` 其中 `<tsp_file>` 是包含节点坐标的文件的路径。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值