Skip to content

Commit e7fae26

Browse files
authored
fix: only include tail chain move when using a single var (#936)
1 parent d5ed7e1 commit e7fae26

File tree

3 files changed

+35
-1
lines changed

3 files changed

+35
-1
lines changed

core/src/main/java/ai/timefold/solver/core/impl/localsearch/DefaultLocalSearchPhaseFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ private UnionMoveSelectorConfig determineDefaultMoveSelectorConfig(HeuristicConf
219219
.withMoveSelectors(new ListChangeMoveSelectorConfig(), new ListSwapMoveSelectorConfig(),
220220
new KOptListMoveSelectorConfig());
221221
} else if (listVariableDescriptor == null) { // We only have basic variables.
222-
if (hasChainedVariable) {
222+
if (hasChainedVariable && basicVariableDescriptorList.size() == 1) {
223223
return new UnionMoveSelectorConfig()
224224
.withMoveSelectors(new ChangeMoveSelectorConfig(), new SwapMoveSelectorConfig(),
225225
new TailChainSwapMoveSelectorConfig());

core/src/test/java/ai/timefold/solver/core/impl/localsearch/DefaultLocalSearchPhaseTest.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
import ai.timefold.solver.core.impl.testdata.domain.TestdataEntity;
1515
import ai.timefold.solver.core.impl.testdata.domain.TestdataSolution;
1616
import ai.timefold.solver.core.impl.testdata.domain.TestdataValue;
17+
import ai.timefold.solver.core.impl.testdata.domain.chained.TestdataChainedEntity;
18+
import ai.timefold.solver.core.impl.testdata.domain.chained.TestdataChainedSolution;
1719
import ai.timefold.solver.core.impl.testdata.domain.list.TestdataListEntity;
1820
import ai.timefold.solver.core.impl.testdata.domain.list.TestdataListSolution;
1921
import ai.timefold.solver.core.impl.testdata.domain.list.TestdataListValue;
@@ -244,6 +246,16 @@ void solveListVariable() {
244246
assertThat(solution).isNotNull();
245247
}
246248

249+
@Test
250+
void solveMultiVarChainedVariable() {
251+
var solverConfig = PlannerTestUtils.buildSolverConfig(TestdataChainedSolution.class, TestdataChainedEntity.class);
252+
253+
var solution = TestdataChainedSolution.generateUninitializedSolution(6, 2);
254+
255+
solution = PlannerTestUtils.solve(solverConfig, solution);
256+
assertThat(solution).isNotNull();
257+
}
258+
247259
@Test
248260
void solveListVariableWithExternalizedInverseAndIndexSupplies() {
249261
var solverConfig = PlannerTestUtils.buildSolverConfig(

core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/chained/TestdataChainedSolution.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package ai.timefold.solver.core.impl.testdata.domain.chained;
22

33
import java.util.List;
4+
import java.util.stream.IntStream;
45

56
import ai.timefold.solver.core.api.domain.solution.PlanningEntityCollectionProperty;
67
import ai.timefold.solver.core.api.domain.solution.PlanningScore;
@@ -74,4 +75,25 @@ public void setScore(SimpleScore score) {
7475
// Complex methods
7576
// ************************************************************************
7677

78+
public static TestdataChainedSolution generateUninitializedSolution(int valueCount, int entityCount) {
79+
return generateSolution(valueCount, entityCount);
80+
}
81+
82+
private static TestdataChainedSolution generateSolution(int valueCount, int entityCount) {
83+
List<TestdataChainedEntity> entityList = IntStream.range(0, entityCount)
84+
.mapToObj(i -> new TestdataChainedEntity("Generated Entity " + i))
85+
.toList();
86+
List<TestdataChainedAnchor> anchorList = IntStream.range(0, entityCount)
87+
.mapToObj(i -> new TestdataChainedAnchor("Generated Anchor " + i))
88+
.toList();
89+
List<TestdataValue> valueList = IntStream.range(0, valueCount)
90+
.mapToObj(i -> new TestdataValue("Generated Value " + i))
91+
.toList();
92+
TestdataChainedSolution solution = new TestdataChainedSolution();
93+
solution.setChainedEntityList(entityList);
94+
solution.setChainedAnchorList(anchorList);
95+
solution.setUnchainedValueList(valueList);
96+
return solution;
97+
}
98+
7799
}

0 commit comments

Comments
 (0)