鱼C论坛

 找回密码
 立即注册
查看: 2934|回复: 12

求助求助 tsp问题

[复制链接]
发表于 2023-4-5 16:50:35 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
大佬们,来帮我看看这大一老师布置的作业正常吗
哪位大佬来帮我写个代码出来
万分感谢!!!
实验2.rar (1.46 KB, 下载次数: 5)
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2023-4-5 16:58:43 | 显示全部楼层
请把里面的内容粘贴过来
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-4-5 16:58:43 | 显示全部楼层
本帖最后由 isdkz 于 2023-4-5 17:19 编辑

这是一个关于解决TSP问题的Python作业。我将提供一个基本的解决方案,

使用简单的贪心算法来解决这个问题。你可以优化这个代码并创建一个PPT来解释你的程序。

首先,我们从CSV文件中读取数据并将其存储在City类的实例中。

  1. import csv
  2. import math

  3. class City:
  4.     def __init__(self, name, x, y):
  5.         self.name = name
  6.         self.x = x
  7.         self.y = y
  8.         
  9.     def distance(self, city):
  10.         return math.sqrt((self.x - city.x)**2 + (self.y - city.y)**2)

  11.     def __str__(self):
  12.         return f"{self.name} ({self.x}, {self.y})"
  13.    
  14. def read_cities_from_csv(file_path):
  15.     cities = []
  16.     with open(file_path, 'r', encoding='utf-8') as file:
  17.         reader = csv.reader(file, delimiter=';')
  18.         for row in reader:
  19.             name, x, y = row
  20.             cities.append(City(name.strip(), float(x), float(y)))
  21.     return cities

  22. cities = read_cities_from_csv("china.csv")
复制代码


接下来,我们将使用一个简单的贪心算法来解决TSP问题:

  1. def find_shortest_path(cities):
  2.     unvisited_cities = cities.copy()
  3.     starting_city = unvisited_cities.pop(0)
  4.     visited_cities = [starting_city]
  5.    
  6.     while unvisited_cities:
  7.         closest_city = min(unvisited_cities, key=lambda city: visited_cities[-1].distance(city))
  8.         visited_cities.append(closest_city)
  9.         unvisited_cities.remove(closest_city)
  10.         
  11.     visited_cities.append(starting_city)
  12.    
  13.     return visited_cities

  14. path = find_shortest_path(cities)
复制代码


现在我们可以计算路径的总距离,并将结果显示出来。

  1. def path_distance(path):
  2.     distance = 0
  3.     for i in range(len(path) - 1):
  4.         distance += path[i].distance(path[i + 1])
  5.     return distance

  6. print("最短路径为:")
  7. for city in path:
  8.     print(city)

  9. print(f"总距离:{path_distance(path)}")
复制代码


这个程序使用了一个简单的贪心算法,它可能无法找到最优解。

但是,它可以作为一个起点,你可以在此基础上对其进行优化,如使用模拟退火、遗传算法等更高级的算法。

创建一个PPT来解释你的代码,包括如何从CSV文件读取数据,以及你使用的算法原理。不要忘记将你的代码和PPT一起提交。


总代码:
  1. import csv
  2. import math

  3. class City:
  4.     def __init__(self, name, x, y):
  5.         self.name = name
  6.         self.x = x
  7.         self.y = y
  8.         
  9.     def distance(self, city):
  10.         return math.sqrt((self.x - city.x)**2 + (self.y - city.y)**2)

  11.     def __str__(self):
  12.         return f"{self.name} ({self.x}, {self.y})"
  13.    
  14. def read_cities_from_csv(file_path):
  15.     cities = []
  16.     with open(file_path, 'r', encoding='utf-8') as file:
  17.         reader = csv.reader(file, delimiter=';')
  18.         for row in reader:
  19.             name, x, y = row
  20.             cities.append(City(name.strip(), float(x), float(y)))
  21.     return cities

  22. def find_shortest_path(cities):
  23.     unvisited_cities = cities.copy()
  24.     starting_city = unvisited_cities.pop(0)
  25.     visited_cities = [starting_city]
  26.    
  27.     while unvisited_cities:
  28.         closest_city = min(unvisited_cities, key=lambda city: visited_cities[-1].distance(city))
  29.         visited_cities.append(closest_city)
  30.         unvisited_cities.remove(closest_city)
  31.         
  32.     visited_cities.append(starting_city)
  33.    
  34.     return visited_cities

  35. def path_distance(path):
  36.     distance = 0
  37.     for i in range(len(path) - 1):
  38.         distance += path[i].distance(path[i + 1])
  39.     return distance

  40. def main():
  41.     cities = read_cities_from_csv("china.csv")
  42.     path = find_shortest_path(cities)
  43.     print("最短路径为:")
  44.     for city in path:
  45.         print(city)

  46.     print(f"总距离:{path_distance(path)}")

  47. if __name__ == '__main__':
  48.     main()
