This is machine translation

Translated by Microsoft
Mouseover text to see original. Click the button below to return to the English version of the page.

Note: This page has been translated by MathWorks. Click here to see
To view all translated materials including this page, select Country from the country navigator on the bottom of this page.

Coding and Minimizing a Fitness Function Using the Genetic Algorithm

This example shows how to create and minimize a fitness function for the genetic algorithm solver ga using three techniques:

  • Basic

  • Including additional parameters

  • Vectorized for speed

Basic Fitness Function

The basic fitness function is Rosenbrock's function, a common test function for optimizers. The function is a sum of squares:

f(x)=100(x12-x2)2+(1-x1)2.

The function has a minimum value of zero at the point [1,1]. Because the Rosenbrock function is quite steep, plot the logarithm of one plus the function.

fsurf(@(x,y)log(1 + 100*(x.^2 - y).^2 + (1 - x).^2),[0,2])
title('log(1 + 100*(x(1)^2 - x(2))^2 + (1 - x(1))^2)')
view(-13,78)
hold on
h1 = plot3(1,1,0.1,'r*','MarkerSize',12);
legend(h1,'Minimum','Location','best');
hold off

Fitness Function Code

The simple_fitness function file implements Rosenbrock's function.

type simple_fitness
function y = simple_fitness(x)
%SIMPLE_FITNESS fitness function for GA

%   Copyright 2004 The MathWorks, Inc. 

  y = 100 * (x(1)^2 - x(2)) ^2 + (1 - x(1))^2;

A fitness function must take one input x where x is a row vector with as many elements as number of variables in the problem. The fitness function computes the value of the function and returns that scalar value in its one return argument y.

Minimize Using ga

To minimize the fitness function using ga, pass a function handle to the fitness function as well as the number of variables in the problem. To have ga examine the relevant region, include bounds -3 <= x(i) <= 3. Pass the bounds as the fifth and sixth arguments after numberOfVariables. For ga syntax details, see ga.

ga is a random algorithm. For reproducibility, set the random number stream.

rng default % For reproducibility
FitnessFunction = @simple_fitness;
numberOfVariables = 2;
lb = [-3,-3];
ub = [3,3];
[x,fval] = ga(FitnessFunction,numberOfVariables,[],[],[],[],lb,ub)
Optimization terminated: maximum number of generations exceeded.
x = 1×2

    1.5083    2.2781

fval = 0.2594

The x returned by the solver is the best point in the final population computed by ga. The fval is the value of the function simple_fitness evaluated at the point x. ga did not find an especially good solution. For ways to improve the solution, see "Common Tuning Options" in Genetic Algorithm.

Fitness Function with Additional Parameters

Sometimes your fitness function has extra parameters that act as constants during the optimization. For example, a generalized Rosenbrock's function can have extra parameters representing the constants 100 and 1:

f(x,a,b)=a(x12-x2)2+(b-x1)2.

a and b are parameters to the fitness function that act as constants during the optimization (they are not varied as part of the minimization). The parameterized_fitness.m file implements this parameterized fitness function.

type parameterized_fitness
function y = parameterized_fitness(x,p1,p2)
%PARAMETERIZED_FITNESS fitness function for GA

%   Copyright 2004 The MathWorks, Inc.        
 
y = p1 * (x(1)^2 - x(2)) ^2 + (p2 - x(1))^2;

Minimize Using Additional Parameters

Use an anonymous function to capture the values of the additional arguments, namely, the constants a and b. Create a function handle FitnessFunction to an anonymous function that takes one input x, and calls parameterized_fitness with x, a, and b. The anonymous function contains the values of a and b that exist when the function handle is created.

a = 100;
b = 1; % define constant values
FitnessFunction = @(x) parameterized_fitness(x,a,b);
[x,fval] = ga(FitnessFunction,numberOfVariables,[],[],[],[],lb,ub)
Optimization terminated: maximum number of generations exceeded.
x = 1×2

    1.3198    1.7434

fval = 0.1025

See Passing Extra Parameters (Optimization Toolbox).

Vectorized Fitness Function

To gain speed, vectorize your fitness function. A vectorized fitness function computes the fitness of a collection of points at once, which generally saves time over evaluating these points individually. To write a vectorized fitness function, have your function accept a matrix, where each matrix row represents one point, and have the fitness function return a column vector of fitness function values.

To change the parameterized_fitness function file to a vectorized form:

  • Change each variable x(i) to x(:,i), meaning the column vector of variables corresponding to x(i).

  • Change each vector multiplication * to .* and each exponentiation ^ to .^ indicating that the operations are element-wise. There are no vector multiplications in this code, so simply change the exponents.

type vectorized_fitness
function y = vectorized_fitness(x,p1,p2)
%VECTORIZED_FITNESS fitness function for GA

%   Copyright 2004-2010 The MathWorks, Inc.  

y = p1 * (x(:,1).^2 - x(:,2)).^2 + (p2 - x(:,1)).^2;

This vectorized version of the fitness function takes a matrix x with an arbitrary number of points, meaning and arbitrary number of rows, and returns a column vector y with the same number of rows as x.

Tell the solver that the fitness function is vectorized in the 'UseVectorized' option.

options = optimoptions(@ga,'UseVectorized',true);

Include options as the last argument to ga.

VFitnessFunction = @(x) vectorized_fitness(x,100,1);
[x,fval] = ga(VFitnessFunction,numberOfVariables,[],[],[],[],lb,ub,[],options)
Optimization terminated: maximum number of generations exceeded.
x = 1×2

    1.6219    2.6334

fval = 0.3876

What is the difference in speed? Time the optimization both with and without vectorization.

tic
[x,fval] = ga(VFitnessFunction,numberOfVariables,[],[],[],[],lb,ub,[],options);
Optimization terminated: maximum number of generations exceeded.
v = toc;
tic
[x,fval] = ga(FitnessFunction,numberOfVariables,[],[],[],[],lb,ub);
Optimization terminated: maximum number of generations exceeded.
nv = toc;
fprintf('Using vectorization took %f seconds. No vectorization took %f seconds.\n',v,nv)
Using vectorization took 0.154365 seconds. No vectorization took 0.220625 seconds.

In this case, the improvement by vectorization was not great, because computing the fitness function takes very little time. However, for more time-consuming fitness functions, vectorization can be helpful. See Vectorize the Fitness Function.