Main Content

Custom Output Function for Genetic Algorithm

This example shows the use of a custom output function in the genetic algorithm solver ga. The custom output function performs the following tasks:

  • Plot the range of the first two components of the population as a rectangle. The left and lower sides of the rectangle are at the minima of x(1) and x(2) respectively, and the right and upper sides are at the respective maxima.

  • Halt the iterations when the best function value drops below 0.1 (the minimum value of the objective function is 0).

  • Record the entire population in a variable named gapopulationhistory in your MATLAB® workspace every 10 generations.

  • Modify the initial crossover fraction to the custom value 0.2, and then update it back to the default 0.8 after 25 generations. The initial setting of 0.2 causes the first several iterations to search primarily at random via mutation. The later setting of 0.8 causes the following iterations to search primarily via combinations of existing population members.

Objective Function

The objective function is for four-dimensional x whose first two components are integer-valued.

function f = gaintobj(x)
f = rastriginsfcn([x(1)-6 x(2)-13]);
f = f + rastriginsfcn([x(3)-3*pi x(4)-5*pi]);

Output Function

The custom output function sets up the plot during initialization, and maintains the plot during iterations. The output function also pauses the iterations for 0.1s so you can see the plot as it develops.

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

Problem Setup and Solution

Set the lower and upper bounds.

lb = [1 1 -30 -30];
ub = [20 20 70 70];

Set the integer variables and number of variables.

intcon = [1 2];
nvar = 4;

Set options to call the custom output function, and to initially have little crossover.

options = optimoptions('ga','OutputFcn',@gaoutfun,'CrossoverFraction',0.2);

For reproducibility, set the random number generator.

rng default

Set the objective function and call the solver.

fun = @gaintobj;
[x,fval] = ga(fun,nvar,[],[],[],[],lb,ub,[],intcon,options)
Got below 0.1
ga stopped by the output or plot function. The reason for stopping: 
y

x =

    6.0000   13.0000    9.4201   15.7052


fval =

    0.0059

The output function halted the solver.

View the size of the recorded history.

disp(size(gapopulationhistory))
    40     4     6

There are six records of the 40-by-4 population matrix (40 individuals, each a 4-element row vector).

Related Topics