MATLAB Examples

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.

Contents

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(10)

Set the objective function and call the solver.

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

The output function halted the solver.

View the size of the recorded history.

disp(size(gapopulationhistory))
    40     4     7

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