Skip to content

Commit 5c951a8

Browse files
committed
chore: set mixed models as a preview feature
1 parent ae7d07c commit 5c951a8

File tree

5 files changed

+24
-10
lines changed

5 files changed

+24
-10
lines changed

core/src/main/java/ai/timefold/solver/core/config/solver/PreviewFeature.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ public enum PreviewFeature {
2222
DECLARATIVE_SHADOW_VARIABLES,
2323
DIVERSIFIED_LATE_ACCEPTANCE,
2424
PLANNING_SOLUTION_DIFF,
25+
MIXED_MODELS,
2526
/**
2627
* Unlike other preview features, Move Streams are an active research project.
2728
* It is intended to simplify the creation of custom moves, eventually replacing move selectors.

core/src/main/java/ai/timefold/solver/core/impl/heuristic/HeuristicConfigPolicy.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828

2929
public class HeuristicConfigPolicy<Solution_> {
3030

31-
private final Set<PreviewFeature> previewFeatureList;
31+
private final Set<PreviewFeature> previewFeatureSet;
3232
private final EnvironmentMode environmentMode;
3333
private final String logIndentation;
3434
private final Integer moveThreadCount;
@@ -50,7 +50,7 @@ public class HeuristicConfigPolicy<Solution_> {
5050
private final Map<String, ValueMimicRecorder<Solution_>> valueMimicRecorderMap = new HashMap<>();
5151

5252
private HeuristicConfigPolicy(Builder<Solution_> builder) {
53-
this.previewFeatureList = builder.previewFeatureList;
53+
this.previewFeatureSet = builder.previewFeatureSet;
5454
this.environmentMode = builder.environmentMode;
5555
this.logIndentation = builder.logIndentation;
5656
this.moveThreadCount = builder.moveThreadCount;
@@ -134,7 +134,7 @@ public Random getRandom() {
134134

135135
public Builder<Solution_> cloneBuilder() {
136136
return new Builder<Solution_>()
137-
.withPreviewFeatureList(previewFeatureList)
137+
.withPreviewFeatureSet(previewFeatureSet)
138138
.withEnvironmentMode(environmentMode)
139139
.withMoveThreadCount(moveThreadCount)
140140
.withMoveThreadBufferSize(moveThreadBufferSize)
@@ -229,11 +229,11 @@ public ThreadFactory buildThreadFactory(ChildThreadType childThreadType) {
229229
}
230230

231231
public void ensurePreviewFeature(PreviewFeature previewFeature) {
232-
ensurePreviewFeature(previewFeature, previewFeatureList);
232+
ensurePreviewFeature(previewFeature, previewFeatureSet);
233233
}
234234

235-
public static void ensurePreviewFeature(PreviewFeature previewFeature, Collection<PreviewFeature> previewFeatureList) {
236-
if (previewFeatureList == null || !previewFeatureList.contains(previewFeature)) {
235+
public static void ensurePreviewFeature(PreviewFeature previewFeature, Collection<PreviewFeature> previewFeatureSet) {
236+
if (previewFeatureSet == null || !previewFeatureSet.contains(previewFeature)) {
237237
throw new IllegalStateException("""
238238
The preview feature %s is not enabled.
239239
Maybe add %s to <enablePreviewFeature> in your configuration file?"""
@@ -248,7 +248,7 @@ public String toString() {
248248

249249
public static class Builder<Solution_> {
250250

251-
private Set<PreviewFeature> previewFeatureList;
251+
private Set<PreviewFeature> previewFeatureSet;
252252
private EnvironmentMode environmentMode;
253253
private Integer moveThreadCount;
254254
private Integer moveThreadBufferSize;
@@ -269,8 +269,8 @@ public static class Builder<Solution_> {
269269
private Class<? extends NearbyDistanceMeter<?, ?>> nearbyDistanceMeterClass;
270270
private Random random;
271271

272-
public Builder<Solution_> withPreviewFeatureList(Set<PreviewFeature> previewFeatureList) {
273-
this.previewFeatureList = previewFeatureList;
272+
public Builder<Solution_> withPreviewFeatureSet(Set<PreviewFeature> previewFeatureSet) {
273+
this.previewFeatureSet = previewFeatureSet;
274274
return this;
275275
}
276276

core/src/main/java/ai/timefold/solver/core/impl/solver/DefaultSolverFactory.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ public <Score_ extends Score<Score_>> ScoreDirectorFactory<Solution_, Score_> ge
131131
var previewFeaturesEnabled = solverConfig.getEnablePreviewFeatureSet();
132132

133133
var configPolicy = new HeuristicConfigPolicy.Builder<Solution_>()
134-
.withPreviewFeatureList(previewFeaturesEnabled)
134+
.withPreviewFeatureSet(previewFeaturesEnabled)
135135
.withEnvironmentMode(environmentMode)
136136
.withMoveThreadCount(moveThreadCount)
137137
.withMoveThreadBufferSize(solverConfig.getMoveThreadBufferSize())
@@ -142,6 +142,9 @@ public <Score_ extends Score<Score_>> ScoreDirectorFactory<Solution_, Score_> ge
142142
.withSolutionDescriptor(solutionDescriptor)
143143
.withClassInstanceCache(ClassInstanceCache.create())
144144
.build();
145+
if (solutionDescriptor.hasBothBasicAndListVariables()) {
146+
configPolicy.ensurePreviewFeature(PreviewFeature.MIXED_MODELS);
147+
}
145148
var basicPlumbingTermination = new BasicPlumbingTermination<Solution_>(isDaemon);
146149
var termination = buildTermination(basicPlumbingTermination, configPolicy, configOverride);
147150
var phaseList = buildPhaseList(configPolicy, bestSolutionRecaller, termination);

core/src/test/java/ai/timefold/solver/core/impl/constructionheuristic/placer/entity/QueuedMultiplePlacerFactoryTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ void testPlacersForConstructionHeuristic() {
7878

7979
placer.solvingStarted(solverScope);
8080
var phaseScope = mock(AbstractPhaseScope.class);
81+
when(phaseScope.getSolverScope()).thenReturn(solverScope);
8182
when(phaseScope.getScoreDirector()).thenReturn(scoreDirector);
8283
placer.phaseStarted(phaseScope);
8384

@@ -195,6 +196,7 @@ void testPinnedPlacersForConstructionHeuristic() {
195196

196197
placer.solvingStarted(solverScope);
197198
var phaseScope = mock(AbstractPhaseScope.class);
199+
when(phaseScope.getSolverScope()).thenReturn(solverScope);
198200
when(phaseScope.getScoreDirector()).thenReturn(scoreDirector);
199201
placer.phaseStarted(phaseScope);
200202

core/src/test/java/ai/timefold/solver/core/impl/solver/DefaultSolverTest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1643,6 +1643,7 @@ void solveMixedModel() {
16431643
var solverConfig = PlannerTestUtils.buildSolverConfig(
16441644
TestdataMixedSolution.class, TestdataMixedEntity.class, TestdataMixedValue.class,
16451645
TestdataMixedOtherValue.class)
1646+
.withPreviewFeature(PreviewFeature.MIXED_MODELS)
16461647
.withPhases(new ConstructionHeuristicPhaseConfig(),
16471648
new LocalSearchPhaseConfig().withTerminationConfig(new TerminationConfig().withStepCountLimit(16)))
16481649
.withEasyScoreCalculatorClass(TestdataMixedEasyScoreCalculator.class);
@@ -1669,6 +1670,7 @@ void solveMixedModelWithSortManner(Pair<EntitySorterManner, ValueSorterManner> s
16691670
var solverConfig = PlannerTestUtils.buildSolverConfig(
16701671
TestdataMixedSolution.class, TestdataMixedEntity.class, TestdataMixedValue.class,
16711672
TestdataMixedOtherValue.class)
1673+
.withPreviewFeature(PreviewFeature.MIXED_MODELS)
16721674
.withPhases(new ConstructionHeuristicPhaseConfig(),
16731675
new LocalSearchPhaseConfig()
16741676
.withMoveSelectorConfig(
@@ -1699,6 +1701,7 @@ void solvePinnedMixedModel() {
16991701
var solverConfig = PlannerTestUtils.buildSolverConfig(
17001702
TestdataMixedSolution.class, TestdataMixedEntity.class, TestdataMixedValue.class,
17011703
TestdataMixedOtherValue.class)
1704+
.withPreviewFeature(PreviewFeature.MIXED_MODELS)
17021705
.withPhases(new ConstructionHeuristicPhaseConfig())
17031706
.withEasyScoreCalculatorClass(TestdataMixedEasyScoreCalculator.class);
17041707

@@ -1717,6 +1720,7 @@ void solvePinnedMixedModel() {
17171720
void solveUnassignedMixedModel() {
17181721
var solverConfig = PlannerTestUtils.buildSolverConfig(
17191722
TestdataUnassignedMixedSolution.class, TestdataUnassignedMixedEntity.class)
1723+
.withPreviewFeature(PreviewFeature.MIXED_MODELS)
17201724
.withPhases(new ConstructionHeuristicPhaseConfig(),
17211725
new LocalSearchPhaseConfig().withTerminationConfig(new TerminationConfig().withStepCountLimit(16)))
17221726
.withEasyScoreCalculatorClass(TestdataUnassignedMixedEasyScoreCalculator.class);
@@ -1743,6 +1747,7 @@ void solveUnassignedMixedModel() {
17431747
void solvePinnedAndUnassignedMixedModel() {
17441748
var solverConfig = PlannerTestUtils.buildSolverConfig(
17451749
TestdataUnassignedMixedSolution.class, TestdataUnassignedMixedEntity.class)
1750+
.withPreviewFeature(PreviewFeature.MIXED_MODELS)
17461751
.withPhases(new ConstructionHeuristicPhaseConfig(),
17471752
new LocalSearchPhaseConfig().withTerminationConfig(new TerminationConfig().withStepCountLimit(16)))
17481753
.withEasyScoreCalculatorClass(TestdataUnassignedMixedEasyScoreCalculator.class);
@@ -1805,6 +1810,7 @@ void solveCustomConfigMixedModel() {
18051810
var solverConfig = PlannerTestUtils.buildSolverConfig(
18061811
TestdataMixedSolution.class, TestdataMixedEntity.class, TestdataMixedValue.class,
18071812
TestdataMixedOtherValue.class)
1813+
.withPreviewFeature(PreviewFeature.MIXED_MODELS)
18081814
.withPhases(new ConstructionHeuristicPhaseConfig()
18091815
.withEntityPlacerConfigList(valuePlacerConfig, entityPlacerConfig),
18101816
new LocalSearchPhaseConfig().withTerminationConfig(new TerminationConfig().withStepCountLimit(16)))
@@ -1866,6 +1872,7 @@ void solveMoveConfigMixedModel(MoveSelectorConfig moveSelectionConfig) {
18661872
var solverConfig = PlannerTestUtils.buildSolverConfig(
18671873
TestdataMixedSolution.class, TestdataMixedEntity.class, TestdataMixedValue.class,
18681874
TestdataMixedOtherValue.class)
1875+
.withPreviewFeature(PreviewFeature.MIXED_MODELS)
18691876
.withPhases(new ConstructionHeuristicPhaseConfig(), localSearchConfig)
18701877
.withEasyScoreCalculatorClass(TestdataMixedEasyScoreCalculator.class);
18711878

@@ -1938,6 +1945,7 @@ void solveMultiEntityMoveConfigMixedModel(MoveSelectorConfig moveSelectionConfig
19381945
var solverConfig = PlannerTestUtils.buildSolverConfig(
19391946
TestdataMixedMultiEntitySolution.class, TestdataMixedMultiEntityFirstEntity.class,
19401947
TestdataMixedMultiEntitySecondEntity.class)
1948+
.withPreviewFeature(PreviewFeature.MIXED_MODELS)
19411949
.withPhases(constructionHeuristicConfig, localSearchConfig)
19421950
.withEasyScoreCalculatorClass(TestdataMixedEntityEasyScoreCalculator.class);
19431951

0 commit comments

Comments
 (0)