Return from a function before reaching its end

Is there a command which makes the running of a function stop and return? In other words, I am looking for the Gauss version of the return command in Matlab.

For example, I have a function that calculates the log-likelihood function of an econometric model. What I want is that if, say, a parameter/matrix has an undesirable value (e.g. the largest eigenvalue of the matrix is greater than 1), then the log-likelihood value takes an extreme value and returns without doing the remaining calculations. Hence, CMLMT (or other optimisation library) must come up with an another parameter structure and start again. Is this possible in Gauss?

Thanks!

8 Answers



0



If there's something happening in your log-likelihood procedure that you don't like, return a scalar missing value.  CMLMT will try to recover, but if it's not able to it'll return with an error code.  Test for an error code greater than 2, and if so, try another set of starting values.



0



Ok, so I can set llfun = {}; if something is wrong with the parameters. What I want is that if this happens, the program should abort the procedure, jump out of it and return to it with a different set of starting values, but without stopping the program running with an error code.

Could you elaborate more on this error code issue? I've never done that and am not very familiar with it.

Thanks!



0



To return from a procedure early, all you need to do is add a retp statement at the location in which you would like to exit. For example:

proc (1) = hypotenuse(a, b);
   local c;
   
   if a <= 0;
       c = {};
       retp(c);
   endif;

   c = sqrt(a.^2 + b.^2);
   retp(c);
endp;

