2025-03-17 16:40:01 +08:00
|
|
|
{
|
|
|
|
"cells": [
|
|
|
|
{
|
|
|
|
"cell_type": "code",
|
|
|
|
"execution_count": 4,
|
|
|
|
"metadata": {},
|
|
|
|
"outputs": [
|
|
|
|
{
|
|
|
|
"data": {
|
|
|
|
"text/html": [
|
|
|
|
"<div>\n",
|
|
|
|
"<style scoped>\n",
|
|
|
|
" .dataframe tbody tr th:only-of-type {\n",
|
|
|
|
" vertical-align: middle;\n",
|
|
|
|
" }\n",
|
|
|
|
"\n",
|
|
|
|
" .dataframe tbody tr th {\n",
|
|
|
|
" vertical-align: top;\n",
|
|
|
|
" }\n",
|
|
|
|
"\n",
|
|
|
|
" .dataframe thead th {\n",
|
|
|
|
" text-align: right;\n",
|
|
|
|
" }\n",
|
|
|
|
"</style>\n",
|
|
|
|
"<table border=\"1\" class=\"dataframe\">\n",
|
|
|
|
" <thead>\n",
|
|
|
|
" <tr style=\"text-align: right;\">\n",
|
|
|
|
" <th></th>\n",
|
|
|
|
" <th>File Name</th>\n",
|
|
|
|
" <th>Line 1</th>\n",
|
|
|
|
" <th>Line 2</th>\n",
|
|
|
|
" <th>Line 3</th>\n",
|
|
|
|
" <th>Line 4</th>\n",
|
|
|
|
" <th>Line 5</th>\n",
|
|
|
|
" <th>Line 6</th>\n",
|
|
|
|
" </tr>\n",
|
|
|
|
" </thead>\n",
|
|
|
|
" <tbody>\n",
|
|
|
|
" <tr>\n",
|
|
|
|
" <th>0</th>\n",
|
|
|
|
" <td>CHN144.tsp</td>\n",
|
|
|
|
" <td>NAME : CHN144</td>\n",
|
|
|
|
" <td>COMMENT : China 144-city problem</td>\n",
|
|
|
|
" <td>TYPE : TSP</td>\n",
|
|
|
|
" <td>DIMENSION : 144</td>\n",
|
|
|
|
" <td>EDGE_WEIGHT_TYPE : EUC_2D</td>\n",
|
|
|
|
" <td>NODE_COORD_SECTION</td>\n",
|
|
|
|
" </tr>\n",
|
|
|
|
" <tr>\n",
|
|
|
|
" <th>1</th>\n",
|
|
|
|
" <td>eil101.tsp</td>\n",
|
|
|
|
" <td>NAME : eil101</td>\n",
|
|
|
|
" <td>COMMENT : 101-city problem (Christofides/Eilon)</td>\n",
|
|
|
|
" <td>TYPE : TSP</td>\n",
|
|
|
|
" <td>DIMENSION : 101</td>\n",
|
|
|
|
" <td>EDGE_WEIGHT_TYPE : EUC_2D</td>\n",
|
|
|
|
" <td>NODE_COORD_SECTION</td>\n",
|
|
|
|
" </tr>\n",
|
|
|
|
" <tr>\n",
|
|
|
|
" <th>2</th>\n",
|
|
|
|
" <td>eil76.tsp</td>\n",
|
|
|
|
" <td>NAME: eil76</td>\n",
|
|
|
|
" <td>TYPE: TSP</td>\n",
|
|
|
|
" <td>COMMENT: 76-city problem (Christofides/Eilon)</td>\n",
|
|
|
|
" <td>DIMENSION: 76</td>\n",
|
|
|
|
" <td>EDGE_WEIGHT_TYPE: EUC_2D</td>\n",
|
|
|
|
" <td>NODE_COORD_SECTION</td>\n",
|
|
|
|
" </tr>\n",
|
|
|
|
" <tr>\n",
|
|
|
|
" <th>3</th>\n",
|
|
|
|
" <td>GR96.tsp</td>\n",
|
|
|
|
" <td>NAME: gr96</td>\n",
|
|
|
|
" <td>TYPE: TSP</td>\n",
|
|
|
|
" <td>COMMENT: Africa-Subproblem of 666-city TSP (Gr...</td>\n",
|
|
|
|
" <td>DIMENSION: 96</td>\n",
|
|
|
|
" <td>EDGE_WEIGHT_TYPE: GEO</td>\n",
|
|
|
|
" <td>DISPLAY_DATA_TYPE: COORD_DISPLAY</td>\n",
|
|
|
|
" </tr>\n",
|
|
|
|
" <tr>\n",
|
|
|
|
" <th>4</th>\n",
|
|
|
|
" <td>PBK411.tsp</td>\n",
|
|
|
|
" <td>NAME : pbk411</td>\n",
|
|
|
|
" <td>COMMENT : Bonn VLSI data set with 411 points</td>\n",
|
|
|
|
" <td>TYPE : TSP</td>\n",
|
|
|
|
" <td>DIMENSION : 411</td>\n",
|
|
|
|
" <td>EDGE_WEIGHT_TYPE : EUC_2D</td>\n",
|
|
|
|
" <td>NODE_COORD_SECTION</td>\n",
|
|
|
|
" </tr>\n",
|
|
|
|
" <tr>\n",
|
|
|
|
" <th>5</th>\n",
|
|
|
|
" <td>PR76.tsp</td>\n",
|
|
|
|
" <td>NAME : pr76</td>\n",
|
|
|
|
" <td>COMMENT : 76-city problem (Padberg/Rinaldi)</td>\n",
|
|
|
|
" <td>TYPE : TSP</td>\n",
|
|
|
|
" <td>DIMENSION : 76</td>\n",
|
|
|
|
" <td>EDGE_WEIGHT_TYPE : EUC_2D</td>\n",
|
|
|
|
" <td>NODE_COORD_SECTION</td>\n",
|
|
|
|
" </tr>\n",
|
|
|
|
" <tr>\n",
|
|
|
|
" <th>6</th>\n",
|
|
|
|
" <td>RBU737.tsp</td>\n",
|
|
|
|
" <td>NAME : rbu737</td>\n",
|
|
|
|
" <td>COMMENT : Bonn VLSI data set with 737 points</td>\n",
|
|
|
|
" <td>TYPE : TSP</td>\n",
|
|
|
|
" <td>DIMENSION : 737</td>\n",
|
|
|
|
" <td>EDGE_WEIGHT_TYPE : EUC_2D</td>\n",
|
|
|
|
" <td>NODE_COORD_SECTION</td>\n",
|
|
|
|
" </tr>\n",
|
|
|
|
" <tr>\n",
|
|
|
|
" <th>7</th>\n",
|
|
|
|
" <td>ulysses16.tsp</td>\n",
|
|
|
|
" <td>NAME: ulysses16.tsp</td>\n",
|
|
|
|
" <td>TYPE: TSP</td>\n",
|
|
|
|
" <td>COMMENT: Odyssey of Ulysses (Groetschel/Padberg)</td>\n",
|
|
|
|
" <td>DIMENSION: 16</td>\n",
|
|
|
|
" <td>EDGE_WEIGHT_TYPE: GEO</td>\n",
|
|
|
|
" <td>DISPLAY_DATA_TYPE: COORD_DISPLAY</td>\n",
|
|
|
|
" </tr>\n",
|
|
|
|
" <tr>\n",
|
|
|
|
" <th>8</th>\n",
|
|
|
|
" <td>ulysses8.tsp</td>\n",
|
|
|
|
" <td>NAME: ulysses16.tsp</td>\n",
|
|
|
|
" <td>TYPE: TSP</td>\n",
|
|
|
|
" <td>COMMENT: Odyssey of Ulysses (Groetschel/Padberg)</td>\n",
|
|
|
|
" <td>DIMENSION: 8</td>\n",
|
|
|
|
" <td>EDGE_WEIGHT_TYPE: GEO</td>\n",
|
|
|
|
" <td>DISPLAY_DATA_TYPE: COORD_DISPLAY</td>\n",
|
|
|
|
" </tr>\n",
|
|
|
|
" <tr>\n",
|
|
|
|
" <th>9</th>\n",
|
|
|
|
" <td>XIT1083.tsp</td>\n",
|
|
|
|
" <td>NAME : xit1083</td>\n",
|
|
|
|
" <td>COMMENT : Bonn VLSI data set with 1083 points</td>\n",
|
|
|
|
" <td>TYPE : TSP</td>\n",
|
|
|
|
" <td>DIMENSION : 1083</td>\n",
|
|
|
|
" <td>EDGE_WEIGHT_TYPE : EUC_2D</td>\n",
|
|
|
|
" <td>NODE_COORD_SECTION</td>\n",
|
|
|
|
" </tr>\n",
|
|
|
|
" </tbody>\n",
|
|
|
|
"</table>\n",
|
|
|
|
"</div>"
|
|
|
|
],
|
|
|
|
"text/plain": [
|
|
|
|
" File Name Line 1 \\\n",
|
|
|
|
"0 CHN144.tsp NAME : CHN144 \n",
|
|
|
|
"1 eil101.tsp NAME : eil101 \n",
|
|
|
|
"2 eil76.tsp NAME: eil76 \n",
|
|
|
|
"3 GR96.tsp NAME: gr96 \n",
|
|
|
|
"4 PBK411.tsp NAME : pbk411 \n",
|
|
|
|
"5 PR76.tsp NAME : pr76 \n",
|
|
|
|
"6 RBU737.tsp NAME : rbu737 \n",
|
|
|
|
"7 ulysses16.tsp NAME: ulysses16.tsp \n",
|
|
|
|
"8 ulysses8.tsp NAME: ulysses16.tsp \n",
|
|
|
|
"9 XIT1083.tsp NAME : xit1083 \n",
|
|
|
|
"\n",
|
|
|
|
" Line 2 \\\n",
|
|
|
|
"0 COMMENT : China 144-city problem \n",
|
|
|
|
"1 COMMENT : 101-city problem (Christofides/Eilon) \n",
|
|
|
|
"2 TYPE: TSP \n",
|
|
|
|
"3 TYPE: TSP \n",
|
|
|
|
"4 COMMENT : Bonn VLSI data set with 411 points \n",
|
|
|
|
"5 COMMENT : 76-city problem (Padberg/Rinaldi) \n",
|
|
|
|
"6 COMMENT : Bonn VLSI data set with 737 points \n",
|
|
|
|
"7 TYPE: TSP \n",
|
|
|
|
"8 TYPE: TSP \n",
|
|
|
|
"9 COMMENT : Bonn VLSI data set with 1083 points \n",
|
|
|
|
"\n",
|
|
|
|
" Line 3 Line 4 \\\n",
|
|
|
|
"0 TYPE : TSP DIMENSION : 144 \n",
|
|
|
|
"1 TYPE : TSP DIMENSION : 101 \n",
|
|
|
|
"2 COMMENT: 76-city problem (Christofides/Eilon) DIMENSION: 76 \n",
|
|
|
|
"3 COMMENT: Africa-Subproblem of 666-city TSP (Gr... DIMENSION: 96 \n",
|
|
|
|
"4 TYPE : TSP DIMENSION : 411 \n",
|
|
|
|
"5 TYPE : TSP DIMENSION : 76 \n",
|
|
|
|
"6 TYPE : TSP DIMENSION : 737 \n",
|
|
|
|
"7 COMMENT: Odyssey of Ulysses (Groetschel/Padberg) DIMENSION: 16 \n",
|
|
|
|
"8 COMMENT: Odyssey of Ulysses (Groetschel/Padberg) DIMENSION: 8 \n",
|
|
|
|
"9 TYPE : TSP DIMENSION : 1083 \n",
|
|
|
|
"\n",
|
|
|
|
" Line 5 Line 6 \n",
|
|
|
|
"0 EDGE_WEIGHT_TYPE : EUC_2D NODE_COORD_SECTION \n",
|
|
|
|
"1 EDGE_WEIGHT_TYPE : EUC_2D NODE_COORD_SECTION \n",
|
|
|
|
"2 EDGE_WEIGHT_TYPE: EUC_2D NODE_COORD_SECTION \n",
|
|
|
|
"3 EDGE_WEIGHT_TYPE: GEO DISPLAY_DATA_TYPE: COORD_DISPLAY \n",
|
|
|
|
"4 EDGE_WEIGHT_TYPE : EUC_2D NODE_COORD_SECTION \n",
|
|
|
|
"5 EDGE_WEIGHT_TYPE : EUC_2D NODE_COORD_SECTION \n",
|
|
|
|
"6 EDGE_WEIGHT_TYPE : EUC_2D NODE_COORD_SECTION \n",
|
|
|
|
"7 EDGE_WEIGHT_TYPE: GEO DISPLAY_DATA_TYPE: COORD_DISPLAY \n",
|
|
|
|
"8 EDGE_WEIGHT_TYPE: GEO DISPLAY_DATA_TYPE: COORD_DISPLAY \n",
|
|
|
|
"9 EDGE_WEIGHT_TYPE : EUC_2D NODE_COORD_SECTION "
|
|
|
|
]
|
|
|
|
},
|
|
|
|
"execution_count": 4,
|
|
|
|
"metadata": {},
|
|
|
|
"output_type": "execute_result"
|
|
|
|
}
|
|
|
|
],
|
|
|
|
"source": [
|
|
|
|
"import os\n",
|
|
|
|
"import pandas as pd\n",
|
|
|
|
"\n",
|
|
|
|
"# 定义文件夹路径\n",
|
|
|
|
"folder_path = './data'\n",
|
|
|
|
"\n",
|
|
|
|
"# 初始化一个空的DataFrame来存储信息\n",
|
|
|
|
"columns = ['File Name', 'Line 1', 'Line 2', 'Line 3', 'Line 4', 'Line 5', 'Line 6']\n",
|
|
|
|
"df = pd.DataFrame(columns=columns)\n",
|
|
|
|
"\n",
|
|
|
|
"# 遍历文件夹中的所有文件\n",
|
|
|
|
"for file_name in os.listdir(folder_path):\n",
|
|
|
|
" if file_name.endswith('.tsp'):\n",
|
|
|
|
" file_path = os.path.join(folder_path, file_name)\n",
|
|
|
|
" with open(file_path, 'r') as file:\n",
|
|
|
|
" lines = file.readlines()\n",
|
|
|
|
" # 取前六行作为基本信息\n",
|
|
|
|
" basic_info = lines[:6]\n",
|
|
|
|
" # 如果行数不足六行,用空字符串填充\n",
|
|
|
|
" while len(basic_info) < 6:\n",
|
|
|
|
" basic_info.append('')\n",
|
|
|
|
" # 将信息添加到DataFrame中\n",
|
|
|
|
" new_row = pd.DataFrame({\n",
|
|
|
|
" 'File Name': [file_name],\n",
|
|
|
|
" 'Line 1': [basic_info[0].strip()],\n",
|
|
|
|
" 'Line 2': [basic_info[1].strip()],\n",
|
|
|
|
" 'Line 3': [basic_info[2].strip()],\n",
|
|
|
|
" 'Line 4': [basic_info[3].strip()],\n",
|
|
|
|
" 'Line 5': [basic_info[4].strip()],\n",
|
|
|
|
" 'Line 6': [basic_info[5].strip()]\n",
|
|
|
|
" })\n",
|
|
|
|
" df = pd.concat([df, new_row], ignore_index=True)\n",
|
|
|
|
"\n",
|
|
|
|
"# 显示表格\n",
|
|
|
|
"df\n"
|
|
|
|
]
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"cell_type": "code",
|
2025-03-18 16:51:30 +08:00
|
|
|
"execution_count": 5,
|
2025-03-17 16:40:01 +08:00
|
|
|
"metadata": {},
|
|
|
|
"outputs": [
|
|
|
|
{
|
|
|
|
"data": {
|
2025-03-18 16:51:30 +08:00
|
|
|
"image/png": "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
|
2025-03-17 16:40:01 +08:00
|
|
|
"text/plain": [
|
|
|
|
"<Figure size 800x800 with 2 Axes>"
|
|
|
|
]
|
|
|
|
},
|
|
|
|
"metadata": {},
|
|
|
|
"output_type": "display_data"
|
|
|
|
}
|
|
|
|
],
|
|
|
|
"source": [
|
|
|
|
"import numpy as np\n",
|
|
|
|
"import matplotlib.pyplot as plt\n",
|
|
|
|
"from matplotlib.path import Path\n",
|
|
|
|
"import matplotlib.patches as patches\n",
|
|
|
|
"import os\n",
|
|
|
|
"\n",
|
|
|
|
"# 确保plot文件夹存在\n",
|
|
|
|
"if not os.path.exists('./plot'):\n",
|
|
|
|
" os.makedirs('./plot')\n",
|
|
|
|
"\n",
|
|
|
|
"# 设置中文显示\n",
|
|
|
|
"plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签\n",
|
|
|
|
"plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号\n",
|
|
|
|
"\n",
|
|
|
|
"# 生成10个随机分布的节点\n",
|
|
|
|
"np.random.seed(2025)\n",
|
|
|
|
"n_points = 10\n",
|
|
|
|
"points = np.random.rand(n_points, 2) * 100\n",
|
|
|
|
"\n",
|
|
|
|
"# 计算两点间距离的函数\n",
|
|
|
|
"def calculate_distance(route):\n",
|
|
|
|
" total = 0\n",
|
|
|
|
" for i in range(len(route)):\n",
|
|
|
|
" j = (i + 1) % len(route)\n",
|
|
|
|
" city1 = points[route[i]]\n",
|
|
|
|
" city2 = points[route[j]]\n",
|
|
|
|
" total += np.sqrt(np.sum((city1 - city2) ** 2))\n",
|
|
|
|
" return total\n",
|
|
|
|
"\n",
|
|
|
|
"# 生成随机解\n",
|
|
|
|
"random_solution = list(range(n_points))\n",
|
|
|
|
"np.random.shuffle(random_solution)\n",
|
|
|
|
"random_distance = calculate_distance(random_solution)\n",
|
|
|
|
"\n",
|
|
|
|
"# 使用启发式算法求解TSP问题\n",
|
|
|
|
"def heuristic_solution():\n",
|
|
|
|
" n = n_points\n",
|
|
|
|
" # 初始解:从城市0开始\n",
|
|
|
|
" current_solution = [0]\n",
|
|
|
|
" unvisited = set(range(1, n))\n",
|
|
|
|
" \n",
|
|
|
|
" # 不断选择最近的未访问城市\n",
|
|
|
|
" while unvisited:\n",
|
|
|
|
" current = current_solution[-1]\n",
|
|
|
|
" # 找到距离当前城市最近的未访问城市\n",
|
|
|
|
" next_city = min(unvisited, \n",
|
|
|
|
" key=lambda x: np.sqrt(np.sum((points[current] - points[x]) ** 2)))\n",
|
|
|
|
" current_solution.append(next_city)\n",
|
|
|
|
" unvisited.remove(next_city)\n",
|
|
|
|
" \n",
|
|
|
|
" # 2-opt局部搜索优化\n",
|
|
|
|
" improved = True\n",
|
|
|
|
" while improved:\n",
|
|
|
|
" improved = False\n",
|
|
|
|
" for i in range(n-2):\n",
|
|
|
|
" for j in range(i+2, n):\n",
|
|
|
|
" # 计算当前路径长度\n",
|
|
|
|
" old_distance = (\n",
|
|
|
|
" np.sqrt(np.sum((points[current_solution[i]] - points[current_solution[i+1]]) ** 2)) +\n",
|
|
|
|
" np.sqrt(np.sum((points[current_solution[j]] - points[current_solution[(j+1)%n]]) ** 2))\n",
|
|
|
|
" )\n",
|
|
|
|
" # 计算交换后的路径长度\n",
|
|
|
|
" new_distance = (\n",
|
|
|
|
" np.sqrt(np.sum((points[current_solution[i]] - points[current_solution[j]]) ** 2)) +\n",
|
|
|
|
" np.sqrt(np.sum((points[current_solution[i+1]] - points[current_solution[(j+1)%n]]) ** 2))\n",
|
|
|
|
" )\n",
|
|
|
|
" \n",
|
|
|
|
" if new_distance < old_distance:\n",
|
|
|
|
" # 如果交换后更优,则进行2-opt交换\n",
|
|
|
|
" current_solution[i+1:j+1] = reversed(current_solution[i+1:j+1])\n",
|
|
|
|
" improved = True\n",
|
|
|
|
" break\n",
|
|
|
|
" if improved:\n",
|
|
|
|
" break\n",
|
|
|
|
" \n",
|
|
|
|
" # 添加回到起点\n",
|
|
|
|
" current_solution.append(0)\n",
|
|
|
|
" return current_solution\n",
|
|
|
|
"\n",
|
|
|
|
"better_solution = heuristic_solution()\n",
|
|
|
|
"better_distance = calculate_distance(better_solution)\n",
|
|
|
|
"\n",
|
|
|
|
"# 创建并保存随机解图\n",
|
|
|
|
"plt.figure(figsize=(8, 8))\n",
|
|
|
|
"ax1 = plt.gca()\n",
|
|
|
|
"for i, point in enumerate(points):\n",
|
|
|
|
" ax1.scatter(point[0], point[1], c='blue', s=100)\n",
|
2025-03-18 16:51:30 +08:00
|
|
|
" ax1.annotate(f'{i}', (point[0], point[1]), xytext=(5, 5), textcoords='offset points',fontsize = 20)\n",
|
2025-03-17 16:40:01 +08:00
|
|
|
"\n",
|
|
|
|
"for i in range(len(random_solution)):\n",
|
|
|
|
" j = (i + 1) % len(random_solution)\n",
|
|
|
|
" city1 = points[random_solution[i]]\n",
|
|
|
|
" city2 = points[random_solution[j]]\n",
|
|
|
|
" ax1.plot([city1[0], city2[0]], [city1[1], city2[1]], 'r-')\n",
|
|
|
|
"\n",
|
2025-03-18 16:51:30 +08:00
|
|
|
"ax1.set_title(f'总距离: {random_distance:.2f}',fontsize = 26)\n",
|
2025-03-17 16:40:01 +08:00
|
|
|
"ax1.grid(True)\n",
|
|
|
|
"ax1.margins(0.13)\n",
|
|
|
|
"plt.savefig('./plot/random_solution.png',dpi=300)\n",
|
|
|
|
"plt.close()\n",
|
|
|
|
"\n",
|
|
|
|
"# 创建并保存贪心解图\n",
|
|
|
|
"plt.figure(figsize=(8, 8))\n",
|
|
|
|
"ax2 = plt.gca()\n",
|
|
|
|
"for i, point in enumerate(points):\n",
|
|
|
|
" ax2.scatter(point[0], point[1], c='blue', s=100)\n",
|
2025-03-18 16:51:30 +08:00
|
|
|
" ax2.annotate(f'{i}', (point[0], point[1]), xytext=(5, 5), textcoords='offset points',fontsize = 20)\n",
|
2025-03-17 16:40:01 +08:00
|
|
|
"\n",
|
|
|
|
"for i in range(len(better_solution)):\n",
|
|
|
|
" j = (i + 1) % len(better_solution)\n",
|
|
|
|
" city1 = points[better_solution[i]]\n",
|
|
|
|
" city2 = points[better_solution[j]]\n",
|
|
|
|
" ax2.plot([city1[0], city2[0]], [city1[1], city2[1]], 'g-')\n",
|
|
|
|
"\n",
|
2025-03-18 16:51:30 +08:00
|
|
|
"ax2.set_title(f'总距离: {better_distance:.2f}',fontsize = 26)\n",
|
2025-03-17 16:40:01 +08:00
|
|
|
"ax2.grid(True)\n",
|
|
|
|
"ax2.margins(0.13)\n",
|
|
|
|
"plt.savefig('./plot/better_solution.png')\n",
|
|
|
|
"plt.close()\n",
|
|
|
|
"\n",
|
|
|
|
"# 显示两个图\n",
|
|
|
|
"fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 8))\n",
|
|
|
|
"\n",
|
|
|
|
"# 绘制随机解\n",
|
|
|
|
"for i, point in enumerate(points):\n",
|
|
|
|
" ax1.scatter(point[0], point[1], c='blue', s=100)\n",
|
2025-03-18 16:51:30 +08:00
|
|
|
" ax1.annotate(f'{i}', (point[0], point[1]), xytext=(5, 5), textcoords='offset points',fontsize = 20)\n",
|
2025-03-17 16:40:01 +08:00
|
|
|
"\n",
|
|
|
|
"for i in range(len(random_solution)):\n",
|
|
|
|
" j = (i + 1) % len(random_solution)\n",
|
|
|
|
" city1 = points[random_solution[i]]\n",
|
|
|
|
" city2 = points[random_solution[j]]\n",
|
|
|
|
" ax1.plot([city1[0], city2[0]], [city1[1], city2[1]], 'r-')\n",
|
|
|
|
"\n",
|
2025-03-18 16:51:30 +08:00
|
|
|
"ax1.set_title(f'总距离: {random_distance:.2f}',fontsize = 26)\n",
|
2025-03-17 16:40:01 +08:00
|
|
|
"ax1.grid(True)\n",
|
|
|
|
"ax1.margins(0.13)\n",
|
|
|
|
"\n",
|
|
|
|
"# 绘制贪心解\n",
|
|
|
|
"for i, point in enumerate(points):\n",
|
|
|
|
" ax2.scatter(point[0], point[1], c='blue', s=100)\n",
|
2025-03-18 16:51:30 +08:00
|
|
|
" ax2.annotate(f'{i}', (point[0], point[1]), xytext=(5, 5), textcoords='offset points',fontsize = 20)\n",
|
2025-03-17 16:40:01 +08:00
|
|
|
"\n",
|
|
|
|
"for i in range(len(better_solution)):\n",
|
|
|
|
" j = (i + 1) % len(better_solution)\n",
|
|
|
|
" city1 = points[better_solution[i]]\n",
|
|
|
|
" city2 = points[better_solution[j]]\n",
|
|
|
|
" ax2.plot([city1[0], city2[0]], [city1[1], city2[1]], 'g-')\n",
|
|
|
|
"\n",
|
2025-03-18 16:51:30 +08:00
|
|
|
"ax2.set_title(f'总距离: {better_distance:.2f}',fontsize = 26)\n",
|
2025-03-17 16:40:01 +08:00
|
|
|
"ax2.grid(True)\n",
|
|
|
|
"ax2.margins(0.13)\n",
|
|
|
|
"\n",
|
|
|
|
"plt.tight_layout()\n",
|
|
|
|
"plt.show()"
|
|
|
|
]
|
|
|
|
}
|
|
|
|
],
|
|
|
|
"metadata": {
|
|
|
|
"kernelspec": {
|
|
|
|
"display_name": "lead",
|
|
|
|
"language": "python",
|
|
|
|
"name": "python3"
|
|
|
|
},
|
|
|
|
"language_info": {
|
|
|
|
"codemirror_mode": {
|
|
|
|
"name": "ipython",
|
|
|
|
"version": 3
|
|
|
|
},
|
|
|
|
"file_extension": ".py",
|
|
|
|
"mimetype": "text/x-python",
|
|
|
|
"name": "python",
|
|
|
|
"nbconvert_exporter": "python",
|
|
|
|
"pygments_lexer": "ipython3",
|
|
|
|
"version": "3.11.11"
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"nbformat": 4,
|
|
|
|
"nbformat_minor": 2
|
|
|
|
}
|