复制代码


贪心算法是一种简单但有效的解决问题的方法,它在每一步都选择局部最优解,希望最终得到的结果是全局最优解。

贪心算法的主要优点是它通常具有较低的时间复杂度,因为它不需要遍历所有可能的解空间。

然而,贪心算法的一个缺点是它并不能保证找到全局最优解,特别是在一些需要全局考虑的问题中。

在解决TSP问题的情况下,我们使用的贪心算法是这样的:

  • 选择一个初始城市,并将其标记为已访问。
  • 从未访问的城市中找到离当前城市最近的城市。
  • 将找到的城市标记为已访问,并将其作为当前城市。
  • 重复步骤2-3,直到所有城市都被访问过。
  • 最后返回到初始城市,完成整个路径。


这种贪心算法的想法是,在每一步都选择距离当前城市最近的下一个城市,这样可以在每个步骤中选择较短的路径。

然而,这种方法并不总是能找到最短的路径,因为它只关注局部最优解,而不是全局最优解。

尽管贪心算法在TSP问题上可能无法找到最优解,但它仍然可以作为其他更复杂算法(如模拟退火、遗传算法等)的一个参考起点。

在实际应用中,可以结合不同的算法来解决问题,以获得更好的性能和结果。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-4-5 17:06:28 | 显示全部楼层
用Python实现
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-4-5 17:07:51 | 显示全部楼层
sfqxx 发表于 2023-4-5 16:58
请把里面的内容粘贴过来

chatgpt?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-4-5 17:19:49 | 显示全部楼层

我的代码中就是用的python呀
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-4-5 17:27:33 | 显示全部楼层
isdkz 发表于 2023-4-5 17:19
我的代码中就是用的python呀

老师让用遗传算法,但是你这个坐标怎么没了
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-4-5 17:28:19 | 显示全部楼层
江山是个艺术家 发表于 2023-4-5 17:27
老师让用遗传算法,但是你这个坐标怎么没了

什么坐标没了?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-4-5 17:33:23 | 显示全部楼层
isdkz 发表于 2023-4-5 17:28
什么坐标没了?

文件里的坐标
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-4-5 17:38:22 | 显示全部楼层

不是有吗?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-4-5 17:47:37 | 显示全部楼层
这个是遗传算法的:

遗传算法是一种基于自然选择和遗传原理的全局优化搜索算法。它适用于解决一些较难的优化问题,如TSP问题。

遗传算法的基本思想是通过模拟自然界中的遗传和变异过程,在解空间中搜索全局最优解。以下是使用遗传算法解决TSP问题的基本步骤:

  • 随机生成初始种群:创建一定数量的随机路径(称为染色体),每个路径表示一个城市访问顺序的解决方案。
  • 评估适应度:计算每个染色体的适应度值,即路径长度的倒数。适应度值越高,表示解决方案越优秀。
  • 选择:按照某种选择策略(如轮盘赌、锦标赛选择等)从当前种群中选取一定数量的染色体,作为下一代种群的父代。
  • 交叉(或称为杂交、重组):根据设定的交叉概率,将父代染色体进行配对并交换部分基因,生成新的子代染色体。常用的交叉方法有顺序交叉、部分映射交叉(PMX)等。
  • 变异:根据设定的变异概率,随机调整子代染色体的部分基因。变异可以引入新的基因特征,避免算法陷入局部最优解。常用的变异方法有交换变异、逆序变异等。
  • 更新种群:将子代染色体替换原种群,形成新的种群。
  • 终止条件:如果达到预设的迭代次数或找到满足要求的解,结束算法。否则,返回第2步,继续迭代。


遗传算法在TSP问题上表现较好,因为它能搜索解空间的较大范围,并以较高概率找到全局最优解。

然而,遗传算法的时间复杂度和空间复杂度较高,需要调整参数(如交叉概率、变异概率等)以获得最佳性能。

