import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
def calc_distance(city1, city2):
return np.linalg.norm(np.array(city1) - np.array(city2))
def calc_distances(cities):
n_cities = len(cities)
distances = np.zeros((n_cities, n_cities))
for i in range(n_cities):
for j in range(i + 1, n_cities):
distances[i][j] = distances[j][i] = calc_distance(cities[i], cities[j])
return distances
class AntColony:
def __init__(self, distances, n_ants, n_iterations, decay, alpha=1, beta=5, rho=0.1, Q=1):
self.distances = distances
self.pheromone = np.ones_like(distances) / len(distances)
self.n_ants = n_ants
self.n_iterations = n_iterations
self.decay = decay
self.alpha = alpha
self.beta = beta
self.rho = rho
self.Q = Q
self.shortest_path_lengths = []
def run(self):
shortest_path = None
shortest_path_length = np.inf
for _ in range(self.n_iterations):
all_paths = self.gen_all_paths()
self.spread_pheromone(all_paths)
shortest_path, shortest_path_length = self.get_shortest(all_paths, shortest_path, shortest_path_length)
self.pheromone *= (1 - self.rho)
self.shortest_path_lengths.append(shortest_path_length)
return shortest_path, shortest_path_length
def spread_pheromone(self, all_paths):
for path in all_paths:
for move in path:
self.pheromone[move] += self.Q / self.distances[move]
def gen_path_dist(self, path):
total = 0
for move in path:
total += self.distances[move]
return total
def gen_all_paths(self):
all_paths = []
for _ in range(self.n_ants):
path = self.gen_path()
all_paths.append(path)
return all_paths
def gen_path(self):
n_cities = len(self.distances)
path = []
visited = set()
start = np.random.randint(n_cities)
visited.add(start)
prev = start
for _ in range(n_cities - 1):
next_city = self.pick_city(prev, visited)
path.append((prev, next_city))
prev = next_city
visited.add(next_city)
path.append((prev, start))
return path
def pick_city(self, prev, visited):
pheromone = np.copy(self.pheromone[prev])
pheromone[list(visited)] = 0
row = pheromone ** self.alpha * (1.0 / (self.distances[prev] + 1e-6) ** self.beta)
norm_row = row / row.sum()
next_city = np.random.choice(range(len(self.distances)), 1, p=norm_row)[0]
return next_city
def get_shortest(self, all_paths, shortest_path, shortest_path_length):
for path in all_paths:
path_dist = self.gen_path_dist(path)
if path_dist < shortest_path_length:
shortest_path = [(int(a), int(b)) for (a, b) in path]
shortest_path_length = path_dist
return shortest_path, shortest_path_length
try:
df = pd.read_excel("100个城市的坐标.xlsx", header=None)
cities = df.iloc[:, [0, 1]].values
assert cities.shape[1] == 2, "坐标数据必须包含X,Y两列"
except FileNotFoundError:
print("错误:Excel文件未找到,请检查以下事项:")
print("1. 文件是否位于当前工作目录")
print("2. 文件名是否为'100个城市的坐标.xlsx'")
print("3. 文件扩展名是否正确(.xlsx)")
exit()
except Exception as e:
print(f"数据加载失败:{str(e)}")
exit()
# 计算距离矩阵
distances = calc_distances(cities)
# 参数设置
n_ants = 20
n_iterations = 1000
decay = 0.1
alpha = 1
beta = 2
rho = 0.1
Q = 1
# 创建并运行蚁群算法
ant_colony = AntColony(distances, n_ants, n_iterations, decay, alpha, beta, rho, Q)
shortest_path, shortest_path_length = ant_colony.run()
# 输出结果
print("最短路径:", shortest_path)
print("最短路径长度:", shortest_path_length)
# 绘制迭代曲线
plt.rcParams['font.sans-serif'] = 'SimHei' # 设置中文显示
plt.rcParams['axes.unicode_minus'] = False
plt.figure(figsize=(10, 5))
plt.plot(range(1, n_iterations + 1), ant_colony.shortest_path_lengths)
plt.xlabel('迭代')
plt.ylabel('最短路径长度')
plt.title('优化过程')
plt.grid(True)
plt.show()
# 路径可视化函数
def plot_path(cities, path):
path_order = [path[0][0]] + [move[1] for move in path]
x, y = cities[path_order, 0], cities[path_order, 1]
plt.figure(figsize=(12, 8))
# 绘制城市点并添加编号(从1开始)
for idx, (xi, yi) in enumerate(cities):
plt.scatter(xi, yi, color='red', s=6,zorder=2)
plt.text(xi, yi, str(idx + 1), fontsize=8,ha='center',va='bottom',
color='black',zorder=3)
# 绘制路径连线
plt.rcParams['font.sans-serif'] = 'SimHei' # 设置中文显示
plt.rcParams['axes.unicode_minus'] = False
plt.plot(x, y, linestyle='-', marker='o', color='blue', linewidth=1, markersize=4, zorder=1)
plt.xlabel('X坐标', fontsize=12)
plt.ylabel('Y坐标', fontsize=12)
plt.title('最佳路线 城市编号(1-100)', fontsize=14)
plt.grid(True, linestyle='--', alpha=0.7)
plt.tight_layout()
plt.show()
plot_path(cities, shortest_path) 修改路径输出格式为:最短路径序列: 40,41,95,13,16,66,96,56,85,97,27,38,10,64,5,81,57,71,51,72,8,49,29,2,50,4,12,61,62,92,22,79,80,21,83,7,17,9,63,43,32,37,19,24,54,69,58,11,74,59,68,89,87,53,23,84,67,0,34,33,60,86,47,90,42,82,77,25,28,36,31,1,44,76,6,93,30,52,18,14,39,98,88,26,75,3,20,73,91,65,48,99,78,70,45,35,94,15,46,55
最短路径长度: 8302.192271155956
最新发布