Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: change move support in Move Streams #1169

Closed
wants to merge 3 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -15,15 +15,15 @@
import ai.timefold.solver.core.api.score.stream.quad.QuadJoiner;
import ai.timefold.solver.core.api.score.stream.tri.TriJoiner;
import ai.timefold.solver.core.api.score.stream.uni.UniConstraintStream;
import ai.timefold.solver.core.impl.score.stream.JoinerType;
import ai.timefold.solver.core.impl.score.stream.common.bi.DefaultBiJoiner;
import ai.timefold.solver.core.impl.score.stream.common.bi.FilteringBiJoiner;
import ai.timefold.solver.core.impl.score.stream.common.penta.DefaultPentaJoiner;
import ai.timefold.solver.core.impl.score.stream.common.penta.FilteringPentaJoiner;
import ai.timefold.solver.core.impl.score.stream.common.quad.DefaultQuadJoiner;
import ai.timefold.solver.core.impl.score.stream.common.quad.FilteringQuadJoiner;
import ai.timefold.solver.core.impl.score.stream.common.tri.DefaultTriJoiner;
import ai.timefold.solver.core.impl.score.stream.common.tri.FilteringTriJoiner;
import ai.timefold.solver.core.impl.bavet.common.index.joiner.DefaultBiJoiner;
import ai.timefold.solver.core.impl.bavet.common.index.joiner.DefaultPentaJoiner;
import ai.timefold.solver.core.impl.bavet.common.index.joiner.DefaultQuadJoiner;
import ai.timefold.solver.core.impl.bavet.common.index.joiner.DefaultTriJoiner;
import ai.timefold.solver.core.impl.bavet.common.index.joiner.FilteringBiJoiner;
import ai.timefold.solver.core.impl.bavet.common.index.joiner.FilteringPentaJoiner;
import ai.timefold.solver.core.impl.bavet.common.index.joiner.FilteringQuadJoiner;
import ai.timefold.solver.core.impl.bavet.common.index.joiner.FilteringTriJoiner;
import ai.timefold.solver.core.impl.bavet.common.index.joiner.JoinerType;
import ai.timefold.solver.core.impl.util.ConstantLambdaUtils;

import org.jspecify.annotations.NonNull;
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package ai.timefold.solver.core.impl.bavet;

import java.util.IdentityHashMap;
import java.util.Map;

import ai.timefold.solver.core.impl.bavet.uni.AbstractForEachUniNode;

public abstract class AbstractSession {

private final NodeNetwork nodeNetwork;
private final Map<Class<?>, AbstractForEachUniNode<Object>[]> effectiveClassToNodeArrayMap;

protected AbstractSession(NodeNetwork nodeNetwork) {
this.nodeNetwork = nodeNetwork;
this.effectiveClassToNodeArrayMap = new IdentityHashMap<>(nodeNetwork.forEachNodeCount());
}

public final void insert(Object fact) {
var factClass = fact.getClass();
for (var node : findNodes(factClass)) {
node.insert(fact);
}
}

@SuppressWarnings("unchecked")
private AbstractForEachUniNode<Object>[] findNodes(Class<?> factClass) {
// Map.computeIfAbsent() would have created lambdas on the hot path, this will not.
var nodeArray = effectiveClassToNodeArrayMap.get(factClass);
if (nodeArray == null) {
nodeArray = nodeNetwork.getForEachNodes(factClass)
.filter(AbstractForEachUniNode::supportsIndividualUpdates)
.toArray(AbstractForEachUniNode[]::new);
effectiveClassToNodeArrayMap.put(factClass, nodeArray);
}
return nodeArray;
}

public final void update(Object fact) {
var factClass = fact.getClass();
for (var node : findNodes(factClass)) {
node.update(fact);
}
}

public final void retract(Object fact) {
var factClass = fact.getClass();
for (var node : findNodes(factClass)) {
node.retract(fact);
}
}

protected void settle() {
nodeNetwork.settle();
}

}
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package ai.timefold.solver.core.impl.score.stream.bavet;
package ai.timefold.solver.core.impl.bavet;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Stream;

import ai.timefold.solver.core.impl.score.stream.bavet.common.Propagator;
import ai.timefold.solver.core.impl.score.stream.bavet.uni.AbstractForEachUniNode;
import ai.timefold.solver.core.impl.bavet.common.Propagator;
import ai.timefold.solver.core.impl.bavet.uni.AbstractForEachUniNode;

