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

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
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
Expand Up @@ -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;
Expand Down
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.
Expand All @@ -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]);

Expand All @@ -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();
Expand Down
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_> {
Expand Down
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);
Expand Down
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);
Expand Down
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,
Expand Down
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;
Expand Down
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;
Expand Down
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;
Expand Down
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;
Expand Down
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>> {

Expand Down
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;
Expand Down
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;
Expand Down
Loading
Loading