- •Постановка задачи:
- •Формализовать описание задачи в математическом виде. Выделить жесткие и мягкие ограничения.
- •Описать представление решения в виде хромосомы. Пояснить выбранное представление и какие ограничения есть на хромосому.
- •Разработать метрику для оценки качества решения. Пояснить разработанную метрику, и как она позволяет соблюдать мягкие и жесткие ограничения.
- •Выполнение га:
- •Выбрать операции для га: метод отбора, метод скрещивания, метод мутации. Обосновать выбор.
- •Подобрать параметры га: размер популяции, вероятность скрещивания и мутации, количество поколений (если есть другие параметры, то и их тоже). Описать процесс подбора параметров.
- •Провести оптимизацию и визуализировать полученное решение. Графически отобразить решение. Например, траектория броска мяча или в виде таблицы показать расписание работы.
- •Построить график зависимости лучшей и средней приспособленности в зависимости от поколения.
Провести оптимизацию и визуализировать полученное решение. Графически отобразить решение. Например, траектория броска мяча или в виде таблицы показать расписание работы.
Сначала импортируется библиотека matplotlib.pyplot для визуализации графика. Затем для 30 городов генерируются случайные координаты и приоритеты городов, запускается генетический алгоритм и возвращается наилучшее найденное решение. Функция GA создает популяцию случайных маршрутов (перестановок городов), применяет к ним операции скрещивания, мутации и отбора, возвращает лучший найденный маршрут и его длину с учетом штрафов. Функция plot_route визуализирует полученный маршрут на плоскости. Цвет точки указывает приоритет города (от зеленого до черного). Зеленые линии – допустимые перелеты, красные – превышающие 5 км.
В конце программа выводит лучший найденный маршрут, его стоимость, а также отображает график маршрута. Реализация представлена в Листинге 2.3.1. Результат представлен в Листинге 2.3.2 и на Рисунке 2.3.3.
Листинг 2.3.1 – Запуск и визуализация ГА
import matplotlib.pyplot as plt
def GA(coords, priorities, params): dist_matrix = compute_distance_matrix(coords) N = len(coords)
if not hasattr(creator, 'FitnessMin'): creator.create("FitnessMin", base.Fitness, weights=(-1.0,)) if not hasattr(creator, 'Individual'): creator.create("Individual", list, fitness=creator.FitnessMin)
toolbox = base.Toolbox() toolbox.register("indices", random.sample, range(N), N) toolbox.register("individual", tools.initIterate, creator.Individual, toolbox.indices) toolbox.register("population", tools.initRepeat, list, toolbox.individual) toolbox.register("evaluate", eval_route, dist_matrix=dist_matrix, penalty_coef=params['penalty_coef']) toolbox.register("mate", tools.cxOrdered) toolbox.register("mutate", tools.mutShuffleIndexes, indpb=0.2) toolbox.register("select", tools.selTournament, tournsize=params['tour_size'])
pop = toolbox.population(n=params['pop_size']) hof = tools.HallOfFame(1) stats = tools.Statistics(lambda ind: ind.fitness.values) stats.register("min", np.min) stats.register("avg", np.mean)
pop, log = algorithms.eaSimple( pop, toolbox, cxpb=params['cxpb'], mutpb=params['mutpb'], ngen=params['ngen'], stats=stats, halloffame=hof, verbose=False )
return hof[0], hof[0].fitness.values[0], log
def plot_route(coords, route, priorities, Dmax=5.0): colors = {1: 'green', 2: 'yellow', 3: 'orange', 4: 'red', 5: 'black'} plt.figure(figsize=(7, 7)) for i, (x, y) in enumerate(coords): plt.scatter(x, y, color=colors[priorities[i]], s=80, edgecolor='black') plt.text(x + 0.3, y + 0.3, str(i), fontsize=9)
for i in range(len(route)): a, b = route[i], route[(i + 1) % len(route)] xa, ya = coords[a] xb, yb = coords[b] dist = np.hypot(xa - xb, ya - yb) color = 'red' if dist > Dmax else 'green' plt.plot([xa, xb], [ya, yb], color=color, linestyle='-', linewidth=1.5)
plt.title("Оптимальный маршрут почтальона") plt.xlabel("X (км)") plt.ylabel("Y (км)") plt.axis('equal') plt.grid() plt.show()
N = 30 # число городов PARAMS = { 'cxpb': 0.63, 'mutpb': 0.22, 'penalty_coef': 4.4, 'tour_size': 4, 'ngen': 200, 'pop_size': 100 }
coords = [(random.uniform(0, 30), random.uniform(0, 30)) for _ in range(N)] priorities = [random.randint(1, 5) for _ in range(N)]
best_route, best_score, log = GA(coords, priorities, PARAMS) print("Лучший маршрут:", best_route) print("Длина маршрута с учетом штрафов:", best_score)
plot_route(coords, best_route, priorities) |
Листинг 2.3.2 – Результат ГА
Лучший маршрут: [19, 29, 11, 5, 18, 12, 14, 20, 16, 1, 23, 0, 13, 8, 25, 9, 2, 21, 3, 26, 6, 22, 15, 4, 7, 27, 10, 17, 24, 28] Длина маршрута с учетом штрафов: 470.3076746873411 |
Рисунок 2.3.3 – Визуализация маршрута
Как можно заметить, ограничение на длину перелета часто нарушается. Это связано с тем, что и сами города находятся на большом удалении друг от друга. Кроме того, ограничение по приоритетности доставки также заставляет нарушать это мягкое ограничение.
