Star
Star

Reputation: 2299

Nesting multiple functions in Matlab

I have two nested functions in Matlab. The outer one uses fminunc and I would like your help how to correctly pass through it some arguments. Here my code

clear
rng default

%Some useful parameters
number_starting=10^3; 
r=10^5; 
J=2; 
epsilon_sim=-evrnd(0,1,r,J+1); %rx(J+1) 
options =  optimoptions(@fminunc, 'MaxFunctionEvaluations', 10^4 ,'MaxIterations', 10^4, 'StepTolerance', 10^(-8), 'Display', 'off');
u_starting=normrnd(0,1,number_starting,J); %rxJ

This is the outer function which uses fminunc

function conv_conjugate=G_star(P, number_starting, options, u_starting,epsilon_sim)

         fval=NaN(number_starting,1);
         exitflag=NaN(number_starting,1);

         for t=1:number_starting
             try
             coeff=u_starting(t,:).';  %starting values, column vector
             [~,fval_temp,exitflag_temp]=fminunc(@obj,coeff, options);
             fval(t)=fval_temp;
             exitflag(t)=exitflag_temp;
            catch 
             end
         end

         fval(exitflag>0,:);
         conv_conjugate=-min(fval);       
end

This is the inner function

function inner=obj(coeff)

comp1=sum(P.*(coeff.'));

comp2=mean(max(epsilon_sim+[coeff.' 0],[],2));

inner=-(comp1-comp2);
end

Here I try, for example, to evaluate the outer function at a given P and it clearly gives me a mistake because some arguments are not correctly passed through obj. Could you advise?

P_0=[0.7387,0.1562];
G_star(P_0, number_starting, options, u_starting,epsilon_sim);

Upvotes: 0

Views: 99

Answers (1)

Cris Luengo
Cris Luengo

Reputation: 60780

There are two different ways that you can implement this.

1: The simple way

We create an anonymous function that encapsulates function values. Your inner function becomes:

function inner=obj(coeff,P,epsilon_sim)
    comp1 = sum(P.*(coeff.'));
    comp2 = mean(max(epsilon_sim+[coeff.' 0],[],2));
    inner = -(comp1-comp2);
end

such that all values it uses are passed into it as arguments, then we create an anonymous function with one argument that calls obj with all its arguments:

@(x)obj(x,P,epsilon_sim)

This is used as follows:

[~,fval_temp,exitflag_temp] = fminunc(@(x)obj(x,P,epsilon_sim),coeff, options);

2: The more obscure way

I say more obscure because this method makes it harder to see what is happening with variables.

Here we create a nested function, which shares variables with the function it is nested in. A nested function is defined inside another function, and will only be visible to that function:

function conv_conjugate = G_star(P,number_starting,options,u_starting,epsilon_sim)
fval = NaN(number_starting,1);
exitflag = NaN(number_starting,1);
for t = 1:number_starting
   coeff = u_starting(t,:).';  %starting values, column vector
   [~,fval_temp,exitflag_temp] = fminunc(@obj,coeff, options);
   fval(t) = fval_temp;
   exitflag(t) = exitflag_temp;
end
fval(exitflag>0,:);
conv_conjugate = -min(fval);
   % Nested function:
   function inner=obj(coeff)
      comp1 = sum(P.*(coeff.'));
      comp2 = mean(max(epsilon_sim+[coeff.' 0],[],2));
      inner = -(comp1-comp2);
   end
end % Note this "end" terminates the enclosing function, and is mandatory.

In the nested function, P and epsilon_sim are shared with the enclosing function.

Upvotes: 1

Related Questions