Output Functions for GlobalSearch and MultiStart
What Are Output Functions?
Output functions allow you to examine intermediate results in an optimization. Additionally, they allow you to halt a solver programmatically.
There are two types of output functions, like the two types of output structures:
Global output functions run after each local solver run. They also run when the global solver starts and ends.
Local output functions run after each iteration of a local solver. See Output Functions for Optimization Toolbox.
To use global output functions:
Write output functions using the syntax described in OutputFcn.
Set the
OutputFcn
property of yourGlobalSearch
orMultiStart
solver to the function handle of your output function. You can use multiple output functions by setting theOutputFcn
property to a cell array of function handles.
The built-in @savelocalsolutions
output function saves all
local solutions to the localSolTable
variable in the base
workspace. This output function saves the infeasible local solutions as well as the
feasible local solutions; the solutions
output of run
returns
only the local solutions with positive exit flag.
Collect All Local Solutions
This example shows how to use the savelocalsolutions
output
function with MultiStart
to collect all the local solutions found
during a run. Begin by specifying savelocalsolutions
as an output
function for MultiStart
.
ms = MultiStart(OutputFcn=@savelocalsolutions);
Create a problem in three variables for MultiStart
using the
bigtoleft
objective function and the
twocone
nonlinear constraint function, listed in Helper Functions at the end of this
example. Set lower bounds of –1e5
in each component and upper
bounds of 1e5
. For details of this objective function and
nonlinear constraint function, see fmincon Interior-Point Algorithm with Analytic Hessian.
fun = @bigtoleft; lb = -1e5*ones(1,3); ub = -lb;
The objective and constraint functions contain derivative information. Set the options to use derivatives.
opts = optimoptions(@fmincon,SpecifyObjectiveGradient=true,...
SpecifyConstraintGradient=true);
Set the initial point to [–10,–10,–10] and create the optimization problem.
x0 = -10*ones(1,3); prob = createOptimProblem("fmincon",x0=x0,... lb = lb,ub = ub,... objective=fun,nonlcon=@twocone,options=opts);
For reproducibility, set the random seed. Run MultiStart
on 35
start points.
rng default
[x,fval,eflag,output,solns] = run(ms,prob,35)
MultiStart completed some of the runs from the start points. 11 out of 35 local solver runs converged with a positive local solver exitflag. x = -6.5000 -0.0000 -3.5000 fval = -2.8941e+03 eflag = 2 output = struct with fields: funcCount: 73904 localSolverTotal: 35 localSolverSuccess: 11 localSolverIncomplete: 23 localSolverNoSolution: 1 message: 'MultiStart completed some of the runs from the start points. ↵↵11 out of 35 local solver runs converged with a positive local solver exitflag.' solns = 1×2 GlobalOptimSolution array with properties: X Fval Exitflag Output X0
The workspace contains the localSolTable
variable, which has
all 35 local solutions. In contrast, the output structure shows that only 11 local
solver runs were successful.
size(localSolTable)
ans = 35 4
To see the kind of information returned by the output function, view the first
line of localSolTable
.
disp(localSolTable(1,:))
X fval exitflag constrviolation ________________________________ _______ ________ _______________ -6.5 2.3432e-07 -3.5 -2894.1 1 0
The output function returns the local solution X
, its
associated objective function value fval
, the exit flag
corresponding to that local solver run, and the constraint violation, which is
0
for no constraint violations.
Helper Functions
This code creates the bigtoleft
helper function.
function [f,gradf] = bigtoleft(x) % This is a simple function that grows rapidly negative % as x(1) becomes negative % f = 10*x(:,1).^3+x(:,1).*x(:,2).^2+x(:,3).*(x(:,1).^2+x(:,2).^2); if nargout > 1 gradf=[30*x(1)^2+x(2)^2+2*x(3)*x(1); 2*x(1)*x(2)+2*x(3)*x(2); (x(1)^2+x(2)^2)]; end end
This code creates the twocone
helper function.
function [c,ceq,gradc,gradceq] = twocone(x) % This constraint is two cones, z > -10 + r % and z < 3 - r ceq = []; r = sqrt(x(1)^2 + x(2)^2); c = [-10+r-x(3); x(3)-3+r]; if nargout > 2 gradceq = []; gradc = [x(1)/r,x(1)/r; x(2)/r,x(2)/r; -1,1]; end end
Custom GlobalSearch Output Function
This output function stops GlobalSearch
after it
finds five distinct local minima with positive exit flags, or after it finds a local
minimum value less than 0.5
. The output function uses a
persistent local variable, foundLocal
, to store the local
results. foundLocal
enables the output function to determine
whether a local solution is distinct from others, to within a tolerance of
1e-4
.
To store local results using nested functions instead of persistent variables, see Example of a Nested Output Function.
Write the output function using the syntax described in OutputFcn.
function stop = StopAfterFive(optimValues, state) persistent foundLocal stop = false; switch state case 'init' foundLocal = []; % initialized as empty case 'iter' newf = optimValues.localsolution.Fval; exitflag = optimValues.localsolution.Exitflag; % Now check if the exit flag is positive and % the new value differs from all others by at least 1e-4 % If so, add the new value to the newf list if exitflag > 0 && all(abs(newf - foundLocal) > 1e-4) foundLocal = [foundLocal;newf]; % Now check if the latest value added to foundLocal % is less than 1/2 % Also check if there are 5 local minima in foundLocal % If so, then stop if foundLocal(end) < 0.5 || length(foundLocal) >= 5 stop = true; end end end
Save
StopAfterFive.m
as a file in a folder on your MATLAB® path.Write the objective function and create an optimization problem structure as in Find Global or Multiple Local Minima.
function f = sawtoothxy(x,y) [t r] = cart2pol(x,y); % change to polar coordinates h = cos(2*t - 1/2)/2 + cos(t) + 2; g = (sin(r) - sin(2*r)/2 + sin(3*r)/3 - sin(4*r)/4 + 4) ... .*r.^2./(r+1); f = g.*h; end
Save
sawtoothxy.m
as a file in a folder on your MATLAB path.At the command line, create the problem structure:
problem = createOptimProblem('fmincon',... 'objective',@(x)sawtoothxy(x(1),x(2)),... 'x0',[100,-50],'options',... optimoptions(@fmincon,'Algorithm','sqp'));
Create a
GlobalSearch
object with@StopAfterFive
as the output function, and set the iterative display property to'iter'
.gs = GlobalSearch('OutputFcn',@StopAfterFive,'Display','iter');
(Optional) To get the same answer as this example, set the default random number stream.
rng default
Run the problem.
[x,fval] = run(gs,problem)
Num Pts Best Current Threshold Local Local Analyzed F-count f(x) Penalty Penalty f(x) exitflag Procedure 0 200 555.5 555.5 0 Initial Point 200 1463 1.547e-15 1.547e-15 1 Stage 1 Local GlobalSearch stopped by the output or plot function. 1 out of 2 local solver runs converged with a positive local solver exit flag. x = 1.0e-07 * 0.0414 0.1298 fval = 1.5467e-15
The run stopped early because GlobalSearch
found
a point with a function value less than 0.5
.
No Parallel Output Functions
While MultiStart
can run in parallel, it does
not support global output functions and plot functions in parallel.
Furthermore, while local output functions and plot functions run on
workers when MultiStart
runs in parallel, the effect
differs from running serially. Local output and plot functions do
not create a display when running on workers. You do not see any other
effects of output and plot functions until the worker passes its results
to the client (the originator of the MultiStart
parallel
jobs).
For information on running MultiStart
in parallel,
see Parallel Computing.