-
Notifications
You must be signed in to change notification settings - Fork 100
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Overriding Solver termination configuration (#542)
This pull request introduces a new feature that enables users to override solver termination settings without recreating the `SolverFactory` or `SolverManager`. The `SolverManager` now has a builder API for job configuration and execution. Additionally, `SolverFactory` can build a solver and override the termination config settings. Review done in #515
- Loading branch information
Showing
20 changed files
with
982 additions
and
89 deletions.
There are no files selected for viewing
32 changes: 32 additions & 0 deletions
32
core/core-impl/src/main/java/ai/timefold/solver/core/api/solver/SolverConfigOverride.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package ai.timefold.solver.core.api.solver; | ||
|
||
import java.util.Objects; | ||
|
||
import ai.timefold.solver.core.api.domain.solution.PlanningSolution; | ||
import ai.timefold.solver.core.config.solver.termination.TerminationConfig; | ||
|
||
/** | ||
* Includes settings to override default {@link ai.timefold.solver.core.api.solver.Solver} configuration. | ||
* | ||
* @param <Solution_> the solution type, the class with the {@link PlanningSolution} annotation | ||
*/ | ||
public final class SolverConfigOverride<Solution_> { | ||
|
||
private TerminationConfig terminationConfig = null; | ||
|
||
public TerminationConfig getTerminationConfig() { | ||
return terminationConfig; | ||
} | ||
|
||
/** | ||
* Sets the solver {@link TerminationConfig}. | ||
* | ||
* @param terminationConfig allows overriding the default termination config of {@link Solver} | ||
* @return this, never null | ||
*/ | ||
public SolverConfigOverride<Solution_> withTerminationConfig(TerminationConfig terminationConfig) { | ||
this.terminationConfig = | ||
Objects.requireNonNull(terminationConfig, "Invalid terminationConfig (null) given to SolverConfigOverride."); | ||
return this; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
98 changes: 98 additions & 0 deletions
98
core/core-impl/src/main/java/ai/timefold/solver/core/api/solver/SolverJobBuilder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
package ai.timefold.solver.core.api.solver; | ||
|
||
import java.util.UUID; | ||
import java.util.function.BiConsumer; | ||
import java.util.function.Consumer; | ||
import java.util.function.Function; | ||
|
||
import ai.timefold.solver.core.api.domain.solution.PlanningSolution; | ||
|
||
/** | ||
* Provides a fluent contract that allows customization and submission of planning problems to solve. | ||
* <p> | ||
* A {@link SolverManager} can solve multiple planning problems and can be used across different threads. | ||
* <p> | ||
* Hence, it is possible to have multiple distinct build configurations that are scheduled to run by the {@link SolverManager} | ||
* instance. | ||
* <p> | ||
* To solve a planning problem, set the problem configuration: {@link #withProblemId(Object)}, | ||
* {@link #withProblemFinder(Function)} and {@link #withProblem(Object)}. | ||
* <p> | ||
* Then solve it by calling {@link #run()}. | ||
* | ||
* @param <Solution_> the solution type, the class with the {@link PlanningSolution} annotation | ||
* @param <ProblemId_> the ID type of submitted problem, such as {@link Long} or {@link UUID}. | ||
*/ | ||
public interface SolverJobBuilder<Solution_, ProblemId_> { | ||
|
||
/** | ||
* Sets the problem id. | ||
* | ||
* @param problemId never null, a ID for each planning problem. This must be unique. | ||
* @return this, never null | ||
*/ | ||
SolverJobBuilder<Solution_, ProblemId_> withProblemId(ProblemId_ problemId); | ||
|
||
/** | ||
* Sets the problem definition. | ||
* | ||
* @param problem never null, a {@link PlanningSolution} usually with uninitialized planning variables | ||
* @return this, never null | ||
*/ | ||
default SolverJobBuilder<Solution_, ProblemId_> withProblem(Solution_ problem) { | ||
return withProblemFinder(id -> problem); | ||
} | ||
|
||
/** | ||
* Sets the mapping function to the problem definition. | ||
* | ||
* @param problemFinder never null, a function that returns a {@link PlanningSolution}, usually with uninitialized | ||
* planning variables | ||
* @return this, never null | ||
*/ | ||
SolverJobBuilder<Solution_, ProblemId_> withProblemFinder(Function<? super ProblemId_, ? extends Solution_> problemFinder); | ||
|
||
/** | ||
* Sets the best solution consumer, which may be called multiple times during the solving process. | ||
* | ||
* @param bestSolutionConsumer never null, called multiple times for each new best solution on a consumer thread | ||
* @return this, never null | ||
*/ | ||
SolverJobBuilder<Solution_, ProblemId_> withBestSolutionConsumer(Consumer<? super Solution_> bestSolutionConsumer); | ||
|
||
/** | ||
* Sets the final best solution consumer, which is called at the end of the solving process and returns the final | ||
* best solution. | ||
* | ||
* @param finalBestSolutionConsumer never null, called only once at the end of the solving process on a consumer thread | ||
* @return this, never null | ||
*/ | ||
SolverJobBuilder<Solution_, ProblemId_> | ||
withFinalBestSolutionConsumer(Consumer<? super Solution_> finalBestSolutionConsumer); | ||
|
||
/** | ||
* Sets the custom exception handler. | ||
* | ||
* @param exceptionHandler never null, called if an exception or error occurs. If null it defaults to logging the | ||
* exception as an error. | ||
* @return this, never null | ||
*/ | ||
SolverJobBuilder<Solution_, ProblemId_> | ||
withExceptionHandler(BiConsumer<? super ProblemId_, ? super Throwable> exceptionHandler); | ||
|
||
/** | ||
* Sets the solver config override. | ||
* | ||
* @param solverConfigOverride never null, allows overriding the default behavior of {@link Solver} | ||
* @return this, never null | ||
*/ | ||
SolverJobBuilder<Solution_, ProblemId_> withConfigOverride(SolverConfigOverride<Solution_> solverConfigOverride); | ||
|
||
/** | ||
* Submits a planning problem to solve and returns immediately. The planning problem is solved on a solver {@link Thread}, | ||
* as soon as one is available. | ||
* | ||
* @return never null | ||
*/ | ||
SolverJob<Solution_, ProblemId_> run(); | ||
} |
Oops, something went wrong.