All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.optaplanner.examples.common.experimental.ExperimentalConstraintCollectors Maven / Gradle / Ivy

Go to download

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.

There is a newer version: 9.44.0.Final
Show newest version
/*
 * Copyright 2021 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

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() { } }