org.optaplanner.examples.common.experimental.ExperimentalConstraintCollectors Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of optaplanner-examples Show documentation
Show all versions of optaplanner-examples Show documentation
OptaPlanner solves planning problems.
This lightweight, embeddable planning engine implements powerful and scalable algorithms
to optimize business resource scheduling and planning.
This module contains the examples which demonstrate how to use it in a normal Java application.
package org.optaplanner.examples.common.experimental;
import java.time.Duration;
import java.time.temporal.Temporal;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;
import org.optaplanner.core.api.function.PentaFunction;
import org.optaplanner.core.api.function.QuadFunction;
import org.optaplanner.core.api.function.TriFunction;
import org.optaplanner.core.api.score.stream.bi.BiConstraintCollector;
import org.optaplanner.core.api.score.stream.quad.QuadConstraintCollector;
import org.optaplanner.core.api.score.stream.tri.TriConstraintCollector;
import org.optaplanner.core.api.score.stream.uni.UniConstraintCollector;
import org.optaplanner.examples.common.experimental.api.ConsecutiveInfo;
import org.optaplanner.examples.common.experimental.api.ConsecutiveIntervalInfo;
import org.optaplanner.examples.common.experimental.impl.ConsecutiveSetTree;
import org.optaplanner.examples.common.experimental.impl.Interval;
import org.optaplanner.examples.common.experimental.impl.IntervalTree;
/**
* A collection of experimental constraint collectors subject to change in future versions.
*/
public class ExperimentalConstraintCollectors {
/**
* Creates a constraint collector that returns {@link ConsecutiveInfo} about the first fact.
*
* For instance, {@code [Shift slot=1] [Shift slot=2] [Shift slot=4] [Shift slot=6]}
* returns the following information:
*
*
* {@code
* Consecutive Lengths: 2, 1, 1
* Break Lengths: 1, 2
* Consecutive Items: [[Shift slot=1] [Shift slot=2]], [[Shift slot=4]], [[Shift slot=6]]
* }
*
*
* @param indexMap Maps the fact to its position in the sequence
* @param type of the first mapped fact
* @return never null
*/
public static UniConstraintCollector, ConsecutiveInfo>
consecutive(ToIntFunction indexMap) {
return new UniConstraintCollector<>() {
@Override
public Supplier> supplier() {
return () -> new ConsecutiveSetTree<>(
(Integer a, Integer b) -> b - a,
Integer::sum,
1, 0);
}
@Override
public BiFunction, A, Runnable> accumulator() {
return (acc, a) -> {
Integer value = indexMap.applyAsInt(a);
acc.add(a, value);
return () -> acc.remove(a);
};
}
@Override
public Function, ConsecutiveInfo> finisher() {
return tree -> tree;
}
};
}
/**
* As defined by {@link #consecutive(ToIntFunction)}.
*
* @param resultMap Maps both facts to an item in the sequence
* @param indexMap Maps the item to its position in the sequence
* @param type of the first mapped fact
* @param type of the second mapped fact
* @param type of item in the sequence
* @return never null
*/
public static
BiConstraintCollector, ConsecutiveInfo>
consecutive(BiFunction resultMap, ToIntFunction indexMap) {
return new BiConstraintCollector<>() {
@Override
public Supplier> supplier() {
return () -> new ConsecutiveSetTree<>(
(Integer a, Integer b) -> b - a,
Integer::sum, 1, 0);
}
@Override
public TriFunction, A, B, Runnable> accumulator() {
return (acc, a, b) -> {
Result result = resultMap.apply(a, b);
Integer value = indexMap.applyAsInt(result);
acc.add(result, value);
return () -> acc.remove(result);
};
}
@Override
public Function, ConsecutiveInfo> finisher() {
return tree -> tree;
}
};
}
/**
* As defined by {@link #consecutive(ToIntFunction)}.
*
* @param resultMap Maps the three facts to an item in the sequence
* @param indexMap Maps the item to its position in the sequence
* @param type of the first mapped fact
* @param type of the second mapped fact
* @param type of the third mapped fact
* @param type of item in the sequence
* @return never null
*/
public static
TriConstraintCollector, ConsecutiveInfo>
consecutive(TriFunction resultMap, ToIntFunction indexMap) {
return new TriConstraintCollector<>() {
@Override
public Supplier> supplier() {
return () -> new ConsecutiveSetTree<>(
(Integer a, Integer b) -> b - a, Integer::sum, 1, 0);
}
@Override
public QuadFunction, A, B, C, Runnable> accumulator() {
return (acc, a, b, c) -> {
Result result = resultMap.apply(a, b, c);
Integer value = indexMap.applyAsInt(result);
acc.add(result, value);
return () -> acc.remove(result);
};
}
@Override
public Function, ConsecutiveInfo> finisher() {
return tree -> tree;
}
};
}
/**
* As defined by {@link #consecutive(ToIntFunction)}.
*
* @param resultMap Maps the four facts to an item in the sequence
* @param indexMap Maps the item to its position in the sequence
* @param type of the first mapped fact
* @param type of the second mapped fact
* @param type of the third mapped fact
* @param type of the fourth mapped fact
* @param type of item in the sequence
* @return never null
*/
public static
QuadConstraintCollector, ConsecutiveInfo>
consecutive(QuadFunction resultMap, ToIntFunction indexMap) {
return new QuadConstraintCollector<>() {
@Override
public Supplier> supplier() {
return () -> new ConsecutiveSetTree<>(
(Integer a, Integer b) -> b - a, Integer::sum, 1, 0);
}
@Override
public PentaFunction, A, B, C, D, Runnable> accumulator() {
return (acc, a, b, c, d) -> {
Result result = resultMap.apply(a, b, c, d);
Integer value = indexMap.applyAsInt(result);
acc.add(result, value);
return () -> acc.remove(result);
};
}
@Override
public Function, ConsecutiveInfo> finisher() {
return tree -> tree;
}
};
}
/**
* Creates a constraint collector that returns {@link ConsecutiveIntervalInfo} about the first fact.
*
* For instance, {@code [Shift from=2, to=4] [Shift from=3, to=5] [Shift from=6, to=7] [Shift from=7, to=8]}
* returns the following information:
*
*
* {@code
* IntervalClusters: [[Shift from=2, to=4] [Shift from=3, to=5]], [[Shift from=6, to=7] [Shift from=7, to=8]]
* Breaks: [[Break from=5, to=6, length=1]]
* }
*
*
* @param startMap Maps the fact to its start
* @param endMap Maps the fact to its end
* @param differenceFunction Computes the difference between two points. The second argument is always
* larger than the first (ex: {@link Duration#between}
* or (a,b) -> b - a).
* @param type of the first mapped fact
* @param type of the fact endpoints
* @param type of difference between points
* @return never null
*/
public static , DifferenceType_ extends Comparable>
UniConstraintCollector, ConsecutiveIntervalInfo>
consecutiveIntervals(Function startMap, Function endMap,
BiFunction differenceFunction) {
return new UniConstraintCollector<>() {
@Override
public Supplier> supplier() {
return () -> new IntervalTree<>(
startMap,
endMap, differenceFunction);
}
@Override
public BiFunction, A, Runnable> accumulator() {
return (acc, a) -> {
Interval interval = acc.getInterval(a);
acc.add(interval);
return () -> acc.remove(interval);
};
}
@Override
public Function, ConsecutiveIntervalInfo>
finisher() {
return IntervalTree::getConsecutiveIntervalData;
}
};
}
/**
* Specialized version of {@link #consecutiveIntervals(Function,Function,BiFunction)} for
* {@link Temporal} types.
*
* @param type of the first mapped fact
* @param temporal type of the endpoints
* @param startMap Maps the fact to its start
* @param endMap Maps the fact to its end
* @return never null
*/
public static >
UniConstraintCollector, ConsecutiveIntervalInfo>
consecutiveTemporalIntervals(Function startMap, Function endMap) {
return consecutiveIntervals(startMap, endMap, Duration::between);
}
/**
* Specialized version of {@link #consecutiveIntervals(Function,Function,BiFunction)} for Long.
*
* @param startMap Maps the fact to its start
* @param endMap Maps the fact to its end
* @param type of the first mapped fact
* @return never null
*/
public static UniConstraintCollector, ConsecutiveIntervalInfo>
consecutiveIntervals(ToLongFunction startMap, ToLongFunction endMap) {
return consecutiveIntervals(startMap::applyAsLong, endMap::applyAsLong, (a, b) -> b - a);
}
/**
* As defined by {@link #consecutiveIntervals(Function,Function,BiFunction)}.
*
* @param intervalMap Maps both facts to an item in the cluster
* @param startMap Maps the item to its start
* @param endMap Maps the item to its end
* @param differenceFunction Computes the difference between two points. The second argument is always
* larger than the first (ex: {@link Duration#between}
* or (a,b) -> b - a).
* @param type of the first mapped fact
* @param type of the second mapped fact
* @param type of the item in the cluster
* @param type of the item endpoints
* @param type of difference between points
* @return never null
*/
public static , DifferenceType_ extends Comparable>
BiConstraintCollector, ConsecutiveIntervalInfo>
consecutiveIntervals(BiFunction intervalMap, Function startMap,
Function endMap,
BiFunction differenceFunction) {
return new BiConstraintCollector<>() {
@Override
public Supplier> supplier() {
return () -> new IntervalTree<>(
startMap,
endMap, differenceFunction);
}
@Override
public TriFunction, A, B, Runnable> accumulator() {
return (acc, a, b) -> {
IntervalType_ intervalObj = intervalMap.apply(a, b);
Interval interval = acc.getInterval(intervalObj);
acc.add(interval);
return () -> acc.remove(interval);
};
}
@Override
public Function, ConsecutiveIntervalInfo>
finisher() {
return IntervalTree::getConsecutiveIntervalData;
}
};
}
/**
* As defined by {@link #consecutiveTemporalIntervals(Function,Function)}.
*
* @param intervalMap Maps the three facts to an item in the cluster
* @param startMap Maps the fact to its start
* @param endMap Maps the fact to its end
* @param type of the first mapped fact
* @param type of the second mapped fact
* @param type of the item in the cluster
* @param temporal type of the endpoints
* @return never null
*/
public static >
BiConstraintCollector, ConsecutiveIntervalInfo>
consecutiveTemporalIntervals(BiFunction intervalMap,
Function startMap, Function endMap) {
return consecutiveIntervals(intervalMap, startMap, endMap, Duration::between);
}
/**
* As defined by {@link #consecutiveIntervals(ToLongFunction, ToLongFunction)}.
*
* @param startMap Maps the fact to its start
* @param endMap Maps the fact to its end
* @param type of the first mapped fact
* @param type of the second mapped fact
* @param type of the item in the cluster
* @return never null
*/
public static
BiConstraintCollector, ConsecutiveIntervalInfo>
consecutiveIntervals(BiFunction intervalMap, ToLongFunction startMap,
ToLongFunction endMap) {
return consecutiveIntervals(intervalMap, startMap::applyAsLong, endMap::applyAsLong, (a, b) -> b - a);
}
/**
* As defined by {@link #consecutiveIntervals(Function,Function,BiFunction)}.
*
* @param intervalMap Maps the three facts to an item in the cluster
* @param startMap Maps the item to its start
* @param endMap Maps the item to its end
* @param differenceFunction Computes the difference between two points. The second argument is always
* larger than the first (ex: {@link Duration#between}
* or (a,b) -> b - a).
* @param type of the first mapped fact
* @param type of the second mapped fact
* @param type of the third mapped fact
* @param type of the item in the cluster
* @param type of the item endpoints
* @param type of difference between points
* @return never null
*/
public static , DifferenceType_ extends Comparable>
TriConstraintCollector, ConsecutiveIntervalInfo>
consecutiveIntervals(TriFunction intervalMap, Function startMap,
Function endMap,
BiFunction differenceFunction) {
return new TriConstraintCollector<>() {
@Override
public Supplier> supplier() {
return () -> new IntervalTree<>(
startMap,
endMap, differenceFunction);
}
@Override
public QuadFunction, A, B, C, Runnable> accumulator() {
return (acc, a, b, c) -> {
IntervalType_ intervalObj = intervalMap.apply(a, b, c);
Interval interval = acc.getInterval(intervalObj);
acc.add(interval);
return () -> acc.remove(interval);
};
}
@Override
public Function, ConsecutiveIntervalInfo>
finisher() {
return IntervalTree::getConsecutiveIntervalData;
}
};
}
/**
* As defined by {@link #consecutiveTemporalIntervals(Function,Function)}.
*
* @param intervalMap Maps the three facts to an item in the cluster
* @param startMap Maps the fact to its start
* @param endMap Maps the fact to its end
* @param type of the first mapped fact
* @param type of the second mapped fact
* @param type of the third mapped fact
* @param type of the item in the cluster
* @param temporal type of the endpoints
* @return never null
*/
public static >
TriConstraintCollector, ConsecutiveIntervalInfo>
consecutiveTemporalIntervals(TriFunction intervalMap,
Function startMap, Function endMap) {
return consecutiveIntervals(intervalMap, startMap, endMap, Duration::between);
}
/**
* As defined by {@link #consecutiveIntervals(ToLongFunction, ToLongFunction)}.
*
* @param startMap Maps the fact to its start
* @param endMap Maps the fact to its end
* @param type of the first mapped fact
* @param type of the second mapped fact
* @param type of the third mapped fact
* @param type of the item in the cluster
* @return never null
*/
public static
TriConstraintCollector, ConsecutiveIntervalInfo>
consecutiveIntervals(TriFunction intervalMap, ToLongFunction startMap,
ToLongFunction endMap) {
return consecutiveIntervals(intervalMap, startMap::applyAsLong, endMap::applyAsLong, (a, b) -> b - a);
}
/**
* As defined by {@link #consecutiveIntervals(Function,Function,BiFunction)}.
*
* @param intervalMap Maps the four facts to an item in the cluster
* @param startMap Maps the item to its start
* @param endMap Maps the item to its end
* @param differenceFunction Computes the difference between two points. The second argument is always
* larger than the first (ex: {@link Duration#between}
* or (a,b) -> b - a).
* @param type of the first mapped fact
* @param type of the second mapped fact
* @param type of the third mapped fact
* @param type of the fourth mapped fact
* @param type of the item in the cluster
* @param type of the item endpoints
* @param type of difference between points
* @return never null
*/
public static , DifferenceType_ extends Comparable>
QuadConstraintCollector, ConsecutiveIntervalInfo>
consecutiveIntervals(QuadFunction intervalMap,
Function startMap, Function endMap,
BiFunction differenceFunction) {
return new QuadConstraintCollector<>() {
@Override
public Supplier> supplier() {
return () -> new IntervalTree<>(
startMap,
endMap, differenceFunction);
}
@Override
public PentaFunction, A, B, C, D, Runnable> accumulator() {
return (acc, a, b, c, d) -> {
IntervalType_ intervalObj = intervalMap.apply(a, b, c, d);
Interval interval = acc.getInterval(intervalObj);
acc.add(interval);
return () -> acc.remove(interval);
};
}
@Override
public Function, ConsecutiveIntervalInfo>
finisher() {
return IntervalTree::getConsecutiveIntervalData;
}
};
}
/**
* As defined by {@link #consecutiveTemporalIntervals(Function,Function)}.
*
* @param intervalMap Maps the three facts to an item in the cluster
* @param startMap Maps the fact to its start
* @param endMap Maps the fact to its end
* @param type of the first mapped fact
* @param type of the second mapped fact
* @param type of the third mapped fact
* @param type of the fourth mapped fact
* @param type of the item in the cluster
* @param temporal type of the endpoints
* @return never null
*/
public static >
QuadConstraintCollector, ConsecutiveIntervalInfo>
consecutiveTemporalIntervals(QuadFunction intervalMap,
Function startMap, Function endMap) {
return consecutiveIntervals(intervalMap, startMap, endMap, Duration::between);
}
/**
* As defined by {@link #consecutiveIntervals(ToLongFunction, ToLongFunction)}.
*
* @param startMap Maps the fact to its start
* @param endMap Maps the fact to its end
* @param type of the first mapped fact
* @param type of the second mapped fact
* @param type of the third mapped fact
* @param type of the fourth mapped fact
* @param type of the item in the cluster
* @return never null
*/
public static
QuadConstraintCollector, ConsecutiveIntervalInfo>
consecutiveIntervals(QuadFunction intervalMap, ToLongFunction startMap,
ToLongFunction endMap) {
return consecutiveIntervals(intervalMap, startMap::applyAsLong, endMap::applyAsLong, (a, b) -> b - a);
}
// Hide constructor since this is a factory class
private ExperimentalConstraintCollectors() {
}
}