8.6 Stopping the solver

The Model provides the method Model.breakSolver that notifies the solver that it must stop as soon as possible. The solver will not terminate momentarily, as it only periodically checks for such notifications. In any case, it will stop as soon as possible. The typical usage pattern of this method would be:

  • build the optimization model M,

  • create a separate thread in which M will run,

  • break the solver by calling Model.breakSolver from the main thread.

Warnings and comments:

  • It is recommended to use the solver parameters to set or modify standard built-in termination criteria (such as maximal running time, solution tolerances etc.). See Sec. 8.4 (Setting solver parameters).

  • More complicated user-defined termination criteria can be implemented within a callback function. See Sec. 8.7 (Progress and data callback).

  • The state of the solver and solution after termination may be undefined.

  • This operation is very language dependent and particular care must be taken to avoid stalling or other undesired side effects.

8.6.1 Example: Setting a Time Limit

For the purpose of the tutorial we will implement a busy-waiting breaker with the time limit as a termination criterion. Note that in practice it would be better just to set the parameter optimizerMaxTime.

Suppose we built a model M that is known to run for quite a long time (in the accompanying example code we create a particular integer program). Then we could create a new thread solving the model:

  bool alive = true;
  std::thread T(std::function<void(void)>([&]() { M->solve(); alive = false; }) );

In the main thread we are going to check if a time limit has elapsed. After calling Model.breakSolver we should wait for the solver thread to actually return. Altogether this scenario can be implemented as follows:

Listing 8.5 Stopping solver execution. Click here to download.
  bool alive = true;
  std::thread T(std::function<void(void)>([&]() { M->solve(); alive = false; }) );

  time_t T0 = time(NULL);
  while (true)
  {
    if (time(NULL) - T0 > timeout)
    {
      std::cout << "Solver terminated due to timeout!\n";
      M->breakSolver();
      T.join();
      break;
    }
    if (! alive)
    {
      std::cout << "Solver terminated before anything happened!\n";
      T.join();
      break;
    }
  }