/**
* Represents Bavet's network of nodes, specific to a particular session.
@@ -17,7 +18,7 @@
* @param layeredNodes nodes grouped first by their layer, then by their index within the layer;
* propagation needs to happen in this order.
*/
record NodeNetwork(Map<Class<?>, List<AbstractForEachUniNode<Object>>> declaredClassToNodeMap, Propagator[][] layeredNodes) {
public record NodeNetwork(Map<Class<?>, List<AbstractForEachUniNode<?>>> declaredClassToNodeMap, Propagator[][] layeredNodes) {

public static final NodeNetwork EMPTY = new NodeNetwork(Map.of(), new Propagator[0][0]);

@@ -29,23 +30,27 @@ public int layerCount() {
return layeredNodes.length;
}

@SuppressWarnings("unchecked")
public AbstractForEachUniNode<Object>[] getApplicableForEachNodes(Class<?> factClass) {
public Stream<AbstractForEachUniNode<?>> getForEachNodes() {
return declaredClassToNodeMap.values()
.stream()
.flatMap(List::stream);
}

public Stream<AbstractForEachUniNode<?>> getForEachNodes(Class<?> factClass) {
return declaredClassToNodeMap.entrySet()
.stream()
.filter(entry -> entry.getKey().isAssignableFrom(factClass))
.map(Map.Entry::getValue)
.flatMap(List::stream)
.toArray(AbstractForEachUniNode[]::new);
.flatMap(List::stream);
}

public void propagate() {
public void settle() {
for (var layerIndex = 0; layerIndex < layerCount(); layerIndex++) {
propagateInLayer(layeredNodes[layerIndex]);
settleLayer(layeredNodes[layerIndex]);
}
}

private static void propagateInLayer(Propagator[] nodesInLayer) {
private static void settleLayer(Propagator[] nodesInLayer) {
var nodeCount = nodesInLayer.length;
if (nodeCount == 1) {
nodesInLayer[0].propagateEverything();
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package ai.timefold.solver.core.impl.score.stream.bavet.bi;
package ai.timefold.solver.core.impl.bavet.bi;

import java.util.function.Function;

import ai.timefold.solver.core.api.function.TriFunction;
import ai.timefold.solver.core.api.score.stream.bi.BiConstraintCollector;
import ai.timefold.solver.core.config.solver.EnvironmentMode;
import ai.timefold.solver.core.impl.score.stream.bavet.common.AbstractGroupNode;
import ai.timefold.solver.core.impl.score.stream.bavet.common.tuple.AbstractTuple;
import ai.timefold.solver.core.impl.score.stream.bavet.common.tuple.BiTuple;
import ai.timefold.solver.core.impl.score.stream.bavet.common.tuple.TupleLifecycle;
import ai.timefold.solver.core.impl.bavet.common.AbstractGroupNode;
import ai.timefold.solver.core.impl.bavet.common.tuple.AbstractTuple;
import ai.timefold.solver.core.impl.bavet.common.tuple.BiTuple;
import ai.timefold.solver.core.impl.bavet.common.tuple.TupleLifecycle;

abstract class AbstractGroupBiNode<OldA, OldB, OutTuple_ extends AbstractTuple, GroupKey_, ResultContainer_, Result_>
extends AbstractGroupNode<BiTuple<OldA, OldB>, OutTuple_, GroupKey_, ResultContainer_, Result_> {
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package ai.timefold.solver.core.impl.score.stream.bavet.bi;
package ai.timefold.solver.core.impl.bavet.bi;

import ai.timefold.solver.core.impl.score.stream.bavet.common.AbstractConcatNode;
import ai.timefold.solver.core.impl.score.stream.bavet.common.tuple.BiTuple;
import ai.timefold.solver.core.impl.score.stream.bavet.common.tuple.TupleLifecycle;
import ai.timefold.solver.core.impl.bavet.common.AbstractConcatNode;
import ai.timefold.solver.core.impl.bavet.common.tuple.BiTuple;
import ai.timefold.solver.core.impl.bavet.common.tuple.TupleLifecycle;

final class ConcatBiBiNode<A, B>
public final class ConcatBiBiNode<A, B>
extends AbstractConcatNode<BiTuple<A, B>, BiTuple<A, B>, BiTuple<A, B>> {

ConcatBiBiNode(TupleLifecycle<BiTuple<A, B>> nextNodesTupleLifecycle,
public ConcatBiBiNode(TupleLifecycle<BiTuple<A, B>> nextNodesTupleLifecycle,
int inputStoreIndexLeftOutTupleList, int inputStoreIndexRightOutTupleList,
int outputStoreSize) {
super(nextNodesTupleLifecycle, inputStoreIndexLeftOutTupleList, inputStoreIndexRightOutTupleList, outputStoreSize);
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
package ai.timefold.solver.core.impl.score.stream.bavet.bi;
package ai.timefold.solver.core.impl.bavet.bi;

import java.util.function.Function;

import ai.timefold.solver.core.impl.score.stream.bavet.common.AbstractConcatNode;
import ai.timefold.solver.core.impl.score.stream.bavet.common.tuple.BiTuple;
import ai.timefold.solver.core.impl.score.stream.bavet.common.tuple.TupleLifecycle;
import ai.timefold.solver.core.impl.score.stream.bavet.common.tuple.UniTuple;
import ai.timefold.solver.core.impl.bavet.common.AbstractConcatNode;
import ai.timefold.solver.core.impl.bavet.common.tuple.BiTuple;
import ai.timefold.solver.core.impl.bavet.common.tuple.TupleLifecycle;
import ai.timefold.solver.core.impl.bavet.common.tuple.UniTuple;

final class ConcatBiUniNode<A, B>
public final class ConcatBiUniNode<A, B>
extends AbstractConcatNode<BiTuple<A, B>, UniTuple<A>, BiTuple<A, B>> {

private final Function<A, B> paddingFunction;

ConcatBiUniNode(Function<A, B> paddingFunction, TupleLifecycle<BiTuple<A, B>> nextNodesTupleLifecycle,
public ConcatBiUniNode(Function<A, B> paddingFunction, TupleLifecycle<BiTuple<A, B>> nextNodesTupleLifecycle,
int inputStoreIndexLeftOutTupleList, int inputStoreIndexRightOutTupleList,
int outputStoreSize) {
super(nextNodesTupleLifecycle, inputStoreIndexLeftOutTupleList, inputStoreIndexRightOutTupleList, outputStoreSize);
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
package ai.timefold.solver.core.impl.score.stream.bavet.bi;
package ai.timefold.solver.core.impl.bavet.bi;

import java.util.function.Function;

import ai.timefold.solver.core.impl.score.stream.bavet.common.AbstractConcatNode;
import ai.timefold.solver.core.impl.score.stream.bavet.common.tuple.BiTuple;
import ai.timefold.solver.core.impl.score.stream.bavet.common.tuple.TupleLifecycle;
import ai.timefold.solver.core.impl.score.stream.bavet.common.tuple.UniTuple;
import ai.timefold.solver.core.impl.bavet.common.AbstractConcatNode;
import ai.timefold.solver.core.impl.bavet.common.tuple.BiTuple;
import ai.timefold.solver.core.impl.bavet.common.tuple.TupleLifecycle;
import ai.timefold.solver.core.impl.bavet.common.tuple.UniTuple;

final class ConcatUniBiNode<A, B>
public final class ConcatUniBiNode<A, B>
extends AbstractConcatNode<UniTuple<A>, BiTuple<A, B>, BiTuple<A, B>> {

private final Function<A, B> paddingFunction;

ConcatUniBiNode(Function<A, B> paddingFunction, TupleLifecycle<BiTuple<A, B>> nextNodesTupleLifecycle,
public ConcatUniBiNode(Function<A, B> paddingFunction, TupleLifecycle<BiTuple<A, B>> nextNodesTupleLifecycle,
int inputStoreIndexLeftOutTupleList, int inputStoreIndexRightOutTupleList,
int outputStoreSize) {
super(nextNodesTupleLifecycle, inputStoreIndexLeftOutTupleList, inputStoreIndexRightOutTupleList,
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package ai.timefold.solver.core.impl.bavet.bi;

import java.util.function.BiPredicate;

import ai.timefold.solver.core.impl.bavet.common.tuple.AbstractConditionalTupleLifecycle;
import ai.timefold.solver.core.impl.bavet.common.tuple.BiTuple;
import ai.timefold.solver.core.impl.bavet.common.tuple.TupleLifecycle;

public final class ConditionalBiTupleLifecycle<A, B> extends AbstractConditionalTupleLifecycle<BiTuple<A, B>> {
private final BiPredicate<A, B> predicate;

public ConditionalBiTupleLifecycle(BiPredicate<A, B> predicate, TupleLifecycle<BiTuple<A, B>> tupleLifecycle) {
super(tupleLifecycle);
this.predicate = predicate;
}

@Override
protected boolean test(BiTuple<A, B> tuple) {
return predicate.test(tuple.factA, tuple.factB);
}

}
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package ai.timefold.solver.core.impl.score.stream.bavet.bi;
package ai.timefold.solver.core.impl.bavet.bi;

import java.util.function.Function;

import ai.timefold.solver.core.impl.score.stream.bavet.common.AbstractFlattenLastNode;
import ai.timefold.solver.core.impl.score.stream.bavet.common.tuple.BiTuple;
import ai.timefold.solver.core.impl.score.stream.bavet.common.tuple.TupleLifecycle;
import ai.timefold.solver.core.impl.bavet.common.AbstractFlattenLastNode;
import ai.timefold.solver.core.impl.bavet.common.tuple.BiTuple;
import ai.timefold.solver.core.impl.bavet.common.tuple.TupleLifecycle;

final class FlattenLastBiNode<A, B, NewB> extends AbstractFlattenLastNode<BiTuple<A, B>, BiTuple<A, NewB>, B, NewB> {
public final class FlattenLastBiNode<A, B, NewB> extends AbstractFlattenLastNode<BiTuple<A, B>, BiTuple<A, NewB>, B, NewB> {

private final int outputStoreSize;

FlattenLastBiNode(int flattenLastStoreIndex, Function<B, Iterable<NewB>> mappingFunction,
public FlattenLastBiNode(int flattenLastStoreIndex, Function<B, Iterable<NewB>> mappingFunction,
TupleLifecycle<BiTuple<A, NewB>> nextNodesTupleLifecycle, int outputStoreSize) {
super(flattenLastStoreIndex, mappingFunction, nextNodesTupleLifecycle);
this.outputStoreSize = outputStoreSize;
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package ai.timefold.solver.core.impl.score.stream.bavet.bi;
package ai.timefold.solver.core.impl.bavet.bi;

import ai.timefold.solver.core.api.score.stream.bi.BiConstraintCollector;
import ai.timefold.solver.core.config.solver.EnvironmentMode;
import ai.timefold.solver.core.impl.score.stream.bavet.common.tuple.TupleLifecycle;
import ai.timefold.solver.core.impl.score.stream.bavet.common.tuple.UniTuple;
import ai.timefold.solver.core.impl.bavet.common.tuple.TupleLifecycle;
import ai.timefold.solver.core.impl.bavet.common.tuple.UniTuple;

final class Group0Mapping1CollectorBiNode<OldA, OldB, A, ResultContainer_>
public final class Group0Mapping1CollectorBiNode<OldA, OldB, A, ResultContainer_>
extends AbstractGroupBiNode<OldA, OldB, UniTuple<A>, Void, ResultContainer_, A> {

private final int outputStoreSize;
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package ai.timefold.solver.core.impl.score.stream.bavet.bi;
package ai.timefold.solver.core.impl.bavet.bi;

import ai.timefold.solver.core.api.score.stream.ConstraintCollectors;
import ai.timefold.solver.core.api.score.stream.bi.BiConstraintCollector;
import ai.timefold.solver.core.config.solver.EnvironmentMode;
import ai.timefold.solver.core.impl.score.stream.bavet.common.tuple.BiTuple;
import ai.timefold.solver.core.impl.score.stream.bavet.common.tuple.TupleLifecycle;
import ai.timefold.solver.core.impl.bavet.common.tuple.BiTuple;
import ai.timefold.solver.core.impl.bavet.common.tuple.TupleLifecycle;
import ai.timefold.solver.core.impl.util.Pair;

final class Group0Mapping2CollectorBiNode<OldA, OldB, A, B, ResultContainerA_, ResultContainerB_>
public final class Group0Mapping2CollectorBiNode<OldA, OldB, A, B, ResultContainerA_, ResultContainerB_>
extends AbstractGroupBiNode<OldA, OldB, BiTuple<A, B>, Void, Object, Pair<A, B>> {

private final int outputStoreSize;
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package ai.timefold.solver.core.impl.score.stream.bavet.bi;
package ai.timefold.solver.core.impl.bavet.bi;

import ai.timefold.solver.core.api.score.stream.ConstraintCollectors;
import ai.timefold.solver.core.api.score.stream.bi.BiConstraintCollector;
import ai.timefold.solver.core.config.solver.EnvironmentMode;
import ai.timefold.solver.core.impl.score.stream.bavet.common.tuple.TriTuple;
import ai.timefold.solver.core.impl.score.stream.bavet.common.tuple.TupleLifecycle;
import ai.timefold.solver.core.impl.bavet.common.tuple.TriTuple;
import ai.timefold.solver.core.impl.bavet.common.tuple.TupleLifecycle;
import ai.timefold.solver.core.impl.util.Triple;

final class Group0Mapping3CollectorBiNode<OldA, OldB, A, B, C, ResultContainerA_, ResultContainerB_, ResultContainerC_>
public final class Group0Mapping3CollectorBiNode<OldA, OldB, A, B, C, ResultContainerA_, ResultContainerB_, ResultContainerC_>
extends AbstractGroupBiNode<OldA, OldB, TriTuple<A, B, C>, Void, Object, Triple<A, B, C>> {

private final int outputStoreSize;
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package ai.timefold.solver.core.impl.score.stream.bavet.bi;
package ai.timefold.solver.core.impl.bavet.bi;

import ai.timefold.solver.core.api.score.stream.ConstraintCollectors;
import ai.timefold.solver.core.api.score.stream.bi.BiConstraintCollector;
import ai.timefold.solver.core.config.solver.EnvironmentMode;
import ai.timefold.solver.core.impl.score.stream.bavet.common.tuple.QuadTuple;
import ai.timefold.solver.core.impl.score.stream.bavet.common.tuple.TupleLifecycle;
import ai.timefold.solver.core.impl.bavet.common.tuple.QuadTuple;
import ai.timefold.solver.core.impl.bavet.common.tuple.TupleLifecycle;
import ai.timefold.solver.core.impl.util.Quadruple;

final class Group0Mapping4CollectorBiNode<OldA, OldB, A, B, C, D, ResultContainerA_, ResultContainerB_, ResultContainerC_, ResultContainerD_>
public final class Group0Mapping4CollectorBiNode<OldA, OldB, A, B, C, D, ResultContainerA_, ResultContainerB_, ResultContainerC_, ResultContainerD_>
extends
AbstractGroupBiNode<OldA, OldB, QuadTuple<A, B, C, D>, Void, Object, Quadruple<A, B, C, D>> {

Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package ai.timefold.solver.core.impl.score.stream.bavet.bi;
package ai.timefold.solver.core.impl.bavet.bi;

import java.util.function.BiFunction;

import ai.timefold.solver.core.config.solver.EnvironmentMode;
import ai.timefold.solver.core.impl.score.stream.bavet.common.tuple.BiTuple;
import ai.timefold.solver.core.impl.score.stream.bavet.common.tuple.TupleLifecycle;
import ai.timefold.solver.core.impl.score.stream.bavet.common.tuple.UniTuple;
import ai.timefold.solver.core.impl.bavet.common.tuple.BiTuple;
import ai.timefold.solver.core.impl.bavet.common.tuple.TupleLifecycle;
import ai.timefold.solver.core.impl.bavet.common.tuple.UniTuple;

final class Group1Mapping0CollectorBiNode<OldA, OldB, A>
public final class Group1Mapping0CollectorBiNode<OldA, OldB, A>
extends AbstractGroupBiNode<OldA, OldB, UniTuple<A>, A, Void, Void> {

private final int outputStoreSize;
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package ai.timefold.solver.core.impl.score.stream.bavet.bi;
package ai.timefold.solver.core.impl.bavet.bi;

import static ai.timefold.solver.core.impl.score.stream.bavet.bi.Group1Mapping0CollectorBiNode.createGroupKey;
import static ai.timefold.solver.core.impl.bavet.bi.Group1Mapping0CollectorBiNode.createGroupKey;

import java.util.function.BiFunction;

import ai.timefold.solver.core.api.score.stream.bi.BiConstraintCollector;
import ai.timefold.solver.core.config.solver.EnvironmentMode;
import ai.timefold.solver.core.impl.score.stream.bavet.common.tuple.BiTuple;
import ai.timefold.solver.core.impl.score.stream.bavet.common.tuple.TupleLifecycle;
import ai.timefold.solver.core.impl.bavet.common.tuple.BiTuple;
import ai.timefold.solver.core.impl.bavet.common.tuple.TupleLifecycle;

final class Group1Mapping1CollectorBiNode<OldA, OldB, A, B, ResultContainer_>
public final class Group1Mapping1CollectorBiNode<OldA, OldB, A, B, ResultContainer_>
extends AbstractGroupBiNode<OldA, OldB, BiTuple<A, B>, A, ResultContainer_, B> {

private final int outputStoreSize;
Loading