This commit is contained in:
2025-10-15 16:43:11 +03:00
parent 2cf0693070
commit 740a7be984
18 changed files with 2087 additions and 0 deletions

111
lab3/main.py Normal file
View File

@@ -0,0 +1,111 @@
import math
import os
import matplotlib.pyplot as plt
import numpy as np
from gen import (
Chromosome,
GARunConfig,
genetic_algorithm,
initialize_random_population,
inversion_mutation_fn,
partially_mapped_crossover_fn,
plot_fitness_history,
plot_tour,
swap_mutation_fn,
)
# В списке из 89 городов только 38 уникальных
cities = set()
with open("data.txt", "r") as file:
for line in file:
# x и y поменяны местами в визуализациях в методичке
_, y, x = line.split()
cities.add((float(x), float(y)))
cities = list(cities)
def euclidean_distance(city1, city2):
return math.sqrt((city1[0] - city2[0]) ** 2 + (city1[1] - city2[1]) ** 2)
def build_fitness_function(cities):
def fitness_function(chromosome: Chromosome) -> float:
return sum(
euclidean_distance(cities[chromosome[i]], cities[chromosome[i + 1]])
for i in range(len(chromosome) - 1)
) + euclidean_distance(cities[chromosome[0]], cities[chromosome[-1]])
return fitness_function
config = GARunConfig(
fitness_func=build_fitness_function(cities),
initialize_population_fn=initialize_random_population,
cities=cities,
crossover_fn=partially_mapped_crossover_fn,
# mutation_fn=swap_mutation_fn,
mutation_fn=inversion_mutation_fn,
pop_size=500,
elitism=3,
pc=0.9,
pm=0.3,
max_generations=2500,
# max_best_repetitions=10,
minimize=False,
seed=17,
save_generations=[
1,
5,
20,
50,
100,
300,
500,
700,
900,
1500,
2000,
2500,
3000,
3500,
4000,
4500,
],
log_every_generation=True,
)
result = genetic_algorithm(config)
# Сохраняем конфиг и результаты в файлы
config.save()
result.save(config.results_dir)
# Выводим результаты
print(f"Лучшая особь: {result.best_generation.best}")
print(f"Лучшее значение фитнеса: {result.best_generation.best_fitness:.6f}")
print(f"Количество поколений: {result.generations_count}")
print(f"Время выполнения: {result.time_ms:.2f} мс")
# Сохраняем лучшую особь за всё время
fig = plt.figure(figsize=(7, 7))
fig.suptitle(
f"Поколение #{result.best_generation.number}. "
f"Лучшая особь: {result.best_generation.best_fitness:.4f}. "
f"Среднее значение: {np.mean(result.best_generation.fitnesses):.4f}",
fontsize=14,
y=0.95,
)
# Рисуем лучший маршрут в поколении
ax = fig.add_subplot(1, 1, 1)
plot_tour(config.cities, result.best_generation.best, ax)
filename = f"best_generation_{result.best_generation.number:03d}.png"
path_png = os.path.join(config.results_dir, filename)
fig.savefig(path_png, dpi=150, bbox_inches="tight")
plt.close(fig)
# Рисуем график прогресса по поколениям
plot_fitness_history(
result, save_path=os.path.join(config.results_dir, "fitness_history.png")
)