Solver Portfolio
A solver portfolio: N solver instances — typically of different algorithms — race on the same problem concurrently, each on its own worker with its own factory-created solver and private evaluation resources, and the portfolio reports the best solution found across all members.
The portfolio is itself a solver, following the convention the random-restart solver established: the maximum number of iterations equals the member count, and outer iteration k blocks until member k completes, no matter which member happened to finish first. Trackers, snapshots, and results therefore see a deterministic per-member sequence, and the whole orchestration/reporting stack works on a portfolio unchanged.
Reproducibility follows the concurrent-substrate rules: member starting points are fixed at launch (per task, or inherited from the portfolio's starting point), member solvers own fresh stream providers, and each member's simulation streams occupy a dedicated block of the sub-stream tape — so results do not depend on scheduling or the worker count.
Because members may estimate their bests with different statistical precision (different replication budgets, different luck), picking the winner from raw point estimates favors noise. Configure a confirmation stage via ConcurrentRunOptions.confirmation to re-evaluate the top member bests under common random numbers; the confirmed winner becomes the final current solution and the full outcome is available via confirmationOutcome.
Starting points: a member task with its own starting point keeps it. Members without one inherit the portfolio's starting point when set (racing algorithms from a common start), and otherwise generate their own.
Parameters
the problem all members solve
the portfolio's own evaluator; used for the initial-point evaluation and the optional confirmation stage (member evaluations never route through it)
the member tasks, in reporting order; labels must be unique
provisions each member's private evaluation resources
worker count, stream-block size, and optional confirmation
the replication strategy for the portfolio's own evaluations (the initial point)
the random number stream number for the portfolio driver
the stream provider for the portfolio driver
optional name identifier for this instance of the solver
Constructors
Properties
Flat representation: each member prototype's keys are re-emitted with a dotted, indexed prefix (member.0.label, member.0.solverName, ...) so the resulting map stays flat and TOML-friendly.
The outcome of the confirmation stage, when one was configured via ConcurrentRunOptions.confirmation and the run completed without a stop request; null otherwise. The confirmed winner is also reported as the final current solution. Note that the solver's best-solutions record keeps the unconfirmed member bests as well, so bestSolution may still report an unconfirmed (noise-favored) point; consult this property when a confirmation stage is in use.
The results of the members, in member order, as consumed so far. Complete after the portfolio finishes running.
The number of members in the portfolio.
Functions
A hook for subclasses to inject their specific internal state metrics into the snapshot without having to override the entire makeSolverStateSnapshot method.
Subclasses may implement this function to prepare the solver before running the first iteration. Generally, it is sufficient to just implement the startingPoint() function.
This function should contain the logic that iteratively executes until the maximum number of iterations is reached or until the stopping criteria is met. The base implementation calls nextPoint() to determine the next point to evaluate, requests an evaluation of the point, and then updates the current solution if the resulting solution is better than the current solution. Generally, implementing startingPoint() and nextPoint() should be adequate. The property iterationCounter represents the current iteration within the mainIteration() function. That is, the value of iterationCounter is incremented prior to the execution of the mainIteration() function.
Subclasses should implement this function to clean up after running all iterations. That is, after the main iteration has stopped. This may include such concepts as selecting the best once all iterations have completed.
A hook invoked when stopIterations() is called, before the solver's own iterative process is signaled to stop. The stop flag of the iterative process is only checked between outer iterations, so a composite solver that blocks inside an iteration waiting on inner solvers (possibly running on other threads) overrides this to forward the stop request to those in-flight inner solvers. The default does nothing.