Skip to content

Commit bbff431

Browse files
authored
chore: 2.0 migration docs and final API cleanup (#2178)
1 parent d4592ee commit bbff431

23 files changed

Lines changed: 2256 additions & 619 deletions

core/src/main/java/ai/timefold/solver/core/api/solver/phase/PhaseCommandContext.java

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public interface PhaseCommandContext<Solution_>
3131
/**
3232
* Returns the current working solution.
3333
* It must not be modified directly,
34-
* but only through {@link #executeAndCalculateScore(Move)} or {@link #executeTemporarily(Move, Function)}.
34+
* but only through {@link #execute(Move)} and other similar methods on this interface.
3535
* Direct modifications will cause the solver to be in an inconsistent state and likely throw an exception later on.
3636
*
3737
* @return the current working solution
@@ -65,30 +65,41 @@ public interface PhaseCommandContext<Solution_>
6565
*/
6666
<Score_ extends Score<Score_>> Score_ executeAndCalculateScore(Move<Solution_> move);
6767

68-
/**
69-
* As defined by {@link #executeTemporarily(Move, Function, boolean)},
70-
* with the guarantee of a fresh score.
71-
*/
72-
default <Result_> @Nullable Result_ executeTemporarily(Move<Solution_> move,
73-
Function<Solution_, @Nullable Result_> temporarySolutionConsumer) {
74-
return executeTemporarily(move, temporarySolutionConsumer, true);
75-
}
76-
7768
/**
7869
* Executes the given move temporarily and returns the result of the given consumer.
7970
* The working solution is reverted to its original state after the consumer has been executed,
80-
* optionally without recalculating the score for performance reasons.
71+
* except for the score, which is not recalculated for performance reasons.
8172
*
8273
* @param move the move to execute temporarily
8374
* @param temporarySolutionConsumer the consumer to execute with the temporarily modified solution;
8475
* this solution must not be modified any further.
85-
* @param guaranteeFreshScore if true, the score of {@link #getWorkingSolution()} after this method returns
86-
* is guaranteed to be up-to-date;
87-
* otherwise it may be stale as the solver will skip recalculating it for performance reasons.
8876
* @return the result of the consumer
8977
*/
9078
<Result_> @Nullable Result_ executeTemporarily(Move<Solution_> move,
91-
Function<Solution_, @Nullable Result_> temporarySolutionConsumer, boolean guaranteeFreshScore);
79+
Function<Solution_, @Nullable Result_> temporarySolutionConsumer);
80+
81+
/**
82+
* Executes the given move temporarily and returns the score of the temporarily modified solution.
83+
* The working solution is reverted to its original state after the consumer has been executed,
84+
* except for the score, which is not recalculated for performance reasons.
85+
*
86+
* @param move the move to execute temporarily
87+
* @return the score of the temporarily modified solution after executing the move
88+
*/
89+
<Score_ extends Score<Score_>> Score_ executeTemporarily(Move<Solution_> move);
90+
91+
/**
92+
* As defined by {@link #executeTemporarily(Move)},
93+
* with the guarantee of a fresh score at the end of the method's invocation.
94+
*/
95+
<Score_ extends Score<Score_>> Score_ executeTemporarilyAndCalculateScore(Move<Solution_> move);
96+
97+
/**
98+
* As defined by {@link #executeTemporarily(Move, Function)},
99+
* with the guarantee of a fresh score at the end of the method's invocation.
100+
*/
101+
<Result_> @Nullable Result_ executeTemporarilyAndCalculateScore(Move<Solution_> move,
102+
Function<Solution_, @Nullable Result_> temporarySolutionConsumer);
92103

93104
@Override
94105
<T> @Nullable T lookUpWorkingObject(@Nullable T problemFactOrPlanningEntity);

core/src/main/java/ai/timefold/solver/core/impl/move/MoveDirector.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -332,17 +332,18 @@ public final InnerScore<Score_> executeTemporary(Move<Solution_> move) {
332332
return score;
333333
}
334334

