Optimization: Reuse calculations from objective function in nonlinear constraints function

6 vues (au cours des 30 derniers jours)
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.

Réponse acceptée

Torsten
Torsten le 15 Août 2022
  13 commentaires
Torsten
Torsten le 16 Août 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 le 16 Août 2022
Thanks for the explanation! Passing a handle looks better than passing a vector as I was thinking. Looks more neat.

Connectez-vous pour commenter.

Plus de réponses (1)

Bruno Luong
Bruno Luong le 15 Août 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 commentaire
Gustavo Lunardon
Gustavo Lunardon le 15 Août 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.

Connectez-vous pour commenter.

Produits


Version

R2020b

Community Treasure Hunt

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

Start Hunting!

Translated by