Thread Subject:
fmincon flow control/sharing variables

Subject: fmincon flow control/sharing variables

From: Andrew

Date: 31 Jul, 2012 21:39:31

Message: 1 of 3

Hello,

I'm having trouble setting up fmincon for a constrained optimization problem. I'm not sure what the best way to setup a script/function to minimize my computation with fmincon.

I have 2 nonlinear constraint functions,f1 and f2, in which I can compute both gradients.

I also have the objective function, obj, that I am trying to minimize, with gradient.

obj(x), f1(x) and f2(x) have shared computation. In practice, I would compute all of these in one function to reduce the repeated computation. Or, I would create a fourth function with the repeated calculation output, and I would simply restructure obj(x), f1(x) and f2(x) to have the repeated calculations as input.

What is the best way to set this up? I'm not so familiar with using function handles, although it seems that I should use these. I've also read about using nested functions, but it's not clear how I can nest these. I've read http://www.mathworks.com/matlabcentral/newsreader/view_thread/269936 and I am still confused. It's not obvious to me on how to create the handles to reduce computation and when I should actually call fmincon.

Thank you.

Subject: fmincon flow control/sharing variables

From: Matt J

Date: 31 Jul, 2012 23:35:44

Message: 2 of 3

"Andrew" wrote in message <jv9jaj$50l$1@newscl01ah.mathworks.com>...
>
> I've read http://www.mathworks.com/matlabcentral/newsreader/view_thread/269936 and I am still confused. It's not obvious to me on how to create the handles to reduce computation and when I should actually call fmincon.
===================

In attempt to make that clearer, I've modified the code below describing the technique, combining it with corrections and tweaks that came later in the thread. I've also used notation closer to FMINCON documentation.

So, you need to call ObjectiveAndConstraints first. It creates handles fun and nonlcon to your objective function and constraints. It must be implemented in a function mfile and your objective and constraints must be implemented as nested functions within this file.

Once fun and nonlcon have been created, you pass them to FMINCON as described in fmincon's documentation.


%%%%This goes in an mfile called ObjectiveAndConstraints.m

function [fun,nonlcon]=ObjectiveAndConstraints

ImportantQuantity=[];
LastX=[];

fun=@objective;
nonlcon=@constraints;

   function [val,grad]=objective(x)
    
        if ~isequal(x,LastX) %update if x is new

            ImportantQuantity=....; %shared computation here
            LastX=x;

       end

        %other code down here
       
   end

   function [c,ceq,GC,GCeq]=constraints(x)
    
        if ~isequal(x,LastX) %update if x is new

            ImportantQuantity=....; %shared computation here
            LastX=x;

       end

        %other code down here

   end


end

Subject: fmincon flow control/sharing variables

From: Alan_Weiss

Date: 1 Aug, 2012 14:50:53

Message: 3 of 3

On 7/31/2012 7:35 PM, Matt J wrote:
> "Andrew" wrote in message <jv9jaj$50l$1@newscl01ah.mathworks.com>...
>>
>> I've read
>> http://www.mathworks.com/matlabcentral/newsreader/view_thread/269936
>> and I am still confused. It's not obvious to me on how to create the
>> handles to reduce computation and when I should actually call fmincon.
> ===================
>
> In attempt to make that clearer, I've modified the code below
> describing the technique, combining it with corrections and tweaks
> that came later in the thread. I've also used notation closer to
> FMINCON documentation.
>
> So, you need to call ObjectiveAndConstraints first. It creates handles
> fun and nonlcon to your objective function and constraints. It must be
> implemented in a function mfile and your objective and constraints
> must be implemented as nested functions within this file.
> Once fun and nonlcon have been created, you pass them to FMINCON as
> described in fmincon's documentation.
>
>
> %%%%This goes in an mfile called ObjectiveAndConstraints.m
>
> function [fun,nonlcon]=ObjectiveAndConstraints
>
> ImportantQuantity=[];
> LastX=[];
>
> fun=@objective;
> nonlcon=@constraints;
>
> function [val,grad]=objective(x)
> if ~isequal(x,LastX) %update if x is new
>
> ImportantQuantity=....; %shared computation here
> LastX=x;
>
> end
>
> %other code down here
> end
>
> function [c,ceq,GC,GCeq]=constraints(x)
> if ~isequal(x,LastX) %update if x is new
>
> ImportantQuantity=....; %shared computation here
> LastX=x;
>
> end
>
> %other code down here
>
> end
>
>
> end

There is going to be a new documentation section dealing with this issue
in the future. Meanwhile, you might benefit from a sneak peak:


      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.
    <writing-constraints.html#zmw57dd0e5475>

  *

    Step 2. Embed function in nested function that keeps recent values.
    <writing-constraints.html#zmw57dd0e5516>

  *

    Step 3. Time to run with the nested function.
    <writing-constraints.html#zmw57dd0e5591>

  *

    Step 4. Time to run without nested function.
    <writing-constraints.html#zmw57dd0e5606>

  *

    Step 5. Save computing time with parallel computing.
    <writing-constraints.html#zmw57dd0e5636>

*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. (This example is in Solve a Constrained Nonlinear
Problem <example-nonlinear-constrained-minimization.html>.) 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
end

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(/x/_2 – /x/_1 ^2 )^2 + (1 – /x/_1 )^2
+ 20*(/x/_3 – /x/_4 ^2 )^2 + 5*(1 – /x/_4 )^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 = [];
end

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;
         end
         % Now compute objective function
         y = myf + 20*(x(3) - x(4)^2)^2 + 5*(1 - x(4))^2;
     end

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

end

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

*Step 3. Time to run with the nested function.*

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

opts = optimset('Algorithm','interior-point','Display','off');
x0 = [-1,1,1,2];
tic
[x,fval,exitflag,output] = runobjconstr(x0,opts);
toc

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;
end

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

Run fmincon, timing the call with tic and toc.

tic
[x,fval,exitflag,output] = fmincon(@myrosen2,x0,...
                    [],[],[],[],[],[],@constr,opts);
toc

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 'always'.

matlabpoolopen 4

Starting matlabpool using the 'local' profile ... connected to 4 labs.

opts = optimset(opts,'UseParallel','always');
tic
[x,fval,exitflag,output] = runobjconstr(x0,opts);
toc

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:

tic
[x,fval,exitflag,output] = fmincon(@myrosen2,x0,...
                    [],[],[],[],[],[],@constr,opts);
toc

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.


Alan Weiss
MATLAB mathematical toolbox documentation

Tags for this Thread

Everyone's Tags:

Add a New Tag:

Separated by commas
Ex.: root locus, bode

What are tags?

A tag is like a keyword or category label associated with each thread. Tags make it easier for you to find threads of interest.

Anyone can tag a thread. Tags are public and visible to everyone.

Tag Activity for This Thread
Tag Applied By Date/Time
optimization Andrew 31 Jul, 2012 17:44:14
fmincon Andrew 31 Jul, 2012 17:44:14
sharing variables ... Andrew 31 Jul, 2012 17:44:14
nonlinear constrai... Andrew 31 Jul, 2012 17:44:14
flow control Andrew 31 Jul, 2012 17:44:14
fmincon flow contr... Andrew 31 Jul, 2012 17:44:14
rssFeed for this Thread

Contact us