This example shows how to create and minimize an objective function using pattern search.

For this problem, the objective function to minimize is a simple function of a 2-D variable `x`

.

` simple_objective(x) = (4 - 2.1*x(1)^2 + x(1)^4/3)*x(1)^2 + x(1)*x(2) + (-4 + 4*x(2)^2)*x(2)^2;`

This function is known as "cam," as described in L.C.W. Dixon and G.P. Szego [1].

Create a MATLAB file named `simple_objective.m`

containing the following code:

`type simple_objective`

function y = simple_objective(x) %SIMPLE_OBJECTIVE Objective function for PATTERNSEARCH solver % Copyright 2004 The MathWorks, Inc. x1 = x(1); x2 = x(2); y = (4-2.1.*x1.^2+x1.^4./3).*x1.^2+x1.*x2+(-4+4.*x2.^2).*x2.^2;

Solvers such as `patternsearch`

accept a single input `x`

, where `x`

has as many elements as the number of variables in the problem. The objective function computes the scalar value of the objective function and returns it in its single output argument `y`

.

`patternsearch`

Specify the objective function as a function handle.

ObjectiveFunction = @simple_objective;

Specify an initial point for the solver.

`x0 = [0.5 0.5]; % Starting point`

Call the solver, requesting the optimal point `x`

and the function value at the optimal point `fval`

.

[x,fval] = patternsearch(ObjectiveFunction,x0)

Optimization terminated: mesh size less than options.MeshTolerance.

`x = `*1×2*
-0.0898 0.7127

fval = -1.0316

Sometimes your objective function has extra arguments that act as constants during the optimization. For example, in `simple_objective`

, you might want to specify the constants 4, 2.1, and 4 as variable parameters to create a family of objective functions.

Rewrite `simple_objective`

to take three additional parameters (`p1`

, `p2`

, and `p3`

) that act as constants during the optimization (they are not varied as part of the minimization). To implement the objective function calculation, the MATLAB file `parameterized_objective.m`

contains the following code:

`type parameterized_objective`

function y = parameterized_objective(x,p1,p2,p3) %PARAMETERIZED_OBJECTIVE Objective function for PATTERNSEARCH solver % Copyright 2004 The MathWorks, Inc. x1 = x(1); x2 = x(2); y = (p1-p2.*x1.^2+x1.^4./3).*x1.^2+x1.*x2+(-p3+p3.*x2.^2).*x2.^2;

`patternsearch`

calls the objective function with just one argument `x`

, but the parameterized objective function has four arguments: `x`

, `p1`

, `p2`

, and `p3`

. Use an anonymous function to capture the values of the additional arguments `p1`

, `p2`

, and `p3`

. Create a function handle `ObjectiveFunction`

to an anonymous function that takes one input `x`

, but calls `parameterized_objective`

with `x`

, `p1`

, `p2`

, and `p3`

. When you create the function handle `ObjectiveFunction`

, the variables `p1`

, `p2`

, and `p3`

have values that are stored in the anonymous function. For details, see Passing Extra Parameters (Optimization Toolbox).

```
p1 = 4; p2 = 2.1; p3 = 4; % Define constant values
ObjectiveFunction = @(x) parameterized_objective(x,p1,p2,p3);
[x,fval] = patternsearch(ObjectiveFunction,x0)
```

Optimization terminated: mesh size less than options.MeshTolerance.

`x = `*1×2*
-0.0898 0.7127

fval = -1.0316

By default, `patternsearch`

passes in one point at a time to the objective function. Sometimes, you can speed the solver by *vectorizing* the objective function to take a set of points and return a set of function values.

For the solver to evaluate a set of five points in one call to the objective function, for example, the solver calls the objective on a matrix of size 5-by-2 (where 2 is the number of variables). For details, see Vectorize the Objective and Constraint Functions.

To vectorize `parameterized_objective`

, use the following code:

`type vectorized_objective`

function y = vectorized_objective(x,p1,p2,p3) %VECTORIZED_OBJECTIVE Objective function for PATTERNSEARCH solver % Copyright 2004-2018 The MathWorks, Inc. x1 = x(:,1); % First column of x x2 = x(:,2); y = (p1 - p2.*x1.^2 + x1.^4./3).*x1.^2 + x1.*x2 + (-p3 + p3.*x2.^2).*x2.^2;

This vectorized version of the objective function takes a matrix `x`

with an arbitrary number of points (the rows of `x`

) and returns a column vector `y`

whose length is the number of rows of `x`

.

To take advantage of the vectorized objective function, set the `UseVectorized`

option to `true`

and the `UseCompletePoll`

option to `true`

. `patternsearch`

requires both of these options to compute in a vectorized manner.

options = optimoptions(@patternsearch,'UseVectorized',true,'UseCompletePoll',true);

Specify the objective function and call `patternsearch`

, including the `options`

argument. Use `tic/toc`

to evaluate the solution time.

ObjectiveFunction = @(x) vectorized_objective(x,4,2.1,4); tic [x,fval] = patternsearch(ObjectiveFunction,x0,[],[],[],[],[],[],[],options)

Optimization terminated: mesh size less than options.MeshTolerance.

`x = `*1×2*
-0.0898 0.7127

fval = -1.0316

toc

Elapsed time is 0.027503 seconds.

Evaluate the nonvectorized solution time for comparison.

tic [x,fval] = patternsearch(ObjectiveFunction,x0)

Optimization terminated: mesh size less than options.MeshTolerance.

`x = `*1×2*
-0.0898 0.7127

fval = -1.0316

toc

Elapsed time is 0.027502 seconds.

In this case, the vectorization does not have a significant impact on the solution time.

[1] Dixon, L. C. W., and G .P. Szego (eds.). *Towards Global Optimisation 2.* North-Holland: Elsevier Science Ltd., Amsterdam, 1978.