0

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);
2
  • If they were nested functions, then the inner function would be defined inside the outer function, and would have access to its variables. As it stands, it looks like obj is an independent, stand-alone function that uses undefined variables. Because you catch all errors and ignore them, you might not have noticed this. Commented Jun 29, 2020 at 21:20
  • Thanks. obj uses P when computing com1 which is one of the arguments of G_star. I don't know how to pass P through obj. Commented Jun 29, 2020 at 21:50

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.