isStoppingCriteriaSatisfied

protected open override fun isStoppingCriteriaSatisfied(): Boolean(source)

Stops when the orchestration has finished, or when an externally supplied solutionQualityEvaluator says to.

The phases are checked FIRST and the criterion is an additional reason to stop, not a replacement for them. Every other solver reads the criterion in place of its own convergence test (criterion?.isStoppingCriteriaReached(this) ?: ownTest()); doing that here would mean that supplying a criterion stopped ISC from ever noticing it had reached Phase.DONE, and it would keep iterating over a phase that does nothing until the iteration cap expired.

The budget is honoured between macro-steps, not within them. One mainIteration is a whole phase step — the entire niching-GA global phase, or one seed's entire COMPASS local search — so a budget exhausted partway through a phase is noticed only when that phase returns. Adherence is therefore "budget plus at most one phase step", not exact. That is a large improvement on ignoring the budget altogether, which is what this solver did before: measured at budgets of 500, 2,000 and 10,000 it consumed 5,100 replications every time. It is not yet equal-budget parity with the solvers that stop within an iteration, and the complementary problem — that ISC may also UNDER-spend a large budget, since nothing makes it use one — is a question about the algorithm's configuration rather than about this test.

One phase step can be many times the budget. With deltaC > 0 and responses noisy relative to it, a single local search or clean-up runs to completion before the budget is checked. On a one-dimensional bimodal problem with variance 100 and deltaC = 0.25, a run consumed 40,975 replications at budgets of 1,000, 10,000 and 100,000 alike: 41 times over the smallest. An equal-budget comparison that includes ISC is therefore not equal unless the phase caps (globalBudget, maxLocalPhaseReplications, maxCleanUpReplicationsPerSystem) are set to fit it, and in a concurrent benchmark the overrun can also run past the member's sub-stream block, which the benchmark records per cell.