335-
public <Result_> Result_ executeTemporary(Move<Solution_> move,
336-
TemporaryMovePostprocessor<Solution_, Score_, Result_> postprocessor) {
335+
public @Nullable <Result_> Result_ executeTemporary(Move<Solution_> move,
336+
TemporaryMovePostprocessor<Solution_, Score_, @Nullable Result_> postprocessor) {
337337
try (var ephemeralMoveDirector = ephemeral()) {
338338
ephemeralMoveDirector.execute(move);
339339
var score = backingScoreDirector.calculateScore();
340340
return postprocessor.apply(score, ephemeralMoveDirector.createUndoMove());
341341
}
342342
}
343343

344-
public <Result_> @Nullable Result_ executeTemporary(Move<Solution_> move,
345-
Function<Solution_, @Nullable Result_> postprocessor, boolean guaranteeFreshScore) {
344+
public @Nullable <Result_> Result_ executeTemporary(Move<Solution_> move,
345+
Function<Solution_, @Nullable Result_> postprocessor,
346+
boolean guaranteeFreshScore) {
346347
var ephemeralMoveDirector = ephemeral();
347348
ephemeralMoveDirector.execute(move, true);
348349
var result = postprocessor.apply(backingScoreDirector.getWorkingSolution());
@@ -451,7 +452,7 @@ public final VariableDescriptorAwareScoreDirector<Solution_> getScoreDirector()
451452
*/
452453
@FunctionalInterface
453454
public interface TemporaryMovePostprocessor<Solution_, Score_ extends Score<Score_>, Result_>
454-
extends BiFunction<InnerScore<Score_>, Move<Solution_>, Result_> {
455+
extends BiFunction<InnerScore<Score_>, Move<Solution_>, @Nullable Result_> {
455456

456457
}
457458

core/src/main/java/ai/timefold/solver/core/impl/phase/custom/DefaultPhaseCommandContext.java

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,30 @@ public <Score_ extends Score<Score_>> Score_ executeAndCalculateScore(Move<Solut
5757

5858
@Override
5959
public @Nullable <Result_> Result_ executeTemporarily(Move<Solution_> move,
60-
Function<Solution_, @Nullable Result_> temporarySolutionConsumer, boolean guaranteeFreshScore) {
61-
return moveDirector.executeTemporary(move, temporarySolutionConsumer, guaranteeFreshScore);
60+
Function<Solution_, @Nullable Result_> temporarySolutionConsumer) {
61+
return moveDirector.executeTemporary(move, temporarySolutionConsumer, false);
62+
}
63+
64+
@Override
65+
public <Score_ extends Score<Score_>> Score_ executeTemporarily(Move<Solution_> move) {
66+
Score_ score = executeTemporarily(move, solution -> moveDirector.getScoreDirector()
67+
.getSolutionDescriptor()
68+
.getScore(solution));
69+
return Objects.requireNonNull(score, () -> "The move (%s) failed to calculate a score.".formatted(move));
70+
}
71+
72+
@Override
73+
public @Nullable <Result_> Result_ executeTemporarilyAndCalculateScore(Move<Solution_> move,
74+
Function<Solution_, @Nullable Result_> temporarySolutionConsumer) {
75+
return moveDirector.executeTemporary(move, temporarySolutionConsumer, true);
76+
}
77+
78+
@Override
79+
public <Score_ extends Score<Score_>> Score_ executeTemporarilyAndCalculateScore(Move<Solution_> move) {
80+
Score_ score = executeTemporarilyAndCalculateScore(move, solution -> moveDirector.getScoreDirector()
81+
.getSolutionDescriptor()
82+
.getScore(solution));
83+
return Objects.requireNonNull(score, () -> "The move (%s) failed to calculate a score.".formatted(move));
6284
}
6385

6486
}

docs/TODO.md

Lines changed: 0 additions & 47 deletions
This file was deleted.
-29.6 KB
Loading

0 commit comments

Comments
 (0)