001 /*
002 * Java Genetic Algorithm Library (jenetics-3.5.0).
003 * Copyright (c) 2007-2016 Franz Wilhelmstötter
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 *
017 * Author:
018 * Franz Wilhelmstötter (franz.wilhelmstoetter@gmx.at)
019 */
020 package org.jenetics.engine;
021
022 import static java.lang.String.format;
023
024 import java.time.Clock;
025 import java.time.Duration;
026 import java.util.function.Predicate;
027
028 import org.jenetics.internal.util.require;
029
030 import org.jenetics.util.NanoClock;
031
032 /**
033 * This class contains factory methods for creating predicates, which can be
034 * used for limiting the evolution stream.
035 *
036 * @see EvolutionStream#limit(Predicate)
037 *
038 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
039 * @since 3.0
040 * @version 3.1
041 */
042 public final class limit {
043 private limit() {require.noInstance();}
044
045 /**
046 * Return a predicate, which will truncate the evolution stream after the
047 * given number of generations. The returned predicate behaves like a call
048 * of the {@link java.util.stream.Stream#limit(long)} and exists for
049 * <i>completeness</i> reasons.
050 *
051 * @since 3.1
052 *
053 * @param generation the number of generations after the evolution stream is
054 * truncated
055 * @return a predicate which truncates the evolution stream after the given
056 * number of generations
057 * @throws java.lang.IllegalArgumentException if the given {@code generation}
058 * is smaller than zero.
059 */
060 public static Predicate<Object> byFixedGeneration(final long generation) {
061 if (generation < 0) {
062 throw new IllegalArgumentException(format(
063 "The number of generations must greater than one, but was %d",
064 generation
065 ));
066 }
067
068 return new Predicate<Object>() {
069 private long _current;
070 @Override
071 public boolean test(final Object o) {
072 return ++_current < generation;
073 }
074 };
075 }
076
077 /**
078 * Return a predicate, which will truncate the evolution stream if no
079 * better phenotype could be found after the given number of
080 * {@code generations}.
081 *
082 * <pre>{@code
083 * final Phenotype<DoubleGene, Double> result = engine.stream()
084 * // Truncate the evolution stream after 5 "steady" generations.
085 * .limit(bySteadyFitness(5))
086 * // The evolution will stop after maximal 100 generations.
087 * .limit(100)
088 * .collect(toBestPhenotype());
089 * }</pre>
090 *
091 * @param generations the number of <i>steady</i> generations
092 * @param <C> the fitness type
093 * @return a predicate which truncate the evolution stream if no better
094 * phenotype could be found after a give number of
095 * {@code generations}
096 * @throws IllegalArgumentException if the generation is smaller than
097 * one.
098 */
099 public static <C extends Comparable<? super C>>
100 Predicate<EvolutionResult<?, C>> bySteadyFitness(final int generations) {
101 return new SteadyFitnessLimit<>(generations);
102 }
103
104 /**
105 * Return a predicate, which will truncate the evolution stream if the GA
106 * execution exceeds a given time duration. This predicate is (normally)
107 * used as safety net, for guaranteed stream truncation.
108 *
109 * <pre>{@code
110 * final Phenotype<DoubleGene, Double> result = engine.stream()
111 * // Truncate the evolution stream after 5 "steady" generations.
112 * .limit(bySteadyFitness(5))
113 * // The evolution will stop after maximal 500 ms.
114 * .limit(byExecutionTime(Duration.ofMillis(500), Clock.systemUTC())
115 * .collect(toBestPhenotype());
116 * }</pre>
117 *
118 * @since 3.1
119 *
120 * @param duration the duration after the evolution stream will be truncated
121 * @param clock the clock used for measure the execution time
122 * @return a predicate, which will truncate the evolution stream, based on
123 * the exceeded execution time
124 * @throws NullPointerException if one of the arguments is {@code null}
125 */
126 public static Predicate<Object>
127 byExecutionTime(final Duration duration, final Clock clock) {
128 return new ExecutionTimeLimit(duration, clock);
129 }
130
131 /**
132 * Return a predicate, which will truncate the evolution stream if the GA
133 * execution exceeds a given time duration. This predicate is (normally)
134 * used as safety net, for guaranteed stream truncation.
135 *
136 * <pre>{@code
137 * final Phenotype<DoubleGene, Double> result = engine.stream()
138 * // Truncate the evolution stream after 5 "steady" generations.
139 * .limit(bySteadyFitness(5))
140 * // The evolution will stop after maximal 500 ms.
141 * .limit(byExecutionTime(Duration.ofMillis(500))
142 * .collect(toBestPhenotype());
143 * }</pre>
144 *
145 * @since 3.1
146 *
147 * @param duration the duration after the evolution stream will be truncated
148 * @return a predicate, which will truncate the evolution stream, based on
149 * the exceeded execution time
150 * @throws NullPointerException if the evolution {@code duration} is
151 * {@code null}
152 */
153 public static Predicate<Object>
154 byExecutionTime(final Duration duration) {
155 return byExecutionTime(duration, NanoClock.systemUTC());
156 }
157
158 /**
159 * Return a predicate, which will truncated the evolution stream if the
160 * best fitness of the current population becomes less than the specified
161 * threshold and the objective is set to minimize the fitness. This
162 * predicate also stops the evolution if the best fitness in the current
163 * population becomes greater than the user-specified fitness threshold when
164 * the objective is to maximize the fitness.
165 *
166 * <pre>{@code
167 * final Phenotype<DoubleGene, Double> result = engine.stream()
168 * // Truncate the evolution stream if the best fitness is higher than
169 * // the given threshold of '2.3'.
170 * .limit(byFitnessThreshold(2.3))
171 * // The evolution will stop after maximal 250 generations; guarantees
172 * // the termination (truncation) of the evolution stream.
173 * .limit(250)
174 * .collect(toBestPhenotype());
175 * }</pre>
176 *
177 * @since 3.1
178 *
179 * @param threshold the desired threshold
180 * @param <C> the fitness type
181 * @return the predicate which truncates the evolution stream based on the
182 * given {@code threshold}.
183 * @throws NullPointerException if the given {@code threshold} is
184 * {@code null}.
185 */
186 public static <C extends Comparable<? super C>>
187 Predicate<EvolutionResult<?, C>> byFitnessThreshold(final C threshold) {
188 return new FitnessThresholdLimit<>(threshold);
189 }
190
191
192 }
|