В этом примере показано использование пользовательской функции вывода в решателе генетических алгоритмов ga. Пользовательская функция вывода выполняет следующие задачи:
Постройте график диапазона первых двух компонентов совокупности в виде прямоугольника. Левая и нижняя стороны прямоугольника находятся на минимуме x(1) и x(2) соответственно, и правая и верхняя стороны находятся на соответствующих максимумах.
Остановка итераций, когда наилучшее значение функции опускается ниже 0.1 (минимальное значение целевой функции - 0).
Запись всей совокупности в переменную с именем gapopulationhistory в рабочей области MATLAB ® каждые 10 поколений.
Изменить начальную фракцию перехода на пользовательское значение 0.2, а затем обновить его до значения по умолчанию 0.8 через 25 поколений. Начальная установка 0.2 заставляет первые несколько итераций искать в основном случайным образом через мутацию. Более поздняя настройка 0.8 вызывает следующие итерации для поиска, главным образом, через комбинации существующих элементов заполнения.
Целевая функция для четырехмерных x первые два компонента которого являются целочисленными.
function f = gaintobj(x)
f = rastriginsfcn([x(1)-6 x(2)-13]);
f = f + rastriginsfcn([x(3)-3*pi x(4)-5*pi]);
Пользовательская функция вывода настраивает график во время инициализации и поддерживает график во время итераций. Функция вывода также приостанавливает итерации для 0.1s чтобы вы могли видеть сюжет по мере его развития.
function [state,options,optchanged] = gaoutfun(options,state,flag) persistent h1 history r optchanged = false; switch flag case 'init' h1 = figure; ax = gca; ax.XLim = [0 21]; ax.YLim = [0 21]; l1 = min(state.Population(:,1)); m1 = max(state.Population(:,1)); l2 = min(state.Population(:,2)); m2 = max(state.Population(:,2)); r = rectangle(ax,'Position',[l1 l2 m1-l1 m2-l2]); history(:,:,1) = state.Population; assignin('base','gapopulationhistory',history); case 'iter' % Update the history every 10 generations. if rem(state.Generation,10) == 0 ss = size(history,3); history(:,:,ss+1) = state.Population; assignin('base','gapopulationhistory',history); end % Find the best objective function, and stop if it is low. ibest = state.Best(end); ibest = find(state.Score == ibest,1,'last'); bestx = state.Population(ibest,:); bestf = gaintobj(bestx); if bestf <= 0.1 state.StopFlag = 'y'; disp('Got below 0.1') end % Update the plot. figure(h1) l1 = min(state.Population(:,1)); m1 = max(state.Population(:,1)); l2 = min(state.Population(:,2)); m2 = max(state.Population(:,2)); r.Position = [l1 l2 m1-l1 m2-l2]; pause(0.1) % Update the fraction of mutation and crossover after 25 generations. if state.Generation == 25 options.CrossoverFraction = 0.8; optchanged = true; end case 'done' % Include the final population in the history. ss = size(history,3); history(:,:,ss+1) = state.Population; assignin('base','gapopulationhistory',history); end
Установите нижнюю и верхнюю границы.
lb = [1 1 -30 -30]; ub = [20 20 70 70];
Задайте целочисленные переменные и число переменных.
IntCon = [1 2]; nvar = 4;
Установите параметры, чтобы вызвать пользовательскую функцию вывода и изначально иметь небольшой кроссовер.
options = optimoptions('ga','OutputFcn',@gaoutfun,'CrossoverFraction',0.2);
Для воспроизводимости установите генератор случайных чисел.
rng(10)
Задайте целевую функцию и вызовите решатель.
fun = @gaintobj; [x,fval] = ga(fun,nvar,[],[],[],[],lb,ub,[],IntCon,options)
Got below 0.1
Optimization terminated: y
x =
6.0000 13.0000 9.4217 15.7016
fval =
0.0098

Функция вывода остановила решатель.
Просмотр размера записанного журнала.
disp(size(gapopulationhistory))
40 4 7
Существует семь записей матрицы популяции 40 на 4 (40 особей, каждая 4-элементный вектор строки).