МИНИСТЕРСТВО ЦИФРОВОГО РАЗВИТИЯ, СВЯЗИ И МАССОВЫХ КОММУНИКАЦИЙ РОССИЙСКОЙ ФЕДЕРАЦИИ
ФЕДЕРАЛЬНОЕ ГОСУДАРСТВЕННОЕ БЮДЖЕТНОЕ ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ ВЫСШЕГО ОБРАЗОВАНИЯ
«САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ ТЕЛЕКОММУНИКАЦИЙ ИМ.ПРОФ.М.А.БОНЧ-БРУЕВИЧА»
(СПбГУТ)
Факультет: «Институт магистратуры»
Кафедра: «Систем автоматизации и робототехники»
Направление подготовки: |
Автоматизация технологических процессов и производств |
Направленность (профиль): |
Интеллектуальные технологии в автоматизации |
ЛАБОРАТОРНАЯ РАБОТА № 2
по дисциплине:
Методы и модели искусственного интеллекта в управлении техническими системами
|
на тему:
Программная реализация структур генетического алгоритма
Вариант: 10
-
Выполнили студенты группы:
дата, подпись
Фамилия И. О.
Принял к.т.н., доцент
Верхова Г.В.
дата, подпись
Фамилия И. О.
Цель работы: приобретение навыков разработки и программной реализации на C# структур и операторов генетических алгоритмов
Задание: Разработать модель хромосомы, фитнес-функцию, операторы мутации и кроссинговера согласно 10 варианту. Выполнить тестирование моделей и операторов с помощью xUnit.Net.
Ход работы
1. Хромосома
1.1. Модель хромосомы
Вектор рабочих параметров для задач непрерывного нелинейного математического программирования X = {x1, x2, xn}, xi ϵ R; количество рабочих параметров задается специальным методом и может быть от 2 до N; вещественное кодирование; диапазон изменения значений элементов вектора рабочих параметров от xmin до xmax.
1.2. Код программной реализации хромосомы
namespace EvolutionaryAlgorithmTemplate
{
/*Класс Chromosome (Хромосома)
Хранит вектор рабочих параметров – список объектов Gen, каждый из которых содержит вещественное значение.
Свойства:
Gens – список генов.
XMin, XMax – границы допустимых значений рабочих параметров.
Dimension – число рабочих параметров.
Методы:
Конструкторы для создания хромосомы из списка вещественных значений или из списка генов.
BLX‑a‑b кроссинговер – для создания потомков по заданному алгоритму.
Mutation – выполняет мутацию, выбирая случайный ген.*/
public class Chromosome
{
public List<Gen> Gens { get; private set; }
public double XMin { get; private set; }
public double XMax { get; private set; }
public int Dimension => Gens.Count;
// Создание хромосомы по списку рабочих параметров
public Chromosome(List<double> values, double xmin, double xmax)
{
XMin = xmin;
XMax = xmax;
Gens = new List<Gen>();
foreach (var val in values)
{
// Если значение выходит за пределы, ограничиваем его
double clamped = Math.Max(xmin, Math.Min(val, xmax));
Gens.Add(new Gen(clamped));
}
}
// Альтернативный конструктор, принимающий уже сформированные гены
public Chromosome(List<Gen> gens, double xmin, double xmax)
{
XMin = xmin;
XMax = xmax;
Gens = new List<Gen>(gens);
}
/*
Оператор кроссинговера BLX‑a‑b.
Для i-го гена вычисляется d = |x - y|. Если x ≤ y, интервал для потомка [x - a*d, y + b*d],
иначе [y - b*d, x + a*d]. Для каждого потомка генерируется случайное значение в этом интервале.
*/
public static (Chromosome, Chromosome) BLXabCrossover(
Chromosome parent1,
Chromosome parent2,
double a, double b,
double xmin, double xmax,
Random rnd)
{
if (parent1.Dimension != parent2.Dimension)
throw new ArgumentException("Размерности хромосом должны совпадать!");
int n = parent1.Dimension;
List<double> child1Values = new List<double>();
List<double> child2Values = new List<double>();
for (int i = 0; i < n; i++)
{
double x = parent1.Gens[i].Value;
double y = parent2.Gens[i].Value;
double d = Math.Abs(x - y);
double lower, upper;
if (x <= y)
{
lower = x - a * d;
upper = y + b * d;
}
else
{
lower = y - b * d;
upper = x + a * d;
}
double child1Value = lower + rnd.NextDouble() * (upper - lower);
double child2Value = lower + rnd.NextDouble() * (upper - lower);
// Ограничиваем значения в [xmin, xmax]
child1Value = Math.Max(xmin, Math.Min(child1Value, xmax));
child2Value = Math.Max(xmin, Math.Min(child2Value, xmax));
child1Values.Add(child1Value);
child2Values.Add(child2Value);
}
Chromosome child1 = new Chromosome(child1Values, xmin, xmax);
Chromosome child2 = new Chromosome(child2Values, xmin, xmax);
return (child1, child2);
}
// Выполняет мутацию хромосомы: выбирается случайный ген и к нему применяется метод мутации
public void Mutation(double mutationProbability, Random rnd)
{
int index = rnd.Next(Dimension);
Gens[index].Mutation(XMin, XMax, mutationProbability, rnd);
}
}
}
1.3. Код юнит-тестов хромосомы
public class ChromosomeTests
{
[Fact]
public void Constructor_ShouldClampValuesWithinRange()
{
// Диапазон допустимых значений от 0 до 10.
double xmin = 0.0;
double xmax = 10.0;
// Задаем входные значения, некоторые из которых выходят за пределы диапазона.
List<double> inputValues = new List<double> { -5.0, 5.0, 15.0 };
// Создаем хромосому по списку значений.
var chromosome = new Chromosome(inputValues, xmin, xmax);
// Проверяем, что количество генов соответствует количеству входных значений.
Assert.Equal(3, chromosome.Dimension);
// Проверяем, что значения корректно ограничены в диапазоне [xmin, xmax].
Assert.Equal(xmin, chromosome.Gens[0].Value); // -5 ограничено до 0
Assert.Equal(5.0, chromosome.Gens[1].Value); // 5 остается без изменений
Assert.Equal(xmax, chromosome.Gens[2].Value); // 15 ограничено до 10
}
}
1.4. Итог юнит-тестов хромосомы
Рис.1 — Скриншот прохождения юнит-тестов хромосомы
2. Фитнес-функция
2.1. Модель фитнес-функции
Функция трехгорбого верблюда:
Глобальный минимум:
2.2. Код программной реализации фитнес-функции
namespace EvolutionaryAlgorithmTemplate
{
/*
Класс Individual (Особь)
Хранит хромосому (вектор рабочих параметров) и вычисляет значение фитнес-функции.
Фитнес-функция – функция трёхгорбого верблюда:
f(x,y)=2x^2 - 1.05x^4 + x^6/6 + x*y + y^2, где x,y [xmin, xmax] ([-5,5]),
глобальный минимум достигается при (0,0) со значением 0.
Методы:
Конструкторы для создания особи по хромосоме или по списку вещественных значений.
SetChromosome – устанавливает новую хромосому.
Fitness – вычисляет значение фитнес-функции.
Mutation – применяет мутацию к хромосоме.
GetGenes – возвращает рабочие параметры в виде списка вещественных чисел.*/
public class Individual
{
public Chromosome Chromosome { get; private set; }
public double FitnessValue { get; private set; }
// Конструктор, принимающий хромосому
public Individual(Chromosome chromosome)
{
Chromosome = chromosome;
FitnessValue = Fitness();
}
// Конструктор, принимающий список рабочих параметров
public Individual(List<double> values, double xmin, double xmax)
{
Chromosome = new Chromosome(values, xmin, xmax);
FitnessValue = Fitness();
}
// Обновляет хромосому и пересчитывает фитнес
public void SetChromosome(List<double> values, double xmin, double xmax)
{
Chromosome = new Chromosome(values, xmin, xmax);
FitnessValue = Fitness();
}
// Фитнес-функция (функция трёхгорбого верблюда) для первых двух параметров
public double Fitness()
{
if (Chromosome.Dimension < 2)
throw new ArgumentException("Фитнес-функция требует не менее двух рабочих параметров.");
double x = Chromosome.Gens[0].Value;
double y = Chromosome.Gens[1].Value;
FitnessValue = 2 * Math.Pow(x, 2) - 1.05 * Math.Pow(x, 4) + Math.Pow(x, 6) / 6 + x * y + Math.Pow(y, 2);
return FitnessValue;
}
// Применяет мутацию: выбирается случайный ген, к которому применяется мутация, затем обновляется фитнес
public void Mutation(double mutationProbability, Random rnd)
{
Chromosome.Mutation(mutationProbability, rnd);
FitnessValue = Fitness();
}
// Возвращает рабочие параметры особи в виде списка вещественных значений
public List<double> GetGenes()
{
List<double> genes = new List<double>();
foreach (var gene in Chromosome.Gens)
{
genes.Add(gene.Value);
}
return genes;
}
}
}
