HPCC2025/test_new_GA/GA_MTSP.bak

251 lines
8.1 KiB
Plaintext
Raw Permalink Normal View History

2025-04-02 21:33:40 +08:00
import numpy as np
import random
import math
import matplotlib.pyplot as plt
import time
class MTSP_GA:
def __init__(self, cities, vehicle_num, population_size=200, max_iterations=1500):
"""
初始化遗传算法求解器
Args:
cities: 城市坐标数组,第一个城市为起始点
vehicle_num: 车辆数量
population_size: 种群大小
max_iterations: 最大迭代次数
"""
self.cities = np.array(cities)
self.city_count = len(cities)
self.vehicle_num = vehicle_num
self.origin = 0 # 起始点
# GA参数
self.population_size = population_size
self.max_iterations = max_iterations
self.retain_rate = 0.3 # 强者存活率
self.random_rate = 0.5 # 弱者存活概率
self.mutation_rate = 0.3 # 变异率
# 计算距离矩阵
self.distance_matrix = self._compute_distance_matrix()
# 记录收敛过程
self.distance_history = []
self.best_path_history = []
def _compute_distance_matrix(self):
"""计算城市间距离矩阵"""
distance = np.zeros((self.city_count, self.city_count))
for i in range(self.city_count):
for j in range(self.city_count):
distance[i][j] = math.sqrt(
(self.cities[i][0] - self.cities[j][0]) ** 2 +
(self.cities[i][1] - self.cities[j][1]) ** 2
)
return distance
def _create_individual(self):
"""生成初始个体"""
index = [i for i in range(self.city_count)]
index.remove(self.origin)
a = int(np.floor(len(index)/self.vehicle_num))
X = []
for i in range(self.vehicle_num):
if i < self.vehicle_num-1:
x = index[a*i:a*(i+1)]
else:
x = index[a*i:]
X.append(x)
return X
def _get_total_distance(self, X):
"""计算路径总距离"""
distance = 0
distance_list = []
for x in X:
d = self.distance_matrix[self.origin][x[0]] # 从起点到第一个城市
d += self.distance_matrix[self.origin][x[-1]] # 从最后一个城市返回起点
for i in range(len(x)-1):
d += self.distance_matrix[x[i]][x[i+1]]
distance += d
distance_list.append(d)
return distance, distance_list
def _selection(self, population):
"""选择操作"""
graded = [[self._get_total_distance(x)[0], x] for x in population]
graded = [x[1] for x in sorted(graded)]
retain_length = int(len(graded) * self.retain_rate)
parents = graded[:retain_length]
for chromosome in graded[retain_length:]:
if random.random() < self.random_rate:
parents.append(chromosome)
return parents
def _crossover(self, parents):
"""交叉操作"""
target_count = self.population_size - len(parents)
children = []
while len(children) < target_count:
male_index = random.randint(0, len(parents) - 1)
female_index = random.randint(0, len(parents) - 1)
if male_index != female_index:
male = parents[male_index]
female = parents[female_index]
gene1 = []
gene2 = []
for i in range(len(male)):
gene1 += male[i]
gene2 += female[i]
left = random.randint(0, len(gene1)//2)
right = random.randint(left + 1, len(gene1))
cut = gene1[left:right]
copy = gene2.copy()
for j in cut:
copy.remove(j)
child = copy + cut
a = int(np.floor(len(child)/self.vehicle_num))
child_c = []
for i in range(self.vehicle_num):
if i < self.vehicle_num - 1:
x = child[a * i:a * (i + 1)]
else:
x = child[a * i:]
child_c.append(x)
children.append(child_c)
return children
def _mutation(self, children):
"""变异操作"""
for i in range(len(children)):
if random.random() < self.mutation_rate:
child = children[i]
for j in range(int(np.floor(len(child)/2))):
a = 2*j
u = random.randint(1, len(child[a]) - 1)
w = random.randint(1, len(child[a+1]) - 1)
child_1 = child[a][:u].copy()
child_2 = child[a][u:].copy()
child_3 = child[a+1][:w].copy()
child_4 = child[a+1][w:].copy()
child_a = child_1+child_3
child_b = child_2+child_4
child[a] = child_a
child[a+1] = child_b
children[i] = child.copy()
return children
def _get_best_solution(self, population):
"""获取最优解"""
graded = [[self._get_total_distance(x)[0], x] for x in population]
graded = sorted(graded, key=lambda x: x[0])
return graded[0][0], graded[0][1]
def solve(self):
"""
求解MTSP加入早停机制
当连续50轮没有更好的解时停止迭代
"""
# 初始化种群
population = [self._create_individual() for _ in range(self.population_size)]
# 初始化早停相关变量
best_distance = float('inf')
early_stop_counter = 0
early_stop_threshold = 100
# 迭代优化
for i in range(self.max_iterations):
parents = self._selection(population)
children = self._crossover(parents)
children = self._mutation(children)
population = parents + children
# 记录当前最优解
current_distance, current_path = self._get_best_solution(population)
self.distance_history.append(current_distance)
self.best_path_history.append(current_path)
# 早停判断
if current_distance < best_distance:
best_distance = current_distance
best_path = current_path
early_stop_counter = 0 # 重置计数器
else:
early_stop_counter += 1
# 如果连续50轮没有更好的解则停止迭代
if early_stop_counter >= early_stop_threshold:
print(f"Early stopping at iteration {i} due to no improvement in {early_stop_threshold} iterations")
break
# 返回最优解
return best_distance, best_path
def plot_convergence(self):
"""绘制收敛曲线"""
plt.plot(range(len(self.distance_history)), self.distance_history)
plt.xlabel('Iteration')
plt.ylabel('Total Distance')
plt.title('Convergence Curve')
plt.show()
def main():
# 城市坐标
cities = np.array([
(456, 320), # 起点(基地)
(228, 0),
(912, 0),
(0, 80),
(114, 80),
(570, 160),
(798, 160),
(342, 240),
(684, 240),
(570, 400),
(912, 400),
(114, 480),
(228, 480),
(342, 560),
(684, 560),
(0, 640),
(798, 640)
])
# 设置随机种子
np.random.seed(42)
random.seed(42)
# 创建求解器实例
solver = MTSP_GA(
cities=cities,
vehicle_num=4,
population_size=200,
max_iterations=1500
)
# 求解
start_time = time.time()
best_distance, best_path = solver.solve()
end_time = time.time()
# 输出结果
print(f"最优总距离: {best_distance:.2f}")
print("最优路径方案:")
for i, path in enumerate(best_path):
print(f"车辆{i+1}的路径: {path}")
print(f"求解时间: {end_time - start_time:.2f}秒")
# 绘制收敛曲线
solver.plot_convergence()
if __name__ == "__main__":
main()