This is machine translation

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

Note: This page has been translated by MathWorks. Please click here
To view all translated materals including this page, select Japan from the country navigator on the bottom of this page.

Objective and Nonlinear Constraints in the Same Function

This example shows how to avoid calling a function twice when it computes values for both objective and constraints.

You typically use such a function in a simulation. Solvers such as fmincon evaluate the objective and nonlinear constraint functions separately. This evaluation is wasteful when you use the same calculation for both results.

To avoid wasting time, have your calculation use a nested function to evaluate the objective and constraint functions only when needed, by retaining the values of time-consuming calculations. Using a nested function avoids using global variables, yet lets intermediate results be retained and shared between the objective and constraint functions.

Step 1. Function that computes objective and constraints.

For example, suppose computeall is the expensive (time-consuming) function called by both the objective function and by the nonlinear constraint functions. Suppose you want to use fmincon as your optimizer.

Write a function that computes a portion of Rosenbrock's function f1 and a nonlinear constraint c1 that keeps the solution in a disk of radius 1 around the origin. Rosenbrock's function is


which has a unique minimum value of 0 at (1,1). See Solve a Constrained Nonlinear Problem.

In this example there is no nonlinear equality constraint, so ceq1 = []. Add a pause(1) statement to simulate an expensive computation.

function [f1,c1,ceq1] = computeall(x)
    ceq1 = [];
    c1 = norm(x)^2 - 1;
    f1 = 100*(x(2) - x(1)^2)^2 + (1-x(1))^2;
    pause(1) % simulate expensive computation

Save computeall.m as a file on your MATLAB® path.

Step 2. Embed function in nested function that keeps recent values.

Suppose the objective function is

y = 100(x2x12)2 + (1 – x1)2
+ 20*(x3x42)2 + 5*(1 – x4)2.

computeall returns the first part of the objective function. Embed the call to computeall in a nested function:

function [x,f,eflag,outpt] = runobjconstr(x0,opts)

if nargin == 1 % No options supplied
    opts = [];

xLast = []; % Last place computeall was called
myf = []; % Use for objective at xLast
myc = []; % Use for nonlinear inequality constraint
myceq = []; % Use for nonlinear equality constraint

fun = @objfun; % the objective function, nested below
cfun = @constr; % the constraint function, nested below

% Call fmincon
[x,f,eflag,outpt] = fmincon(fun,x0,[],[],[],[],[],[],cfun,opts);

    function y = objfun(x)
        if ~isequal(x,xLast) % Check if computation is necessary
            [myf,myc,myceq] = computeall(x);
            xLast = x;
        % Now compute objective function
        y = myf + 20*(x(3) - x(4)^2)^2 + 5*(1 - x(4))^2;

    function [c,ceq] = constr(x)
        if ~isequal(x,xLast) % Check if computation is necessary
            [myf,myc,myceq] = computeall(x);
            xLast = x;
        % Now compute constraint functions
        c = myc; % In this case, the computation is trivial
        ceq = myceq;


Save the nested function as a file named runobjconstr.m on your MATLAB path.

Step 3. Time to run with nested function.

Run the file, timing the call with tic and toc.

opts = optimoptions(@fmincon,'Algorithm','interior-point','Display','off');
x0 = [-1,1,1,2];
[x,fval,exitflag,output] = runobjconstr(x0,opts);
Elapsed time is 203.797275 seconds.

Step 4. Time to run without nested function.

Compare the times to run the solver with and without the nested function. For the run without the nested function, save myrosen2.m as the objective function file, and constr.m as the constraint:

function y = myrosen2(x)
    f1 = computeall(x); % get first part of objective
    y = f1 + 20*(x(3) - x(4)^2)^2 + 5*(1 - x(4))^2;

function [c,ceq] = constr(x)
    [~,c,ceq] = computeall(x);

Run fmincon, timing the call with tic and toc.

[x,fval,exitflag,output] = fmincon(@myrosen2,x0,...
Elapsed time is 406.771978 seconds.

The solver takes twice as long as before, because it evaluates the objective and constraint separately.

Step 5. Save computing time with parallel computing.

If you have a Parallel Computing Toolbox™ license, you can save even more time by setting the UseParallel option to true.

Starting parallel pool (parpool) using the 'local' profile ... connected to 4 workers.

ans = 

 Pool with properties: 

            Connected: true
           NumWorkers: 4
              Cluster: local
        AttachedFiles: {}
          IdleTimeout: 30 minute(s) (30 minutes remaining)
          SpmdEnabled: true
opts = optimoptions(opts,'UseParallel',true);
[x,fval,exitflag,output] = runobjconstr(x0,opts);
Elapsed time is 97.528110 seconds.

In this case, enabling parallel computing cuts the computational time in half.

Compare the runs with parallel computing, with and without a nested function:

[x,fval,exitflag,output] = fmincon(@myrosen2,x0,...
Elapsed time is 188.985178 seconds.

In this example, computing in parallel but not nested takes about the same time as computing nested but not parallel. Computing both nested and parallel takes half the time of using either alone.

Related Examples

More About

Was this topic helpful?