Skip to content

Commit

Permalink
check for interrupt signal in AmplTNLP (optionally) and ipopt exe
Browse files Browse the repository at this point in the history
- stop gracefully and return current iterate
  • Loading branch information
svigerske committed Jul 3, 2024
1 parent 8abed8a commit d6a5f96
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 5 deletions.
4 changes: 4 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ More detailed information about incremental changes can be found in the

- Added `Ipopt::RegisterInterruptHandler()` and `Ipopt::UnregisterInterruptHandler()`
to `IpUtils.hpp` to wrap handling of interrupt signals.
Added parameter `checkinterrupt` (default false) to `AmplTNLP` constructor
to enable check for interrupt signal in `intermediate_callback`.
- The `ipopt` executable can now be interrupted by SIGINT/SIGHUP (POSIX systems) or
SIGINT/SIGTERM/SIGABRT (Windows systems).

### 3.14.16 (2024-04-22)

Expand Down
41 changes: 38 additions & 3 deletions src/Apps/AmplSolver/AmplTNLP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,11 @@ void AmplTNLP::gutsOfConstructor(
THROW_EXCEPTION(INVALID_TNLP, "Unknown error in stub file read");
}
}

if( checkinterrupt_ && !RegisterInterruptHandler(NULL, &interrupted_) )
{
jnlst_->Printf(J_STRONGWARNING, J_MAIN, "Could not register handler for interrupt signals.\n");
}
}

AmplTNLP::AmplTNLP(
Expand All @@ -182,7 +187,8 @@ AmplTNLP::AmplTNLP(
const char* ampl_option_string /* = NULL */,
const char* ampl_invokation_string /* = NULL */,
const char* ampl_banner_string /* = NULL */,
std::string* nl_file_content /* = NULL */
std::string* nl_file_content /* = NULL */,
bool checkinterrupt /* = false */
)
: TNLP(),
jnlst_(jnlst),
Expand All @@ -200,7 +206,9 @@ AmplTNLP::AmplTNLP(
hesset_called_(false),
set_active_objective_called_(false),
Oinfo_ptr_(NULL),
suffix_handler_(suffix_handler)
suffix_handler_(suffix_handler),
checkinterrupt_(checkinterrupt),
interrupted_(false)
{
DBG_START_METH("AmplTNLP::AmplTNLP", dbg_verbosity);

Expand Down Expand Up @@ -236,7 +244,9 @@ AmplTNLP::AmplTNLP(
hesset_called_(false),
set_active_objective_called_(false),
Oinfo_ptr_(NULL),
suffix_handler_(suffix_handler)
suffix_handler_(suffix_handler),
checkinterrupt_(false),
interrupted_(false)
{
DBG_START_METH("AmplTNLP::AmplTNLP", dbg_verbosity);

Expand Down Expand Up @@ -356,6 +366,11 @@ AmplTNLP::~AmplTNLP()
}

delete (fint*) nerror_;

if( checkinterrupt_ && !UnregisterInterruptHandler() )
{
jnlst_->Printf(J_STRONGWARNING, J_MAIN, "Failed to unregister handler for interrupt signals.\n");
}
}

bool AmplTNLP::get_nlp_info(
Expand Down Expand Up @@ -763,6 +778,26 @@ bool AmplTNLP::eval_h(
return false;
}

bool AmplTNLP::intermediate_callback(
AlgorithmMode /*mode*/,
Index /*iter*/,
Number /*obj_value*/,
Number /*inf_pr*/,
Number /*inf_du*/,
Number /*mu*/,
Number /*d_norm*/,
Number /*regularization_size*/,
Number /*alpha_du*/,
Number /*alpha_pr*/,
Index /*ls_trials*/,
const IpoptData* /*ip_data*/,
IpoptCalculatedQuantities* /*ip_cq*/
)
{
/* returning false makes Ipopt stop */
return !interrupted_;
}

void AmplTNLP::finalize_solution(
SolverReturn status,
Index n,
Expand Down
24 changes: 23 additions & 1 deletion src/Apps/AmplSolver/AmplTNLP.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,8 @@ class IPOPTAMPLINTERFACELIB_EXPORT AmplTNLP: public TNLP
const char* ampl_option_string = NULL,
const char* ampl_invokation_string = NULL,
const char* ampl_banner_string = NULL,
std::string* nl_file_content = NULL
std::string* nl_file_content = NULL,
bool checkinterrupt = false ///< @since 3.14.17
);

/** Constructor without RegisteredOptions.
Expand Down Expand Up @@ -468,6 +469,22 @@ class IPOPTAMPLINTERFACELIB_EXPORT AmplTNLP: public TNLP

/** @name Solution Methods */
///@{
virtual bool intermediate_callback(
AlgorithmMode mode,
Index iter,
Number obj_value,
Number inf_pr,
Number inf_du,
Number mu,
Number d_norm,
Number regularization_size,
Number alpha_du,
Number alpha_pr,
Index ls_trials,
const IpoptData* ip_data,
IpoptCalculatedQuantities* ip_cq
);

virtual void finalize_solution(
SolverReturn status,
Index n,
Expand Down Expand Up @@ -687,6 +704,11 @@ class IPOPTAMPLINTERFACELIB_EXPORT AmplTNLP: public TNLP
/** Suffix Handler */
SmartPtr<AmplSuffixHandler> suffix_handler_;

/** whether to register handler for interrupt signals */
bool checkinterrupt_;
/** pointer to flag to check whether to interrupt signal was set */
bool interrupted_;

/** Make the objective call to ampl */
bool internal_objval(
const Number* x,
Expand Down
2 changes: 1 addition & 1 deletion src/Apps/AmplSolver/ampl_ipopt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ int main(
suffix_handler->AddAvailableSuffix("ipopt_zU_in", AmplSuffixHandler::Variable_Source,
AmplSuffixHandler::Number_Type);

SmartPtr<TNLP> ampl_tnlp = new AmplTNLP(ConstPtr(app->Jnlst()), app->RegOptions(), app->Options(), args, suffix_handler);
SmartPtr<TNLP> ampl_tnlp = new AmplTNLP(ConstPtr(app->Jnlst()), app->RegOptions(), app->Options(), args, suffix_handler, false, NULL, NULL, NULL, NULL, NULL, true);

// Call Initialize again to process output related options
retval = app->Initialize();
Expand Down

0 comments on commit d6a5f96

Please sign in to comment.