A scalar error code is a special type of missing value that has an integer encoded in it. This allows you to pass different types of non-fatal errors (i.e. where you don't necessarily want the program to end) and handle them appropriately. You can:

  1. Set a variable to be an error code with error
  2. Test to see if a variable is a scalar error code with scalmiss
  3. Decode the value of a scalar error code with scalerr

Continuing with our simple example from above:

a = 0;
b = 5;
c = hypotenuse(a, b);
if scalmiss(c);
   print "The following input was out of range: ";
   print scalerr(c);
endif;
proc (1) = hypotenuse(a, b);
   local c;
   
   if a <= 0;
       c = error(1);
       retp(c);
   endif;
   if b <= 0;
       c = error(2);
       retp(c);
   endif;

   c = sqrt(a.^2 + b.^2);
   retp(c);
endp;

aptech

1,773


0



Thanks for your reply.

Ok, I know how to do an early return from the procedure and now I also know how to define error codes. However, I still have some questions.

My procedure is the objective function for CMLMT, i.e., it's a function to be maximised. If a have a parameter value I don't like, I can set the function value to a missing value or an error code, that's fine. But how does CMLMT treat this? I don't want it to abort running, but rather that it return to the procedure with a different set of starting values. According to Ron's comment, I should return a scalar missing value and then CMLMT will try to recover, which I suppose means it tries new starting values. But what about CMLMT's error codes? Ron suggests testing for an error code greater than 2. Is there somewhere a list of error codes for CMLMT? Or is it just the out.Retcode number?



0



CMLMT returns a return code in out.retcode.  A complete list can be found in the Reference Section for CMLMT in the CMLMT documentation.  Zero is a normal return, one is a forced exit (pressing C on the keyboard during the iterations), and two is maximum iterations exceeded.  All other return values indicate some sort of pathological return.

It isn't possible to change the parameter values by the user during the iterations.   Generally, a calculation failure in the log-likelihood procedure indicates that constraints on the parameters need to be modified or added.  Your best alternative would be to add a constraint which would avoid that failure.

Alternatively if you wish to restart the estimation with new start values, you must test the return code and if it is greater than two, modify the start values appropriately and restart the iterations.

struct cmlmtResults out;

out.retcode = 3;

do until out.retcode <= 2;

out = cmlmt(&lpr,p0,d0,c0);

if out.retcode > 2;

// generate new start values in p0

endif;

endo;

If no set of parameters result in a return code less than or equal to 2, the loop will never end and you would need to force an exit, i.e., press the C key during the iterations.

As I've stated above, a better strategy would be to place sufficient constraints on the parameters to keep them in a well-defined region of the parameter space.



0



Thanks, that helps.

Actually, I don't want to change the parameter values during iterations. Instead, I want CMLMT to change them if they are not ok.

In a very simplified way, my problem is the following. In my model there is an autoregressive coefficient matrix, say, Phi, which I want to be stationary, i.e., its largest eigenvalue should be lower than 1. For simplicity, suppose Phi is 3x3 and diagonal. What I do is estimate the diagonal elements without any constraints and then do the following:

Phi_diag = phi1|phi2|phi3;
Phi = diagrv(zeros(3,3), exp(Phi_diag)./(1+exp(Phi_diag)));

This is supposed to yield a matrix with eigenvalues lower than 1, but numerically it happens sometimes that the largest eigenvalue is 1. In that case I want CMLMT to drop that parameter vector and go to another direction. Does this do the job?

if maxc(abs(eigh(Phi))) ge 1;
sum_ll = {};
retp{sum_ll};
endif;

What does CMLMT do exactly when I return a scalar missing value? What I don't want is to stop with an error message, I'd rather want it to be flexible and try different values as long as possible.



0



CMLMT is a computer program designed to handle that kind of problem.  Here is I would do it:

c0.ineqProc = &ineqp;

proc ineqp(struct PV p, struct DS d);

local phi, e;

phi = pvUnpack(p,"phi");

e = eigh(phi);

retp( (.999 - e) | (e + .999));

endp;

CMLMT will then keep the eigenvalues in the appropriate range.  No need to modify parameter settings, CMLMT knows how to do it.  And also, this works for both a full symmetric phi or a diagonal phi.

The nonlinear inequality is that it keeps what is returned by the procedure greater than or equal to zero.  Thus you must use .999 to avoid it being put on the boundary.

25 years ago, before programs like CMLMT existed, it was necessary to constrain using math transformations as you were doing.  To estimate the model using your method, you would need to slightly modify your code to keep it off of the boundary:

Phi = diagrv(zeros(3,3), exp(Phi_diag)./(1.001+exp(Phi_diag)));

 

 

 

 

 



0



Great reply, thanks!

Your solution is amazing, I've learnt a lot now.

Your Answer

8 Answers

0

If there's something happening in your log-likelihood procedure that you don't like, return a scalar missing value.  CMLMT will try to recover, but if it's not able to it'll return with an error code.  Test for an error code greater than 2, and if so, try another set of starting values.

0

Ok, so I can set llfun = {}; if something is wrong with the parameters. What I want is that if this happens, the program should abort the procedure, jump out of it and return to it with a different set of starting values, but without stopping the program running with an error code.

Could you elaborate more on this error code issue? I've never done that and am not very familiar with it.

Thanks!

0

To return from a procedure early, all you need to do is add a retp statement at the location in which you would like to exit. For example:

proc (1) = hypotenuse(a, b);
   local c;
   
   if a <= 0;
       c = {};
       retp(c);
   endif;

   c = sqrt(a.^2 + b.^2);
   retp(c);
endp;

A scalar error code is a special type of missing value that has an integer encoded in it. This allows you to pass different types of non-fatal errors (i.e. where you don't necessarily want the program to end) and handle them appropriately. You can:

  1. Set a variable to be an error code with error
  2. Test to see if a variable is a scalar error code with scalmiss
  3. Decode the value of a scalar error code with scalerr

Continuing with our simple example from above:

a = 0;
b = 5;
c = hypotenuse(a, b);
if scalmiss(c);
   print "The following input was out of range: ";
   print scalerr(c);
endif;
proc (1) = hypotenuse(a, b);
   local c;
   
   if a <= 0;
       c = error(1);
       retp(c);
   endif;
   if b <= 0;
       c = error(2);
       retp(c);
   endif;

   c = sqrt(a.^2 + b.^2);
   retp(c);
endp;
0

Thanks for your reply.

Ok, I know how to do an early return from the procedure and now I also know how to define error codes. However, I still have some questions.

My procedure is the objective function for CMLMT, i.e., it's a function to be maximised. If a have a parameter value I don't like, I can set the function value to a missing value or an error code, that's fine. But how does CMLMT treat this? I don't want it to abort running, but rather that it return to the procedure with a different set of starting values. According to Ron's comment, I should return a scalar missing value and then CMLMT will try to recover, which I suppose means it tries new starting values. But what about CMLMT's error codes? Ron suggests testing for an error code greater than 2. Is there somewhere a list of error codes for CMLMT? Or is it just the out.Retcode number?

0

CMLMT returns a return code in out.retcode.  A complete list can be found in the Reference Section for CMLMT in the CMLMT documentation.  Zero is a normal return, one is a forced exit (pressing C on the keyboard during the iterations), and two is maximum iterations exceeded.  All other return values indicate some sort of pathological return.

It isn't possible to change the parameter values by the user during the iterations.   Generally, a calculation failure in the log-likelihood procedure indicates that constraints on the parameters need to be modified or added.  Your best alternative would be to add a constraint which would avoid that failure.

Alternatively if you wish to restart the estimation with new start values, you must test the return code and if it is greater than two, modify the start values appropriately and restart the iterations.

struct cmlmtResults out;

out.retcode = 3;

do until out.retcode <= 2;

out = cmlmt(&lpr,p0,d0,c0);

if out.retcode > 2;

// generate new start values in p0

endif;

endo;

If no set of parameters result in a return code less than or equal to 2, the loop will never end and you would need to force an exit, i.e., press the C key during the iterations.

As I've stated above, a better strategy would be to place sufficient constraints on the parameters to keep them in a well-defined region of the parameter space.

0

Thanks, that helps.

Actually, I don't want to change the parameter values during iterations. Instead, I want CMLMT to change them if they are not ok.

In a very simplified way, my problem is the following. In my model there is an autoregressive coefficient matrix, say, Phi, which I want to be stationary, i.e., its largest eigenvalue should be lower than 1. For simplicity, suppose Phi is 3x3 and diagonal. What I do is estimate the diagonal elements without any constraints and then do the following:

Phi_diag = phi1|phi2|phi3;
Phi = diagrv(zeros(3,3), exp(Phi_diag)./(1+exp(Phi_diag)));

This is supposed to yield a matrix with eigenvalues lower than 1, but numerically it happens sometimes that the largest eigenvalue is 1. In that case I want CMLMT to drop that parameter vector and go to another direction. Does this do the job?

if maxc(abs(eigh(Phi))) ge 1;
sum_ll = {};
retp{sum_ll};
endif;

What does CMLMT do exactly when I return a scalar missing value? What I don't want is to stop with an error message, I'd rather want it to be flexible and try different values as long as possible.

0

CMLMT is a computer program designed to handle that kind of problem.  Here is I would do it:

c0.ineqProc = &ineqp;

proc ineqp(struct PV p, struct DS d);

local phi, e;

phi = pvUnpack(p,"phi");

e = eigh(phi);

retp( (.999 - e) | (e + .999));

endp;

CMLMT will then keep the eigenvalues in the appropriate range.  No need to modify parameter settings, CMLMT knows how to do it.  And also, this works for both a full symmetric phi or a diagonal phi.

The nonlinear inequality is that it keeps what is returned by the procedure greater than or equal to zero.  Thus you must use .999 to avoid it being put on the boundary.

25 years ago, before programs like CMLMT existed, it was necessary to constrain using math transformations as you were doing.  To estimate the model using your method, you would need to slightly modify your code to keep it off of the boundary:

Phi = diagrv(zeros(3,3), exp(Phi_diag)./(1.001+exp(Phi_diag)));

 

 

 

 

 

0

Great reply, thanks!

Your solution is amazing, I've learnt a lot now.


You must login to post answers.

Have a Specific Question?

Get a real answer from a real person

Need Support?

Get help from our friendly experts.