2.3. Код юнит-тестов фитнес-функции
namespace EvolutionaryAlgorithmTemplate.Tests
{
public class IndividualFitnessTests
{
/*
Проверяет вычисление фитнес-функции для разных пар (x,y)
Формула: f(x,y) = 2*x^2 - 1.05*x^4 + x^6/6 + x*y + y^2*/
[Theory]
[InlineData(0.0, 0.0, 0.0)]
// Для (1,0): 2 - 1.05 + 1/6 ≈ 1.11667
[InlineData(1.0, 0.0, 1.11667)]
// Для (-1,-1): 2 - 1.05 + 1/6 + 1 + 1 ≈ 3.11667
[InlineData(-1.0, -1.0, 3.11667)]
public void FitnessFunction_ShouldReturnExpectedValue(double x, double y, double expected)
{
// создаём особь с указанными параметрами, диапазон [-5,5]
List<double> genes = new List<double> { x, y };
Individual individual = new Individual(genes, -5, 5);
// вычисляем фитнес
double fitness = individual.Fitness();
// сравниваем с ожидаемым значением (с точностью до 5 знаков после запятой)
Assert.Equal(expected, fitness, 5);
}
//Проверяет, что если в особи меньше двух параметров, то метод Fitness() бросает ArgumentException.
[Fact]
public void FitnessFunction_ShouldThrowException_WhenLessThanTwoParameters()
{
List<double> genes = new List<double> { 0.0 };
var ex = Assert.Throws<ArgumentException>(() =>
{
Individual individual = new Individual(genes, -5, 5);
// Попытка вычислить фитнес должна привести к исключению
individual.Fitness();
});
Assert.Equal("Фитнес-функция требует не менее двух рабочих параметров.", ex.Message);
}
// Проверяет, что если в хромосоме больше двух параметров, то метод Fitness() использует только первые два.
[Fact]
public void FitnessFunction_ShouldIgnoreExtraParameters()
{
// создаём особь с тремя параметрами; фитнес вычисляется только по первым двум (x=1.0, y=0.0)
List<double> genes = new List<double> { 1.0, 0.0, 2.0 };
Individual individual = new Individual(genes, -5, 5);
double fitness = individual.Fitness();
double expected = 2 * Math.Pow(1.0, 2)
- 1.05 * Math.Pow(1.0, 4)
+ Math.Pow(1.0, 6) / 6
+ 1.0 * 0.0
+ Math.Pow(0.0, 2);
Assert.Equal(expected, fitness, 5);
}
}
}
2.4. Итог юнит-тестов фитнес-функции
Рис.2 — Скриншот прохождения юнит-тестов фитнес-функции
3. Оператор мутации
3.1. Модель оператора мутации
Альтернативная случайная мутация (Alternate Random Mutation). Мутация у отдельной особи происходит с вероятностью 0,005 – 0,1. Выбирается случайным образом ген, и в нем генерируется случайное смещение Δ ϵ [xmin/5, xmax/5] с равномерным распределением вероятности, если после смещения текущее значение выходит за пределы интервала, то округляем до xmin или xmax.
3.2. Код программной реализации оператора мутации
namespace EvolutionaryAlgorithmTemplate
{
/* Класс Gen (Ген)
Свойства:
Value (double) – рабочий параметр.
Методы:
Конструктор Gen(double value) – задаёт значение гена.
SetValue(double newValue) – устанавливает новое значение гена.
Mutation() – выполняет мутацию гена: с заданной вероятностью прибавляет случайное смещение [xmin/5, xmax/5],
при этом результат ограничивается диапазоном [xmin, xmax].*/
public class Gen
{
public double Value { get; private set; }
public Gen(double value)
{
Value = value;
}
public void SetValue(double newValue)
{
Value = newValue;
}
public void Mutation(double xmin, double xmax, double mutationProbability, Random rnd)
{
if (rnd.NextDouble() < mutationProbability)
{
// Генерируем случайное смещение из интервала [xmin/5, xmax/5]
double lowerDelta = xmin / 5.0;
double upperDelta = xmax / 5.0;
double delta = lowerDelta + rnd.NextDouble() * (upperDelta - lowerDelta);
double newValue = Value + delta;
// Ограничиваем значение в диапазоне [xmin, xmax]
if (newValue < xmin) newValue = xmin;
if (newValue > xmax) newValue = xmax;
Value = newValue;
}
}
}
}
