模拟退火算法求解TSP问题(python)

模拟退火算法求解TSP的步骤参考书籍《Matlab智能算法30个案例分析》。

问题描述

TSP问题描述在该书籍的第4章

在这里插入图片描述

算法流程

在这里插入图片描述

部分实现代码片段

坐标轴转换成两点之间直线距离长度的代码

coordinates = np.array([(16.47, 96.10),
                            (16.47, 94.44),
                            (20.09, 92.54),
                            (22.39, 93.37),
                            (25.23, 97.24),
                            (22.00, 96.05),
                            (20.47, 97.02),
                            (17.20, 96.29),
                            (16.30, 97.38),
                            (14.05, 98.12),
                            (16.53, 97.38),
                            (21.52, 95.59),
                            (19.41, 97.13),
                            (20.09, 92.55),])

# 将距离坐标矩阵转换成两点之间实际的直线距离
city_num = coordinates.shape[0]


def get_distanceGraph(coordinates):
    # 计算城市间的欧式距离
    diatance_graph = np.zeros((city_num, city_num))
    # 初始化生成矩阵
    for i in range(city_num):
        for j in range(i, city_num):
            diatance_graph[i][j] = diatance_graph[j][i] = np.linalg.norm(coordinates[i] - coordinates[j])
    print("diatance_graph", diatance_graph)
    return diatance_graph

求解TSP问题路径长度的代码

def cal_length(cur_solution, distance_graph):
    # 计算路线长度
    total_length = 0
    visited_city_list = [cur_solution[0]]
    for i in range(city_num):
        visited_city = visited_city_list[-1]
        cur_city = cur_solution[i]
        visited_city_id = visited_city - 1
        cur_city_id = cur_city - 1
        next_city_length = distance_graph[visited_city_id][cur_city_id]
        total_length += next_city_length
        visited_city_list.append(cur_city)
    print("total_length", total_length)
    return total_length

使用一个路径长度矩阵相对简单,可以进行笔算验证解结果的算例,验证计算TSP路径长度的代码是可行的

可以笔算验证的算例代码

# 各个节点之间的欧氏距离
distance_list = [[0, 4.0, 6.0, 7.5, 9.0, 20.0, 10.0, 16.0, 8.0],
                [4.0, 0, 6.5, 4.0, 10.0, 5.0, 7.5, 11.0, 10.0],
                [6.0, 6.5, 0, 7.5, 10.0, 10.0, 7.5, 7.5, 7.5],
                [7.5, 4.0, 7.5, 0, 10.0, 5.0, 9.0, 9.0, 15.0],
                [9.0, 10.0, 10.0, 10.0, 0, 10.0, 7.5, 7.5, 10.0],
                [20.0, 5.0, 10.0, 5.0, 10.0, 0, 7.0, 9.0, 7.5],
                [10.0, 7.5, 7.5, 9.0, 7.5, 7.0, 0, 7.0, 10.0],
                [15.0, 11.0, 7.5, 9.0, 7.5, 9.0, 7.0, 0, 10.0],
                [8.0, 10.0, 7.5, 15.0, 10.0, 7.5, 10.0, 10.0, 0]]
demand_node_num = 9
supply_node_num = 0
city_num = 9
distance_graph = np.zeros((demand_node_num+supply_node_num, demand_node_num+supply_node_num))
for i in range(demand_node_num+supply_node_num):
    distance_graph[i] = np.array(distance_list[i])

cur_solution = [3, 9, 6, 4, 7, 8, 1, 5, 2]
length = cal_length(cur_solution, distance_graph)
print("length", length)

Metropolis准则函数

# Metropolis准则函数
def Metropolis_func(cur_solution, new_solution, distance_graph, cur_temp):
    # 计算新旧解之间的能量之差,如果能量降低:以概率1接受新解,如果能量升高,以一定概率接受劣化解
    dC = cal_length(new_solution, distance_graph) - cal_length(cur_solution, distance_graph)
    if dC < 0:
        cur_solution = new_solution
        cur_length = cal_length(cur_solution, distance_graph)
    elif pow(math.e, -dC/cur_temp) >= np.random.rand():  # 大于一个随机生成的数:
        cur_solution = new_solution
        cur_length = cal_length(cur_solution, distance_graph)
    else:
        cur_length = cal_length(cur_solution, distance_graph)
    return cur_solution, cur_length

