Skip to content

Commit a69c7c2

Browse files
committed
WIP: partially convert unis
1 parent 7614e17 commit a69c7c2

18 files changed

Lines changed: 794 additions & 368 deletions

core/src/main/java/ai/timefold/solver/core/api/score/stream/ConstraintCollectors.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1709,7 +1709,7 @@ public final class ConstraintCollectors {
17091709
toConnectedRanges(@NonNull Function<A, PointType_> startInclusiveMap,
17101710
@NonNull Function<A, PointType_> endExclusiveMap,
17111711
@NonNull BiFunction<PointType_, PointType_, DifferenceType_> differenceFunction) {
1712-
return InnerUniConstraintCollectors.toConnectedRanges(ConstantLambdaUtils.identity(), startInclusiveMap,
1712+
return InnerUniConstraintCollectors.toConnectedRanges(startInclusiveMap,
17131713
endExclusiveMap,
17141714
differenceFunction);
17151715
}

core/src/main/java/ai/timefold/solver/core/impl/bavet/common/AbstractGroupNode.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,9 @@ public abstract class AbstractGroupNode<InTuple_ extends Tuple, OutTuple_ extend
5353
private final boolean useAssertingGroupKey;
5454

5555
protected AbstractGroupNode(int groupStoreIndex, Function<InTuple_, GroupKey_> groupKeyFunction,
56-
Supplier<ResultContainer_> supplier,
57-
Function<ResultContainer_, Result_> finisher,
58-
TupleLifecycle<OutTuple_> nextNodesTupleLifecycle, EnvironmentMode environmentMode) {
56+
Supplier<ResultContainer_> supplier,
57+
Function<ResultContainer_, Result_> finisher,
58+
TupleLifecycle<OutTuple_> nextNodesTupleLifecycle, EnvironmentMode environmentMode) {
5959
this.groupStoreIndex = groupStoreIndex;
6060
this.groupKeyFunction = groupKeyFunction;
6161
this.supplier = supplier;
@@ -80,8 +80,8 @@ protected AbstractGroupNode(int groupStoreIndex, Function<InTuple_, GroupKey_> g
8080
}
8181

8282
protected AbstractGroupNode(int groupStoreIndex,
83-
Function<InTuple_, GroupKey_> groupKeyFunction, TupleLifecycle<OutTuple_> nextNodesTupleLifecycle,
84-
EnvironmentMode environmentMode) {
83+
Function<InTuple_, GroupKey_> groupKeyFunction, TupleLifecycle<OutTuple_> nextNodesTupleLifecycle,
84+
EnvironmentMode environmentMode) {
8585
this(groupStoreIndex,
8686
groupKeyFunction, null, null, nextNodesTupleLifecycle,
8787
environmentMode);
@@ -152,7 +152,7 @@ private Group<OutTuple_, ResultContainer_> createGroupWithGroupKey(Object groupM
152152
var userSuppliedKey = extractUserSuppliedKey(groupMapKey);
153153
var outTuple = createOutTuple(userSuppliedKey);
154154
var group = hasCollector ? Group.create(groupMapKey, supplier.get(), outTuple)
155-
: Group.<OutTuple_, ResultContainer_>createWithoutAccumulate(groupMapKey, outTuple);
155+
: Group.<OutTuple_, ResultContainer_> createWithoutAccumulate(groupMapKey, outTuple);
156156
propagationQueue.insert(group);
157157
return group;
158158
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package ai.timefold.solver.core.impl.score.stream.collector;
22

33
public sealed interface LongCalculator<Output_> permits LongAverageCalculator, LongSumCalculator {
4+
45
void insert(long input);
56

67
void retract(long input);
78

89
Output_ result();
10+
911
}

core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/InnerBiConstraintCollectors.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,8 +198,7 @@ public static <A, B, ResultContainer_, Result_> BiConstraintCollector<A, B, Resu
198198
Function<? super Interval_, ? extends Point_> startMap,
199199
Function<? super Interval_, ? extends Point_> endMap,
200200
BiFunction<? super Point_, ? super Point_, ? extends Difference_> differenceFunction) {
201-
return new ConnectedRangesBiConstraintCollector<>(mapper, startMap, endMap,
202-
differenceFunction);
201+
return new ConnectedRangesBiConstraintCollector<>(mapper, startMap, endMap, differenceFunction);
203202
}
204203

205204
public static <A, B, Intermediate_, Result_> BiConstraintCollector<A, B, ?, Result_>

core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/AndThenUniCollector.java

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,17 @@
66
import java.util.function.Supplier;
77

88
import ai.timefold.solver.core.api.score.stream.uni.UniConstraintCollector;
9+
import ai.timefold.solver.core.api.score.stream.uni.UniConstraintCollectorAccumulator;
910

10-
import org.jspecify.annotations.NonNull;
11+
import org.jspecify.annotations.NullMarked;
1112
import org.jspecify.annotations.Nullable;
1213

14+
@NullMarked
1315
final class AndThenUniCollector<A, ResultContainer_, Intermediate_, Result_>
1416
implements UniConstraintCollector<A, ResultContainer_, Result_> {
1517

1618
private final UniConstraintCollector<A, ResultContainer_, Intermediate_> delegate;
17-
private final Function<Intermediate_, Result_> mappingFunction;
19+
private final Function<@Nullable Intermediate_, Result_> mappingFunction;
1820

1921
AndThenUniCollector(UniConstraintCollector<A, ResultContainer_, Intermediate_> delegate,
2022
Function<Intermediate_, Result_> mappingFunction) {
@@ -23,17 +25,29 @@ final class AndThenUniCollector<A, ResultContainer_, Intermediate_, Result_>
2325
}
2426

2527
@Override
26-
public @NonNull Supplier<ResultContainer_> supplier() {
28+
public Supplier<ResultContainer_> supplier() {
2729
return delegate.supplier();
2830
}
2931

3032
@Override
31-
public @NonNull BiFunction<ResultContainer_, A, Runnable> accumulator() {
32-
return delegate.accumulator();
33+
public BiFunction<ResultContainer_, A, Runnable> accumulator() {
34+
throw new UnsupportedOperationException();
3335
}
3436

3537
@Override
36-
public @Nullable Function<ResultContainer_, Result_> finisher() {
38+
public boolean isIncremental() {
39+
return true;
40+
}
41+
42+
@Override
43+
public UniConstraintCollectorAccumulator<ResultContainer_, A> incrementalAccumulator() {
44+
return delegate.isIncremental()
45+
? delegate.incrementalAccumulator()
46+
: ComposeFourUniCollector.toIncremental(delegate.accumulator());
47+
}
48+
49+
@Override
50+
public Function<ResultContainer_, @Nullable Result_> finisher() {
3751
var finisher = delegate.finisher();
3852
return container -> mappingFunction.apply(finisher.apply(container));
3953
}

core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ComposeFourUniCollector.java

Lines changed: 104 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7,34 +7,37 @@
77

88
import ai.timefold.solver.core.api.function.QuadFunction;
99
import ai.timefold.solver.core.api.score.stream.uni.UniConstraintCollector;
10+
import ai.timefold.solver.core.api.score.stream.uni.UniConstraintCollectorAccumulatedValue;
11+
import ai.timefold.solver.core.api.score.stream.uni.UniConstraintCollectorAccumulator;
1012
import ai.timefold.solver.core.impl.util.Quadruple;
1113

12-
import org.jspecify.annotations.NonNull;
14+
import org.jspecify.annotations.NullMarked;
1315
import org.jspecify.annotations.Nullable;
1416

17+
@NullMarked
1518
final class ComposeFourUniCollector<A, ResultHolder1_, ResultHolder2_, ResultHolder3_, ResultHolder4_, Result1_, Result2_, Result3_, Result4_, Result_>
1619
implements
1720
UniConstraintCollector<A, Quadruple<ResultHolder1_, ResultHolder2_, ResultHolder3_, ResultHolder4_>, Result_> {
1821
private final UniConstraintCollector<A, ResultHolder1_, Result1_> first;
1922
private final UniConstraintCollector<A, ResultHolder2_, Result2_> second;
2023
private final UniConstraintCollector<A, ResultHolder3_, Result3_> third;
2124
private final UniConstraintCollector<A, ResultHolder4_, Result4_> fourth;
22-
private final QuadFunction<Result1_, Result2_, Result3_, Result4_, Result_> composeFunction;
25+
private final QuadFunction<@Nullable Result1_, @Nullable Result2_, @Nullable Result3_, @Nullable Result4_, @Nullable Result_> composeFunction;
2326

2427
private final Supplier<ResultHolder1_> firstSupplier;
2528
private final Supplier<ResultHolder2_> secondSupplier;
2629
private final Supplier<ResultHolder3_> thirdSupplier;
2730
private final Supplier<ResultHolder4_> fourthSupplier;
2831

29-
private final BiFunction<ResultHolder1_, A, Runnable> firstAccumulator;
30-
private final BiFunction<ResultHolder2_, A, Runnable> secondAccumulator;
31-
private final BiFunction<ResultHolder3_, A, Runnable> thirdAccumulator;
32-
private final BiFunction<ResultHolder4_, A, Runnable> fourthAccumulator;
32+
private final UniConstraintCollectorAccumulator<ResultHolder1_, A> firstIncremental;
33+
private final UniConstraintCollectorAccumulator<ResultHolder2_, A> secondIncremental;
34+
private final UniConstraintCollectorAccumulator<ResultHolder3_, A> thirdIncremental;
35+
private final UniConstraintCollectorAccumulator<ResultHolder4_, A> fourthIncremental;
3336

34-
private final Function<ResultHolder1_, Result1_> firstFinisher;
35-
private final Function<ResultHolder2_, Result2_> secondFinisher;
36-
private final Function<ResultHolder3_, Result3_> thirdFinisher;
37-
private final Function<ResultHolder4_, Result4_> fourthFinisher;
37+
private final Function<ResultHolder1_, @Nullable Result1_> firstFinisher;
38+
private final Function<ResultHolder2_, @Nullable Result2_> secondFinisher;
39+
private final Function<ResultHolder3_, @Nullable Result3_> thirdFinisher;
40+
private final Function<ResultHolder4_, @Nullable Result4_> fourthFinisher;
3841

3942
ComposeFourUniCollector(UniConstraintCollector<A, ResultHolder1_, Result1_> first,
4043
UniConstraintCollector<A, ResultHolder2_, Result2_> second,
@@ -52,10 +55,12 @@ final class ComposeFourUniCollector<A, ResultHolder1_, ResultHolder2_, ResultHol
5255
this.thirdSupplier = third.supplier();
5356
this.fourthSupplier = fourth.supplier();
5457

55-
this.firstAccumulator = first.accumulator();
56-
this.secondAccumulator = second.accumulator();
57-
this.thirdAccumulator = third.accumulator();
58-
this.fourthAccumulator = fourth.accumulator();
58+
this.firstIncremental = first.isIncremental() ? first.incrementalAccumulator() : toIncremental(first.accumulator());
59+
this.secondIncremental =
60+
second.isIncremental() ? second.incrementalAccumulator() : toIncremental(second.accumulator());
61+
this.thirdIncremental = third.isIncremental() ? third.incrementalAccumulator() : toIncremental(third.accumulator());
62+
this.fourthIncremental =
63+
fourth.isIncremental() ? fourth.incrementalAccumulator() : toIncremental(fourth.accumulator());
5964

6065
this.firstFinisher = first.finisher();
6166
this.secondFinisher = second.finisher();
@@ -64,44 +69,53 @@ final class ComposeFourUniCollector<A, ResultHolder1_, ResultHolder2_, ResultHol
6469
}
6570

6671
@Override
67-
public @NonNull Supplier<Quadruple<ResultHolder1_, ResultHolder2_, ResultHolder3_, ResultHolder4_>> supplier() {
72+
public Supplier<Quadruple<ResultHolder1_, ResultHolder2_, ResultHolder3_, ResultHolder4_>> supplier() {
6873
return () -> {
69-
ResultHolder1_ a = firstSupplier.get();
70-
ResultHolder2_ b = secondSupplier.get();
71-
ResultHolder3_ c = thirdSupplier.get();
74+
var a = firstSupplier.get();
75+
var b = secondSupplier.get();
76+
var c = thirdSupplier.get();
7277
return new Quadruple<>(a, b, c, fourthSupplier.get());
7378
};
7479
}
7580

7681
@Override
77-
public @NonNull BiFunction<Quadruple<ResultHolder1_, ResultHolder2_, ResultHolder3_, ResultHolder4_>, A, Runnable>
82+
public BiFunction<Quadruple<ResultHolder1_, ResultHolder2_, ResultHolder3_, ResultHolder4_>, A, Runnable>
7883
accumulator() {
79-
return (resultHolder, a) -> composeUndo(firstAccumulator.apply(resultHolder.a(), a),
80-
secondAccumulator.apply(resultHolder.b(), a),
81-
thirdAccumulator.apply(resultHolder.c(), a),
82-
fourthAccumulator.apply(resultHolder.d(), a));
84+
throw new UnsupportedOperationException();
8385
}
8486

85-
private static Runnable composeUndo(Runnable first, Runnable second, Runnable third,
86-
Runnable fourth) {
87-
return () -> {
88-
first.run();
89-
second.run();
90-
third.run();
91-
fourth.run();
87+
@Override
88+
public boolean isIncremental() {
89+
return true;
90+
}
91+
92+
@Override
93+
public UniConstraintCollectorAccumulator<Quadruple<ResultHolder1_, ResultHolder2_, ResultHolder3_, ResultHolder4_>, A>
94+
incrementalAccumulator() {
95+
return container -> {
96+
var v1 = firstIncremental.intoGroup(container.a());
97+
var v2 = secondIncremental.intoGroup(container.b());
98+
var v3 = thirdIncremental.intoGroup(container.c());
99+
var v4 = fourthIncremental.intoGroup(container.d());
100+
return new ComposingAccumulatedValue<>(v1, v2, v3, v4);
92101
};
93102
}
94103

95104
@Override
96-
public @Nullable Function<Quadruple<ResultHolder1_, ResultHolder2_, ResultHolder3_, ResultHolder4_>, Result_> finisher() {
105+
public Function<Quadruple<ResultHolder1_, ResultHolder2_, ResultHolder3_, ResultHolder4_>, @Nullable Result_> finisher() {
97106
return resultHolder -> composeFunction.apply(firstFinisher.apply(resultHolder.a()),
98107
secondFinisher.apply(resultHolder.b()),
99108
thirdFinisher.apply(resultHolder.c()),
100109
fourthFinisher.apply(resultHolder.d()));
101110
}
102111

112+
static <ResultContainer_, A> UniConstraintCollectorAccumulator<ResultContainer_, A>
113+
toIncremental(BiFunction<ResultContainer_, A, Runnable> accumulator) {
114+
return container -> new AdaptedIncrementalAccumulatedValue<>(accumulator, container);
115+
}
116+
103117
@Override
104-
public boolean equals(Object object) {
118+
public boolean equals(@Nullable Object object) {
105119
if (this == object)
106120
return true;
107121
if (object == null || getClass() != object.getClass())
@@ -118,4 +132,62 @@ public boolean equals(Object object) {
118132
public int hashCode() {
119133
return Objects.hash(first, second, third, fourth, composeFunction);
120134
}
135+
136+
private static final class AdaptedIncrementalAccumulatedValue<ResultContainer_, A>
137+
implements UniConstraintCollectorAccumulatedValue<A> {
138+
139+
private final BiFunction<ResultContainer_, @Nullable A, Runnable> accumulator;
140+
private final ResultContainer_ container;
141+
private @Nullable Runnable runningUndo;
142+
143+
public AdaptedIncrementalAccumulatedValue(BiFunction<ResultContainer_, @Nullable A, Runnable> accumulator,
144+
ResultContainer_ container) {
145+
this.accumulator = accumulator;
146+
this.container = container;
147+
}
148+
149+
@Override
150+
public boolean add(@Nullable A a) {
151+
runningUndo = accumulator.apply(container, a);
152+
return true;
153+
}
154+
155+
@Override
156+
public boolean update(@Nullable A a) {
157+
runningUndo.run();
158+
runningUndo = accumulator.apply(container, a);
159+
return true;
160+
}
161+
162+
@Override
163+
public boolean remove() {
164+
runningUndo.run();
165+
runningUndo = null;
166+
return true;
167+
}
168+
169+
}
170+
171+
private record ComposingAccumulatedValue<A>(UniConstraintCollectorAccumulatedValue<A> v1,
172+
UniConstraintCollectorAccumulatedValue<A> v2,
173+
UniConstraintCollectorAccumulatedValue<A> v3,
174+
UniConstraintCollectorAccumulatedValue<A> v4)
175+
implements
176+
UniConstraintCollectorAccumulatedValue<A> {
177+
178+
@Override
179+
public boolean add(@Nullable A a) {
180+
return v1.add(a) | v2.add(a) | v3.add(a) | v4.add(a);
181+
}
182+
183+
@Override
184+
public boolean update(@Nullable A a) {
185+
return v1.update(a) | v2.update(a) | v3.update(a) | v4.update(a);
186+
}
187+
188+
@Override
189+
public boolean remove() {
190+
return v1.remove() | v2.remove() | v3.remove() | v4.remove();
191+
}
192+
}
121193
}

0 commit comments

Comments
 (0)