示例代码:
  1. import csv
  2. import random
  3. import math
  4. from typing import List, Tuple

  5. class City:
  6.     def __init__(self, name: str, longitude: float, latitude: float):
  7.         self.name = name
  8.         self.longitude = longitude
  9.         self.latitude = latitude

  10.     def __repr__(self):
  11.         return self.name

  12. def euclidean_distance(city1: City, city2: City) -> float:
  13.     x_diff = city1.longitude - city2.longitude
  14.     y_diff = city1.latitude - city2.latitude
  15.     return math.sqrt(x_diff ** 2 + y_diff ** 2)

  16. def load_cities_from_csv(file_path: str) -> List[City]:
  17.     cities = []
  18.     with open(file_path, "r", encoding="utf-8") as file:
  19.         csv_reader = csv.reader(file, delimiter=";")
  20.         for row in csv_reader:
  21.             city = City(row[0], float(row[1]), float(row[2]))
  22.             cities.append(city)
  23.     return cities

  24. def path_distance(path: List[City]) -> float:
  25.     distance = sum(euclidean_distance(path[i - 1], path[i]) for i in range(1, len(path)))
  26.     distance += euclidean_distance(path[-1], path[0])  # 最后一个城市返回到第一个城市
  27.     return distance

  28. class GeneticAlgorithm:
  29.     def __init__(
  30.         self,
  31.         cities: List[City],
  32.         population_size: int = 100,
  33.         generations: int = 1000,
  34.         mutation_rate: float = 0.01,
  35.         elite_size: int = 10
  36.     ):
  37.         self.cities = cities
  38.         self.population_size = population_size
  39.         self.generations = generations
  40.         self.mutation_rate = mutation_rate
  41.         self.elite_size = elite_size

  42.     def create_population(self) -> List[List[City]]:
  43.         return [random.sample(self.cities, len(self.cities)) for _ in range(self.population_size)]

  44.     def fitness(self, path: List[City]) -> float:
  45.         return 1 / path_distance(path)

  46.     def selection(self, population: List[List[City]]) -> List[List[City]]:
  47.         ranked_population = sorted(population, key=self.fitness, reverse=True)
  48.         selected = ranked_population[:self.elite_size]
  49.         weights = [self.fitness(path) for path in ranked_population]
  50.         selected.extend(random.choices(ranked_population, weights, k=self.population_size - self.elite_size))
  51.         return selected

  52.     def crossover(self, parent1: List[City], parent2: List[City]) -> List[City]:
  53.         start, end = random.sample(range(len(parent1)), 2)
  54.         start, end = min(start, end), max(start, end)

  55.         child = [None] * len(parent1)
  56.         child[start:end] = parent1[start:end]

  57.         for city in parent2[end:] + parent2[:end]:
  58.             if city not in child:
  59.                 index = child.index(None)
  60.                 child[index] = city

  61.         return child

  62.     def mutate(self, path: List[City]) -> List[City]:
  63.         for i in range(len(path)):
  64.             if random.random() < self.mutation_rate:
  65.                 j = random.randint(0, len(path) - 1)
  66.                 path[i], path[j] = path[j], path[i]
  67.         return path

  68.     def evolve(self, population: List[List[City]]) -> List[List[City]]:
  69.         selected = self.selection(population)
  70.         children = []

  71.         for i in range(0, len(selected) - 1, 2):
  72.             child1 = self.crossover(selected[i], selected[i + 1])
  73.             child2 = self.crossover(selected[i + 1], selected[i])
  74.             children.extend([child1, child2])
  75.         
  76.             if len(children) < len(population):
  77.                 children.append(selected[-1])
  78.         return [self.mutate(child) for child in children]

  79.     def run(self) -> Tuple[List[City], float]:
  80.         population = self.create_population()

  81.         for _ in range(self.generations):
  82.             population = self.evolve(population)

  83.         best_path = max(population, key=self.fitness)
  84.         return best_path, path_distance(best_path)
  85.    
  86. # 读取城市数据
  87. cities = load_cities_from_csv("china.csv")
  88. # 运行遗传算法
  89. ga = GeneticAlgorithm(cities, population_size=100, generations=1000, mutation_rate=0.01, elite_size=10)
  90. best_path, distance = ga.run()
  91. #输出结果
  92. print("最短路径为:")
  93. for city in best_path:
  94.     print(f"{city.name} ({city.longitude}, {city.latitude})")
  95. print(f"总距离:{distance}")
复制代码



这个示例代码实现了一个针对china.csv数据的遗传算法。它首先从csv文件中读取城市数据,然后运行遗传算法以寻找最佳路径。在运行结束时,它将输出所找到的最佳路径以及其总距离。

请注意,由于遗传算法是一种随机算法,每次运行时找到的解可能略有不同。为了获得更好的结果,可以尝试增加种群大小、代数或改变其他参数。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-4-5 18:22:15 From FishC Mobile | 显示全部楼层
歌者文明清理员 发表于 2023-4-5 17:07
chatgpt?

???
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-4-6 09:32:41 | 显示全部楼层


哈哈,至少利用里类似ChatGPT的工具,并很可能是加上了自动化脚本监测论坛上的提问。。
不然,这位 isdkz 难道是神仙,随时随地盯着论坛,基本每个提问10分钟之内它就会回复,回答的内容也有迹可循。。

反正,我观察 它 好多天了。。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-4-24 15:50

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表