EvolutionInterceptor.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-6.1.0).
003  * Copyright (c) 2007-2020 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@gmail.com)
019  */
020 package io.jenetics.engine;
021 
022 import static java.util.Objects.requireNonNull;
023 
024 import java.util.function.Function;
025 
026 import io.jenetics.Gene;
027 
028 /**
029  * The evolution interceptor allows to update the {@link EvolutionStart} object,
030  <em>before</em> the evolution start, and update the {@link EvolutionResult}
031  * object <em>after</em> the evolution.
032  *
033  @see EvolutionResult#toUniquePopulation()
034  @see Engine.Builder#interceptor(EvolutionInterceptor)
035  *
036  @param <G> the gene type
037  @param <C> the fitness result type
038  *
039  @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
040  @since 6.0
041  @version 6.0
042  */
043 public interface EvolutionInterceptor<
044     extends Gene<?, G>,
045     extends Comparable<? super C>
046 {
047 
048     /**
049      * This method is called right before the evaluation of a generation is
050      * started.
051      *
052      @param start the evolution start object
053      @return the possible <em>update</em> evolution start object
054      @throws NullPointerException if the evolution {@code start} object is
055      *         {@code null}
056      */
057     default EvolutionStart<G, C> before(final EvolutionStart<G, C> start) {
058         return start;
059     }
060 
061     /**
062      * This method is called after the evaluation of a generation. If this
063      * method alters the evolution result object, the population within this
064      * result object is re-evaluated.
065      *
066      @param result the evolution result object to update
067      @return the possible <em>updated</em> evolution result object
068      @throws NullPointerException if the evolution {@code result} object is
069      *         {@code null}
070      */
071     default EvolutionResult<G, C> after(final EvolutionResult<G, C> result) {
072         return result;
073     }
074 
075     /**
076      * Composes {@code this} interceptor with the {@code other} one. The
077      {@link #before(EvolutionStart)} of {@code this} interceptor is called
078      <em>after</em> the {@code before} method of the {@code other} interceptor.
079      * And the {@link #after(EvolutionResult)} of {@code this} interceptor is
080      * called <em>before</em> the {@code after} method of the {@code other}
081      * interceptor.
082      *
083      @param other the other, composing interceptor
084      @return a new, composed interceptor
085      @throws NullPointerException if the {@code other} interceptor is
086      *         {@code null}
087      */
088     default EvolutionInterceptor<G, C>
089     compose(final EvolutionInterceptor<G, C> other) {
090         requireNonNull(other);
091         return EvolutionInterceptor.of(
092             start -> before(other.before(start)),
093             result -> other.after(after(result))
094         );
095     }
096 
097     /**
098      * Create a new interceptor instance with the given {@code before} and
099      * {@code after} functions.
100      *
101      @param before the function executed before each evolution step
102      @param after the function executed after each evolution step
103      @param <G> the gene type
104      @param <C> the fitness result type
105      @return a new interceptor instance with the given interceptor functions
106      @throws NullPointerException if one of the functions is {@code null}
107      */
108     public static <G extends Gene<?, G>, C extends Comparable<? super C>>
109     EvolutionInterceptor<G, C> of(
110         final Function<? super EvolutionStart<G, C>, EvolutionStart<G, C>> before,
111         final Function<? super EvolutionResult<G, C>, EvolutionResult<G, C>> after
112     ) {
113         requireNonNull(before);
114         requireNonNull(after);
115 
116         return new EvolutionInterceptor<>() {
117             @Override
118             public EvolutionStart<G, C> before(final EvolutionStart<G, C> start) {
119                 return before.apply(start);
120             }
121 
122             @Override
123             public EvolutionResult<G, C> after(final EvolutionResult<G, C> result) {
124                 return after.apply(result);
125             }
126         };
127     }
128 
129     /**
130      * Create a new interceptor instance with the given {@code before} function.
131      *
132      @param before the function executed before each evolution step
133      @param <G> the gene type
134      @param <C> the fitness result type
135      @return a new interceptor instance with the given interceptor function
136      @throws NullPointerException if the function is {@code null}
137      */
138     public static <G extends Gene<?, G>, C extends Comparable<? super C>>
139     EvolutionInterceptor<G, C>
140     ofBefore(final Function<? super EvolutionStart<G, C>, EvolutionStart<G, C>> before) {
141         return EvolutionInterceptor.of(before, Function.identity());
142     }
143 
144     /**
145      * Create a new interceptor instance with the given {@code after} function.
146      *
147      @param after the function executed after each evolution step
148      @param <G> the gene type
149      @param <C> the fitness result type
150      @return a new interceptor instance with the given interceptor function
151      @throws NullPointerException if the function is {@code null}
152      */
153     public static <G extends Gene<?, G>, C extends Comparable<? super C>>
154     EvolutionInterceptor<G, C>
155     ofAfter(final Function<? super EvolutionResult<G, C>, EvolutionResult<G, C>> after) {
156         return EvolutionInterceptor.of(Function.identity(), after);
157     }
158 
159     /**
160      * Return an interceptor object which does nothing.
161      *
162      @param <G> the gene type
163      @param <C> the fitness result type
164      @return a new <em>identity</em> interceptor
165      */
166     public static <G extends Gene<?, G>, C extends Comparable<? super C>>
167     EvolutionInterceptor<G, C> identity() {
168         return EvolutionInterceptor.of(Function.identity(), Function.identity());
169     }
170 
171 }