When an interrupt request (ctrl-c) is sent to a Gurobi command line process (gurobi_cl), Gurobi will generally:
- terminate the process prematurely (Interrupt Request Received) and
- report the current optimization statistics (e.g., best objective, best bound, gap).
When terminating a standalone application that embeds Gurobi, data collection and processing need to happen before exiting the overall process. This scenario requires catching and handling termination signals gracefully.
In order to handle this software-generated interrupt from an external input (ctrl-c for instance), the application needs to:
- catch and register an external signal in the application and
- then manage such a signal through a signal handler.
Here, the signal handler must:
- terminate the Gurobi optimization process,
- wait for the optimization status to reflect that the process has been interrupted, and
- then query data from the solution and end the overall process.
The following C++ example illustrates this idea, which can be implemented in other programming languages (except for Python, where the signal is caught on the gurobipy module by default).
#include <iostream>
#include <csignal>
#include <Windows.h>
#include "gurobi_c++.h"
using namespace std;
GRBEnv env = GRBEnv();
GRBModel model = GRBModel(env, "glass4.mps");
/* handle termination signal caught in main */
static void signalHandler(int signum) {
/* terminate solve process */
model.terminate();
/* query solve status until available and handle exception when not available */
for (bool success = false; !success; ){
try {
if (model.get(GRB_IntAttr_Status) == GRB_INTERRUPTED) {
/* query solver data once solve is interrupted */
cout << "\n OBJECTIVE = " << model.get(GRB_DoubleAttr_ObjVal) << "\n";
}
success = true;
}
catch (GRBException e) {
/* the error output is optional */
cout << "Error code = " << e.getErrorCode() << endl;
cout << e.getMessage() << endl;
}
}
exit(signum);
}
int main() {
int optimstatus;
/* register signal SIGINT and signal handler */
signal(SIGINT, signalHandler);
try {
model.optimize();
optimstatus = model.get(GRB_IntAttr_Status);
if (optimstatus == GRB_OPTIMAL) {
double objval = model.get(GRB_DoubleAttr_ObjVal);
cout << "Optimal objective: " << objval << endl;
}
else {
cout << "Optimization was stopped with status = "
<< optimstatus << endl;
}
}
catch (GRBException e) {
cout << "Error code = " << e.getErrorCode() << endl;
cout << e.getMessage() << endl;
}
catch (...) {
cout << "Error during optimization" << endl;
}
return 0;
}
Comments
0 comments
Article is closed for comments.