Skip to content

Commit 7b60327

Browse files
committed
chore: address comments
1 parent 35bca6a commit 7b60327

File tree

21 files changed

+143
-91
lines changed

21 files changed

+143
-91
lines changed

core/src/main/java/ai/timefold/solver/core/api/domain/valuerange/ValueRange.java

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88

99
import ai.timefold.solver.core.api.domain.variable.PlanningListVariable;
1010
import ai.timefold.solver.core.api.domain.variable.PlanningVariable;
11-
import ai.timefold.solver.core.impl.domain.valuerange.sort.ValueRangeSorter;
1211

1312
import org.jspecify.annotations.NullMarked;
1413
import org.jspecify.annotations.Nullable;
@@ -46,14 +45,6 @@ public interface ValueRange<T> {
4645
*/
4746
boolean contains(@Nullable T value);
4847

49-
/**
50-
* The sorting operation copies the current value range and sorts it using the provided sorter.
51-
*
52-
* @param sorter never null, the value range sorter
53-
* @return A new instance of the value range, with the data sorted.
54-
*/
55-
ValueRange<T> sort(ValueRangeSorter<T> sorter);
56-
5748
/**
5849
* Select in random order, but without shuffling the elements.
5950
* Each element might be selected multiple times.

core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/AbstractCountableValueRange.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import ai.timefold.solver.core.api.domain.valuerange.CountableValueRange;
66
import ai.timefold.solver.core.api.domain.valuerange.ValueRange;
77
import ai.timefold.solver.core.api.domain.valuerange.ValueRangeFactory;
8+
import ai.timefold.solver.core.impl.domain.valuerange.sort.SortableValueRange;
89
import ai.timefold.solver.core.impl.domain.valuerange.sort.ValueRangeSorter;
910

1011
import org.jspecify.annotations.NullMarked;
@@ -17,7 +18,7 @@
1718
* @see ValueRangeFactory
1819
*/
1920
@NullMarked
20-
public abstract class AbstractCountableValueRange<T> implements CountableValueRange<T> {
21+
public abstract class AbstractCountableValueRange<T> implements CountableValueRange<T>, SortableValueRange<T> {
2122

2223
/**
2324
* Certain optimizations can be applied if {@link Object#equals(Object)} can be relied upon

core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/AbstractUncountableValueRange.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import ai.timefold.solver.core.api.domain.valuerange.CountableValueRange;
44
import ai.timefold.solver.core.api.domain.valuerange.ValueRange;
55
import ai.timefold.solver.core.api.domain.valuerange.ValueRangeFactory;
6+
import ai.timefold.solver.core.impl.domain.valuerange.sort.SortableValueRange;
67
import ai.timefold.solver.core.impl.domain.valuerange.sort.ValueRangeSorter;
78

89
/**
@@ -15,7 +16,7 @@
1516
* Use {@link CountableValueRange} instead, and configure a step.
1617
*/
1718
@Deprecated(forRemoval = true, since = "1.1.0")
18-
public abstract class AbstractUncountableValueRange<T> implements ValueRange<T> {
19+
public abstract class AbstractUncountableValueRange<T> implements ValueRange<T>, SortableValueRange<T> {
1920

2021
@Override
2122
public ValueRange<T> sort(ValueRangeSorter<T> sorter) {
Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
package ai.timefold.solver.core.impl.domain.valuerange.sort;
22

3-
import java.util.ArrayList;
4-
import java.util.Collections;
53
import java.util.List;
64
import java.util.Set;
75
import java.util.SortedSet;
86

9-
import ai.timefold.solver.core.impl.heuristic.selector.common.decorator.SelectionSetSorter;
107
import ai.timefold.solver.core.impl.heuristic.selector.common.decorator.SelectionSorter;
118

129
import org.jspecify.annotations.NullMarked;
@@ -21,18 +18,11 @@ public static <Solution_, T> ValueRangeSorter<T> of(Solution_ solution, Selectio
2118

2219
@Override
2320
public List<T> sort(List<T> selectionList) {
24-
var newList = new ArrayList<>(selectionList);
25-
selectionSorter.sort(solution, newList);
26-
return Collections.unmodifiableList(newList);
21+
return selectionSorter.sort(solution, selectionList);
2722
}
2823

2924
@Override
30-
@SuppressWarnings({ "rawtypes", "unchecked" })
3125
public SortedSet<T> sort(Set<T> selectionSet) {
32-
if (!(selectionSorter instanceof SelectionSetSorter selectionSetSorter)) {
33-
throw new IllegalStateException(
34-
"Impossible state: the sorting operation cannot be performed because the sorter does not support sorting collection sets.");
35-
}
36-
return selectionSetSorter.sort(solution, selectionSet);
26+
return selectionSorter.sort(solution, selectionSet);
3727
}
3828
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package ai.timefold.solver.core.impl.domain.valuerange.sort;
2+
3+
import ai.timefold.solver.core.api.domain.valuerange.ValueRange;
4+
5+
import org.jspecify.annotations.NullMarked;
6+
7+
@NullMarked
8+
@FunctionalInterface
9+
public interface SortableValueRange<T> {
10+
11+
/**
12+
* The sorting operation copies the current value range and sorts it using the provided sorter.
13+
*
14+
* @param sorter never null, the value range sorter
15+
* @return A new instance of the value range, with the data sorted.
16+
*/
17+
ValueRange<T> sort(ValueRangeSorter<T> sorter);
18+
}

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

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

3+
import java.util.ArrayList;
34
import java.util.Collections;
45
import java.util.Comparator;
56
import java.util.List;
@@ -21,8 +22,7 @@
2122
* @param <T> the selection type
2223
*/
2324
@NullMarked
24-
public final class ComparatorFactorySelectionSorter<Solution_, T>
25-
implements SelectionSorter<Solution_, T>, SelectionSetSorter<Solution_, T> {
25+
public final class ComparatorFactorySelectionSorter<Solution_, T> implements SelectionSorter<Solution_, T> {
2626

2727
private final ComparatorFactory<Solution_, T> selectionComparatorFactory;
2828
private final SelectionSorterOrder selectionSorterOrder;
@@ -41,9 +41,11 @@ private Comparator<T> getAppliedComparator(Comparator<T> comparator) {
4141
}
4242

4343
@Override
44-
public void sort(Solution_ solution, List<T> selectionList) {
44+
public List<T> sort(Solution_ solution, List<T> selectionList) {
4545
var appliedComparator = getAppliedComparator(selectionComparatorFactory.createComparator(solution));
46-
selectionList.sort(appliedComparator);
46+
var sortedList = new ArrayList<>(selectionList);
47+
sortedList.sort(appliedComparator);
48+
return Collections.unmodifiableList(sortedList);
4749
}
4850

4951
@Override

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

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

3+
import java.util.ArrayList;
34
import java.util.Collections;
45
import java.util.Comparator;
56
import java.util.List;
@@ -20,8 +21,7 @@
2021
* @param <T> the selection type
2122
*/
2223
@NullMarked
23-
public final class ComparatorSelectionSorter<Solution_, T>
24-
implements SelectionSorter<Solution_, T>, SelectionSetSorter<Solution_, T> {
24+
public final class ComparatorSelectionSorter<Solution_, T> implements SelectionSorter<Solution_, T> {
2525

2626
private final Comparator<T> appliedComparator;
2727

@@ -40,8 +40,10 @@ public ComparatorSelectionSorter(Comparator<T> comparator, SelectionSorterOrder
4040
}
4141

4242
@Override
43-
public void sort(Solution_ solution, List<T> selectionList) {
44-
selectionList.sort(appliedComparator);
43+
public List<T> sort(Solution_ solution, List<T> selectionList) {
44+
var sortedList = new ArrayList<>(selectionList);
45+
sortedList.sort(appliedComparator);
46+
return Collections.unmodifiableList(sortedList);
4547
}
4648

4749
@Override

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

Lines changed: 0 additions & 28 deletions
This file was deleted.

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

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

33
import java.util.List;
4+
import java.util.Set;
5+
import java.util.SortedSet;
46

57
import ai.timefold.solver.core.api.domain.entity.PlanningEntity;
68
import ai.timefold.solver.core.api.domain.solution.PlanningSolution;
@@ -21,16 +23,23 @@
2123
* @param <T> the selection type
2224
*/
2325
@NullMarked
24-
@FunctionalInterface
2526
public interface SelectionSorter<Solution_, T> {
2627

2728
/**
28-
* Apply an in-place sorting operation.
29-
*
29+
* Creates a copy of the provided list and sort the data.
30+
*
3031
* @param solution never null, the current solution
3132
* @param selectionList never null, a {@link List}
3233
* of {@link PlanningEntity}, planningValue, {@link Move} or {@link Selector} that will be sorted.
3334
*/
34-
void sort(Solution_ solution, List<T> selectionList);
35+
List<T> sort(Solution_ solution, List<T> selectionList);
36+
37+
/**
38+
* Creates a copy of the provided set and sort the data.
39+
*
40+
* @param solution never null, the current solution
41+
* @param selectionSet never null, a {@link Set} of values that will be used as input for sorting.
42+
*/
43+
SortedSet<T> sort(Solution_ solution, Set<T> selectionSet);
3544

3645
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ public void constructCache(SolverScope<Solution_> solverScope) {
6060
return;
6161
}
6262
super.constructCache(solverScope);
63-
sorter.sort(solverScope.getScoreDirector().getWorkingSolution(), cachedEntityList);
63+
// We need to update the cachedEntityList since the sorter will copy the data and return a sorted list
64+
cachedEntityList = sorter.sort(solverScope.getScoreDirector().getWorkingSolution(), cachedEntityList);
6465
logger.trace(" Sorted cachedEntityList: size ({}), entitySelector ({}).",
6566
cachedEntityList.size(), this);
6667
}

0 commit comments

Comments
 (0)