[Ipopt] Catch (...) statements in Ipopt

Stefan Vigerske stefan at math.hu-berlin.de
Wed May 24 06:56:33 EDT 2017


Hi,

I thought about adding a RethrowNonBonminException(bool) to 
BonBabSetupBase, but getting this to all places that it may be needed 
within Bonmin seemed to be more effort.
There was already a check for a NO_CATCH_ALL define at some places in 
the Bonmin code. I've now added a check for this to other catch(...) 
places where it was misses and added an 
IpIpoptApplication::RethrowNonIpoptException(true) call to the 
Bonmin/Ipopt interface (BonIpoptSolver.cpp).
This is only in trunk for now.
Would that be sufficient for you? So you would have to compile with 
-DNO_CATCH_ALL.

Stefan


On 05/16/2017 07:01 PM, David Wilkinson wrote:
> Hi Stefan:
> 
> I am using Ipopt via Bonmin, and it is not immediately obvious now to 
> get the IpotApplication object on which to call 
> RethrowNonIpoptException(). My goal is to avoid making any modifications 
> in the Bonmin/Ipopt source code (otherwise I could just hard-wire 
> rethrow_nonipoptexception_ to true in the IpoptApplication constructors).
> 
> The way I use Bonmin (based on the example in the Bonmin documentation) 
> is something like
> 
> // BonminOptimizer.cpp
> // Implementation of driver class for Bonmin
> 
> using namespace Bonmin;
> using namespace Ipopt;
> 
> // m_babPtr member is a smart pointer to Bonmin::Bab object
> 
> void BonminOptimizer::Run()
> {
>    BonminSetup bonmin(someArg);
>    // work with options
>    bonmin.initialize(GetRawPtr(myTminlp)); // creates first instance
>    try
>    {
>      m_babPtr.reset(new Bab());
>      m_babPtr->branchAndBound(bonmin);  // creates second instance
>    }
>    // some catch statements
>    // save some results
> }
> 
> This code indirectly creates two instances of IpoptApplication, as 
> indicated in the comments. It is the second one that catches exceptions 
> thrown in the TMINLP object of my driver application, but this 
> IpoptApplication object is not directly available in the above function, 
> because the branchAndBound() call does not return until the optimization 
> is completed.
> 
> I have actually been able to get what I want by doing the following:
> 
> // BonminOptimizer.cpp
> 
> void BonminOptimizer::RethrowNonIpoptException(bool dorethrow) const
> {
>    CbcModel& model = m_babPtr->model();
>    OsiTMINLPInterface* p = 
> static_cast<OsiTMINLPInterface*>(model.solver());
>    IpoptSolver* pSolver = static_cast<IpoptSolver*>(p->solver());
>    IpoptApplication& app = pSolver->getIpoptApp();
>    app.RethrowNonIpoptException(dorethrow);
> }
> 
> The above method is called from
> 
> // MyTMINLP.cpp
> 
> void MyTMINLP::CheckOptimizerStatus()
> {
>    // This method is called from each evaluation method in MyTMINLP
>    // m_pOptimizer is a member pointer to BonminOptimizer object
>    // m_bRethrow is a member bool, initially false
> 
>    if (!m_bRethrow) // IpoptApplication object is not yet in rethrow mode
>    {
>      m_pOptimizer->RethrowNonIpoptException(true); put in rethrow mode
>      m_bRethrow = true;
>    }
>    m_pOptimizer->CheckStatus();  // this may throw (by design)
> }
> 
> This seems to work but, as you can imagine, it took me a long time to 
> figure out how to get the IpoptApplication object, and it is extremely 
> clunky.
> 
> Might there be simpler way to do this?
> 
> If not, maybe this is a defect in Bonmin rather than Ipopt, but it would 
> be much easier if there were some global way to set 
> rethrow_nonipoptexception_, or if it could be set via the options.
> 
> Sorry for the long post...
> 
> David Wilkinson
> 
> ==========================================
> 
> Stefan Vigerske wrote:
>> Hi,
>>
>> you can change the value of rethrow_nonipoptexception_ via
>> IpoptApplication::RethrowNonIpoptException():
>>
>> https://www.coin-or.org/Ipopt/doxygen/classIpopt_1_1IpoptApplication.html#a985d4b2f4b443b7aef8d6e924c49b5ce 
>>
>>
>>
>> Best,
>> Stefan
>>
>> On 05/13/2017 12:47 PM, David Wilkinson wrote:
>>> I have a Bonmin/Ipopt client application that (rightly or wrongly) 
>>> uses C++
>>> exceptions for flow control in abnormal situations. In some of these
>>> situations, the exception is getting caught by catch (...) statements in
>>> Ipopt::IpoptApplication. The content in some (but not all) of these 
>>> catch
>>> (...) statements is protected by a variable 
>>> rethrow_nonipoptexception_, but
>>> this variable is hard-wired to be false, and so cannot be used to change
>>> behavior without modifying source code.
>>>
>>> Suggestion:
>>>
>>> The content of all occurrences of catch (...) in Ipopt::IpoptApplication
>>> should be protected by this rethrow_nonipoptexception_ variable, and its
>>> value should be controllable by a preprocessor symbol.
>>>
>>> There are examples of catch (...) statements in other parts of 
>>> COIN-OR (Bonmin
>>> and Clp) that are not harmful to my client application, but perhaps 
>>> these
>>> should also be protected in a similar manner.
>>>
>>> Thanks,
>>>
>>> David Wilkinson
>>> _______________________________________________
>>> Ipopt mailing list
>>> Ipopt at list.coin-or.org
>>> https://urldefense.proofpoint.com/v2/url?u=https-3A__list.coin-2Dor.org_mailman_listinfo_ipopt&d=DwICAg&c=Ngd-ta5yRYsqeUsEDgxhcqsYYY1Xs5ogLxWPA_2Wlc4&r=BRcuJnQr5NAzU29t80hk2rsLc4vrlRySBDabuq0O1ZI&m=uUZR1xuZjRHb2iwG1M6a4OZH7EZH4pOHxKw1tfWL5TE&s=_8Ow3ENlrd9SRhRDClaTgphGxyICFFwa7JbRD6uhG6o&e= 
>>>
>>>
>>
>>
> 


-- 
http://www.gams.com/~stefan


More information about the Ipopt mailing list