import random
import math
import numpy as np
import time
# 相关的系数
PC = 0.55 # 交叉概率
PM = 0.05 # 变异概率
POP_SIZE = 100 # 种群规模
N_GENERATIONS = 700 # 进化代数
N_CITIES = 31 # 城市数量
SEED = 20 # 随机种子
# 城市坐标
city_pos = [
[1304, 2312], [3639, 1315], [4177, 2244], [3712, 1399], [3488, 1535],
[3326, 1556], [3238, 1229], [4196, 1004], [4312, 790], [4386, 570],
[3007, 1970], [2562, 1756], [2788, 1491], [2381, 1676], [1332, 695],
[3715, 1678], [3918, 2179], [4061, 2370], [3780, 2212], [3676, 2578],
[4029, 2838], [4263, 2931], [3429, 1908], [3507, 2367], [3394, 2643],
[3439, 3201], [2935, 3240], [3140, 3550], [2545, 2357], [2778, 2826],
[2370, 2975]
]
# 定义个体类
class Individual:
def __init__(self, sequence):
self.sequence = sequence # 城市访问序列
self.fitness = 0 # 适应度
self.p_fitness = 0 # 适应度概率
self.sum_p_fitness = 0 # 累加适应度概率
# 计算路径的适应度
def calculate_fitness(self):
total_distance = 0 # 总的距离
for i in range(N_CITIES):
city1 = self.sequence[i]
city2 = self.sequence[(i + 1) % N_CITIES] # 回到起始城市
total_distance += self.calculate_distance(city1, city2)
self.fitness = 50000 - total_distance # 适应度越高越好
# 计算两个城市之间的距离
@staticmethod
def calculate_distance(city1, city2):
x1, y1 = city_pos[city1 - 1]
x2, y2 = city_pos[city2 - 1]
return math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2)
# 初始化种群
def initialize_population():
population = []
for _ in range(POP_SIZE):
sequence = list(range(1, N_CITIES + 1))
random.shuffle(sequence) # 随机打乱城市顺序
individual = Individual(sequence)
population.append(individual)
return population
# 计算适应度
def calculate_fitness(population):
for individual in population:
individual.calculate_fitness()
# 选择操作
def selection(population):
population.sort(key=lambda ind: ind.fitness, reverse=True) # 按适应度排序
selected = population[:POP_SIZE // 4] # 选择适应度前 25% 的个体
# 轮盘选择
fitness_sum = sum(ind.fitness for ind in population)
probabilities = [ind.fitness / fitness_sum for ind in population]
cumulative_probabilities = np.cumsum(probabilities)
while len(selected) < POP_SIZE:
r = random.random()
for i, cum_prob in enumerate(cumulative_probabilities):
if r <= cum_prob:
selected.append(population[i])
break
return selected
# 交叉操作
def crossover(selected):
next_population = []
while len(next_population) < POP_SIZE:
parent1, parent2 = random.sample(selected, 2)
if random.random() <= PC: # 按照交叉概率进行交叉
cross_point = random.randint(1, N_CITIES - 1)
child1_sequence = parent1.sequence[:cross_point] + \
[city for city in parent2.sequence if city not in parent1.sequence[:cross_point]]
child2_sequence = parent2.sequence[:cross_point] + \
[city for city in parent1.sequence if city not in parent2.sequence[:cross_point]]
next_population.append(Individual(child1_sequence))
next_population.append(Individual(child2_sequence))
else:
next_population.append(Individual(parent1.sequence))
next_population.append(Individual(parent2.sequence))
return next_population
# 变异操作
def mutation(population):
for individual in population:
if random.random() <= PM: # 按照变异概率进行变异
idx1, idx2 = random.sample(range(N_CITIES), 2) # 随机选择两个城市进行交换
individual.sequence[idx1], individual.sequence[idx2] = individual.sequence[idx2], individual.sequence[idx1]
# 遗传算法主函数
def genetic_algorithm():
population = initialize_population() # 初始化种群
max_fitness_history = [] # 记录每代的最大适应度
for generation in range(N_GENERATIONS):
calculate_fitness(population) # 计算适应度
max_fitness = max(ind.fitness for ind in population) # 找到最大适应度
max_fitness_history.append(max_fitness)
print(f"代数: {generation}, 最大适应度: {max_fitness}")
selected = selection(population) # 选择
next_population = crossover(selected) # 交叉
mutation(next_population) # 变异
population = next_population # 更新种群
# 输出结果
best_individual = max(population, key=lambda ind: ind.fitness)
print("最佳路径:", "->".join(map(str, best_individual.sequence)))
print("路径长度:", 50000 - best_individual.fitness)
if __name__ == "__main__":
start_time = time.time()
genetic_algorithm()
print("总时间:", time.time() - start_time, "秒")