From 1f80f2f7dc26427e185982520422ec7c949d4668 Mon Sep 17 00:00:00 2001 From: Arity-T Date: Fri, 21 Nov 2025 16:24:30 +0300 Subject: [PATCH] =?UTF-8?q?=D0=97=D0=B0=D0=B3=D0=BE=D1=82=D0=BE=D0=B2?= =?UTF-8?q?=D0=BA=D0=B0=20lab6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lab6/report/.gitignore | 6 + lab6/report/img/optimal_tour.png | Bin 0 -> 32528 bytes lab6/report/report.tex | 395 +++++++++++++++++++++++++++++++ 3 files changed, 401 insertions(+) create mode 100644 lab6/report/.gitignore create mode 100644 lab6/report/img/optimal_tour.png create mode 100644 lab6/report/report.tex diff --git a/lab6/report/.gitignore b/lab6/report/.gitignore new file mode 100644 index 0000000..38887f8 --- /dev/null +++ b/lab6/report/.gitignore @@ -0,0 +1,6 @@ +* + +!**/ +!.gitignore +!report.tex +!img/**/*.png \ No newline at end of file diff --git a/lab6/report/img/optimal_tour.png b/lab6/report/img/optimal_tour.png new file mode 100644 index 0000000000000000000000000000000000000000..15e5e95537920723d3d3e6e04d20ab16029c8b32 GIT binary patch literal 32528 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\\ + + \hfill \break + \hfill \break + \hfill \break + \hfill \break + \large{Лабораторная работа №6}\\ + \large{по дисциплине}\\ + \large{<<Генетические алгоритмы>>}\\ + \large{Вариант 18}\\ + + % \hfill \break + \hfill \break + \end{center} + + \small{ + \begin{tabular}{lrrl} + \!\!\!Студент, & \hspace{2cm} & & \\ + \!\!\!группы 5130201/20101 & \hspace{2cm} & \underline{\hspace{3cm}} &Тищенко А. А. \\\\ + \!\!\!Преподаватель & \hspace{2cm} & \underline{\hspace{3cm}} & Большаков А. А. \\\\ + &&\hspace{4cm} + \end{tabular} + \begin{flushright} + <<\underline{\hspace{1cm}}>>\underline{\hspace{2.5cm}} 2025г. + \end{flushright} + } + + \hfill \break + % \hfill \break + \begin{center} \small{Санкт-Петербург, 2025} \end{center} + \thispagestyle{empty} % выключаем отображение номера для этой страницы + + % КОНЕЦ ТИТУЛЬНОГО ЛИСТА + \newpage + + \tableofcontents + + \newpage + \section {Постановка задачи} + В данной работе были поставлены следующие задачи: + + \begin{itemize} + \item Реализовать с использованием муравьиных алгоритмов решение задачи коммивояжера по индивидуальному заданию согласно номеру варианта. + \item Представить графически найденное решение + \item Сравнить найденное решение с представленным в условии задачи оптимальным решением и результатами, полученными в лабораторной работе №3. + \end{itemize} + + \textbf{Индивидуальное задание вариант 18:} + + \textbf{Дано:} Эвклидовы координаты городов 38 городов в Джибути (см.~Приложение~А). Оптимальный тур представлен на Рис.~\ref{fig:optimal_tour}, его длина равна 6659. + + \begin{figure}[h!] + \centering + \includegraphics[width=0.5\linewidth]{img/optimal_tour.png} + \caption{Оптимальный тур для заданного набора данных} + \label{fig:optimal_tour} + \end{figure} + + + \newpage + \section{Теоретические сведения} + + \subsection{Общие сведения о муравьиных алгоритмах} + + Муравьиные алгоритмы (МА) относятся к метаэвристическим методам оптимизации и предназначены преимущественно для решения задач комбинаторной оптимизации, в частности задачи поиска оптимальных путей на графах. Основная идея таких алгоритмов основана на моделировании коллективного поведения реальных муравьёв, использующих феромонные следы для обмена информацией. + + Каждый агент, называемый \textit{искусственным муравьём}, поэтапно строит решение задачи, перемещаясь по графу и выбирая следующую вершину на основе вероятностного правила, учитывающего концентрацию феромона на дугах графа. Феромон отражает привлекательность соответствующих маршрутов: чем выше его концентрация на дуге, тем вероятнее выбор этой дуги муравьём. + + \subsection{Простой муравьиный алгоритм (SACO)} + + Для иллюстрации рассмотрим простой муравьиный алгоритм SACO (Simple Ant Colony Optimization). Пусть задан граф + \[ + G = (V, E), + \] + где $V$ — множество вершин, $E$ — множество рёбер. Каждой дуге $(i,j)$ сопоставлена величина феромона $\tau_{ij}$. + + В начальный момент концентрация феромона обычно принимается нулевой, однако для предотвращения зацикливания каждому ребру присваивается малое случайное начальное значение $\tau_{ij}^{(0)}$. + + Каждый муравей $k=1,\ldots,n_k$ помещается в стартовую вершину и начинает построение пути. Если муравей находится в вершине $i$, он выбирает следующую вершину $j \in N_i^k$ на основе вероятностного правила + \[ + p_{ij}^k(t) = \frac{\tau_{ij}^\alpha(t)}{\sum\limits_{l \in N_i^k} \tau_{il}^\alpha(t)}, + \] + где $\alpha$ — параметр, определяющий степень влияния феромона. + + При отсутствии допустимых переходов допускается возврат в предыдущую вершину, что приводит к появлению петель, которые впоследствии удаляются. + + После завершения построения полного пути $x_k(t)$ выполняется его оценка. Длина пути обозначается как $L_k(t)$ и равна числу пройденных дуг. + + \subsection{Обновление феромона} + + Каждый муравей откладывает феромон на рёбрах своего пути согласно правилу + \[ + \Delta \tau_{ij}^k(t) = + \begin{cases} + \frac{1}{L_k(t)}, &\text{если дуга } (i,j) \in x_k(t), \\ + 0, &\text{иначе}. + \end{cases} + \] + + Общее обновление феромона на дуге $(i,j)$: + \[ + \tau_{ij}(t+1) = \tau_{ij}(t) + \sum_{k=1}^{n_k} \Delta\tau_{ij}^k(t). + \] + + Чем короче путь, тем больше феромона откладывается на его рёбрах, что повышает вероятность выбора коротких маршрутов в последующих итерациях. + + \subsection{Испарение феромона} + + Чтобы предотвратить преждевременную сходимость алгоритма к локальным минимумам, применяется механизм \textit{искусственного испарения феромона}. На каждом шаге выполняется: + \[ + \tau_{ij}(t) = (1 - \rho)\,\tau_{ij}(t), + \] + где $\rho \in [0,1]$ — коэффициент испарения. Большие значения $\rho$ усиливают случайность поиска, малые — повышают устойчивость к изменениям. + + \subsection{Критерии остановки алгоритма} + + Муравьиные алгоритмы могут завершаться при выполнении одного из условий: + \begin{itemize} + \item достигнуто максимальное число итераций; + \item найдено решение приемлемого качества $f(x_k(t)) \leq \varepsilon$; + \item все муравьи начинают строить одинаковые маршруты, что говорит о стабилизации процесса. + \end{itemize} + + \subsection{Описание общего алгоритма} + + Алгоритм SACO можно представить в следующем виде: + + \begin{enumerate} + \item Инициализация феромона малыми случайными значениями $\tau_{ij}^{(0)}$. + \item Размещение всех муравьёв в начальной вершине. + \item Для каждой итерации: + \begin{enumerate} + \item Каждый муравей строит путь согласно вероятностному правилу выбора вершины. + \item Выполняется удаление петель. + \item Вычисляется длина пути $L_k(t)$. + \end{enumerate} + \item Выполняется испарение феромона. + \item Каждый муравей откладывает феромон на рёбрах своего пути. + \item Итерация продолжается до выполнения критерия остановки. + \end{enumerate} + + Муравьиные алгоритмы позволяют эффективно находить приближённые решения задач комбинаторной оптимизации, таких как задача коммивояжёра, что и является целью данной лабораторной работы. + + + + \newpage + \section{Особенности реализации} + + === Нужно обновить раздел === + + В рамках работы создана мини-библиотека \texttt{gen.py} для решения задачи коммивояжёра (TSP) генетическим алгоритмом с путевым представлением хромосом. Второй модуль + \texttt{expirements.py} организует серийные эксперименты (перебор параметров, + форматирование и сохранение результатов). + + \begin{itemize} + \item \textbf{Кодирование особей}: каждая хромосома представлена как перестановка городов (\texttt{Chromosome = list[int]}), где каждый элемент -- индекс города. Популяция -- список хромосом (\texttt{Population = list[Chromosome]}). Инициализация случайными перестановками без повторений: + \begin{itemize} + \item \texttt{initialize\_random\_population(pop\_size: int, cities: Cites) -> Population} + \end{itemize} + \item \textbf{Фитнесс-функция}: целевая функция принимает хромосому (маршрут) и возвращает скалярное значение фитнесса (длину пути). Для режима минимизации используется внутреннее преобразование при селекции (сдвиг и инверсия знака), что позволяет применять рулетку: + \begin{itemize} + \item \texttt{eval\_population(population: Population, fitness\_func: FitnessFn) -> Fitnesses} + \item Логика режима минимизации в \texttt{genetic\_algorithm(config: GARunConfig) -> GARunResult} + \end{itemize} + \item \textbf{Селекция (рулетка)}: вероятности нормируются после сдвига на минимальное значение в поколении (устойчиво к отрицательным фитнессам). Функция: + \texttt{reproduction(population: Population, fitnesses: Fitnesses) -> Population}. + \item \textbf{Кроссинговер}: реализованы специализированные операторы для перестановок: PMX (Partially Mapped Crossover), OX (Ordered Crossover) и CX (Cycle Crossover). Кроссинговер выполняется попарно по перемешанной популяции с вероятностью $p_c$. Функции: + \begin{itemize} + \item \texttt{partially\_mapped\_crossover\_fn(p1: Chromosome, p2: Chromosome) -> tuple[Chromosome, Chromosome]} + \item \texttt{ordered\_crossover\_fn(p1: Chromosome, p2: Chromosome) -> tuple[Chromosome, Chromosome]} + \item \texttt{cycle\_crossover\_fn(p1: Chromosome, p2: Chromosome) -> tuple[Chromosome, Chromosome]} + \item \texttt{crossover(population: Population, pc: float, crossover\_fn: CrossoverFn) -> Population} + \end{itemize} + \item \textbf{Мутация}: реализованы три типа мутаций для перестановок: обмен двух городов (swap), инверсия сегмента (inversion), вырезка и вставка города (insertion). Мутация применяется с вероятностью $p_m$. Функции: + \begin{itemize} + \item \texttt{swap\_mutation\_fn(chrom: Chromosome) -> Chromosome} + \item \texttt{inversion\_mutation\_fn(chrom: Chromosome) -> Chromosome} + \item \texttt{insertion\_mutation\_fn(chrom: Chromosome) -> Chromosome} + \item \texttt{mutation(population: Population, pm: float, mutation\_fn: MutationFn) -> Population} + \end{itemize} + + \item \textbf{Критерий остановки}: поддерживаются критерии по максимальному количеству поколений, повторению лучшего результата, достижению порогового значения фитнесса. Хранится история всех поколений. Проверка выполняется в функции: + + \texttt{genetic\_algorithm(config: GARunConfig) -> GARunResult}. + \item \textbf{Визуализация}: реализована отрисовка маршрутов обхода городов на плоскости с отображением лучшей особи поколения. Функции: + \begin{itemize} + \item \texttt{plot\_tour(cities: list[tuple[float, float]], tour: list[int], ax: Axes)} + \item \texttt{save\_generation(generation: Generation, history: list[Generation], config: GARunConfig)} + \item \texttt{plot\_fitness\_history(result: GARunResult, save\_path: str | None) -> None} + \end{itemize} + \item \textbf{Элитизм}: поддерживается перенос лучших особей без изменения в следующее поколение (\texttt{elitism} параметр). + \item \textbf{Измерение времени}: длительность вычислений возвращается в миллисекундах как часть \texttt{GARunResult.time\_ms}. + \item \textbf{Файловая организация}: результаты экспериментов сохраняются в структуре \texttt{experiments/N/} с таблицами результатов. Задействованные функции: + \begin{itemize} + \item \texttt{clear\_results\_directory(results\_dir: str) -> None} + \item Функции для проведения экспериментов в модуле \texttt{expirements.py} + \end{itemize} + \end{itemize} + + В модуле \texttt{expirements.py} задаются координаты городов и параметры экспериментов. + Серийные запуски и сохранение результатов реализованы для исследования влияния параметров ГА на качество решения задачи коммивояжёра. + + \newpage + \section{Результаты работы} + + === Нужно обновить раздел === + + На Рис.~\ref{fig:results} представлены результаты работы простого муравьиного алгоритма со следующими параметрами: + \begin{itemize} + \item $N = 500$ -- размер популяции. + \item $p_c = 0.9$ -- вероятность кроссинговера. + \item $p_m = 0.3$ -- вероятность мутации. + \item $2500$ -- максимальное количество поколений. + \item $3$ -- количество "элитных" особей, переносимых без изменения в следующее поколение. + \item Partially mapped crossover - кроссовер. + \item Inversion mutation - мутация + \end{itemize} + + На Рис.~\ref{fig:fitness_history} показан график изменения фитнесса по поколениям. Видно, что алгоритм постепенно сходится к минимально возможному значению фитнеса. Лучший маршрут был найден на поколнении №1896 (см. Рис.~\ref{fig:lastgen}). + + % \begin{figure}[h!] + % \centering + % \includegraphics[width=1\linewidth]{img/results/fitness_history.png} + % \caption{График изменения фитнесса по поколениям} + % \label{fig:fitness_history} + % \end{figure} + + \subsection{Сравнение с результатами лабораторной работы №3} + + === Нужно написать раздел, ниже представлена часть отчёта из лаб3, чтобы было с чем сравнить === + + Наилучшее найденное решение составило \textbf{6667.03} при параметрах $N=500$, $P_c=0.9$, $P_m=0.5$ за 1644 поколения. Это всего на \textbf{0.12\%} хуже оптимального значения 6659, что демонстрирует высокую эффективность алгоритма. Наихудшие результаты показала конфигурация с $N=10$, $P_c=0.7$, $P_m=0.3$ (лучший фитнес 6796.98), что на 2.07\% хуже оптимума. Малый размер популяции в 10 особей оказался недостаточным для стабильного поиска качественных решений — более половины конфигураций при $N=10$ вообще не нашли решение за 2500 поколений. + + Наиболее быстрая конфигурация — $N=10$, $P_c=0.7$, $P_m=0.5$ — нашла решение за \textbf{201 мс} (503 поколения). Однако качество решения при таких параметрах нестабильно. Среди конфигураций с большой популяцией лучшее время показала $N=500$, $P_c=0.5$, $P_m=0.2$ — \textbf{5232 мс} (341 поколение), что является оптимальным балансом скорости и качества для больших популяций. + + С ростом размера популяции наблюдается явное улучшение качества решений: при $N=10$ лучший результат 6762.97, при $N=500$ — 6667.03. Одновременно количество необходимых поколений снижается (с 503 до 341), но общее время выполнения растет линейно из-за увеличения числа особей в каждом поколении. Этот эффект объясняется тем, что большая популяция обеспечивает большее генетическое разнообразие, позволяя алгоритму быстрее находить оптимальные решения. + + Что касается вероятности кроссовера, средние значения $P_c=0.6$--$0.8$ показывают стабильные результаты для всех размеров популяций. Экстремальные значения ($P_c=0.9$ или $1.0$) работают хорошо только при больших популяциях ($N \geq 100$), при малых — часто приводят к преждевременной сходимости (наблюдается много прочерков в таблицах). Это связано с тем, что высокая вероятность кроссовера при малой популяции быстро приводит к гомогенизации генофонда. + + Анализ влияния вероятности мутации показал, что низкие значения $P_m=0.05$ неэффективны для малых популяций — недостаточно разнообразия для выхода из локальных минимумов. Умеренные значения $P_m=0.2$--$0.5$ демонстрируют лучшие результаты, обеспечивая баланс между эксплуатацией найденных решений и исследованием нового пространства поиска. Высокое значение $P_m=0.8$ часто приводит к расхождению алгоритма, так как слишком сильные изменения разрушают хорошие решения быстрее, чем алгоритм успевает их найти (многие конфигурации не нашли решение за отведенное время). + + + \newpage + \section{Ответ на контрольный вопрос} + + \textbf{Вопрос}: Какие критерии окончания могут быть использованы в простом МА? + + \textbf{Ответ}: В простом муравьином алгоритме могут использоваться следующие критерии завершения работы: + + \begin{itemize} + \item окончание при превышении заданного числа итераций; + \item окончание по достижению приемлемого решения; + \item окончание в случае, когда все муравьи начинают следовать одним и тем же путём. + \end{itemize} + + + + + \newpage + \section*{Заключение} + \addcontentsline{toc}{section}{Заключение} + + === Нужно обновить раздел === + + В ходе третьей лабораторной работы была успешно решена задача коммивояжера с использованием генетических алгоритмов для 38 городов Джибути: + + \begin{enumerate} + \item Изучен теоретический материал о представлениях туров (соседское, порядковое, путевое) и специализированных операторах кроссинговера и мутации для задачи коммивояжера; + \item Создана программная библиотека на языке Python с реализацией путевого представления хромосом, операторов PMX, OX и CX для кроссинговера, операторов swap, inversion и insertion для мутации, а также селекции методом рулетки с поддержкой элитизма; + \item Проведено исследование влияния параметров генетического алгоритма на качество и скорость нахождения решения для популяций размером 10, 50, 100 и 500 особей с различными значениями вероятностей кроссинговера и мутации; + \item Получено решение с длиной маршрута 6667.03, отклоняющееся от оптимального значения 6659 всего на 0.12\%. + \end{enumerate} + + +\newpage +\section*{Список литературы} +\addcontentsline{toc}{section}{Список литературы} + +\vspace{-1.5cm} +\begin{thebibliography}{0} + \bibitem{vostrov} + Методические указания по выполнению лабораторных работ к курсу «Генетические алгоритмы», 119 стр. +\end{thebibliography} + +\end{document} \ No newline at end of file