Skip to content

Commit 934bf94

Browse files
committed
chore: simplify the selection sorting contract
1 parent 9eb30e8 commit 934bf94

File tree

11 files changed

+29
-20
lines changed

11 files changed

+29
-20
lines changed

core/src/main/java/ai/timefold/solver/core/impl/heuristic/selector/common/decorator/ComparatorFactorySelectionSorter.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
import ai.timefold.solver.core.api.domain.common.ComparatorFactory;
99
import ai.timefold.solver.core.api.domain.solution.PlanningSolution;
10-
import ai.timefold.solver.core.api.score.director.ScoreDirector;
1110
import ai.timefold.solver.core.config.heuristic.selector.common.decorator.SelectionSorterOrder;
1211

1312
/**
@@ -35,9 +34,8 @@ private Comparator<T> getAppliedComparator(Comparator<T> comparator) {
3534
}
3635

3736
@Override
38-
public void sort(ScoreDirector<Solution_> scoreDirector, List<T> selectionList) {
39-
var appliedComparator =
40-
getAppliedComparator(selectionComparatorFactory.createComparator(scoreDirector.getWorkingSolution()));
37+
public void sort(Solution_ solution, List<T> selectionList) {
38+
var appliedComparator = getAppliedComparator(selectionComparatorFactory.createComparator(solution));
4139
selectionList.sort(appliedComparator);
4240
}
4341

core/src/main/java/ai/timefold/solver/core/impl/heuristic/selector/common/decorator/ComparatorSelectionSorter.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import java.util.Objects;
77

88
import ai.timefold.solver.core.api.domain.solution.PlanningSolution;
9-
import ai.timefold.solver.core.api.score.director.ScoreDirector;
109
import ai.timefold.solver.core.config.heuristic.selector.common.decorator.SelectionSorterOrder;
1110

1211
/**
@@ -34,7 +33,7 @@ public ComparatorSelectionSorter(Comparator<T> comparator, SelectionSorterOrder
3433
}
3534

3635
@Override
37-
public void sort(ScoreDirector<Solution_> scoreDirector, List<T> selectionList) {
36+
public void sort(Solution_ solution, List<T> selectionList) {
3837
selectionList.sort(appliedComparator);
3938
}
4039

core/src/main/java/ai/timefold/solver/core/impl/heuristic/selector/common/decorator/SelectionSorter.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@
44

55
import ai.timefold.solver.core.api.domain.entity.PlanningEntity;
66
import ai.timefold.solver.core.api.domain.solution.PlanningSolution;
7-
import ai.timefold.solver.core.api.score.director.ScoreDirector;
87
import ai.timefold.solver.core.impl.heuristic.move.Move;
98
import ai.timefold.solver.core.impl.heuristic.selector.Selector;
109

10+
import org.jspecify.annotations.NullMarked;
11+
1112
/**
1213
* Decides the order of a {@link List} of selection
1314
* (which is a {@link PlanningEntity}, a planningValue, a {@link Move} or a {@link Selector}).
@@ -19,15 +20,15 @@
1920
* @param <Solution_> the solution type, the class with the {@link PlanningSolution} annotation
2021
* @param <T> the selection type
2122
*/
23+
@NullMarked
2224
@FunctionalInterface
2325
public interface SelectionSorter<Solution_, T> {
2426

2527
/**
26-
* @param scoreDirector never null, the {@link ScoreDirector}
27-
* which has the {@link ScoreDirector#getWorkingSolution()} to which the selections belong or apply to
28+
* @param solution never null, the current solution
2829
* @param selectionList never null, a {@link List}
2930
* of {@link PlanningEntity}, planningValue, {@link Move} or {@link Selector}
3031
*/
31-
void sort(ScoreDirector<Solution_> scoreDirector, List<T> selectionList);
32+
void sort(Solution_ solution, List<T> selectionList);
3233

3334
}

core/src/main/java/ai/timefold/solver/core/impl/heuristic/selector/entity/decorator/SortingEntitySelector.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public void constructCache(SolverScope<Solution_> solverScope) {
6060
return;
6161
}
6262
super.constructCache(solverScope);
63-
sorter.sort(solverScope.getScoreDirector(), cachedEntityList);
63+
sorter.sort(solverScope.getScoreDirector().getWorkingSolution(), cachedEntityList);
6464
logger.trace(" Sorted cachedEntityList: size ({}), entitySelector ({}).",
6565
cachedEntityList.size(), this);
6666
}