算法迭代图形

在这里插入图片描述

算法程序还有待改进空间,生成的迭代图形和最优结果和书上的存在差异。

在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
TSP问题是一个经典的组合优化问题,它的目标是找到一条经过所有给定城市并回到起点的最短路径。混合遗传模拟退火算法(Hybrid Genetic Simulated Annealing Algorithm,HGSA)是一种结合了遗传算法模拟退火算法的优化算法,可以用于求解TSP问题。 以下是使用Python实现HGSA算法求解TSP问题的示例代码: ```python import numpy as np import random # TSP问题中的城市坐标 cities = np.array([[60, 200], [180, 200], [80, 180], [140, 180], [20, 160], [100, 160], [200, 160], [140, 140], [40, 120], [100, 120], [180, 100], [60, 80], [120, 80], [180, 60], [20, 40], [100, 40], [200, 40], [20, 20], [60, 20], [160, 20]]) # 计算两个城市之间的距离 def distance(city1, city2): return np.sqrt(np.sum((city1 - city2) ** 2)) # 计算路径的总长度 def path_length(path): length = 0 for i in range(len(path) - 1): length += distance(cities[path[i]], cities[path[i+1]]) length += distance(cities[path[-1]], cities[path[0]]) return length # 初始化种群 def init_population(pop_size, num_cities): population = [] for i in range(pop_size): path = list(range(num_cities)) random.shuffle(path) population.append(path) return population # 交叉操作 def crossover(parent1, parent2): child = [-1] * len(parent1) start, end = sorted([random.randint(0, len(parent1)-1) for _ in range(2)]) for i in range(start, end+1): child[i] = parent1[i] j = 0 for i in range(len(parent2)): if parent2[i] not in child: if child[j] == -1: child[j] = parent2[i] j += 1 return child # 变异操作 def mutation(path): path = path.copy() start, end = sorted([random.randint(0, len(path)-1) for _ in range(2)]) path[start:end+1] = reversed(path[start:end+1]) return path # 模拟退火操作 def simulated_annealing(path, temperature): old_length = path_length(path) new_path = mutation(path) new_length = path_length(new_path) if new_length < old_length: return new_path else: delta = new_length - old_length probability = np.exp(-delta / temperature) if random.random() < probability: return new_path else: return path # 适应度函数 def fitness(path): return 1 / path_length(path) # 选择操作 def selection(population, fitness_values): idx = np.random.choice(len(population), size=2, p=fitness_values/fitness_values.sum(), replace=False) return population[idx[0]], population[idx[1]] # HGSA算法 def hgsa(pop_size, num_cities, max_iter): population = init_population(pop_size, num_cities) for i in range(max_iter): # 交叉操作 new_population = [] fitness_values = np.array([fitness(path) for path in population]) for j in range(pop_size // 2): parent1, parent2 = selection(population, fitness_values) child1 = crossover(parent1, parent2) child2 = crossover(parent2, parent1) new_population.append(child1) new_population.append(child2) # 模拟退火操作 for j in range(pop_size): temperature = (max_iter - i) / max_iter new_population[j] = simulated_annealing(new_population[j], temperature) population = new_population # 返回最优解 fitness_values = np.array([fitness(path) for path in population]) idx = np.argmax(fitness_values) return population[idx], path_length(population[idx]) # 测试代码 path, length = hgsa(100, len(cities), 1000) print("最短路径:", path) print("路径长度:", length) ``` 在上面的代码中,我们首先定义了TSP问题中的城市坐标,然后实现了计算两个城市之间距离、计算路径总长度、初始化种群、交叉操作、变异操作、模拟退火操作、适应度函数和选择操作等函数。最后,我们使用HGSA算法求解TSP问题,并输出最优解的路径和长度。 需要注意的是,上面的代码只是一个示例,实际应用中需要根据具体问题进行调整和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Logintern09

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值