# 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).