Skip to content

Exit Codes

Every optimization reports why it ended. The reason is an ExitCode, carried on the result the optimization returns:

from ropt import optimize

result = optimize(config, x0, objective)
print(result.exit_code.message)

Each code carries a short description in message, which is what to print or log when reporting it. Use name where the identifier itself is wanted, and compare against the member to branch on it. Note that str() and an f-string give the integer value, as they do for any IntEnum:

code = result.exit_code
code.message  # 'Maximum number of function evaluations reached'
code.name     # 'MAX_FUNCTIONS_REACHED'
str(code)     # '2'

An optimization either stops or is aborted. It stops when a condition on the optimization is met — the optimizer converged, a budget ran out, a result callback returned True — so it ends at a point that satisfied a stated criterion, and returns its result with the code. It is aborted when something ends it regardless of its state, and it then raises AbortedError, whose exit_code attribute holds the code:

from ropt import AbortedError

try:
    result = optimize(config, x0, objective, pool=pool)
except AbortedError as error:
    print(error.exit_code.message)
Exit code Meaning
FINISHED The optimizer ended the optimization, by converging or on a limit of its own such as max_iterations.
MAX_FUNCTIONS_REACHED The configured maximum number of function evaluations was reached.
MAX_BATCHES_REACHED The configured maximum number of evaluation batches was reached.
STOPPED A result callback returned True, ending the optimization at the next evaluation boundary.
TOO_FEW_REALIZATIONS Too few realizations were evaluated successfully to form an aggregate.
ABORTED The call was aborted from outside, as closing a session, or a KeyboardInterrupt, does to a call still under way.
ABORTED_ON_ERROR A failure of the call that started this work aborted it.
USER_ABORT Session.abort aborted the call.
EXECUTOR_SHUT_DOWN The pool the call was evaluating on could no longer run the work, which in practice means the interpreter was shutting down under it.
UNKNOWN The zero value of the enumeration. No call reports it.

The first five are stops, returned on the result, and the next four are aborts, raised with AbortedError; UNKNOWN is neither. TOO_FEW_REALIZATIONS ends an optimization at an evaluation boundary like the other stops, but unlike them it follows from a failure: one failed realization is enough to trigger it unless realization_min_success is lowered.

What each kind of call reports

An optimization returns any of the stop codes above, and raises with any of the abort codes.

An evaluation is a single batch with no optimizer loop around it, so it has no criterion to stop on and its result carries no exit code. It is all or nothing: either every vector was evaluated and the evaluation returns them, or it was aborted and raises AbortedError. An abort that arrives once the batch has finished leaves it unaffected.

A run call returns whatever its callables return, and raises AbortedError when it is aborted before all of them have finished.

An exit code is not a result

The two are independent. results is None when no feasible result was ever recorded, whatever the code the optimization ended with, and an optimization that stops early still returns the best result it had reached before that. An optimization can therefore report FINISHED and still have nothing on results, because only a result satisfying every constraint to within constraint_tolerance can be returned as the best one — 1e-10 unless you pass another, and it applies to the bounds and the linear constraints as well as the nonlinear ones. See When something goes wrong.