mechmotum / cyipopt

Cython interface for the interior point optimzer IPOPT
Eclipse Public License 2.0
227 stars 54 forks source link

Handle function evaluation errors #210

Closed Robbybp closed 11 months ago

Robbybp commented 1 year ago

Ipopt function/derivative callbacks should return false if there was a problem with the evaluation. This way Ipopt can try to recover by cutting the step size and trying again.

This does not appear to be supported in CyIpopt. For example, here in the constraint callback, True is returned even if an exception is encountered. I'm not sure how this exception is then processed. When my callback Python code raises an exception, I get "Stopping optimization at current point as requested by user" and my Python exception is re-raised.

I propose that there should be a particular type of exception, e.g. CyIpoptEvaluationError, that will cause CyIpopt evaluation callbacks to return False to Ipopt (and are otherwise ignored by CyIpopt).

Does this sound like a reasonable way to handle evaluation errors? If so, I'm happy to try to implement this.

Robbybp commented 1 year ago

In an initial test, returning False in an evaluation callback causes Ipopt to halt with the message "Invalid number in NLP function or derivative detected". Looking at the code for the AMPL interface, which handles evaluation errors routinely, we might be missing a call to ipopt_application->RethrowNonIpoptException(false);? From the documentation, this does not appear to control behavior on callbacks returning False, but it is the only thing that stands out to me in a quick glance at the AMPL interface.

moorepants commented 1 year ago

We'll definitely review pull requests that try to address this. Feel free to submit something though if you are digging into it.

Robbybp commented 1 year ago

In an initial test, returning False in an evaluation callback causes Ipopt to halt with the message "Invalid number in NLP function or derivative detected".

This appears to be because Ipopt only handles function evaluation errors in the objective and constraint callbacks, and I was testing an error in the Jacobian callback. This is a little inconvenient for the user, but there is nothing to stop us from returning false and letting Ipopt handle this how it chooses.