8.7 Progress and data callback¶
Callbacks are a very useful mechanism that allow the caller to track the progress of the MOSEK optimizer. A callback function provided by the user is regularly called during the optimization and can be used to
obtain a customized log of the solver execution,
collect information for debugging purposes or
ask the solver to terminate.
Fusion API for C++ has the following callback mechanisms:
progress callback, which provides only the basic status of the solver.
data callback, which provides the solver status and a complete set of information items that describe the progress of the optimizer in detail.
Warning
The callbacks functions must not invoke any functions of the solver, environment or task. Otherwise the state of the solver and its outcome are undefined.
8.7.1 Data callback¶
In the data callback MOSEK passes a callback code and values of all information items to a user-defined function. The callback function is called, in particular, at the beginning of each iteration of the interior-point optimizer. For the simplex optimizers logSimFreq
controls how frequently the call-back is called.
The data callback is set by calling the method Model.setDataCallbackHandler
.
The callback function should have the following signature:
typedef std::function<bool(MSKcallbackcodee, const double *, const int32_t *, const int64_t *)> callbackHandler_t;
Arguments:
caller
- the status of the optimizer.douinf
- values of double information items.intinf
- values of integer information items.lintinf
- values of long information items.
Return value: Non-zero return value of the callback function indicates that the optimizer should be terminated.
8.7.2 Progress callback¶
In the progress callback MOSEK provides a single code indicating the current stage of the optimization process.
The callback is set by calling the method Model.setCallbackHandler
.
The callback function should have the following signature
typedef std::function<int(MSKcallbackcodee)> progressHandler_t;
Arguments:
caller
- the status of the optimizer.
Return value: Non-zero return value of the callback function indicates that the optimizer should be terminated.
8.7.3 Working example: Data callback¶
The following example defines a data callback function that prints out some of the information items. It interrupts the solver after a certain time limit. Note that the time limit refers to time spent in the solver and does not include setting up the model in Fusion.
static int MSKAPI usercallback( MSKcallbackcodee caller,
const double * douinf,
const int32_t * intinf,
const int64_t * lintinf,
Model::t mod,
const double maxtime)
{
switch ( caller )
{
case MSK_CALLBACK_BEGIN_INTPNT:
std::cerr << "Starting interior-point optimizer\n";
break;
case MSK_CALLBACK_INTPNT:
std::cerr << "Iterations: " << intinf[MSK_IINF_INTPNT_ITER];
std::cerr << " (" << douinf[MSK_DINF_OPTIMIZER_TIME] << "/";
std::cerr << douinf[MSK_DINF_INTPNT_TIME] << ")s. \n";
std::cerr << "Primal obj.: " << douinf[MSK_DINF_INTPNT_PRIMAL_OBJ];
std::cerr << " Dual obj.: " << douinf[MSK_DINF_INTPNT_DUAL_OBJ] << std::endl;
break;
case MSK_CALLBACK_END_INTPNT:
std::cerr << "Interior-point optimizer finished.\n";
break;
case MSK_CALLBACK_BEGIN_PRIMAL_SIMPLEX:
std::cerr << "Primal simplex optimizer started.\n";
break;
case MSK_CALLBACK_UPDATE_PRIMAL_SIMPLEX:
std::cerr << "Iterations: " << intinf[MSK_IINF_SIM_PRIMAL_ITER];
std::cerr << " Elapsed time: " << douinf[MSK_DINF_OPTIMIZER_TIME];
std::cerr << "(" << douinf[MSK_DINF_SIM_TIME] << ")\n";
std::cerr << "Obj.: " << douinf[MSK_DINF_SIM_OBJ] << std::endl;
break;
case MSK_CALLBACK_END_PRIMAL_SIMPLEX:
std::cerr << "Primal simplex optimizer finished.\n";
break;
case MSK_CALLBACK_BEGIN_DUAL_SIMPLEX:
std::cerr << "Dual simplex optimizer started.\n";
break;
case MSK_CALLBACK_UPDATE_DUAL_SIMPLEX:
std::cerr << "Iterations: " << intinf[MSK_IINF_SIM_DUAL_ITER];
std::cerr << " Elapsed time: " << douinf[MSK_DINF_OPTIMIZER_TIME];
std::cerr << "(" << douinf[MSK_DINF_SIM_TIME] << ")\n";
std::cerr << "Obj.: " << douinf[MSK_DINF_SIM_OBJ] << std::endl;
break;
case MSK_CALLBACK_END_DUAL_SIMPLEX:
std::cerr << "Dual simplex optimizer finished.\n";
break;
case MSK_CALLBACK_BEGIN_BI:
std::cerr << "Basis identification started.\n";
break;
case MSK_CALLBACK_END_BI:
std::cerr << "Basis identification finished.\n";
break;
default:
break;
}
if ( douinf[MSK_DINF_OPTIMIZER_TIME] >= maxtime )
{
std::cerr << "MOSEK is spending too much time. Terminate it.\n";
return 1;
}
return 0;
} /* usercallback */
Assuming that we have defined a model M
and a time limit maxtime
, the callback function is attached as follows:
callbackHandler_t cllbck = [&](MSKcallbackcodee caller,
const double * douinf, const int32_t* intinf, const int64_t* lintinf)
{
return usercallback(caller, douinf, intinf, lintinf, M, maxtime);
};
M->setDataCallbackHandler(cllbck);