core/src/main/java/ai/timefold/solver/core/impl/heuristic/selector/move/decorator/SortingMoveSelector.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public SortingMoveSelector(MoveSelector<Solution_> childMoveSelector, SelectionC
2525
@Override
2626
public void constructCache(SolverScope<Solution_> solverScope) {
2727
super.constructCache(solverScope);
28-
sorter.sort(solverScope.getScoreDirector(), cachedMoveList);
28+
sorter.sort(solverScope.getScoreDirector().getWorkingSolution(), cachedMoveList);
2929
logger.trace(" Sorted cachedMoveList: size ({}), moveSelector ({}).",
3030
cachedMoveList.size(), this);
3131
}

core/src/main/java/ai/timefold/solver/core/impl/heuristic/selector/value/decorator/FromEntitySortingValueSelector.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ public Iterator<Object> iterator(Object entity) {
9898
childValueSelector.iterator(entity).forEachRemaining(cachedValueList::add);
9999
logger.trace(" Created cachedValueList: size ({}), valueSelector ({}).",
100100
cachedValueList.size(), this);
101-
sorter.sort(scoreDirector, cachedValueList);
101+
sorter.sort(scoreDirector.getWorkingSolution(), cachedValueList);
102102
logger.trace(" Sorted cachedValueList: size ({}), valueSelector ({}).",
103103
cachedValueList.size(), this);
104104
return cachedValueList.iterator();

core/src/main/java/ai/timefold/solver/core/impl/heuristic/selector/value/decorator/SortingValueSelector.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public SortingValueSelector(IterableValueSelector<Solution_> childValueSelector,
2727
@Override
2828
public void constructCache(SolverScope<Solution_> solverScope) {
2929
super.constructCache(solverScope);
30-
sorter.sort(solverScope.getScoreDirector(), cachedValueList);
30+
sorter.sort(solverScope.getScoreDirector().getWorkingSolution(), cachedValueList);
3131
logger.trace(" Sorted cachedValueList: size ({}), valueSelector ({}).",
3232
cachedValueList.size(), this);
3333
}

core/src/test/java/ai/timefold/solver/core/impl/heuristic/selector/common/decorator/ComparatorFactorySelectionSorterTest.java

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
package ai.timefold.solver.core.impl.heuristic.selector.common.decorator;
22

33
import static ai.timefold.solver.core.testutil.PlannerAssert.assertCodesOfIterator;
4-
import static org.mockito.Mockito.mock;
54

65
import java.util.ArrayList;
76
import java.util.Comparator;
87
import java.util.List;
98

109
import ai.timefold.solver.core.api.domain.common.ComparatorFactory;
11-
import ai.timefold.solver.core.api.score.director.ScoreDirector;
1210
import ai.timefold.solver.core.config.heuristic.selector.common.decorator.SelectionSorterOrder;
1311
import ai.timefold.solver.core.testdomain.TestdataEntity;
1412
import ai.timefold.solver.core.testdomain.TestdataSolution;
@@ -24,13 +22,12 @@ void sortAscending() {
2422
ComparatorFactorySelectionSorter<TestdataSolution, TestdataEntity> selectionSorter =
2523
new ComparatorFactorySelectionSorter<>(
2624
comparatorFactory, SelectionSorterOrder.ASCENDING);
27-
ScoreDirector<TestdataSolution> scoreDirector = mock(ScoreDirector.class);
2825
List<TestdataEntity> selectionList = new ArrayList<>();
2926
selectionList.add(new TestdataEntity("C"));
3027
selectionList.add(new TestdataEntity("A"));
3128
selectionList.add(new TestdataEntity("D"));
3229
selectionList.add(new TestdataEntity("B"));
33-
selectionSorter.sort(scoreDirector, selectionList);
30+
selectionSorter.sort(new TestdataSolution(), selectionList);
3431
assertCodesOfIterator(selectionList.iterator(), "A", "B", "C", "D");
3532
}
3633

@@ -41,13 +38,12 @@ void sortDescending() {
4138
ComparatorFactorySelectionSorter<TestdataSolution, TestdataEntity> selectionSorter =
4239
new ComparatorFactorySelectionSorter<>(
4340
comparatorFactory, SelectionSorterOrder.DESCENDING);
44-
ScoreDirector<TestdataSolution> scoreDirector = mock(ScoreDirector.class);
4541
List<TestdataEntity> selectionList = new ArrayList<>();
4642
selectionList.add(new TestdataEntity("C"));
4743
selectionList.add(new TestdataEntity("A"));
4844
selectionList.add(new TestdataEntity("D"));
4945
selectionList.add(new TestdataEntity("B"));
50-
selectionSorter.sort(scoreDirector, selectionList);
46+
selectionSorter.sort(new TestdataSolution(), selectionList);
5147
assertCodesOfIterator(selectionList.iterator(), "D", "C", "B", "A");
5248
}
5349

core/src/test/java/ai/timefold/solver/core/impl/heuristic/selector/entity/decorator/SortingEntitySelectorTest.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import static ai.timefold.solver.core.testutil.PlannerAssert.verifyPhaseLifecycle;
55
import static org.assertj.core.api.Assertions.assertThat;
66
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
7+
import static org.mockito.Mockito.doReturn;
78
import static org.mockito.Mockito.mock;
89
import static org.mockito.Mockito.times;
910
import static org.mockito.Mockito.verify;
@@ -17,6 +18,7 @@
1718
import ai.timefold.solver.core.impl.heuristic.selector.entity.EntitySelector;
1819
import ai.timefold.solver.core.impl.phase.scope.AbstractPhaseScope;
1920
import ai.timefold.solver.core.impl.phase.scope.AbstractStepScope;
21+
import ai.timefold.solver.core.impl.score.director.InnerScoreDirector;
2022
import ai.timefold.solver.core.impl.solver.scope.SolverScope;
2123
import ai.timefold.solver.core.testdomain.TestdataEntity;
2224
import ai.timefold.solver.core.testdomain.TestdataObject;
@@ -56,6 +58,9 @@ public void runCacheType(SelectionCacheType cacheType, int timesCalled) {
5658
EntitySelector entitySelector = new SortingEntitySelector(childEntitySelector, cacheType, sorter);
5759

5860
SolverScope solverScope = mock(SolverScope.class);
61+
InnerScoreDirector<?, ?> scoreDirector = mock(InnerScoreDirector.class);
62+
doReturn(scoreDirector).when(solverScope).getScoreDirector();
63+
doReturn(new TestdataSolution()).when(scoreDirector).getWorkingSolution();
5964
entitySelector.solvingStarted(solverScope);
6065

6166
AbstractPhaseScope phaseScopeA = mock(AbstractPhaseScope.class);

core/src/test/java/ai/timefold/solver/core/impl/heuristic/selector/move/decorator/SortingMoveSelectorTest.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import static ai.timefold.solver.core.testutil.PlannerAssert.verifyPhaseLifecycle;
66
import static ai.timefold.solver.core.testutil.PlannerTestUtils.mockScoreDirector;
77
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
8+
import static org.mockito.Mockito.doReturn;
89
import static org.mockito.Mockito.mock;
910
import static org.mockito.Mockito.times;
1011
import static org.mockito.Mockito.verify;
@@ -27,6 +28,7 @@
2728
import ai.timefold.solver.core.impl.heuristic.selector.move.MoveSelector;
2829
import ai.timefold.solver.core.impl.phase.scope.AbstractPhaseScope;
2930
import ai.timefold.solver.core.impl.phase.scope.AbstractStepScope;
31+
import ai.timefold.solver.core.impl.score.director.InnerScoreDirector;
3032
import ai.timefold.solver.core.impl.solver.scope.SolverScope;
3133
import ai.timefold.solver.core.testdomain.TestdataSolution;
3234
import ai.timefold.solver.core.testutil.CodeAssertable;
@@ -109,6 +111,9 @@ public void runCacheType(SelectionCacheType cacheType, int timesCalled) {
109111
MoveSelector moveSelector = new SortingMoveSelector(childMoveSelector, cacheType, sorter);
110112

111113
SolverScope solverScope = mock(SolverScope.class);
114+
InnerScoreDirector<?, ?> scoreDirector = mock(InnerScoreDirector.class);
115+
doReturn(scoreDirector).when(solverScope).getScoreDirector();
116+
doReturn(new TestdataSolution()).when(scoreDirector).getWorkingSolution();
112117
moveSelector.solvingStarted(solverScope);
113118

114119
AbstractPhaseScope phaseScopeA = mock(AbstractPhaseScope.class);

0 commit comments

Comments
 (0)