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:

        T = threading.Thread(target=M.solve)

In the main thread we are going to check if one of the two criteria are satisfied:

  • a time limit has elapsed,

  • the user pressed CTRL+C.

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.
        T = threading.Thread(target=M.solve)
        T0 = time.time()

        try:
            T.start() # optimization now running in background

            # Loop until we get a solution or you run out of patience and press
            # Ctrl-C
            while True:
                if not T.is_alive():
                    print("Solver terminated before anything happened!")
                    break
                elif time.time() - T0 > timeout:
                    print("Solver terminated due to timeout!")
                    M.breakSolver()
                    break
        except KeyboardInterrupt:
            print("Signalling the solver that it can give up now!")
            M.breakSolver()
        finally:
            try:
                T.join() # wait for the solver to return
            except:
                pass