>) neighborhoodProviderClass;
}
/**
- * Part of {@link PreviewFeature#MOVE_STREAMS}.
+ * Part of {@link PreviewFeature#NEIGHBORHOODS}.
*/
@SuppressWarnings("rawtypes")
- public void setMoveProviderClass(@Nullable Class extends MoveProvider> moveProviderClass) {
- this.moveProviderClass = moveProviderClass;
+ public void setNeighborhoodProviderClass(@Nullable Class extends NeighborhoodProvider> neighborhoodProviderClass) {
+ this.neighborhoodProviderClass = neighborhoodProviderClass;
}
public @Nullable LocalSearchAcceptorConfig getAcceptorConfig() {
@@ -150,10 +150,11 @@ public void setForagerConfig(@Nullable LocalSearchForagerConfig foragerConfig) {
}
/**
- * Part of {@link PreviewFeature#MOVE_STREAMS}.
+ * Part of {@link PreviewFeature#NEIGHBORHOODS}.
*/
- public @NonNull LocalSearchPhaseConfig withMoveProviderClass(@NonNull Class extends MoveProvider>> moveProviderClass) {
- this.moveProviderClass = moveProviderClass;
+ public @NonNull LocalSearchPhaseConfig
+ withMoveProviderClass(@NonNull Class extends NeighborhoodProvider>> moveProviderClass) {
+ this.neighborhoodProviderClass = moveProviderClass;
return this;
}
@@ -174,8 +175,8 @@ public void setForagerConfig(@Nullable LocalSearchForagerConfig foragerConfig) {
inheritedConfig.getLocalSearchType());
setMoveSelectorConfig(ConfigUtils.inheritOverwritableProperty(
getMoveSelectorConfig(), inheritedConfig.getMoveSelectorConfig()));
- setMoveProviderClass(ConfigUtils.inheritOverwritableProperty(getMoveProviderClass(),
- inheritedConfig.getMoveProviderClass()));
+ setNeighborhoodProviderClass(ConfigUtils.inheritOverwritableProperty(getNeighborhoodProviderClass(),
+ inheritedConfig.getNeighborhoodProviderClass()));
acceptorConfig = ConfigUtils.inheritConfig(acceptorConfig, inheritedConfig.getAcceptorConfig());
foragerConfig = ConfigUtils.inheritConfig(foragerConfig, inheritedConfig.getForagerConfig());
return this;
@@ -194,8 +195,8 @@ public void visitReferencedClasses(@NonNull Consumer> classVisitor) {
if (moveSelectorConfig != null) {
moveSelectorConfig.visitReferencedClasses(classVisitor);
}
- if (moveProviderClass != null) {
- classVisitor.accept(moveProviderClass);
+ if (neighborhoodProviderClass != null) {
+ classVisitor.accept(neighborhoodProviderClass);
}
if (acceptorConfig != null) {
acceptorConfig.visitReferencedClasses(classVisitor);
diff --git a/core/src/main/java/ai/timefold/solver/core/config/solver/PreviewFeature.java b/core/src/main/java/ai/timefold/solver/core/config/solver/PreviewFeature.java
index 37c895f8b0..03632d91bc 100644
--- a/core/src/main/java/ai/timefold/solver/core/config/solver/PreviewFeature.java
+++ b/core/src/main/java/ai/timefold/solver/core/config/solver/PreviewFeature.java
@@ -7,31 +7,31 @@
* Any class, method, or field related to these features may change or be removed without prior notice,
* although we will strive to avoid this as much as possible.
* We encourage you to try these preview features and give us feedback on your experience with them.
- * Please direct your feedback to our Github Discussions.
+ * Please direct your feedback to
+ * Timefold Solver Github
+ * or to Timefold Discord.
*
*
* This list is not constant and is evolving over time,
* with items being added and removed without warning.
* It should not be treated as part of our public API,
* just like the preview features themselves.
- *
- * @see Timefold Solver Github Discussions
*/
public enum PreviewFeature {
DIVERSIFIED_LATE_ACCEPTANCE,
PLANNING_SOLUTION_DIFF,
/**
- * Unlike other preview features, Move Streams are an active research project.
+ * Unlike other preview features, Neighborhoods are an active research project.
* It is intended to simplify the creation of custom moves, eventually replacing move selectors.
* The component is under heavy development, entirely undocumented, and many key features are yet to be delivered.
* Neither the API nor the feature set are complete, and any part can change or be removed at any time.
*
- * Move Streams will eventually stabilize and be promoted from a research project to a true preview feature.
+ * Neighborhoods will eventually stabilize and be promoted from a research project to a true preview feature.
* We only expose it now to be able to use it for experimentation and testing.
* As such, it is an exception to the rule;
* this preview feature is not finished, and it is not yet ready for feedback.
*/
- MOVE_STREAMS
+ NEIGHBORHOODS
}
diff --git a/core/src/main/java/ai/timefold/solver/core/enterprise/TimefoldSolverEnterpriseService.java b/core/src/main/java/ai/timefold/solver/core/enterprise/TimefoldSolverEnterpriseService.java
index b2c0789c3b..13489dc0c5 100644
--- a/core/src/main/java/ai/timefold/solver/core/enterprise/TimefoldSolverEnterpriseService.java
+++ b/core/src/main/java/ai/timefold/solver/core/enterprise/TimefoldSolverEnterpriseService.java
@@ -31,7 +31,7 @@
import ai.timefold.solver.core.impl.localsearch.decider.LocalSearchDecider;
import ai.timefold.solver.core.impl.localsearch.decider.acceptor.Acceptor;
import ai.timefold.solver.core.impl.localsearch.decider.forager.LocalSearchForager;
-import ai.timefold.solver.core.impl.move.MoveRepository;
+import ai.timefold.solver.core.impl.neighborhood.MoveRepository;
import ai.timefold.solver.core.impl.partitionedsearch.PartitionedSearchPhase;
import ai.timefold.solver.core.impl.solver.termination.PhaseTermination;
import ai.timefold.solver.core.impl.solver.termination.SolverTermination;
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/constructionheuristic/DefaultConstructionHeuristicPhase.java b/core/src/main/java/ai/timefold/solver/core/impl/constructionheuristic/DefaultConstructionHeuristicPhase.java
index 07f4877fb8..9085c5638e 100644
--- a/core/src/main/java/ai/timefold/solver/core/impl/constructionheuristic/DefaultConstructionHeuristicPhase.java
+++ b/core/src/main/java/ai/timefold/solver/core/impl/constructionheuristic/DefaultConstructionHeuristicPhase.java
@@ -6,7 +6,7 @@
import ai.timefold.solver.core.impl.constructionheuristic.placer.EntityPlacer;
import ai.timefold.solver.core.impl.constructionheuristic.scope.ConstructionHeuristicPhaseScope;
import ai.timefold.solver.core.impl.constructionheuristic.scope.ConstructionHeuristicStepScope;
-import ai.timefold.solver.core.impl.move.PlacerBasedMoveRepository;
+import ai.timefold.solver.core.impl.neighborhood.PlacerBasedMoveRepository;
import ai.timefold.solver.core.impl.phase.AbstractPossiblyInitializingPhase;
import ai.timefold.solver.core.impl.solver.scope.SolverScope;
import ai.timefold.solver.core.impl.solver.termination.PhaseTermination;
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/domain/entity/descriptor/EntityDescriptor.java b/core/src/main/java/ai/timefold/solver/core/impl/domain/entity/descriptor/EntityDescriptor.java
index 790c0b8984..b49e018d32 100644
--- a/core/src/main/java/ai/timefold/solver/core/impl/domain/entity/descriptor/EntityDescriptor.java
+++ b/core/src/main/java/ai/timefold/solver/core/impl/domain/entity/descriptor/EntityDescriptor.java
@@ -67,7 +67,7 @@
import ai.timefold.solver.core.impl.heuristic.selector.common.decorator.SelectionSorter;
import ai.timefold.solver.core.impl.heuristic.selector.common.decorator.WeightFactorySelectionSorter;
import ai.timefold.solver.core.impl.move.director.MoveDirector;
-import ai.timefold.solver.core.impl.move.streams.maybeapi.UniDataFilter;
+import ai.timefold.solver.core.impl.neighborhood.maybeapi.stream.enumerating.function.UniEnumeratingFilter;
import ai.timefold.solver.core.impl.util.CollectionUtils;
import ai.timefold.solver.core.impl.util.MutableInt;
import ai.timefold.solver.core.preview.api.domain.metamodel.PlanningEntityMetaModel;
@@ -133,7 +133,7 @@ public class EntityDescriptor {
private List> effectiveGenuineVariableDescriptorList;
private List> effectiveGenuineListVariableDescriptorList;
- private final UniDataFilter entityMovablePredicate =
+ private final UniEnumeratingFilter entityMovablePredicate =
(solutionView, entity) -> {
var moveDirector = (MoveDirector) solutionView;
return !moveDirector.isPinned(this, entity);
@@ -639,8 +639,8 @@ public BiPredicate getEffectiveMovableEntityFilter() {
}
@SuppressWarnings("unchecked")
- public UniDataFilter getEntityMovablePredicate() {
- return (UniDataFilter) entityMovablePredicate;
+ public UniEnumeratingFilter getEntityMovablePredicate() {
+ return (UniEnumeratingFilter) entityMovablePredicate;
}
public SelectionSorter getDecreasingDifficultySorter() {
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/domain/solution/descriptor/DefaultPlanningEntityDiff.java b/core/src/main/java/ai/timefold/solver/core/impl/domain/solution/descriptor/DefaultPlanningEntityDiff.java
index 8767c47c44..2aa850f878 100644
--- a/core/src/main/java/ai/timefold/solver/core/impl/domain/solution/descriptor/DefaultPlanningEntityDiff.java
+++ b/core/src/main/java/ai/timefold/solver/core/impl/domain/solution/descriptor/DefaultPlanningEntityDiff.java
@@ -7,6 +7,7 @@
import java.util.Objects;
import java.util.stream.Collectors;
+import ai.timefold.solver.core.preview.api.domain.metamodel.GenuineVariableMetaModel;
import ai.timefold.solver.core.preview.api.domain.metamodel.PlanningEntityMetaModel;
import ai.timefold.solver.core.preview.api.domain.solution.diff.PlanningEntityDiff;
import ai.timefold.solver.core.preview.api.domain.solution.diff.PlanningSolutionDiff;
@@ -75,7 +76,8 @@ private static String entityDiffToString(PlanningEntityDiff, ?> entityDiff) {
}
return variableDiffs.stream()
.map(diff -> " %s (%s): %s -> %s".formatted(diff.variableMetaModel().name(),
- diff.variableMetaModel().isGenuine() ? "genuine" : "shadow", diff.oldValue(), diff.newValue()))
+ diff.variableMetaModel() instanceof GenuineVariableMetaModel, ?, ?> ? "genuine" : "shadow",
+ diff.oldValue(), diff.newValue()))
.collect(Collectors.joining(System.lineSeparator()));
}
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/domain/solution/descriptor/DefaultPlanningSolutionDiff.java b/core/src/main/java/ai/timefold/solver/core/impl/domain/solution/descriptor/DefaultPlanningSolutionDiff.java
index 121ba3e38a..a7f268880c 100644
--- a/core/src/main/java/ai/timefold/solver/core/impl/domain/solution/descriptor/DefaultPlanningSolutionDiff.java
+++ b/core/src/main/java/ai/timefold/solver/core/impl/domain/solution/descriptor/DefaultPlanningSolutionDiff.java
@@ -9,6 +9,7 @@
import java.util.Set;
import java.util.stream.Collectors;
+import ai.timefold.solver.core.preview.api.domain.metamodel.GenuineVariableMetaModel;
import ai.timefold.solver.core.preview.api.domain.metamodel.PlanningSolutionMetaModel;
import ai.timefold.solver.core.preview.api.domain.solution.diff.PlanningEntityDiff;
import ai.timefold.solver.core.preview.api.domain.solution.diff.PlanningSolutionDiff;
@@ -152,7 +153,8 @@ static String entityDiffToString(PlanningEntityDiff, ?> entityDiff) {
}
var variableDiffString = variableDiffs.stream()
.map(diff -> " %s (%s): %s -> %s".formatted(diff.variableMetaModel().name(),
- diff.variableMetaModel().isGenuine() ? "genuine" : "shadow", diff.oldValue(), diff.newValue()))
+ diff.variableMetaModel() instanceof GenuineVariableMetaModel, ?, ?> ? "genuine" : "shadow",
+ diff.oldValue(), diff.newValue()))
.collect(Collectors.joining(System.lineSeparator()));
return """
%s:
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/domain/solution/descriptor/DefaultPlanningVariableDiff.java b/core/src/main/java/ai/timefold/solver/core/impl/domain/solution/descriptor/DefaultPlanningVariableDiff.java
index 1f694bf0a9..ca56356d2a 100644
--- a/core/src/main/java/ai/timefold/solver/core/impl/domain/solution/descriptor/DefaultPlanningVariableDiff.java
+++ b/core/src/main/java/ai/timefold/solver/core/impl/domain/solution/descriptor/DefaultPlanningVariableDiff.java
@@ -2,6 +2,7 @@
import java.util.Objects;
+import ai.timefold.solver.core.preview.api.domain.metamodel.GenuineVariableMetaModel;
import ai.timefold.solver.core.preview.api.domain.metamodel.VariableMetaModel;
import ai.timefold.solver.core.preview.api.domain.solution.diff.PlanningEntityDiff;
import ai.timefold.solver.core.preview.api.domain.solution.diff.PlanningVariableDiff;
@@ -27,7 +28,10 @@ public String toString() {
Old value: %s
New value: %s
"""
- .formatted(variableMetaModel.isGenuine() ? "genuine" : "shadow", variableMetaModel.name(),
+ .formatted(
+ variableMetaModel instanceof GenuineVariableMetaModel ? "genuine"
+ : "shadow",
+ variableMetaModel.name(),
entityDiff.entity(), entityDiff.entityMetaModel().type(), oldValue, newValue);
}
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/ListVariableStateSupply.java b/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/ListVariableStateSupply.java
index 6d83a32923..421d89f23c 100644
--- a/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/ListVariableStateSupply.java
+++ b/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/ListVariableStateSupply.java
@@ -38,10 +38,8 @@
* which doesn't care whether the variable is internal or externalized.
*/
@NullMarked
-public interface ListVariableStateSupply extends
- SourcedListVariableListener,
- SingletonInverseVariableSupply,
- IndexVariableSupply {
+public interface ListVariableStateSupply
+ extends SourcedListVariableListener, SingletonInverseVariableSupply, IndexVariableSupply {
void externalize(IndexShadowVariableDescriptor shadowVariableDescriptor);
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/descriptor/ListVariableDescriptor.java b/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/descriptor/ListVariableDescriptor.java
index a217466c96..19aff357f0 100644
--- a/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/descriptor/ListVariableDescriptor.java
+++ b/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/descriptor/ListVariableDescriptor.java
@@ -15,7 +15,7 @@
import ai.timefold.solver.core.impl.domain.variable.ListVariableStateDemand;
import ai.timefold.solver.core.impl.domain.variable.inverserelation.InverseRelationShadowVariableDescriptor;
import ai.timefold.solver.core.impl.move.director.MoveDirector;
-import ai.timefold.solver.core.impl.move.streams.maybeapi.BiDataFilter;
+import ai.timefold.solver.core.impl.neighborhood.maybeapi.stream.enumerating.function.BiEnumeratingFilter;
public final class ListVariableDescriptor extends GenuineVariableDescriptor {
@@ -24,7 +24,7 @@ public final class ListVariableDescriptor extends GenuineVariableDesc
var list = getValue(entity);
return list.contains(element);
};
- private final BiDataFilter entityContainsPinnedValuePredicate =
+ private final BiEnumeratingFilter entityContainsPinnedValuePredicate =
(solutionView, value, entity) -> {
var moveDirector = (MoveDirector) solutionView;
return moveDirector.isPinned(this, value);
@@ -47,8 +47,8 @@ public BiPredicate getInListPredicate() {
}
@SuppressWarnings("unchecked")
- public BiDataFilter getEntityContainsPinnedValuePredicate() {
- return (BiDataFilter) entityContainsPinnedValuePredicate;
+ public BiEnumeratingFilter getEntityContainsPinnedValuePredicate() {
+ return (BiEnumeratingFilter) entityContainsPinnedValuePredicate;
}
public boolean allowsUnassignedValues() {
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/exhaustivesearch/DefaultExhaustiveSearchPhase.java b/core/src/main/java/ai/timefold/solver/core/impl/exhaustivesearch/DefaultExhaustiveSearchPhase.java
index 1a7eb8152c..eed7cf89bf 100644
--- a/core/src/main/java/ai/timefold/solver/core/impl/exhaustivesearch/DefaultExhaustiveSearchPhase.java
+++ b/core/src/main/java/ai/timefold/solver/core/impl/exhaustivesearch/DefaultExhaustiveSearchPhase.java
@@ -14,7 +14,7 @@
import ai.timefold.solver.core.impl.exhaustivesearch.scope.ExhaustiveSearchPhaseScope;
import ai.timefold.solver.core.impl.exhaustivesearch.scope.ExhaustiveSearchStepScope;
import ai.timefold.solver.core.impl.heuristic.selector.entity.EntitySelector;
-import ai.timefold.solver.core.impl.move.streams.maybeapi.generic.Moves;
+import ai.timefold.solver.core.impl.neighborhood.maybeapi.move.Moves;
import ai.timefold.solver.core.impl.phase.AbstractPhase;
import ai.timefold.solver.core.impl.solver.scope.SolverScope;
import ai.timefold.solver.core.impl.solver.termination.PhaseTermination;
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/exhaustivesearch/DefaultExhaustiveSearchPhaseFactory.java b/core/src/main/java/ai/timefold/solver/core/impl/exhaustivesearch/DefaultExhaustiveSearchPhaseFactory.java
index 9ab8668822..925340e6de 100644
--- a/core/src/main/java/ai/timefold/solver/core/impl/exhaustivesearch/DefaultExhaustiveSearchPhaseFactory.java
+++ b/core/src/main/java/ai/timefold/solver/core/impl/exhaustivesearch/DefaultExhaustiveSearchPhaseFactory.java
@@ -32,7 +32,7 @@
import ai.timefold.solver.core.impl.heuristic.selector.entity.mimic.ManualEntityMimicRecorder;
import ai.timefold.solver.core.impl.heuristic.selector.move.MoveSelector;
import ai.timefold.solver.core.impl.heuristic.selector.move.MoveSelectorFactory;
-import ai.timefold.solver.core.impl.move.MoveSelectorBasedMoveRepository;
+import ai.timefold.solver.core.impl.neighborhood.MoveSelectorBasedMoveRepository;
import ai.timefold.solver.core.impl.phase.AbstractPhaseFactory;
import ai.timefold.solver.core.impl.solver.recaller.BestSolutionRecaller;
import ai.timefold.solver.core.impl.solver.termination.PhaseTermination;
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/exhaustivesearch/decider/ExhaustiveSearchDecider.java b/core/src/main/java/ai/timefold/solver/core/impl/exhaustivesearch/decider/ExhaustiveSearchDecider.java
index 044f76eabb..e9388dac9d 100644
--- a/core/src/main/java/ai/timefold/solver/core/impl/exhaustivesearch/decider/ExhaustiveSearchDecider.java
+++ b/core/src/main/java/ai/timefold/solver/core/impl/exhaustivesearch/decider/ExhaustiveSearchDecider.java
@@ -7,7 +7,7 @@
import ai.timefold.solver.core.impl.exhaustivesearch.scope.ExhaustiveSearchPhaseScope;
import ai.timefold.solver.core.impl.exhaustivesearch.scope.ExhaustiveSearchStepScope;
import ai.timefold.solver.core.impl.heuristic.selector.entity.mimic.ManualEntityMimicRecorder;
-import ai.timefold.solver.core.impl.move.MoveRepository;
+import ai.timefold.solver.core.impl.neighborhood.MoveRepository;
import ai.timefold.solver.core.impl.phase.scope.SolverLifecyclePoint;
import ai.timefold.solver.core.impl.score.director.InnerScore;
import ai.timefold.solver.core.impl.solver.recaller.BestSolutionRecaller;
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/localsearch/DefaultLocalSearchPhaseFactory.java b/core/src/main/java/ai/timefold/solver/core/impl/localsearch/DefaultLocalSearchPhaseFactory.java
index 6d54affdb6..f020be068a 100644
--- a/core/src/main/java/ai/timefold/solver/core/impl/localsearch/DefaultLocalSearchPhaseFactory.java
+++ b/core/src/main/java/ai/timefold/solver/core/impl/localsearch/DefaultLocalSearchPhaseFactory.java
@@ -39,12 +39,14 @@
import ai.timefold.solver.core.impl.localsearch.decider.acceptor.AcceptorFactory;
import ai.timefold.solver.core.impl.localsearch.decider.forager.LocalSearchForager;
import ai.timefold.solver.core.impl.localsearch.decider.forager.LocalSearchForagerFactory;
-import ai.timefold.solver.core.impl.move.MoveRepository;
-import ai.timefold.solver.core.impl.move.MoveSelectorBasedMoveRepository;
-import ai.timefold.solver.core.impl.move.MoveStreamsBasedMoveRepository;
-import ai.timefold.solver.core.impl.move.streams.DefaultMoveStreamFactory;
-import ai.timefold.solver.core.impl.move.streams.InnerMoveProducer;
-import ai.timefold.solver.core.impl.move.streams.maybeapi.stream.MoveProvider;
+import ai.timefold.solver.core.impl.neighborhood.MoveRepository;
+import ai.timefold.solver.core.impl.neighborhood.MoveSelectorBasedMoveRepository;
+import ai.timefold.solver.core.impl.neighborhood.NeighborhoodsBasedMoveRepository;
+import ai.timefold.solver.core.impl.neighborhood.maybeapi.NeighborhoodProvider;
+import ai.timefold.solver.core.impl.neighborhood.move.InnerMoveStream;
+import ai.timefold.solver.core.impl.neighborhood.stream.DefaultMoveStreamFactory;
+import ai.timefold.solver.core.impl.neighborhood.stream.DefaultNeighborhood;
+import ai.timefold.solver.core.impl.neighborhood.stream.DefaultNeighborhoodBuilder;
import ai.timefold.solver.core.impl.phase.AbstractPhaseFactory;
import ai.timefold.solver.core.impl.solver.recaller.BestSolutionRecaller;
import ai.timefold.solver.core.impl.solver.termination.PhaseTermination;
@@ -61,19 +63,19 @@ public DefaultLocalSearchPhaseFactory(LocalSearchPhaseConfig phaseConfig) {
public LocalSearchPhase buildPhase(int phaseIndex, boolean lastInitializingPhase,
HeuristicConfigPolicy solverConfigPolicy, BestSolutionRecaller bestSolutionRecaller,
SolverTermination solverTermination) {
- var moveProviderClass = phaseConfig. getMoveProviderClass();
- var moveStreamsEnabled = moveProviderClass != null;
+ var neighborhoodProviderClass = phaseConfig. getNeighborhoodProviderClass();
+ var neighborhoodsEnabled = neighborhoodProviderClass != null;
var moveSelectorConfig = phaseConfig.getMoveSelectorConfig();
var moveSelectorsEnabled = moveSelectorConfig != null;
- if (moveSelectorsEnabled && moveStreamsEnabled) {
+ if (moveSelectorsEnabled && neighborhoodsEnabled) {
throw new UnsupportedOperationException("""
- The solver configuration enabled both move selectors and Move Streams.
+ The solver configuration enabled both move selectors and the Neighborhoods API.
These are mutually exclusive features, please pick one or the other.""");
}
var phaseConfigPolicy = solverConfigPolicy.createPhaseConfigPolicy();
var phaseTermination = buildPhaseTermination(phaseConfigPolicy, solverTermination);
- var decider = moveStreamsEnabled
- ? buildMoveStreamsBasedDecider(phaseConfigPolicy, phaseTermination, moveProviderClass)
+ var decider = neighborhoodsEnabled
+ ? buildNeighborhoodsBasedDecider(phaseConfigPolicy, phaseTermination, neighborhoodProviderClass)
: buildMoveSelectorBasedDecider(phaseConfigPolicy, phaseTermination);
return new DefaultLocalSearchPhase.Builder<>(phaseIndex, solverConfigPolicy.getLogIndentation(), phaseTermination,
decider)
@@ -87,26 +89,27 @@ private LocalSearchDecider buildMoveSelectorBasedDecider(HeuristicCon
return buildDecider(moveRepository, configPolicy, termination);
}
- private LocalSearchDecider buildMoveStreamsBasedDecider(HeuristicConfigPolicy configPolicy,
- PhaseTermination termination, Class extends MoveProvider> moveProviderClass) {
- configPolicy.ensurePreviewFeature(PreviewFeature.MOVE_STREAMS);
+ private LocalSearchDecider buildNeighborhoodsBasedDecider(HeuristicConfigPolicy configPolicy,
+ PhaseTermination termination,
+ Class extends NeighborhoodProvider> neighborhoodProviderClass) {
+ configPolicy.ensurePreviewFeature(PreviewFeature.NEIGHBORHOODS);
var solutionDescriptor = configPolicy.getSolutionDescriptor();
var solutionMetaModel = solutionDescriptor.getMetaModel();
if (solutionMetaModel.genuineEntities().size() > 1) {
throw new UnsupportedOperationException(
- "Move Streams currently only support solutions with a single entity class, not multiple.");
+ "Neighborhoods API currently only supports solutions with a single entity class, not multiple.");
}
var entityMetaModel = solutionMetaModel.genuineEntities().get(0);
if (entityMetaModel.genuineVariables().size() > 1) {
throw new UnsupportedOperationException(
- "Move Streams currently only support solutions with a single variable class, not multiple.");
+ "Neighborhoods API currently only supports solutions with a single variable class, not multiple.");
}
var variableMetaModel = entityMetaModel.genuineVariables().get(0);
if (variableMetaModel instanceof PlanningVariableMetaModel planningVariableMetaModel
&& planningVariableMetaModel.isChained()) {
throw new UnsupportedOperationException("""
- Move Streams don't support solutions with chained variables.
+ Neighborhoods API doesn't support solutions with chained variables.
Convert your model to use @%s instead."""
.formatted(PlanningListVariable.class.getSimpleName()));
}
@@ -115,29 +118,32 @@ private LocalSearchDecider buildMoveStreamsBasedDecider(HeuristicConf
.toList();
if (!entitiesWithPinningFilters.isEmpty()) {
throw new UnsupportedOperationException("""
- %s is deprecated and Move Streams do not support it.
+ %s is deprecated and Neighborhoods API does not support it.
Convert your entities (%s) to use @%s instead."""
.formatted(PinningFilter.class.getSimpleName(), entitiesWithPinningFilters,
PlanningPin.class.getSimpleName()));
}
- if (!MoveProvider.class.isAssignableFrom(moveProviderClass)) {
+ if (!NeighborhoodProvider.class.isAssignableFrom(neighborhoodProviderClass)) {
throw new IllegalArgumentException(
- "The moveProviderClass (%s) does not implement %s."
- .formatted(moveProviderClass, MoveProvider.class.getSimpleName()));
+ "The neighborhoodProviderClass (%s) does not implement %s."
+ .formatted(neighborhoodProviderClass, NeighborhoodProvider.class.getSimpleName()));
}
- var moveProvider =
- ConfigUtils.newInstance(LocalSearchPhaseConfig.class::getSimpleName, "moveProviderClass", moveProviderClass);
- var moveDefinitionList = moveProvider.defineMoves(solutionMetaModel);
+ var neighborhoodProvider =
+ ConfigUtils.newInstance(LocalSearchPhaseConfig.class::getSimpleName, "neighborhoodProviderClass",
+ neighborhoodProviderClass);
+ var neighborhoodBuilder = new DefaultNeighborhoodBuilder<>(solutionMetaModel);
+ var moveDefinitionList = ((DefaultNeighborhood) neighborhoodProvider.defineNeighborhood(neighborhoodBuilder))
+ .getMoveDefinitionList();
if (moveDefinitionList.size() != 1) {
throw new IllegalArgumentException(
- "The moveProviderClass (%s) must define exactly one MoveDefinition, not %s."
- .formatted(moveProviderClass, moveDefinitionList.size()));
+ "The neighborhoodProviderClass (%s) must define exactly one MoveDefinition, not %s."
+ .formatted(neighborhoodProviderClass, moveDefinitionList.size()));
}
var moveDefinition = moveDefinitionList.get(0);
var moveStreamFactory = new DefaultMoveStreamFactory<>(solutionDescriptor, configPolicy.getEnvironmentMode());
- var moveProducer = (InnerMoveProducer) moveDefinition.build(moveStreamFactory);
- var moveRepository = new MoveStreamsBasedMoveRepository<>(moveStreamFactory, moveProducer,
+ var moveStream = (InnerMoveStream) moveDefinition.build(moveStreamFactory);
+ var moveRepository = new NeighborhoodsBasedMoveRepository<>(moveStreamFactory, moveStream,
pickSelectionOrder() == SelectionOrder.RANDOM);
return buildDecider(moveRepository, configPolicy, termination);
@@ -145,7 +151,7 @@ Convert your entities (%s) to use @%s instead."""
private LocalSearchDecider buildDecider(MoveRepository moveRepository,
HeuristicConfigPolicy configPolicy, PhaseTermination termination) {
- var acceptor = buildAcceptor(configPolicy, moveRepository instanceof MoveStreamsBasedMoveRepository);
+ var acceptor = buildAcceptor(configPolicy, moveRepository instanceof NeighborhoodsBasedMoveRepository);
var forager = buildForager(configPolicy);
if (moveRepository.isNeverEnding() && !forager.supportsNeverEndingMoveSelector()) {
throw new IllegalStateException("""
@@ -164,7 +170,7 @@ The move repository (%s) is neverEnding (%s), but the forager (%s) does not supp
return decider;
}
- protected Acceptor buildAcceptor(HeuristicConfigPolicy configPolicy, boolean moveStreamsEnabled) {
+ protected Acceptor buildAcceptor(HeuristicConfigPolicy configPolicy, boolean neighborhoodsEnabled) {
var acceptorConfig = phaseConfig.getAcceptorConfig();
var localSearchType = phaseConfig.getLocalSearchType();
if (acceptorConfig != null) {
@@ -177,10 +183,10 @@ protected Acceptor buildAcceptor(HeuristicConfigPolicy con
} else {
var localSearchType_ = Objects.requireNonNullElse(localSearchType, LocalSearchType.LATE_ACCEPTANCE);
var acceptorConfig_ = new LocalSearchAcceptorConfig();
- if (moveStreamsEnabled && localSearchType_ == LocalSearchType.VARIABLE_NEIGHBORHOOD_DESCENT) {
+ if (neighborhoodsEnabled && localSearchType_ == LocalSearchType.VARIABLE_NEIGHBORHOOD_DESCENT) {
// Maybe works, but never tested.
throw new UnsupportedOperationException(
- "Variable Neighborhood descent is not yet supported with Move Streams.");
+ "Variable Neighborhood descent is not yet supported with the Neighborhoods API.");
}
var acceptorType = switch (localSearchType_) {
case HILL_CLIMBING, VARIABLE_NEIGHBORHOOD_DESCENT -> AcceptorType.HILL_CLIMBING;
@@ -190,8 +196,8 @@ protected Acceptor buildAcceptor(HeuristicConfigPolicy con
case DIVERSIFIED_LATE_ACCEPTANCE -> AcceptorType.DIVERSIFIED_LATE_ACCEPTANCE;
case GREAT_DELUGE -> AcceptorType.GREAT_DELUGE;
};
- if (moveStreamsEnabled && acceptorType.isTabu()) {
- throw new UnsupportedOperationException("Tabu search is not yet supported with Move Streams.");
+ if (neighborhoodsEnabled && acceptorType.isTabu()) {
+ throw new UnsupportedOperationException("Tabu search is not yet supported with the Neighborhoods API.");
}
acceptorConfig_.setAcceptorTypeList(Collections.singletonList(acceptorType));
return buildAcceptor(acceptorConfig_, configPolicy);
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/localsearch/decider/LocalSearchDecider.java b/core/src/main/java/ai/timefold/solver/core/impl/localsearch/decider/LocalSearchDecider.java
index 80215d7996..b5a5801bba 100644
--- a/core/src/main/java/ai/timefold/solver/core/impl/localsearch/decider/LocalSearchDecider.java
+++ b/core/src/main/java/ai/timefold/solver/core/impl/localsearch/decider/LocalSearchDecider.java
@@ -9,7 +9,7 @@
import ai.timefold.solver.core.impl.localsearch.scope.LocalSearchMoveScope;
import ai.timefold.solver.core.impl.localsearch.scope.LocalSearchPhaseScope;
import ai.timefold.solver.core.impl.localsearch.scope.LocalSearchStepScope;
-import ai.timefold.solver.core.impl.move.MoveRepository;
+import ai.timefold.solver.core.impl.neighborhood.MoveRepository;
import ai.timefold.solver.core.impl.phase.scope.SolverLifecyclePoint;
import ai.timefold.solver.core.impl.solver.scope.SolverScope;
import ai.timefold.solver.core.impl.solver.termination.PhaseTermination;
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/move/streams/DefaultBiFromBiMoveStream.java b/core/src/main/java/ai/timefold/solver/core/impl/move/streams/DefaultBiFromBiMoveStream.java
deleted file mode 100644
index b4e65aef88..0000000000
--- a/core/src/main/java/ai/timefold/solver/core/impl/move/streams/DefaultBiFromBiMoveStream.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package ai.timefold.solver.core.impl.move.streams;
-
-import java.util.Objects;
-
-import ai.timefold.solver.core.impl.move.streams.dataset.bi.BiDataset;
-import ai.timefold.solver.core.impl.move.streams.maybeapi.stream.BiMoveConstructor;
-import ai.timefold.solver.core.impl.move.streams.maybeapi.stream.BiMoveStream;
-import ai.timefold.solver.core.impl.move.streams.maybeapi.stream.MoveProducer;
-
-import org.jspecify.annotations.NullMarked;
-
-@NullMarked
-public final class DefaultBiFromBiMoveStream implements BiMoveStream {
-
- private final BiDataset dataset;
-
- public DefaultBiFromBiMoveStream(BiDataset dataset) {
- this.dataset = Objects.requireNonNull(dataset);
- }
-
- @Override
- public MoveProducer asMove(BiMoveConstructor moveConstructor) {
- return new FromBiUniMoveProducer<>(dataset, Objects.requireNonNull(moveConstructor));
- }
-
-}
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/move/streams/DefaultBiFromUnisMoveStream.java b/core/src/main/java/ai/timefold/solver/core/impl/move/streams/DefaultBiFromUnisMoveStream.java
deleted file mode 100644
index 7347f6d44b..0000000000
--- a/core/src/main/java/ai/timefold/solver/core/impl/move/streams/DefaultBiFromUnisMoveStream.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package ai.timefold.solver.core.impl.move.streams;
-
-import java.util.Objects;
-import java.util.function.BiPredicate;
-
-import ai.timefold.solver.core.impl.move.streams.dataset.uni.UniDataset;
-import ai.timefold.solver.core.impl.move.streams.maybeapi.stream.BiMoveConstructor;
-import ai.timefold.solver.core.impl.move.streams.maybeapi.stream.BiMoveStream;
-import ai.timefold.solver.core.impl.move.streams.maybeapi.stream.MoveProducer;
-
-import org.jspecify.annotations.NullMarked;
-
-@NullMarked
-public final class DefaultBiFromUnisMoveStream implements BiMoveStream {
-
- private final UniDataset leftDataset;
- private final UniDataset rightDataset;
- private final BiPredicate filter;
-
- public DefaultBiFromUnisMoveStream(UniDataset leftDataset, UniDataset rightDataset,
- BiPredicate filter) {
- this.leftDataset = Objects.requireNonNull(leftDataset);
- this.rightDataset = Objects.requireNonNull(rightDataset);
- this.filter = Objects.requireNonNull(filter);
- }
-
- @Override
- public MoveProducer asMove(BiMoveConstructor moveConstructor) {
- return new FromUniBiMoveProducer<>(leftDataset, rightDataset, filter, Objects.requireNonNull(moveConstructor));
- }
-
-}
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/move/streams/DefaultMoveStreamFactory.java b/core/src/main/java/ai/timefold/solver/core/impl/move/streams/DefaultMoveStreamFactory.java
deleted file mode 100644
index 7c8e9a84d0..0000000000
--- a/core/src/main/java/ai/timefold/solver/core/impl/move/streams/DefaultMoveStreamFactory.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package ai.timefold.solver.core.impl.move.streams;
-
-import ai.timefold.solver.core.config.solver.EnvironmentMode;
-import ai.timefold.solver.core.impl.domain.solution.descriptor.SolutionDescriptor;
-import ai.timefold.solver.core.impl.move.streams.dataset.DataStreamFactory;
-import ai.timefold.solver.core.impl.move.streams.dataset.DatasetSessionFactory;
-import ai.timefold.solver.core.impl.move.streams.dataset.bi.AbstractBiDataStream;
-import ai.timefold.solver.core.impl.move.streams.dataset.uni.AbstractUniDataStream;
-import ai.timefold.solver.core.impl.move.streams.maybeapi.DataJoiners;
-import ai.timefold.solver.core.impl.move.streams.maybeapi.stream.BiDataStream;
-import ai.timefold.solver.core.impl.move.streams.maybeapi.stream.BiMoveStream;
-import ai.timefold.solver.core.impl.move.streams.maybeapi.stream.MoveStreamFactory;
-import ai.timefold.solver.core.impl.move.streams.maybeapi.stream.UniDataStream;
-import ai.timefold.solver.core.impl.move.streams.maybeapi.stream.UniMoveStream;
-import ai.timefold.solver.core.impl.score.director.SessionContext;
-import ai.timefold.solver.core.preview.api.domain.metamodel.GenuineVariableMetaModel;
-import ai.timefold.solver.core.preview.api.domain.metamodel.PlanningListVariableMetaModel;
-import ai.timefold.solver.core.preview.api.domain.metamodel.PlanningVariableMetaModel;
-
-import org.jspecify.annotations.NullMarked;
-
-@NullMarked
-public final class DefaultMoveStreamFactory
- implements MoveStreamFactory {
-
- private final DataStreamFactory dataStreamFactory;
- private final DatasetSessionFactory datasetSessionFactory;
-
- public DefaultMoveStreamFactory(SolutionDescriptor solutionDescriptor, EnvironmentMode environmentMode) {
- this.dataStreamFactory = new DataStreamFactory<>(solutionDescriptor, environmentMode);
- this.datasetSessionFactory = new DatasetSessionFactory<>(dataStreamFactory);
- }
-
- public DefaultMoveStreamSession createSession(SessionContext context) {
- var session = datasetSessionFactory.buildSession(context);
- return new DefaultMoveStreamSession<>(session, context.solutionView());
- }
-
- @Override
- public UniDataStream forEach(Class sourceClass, boolean includeNull) {
- var entityDescriptor = getSolutionDescriptor().findEntityDescriptor(sourceClass);
- if (entityDescriptor == null) { // Not an entity, can't be pinned.
- return dataStreamFactory.forEachNonDiscriminating(sourceClass, includeNull);
- }
- if (entityDescriptor.isGenuine()) { // Genuine entity can be pinned.
- return dataStreamFactory.forEachExcludingPinned(sourceClass, includeNull);
- }
- // From now on, we are testing a shadow entity.
- var listVariableDescriptor = getSolutionDescriptor().getListVariableDescriptor();
- if (listVariableDescriptor == null) { // Can't be pinned when there are only basic variables.
- return dataStreamFactory.forEachNonDiscriminating(sourceClass, includeNull);
- }
- if (!listVariableDescriptor.supportsPinning()) { // The genuine entity does not support pinning.
- return dataStreamFactory.forEachNonDiscriminating(sourceClass, includeNull);
- }
- if (!listVariableDescriptor.acceptsValueType(sourceClass)) { // Can't be used as an element.
- return dataStreamFactory.forEachNonDiscriminating(sourceClass, includeNull);
- }
- // Finally a valid pin-supporting type.
- return dataStreamFactory.forEachExcludingPinned(sourceClass, includeNull);
- }
-
- @Override
- public UniDataStream forEachUnfiltered(Class sourceClass, boolean includeNull) {
- return dataStreamFactory.forEachNonDiscriminating(sourceClass, includeNull);
- }
-
- @Override
- public BiDataStream forEachEntityValuePair(
- GenuineVariableMetaModel variableMetaModel,
- UniDataStream entityDataStream) {
- var includeNull =
- variableMetaModel instanceof PlanningVariableMetaModel planningVariableMetaModel
- ? planningVariableMetaModel.allowsUnassigned()
- : variableMetaModel instanceof PlanningListVariableMetaModel planningListVariableMetaModel
- && planningListVariableMetaModel.allowsUnassignedValues();
- var stream = dataStreamFactory.forEachExcludingPinned(variableMetaModel.type(), includeNull);
- return entityDataStream.join(stream, DataJoiners. filtering(
- (solutionView, entity, value) -> solutionView.isValueInRange(variableMetaModel, entity, value)));
- }
-
- @Override
- public UniMoveStream pick(UniDataStream dataStream) {
- return new DefaultUniMoveStream<>(this,
- ((AbstractUniDataStream) dataStream).createDataset());
- }
-
- @Override
- public BiMoveStream pick(BiDataStream dataStream) {
- return new DefaultBiFromBiMoveStream<>(((AbstractBiDataStream) dataStream).createDataset());
- }
-
- public SolutionDescriptor getSolutionDescriptor() {
- return dataStreamFactory.getSolutionDescriptor();
- }
-
-}
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/move/streams/DefaultUniMoveStream.java b/core/src/main/java/ai/timefold/solver/core/impl/move/streams/DefaultUniMoveStream.java
deleted file mode 100644
index d976eb609d..0000000000
--- a/core/src/main/java/ai/timefold/solver/core/impl/move/streams/DefaultUniMoveStream.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package ai.timefold.solver.core.impl.move.streams;
-
-import java.util.Objects;
-import java.util.function.BiPredicate;
-
-import ai.timefold.solver.core.impl.move.streams.dataset.uni.AbstractUniDataStream;
-import ai.timefold.solver.core.impl.move.streams.dataset.uni.UniDataset;
-import ai.timefold.solver.core.impl.move.streams.maybeapi.stream.BiMoveStream;
-import ai.timefold.solver.core.impl.move.streams.maybeapi.stream.UniDataStream;
-
-import org.jspecify.annotations.NullMarked;
-
-@NullMarked
-public final class DefaultUniMoveStream implements InnerUniMoveStream {
-
- private final DefaultMoveStreamFactory moveStreamFactory;
- private final UniDataset dataset;
-
- public DefaultUniMoveStream(DefaultMoveStreamFactory moveStreamFactory, UniDataset dataset) {
- this.moveStreamFactory = Objects.requireNonNull(moveStreamFactory);
- this.dataset = Objects.requireNonNull(dataset);
- }
-
- @Override
- public BiMoveStream pick(UniDataStream uniDataStream, BiPredicate filter) {
- return new DefaultBiFromUnisMoveStream<>(dataset, ((AbstractUniDataStream) uniDataStream).createDataset(),
- filter);
- }
-
- @Override
- public UniDataset getDataset() {
- return dataset;
- }
-
-}
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/move/streams/InnerMoveProducer.java b/core/src/main/java/ai/timefold/solver/core/impl/move/streams/InnerMoveProducer.java
deleted file mode 100644
index cf17553ad1..0000000000
--- a/core/src/main/java/ai/timefold/solver/core/impl/move/streams/InnerMoveProducer.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package ai.timefold.solver.core.impl.move.streams;
-
-import java.util.Set;
-
-import ai.timefold.solver.core.impl.move.streams.dataset.common.AbstractDataStream;
-import ai.timefold.solver.core.impl.move.streams.maybeapi.stream.MoveProducer;
-import ai.timefold.solver.core.impl.move.streams.maybeapi.stream.MoveStreamSession;
-
-import org.jspecify.annotations.NullMarked;
-
-@NullMarked
-public interface InnerMoveProducer extends MoveProducer {
-
- @Override
- MoveIterable getMoveIterable(MoveStreamSession moveStreamSession);
-
- void collectActiveDataStreams(Set> activeDataStreamSet);
-
-}
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/move/streams/InnerMoveStream.java b/core/src/main/java/ai/timefold/solver/core/impl/move/streams/InnerMoveStream.java
deleted file mode 100644
index ff8cc117e6..0000000000
--- a/core/src/main/java/ai/timefold/solver/core/impl/move/streams/InnerMoveStream.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package ai.timefold.solver.core.impl.move.streams;
-
-import ai.timefold.solver.core.impl.bavet.common.tuple.AbstractTuple;
-import ai.timefold.solver.core.impl.move.streams.dataset.common.AbstractDataset;
-import ai.timefold.solver.core.impl.move.streams.maybeapi.stream.MoveStream;
-
-import org.jspecify.annotations.NullMarked;
-
-@NullMarked
-public interface InnerMoveStream extends MoveStream {
-
- AbstractDataset getDataset();
-
-}
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/move/streams/InnerUniMoveStream.java b/core/src/main/java/ai/timefold/solver/core/impl/move/streams/InnerUniMoveStream.java
deleted file mode 100644
index e842401dd4..0000000000
--- a/core/src/main/java/ai/timefold/solver/core/impl/move/streams/InnerUniMoveStream.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package ai.timefold.solver.core.impl.move.streams;
-
-import ai.timefold.solver.core.impl.bavet.common.tuple.UniTuple;
-import ai.timefold.solver.core.impl.move.streams.dataset.uni.UniDataset;
-import ai.timefold.solver.core.impl.move.streams.maybeapi.stream.UniMoveStream;
-
-import org.jspecify.annotations.NullMarked;
-
-@NullMarked
-public interface InnerUniMoveStream
- extends InnerMoveStream>, UniMoveStream {
-
- @Override
- UniDataset getDataset();
-
-}
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/move/streams/dataset/bi/AbstractBiDataStream.java b/core/src/main/java/ai/timefold/solver/core/impl/move/streams/dataset/bi/AbstractBiDataStream.java
deleted file mode 100644
index 04edf5f270..0000000000
--- a/core/src/main/java/ai/timefold/solver/core/impl/move/streams/dataset/bi/AbstractBiDataStream.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package ai.timefold.solver.core.impl.move.streams.dataset.bi;
-
-import java.util.function.BiFunction;
-
-import ai.timefold.solver.core.impl.bavet.bi.Group2Mapping0CollectorBiNode;
-import ai.timefold.solver.core.impl.bavet.common.GroupNodeConstructor;
-import ai.timefold.solver.core.impl.bavet.common.tuple.BiTuple;
-import ai.timefold.solver.core.impl.move.streams.dataset.DataStreamFactory;
-import ai.timefold.solver.core.impl.move.streams.dataset.common.AbstractDataStream;
-import ai.timefold.solver.core.impl.move.streams.dataset.common.bridge.AftBridgeBiDataStream;
-import ai.timefold.solver.core.impl.move.streams.dataset.common.bridge.AftBridgeUniDataStream;
-import ai.timefold.solver.core.impl.move.streams.maybeapi.BiDataFilter;
-import ai.timefold.solver.core.impl.move.streams.maybeapi.BiDataMapper;
-import ai.timefold.solver.core.impl.move.streams.maybeapi.stream.BiDataStream;
-import ai.timefold.solver.core.impl.move.streams.maybeapi.stream.UniDataStream;
-import ai.timefold.solver.core.impl.util.ConstantLambdaUtils;
-
-import org.jspecify.annotations.NullMarked;
-import org.jspecify.annotations.Nullable;
-
-@NullMarked
-public abstract class AbstractBiDataStream extends AbstractDataStream
- implements BiDataStream {
-
- protected AbstractBiDataStream(DataStreamFactory dataStreamFactory) {
- super(dataStreamFactory, null);
- }
-
- protected AbstractBiDataStream(DataStreamFactory dataStreamFactory,
- @Nullable AbstractDataStream parent) {
- super(dataStreamFactory, parent);
- }
-
- @Override
- public final BiDataStream filter(BiDataFilter filter) {
- return shareAndAddChild(new FilterBiDataStream<>(dataStreamFactory, this, filter));
- }
-
- protected AbstractBiDataStream
- groupBy(BiFunction groupKeyAMapping, BiFunction groupKeyBMapping) {
- GroupNodeConstructor> nodeConstructor =
- GroupNodeConstructor.twoKeysGroupBy(groupKeyAMapping, groupKeyBMapping, Group2Mapping0CollectorBiNode::new);
- return buildBiGroupBy(nodeConstructor);
- }
-
- private AbstractBiDataStream
- buildBiGroupBy(GroupNodeConstructor> nodeConstructor) {
- var stream = shareAndAddChild(new BiGroupBiDataStream<>(dataStreamFactory, this, nodeConstructor));
- return dataStreamFactory.share(new AftBridgeBiDataStream<>(dataStreamFactory, stream), stream::setAftBridge);
- }
-
- @Override
- public UniDataStream map(BiDataMapper mapping) {
- var stream = shareAndAddChild(new UniMapBiDataStream<>(dataStreamFactory, this, mapping));
- return dataStreamFactory.share(new AftBridgeUniDataStream<>(dataStreamFactory, stream), stream::setAftBridge);
- }
-
- @Override
- public BiDataStream
- map(BiDataMapper mappingA, BiDataMapper mappingB) {
- var stream = shareAndAddChild(new BiMapBiDataStream<>(dataStreamFactory, this, mappingA, mappingB));
- return dataStreamFactory.share(new AftBridgeBiDataStream<>(dataStreamFactory, stream), stream::setAftBridge);
- }
-
- @Override
- public AbstractBiDataStream distinct() {
- if (guaranteesDistinct()) {
- return this; // Already distinct, no need to create a new stream.
- }
- return groupBy(ConstantLambdaUtils.biPickFirst(), ConstantLambdaUtils.biPickSecond());
- }
-
- public BiDataset createDataset() {
- var stream = shareAndAddChild(new TerminalBiDataStream<>(dataStreamFactory, this));
- return stream.getDataset();
- }
-
-}
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/move/streams/dataset/bi/BiDataset.java b/core/src/main/java/ai/timefold/solver/core/impl/move/streams/dataset/bi/BiDataset.java
deleted file mode 100644
index 72a3667dbe..0000000000
--- a/core/src/main/java/ai/timefold/solver/core/impl/move/streams/dataset/bi/BiDataset.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package ai.timefold.solver.core.impl.move.streams.dataset.bi;
-
-import ai.timefold.solver.core.impl.bavet.common.tuple.BiTuple;
-import ai.timefold.solver.core.impl.move.streams.dataset.DataStreamFactory;
-import ai.timefold.solver.core.impl.move.streams.dataset.common.AbstractDataset;
-
-import org.jspecify.annotations.NullMarked;
-
-@NullMarked
-public final class BiDataset extends AbstractDataset> {
-
- public BiDataset(DataStreamFactory dataStreamFactory, AbstractBiDataStream parent) {
- super(dataStreamFactory, parent);
- }
-
- @Override
- public BiDatasetInstance instantiate(int storeIndex) {
- return new BiDatasetInstance<>(this, storeIndex);
- }
-
-}
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/move/streams/dataset/bi/TerminalBiDataStream.java b/core/src/main/java/ai/timefold/solver/core/impl/move/streams/dataset/bi/TerminalBiDataStream.java
deleted file mode 100644
index 55c305dfa2..0000000000
--- a/core/src/main/java/ai/timefold/solver/core/impl/move/streams/dataset/bi/TerminalBiDataStream.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package ai.timefold.solver.core.impl.move.streams.dataset.bi;
-
-import ai.timefold.solver.core.impl.bavet.common.tuple.BiTuple;
-import ai.timefold.solver.core.impl.move.streams.dataset.DataStreamFactory;
-import ai.timefold.solver.core.impl.move.streams.dataset.common.DataNodeBuildHelper;
-import ai.timefold.solver.core.impl.move.streams.dataset.common.TerminalDataStream;
-
-import org.jspecify.annotations.NullMarked;
-
-@NullMarked
-final class TerminalBiDataStream
- extends AbstractBiDataStream
- implements TerminalDataStream, BiDataset> {
-
- private final BiDataset dataset;
-
- public TerminalBiDataStream(DataStreamFactory dataStreamFactory, AbstractBiDataStream parent) {
- super(dataStreamFactory, parent);
- this.dataset = new BiDataset<>(dataStreamFactory, this);
- }
-
- @Override
- public void buildNode(DataNodeBuildHelper buildHelper) {
- assertEmptyChildStreamList();
- var inputStoreIndex = buildHelper.reserveTupleStoreIndex(parent.getTupleSource());
- buildHelper.putInsertUpdateRetract(this, dataset.instantiate(inputStoreIndex));
- }
-
- @Override
- public BiDataset getDataset() {
- return dataset;
- }
-
- @Override
- public String toString() {
- return "Terminal node";
- }
-
-}
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/move/streams/dataset/common/AbstractDataset.java b/core/src/main/java/ai/timefold/solver/core/impl/move/streams/dataset/common/AbstractDataset.java
deleted file mode 100644
index 99fb5a8bfc..0000000000
--- a/core/src/main/java/ai/timefold/solver/core/impl/move/streams/dataset/common/AbstractDataset.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package ai.timefold.solver.core.impl.move.streams.dataset.common;
-
-import java.util.Objects;
-import java.util.Set;
-
-import ai.timefold.solver.core.impl.bavet.common.tuple.AbstractTuple;
-import ai.timefold.solver.core.impl.move.streams.dataset.DataStreamFactory;
-
-import org.jspecify.annotations.NullMarked;
-
-@NullMarked
-public abstract class AbstractDataset {
-
- private final DataStreamFactory dataStreamFactory;
- private final AbstractDataStream parent;
-
- protected AbstractDataset(DataStreamFactory dataStreamFactory, AbstractDataStream parent) {
- this.dataStreamFactory = Objects.requireNonNull(dataStreamFactory);
- this.parent = Objects.requireNonNull(parent);
- }
-
- public void collectActiveDataStreams(Set> dataStreamSet) {
- parent.collectActiveDataStreams(dataStreamSet);
- }
-
- public abstract AbstractDatasetInstance instantiate(int storeIndex);
-
- public DataStreamFactory getDataStreamFactory() {
- return dataStreamFactory;
- }
-
- @Override
- public boolean equals(Object entity) {
- if (!(entity instanceof AbstractDataset, ?> dataset)) {
- return false;
- }
- return Objects.equals(dataStreamFactory, dataset.dataStreamFactory) && Objects.equals(parent, dataset.parent);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(dataStreamFactory, parent);
- }
-
- @Override
- public String toString() {
- return "%s for %s".formatted(getClass().getSimpleName(), parent);
- }
-}
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/move/streams/dataset/common/DataStreamBinaryOperation.java b/core/src/main/java/ai/timefold/solver/core/impl/move/streams/dataset/common/DataStreamBinaryOperation.java
deleted file mode 100644
index afc1e298c7..0000000000
--- a/core/src/main/java/ai/timefold/solver/core/impl/move/streams/dataset/common/DataStreamBinaryOperation.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package ai.timefold.solver.core.impl.move.streams.dataset.common;
-
-import ai.timefold.solver.core.impl.bavet.common.BavetStreamBinaryOperation;
-
-import org.jspecify.annotations.NullMarked;
-
-@NullMarked
-public sealed interface DataStreamBinaryOperation
- extends BavetStreamBinaryOperation>
- permits IfExistsDataStream, JoinDataStream {
-
-}
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/move/streams/dataset/common/IfExistsDataStream.java b/core/src/main/java/ai/timefold/solver/core/impl/move/streams/dataset/common/IfExistsDataStream.java
deleted file mode 100644
index d1dc71b8ee..0000000000
--- a/core/src/main/java/ai/timefold/solver/core/impl/move/streams/dataset/common/IfExistsDataStream.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package ai.timefold.solver.core.impl.move.streams.dataset.common;
-
-import org.jspecify.annotations.NullMarked;
-
-@NullMarked
-public non-sealed interface IfExistsDataStream extends DataStreamBinaryOperation {
-
-}
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/move/streams/dataset/common/JoinDataStream.java b/core/src/main/java/ai/timefold/solver/core/impl/move/streams/dataset/common/JoinDataStream.java
deleted file mode 100644
index ce69fbd739..0000000000
--- a/core/src/main/java/ai/timefold/solver/core/impl/move/streams/dataset/common/JoinDataStream.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package ai.timefold.solver.core.impl.move.streams.dataset.common;
-
-import ai.timefold.solver.core.impl.bavet.common.TupleSource;
-
-import org.jspecify.annotations.NullMarked;
-
-@NullMarked
-public non-sealed interface JoinDataStream
- extends DataStreamBinaryOperation, TupleSource {
-
-}
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/move/streams/dataset/common/TerminalDataStream.java b/core/src/main/java/ai/timefold/solver/core/impl/move/streams/dataset/common/TerminalDataStream.java
deleted file mode 100644
index ad31999df4..0000000000
--- a/core/src/main/java/ai/timefold/solver/core/impl/move/streams/dataset/common/TerminalDataStream.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package ai.timefold.solver.core.impl.move.streams.dataset.common;
-
-import ai.timefold.solver.core.impl.bavet.common.tuple.AbstractTuple;
-
-import org.jspecify.annotations.NullMarked;
-
-@NullMarked
-public interface TerminalDataStream> {
-
- Dataset_ getDataset();
-
-}
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/move/streams/dataset/common/bridge/AftBridgeBiDataStream.java b/core/src/main/java/ai/timefold/solver/core/impl/move/streams/dataset/common/bridge/AftBridgeBiDataStream.java
deleted file mode 100644
index 343624b86c..0000000000
--- a/core/src/main/java/ai/timefold/solver/core/impl/move/streams/dataset/common/bridge/AftBridgeBiDataStream.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package ai.timefold.solver.core.impl.move.streams.dataset.common.bridge;
-
-import java.util.Objects;
-
-import ai.timefold.solver.core.impl.bavet.common.TupleSource;
-import ai.timefold.solver.core.impl.move.streams.dataset.DataStreamFactory;
-import ai.timefold.solver.core.impl.move.streams.dataset.bi.AbstractBiDataStream;
-import ai.timefold.solver.core.impl.move.streams.dataset.common.AbstractDataStream;
-import ai.timefold.solver.core.impl.move.streams.dataset.common.DataNodeBuildHelper;
-
-import org.jspecify.annotations.NullMarked;
-
-@NullMarked
-public final class AftBridgeBiDataStream
- extends AbstractBiDataStream
- implements TupleSource {
-
- public AftBridgeBiDataStream(DataStreamFactory dataStreamFactory, AbstractDataStream parent) {
- super(dataStreamFactory, parent);
- }
-
- @Override
- public void buildNode(DataNodeBuildHelper buildHelper) {
- // Do nothing. The parent stream builds everything.
- }
-
- @Override
- public boolean equals(Object o) {
- return o instanceof AftBridgeBiDataStream, ?, ?> that && Objects.equals(parent, that.parent);
- }
-
- @Override
- public int hashCode() {
- return Objects.requireNonNull(parent).hashCode();
- }
-
- @Override
- public String toString() {
- return "Bridge from " + parent + " with " + childStreamList.size() + " children";
- }
-
-}
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/move/streams/dataset/common/bridge/AftBridgeUniDataStream.java b/core/src/main/java/ai/timefold/solver/core/impl/move/streams/dataset/common/bridge/AftBridgeUniDataStream.java
deleted file mode 100644
index ed50b5119f..0000000000
--- a/core/src/main/java/ai/timefold/solver/core/impl/move/streams/dataset/common/bridge/AftBridgeUniDataStream.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package ai.timefold.solver.core.impl.move.streams.dataset.common.bridge;
-
-import java.util.Objects;
-
-import ai.timefold.solver.core.impl.bavet.common.TupleSource;
-import ai.timefold.solver.core.impl.move.streams.dataset.DataStreamFactory;
-import ai.timefold.solver.core.impl.move.streams.dataset.common.AbstractDataStream;
-import ai.timefold.solver.core.impl.move.streams.dataset.common.DataNodeBuildHelper;
-import ai.timefold.solver.core.impl.move.streams.dataset.uni.AbstractUniDataStream;
-
-import org.jspecify.annotations.NullMarked;
-
-@NullMarked
-public final class AftBridgeUniDataStream
- extends AbstractUniDataStream
- implements TupleSource {
-
- public AftBridgeUniDataStream(DataStreamFactory dataStreamFactory, AbstractDataStream parent) {
- super(dataStreamFactory, parent);
- }
-
- @Override
- public void buildNode(DataNodeBuildHelper buildHelper) {
- // Do nothing. The parent stream builds everything.
- }
-
- @Override
- public boolean equals(Object o) {
- return o instanceof AftBridgeUniDataStream, ?> that && Objects.equals(parent, that.parent);
- }
-
- @Override
- public int hashCode() {
- return Objects.requireNonNull(parent).hashCode();
- }
-
- @Override
- public String toString() {
- return "Bridge from " + parent + " with " + childStreamList.size() + " children";
- }
-
-}
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/move/streams/dataset/common/bridge/ForeBridgeUniDataStream.java b/core/src/main/java/ai/timefold/solver/core/impl/move/streams/dataset/common/bridge/ForeBridgeUniDataStream.java
deleted file mode 100644
index 8a4c42e801..0000000000
--- a/core/src/main/java/ai/timefold/solver/core/impl/move/streams/dataset/common/bridge/ForeBridgeUniDataStream.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package ai.timefold.solver.core.impl.move.streams.dataset.common.bridge;
-
-import ai.timefold.solver.core.impl.move.streams.dataset.DataStreamFactory;
-import ai.timefold.solver.core.impl.move.streams.dataset.common.AbstractDataStream;
-import ai.timefold.solver.core.impl.move.streams.dataset.common.DataNodeBuildHelper;
-import ai.timefold.solver.core.impl.move.streams.dataset.uni.AbstractUniDataStream;
-import ai.timefold.solver.core.impl.move.streams.maybeapi.stream.UniDataStream;
-
-import org.jspecify.annotations.NullMarked;
-
-@NullMarked
-public final class ForeBridgeUniDataStream
- extends AbstractUniDataStream
- implements UniDataStream {
-
- public ForeBridgeUniDataStream(DataStreamFactory dataStreamFactory, AbstractDataStream parent) {
- super(dataStreamFactory, parent);
- }
-
- @Override
- public void buildNode(DataNodeBuildHelper buildHelper) {
- // Do nothing. The child stream builds everything.
- }
-
- @Override
- public String toString() {
- return "Generic bridge";
- }
-
-}
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/move/streams/dataset/joiner/FilteringBiDataJoiner.java b/core/src/main/java/ai/timefold/solver/core/impl/move/streams/dataset/joiner/FilteringBiDataJoiner.java
deleted file mode 100644
index ff2d157381..0000000000
--- a/core/src/main/java/ai/timefold/solver/core/impl/move/streams/dataset/joiner/FilteringBiDataJoiner.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package ai.timefold.solver.core.impl.move.streams.dataset.joiner;
-
-import ai.timefold.solver.core.impl.move.streams.maybeapi.BiDataFilter;
-import ai.timefold.solver.core.impl.move.streams.maybeapi.BiDataJoiner;
-
-import org.jspecify.annotations.NullMarked;
-
-@NullMarked
-public record FilteringBiDataJoiner(BiDataFilter filter) implements BiDataJoiner {
-
- @Override
- public FilteringBiDataJoiner and(BiDataJoiner otherJoiner) {
- FilteringBiDataJoiner castJoiner = (FilteringBiDataJoiner) otherJoiner;
- return new FilteringBiDataJoiner<>(filter.and(castJoiner.filter()));
- }
-
-}
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/move/streams/dataset/uni/AbstractUniDataStream.java b/core/src/main/java/ai/timefold/solver/core/impl/move/streams/dataset/uni/AbstractUniDataStream.java
deleted file mode 100644
index 430fda1502..0000000000
--- a/core/src/main/java/ai/timefold/solver/core/impl/move/streams/dataset/uni/AbstractUniDataStream.java
+++ /dev/null
@@ -1,152 +0,0 @@
-package ai.timefold.solver.core.impl.move.streams.dataset.uni;
-
-import static ai.timefold.solver.core.impl.bavet.common.GroupNodeConstructor.oneKeyGroupBy;
-
-import java.util.Objects;
-import java.util.function.Function;
-
-import ai.timefold.solver.core.impl.bavet.common.GroupNodeConstructor;
-import ai.timefold.solver.core.impl.bavet.common.tuple.UniTuple;
-import ai.timefold.solver.core.impl.bavet.uni.Group1Mapping0CollectorUniNode;
-import ai.timefold.solver.core.impl.move.streams.dataset.DataStreamFactory;
-import ai.timefold.solver.core.impl.move.streams.dataset.bi.JoinBiDataStream;
-import ai.timefold.solver.core.impl.move.streams.dataset.common.AbstractDataStream;
-import ai.timefold.solver.core.impl.move.streams.dataset.common.bridge.AftBridgeBiDataStream;
-import ai.timefold.solver.core.impl.move.streams.dataset.common.bridge.AftBridgeUniDataStream;
-import ai.timefold.solver.core.impl.move.streams.dataset.common.bridge.ForeBridgeUniDataStream;
-import ai.timefold.solver.core.impl.move.streams.dataset.joiner.BiDataJoinerComber;
-import ai.timefold.solver.core.impl.move.streams.maybeapi.BiDataJoiner;
-import ai.timefold.solver.core.impl.move.streams.maybeapi.UniDataFilter;
-import ai.timefold.solver.core.impl.move.streams.maybeapi.UniDataMapper;
-import ai.timefold.solver.core.impl.move.streams.maybeapi.stream.BiDataStream;
-import ai.timefold.solver.core.impl.move.streams.maybeapi.stream.UniDataStream;
-import ai.timefold.solver.core.impl.util.ConstantLambdaUtils;
-
-import org.jspecify.annotations.NullMarked;
-import org.jspecify.annotations.Nullable;
-
-@NullMarked
-public abstract class AbstractUniDataStream extends AbstractDataStream
- implements UniDataStream {
-
- protected AbstractUniDataStream(DataStreamFactory dataStreamFactory) {
- super(dataStreamFactory, null);
- }
-
- protected AbstractUniDataStream(DataStreamFactory dataStreamFactory,
- @Nullable AbstractDataStream parent) {
- super(dataStreamFactory, parent);
- }
-
- @Override
- public final UniDataStream filter(UniDataFilter filter) {
- return shareAndAddChild(new FilterUniDataStream<>(dataStreamFactory, this, filter));
- }
-
- @Override
- public BiDataStream join(UniDataStream otherStream, BiDataJoiner... joiners) {
- var other = (AbstractUniDataStream) otherStream;
- var leftBridge = new ForeBridgeUniDataStream(dataStreamFactory, this);
- var rightBridge = new ForeBridgeUniDataStream(dataStreamFactory, other);
- var joinerComber = BiDataJoinerComber. comb(joiners);
- var joinStream = new JoinBiDataStream<>(dataStreamFactory, leftBridge, rightBridge,
- joinerComber.mergedJoiner(), joinerComber.mergedFiltering());
- return dataStreamFactory.share(joinStream, joinStream_ -> {
- // Connect the bridges upstream, as it is an actual new join.
- getChildStreamList().add(leftBridge);
- other.getChildStreamList().add(rightBridge);
- });
- }
-
- @Override
- public BiDataStream join(Class otherClass, BiDataJoiner... joiners) {
- return join(dataStreamFactory.forEachNonDiscriminating(otherClass, false), joiners);
- }
-
- @SafeVarargs
- @Override
- public final UniDataStream ifExists(Class otherClass, BiDataJoiner... joiners) {
- return ifExists(dataStreamFactory.forEachNonDiscriminating(otherClass, false), joiners);
- }
-
- @SafeVarargs
- @Override
- public final UniDataStream ifExists(UniDataStream otherStream,
- BiDataJoiner... joiners) {
- return ifExistsOrNot(true, otherStream, joiners);
- }
-
- @SafeVarargs
- @Override
- public final UniDataStream ifNotExists(Class otherClass, BiDataJoiner... joiners) {
- return ifExistsOrNot(false, dataStreamFactory.forEachNonDiscriminating(otherClass, false), joiners);
- }
-
- @SafeVarargs
- @Override
- public final UniDataStream ifNotExists(UniDataStream otherStream,
- BiDataJoiner