100 lines
1.9 KiB
Python
100 lines
1.9 KiB
Python
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,
|
|
)
|
|
|
|
best = [
|
|
0,
|
|
29,
|
|
9,
|
|
27,
|
|
18,
|
|
14,
|
|
5,
|
|
17,
|
|
13,
|
|
30,
|
|
20,
|
|
34,
|
|
15,
|
|
22,
|
|
23,
|
|
24,
|
|
26,
|
|
33,
|
|
32,
|
|
7,
|
|
12,
|
|
37,
|
|
11,
|
|
2,
|
|
6,
|
|
16,
|
|
35,
|
|
1,
|
|
36,
|
|
3,
|
|
28,
|
|
21,
|
|
8,
|
|
31,
|
|
4,
|
|
10,
|
|
25,
|
|
19,
|
|
]
|
|
|
|
|
|
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
|
|
|
|
|
|
fitness_function = build_fitness_function(cities)
|
|
|
|
# Сохраняем лучшую особь за всё время
|
|
fig = plt.figure(figsize=(7, 7))
|
|
fig.suptitle(
|
|
f"Лучший возможный маршрут. " f"Длина: {fitness_function(best):.4f}",
|
|
fontsize=14,
|
|
y=0.95,
|
|
)
|
|
|
|
# Рисуем лучший маршрут в поколении
|
|
ax = fig.add_subplot(1, 1, 1)
|
|
plot_tour(cities, best, ax)
|
|
filename = f"best_possible.png"
|
|
path_png = os.path.join("", filename)
|
|
fig.savefig(path_png, dpi=150, bbox_inches="tight")
|
|
plt.close(fig)
|