graph TD; A[开始] --> B[读取数据]; B --> C[初始化距离和成本矩阵]; C --> D[初始化参数和信息素]; D --> E[执行蚁群算法];
E --> R[绘制最优路径图]; E --> S[绘制距离优化图];
E --> F[构建解决方案]; F --> G[选择下一个城市]; G --> H[计算路径长度和成本]; H --> I[更新信息素]; I --> J{达到停止条件?}; J -->|是| K[结束]; J -->|否| F;
K --> L[计算最佳解决方案]; L --> M[输出结果];
F --> N[检查蚂蚁是否访问所有城市]; N -->|是| O[添加起始城市到路径]; N -->|否| G;
O --> P[计算路径总长度和成本]; P --> Q[更新最佳解决方案]; Q --> F;
E --> T[绘制成本优化图]; E --> U[绘制帕累托前沿图];
import numpy as np import random import matplotlib.pyplot as plt from matplotlib.collections import PolyCollection import pandas as pd import math from tqdm import tqdm import time
for i inrange(len(city_coords)): for j inrange(len(city_coords)): dist_matrix[i][j] = calc_dist(city_coords.iloc[i], city_coords.iloc[j]) cost_matrix[i][j] = city_costs.iloc[i, j]
# 定义一个计算路径成本的函数 deftour_cost(tour, dist_matrix, cost_matrix): total_dist = sum(dist_matrix[tour[i]][tour[(i + 1) % len(tour)]] for i inrange(len(tour))) total_cost = sum(cost_matrix[tour[i]][tour[(i + 1) % len(tour)]] for i inrange(len(tour))) return total_dist, total_cost
defplot_pareto_frontier(self): distances = [sol[1] for sol inself.all_solutions] costs = [sol[2] for sol inself.all_solutions] paths = [sol[0] for sol inself.all_solutions]
pareto_front = [] pareto_paths = [] for i inrange(len(distances)): is_pareto = True for j inrange(len(distances)): if distances[j] < distances[i] and costs[j] < costs[i]: is_pareto = False break if is_pareto: pareto_front.append((distances[i], costs[i])) pareto_paths.append(paths[i])
pareto_front.sort(key=lambda x: x[0])
# 保存pareto_front到xlsx,包括路径信息 df = pd.DataFrame( {'Distance': [d for d, c in pareto_front], 'Cost': [c for d, c in pareto_front], 'Path': pareto_paths}) df.to_excel('./aco_result/aco_pareto_front.xlsx', index=False)
plt.figure(figsize=(8, 6)) plt.scatter([d for d, c in pareto_front], [c for d, c in pareto_front], color='r', label='Pareto Front') plt.scatter(distances, costs, color='b', label='Solutions', alpha=0.5) plt.title('ACO Pareto Frontier') plt.xlabel('Distance') plt.ylabel('Cost') plt.legend() plt.grid(True) plt.savefig('./aco_result/aco_pareto_frontier.png') plt.show()
for i inrange(len(city_coords)): for j inrange(len(city_coords)): dist_matrix[i][j] = calc_dist(city_coords.iloc[i], city_coords.iloc[j]) cost_matrix[i][j] = city_costs.iloc[i, j]
# 定义一个计算路径成本的函数 deftour_cost(tour, dist_matrix, cost_matrix): """计算给定路径的总距离和总成本""" total_dist = sum(dist_matrix[tour[i]][tour[(i + 1) % len(tour)]] for i inrange(len(tour))) total_cost = sum(cost_matrix[tour[i]][tour[(i + 1) % len(tour)]] for i inrange(len(tour))) return total_dist, total_cost
defplot_solution(self, solution): """绘制最优路径图""" plt.figure(figsize=(8, 6)) cities_x = [city_coords.iloc[i, 0] for i in solution] cities_y = [city_coords.iloc[i, 1] for i in solution] plt.plot(cities_x, cities_y, marker='o', linestyle='-')
# 添加城市编号 for i, (x, y) inenumerate(zip(cities_x, cities_y)): plt.text(x, y, str(i), ha='center', va='bottom', fontsize=8)
defplot_pareto_frontier(self): """绘制帕累托前沿图并保存数据""" distances = [sol[1] for sol inself.all_solutions] costs = [sol[2] for sol inself.all_solutions] tours = [sol[0] for sol inself.all_solutions]
for i inrange(len(distances)): is_pareto = True for j inrange(len(distances)): if distances[j] < distances[i] and costs[j] < costs[i]: is_pareto = False break if is_pareto: pareto_front.append((distances[i], costs[i])) pareto_tours.append(tours[i]) else: dominated_solutions.append((distances[i], costs[i], tours[i]))
pareto_front = sorted(pareto_front, key=lambda x: x[0]) pareto_tours = [pareto_tours[i] for i insorted(range(len(pareto_front)), key=lambda k: pareto_front[k][0])]
# 将帕累托前沿数据保存到 Excel 文件 df = pd.DataFrame({ 'Distance': [d for d, c in pareto_front], 'Cost': [c for d, c in pareto_front], 'Path': pareto_tours }) df.to_excel('./pso_result/pso_pareto_front.xlsx', index=False)
plt.figure(figsize=(8, 6)) plt.scatter([d for d, c, _ in dominated_solutions], [c for d, c, _ in dominated_solutions], color='gray', label='Dominated Solutions', alpha=0.5) plt.scatter([d for d, c in pareto_front], [c for d, c in pareto_front], color='r', label='Pareto Front', marker='o', facecolors='none') plt.plot([d for d, c in pareto_front], [c for d, c in pareto_front], color='r', label='Pareto Frontier', linewidth=2) plt.title('PSO Pareto Frontier') plt.xlabel('Distance') plt.ylabel('Cost') plt.legend() plt.grid(True) plt.savefig('./pso_result/pso_pareto_frontier.png') plt.show()
graph TD; A[开始] --> B[读取数据]; B --> C[创建 TSP 实例]; C --> D[运行 NSGA2 优化器]; D --> E{是否达到最大代数?}; E -->|是| F[结束]; E -->|否| G[选择]; G --> H[交叉和变异]; H --> I[评估子代]; I --> J[选择下一代]; J --> E;
F --> K[获取帕累托前沿]; K --> L[保存到 Excel]; L --> M[查找最小距离和最小成本解]; M --> N[打印绘制结果];
import numpy as np import random import matplotlib.pyplot as plt from deap import base, creator, tools, algorithms import pandas as pd import math from tqdm import tqdm import time
defrun(self): # Initialize population pop = self.toolbox.population(n=self.pop_size)
# Evaluate initial population fitnesses = list(map(self.toolbox.evaluate, pop)) for ind, fit inzip(pop, fitnesses): ind.fitness.values = fit
# Evolution loop for g in tqdm(range(self.max_gen), desc="Running NSGA"): # Selection offspring = self.toolbox.select(pop, len(pop))
# Crossover and mutation offspring = [self.toolbox.clone(ind) for ind in offspring] for i inrange(1, len(offspring), 2): if random.random() < self.cxpb: self.toolbox.mate(offspring[i - 1], offspring[i]) del offspring[i - 1].fitness.values, offspring[i].fitness.values
for mutant in offspring: if random.random() < self.mutpb: self.toolbox.mutate(mutant) del mutant.fitness.values
# Evaluate offspring invalid_ind = [ind for ind in offspring ifnot ind.fitness.valid] fitnesses = map(self.toolbox.evaluate, invalid_ind) for ind, fit inzip(invalid_ind, fitnesses): ind.fitness.values = fit
# Select the next generation pop = self.toolbox.select(pop + offspring, self.pop_size)
# Update minimum distance and minimum cost self.min_distances.append(min(ind.fitness.values[0] for ind in pop)) self.min_costs.append(min(ind.fitness.values[1] for ind in pop))
return pop
defnsga_main(): # Start time start_time = time.time()
# Read data city_coords = pd.read_excel('city_coordinate.xlsx') city_costs = pd.read_excel('city_cost.xlsx')
# Get Pareto front pareto_front = tools.emo.sortNondominated(final_pop, len(final_pop))
# Create a list to store the Pareto front data pareto_front_data = []
# Iterate through the Pareto front and collect the data for individual in pareto_front[0]: distance, cost = tsp.evaluate_individual(individual) pareto_front_data.append((distance, cost, individual))
# Convert the data to a pandas DataFrame and save to Excel pareto_front_df = pd.DataFrame(pareto_front_data, columns=['Distance', 'Cost', 'Path']) pareto_front_df.to_excel('./nsga2_result/nsga_pareto_front.xlsx', index=False)
defplot_route(tsp, route, save_path, title): plt.figure(figsize=(8, 6)) route_x = [tsp.city_coords.iloc[city]['X'] for city in route] route_y = [tsp.city_coords.iloc[city]['Y'] for city in route] route_x.append(route_x[0]) # Close the loop route_y.append(route_y[0]) # Close the loop plt.plot(route_x, route_y, '-o') for i, city inenumerate(route): plt.text(tsp.city_coords.iloc[city]['X'], tsp.city_coords.iloc[city]['Y'], str(city), fontsize=8) plt.xlabel('X Coordinate') plt.ylabel('Y Coordinate') plt.title(title) plt.savefig(save_path) plt.show()
# Plot Pareto front distances = [ind.fitness.values[0] for ind in pareto_front[0]] costs = [ind.fitness.values[1] for ind in pareto_front[0]] #plt.plot(distances, costs, '-r', label='Pareto Front')
# Plot Pareto optimal solutions pareto_distances = [ind.fitness.values[0] for ind in pareto_front[0]] pareto_costs = [ind.fitness.values[1] for ind in pareto_front[0]] plt.scatter(pareto_distances, pareto_costs, facecolors='none', edgecolors='r', label='Pareto Optimal Solutions')
# Plot dominated solutions dominated_distances = [ind.fitness.values[0] for ind in final_pop if ind notin pareto_front[0]] dominated_costs = [ind.fitness.values[1] for ind in final_pop if ind notin pareto_front[0]] plt.scatter(dominated_distances, dominated_costs, color='gray', label='Dominated Solutions')
# Analysis Function defanalysis(file_path): data = pd.read_excel(file_path) data1 = data.copy() data1 = data1.drop(columns=['Path']) data1['Distance'] = normalization1(data1['Distance']) data1['Cost'] = normalization1(data1['Cost']) [result, z1, weight] = topsis(data1) best_solution_index = result['排序'].idxmin() best_solution_data = data.loc[best_solution_index] print("最优解的原数据:") print(best_solution_data) optimal_path = [int(x) for x in best_solution_data['Path'].strip('[]').split(', ')] return optimal_path
# Plot Solution Function defplot_solution(optimal_path, file_name): plt.figure(figsize=(8, 6)) cities_x = [city_coords.iloc[i, 0] for i in optimal_path] cities_y = [city_coords.iloc[i, 1] for i in optimal_path] plt.plot(cities_x, cities_y, marker='o', linestyle='-')
for i, (x, y) inenumerate(zip(cities_x, cities_y)): plt.text(x, y, str(i), ha='center', va='bottom', fontsize=8)