Interface SolverManager<Solution_,ProblemId_>
-
- Type Parameters:
Solution_
- the solution type, the class with thePlanningSolution
annotationProblemId_
- the ID type of a submitted problem, such asLong
orUUID
.
- All Superinterfaces:
AutoCloseable
- All Known Implementing Classes:
DefaultSolverManager
public interface SolverManager<Solution_,ProblemId_> extends AutoCloseable
A SolverManager solves multiple planning problems of the same domain, asynchronously without blocking the calling thread.To create a SolverManager, use
create(SolverFactory, SolverManagerConfig)
. To solve a planning problem, callsolve(Object, Function, Consumer)
orsolveAndListen(Object, Function, Consumer)
.These methods are thread-safe unless explicitly stated otherwise.
Internally a SolverManager manages a thread pool of solver threads (which call
Solver.solve(Object)
) and consumer threads (to handle theBestSolutionChangedEvent
s).
-
-
Method Summary
All Methods Static Methods Instance Methods Abstract Methods Default Methods Modifier and Type Method Description void
addProblemChange(ProblemId_ problemId, ProblemChange<Solution_> problemChange)
Schedules aProblemChange
to be processed by the underlyingSolver
and returns immediately.void
close()
Terminates all solvers, cancels all solver jobs that haven't (re)started yet and discards all queuedProblemChange
s.static <Solution_,ProblemId_>
SolverManager<Solution_,ProblemId_>create(SolverFactory<Solution_> solverFactory)
Use aSolverFactory
to build aSolverManager
.static <Solution_,ProblemId_>
SolverManager<Solution_,ProblemId_>create(SolverFactory<Solution_> solverFactory, SolverManagerConfig solverManagerConfig)
static <Solution_,ProblemId_>
SolverManager<Solution_,ProblemId_>create(SolverConfig solverConfig)
Use aSolverConfig
to build aSolverManager
.static <Solution_,ProblemId_>
SolverManager<Solution_,ProblemId_>create(SolverConfig solverConfig, SolverManagerConfig solverManagerConfig)
SolverStatus
getSolverStatus(ProblemId_ problemId)
Returns if theSolver
is scheduled to solve, actively solving or not.default SolverJob<Solution_,ProblemId_>
solve(ProblemId_ problemId, Function<? super ProblemId_,? extends Solution_> problemFinder, Consumer<? super Solution_> finalBestSolutionConsumer)
Submits a planning problem to solve and returns immediately.SolverJob<Solution_,ProblemId_>
solve(ProblemId_ problemId, Function<? super ProblemId_,? extends Solution_> problemFinder, Consumer<? super Solution_> finalBestSolutionConsumer, BiConsumer<? super ProblemId_,? super Throwable> exceptionHandler)
As defined bysolve(Object, Function, Consumer)
.default SolverJob<Solution_,ProblemId_>
solve(ProblemId_ problemId, Solution_ problem)
Submits a planning problem to solve and returns immediately.default SolverJob<Solution_,ProblemId_>
solve(ProblemId_ problemId, Solution_ problem, Consumer<? super Solution_> finalBestSolutionConsumer)
As defined bysolve(Object, Object)
.default SolverJob<Solution_,ProblemId_>
solve(ProblemId_ problemId, Solution_ problem, Consumer<? super Solution_> finalBestSolutionConsumer, BiConsumer<? super ProblemId_,? super Throwable> exceptionHandler)
As defined bysolve(Object, Object)
.default SolverJob<Solution_,ProblemId_>
solveAndListen(ProblemId_ problemId, Function<? super ProblemId_,? extends Solution_> problemFinder, Consumer<? super Solution_> bestSolutionConsumer)
Submits a planning problem to solve and returns immediately.default SolverJob<Solution_,ProblemId_>
solveAndListen(ProblemId_ problemId, Function<? super ProblemId_,? extends Solution_> problemFinder, Consumer<? super Solution_> bestSolutionConsumer, BiConsumer<? super ProblemId_,? super Throwable> exceptionHandler)
As defined bysolveAndListen(Object, Function, Consumer)
.SolverJob<Solution_,ProblemId_>
solveAndListen(ProblemId_ problemId, Function<? super ProblemId_,? extends Solution_> problemFinder, Consumer<? super Solution_> bestSolutionConsumer, Consumer<? super Solution_> finalBestSolutionConsumer, BiConsumer<? super ProblemId_,? super Throwable> exceptionHandler)
As defined bysolveAndListen(Object, Function, Consumer)
.void
terminateEarly(ProblemId_ problemId)
Terminates the solver or cancels the solver job if it hasn't (re)started yet.
-
-
-
Method Detail
-
create
static <Solution_,ProblemId_> SolverManager<Solution_,ProblemId_> create(SolverConfig solverConfig)
Use aSolverConfig
to build aSolverManager
.When using
ScoreManager
too, usecreate(SolverFactory)
instead so they reuse the sameSolverFactory
instance.- Type Parameters:
Solution_
- the solution type, the class with thePlanningSolution
annotationProblemId_
- the ID type of a submitted problem, such asLong
orUUID
- Parameters:
solverConfig
- never null- Returns:
- never null
-
create
static <Solution_,ProblemId_> SolverManager<Solution_,ProblemId_> create(SolverConfig solverConfig, SolverManagerConfig solverManagerConfig)
Use aSolverConfig
and aSolverManagerConfig
to build aSolverManager
.When using
ScoreManager
too, usecreate(SolverFactory, SolverManagerConfig)
instead so they reuse the sameSolverFactory
instance.- Type Parameters:
Solution_
- the solution type, the class with thePlanningSolution
annotationProblemId_
- the ID type of a submitted problem, such asLong
orUUID
.- Parameters:
solverConfig
- never nullsolverManagerConfig
- never null- Returns:
- never null
-
create
static <Solution_,ProblemId_> SolverManager<Solution_,ProblemId_> create(SolverFactory<Solution_> solverFactory)
Use aSolverFactory
to build aSolverManager
.- Type Parameters:
Solution_
- the solution type, the class with thePlanningSolution
annotationProblemId_
- the ID type of a submitted problem, such asLong
orUUID
- Parameters:
solverFactory
- never null- Returns:
- never null
-
create
static <Solution_,ProblemId_> SolverManager<Solution_,ProblemId_> create(SolverFactory<Solution_> solverFactory, SolverManagerConfig solverManagerConfig)
- Type Parameters:
Solution_
- the solution type, the class with thePlanningSolution
annotationProblemId_
- the ID type of a submitted problem, such asLong
orUUID
.- Parameters:
solverFactory
- never nullsolverManagerConfig
- never null- Returns:
- never null
-
solve
default SolverJob<Solution_,ProblemId_> solve(ProblemId_ problemId, Solution_ problem)
Submits a planning problem to solve and returns immediately. The planning problem is solved on a solverThread
, as soon as one is available. To retrieve the final best solution, useSolverJob.getFinalBestSolution()
.In server applications, it's recommended to use
solve(Object, Function, Consumer)
instead, to avoid loading the problem going stale if solving can't start immediately. To listen to intermediate best solutions too, usesolveAndListen(Object, Function, Consumer)
instead.Defaults to logging exceptions as an error.
To stop a solver job before it naturally terminates, call
SolverJob.terminateEarly()
.- Parameters:
problemId
- never null, a ID for each planning problem. This must be unique. Use this problemId toterminate
the solver early,problem
- never null, aPlanningSolution
usually with uninitialized planning variables- Returns:
- never null
-
solve
default SolverJob<Solution_,ProblemId_> solve(ProblemId_ problemId, Solution_ problem, Consumer<? super Solution_> finalBestSolutionConsumer)
As defined bysolve(Object, Object)
.- Parameters:
problemId
- never null, a ID for each planning problem. This must be unique. Use this problemId toterminate
the solver early,to get the status
or if the problem changes while solving.problem
- never null, aPlanningSolution
usually with uninitialized planning variablesfinalBestSolutionConsumer
- sometimes null, called only once, at the end, on a consumer thread- Returns:
- never null
-
solve
default SolverJob<Solution_,ProblemId_> solve(ProblemId_ problemId, Solution_ problem, Consumer<? super Solution_> finalBestSolutionConsumer, BiConsumer<? super ProblemId_,? super Throwable> exceptionHandler)
As defined bysolve(Object, Object)
.- Parameters:
problemId
- never null, a ID for each planning problem. This must be unique. Use this problemId toterminate
the solver early,to get the status
or if the problem changes while solving.problem
- never null, aPlanningSolution
usually with uninitialized planning variablesfinalBestSolutionConsumer
- sometimes null, called only once, at the end, on a consumer threadexceptionHandler
- sometimes null, called if an exception or error occurs. If null it defaults to logging the exception as an error.- Returns:
- never null
-
solve
default SolverJob<Solution_,ProblemId_> solve(ProblemId_ problemId, Function<? super ProblemId_,? extends Solution_> problemFinder, Consumer<? super Solution_> finalBestSolutionConsumer)
Submits a planning problem to solve and returns immediately. The planning problem is solved on a solverThread
, as soon as one is available.When the solver terminates, the
finalBestSolutionConsumer
is called once with the final best solution, on a consumerThread
, as soon as one is available. To listen to intermediate best solutions too, usesolveAndListen(Object, Function, Consumer)
instead.Defaults to logging exceptions as an error.
To stop a solver job before it naturally terminates, call
terminateEarly(Object)
.- Parameters:
problemId
- never null, a ID for each planning problem. This must be unique. Use this problemId toterminate
the solver early,to get the status
or if the problem changes while solving.problemFinder
- never null, a function that returns aPlanningSolution
, usually with uninitialized planning variablesfinalBestSolutionConsumer
- sometimes null, called only once, at the end, on a consumer thread- Returns:
- never null
-
solve
SolverJob<Solution_,ProblemId_> solve(ProblemId_ problemId, Function<? super ProblemId_,? extends Solution_> problemFinder, Consumer<? super Solution_> finalBestSolutionConsumer, BiConsumer<? super ProblemId_,? super Throwable> exceptionHandler)
As defined bysolve(Object, Function, Consumer)
.- Parameters:
problemId
- never null, a ID for each planning problem. This must be unique. Use this problemId toterminate
the solver early,to get the status
or if the problem changes while solving.problemFinder
- never null, function that returns aPlanningSolution
, usually with uninitialized planning variablesfinalBestSolutionConsumer
- sometimes null, called only once, at the end, on a consumer threadexceptionHandler
- sometimes null, called if an exception or error occurs. If null it defaults to logging the exception as an error.- Returns:
- never null
-
solveAndListen
default SolverJob<Solution_,ProblemId_> solveAndListen(ProblemId_ problemId, Function<? super ProblemId_,? extends Solution_> problemFinder, Consumer<? super Solution_> bestSolutionConsumer)
Submits a planning problem to solve and returns immediately. The planning problem is solved on a solverThread
, as soon as one is available.When the solver finds a new best solution, the
bestSolutionConsumer
is called every time, on a consumerThread
, as soon as one is available (taking into account any throttling waiting time), unless a newer best solution is already available by then (in which case skip ahead discards it).Defaults to logging exceptions as an error.
To stop a solver job before it naturally terminates, call
terminateEarly(Object)
.- Parameters:
problemId
- never null, a ID for each planning problem. This must be unique. Use this problemId toterminate
the solver early,to get the status
or if the problem changes while solving.problemFinder
- never null, a function that returns aPlanningSolution
, usually with uninitialized planning variablesbestSolutionConsumer
- never null, called multiple times, on a consumer thread- Returns:
- never null
-
solveAndListen
default SolverJob<Solution_,ProblemId_> solveAndListen(ProblemId_ problemId, Function<? super ProblemId_,? extends Solution_> problemFinder, Consumer<? super Solution_> bestSolutionConsumer, BiConsumer<? super ProblemId_,? super Throwable> exceptionHandler)
As defined bysolveAndListen(Object, Function, Consumer)
.- Parameters:
problemId
- never null, a ID for each planning problem. This must be unique. Use this problemId toterminate
the solver early,to get the status
or if the problem changes while solving.problemFinder
- never null, function that returns aPlanningSolution
, usually with uninitialized planning variablesbestSolutionConsumer
- never null, called multiple times, on a consumer threadexceptionHandler
- sometimes null, called if an exception or error occurs. If null it defaults to logging the exception as an error.- Returns:
- never null
-
solveAndListen
SolverJob<Solution_,ProblemId_> solveAndListen(ProblemId_ problemId, Function<? super ProblemId_,? extends Solution_> problemFinder, Consumer<? super Solution_> bestSolutionConsumer, Consumer<? super Solution_> finalBestSolutionConsumer, BiConsumer<? super ProblemId_,? super Throwable> exceptionHandler)
As defined bysolveAndListen(Object, Function, Consumer)
.The final best solution is delivered twice: first to the
bestSolutionConsumer
when it is found and then again to thefinalBestSolutionConsumer
when the solver terminates. Do not store the solution twice. This allows for use cases that only process theScore
first (during best solution changed events) and then store the solution upon termination.- Parameters:
problemId
- never null, an ID for each planning problem. This must be unique. Use this problemId toterminate
the solver early,to get the status
or if the problem changes while solving.problemFinder
- never null, function that returns aPlanningSolution
, usually with uninitialized planning variablesbestSolutionConsumer
- never null, called multiple times, on a consumer threadfinalBestSolutionConsumer
- sometimes null, called only once, at the end, on a consumer thread. That final best solution is already consumed by the bestSolutionConsumer earlier.exceptionHandler
- sometimes null, called if an exception or error occurs. If null it defaults to logging the exception as an error.- Returns:
- never null
-
getSolverStatus
SolverStatus getSolverStatus(ProblemId_ problemId)
Returns if theSolver
is scheduled to solve, actively solving or not.Returns
SolverStatus.NOT_SOLVING
if the solver already terminated or if the problemId was never added. To distinguish between both cases, useSolverJob.getSolverStatus()
instead. Here, that distinction is not supported because it would cause a memory leak.- Parameters:
problemId
- never null, a value given tosolve(Object, Function, Consumer)
orsolveAndListen(Object, Function, Consumer)
- Returns:
- never null
-
addProblemChange
void addProblemChange(ProblemId_ problemId, ProblemChange<Solution_> problemChange)
Schedules aProblemChange
to be processed by the underlyingSolver
and returns immediately. If the solver already terminated or the problemId was never added, throws an exception. The same applies if the underlyingSolver
is not in theSolverStatus.SOLVING_ACTIVE
state.- Parameters:
problemId
- never null, a value given tosolve(Object, Function, Consumer)
orsolveAndListen(Object, Function, Consumer)
problemChange
- never null- Throws:
IllegalStateException
- if there is no solver actively solving the problem associated with the problemId
-
terminateEarly
void terminateEarly(ProblemId_ problemId)
Terminates the solver or cancels the solver job if it hasn't (re)started yet.Does nothing if the solver already terminated or the problemId was never added. To distinguish between both cases, use
SolverJob.terminateEarly()
instead. Here, that distinction is not supported because it would cause a memory leak.Waits for the termination or cancellation to complete before returning. During termination, a
bestSolutionConsumer
could still be called (on a consumer thread), before this method returns.- Parameters:
problemId
- never null, a value given tosolve(Object, Function, Consumer)
orsolveAndListen(Object, Function, Consumer)
-
close
void close()
Terminates all solvers, cancels all solver jobs that haven't (re)started yet and discards all queuedProblemChange
s. Releases all thread pool resources.No new planning problems can be submitted after calling this method.
- Specified by:
close
in interfaceAutoCloseable
-
-