Optimization: Reuse calculations from objective function in nonlinear constraints function

2 views (last 30 days)
Hello,
Is it possible to reuse calculations from one function in the other to save computational effort?
Example:
function SSE = objfunc(inputs)
% some calculations that output model results + some other things
SSE = sum(residuals.^2)
end
function [c, ceq] = nonlinconstraint(inputs)
% same calculations as the objective function
building c and ceq vectors
end
Now, I know I could make a third function that wraps the calculations I mention and call that function both in objfunc and nonlinconstraint but that would imply in doing (the same) expensive calculations twice. Is there a way to reuse the calculations from one function into another or calculate it only once and pass the results to them? Other some other workflow that saves time?
If I use parallel computing toolbox I doubt it would reuse these common calculations, although it would probably make the code faster.
I am talking in the context of optimization, like multistart, globalsearch, fmincon, etc. that take up those functions to try to find global/local optimum.
I could potentially write a single function that outputs SSE,c,ceq but then I do not know how I would pass it to the aforementioned algorithms.

Accepted Answer

Torsten
Torsten on 15 Aug 2022
  13 Comments
Torsten
Torsten on 16 Aug 2022
You get the control vector
u = [u1,u2,u3,...,uN]
passed from "fmincon", I guess, because it is usually made up of variables to be adapted/optimized. With this control vector, one usually forms a function handle
fun_u = @(t)interp1(tspan,u,t,'spline') (or something else instead of spline)
passes this function handle to the ode-integrator (more precisely: to the function where you define the ode system) and evaluates it at the places where the control variable needs to be inserted as
u = fun_u(t).
Note that the (length of u) might be the (length of tspan - 1) ; this has somhow to be handled in the definition of fun_u.
Gustavo Lunardon
Gustavo Lunardon on 16 Aug 2022
Thanks for the explanation! Passing a handle looks better than passing a vector as I was thinking. Looks more neat.

Sign in to comment.

More Answers (1)

Bruno Luong
Bruno Luong on 15 Aug 2022
You can use this design pattern
function preciousvalue = expensivereuse(inputs)
persistent lastresult
if ~isempty(lastresult) && isequal(input, lastresult.inputs)
preciousvalue = lastresult.preciousvalue;
else
preciousvalue = computepreciousvalue(inputs); % this is the function that computes the expensive part
lastresult = struct('inputs', inputs, 'preciousvalue', preciousvalue);
end
end
function SSE = objfunc(inputs)
preciousvalue = expensivereuse(inputs);
% some specific calculations that output model results + some other things
% from preciousvalue
SSE = sum(residuals.^2)
end
function [c, ceq] = nonlinconstraint(inputs)
preciousvalue = expensivereuse(inputs);
% some specific calculations
from preciousvalue
building c and ceq vectors
end
  1 Comment
Gustavo Lunardon
Gustavo Lunardon on 15 Aug 2022
That is an interesting approach. It uses some lines I was not familiar with, like the persistent and from. I will keep that in mind. Thanks for the suggestion! It opens some paths to do other things I was looking for as well.

Sign in to comment.

Products


Release

R2020b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!