org.optaplanner.constraint.streams.bavet.common.NodeBuildHelper Maven / Gradle / Ivy
package org.optaplanner.constraint.streams.bavet.common;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import org.optaplanner.constraint.streams.common.AbstractConstraintStream;
import org.optaplanner.constraint.streams.common.inliner.AbstractScoreInliner;
import org.optaplanner.core.api.score.Score;
import org.optaplanner.core.api.score.stream.Constraint;
import org.optaplanner.core.api.score.stream.ConstraintStream;
public final class NodeBuildHelper> {
private final Set extends ConstraintStream> activeStreamSet;
private final Map constraintWeightMap;
private final AbstractScoreInliner scoreInliner;
private final Map> tupleLifecycleMap;
private final Map storeIndexMap;
private List reversedNodeList;
public NodeBuildHelper(Set extends ConstraintStream> activeStreamSet, Map constraintWeightMap,
AbstractScoreInliner scoreInliner) {
this.activeStreamSet = activeStreamSet;
this.constraintWeightMap = constraintWeightMap;
this.scoreInliner = scoreInliner;
int activeStreamSetSize = activeStreamSet.size();
this.tupleLifecycleMap = new HashMap<>(Math.max(16, activeStreamSetSize));
this.storeIndexMap = new HashMap<>(Math.max(16, activeStreamSetSize / 2));
this.reversedNodeList = new ArrayList<>(activeStreamSetSize);
}
public boolean isStreamActive(ConstraintStream stream) {
return activeStreamSet.contains(stream);
}
public AbstractScoreInliner getScoreInliner() {
return scoreInliner;
}
public Score_ getConstraintWeight(Constraint constraint) {
return constraintWeightMap.get(constraint);
}
public void addNode(AbstractNode node) {
reversedNodeList.add(node);
}
public void addNode(AbstractNode node, ConstraintStream parent) {
addNode(node);
putInsertUpdateRetract(parent, (TupleLifecycle extends Tuple>) node);
}
public void addNode(AbstractNode node, ConstraintStream leftParent, ConstraintStream rightParent) {
addNode(node);
putInsertUpdateRetract(leftParent, TupleLifecycle.ofLeft((LeftTupleLifecycle extends Tuple>) node));
putInsertUpdateRetract(rightParent, TupleLifecycle.ofRight((RightTupleLifecycle extends Tuple>) node));
}
public void putInsertUpdateRetract(ConstraintStream stream, TupleLifecycle tupleLifecycle) {
tupleLifecycleMap.put(stream, tupleLifecycle);
}
public void putInsertUpdateRetract(ConstraintStream stream,
List extends AbstractConstraintStream> childStreamList,
Function, AbstractConditionalTupleLifecycle> tupleLifecycleFunction) {
TupleLifecycle tupleLifecycle = getAggregatedTupleLifecycle(childStreamList);
putInsertUpdateRetract(stream, tupleLifecycleFunction.apply(tupleLifecycle));
}
public TupleLifecycle getAggregatedTupleLifecycle(
List extends ConstraintStream> streamList) {
TupleLifecycle[] tupleLifecycles = streamList.stream()
.filter(this::isStreamActive)
.map(s -> getTupleLifecycle(s, tupleLifecycleMap))
.toArray(TupleLifecycle[]::new);
switch (tupleLifecycles.length) {
case 0:
throw new IllegalStateException("Impossible state: None of the streamList (" + streamList
+ ") are active.");
case 1:
return tupleLifecycles[0];
default:
return new AggregatedTupleLifecycle<>(tupleLifecycles);
}
}
private static TupleLifecycle getTupleLifecycle(ConstraintStream stream,
Map> tupleLifecycleMap) {
TupleLifecycle tupleLifecycle = (TupleLifecycle) tupleLifecycleMap.get(stream);
if (tupleLifecycle == null) {
throw new IllegalStateException("Impossible state: the stream (" + stream + ") hasn't built a node yet.");
}
return tupleLifecycle;
}
public int reserveTupleStoreIndex(ConstraintStream tupleSourceStream) {
return storeIndexMap.compute(tupleSourceStream, (k, index) -> {
if (index == null) {
return 0;
} else if (index < 0) {
throw new IllegalStateException("Impossible state: the tupleSourceStream (" + k
+ ") is reserving a store after it has been extracted.");
} else {
return index + 1;
}
});
}
public int extractTupleStoreSize(ConstraintStream tupleSourceStream) {
Integer lastIndex = storeIndexMap.put(tupleSourceStream, Integer.MIN_VALUE);
return (lastIndex == null) ? 0 : lastIndex + 1;
}
public List destroyAndGetNodeList() {
List nodeList = this.reversedNodeList;
Collections.reverse(nodeList);
this.reversedNodeList = null;
return nodeList;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy